llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: David Spickett (DavidSpickett)

<details>
<summary>Changes</summary>

This change adds initial support for managing the Permission Overlay Extension 
(POE). This extension allows userspace programs to change memory permissions 
without making a sycall.

This is used to implement Linux's memory protection keys 
(https://docs.kernel.org/core-api/protection-keys.html) on AArch64.

Overview of POE:
* Page table entries have a set of permissions. To change these, a program 
would have to use a syscall which adds overhead.
* 3 bits of the page table entry are used for a protection key 0-7.
* POE adds a new register "por" which stores 4-bit sets of permissions.
* The protection key is an index into this por register.
* Permissions in POR are applied on top of the page table permissions, but may 
only remove permissions. For example, if you overlay read/execute over 
read/write, the result is read. Since execute was not in the page table 
permissions.
* This register can be modified without leaving userspace, making permission 
changes faster.

To help debug this, I have made the following changes to LLDB:
* Ability to read and write the por register.
* Save and restore of por when running expressions.
* Register field definitions to print the por permissions in a human readable 
form.
* Recognition of memory protection key faults as a distinct type of SIGSEGV 
(this will apply to Linux on any architecture).

There are a few more features to add around memory region information, that 
will be in follow up changes.

---

Patch is 34.66 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/177145.diff


18 Files Affected:

- (modified) lldb/packages/Python/lldbsuite/test/cpu_feature.py (+1) 
- (modified) lldb/packages/Python/lldbsuite/test/lldbtest.py (+3) 
- (modified) 
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (+88-1) 
- (modified) 
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h (+16) 
- (modified) lldb/source/Plugins/Process/Utility/LinuxSignals.cpp (+1) 
- (modified) lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp 
(+4) 
- (modified) lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h 
(+1) 
- (modified) 
lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp (+34) 
- (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h 
(+4-1) 
- (modified) lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp 
(+33) 
- (modified) lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h (+7) 
- (modified) 
lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp (+15) 
- (modified) 
lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h (+1) 
- (modified) lldb/source/Plugins/Process/elf-core/RegisterUtilities.h (+4) 
- (added) lldb/test/API/linux/aarch64/permission_overlay/Makefile (+3) 
- (added) lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py 
(+129) 
- (added) lldb/test/API/linux/aarch64/permission_overlay/corefile () 
- (added) lldb/test/API/linux/aarch64/permission_overlay/main.c (+128) 


``````````diff
diff --git a/lldb/packages/Python/lldbsuite/test/cpu_feature.py 
b/lldb/packages/Python/lldbsuite/test/cpu_feature.py
index d7668c1884e40..736d5e86399ae 100644
--- a/lldb/packages/Python/lldbsuite/test/cpu_feature.py
+++ b/lldb/packages/Python/lldbsuite/test/cpu_feature.py
@@ -61,6 +61,7 @@ def _is_supported_darwin(self, cmd_runner):
 
 class AArch64:
     FPMR = CPUFeature("fpmr")
+    POE = CPUFeature("poe")
     GCS = CPUFeature("gcs")
     MTE = CPUFeature("mte", "hw.optional.arm.FEAT_MTE4")
     MTE_STORE_ONLY = CPUFeature("mtestoreonly")
diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py 
b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index 55b527e3a9ce6..616d7cea6b4e3 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1405,6 +1405,9 @@ def isAArch64PAuth(self):
     def isAArch64FPMR(self):
         return self.isAArch64() and self.isSupported(cpu_feature.AArch64.FPMR)
 
+    def isAArch64POE(self):
+        return self.isAArch64() and self.isSupported(cpu_feature.AArch64.POE)
+
     def isAArch64Windows(self):
         """Returns true if the architecture is AArch64 and platform windows."""
         if self.getPlatform() == "windows":
diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 294a446686f22..41b094f1a383a 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -65,6 +65,10 @@
 #define NT_ARM_FPMR 0x40e /* Floating point mode register */
 #endif
 
+#ifndef NT_ARM_POE
+#define NT_ARM_POE 0x40f /* Permission Overlay registers */
+#endif
+
 #ifndef NT_ARM_GCS
 #define NT_ARM_GCS 0x410 /* Guarded Control Stack control registers */
 #endif
@@ -77,6 +81,8 @@
 
 #define HWCAP2_FPMR (1UL << 48)
 
+#define HWCAP2_POE (1ULL << 63)
+
 using namespace lldb;
 using namespace lldb_private;
 using namespace lldb_private::process_linux;
@@ -159,6 +165,8 @@ 
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
         opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskFPMR);
       if (*auxv_at_hwcap & HWCAP_GCS)
         opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskGCS);
+      if (*auxv_at_hwcap2 & HWCAP2_POE)
+        opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPOE);
     }
 
     opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS);
@@ -206,6 +214,7 @@ 
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
   ::memset(&m_tls_regs, 0, sizeof(m_tls_regs));
   ::memset(&m_sme_pseudo_regs, 0, sizeof(m_sme_pseudo_regs));
   ::memset(&m_gcs_regs, 0, sizeof(m_gcs_regs));
+  ::memset(&m_poe_regs, 0, sizeof(m_poe_regs));
   std::fill(m_zt_reg.begin(), m_zt_reg.end(), 0);
 
   m_mte_ctrl_reg = 0;
@@ -227,6 +236,7 @@ 
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
   m_zt_buffer_is_valid = false;
   m_fpmr_is_valid = false;
   m_gcs_is_valid = false;
+  m_poe_is_valid = false;
 
   // SME adds the tpidr2 register
   m_tls_size = GetRegisterInfo().IsSSVEPresent() ? sizeof(m_tls_regs)
@@ -455,6 +465,14 @@ NativeRegisterContextLinux_arm64::ReadRegister(const 
RegisterInfo *reg_info,
     offset = reg_info->byte_offset - GetRegisterInfo().GetGCSOffset();
     assert(offset < GetGCSBufferSize());
     src = (uint8_t *)GetGCSBuffer() + offset;
+  } else if (IsPOE(reg)) {
+    error = ReadPOE();
+    if (error.Fail())
+      return error;
+
+    offset = reg_info->byte_offset - GetRegisterInfo().GetPOEOffset();
+    assert(offset < GetPOEBufferSize());
+    src = (uint8_t *)GetPOEBuffer() + offset;
   } else
     return Status::FromErrorString(
         "failed - register wasn't recognized to be a GPR or an FPR, "
@@ -690,6 +708,17 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
 
     return WriteGCS();
+  } else if (IsPOE(reg)) {
+    error = ReadPOE();
+    if (error.Fail())
+      return error;
+
+    offset = reg_info->byte_offset - GetRegisterInfo().GetPOEOffset();
+    assert(offset < GetPOEBufferSize());
+    dst = (uint8_t *)GetPOEBuffer() + offset;
+    ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
+
+    return WritePOE();
   }
 
   return Status::FromErrorString("Failed to write register value");
@@ -706,6 +735,7 @@ enum RegisterSetType : uint32_t {
   SME2, // ZT only.
   FPMR,
   GCS, // Guarded Control Stack registers.
+  POE, // Permission Overlay registers.
 };
 
 static uint8_t *AddRegisterSetType(uint8_t *dst,
@@ -800,6 +830,13 @@ 
NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
       return error;
   }
 
+  if (GetRegisterInfo().IsPOEPresent()) {
+    cached_size += sizeof(RegisterSetType) + GetPOEBufferSize();
+    error = ReadPOE();
+    if (error.Fail())
+      return error;
+  }
+
   // tpidr is always present but tpidr2 depends on SME.
   cached_size += sizeof(RegisterSetType) + GetTLSBufferSize();
   error = ReadTLS();
@@ -913,6 +950,11 @@ Status 
NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
                             GetGCSBufferSize());
   }
 
+  if (GetRegisterInfo().IsPOEPresent()) {
+    dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(),
+                            GetPOEBufferSize());
+  }
+
   dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
                           GetTLSBufferSize());
 
@@ -1066,7 +1108,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
           GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid,
           std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR, this));
       break;
-    case RegisterSetType::GCS:
+    case RegisterSetType::GCS: {
       // It is not permitted to enable GCS via ptrace. We can disable it, but
       // to keep things simple we will not revert any change to the
       // PR_SHADOW_STACK_ENABLE bit. Instead patch in the current enable bit
@@ -1090,6 +1132,12 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
 
       break;
     }
+    case RegisterSetType::POE:
+      error = RestoreRegisters(
+          GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid,
+          std::bind(&NativeRegisterContextLinux_arm64::WritePOE, this));
+      break;
+    }
 
     if (error.Fail())
       return error;
@@ -1140,6 +1188,10 @@ bool NativeRegisterContextLinux_arm64::IsGCS(unsigned 
reg) const {
   return GetRegisterInfo().IsGCSReg(reg);
 }
 
