Skip to content

[lldb][AArch64] Read fpmr register from core files #110104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
if (zt_data.GetByteSize() >= 64)
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZT);

DataExtractor fpmr_data =
getRegset(notes, arch.GetTriple(), AARCH64_FPMR_Desc);
if (fpmr_data.GetByteSize() >= sizeof(uint64_t))
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskFPMR);

auto register_info_up =
std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
Expand Down Expand Up @@ -128,6 +133,9 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
if (m_register_info_up->IsZTPresent())
m_zt_data = getRegset(notes, target_triple, AARCH64_ZT_Desc);

if (m_register_info_up->IsFPMRPresent())
m_fpmr_data = getRegset(notes, target_triple, AARCH64_FPMR_Desc);

ConfigureRegisterContext();
}

Expand Down Expand Up @@ -370,6 +378,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
*reg_info, reinterpret_cast<uint8_t *>(&m_sme_pseudo_regs) + offset,
reg_info->byte_size, lldb_private::endian::InlHostByteOrder(), error);
}
} else if (IsFPMR(reg)) {
offset = reg_info->byte_offset - m_register_info_up->GetFPMROffset();
assert(offset < m_fpmr_data.GetByteSize());
value.SetFromMemoryData(*reg_info, m_fpmr_data.GetDataStart() + offset,
reg_info->byte_size, lldb::eByteOrderLittle, error);
} else
return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
lldb_private::DataExtractor m_za_data;
lldb_private::DataExtractor m_mte_data;
lldb_private::DataExtractor m_zt_data;
lldb_private::DataExtractor m_fpmr_data;

SVEState m_sve_state = SVEState::Unknown;
uint16_t m_sve_vector_length = 0;
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ constexpr RegsetDesc AARCH64_MTE_Desc[] = {
llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL},
};

constexpr RegsetDesc AARCH64_FPMR_Desc[] = {
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_FPMR},
};

constexpr RegsetDesc PPC_VMX_Desc[] = {
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
Expand Down
32 changes: 26 additions & 6 deletions lldb/test/API/linux/aarch64/fpmr/TestAArch64LinuxFPMR.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
class AArch64LinuxFPMR(TestBase):
NO_DEBUG_INFO_TESTCASE = True

# The value set by the inferior.
EXPECTED_FPMR = (0b101010 << 32) | 0b101
EXPECTED_FPMR_FIELDS = ["LSCALE2 = 42", "F8S1 = FP8_E4M3 | 0x4"]

@skipUnlessArch("aarch64")
@skipUnlessPlatform(["linux"])
def test_fpmr_register(self):
def test_fpmr_register_live(self):
if not self.isAArch64FPMR():
self.skipTest("FPMR must be present.")

Expand All @@ -39,16 +43,16 @@ def test_fpmr_register(self):
)

# This has been set by the program.
expected_fpmr = (0b101010 << 32) | 0b101
self.expect(
"register read --all",
substrs=["Floating Point Mode Register", f"fpmr = {expected_fpmr:#018x}"],
substrs=[
"Floating Point Mode Register",
f"fpmr = {self.EXPECTED_FPMR:#018x}",
],
)

if self.hasXMLSupport():
self.expect(
"register read fpmr", substrs=["LSCALE2 = 42", "F8S1 = FP8_E4M3 | 0x4"]
)
self.expect("register read fpmr", substrs=self.EXPECTED_FPMR_FIELDS)

# Write a value for the program to find. Same fields but with bit values
# inverted.
Expand All @@ -61,3 +65,19 @@ def test_fpmr_register(self):

# 0 means the program found the new value in the sysreg as expected.
self.expect("continue", substrs=["exited with status = 0"])

@skipIfLLVMTargetMissing("AArch64")
def test_fpmr_register_core(self):
if not self.isAArch64FPMR():
self.skipTest("FPMR must be present.")

self.runCmd("target create --core corefile")

self.expect(
"register read --all",
substrs=[
"Floating Point Mode Register",
f"fpmr = {self.EXPECTED_FPMR:#018x}",
],
)
self.expect("register read fpmr", substrs=self.EXPECTED_FPMR_FIELDS)
Binary file added lldb/test/API/linux/aarch64/fpmr/corefile
Binary file not shown.
7 changes: 6 additions & 1 deletion lldb/test/API/linux/aarch64/fpmr/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,10 @@ int main(int argc, char *argv[]) {
uint64_t new_fpmr = get_fpmr(); // Set break point at this line.
uint64_t expected_fpmr = ((uint64_t)0b010101 << 32) | (uint64_t)0b010;

return new_fpmr == expected_fpmr ? 0 : 1;
// If the debugger failed to update the value, exit uncleanly.
// This also allows you to run this program standalone to create a core file.
if (new_fpmr != expected_fpmr)
__builtin_trap();

return 0;
}
Loading