Author: David Spickett Date: 2025-01-28T12:05:24Z New Revision: c5840cc609a3674cf7453a45946f7e4a2a73590b
URL: https://github.com/llvm/llvm-project/commit/c5840cc609a3674cf7453a45946f7e4a2a73590b DIFF: https://github.com/llvm/llvm-project/commit/c5840cc609a3674cf7453a45946f7e4a2a73590b.diff LOG: [lldb][AArch64] Add register fields for Guarded Control Stack registers (#124295) The features and locked registers hold the same bits, the latter is a lock for the former. Tested with core files and live processes. I thought about setting a non-zero lock register in the core file, however: * We can be pretty sure it's reading correctly because its between the 2 other GCS registers in the same core file note. * I can't make the test case modify lock bits because userspace can't clear them (without using ptrace) and we don't know what the libc has locked (probably all feature bits). Added: Modified: lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py Removed: ################################################################################ diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp index 9f82c935c0e7ed..1438a45f37d724 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp @@ -17,6 +17,7 @@ #define HWCAP_ASIMDHP (1ULL << 10) #define HWCAP_DIT (1ULL << 24) #define HWCAP_SSBS (1ULL << 28) +#define HWCAP_GCS (1UL << 32) #define HWCAP2_BTI (1ULL << 17) #define HWCAP2_MTE (1ULL << 18) @@ -50,6 +51,21 @@ Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) { }; } +Arm64RegisterFlagsDetector::Fields +Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap, + uint64_t hwcap2) { + (void)hwcap2; + + if (!(hwcap & HWCAP_GCS)) + return {}; + + return { + {"PUSH", 2}, + {"WRITE", 1}, + {"ENABLE", 0}, + }; +} + Arm64RegisterFlagsDetector::Fields Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) { (void)hwcap; diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h index 0f3d53d93892bd..7daebcc71db044 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h @@ -61,6 +61,7 @@ class Arm64RegisterFlagsDetector { static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2); static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2); static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2); + static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2); struct RegisterEntry { RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector) @@ -70,13 +71,15 @@ class Arm64RegisterFlagsDetector { llvm::StringRef m_name; RegisterFlags m_flags; DetectorFn m_detector; - } m_registers[6] = { + } m_registers[8] = { RegisterEntry("cpsr", 4, DetectCPSRFields), RegisterEntry("fpsr", 4, DetectFPSRFields), RegisterEntry("fpcr", 4, DetectFPCRFields), RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields), RegisterEntry("svcr", 8, DetectSVCRFields), RegisterEntry("fpmr", 8, DetectFPMRFields), + RegisterEntry("gcs_features_enabled", 8, DetectGCSFeatureFields), + RegisterEntry("gcs_features_locked", 8, DetectGCSFeatureFields), }; // Becomes true once field detection has been run for all registers. diff --git a/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py b/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py index adbef69c5c38b0..f5a2ca356bbe81 100644 --- a/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py +++ b/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py @@ -223,7 +223,10 @@ def test_gcs_registers(self): self.runCmd(f"register write gcs_features_enabled {enabled}") self.expect( "register read gcs_features_enabled", - substrs=[f"gcs_features_enabled = 0x{enabled:016x}"], + substrs=[ + f"gcs_features_enabled = 0x{enabled:016x}", + f"= (PUSH = {(enabled >> 2) & 1}, WRITE = {(enabled >> 1) & 1}, ENABLE = {enabled & 1})", + ], ) # With GCS disabled, the invalid guarded control stack pointer is not @@ -399,6 +402,16 @@ def test_gcs_core_file(self): ], ) + # Should get register fields for both. They have the same fields. + self.expect( + "register read gcs_features_enabled", + substrs=["= (PUSH = 0, WRITE = 0, ENABLE = 1)"], + ) + self.expect( + "register read gcs_features_locked", + substrs=["= (PUSH = 0, WRITE = 0, ENABLE = 0)"], + ) + # 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. _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits