mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 21:55:39 +08:00
[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).
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
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 @@ private:
|
||||
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.
|
||||
|
||||
@@ -223,7 +223,10 @@ class AArch64LinuxGCSTestCase(TestBase):
|
||||
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 @@ class AArch64LinuxGCSTestCase(TestBase):
|
||||
],
|
||||
)
|
||||
|
||||
# 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.
|
||||
|
||||
Reference in New Issue
Block a user