+bool NativeRegisterContextLinux_arm64::IsPOE(unsigned reg) const {
+  return GetRegisterInfo().IsPOEReg(reg);
+}
+
 llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
   if (!m_refresh_hwdebug_info) {
     return llvm::Error::success();
@@ -1244,6 +1296,7 @@ void 
NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
   m_zt_buffer_is_valid = false;
   m_fpmr_is_valid = false;
   m_gcs_is_valid = false;
+  m_poe_is_valid = false;
 
   // Update SVE and ZA registers in case there is change in configuration.
   ConfigureRegisterContext();
@@ -1591,6 +1644,40 @@ Status NativeRegisterContextLinux_arm64::WriteFPMR() {
   return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
 }
 
+Status NativeRegisterContextLinux_arm64::ReadPOE() {
+  Status error;
+
+  if (m_poe_is_valid)
+    return error;
+
+  struct iovec ioVec;
+  ioVec.iov_base = GetPOEBuffer();
+  ioVec.iov_len = GetPOEBufferSize();
+
+  error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
+
+  if (error.Success())
+    m_poe_is_valid = true;
+
+  return error;
+}
+
+Status NativeRegisterContextLinux_arm64::WritePOE() {
+  Status error;
+
+  error = ReadPOE();
+  if (error.Fail())
+    return error;
+
+  struct iovec ioVec;
+  ioVec.iov_base = GetPOEBuffer();
+  ioVec.iov_len = GetPOEBufferSize();
+
+  m_poe_is_valid = false;
+
+  return WriteRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
+}
+
 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
   // ConfigureRegisterContext gets called from InvalidateAllRegisters
   // on every stop and configures SVE vector length and whether we are in
diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 7ed0da8503496..cc34ef4c8f246 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -93,6 +93,7 @@ class NativeRegisterContextLinux_arm64
   bool m_tls_is_valid;
   size_t m_tls_size;
   bool m_gcs_is_valid;
+  bool m_poe_is_valid;
 
   struct user_pt_regs m_gpr_arm64; // 64-bit general purpose registers.
 
@@ -137,6 +138,12 @@ class NativeRegisterContextLinux_arm64
 
   uint64_t m_fpmr_reg;
 
+  struct poe_regs {
+    uint64_t por_reg;
+  };
+
+  struct poe_regs m_poe_regs;
+
   struct gcs_regs {
     uint64_t features_enabled;
     uint64_t features_locked;
@@ -192,6 +199,10 @@ class NativeRegisterContextLinux_arm64
 
   Status WriteFPMR();
 
+  Status ReadPOE();
+
+  Status WritePOE();
+
   bool IsSVE(unsigned reg) const;
   bool IsSME(unsigned reg) const;
   bool IsPAuth(unsigned reg) const;
@@ -199,6 +210,7 @@ class NativeRegisterContextLinux_arm64
   bool IsTLS(unsigned reg) const;
   bool IsFPMR(unsigned reg) const;
   bool IsGCS(unsigned reg) const;
+  bool IsPOE(unsigned reg) const;
 
   uint64_t GetSVERegVG() { return m_sve_header.vl / 8; }
 
@@ -226,6 +238,8 @@ class NativeRegisterContextLinux_arm64
 
   void *GetGCSBuffer() { return &m_gcs_regs; }
 
+  void *GetPOEBuffer() { return &m_poe_regs; }
+
   size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
 
   size_t GetPACMaskSize() { return sizeof(m_pac_mask); }
@@ -250,6 +264,8 @@ class NativeRegisterContextLinux_arm64
 
   size_t GetGCSBufferSize() { return sizeof(m_gcs_regs); }
 
+  size_t GetPOEBufferSize() { return sizeof(m_poe_regs); }
+
   llvm::Error ReadHardwareDebugInfo() override;
 
   llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
diff --git a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp 
b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
index dbbfc6a352e02..3cda0c80259de 100644
--- a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -137,6 +137,7 @@ void LinuxSignals::Reset() {
   ADD_SIGCODE(SIGSEGV, 11, SEGV_MAPERR,  1, "address not mapped to object", 
SignalCodePrintOption::Address);
   ADD_SIGCODE(SIGSEGV, 11, SEGV_ACCERR,  2, "invalid permissions for mapped 
object", SignalCodePrintOption::Address);
   ADD_SIGCODE(SIGSEGV, 11, SEGV_BNDERR,  3, "failed address bounds checks", 
SignalCodePrintOption::Bounds);
+  ADD_SIGCODE(SIGSEGV, 11, SEGV_PKUERR,  4, "failed protection key checks", 
SignalCodePrintOption::Address);
   ADD_SIGCODE(SIGSEGV, 11, SEGV_MTEAERR, 8, "async tag check fault");
   ADD_SIGCODE(SIGSEGV, 11, SEGV_MTESERR, 9, "sync tag check fault", 
SignalCodePrintOption::Address);
   ADD_SIGCODE(SIGSEGV, 11, SEGV_CPERR,  10, "control protection fault");
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp 
b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 0233837f99d09..ecff3bfd6c898 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -67,6 +67,10 @@ bool RegisterContextPOSIX_arm64::IsGCS(unsigned reg) const {
   return m_register_info_up->IsGCSReg(reg);
 }
 
+bool RegisterContextPOSIX_arm64::IsPOE(unsigned reg) const {
+  return m_register_info_up->IsPOEReg(reg);
+}
+
 RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
     lldb_private::Thread &thread,
     std::unique_ptr<RegisterInfoPOSIX_arm64> register_info)
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h 
b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
index de46c628d836d..eba02cdd13699 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -60,6 +60,7 @@ class RegisterContextPOSIX_arm64 : public 
lldb_private::RegisterContext {
   bool IsMTE(unsigned reg) const;
   bool IsFPMR(unsigned reg) const;
   bool IsGCS(unsigned reg) const;
+  bool IsPOE(unsigned reg) const;
 
   bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); 
}
   bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); 
}
diff --git 
a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp 
b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
index 330a24af67c4e..038bc946d1441 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
@@ -25,11 +25,45 @@
 #define HWCAP2_SME (1ULL << 23)
 #define HWCAP2_EBF16 (1ULL << 32)
 #define HWCAP2_FPMR (1ULL << 48)
