diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 413bf1bbdb2a5..2ddf8440aeb03 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -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(arch, opt_regsets); return std::unique_ptr( @@ -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(); } @@ -370,6 +378,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, *reg_info, reinterpret_cast(&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; diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index ff94845e58d60..35588c40c2eb1 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -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; diff --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h index 12aa5f72371c5..b97279b0d735b 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -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}, diff --git a/lldb/test/API/linux/aarch64/fpmr/TestAArch64LinuxFPMR.py b/lldb/test/API/linux/aarch64/fpmr/TestAArch64LinuxFPMR.py index d022c8eb3d6cc..7f8dc811c5df3 100644 --- a/lldb/test/API/linux/aarch64/fpmr/TestAArch64LinuxFPMR.py +++ b/lldb/test/API/linux/aarch64/fpmr/TestAArch64LinuxFPMR.py @@ -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.") @@ -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. @@ -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) diff --git a/lldb/test/API/linux/aarch64/fpmr/corefile b/lldb/test/API/linux/aarch64/fpmr/corefile new file mode 100644 index 0000000000000..8496b6a774df9 Binary files /dev/null and b/lldb/test/API/linux/aarch64/fpmr/corefile differ diff --git a/lldb/test/API/linux/aarch64/fpmr/main.c b/lldb/test/API/linux/aarch64/fpmr/main.c index bdb7d8f40b64d..0a9a9c53eb788 100644 --- a/lldb/test/API/linux/aarch64/fpmr/main.c +++ b/lldb/test/API/linux/aarch64/fpmr/main.c @@ -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; }