Skip to content

Commit c5840cc

Browse files
[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).
1 parent 83433d9 commit c5840cc

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define HWCAP_ASIMDHP (1ULL << 10)
1818
#define HWCAP_DIT (1ULL << 24)
1919
#define HWCAP_SSBS (1ULL << 28)
20+
#define HWCAP_GCS (1UL << 32)
2021

2122
#define HWCAP2_BTI (1ULL << 17)
2223
#define HWCAP2_MTE (1ULL << 18)
@@ -50,6 +51,21 @@ Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) {
5051
};
5152
}
5253

54+
Arm64RegisterFlagsDetector::Fields
55+
Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap,
56+
uint64_t hwcap2) {
57+
(void)hwcap2;
58+
59+
if (!(hwcap & HWCAP_GCS))
60+
return {};
61+
62+
return {
63+
{"PUSH", 2},
64+
{"WRITE", 1},
65+
{"ENABLE", 0},
66+
};
67+
}
68+
5369
Arm64RegisterFlagsDetector::Fields
5470
Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
5571
(void)hwcap;

lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class Arm64RegisterFlagsDetector {
6161
static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
6262
static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
6363
static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2);
64+
static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2);
6465

6566
struct RegisterEntry {
6667
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -70,13 +71,15 @@ class Arm64RegisterFlagsDetector {
7071
llvm::StringRef m_name;
7172
RegisterFlags m_flags;
7273
DetectorFn m_detector;
73-
} m_registers[6] = {
74+
} m_registers[8] = {
7475
RegisterEntry("cpsr", 4, DetectCPSRFields),
7576
RegisterEntry("fpsr", 4, DetectFPSRFields),
7677
RegisterEntry("fpcr", 4, DetectFPCRFields),
7778
RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields),
7879
RegisterEntry("svcr", 8, DetectSVCRFields),
7980
RegisterEntry("fpmr", 8, DetectFPMRFields),
81+
RegisterEntry("gcs_features_enabled", 8, DetectGCSFeatureFields),
82+
RegisterEntry("gcs_features_locked", 8, DetectGCSFeatureFields),
8083
};
8184

8285
// Becomes true once field detection has been run for all registers.

lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ def test_gcs_registers(self):
223223
self.runCmd(f"register write gcs_features_enabled {enabled}")
224224
self.expect(
225225
"register read gcs_features_enabled",
226-
substrs=[f"gcs_features_enabled = 0x{enabled:016x}"],
226+
substrs=[
227+
f"gcs_features_enabled = 0x{enabled:016x}",
228+
f"= (PUSH = {(enabled >> 2) & 1}, WRITE = {(enabled >> 1) & 1}, ENABLE = {enabled & 1})",
229+
],
227230
)
228231

229232
# With GCS disabled, the invalid guarded control stack pointer is not
@@ -399,6 +402,16 @@ def test_gcs_core_file(self):
399402
],
400403
)
401404

405+
# Should get register fields for both. They have the same fields.
406+
self.expect(
407+
"register read gcs_features_enabled",
408+
substrs=["= (PUSH = 0, WRITE = 0, ENABLE = 1)"],
409+
)
410+
self.expect(
411+
"register read gcs_features_locked",
412+
substrs=["= (PUSH = 0, WRITE = 0, ENABLE = 0)"],
413+
)
414+
402415
# Core files do not include /proc/pid/smaps, so we cannot see the
403416
# shadow stack "ss" flag. gcspr_el0 should at least point to some mapped
404417
# region.

0 commit comments

Comments
 (0)