+#define HWCAP2_POE (1ULL << 63)
 
 #define HWCAP3_MTE_STORE_ONLY (1ULL << 1)
 
 using namespace lldb_private;
 
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectPORFields(uint64_t hwcap, uint64_t hwcap2,
+                                            uint64_t hwcap3) {
+  (void)hwcap;
+  (void)hwcap3;
+
+  if (!(hwcap2 & HWCAP2_POE))
+    return {};
+
+  static const FieldEnum por_perm_enum("por_perm_enum",
+                                       {
+                                           {0b0000, "No Access"},
+                                           {0b0001, "Read"},
+                                           {0b0010, "Execute"},
+                                           {0b0011, "Read, Execute"},
+                                           {0b0100, "Write"},
+                                           {0b0101, "Write, Read"},
+                                           {0b0110, "Write, Execute"},
+                                           {0b0111, "Read, Write, Execute"},
+                                       });
+
+  return {
+      {"Perm15", 60, 63, &por_perm_enum}, {"Perm14", 56, 59, &por_perm_enum},
+      {"Perm13", 52, 55, &por_perm_enum}, {"Perm12", 48, 51, &por_perm_enum},
+      {"Perm11", 44, 47, &por_perm_enum}, {"Perm10", 40, 43, &por_perm_enum},
+      {"Perm9", 36, 39, &por_perm_enum},  {"Perm8", 32, 35, &por_perm_enum},
+      {"Perm7", 28, 31, &por_perm_enum},  {"Perm6", 24, 27, &por_perm_enum},
+      {"Perm5", 20, 23, &por_perm_enum},  {"Perm4", 16, 19, &por_perm_enum},
+      {"Perm3", 12, 15, &por_perm_enum},  {"Perm2", 8, 11, &por_perm_enum},
+      {"Perm1", 4, 7, &por_perm_enum},    {"Perm0", 0, 3, &por_perm_enum},
+  };
+}
+
 Arm64RegisterFlagsDetector::Fields
 Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
                                              uint64_t hwcap3) {
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h 
b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
index aec2bf9f4886f..3bd3a44f1c30d 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
@@ -69,6 +69,8 @@ class Arm64RegisterFlagsDetector {
                                  uint64_t hwcap3);
   static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2,
                                        uint64_t hwcap3);
