[Lldb-commits] [lldb] [lldb][AArch64] Add register fields for Guarded Control Stack registers (PR #124295)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Tue Jan 28 03:51:13 PST 2025
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/124295
>From de84dc94ee6e5f15450f9e2729bfdbafd212b7f0 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Tue, 27 Aug 2024 14:35:28 +0100
Subject: [PATCH] [lldb][AArch64] Add register fields for Guarded Control Stack
registers
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 and we don't know what the libc has locked
(probably all feature bits).
---
.../Utility/RegisterFlagsDetector_arm64.cpp | 16 ++++++++++++++++
.../Utility/RegisterFlagsDetector_arm64.h | 5 ++++-
.../API/linux/aarch64/gcs/TestAArch64LinuxGCS.py | 15 ++++++++++++++-
3 files changed, 34 insertions(+), 2 deletions(-)
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.
More information about the lldb-commits
mailing list