Skip to content

Commit f52b895

Browse files
[lldb][AArch64] Read fpmr register from core files (llvm#110104)
https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers/FPMR--Floating-point-Mode-Register for details of the register.
1 parent 4dd55c5 commit f52b895

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
6464
if (zt_data.GetByteSize() >= 64)
6565
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZT);
6666

67+
DataExtractor fpmr_data =
68+
getRegset(notes, arch.GetTriple(), AARCH64_FPMR_Desc);
69+
if (fpmr_data.GetByteSize() >= sizeof(uint64_t))
70+
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskFPMR);
71+
6772
auto register_info_up =
6873
std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
6974
return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
@@ -128,6 +133,9 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
128133
if (m_register_info_up->IsZTPresent())
129134
m_zt_data = getRegset(notes, target_triple, AARCH64_ZT_Desc);
130135

136+
if (m_register_info_up->IsFPMRPresent())
137+
m_fpmr_data = getRegset(notes, target_triple, AARCH64_FPMR_Desc);
138+
131139
ConfigureRegisterContext();
132140
}
133141

@@ -370,6 +378,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
370378
*reg_info, reinterpret_cast<uint8_t *>(&m_sme_pseudo_regs) + offset,
371379
reg_info->byte_size, lldb_private::endian::InlHostByteOrder(), error);
372380
}
381+
} else if (IsFPMR(reg)) {
382+
offset = reg_info->byte_offset - m_register_info_up->GetFPMROffset();
383+
assert(offset < m_fpmr_data.GetByteSize());
384+
value.SetFromMemoryData(*reg_info, m_fpmr_data.GetDataStart() + offset,
385+
reg_info->byte_size, lldb::eByteOrderLittle, error);
373386
} else
374387
return false;
375388

lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
6262
lldb_private::DataExtractor m_za_data;
6363
lldb_private::DataExtractor m_mte_data;
6464
lldb_private::DataExtractor m_zt_data;
65+
lldb_private::DataExtractor m_fpmr_data;
6566

6667
SVEState m_sve_state = SVEState::Unknown;
6768
uint16_t m_sve_vector_length = 0;

lldb/source/Plugins/Process/elf-core/RegisterUtilities.h

+4
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ constexpr RegsetDesc AARCH64_MTE_Desc[] = {
144144
llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL},
145145
};
146146

147+
constexpr RegsetDesc AARCH64_FPMR_Desc[] = {
148+
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_FPMR},
149+
};
150+
147151
constexpr RegsetDesc PPC_VMX_Desc[] = {
148152
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
149153
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},

lldb/test/API/linux/aarch64/fpmr/TestAArch64LinuxFPMR.py

+26-6
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
class AArch64LinuxFPMR(TestBase):
1212
NO_DEBUG_INFO_TESTCASE = True
1313

14+
# The value set by the inferior.
15+
EXPECTED_FPMR = (0b101010 << 32) | 0b101
16+
EXPECTED_FPMR_FIELDS = ["LSCALE2 = 42", "F8S1 = FP8_E4M3 | 0x4"]
17+
1418
@skipUnlessArch("aarch64")
1519
@skipUnlessPlatform(["linux"])
16-
def test_fpmr_register(self):
20+
def test_fpmr_register_live(self):
1721
if not self.isAArch64FPMR():
1822
self.skipTest("FPMR must be present.")
1923

@@ -39,16 +43,16 @@ def test_fpmr_register(self):
3943
)
4044

4145
# This has been set by the program.
42-
expected_fpmr = (0b101010 << 32) | 0b101
4346
self.expect(
4447
"register read --all",
45-
substrs=["Floating Point Mode Register", f"fpmr = {expected_fpmr:#018x}"],
48+
substrs=[
49+
"Floating Point Mode Register",
50+
f"fpmr = {self.EXPECTED_FPMR:#018x}",
51+
],
4652
)
4753

4854
if self.hasXMLSupport():
49-
self.expect(
50-
"register read fpmr", substrs=["LSCALE2 = 42", "F8S1 = FP8_E4M3 | 0x4"]
51-
)
55+
self.expect("register read fpmr", substrs=self.EXPECTED_FPMR_FIELDS)
5256

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

6266
# 0 means the program found the new value in the sysreg as expected.
6367
self.expect("continue", substrs=["exited with status = 0"])
68+
69+
@skipIfLLVMTargetMissing("AArch64")
70+
def test_fpmr_register_core(self):
71+
if not self.isAArch64FPMR():
72+
self.skipTest("FPMR must be present.")
73+
74+
self.runCmd("target create --core corefile")
75+
76+
self.expect(
77+
"register read --all",
78+
substrs=[
79+
"Floating Point Mode Register",
80+
f"fpmr = {self.EXPECTED_FPMR:#018x}",
81+
],
82+
)
83+
self.expect("register read fpmr", substrs=self.EXPECTED_FPMR_FIELDS)
20 KB
Binary file not shown.

lldb/test/API/linux/aarch64/fpmr/main.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,10 @@ int main(int argc, char *argv[]) {
3737
uint64_t new_fpmr = get_fpmr(); // Set break point at this line.
3838
uint64_t expected_fpmr = ((uint64_t)0b010101 << 32) | (uint64_t)0b010;
3939

40-
return new_fpmr == expected_fpmr ? 0 : 1;
40+
// If the debugger failed to update the value, exit uncleanly.
41+
// This also allows you to run this program standalone to create a core file.
42+
if (new_fpmr != expected_fpmr)
43+
__builtin_trap();
44+
45+
return 0;
4146
}

0 commit comments

Comments
 (0)