+  static Fields DetectPORFields(uint64_t hwcap, uint64_t hwcap2,
+                                uint64_t hwcap3);
 
   struct RegisterEntry {
     RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -78,7 +80,7 @@ class Arm64RegisterFlagsDetector {
     llvm::StringRef m_name;
     RegisterFlags m_flags;
     DetectorFn m_detector;
-  } m_registers[8] = {
+  } m_registers[9] = {
       RegisterEntry("cpsr", 4, DetectCPSRFields),
       RegisterEntry("fpsr", 4, DetectFPSRFields),
       RegisterEntry("fpcr", 4, DetectFPCRFields),
@@ -87,6 +89,7 @@ class Arm64RegisterFlagsDetector {
       RegisterEntry("fpmr", 8, DetectFPMRFields),
       RegisterEntry("gcs_features_enabled", 8, DetectGCSFeatureFields),
       RegisterEntry("gcs_features_locked", 8, DetectGCSFeatureFields),
+      RegisterEntry("por", 8, DetectPORFields),
   };
 
   // Becomes true once field detection has been run for all registers.
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp 
b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
index 3b8d6a84c964c..df1940a15ec6e 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -101,6 +101,9 @@ static lldb_private::RegisterInfo g_register_infos_gcs[] = {
     DEFINE_EXTENSION_REG(gcs_features_enabled),
     DEFINE_EXTENSION_REG(gcs_features_locked), 
DEFINE_EXTENSION_REG(gcspr_el0)};
 
+static lldb_private::RegisterInfo g_register_infos_poe[] = {
+    DEFINE_EXTENSION_REG(por)};
+
 // Number of register sets provided by this context.
 enum {
   k_num_gpr_registers = gpr_w28 - gpr_x0 + 1,
@@ -114,6 +117,7 @@ enum {
   k_num_sme_register = 3,
   k_num_fpmr_register = 1,
   k_num_gcs_register = 3,
+  k_num_poe_register = 1,
   k_num_register_sets_default = 2,
   k_num_register_sets = 3
 };
@@ -229,6 +233,9 @@ static const lldb_private::RegisterSet g_reg_set_fpmr_arm64 
= {
 static const lldb_private::RegisterSet g_reg_set_gcs_arm64 = {
     "Guarded Control Stack Registers", "gcs", k_num_gcs_register, nullptr};
 
+static const lldb_private::RegisterSet g_reg_set_poe_arm64 = {
+    "Permission Overlay Registers", "poe", k_num_poe_register, nullptr};
+
 RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
     const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
     : lldb_private::RegisterInfoAndSetInterface(target_arch),
@@ -284,6 +291,9 @@ RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
       if (m_opt_regsets.AllSet(eRegsetMaskGCS))
         AddRegSetGCS();
 
+      if (m_opt_regsets.AllSet(eRegsetMaskPOE))
+        AddRegSetPOE();
+
       m_register_info_count = m_dynamic_reg_infos.size();
       m_register_info_p = m_dynamic_reg_infos.data();
       m_register_set_p = m_dynamic_reg_sets.data();
@@ -462,6 +472,21 @@ void RegisterInfoPOSIX_arm64::AddRegSetGCS() {
   m_dynamic_reg_sets.back().registers = m_gcs_regnum_collection.data();
 }
 
+void RegisterInfoPOSIX_arm64::AddRegSetPOE() {
+  uint32_t poe_regnum = m_dynamic_reg_infos.size();
+  m_poe_regnum_collection.push_back(poe_regnum);
+  m_dynamic_reg_infos.push_back(g_register_infos_poe[0]);
+  m_dynamic_reg_infos[poe_regnum].byte_offset =
+      m_dynamic_reg_infos[poe_regnum - 1].byte_offset +
+      m_dynamic_reg_infos[poe_regnum - 1].byte_size;
+  m_dynamic_reg_infos[poe_regnum].kinds[lldb::eRegisterKindLLDB] = poe_regnum;
+
+  m_per_regset_regnum_range[m_register_set_count] =
+      std::make_pair(poe_regnum, poe_regnum + 1);
+  m_dynamic_reg_sets.push_back(g_reg_set_poe_arm64);
+  m_dynamic_reg_sets.back().registers = m_poe_regnum_collection.data();
+}
+
 uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLengthSVE(uint32_t sve_vq) {
   // sve_vq contains SVE Quad vector length in context of AArch64 SVE.
   // SVE register infos if enabled cannot be disabled by selecting sve_vq = 0.
@@ -593,6 +618,10 @@ bool RegisterInfoPOSIX_arm64::IsGCSReg(unsigned reg) const 
{
   return llvm::is_contained(m_gcs_regnum_collection, reg);
 }
 
+bool RegisterInfoPOSIX_arm64::IsPOEReg(unsigned reg) const {
+  return llvm::is_contained(m_poe_regnum_collection, reg);
+}
+
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; }
@@ -630,3 +659,7 @@ uint32_t RegisterInfoPOSIX_arm64::GetFPMROffset() const {
 uint32_t RegisterInfoPOSIX_arm64::GetGCSOffset() const {
   return m_register_info_p[m_gcs_regnum_collection[0]].byte_offset;
 }
+
+uint32_t RegisterInfoPOSIX_arm64::GetPOEOffset() const {
+  return m_register_info_p[m_poe_regnum_collection[0]].byte_offset;
+}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h 
b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
index bca5bff24bff0..b40235a3655b8 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ar...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/177145
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to