From d2c221b9b8cfeb8d9d902947db38c716e7a09804 Mon Sep 17 00:00:00 2001 From: David Spickett Date: Tue, 27 Aug 2024 11:45:52 +0100 Subject: [PATCH] [lldb][AArch64] Add Guarded Control Stack support for Linux core files This allows you to read the same registers as you would for a live process. As the content of proc/pid/smaps is not included in the core file, we don't get the "ss" marker. The GCS region is stil in the list though. --- .../RegisterContextPOSIXCore_arm64.cpp | 17 ++++++++++ .../elf-core/RegisterContextPOSIXCore_arm64.h | 1 + .../Process/elf-core/RegisterUtilities.h | 4 +++ .../linux/aarch64/gcs/TestAArch64LinuxGCS.py | 32 ++++++++++++++++++ lldb/test/API/linux/aarch64/gcs/corefile | Bin 0 -> 24576 bytes 5 files changed, 54 insertions(+) create mode 100644 lldb/test/API/linux/aarch64/gcs/corefile diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 2ddf8440aeb03..bd02bb0e69a4d 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -69,6 +69,15 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch, if (fpmr_data.GetByteSize() >= sizeof(uint64_t)) opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskFPMR); + DataExtractor gcs_data = getRegset(notes, arch.GetTriple(), AARCH64_GCS_Desc); + struct __attribute__((packed)) gcs_regs { + uint64_t features_enabled; + uint64_t features_locked; + uint64_t gcspr_e0; + }; + if (gcs_data.GetByteSize() >= sizeof(gcs_regs)) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskGCS); + auto register_info_up = std::make_unique(arch, opt_regsets); return std::unique_ptr( @@ -136,6 +145,9 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( if (m_register_info_up->IsFPMRPresent()) m_fpmr_data = getRegset(notes, target_triple, AARCH64_FPMR_Desc); + if (m_register_info_up->IsGCSPresent()) + m_gcs_data = getRegset(notes, target_triple, AARCH64_GCS_Desc); + ConfigureRegisterContext(); } @@ -330,6 +342,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, assert(offset < m_mte_data.GetByteSize()); value.SetFromMemoryData(*reg_info, m_mte_data.GetDataStart() + offset, reg_info->byte_size, lldb::eByteOrderLittle, error); + } else if (IsGCS(reg)) { + offset = reg_info->byte_offset - m_register_info_up->GetGCSOffset(); + assert(offset < m_gcs_data.GetByteSize()); + value.SetFromMemoryData(*reg_info, m_gcs_data.GetDataStart() + offset, + reg_info->byte_size, lldb::eByteOrderLittle, error); } else if (IsSME(reg)) { // If you had SME in the process, active or otherwise, there will at least // be a ZA header. No header, no SME at all. diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index 35588c40c2eb1..6140f805ffc78 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -63,6 +63,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 { lldb_private::DataExtractor m_mte_data; lldb_private::DataExtractor m_zt_data; lldb_private::DataExtractor m_fpmr_data; + lldb_private::DataExtractor m_gcs_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 b97279b0d735b..59382a12cde0a 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -148,6 +148,10 @@ constexpr RegsetDesc AARCH64_FPMR_Desc[] = { {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_FPMR}, }; +constexpr RegsetDesc AARCH64_GCS_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_GCS}, +}; + 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/gcs/TestAArch64LinuxGCS.py b/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py index 797551b061a23..adbef69c5c38b 100644 --- a/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py +++ b/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py @@ -374,3 +374,35 @@ def test_gcs_expression_enable_gcs(self): # consistent with the disabled -> enabled behaviour. enabled |= 1 self.check_gcs_registers(enabled, locked, spr_el0) + + @skipIfLLVMTargetMissing("AArch64") + def test_gcs_core_file(self): + # To re-generate the core file, build the test file and run it on a + # machine with GCS enabled. Note that because the kernel decides where + # the GCS is stored, the value of gcspr_el0 and which memory region it + # points to may change between runs. + + self.runCmd("target create --core corefile") + + self.expect( + "bt", + substrs=["stop reason = SIGSEGV: control protection fault"], + ) + + self.expect( + "register read --all", + substrs=[ + "Guarded Control Stack Registers:", + "gcs_features_enabled = 0x0000000000000001", + "gcs_features_locked = 0x0000000000000000", + "gcspr_el0 = 0x0000ffffa83ffff0", + ], + ) + + # Core files do not include /proc/pid/smaps, so we cannot see the + # shadow stack "ss" flag. gcspr_el0 should at least point to some mapped + # region. + self.expect( + "memory region $gcspr_el0", + substrs=["[0x0000ffffa8000000-0x0000ffffa8400000) rw-"], + ) diff --git a/lldb/test/API/linux/aarch64/gcs/corefile b/lldb/test/API/linux/aarch64/gcs/corefile new file mode 100644 index 0000000000000000000000000000000000000000..34faa98c4d783d8d6905c9620976039e35025e00 GIT binary patch literal 24576 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 literal 0 HcmV?d00001