omjavaid updated this revision to Diff 325493.
omjavaid added a comment.

Ran clang format and fixed typos.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96460/new/

https://reviews.llvm.org/D96460

Files:
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
  lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h

Index: lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -470,6 +470,13 @@
         LLDB_INVALID_REGNUM, lldb_kind                                         \
   }
 
+// Generates register kinds array for registers with only lldb kind
+#define KIND_ALL_INVALID                                                       \
+  {                                                                            \
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,             \
+        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM                               \
+  }
+
 // Generates register kinds array for vector registers
 #define GPR64_KIND(reg, generic_kind) MISC_KIND(reg, gpr, generic_kind)
 #define VREG_KIND(reg) MISC_KIND(reg, fpu, LLDB_INVALID_REGNUM)
@@ -526,6 +533,13 @@
         nullptr, 0                                                             \
   }
 
+// Defines pointer authentication mask registers
+#define DEFINE_EXTENSION_REG(reg)                                              \
+  {                                                                            \
+    #reg, nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex,                \
+        KIND_ALL_INVALID, nullptr, nullptr, nullptr, 0                         \
+  }
+
 static lldb_private::RegisterInfo g_register_infos_arm64_le[] = {
     // DEFINE_GPR64(name, GENERIC KIND)
     DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1),
@@ -772,7 +786,12 @@
     {DEFINE_DBG(wcr, 13)},
     {DEFINE_DBG(wcr, 14)},
     {DEFINE_DBG(wcr, 15)}
-    // clang-format on
 };
+// clang-format on
+static lldb_private::RegisterInfo g_register_infos_pauth[] = {
+    DEFINE_EXTENSION_REG(data_mask), DEFINE_EXTENSION_REG(code_mask)};
+
+static lldb_private::RegisterInfo g_register_infos_mte[] = {
+    DEFINE_EXTENSION_REG(mte_ctrl)};
 
 #endif // DECLARE_REGISTER_INFOS_ARM64_STRUCT
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -25,6 +25,8 @@
   enum {
     eRegsetEnableDefault = 0,
     eRegsetEnableSVE = 1,
+    eRegsetEnablePAuth = 2,
+    eRegsetEnableMTE = 4
   };
 
   // AArch64 Register set FP/SIMD feature configuration
@@ -93,6 +95,10 @@
 
   void ConfigureRegisterInfos(uint32_t opt_regsets);
 
+  void AddRegSetPAuth();
+
+  void AddRegSetMTE();
+
   uint32_t ConfigureVectorLength(uint32_t sve_vq);
 
   bool VectorSizeIsValid(uint32_t vq) {
@@ -107,12 +113,16 @@
   bool IsSVEZReg(unsigned reg) const;
   bool IsSVEPReg(unsigned reg) const;
   bool IsSVERegVG(unsigned reg) const;
+  bool IsPAuthReg(unsigned reg) const;
+  bool IsMTEReg(unsigned reg) const;
 
   uint32_t GetRegNumSVEZ0() const;
   uint32_t GetRegNumSVEFFR() const;
   uint32_t GetRegNumFPCR() const;
   uint32_t GetRegNumFPSR() const;
   uint32_t GetRegNumSVEVG() const;
+  uint32_t GetPAuthOffset() const;
+  uint32_t GetMTEOffset() const;
 
 private:
   typedef std::map<uint32_t, std::vector<lldb_private::RegisterInfo>>
@@ -132,10 +142,15 @@
   // and end included.
   std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range;
 
+  bool m_mte_regset_enabled = false;
+  bool m_pauth_regset_enabled = false;
   bool m_reg_infos_is_dynamic = false;
 
   std::vector<lldb_private::RegisterInfo> m_dynamic_reg_infos;
   std::vector<lldb_private::RegisterSet> m_dynamic_reg_sets;
+
+  std::vector<uint32_t> pauth_regnum_collection;
+  std::vector<uint32_t> m_mte_regnum_collection;
 };
 
 #endif
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -89,6 +89,8 @@
   k_num_gpr_registers = gpr_w28 - gpr_x0 + 1,
   k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1,
   k_num_sve_registers = sve_ffr - sve_vg + 1,
+  k_num_mte_register = 1,
+  k_num_pauth_register = 2,
   k_num_register_sets = 3
 };
 
@@ -186,6 +188,12 @@
     {"Scalable Vector Extension Registers", "sve", k_num_sve_registers,
      g_sve_regnums_arm64}};
 
+static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = {
+    "Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL};
+
+static const lldb_private::RegisterSet g_reg_set_mte_arm64 = {
+    "MTE Control Register", "mte", k_num_mte_register, NULL};
+
 static uint32_t
 GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
   switch (target_arch.GetMachine()) {
@@ -261,6 +269,11 @@
   // register infos and regset and calculate register offsets accordingly.
   if (opt_regsets > eRegsetEnableSVE) {
     m_reg_infos_is_dynamic = true;
+    if (opt_regsets & eRegsetEnablePAuth)
+      m_pauth_regset_enabled = true;
+
+    if (opt_regsets & eRegsetEnableMTE)
+      m_mte_regset_enabled = true;
   }
 
   if (m_reg_infos_is_dynamic) {
@@ -282,6 +295,12 @@
     std::copy(regset_start, regset_start + m_register_set_count,
               std::back_inserter(m_dynamic_reg_sets));
 
+    if (m_pauth_regset_enabled)
+      AddRegSetPAuth();
+
+    if (m_mte_regset_enabled)
+      AddRegSetMTE();
+
     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();
@@ -299,6 +318,35 @@
   }
 }
 
+void RegisterInfoPOSIX_arm64::AddRegSetPAuth() {
+  uint32_t pa_regnum = m_dynamic_reg_infos.size();
+  for (uint32_t i = 0; i < k_num_pauth_register; i++) {
+    pauth_regnum_collection.push_back(pa_regnum + i);
+    m_dynamic_reg_infos.push_back(g_register_infos_pauth[i]);
+    m_dynamic_reg_infos[pa_regnum + i].byte_offset =
+        m_dynamic_reg_infos[pa_regnum + i - 1].byte_offset +
+        m_dynamic_reg_infos[pa_regnum + i - 1].byte_size;
+    m_dynamic_reg_infos[pa_regnum + i].kinds[lldb::eRegisterKindLLDB] =
+        pa_regnum + i;
+  }
+
+  m_dynamic_reg_sets.push_back(g_reg_set_pauth_arm64);
+  m_dynamic_reg_sets.back().registers = pauth_regnum_collection.data();
+}
+
+void RegisterInfoPOSIX_arm64::AddRegSetMTE() {
+  uint32_t mte_regnum = m_dynamic_reg_infos.size();
+  m_mte_regnum_collection.push_back(mte_regnum);
+  m_dynamic_reg_infos.push_back(g_register_infos_mte[0]);
+  m_dynamic_reg_infos[mte_regnum].byte_offset =
+      m_dynamic_reg_infos[mte_regnum - 1].byte_offset +
+      m_dynamic_reg_infos[mte_regnum - 1].byte_size;
+  m_dynamic_reg_infos[mte_regnum].kinds[lldb::eRegisterKindLLDB] = mte_regnum;
+
+  m_dynamic_reg_sets.push_back(g_reg_set_mte_arm64);
+  m_dynamic_reg_sets.back().registers = m_mte_regnum_collection.data();
+}
+
 uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(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.
@@ -382,6 +430,18 @@
   return sve_vg == reg;
 }
 
+bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
+  return std::find(pauth_regnum_collection.begin(),
+                   pauth_regnum_collection.end(),
+                   reg) != pauth_regnum_collection.end();
+}
+
+bool RegisterInfoPOSIX_arm64::IsMTEReg(unsigned reg) const {
+  return std::find(m_mte_regnum_collection.begin(),
+                   m_mte_regnum_collection.end(),
+                   reg) != m_mte_regnum_collection.end();
+}
+
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; }
@@ -391,3 +451,11 @@
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
+
+uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
+  return m_register_info_p[pauth_regnum_collection[0]].byte_offset;
+}
+
+uint32_t RegisterInfoPOSIX_arm64::GetMTEOffset() const {
+  return m_register_info_p[m_mte_regnum_collection[0]].byte_offset;
+}
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -109,8 +109,10 @@
   bool m_gpr_is_valid;
   bool m_fpu_is_valid;
   bool m_sve_buffer_is_valid;
+  bool m_mte_ctrl_is_valid;
 
   bool m_sve_header_is_valid;
+  bool m_pac_mask_is_valid;
 
   struct user_pt_regs m_gpr_arm64; // 64-bit general purpose registers.
 
@@ -138,6 +140,15 @@
   uint32_t m_max_hbp_supported;
   bool m_refresh_hwdebug_info;
 
+  struct user_pac_mask {
+    uint64_t data_mask;
+    uint64_t insn_mask;
+  };
+
+  struct user_pac_mask m_pac_mask;
+
+  uint64_t m_mte_ctrl_reg;
+
   bool IsGPR(unsigned reg) const;
 
   bool IsFPR(unsigned reg) const;
@@ -150,7 +161,15 @@
 
   Status WriteSVEHeader();
 
+  Status ReadPAuthMask();
+
+  Status ReadMTEControl();
+
+  Status WriteMTEControl();
+
   bool IsSVE(unsigned reg) const;
+  bool IsPAuth(unsigned reg) const;
+  bool IsMTE(unsigned reg) const;
 
   uint64_t GetSVERegVG() { return m_sve_header.vl / 8; }
 
@@ -158,12 +177,20 @@
 
   void *GetSVEHeader() { return &m_sve_header; }
 
+  void *GetPACMask() { return &m_pac_mask; }
+
+  void *GetMTEControl() { return &m_mte_ctrl_reg; }
+
   void *GetSVEBuffer();
 
   size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
 
+  size_t GetPACMaskSize() { return sizeof(m_pac_mask); }
+
   size_t GetSVEBufferSize() { return m_sve_ptrace_payload.size(); }
 
+  size_t GetMTEControlSize() { return sizeof(m_mte_ctrl_reg); }
+
   Status ReadHardwareDebugInfo();
 
   uint32_t QueryAuxvForOptionalRegset();
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -34,6 +34,17 @@
 #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
 #endif
 
+#ifndef NT_ARM_PAC_MASK
+#define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
+#endif
+
+#ifndef NT_ARM_TAGGED_ADDR_CTRL
+#define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
+#endif
+
+#define HWCAP_PACA (1 << 30)
+#define HWCAP2_MTE (1 << 18)
+
 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
 
 using namespace lldb;
@@ -64,6 +75,9 @@
   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
   ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs));
   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
+  ::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
+
+  m_mte_ctrl_reg = 0;
 
   // 16 is just a maximum value, query hardware for actual watchpoint count
   m_max_hwp_supported = 16;
@@ -75,6 +89,8 @@
   m_fpu_is_valid = false;
   m_sve_buffer_is_valid = false;
   m_sve_header_is_valid = false;
+  m_pac_mask_is_valid = false;
+  m_mte_ctrl_is_valid = false;
 
   // At this stage we configure register sets supported by this AArch64 target.
   // ReadSVEHeader is called to check for SVE support.
@@ -100,7 +116,31 @@
 }
 
 uint32_t NativeRegisterContextLinux_arm64::QueryAuxvForOptionalRegset() {
-  return RegisterInfoPOSIX_arm64::eRegsetEnableSVE;
+  NativeProcessProtocol &process = m_thread.GetProcess();
+  auto buffer_or_error = process.GetAuxvData();
+  if (!buffer_or_error)
+    return 0;
+
+  DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(),
+                          buffer_or_error.get()->getBufferSize(),
+                          process.GetByteOrder(), process.GetAddressByteSize());
+
+  std::unique_ptr<AuxVector> aux_vector =
+      std::make_unique<AuxVector>(auxv_data);
+
+  llvm::Optional<uint64_t> auxv_at_hwcap =
+      aux_vector->GetAuxValue(AuxVector::AUXV_AT_HWCAP);
+  uint32_t result = RegisterInfoPOSIX_arm64::eRegsetEnableDefault;
+  if (auxv_at_hwcap && *auxv_at_hwcap & HWCAP_PACA)
+    result |= RegisterInfoPOSIX_arm64::eRegsetEnablePAuth;
+
+  llvm::Optional<uint64_t> auxv_at_hwcap2 =
+      aux_vector->GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
+
+  if (auxv_at_hwcap && *auxv_at_hwcap2 & HWCAP2_MTE)
+    result |= RegisterInfoPOSIX_arm64::eRegsetEnableMTE;
+
+  return result;
 }
 
 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
@@ -227,6 +267,22 @@
         src = (uint8_t *)GetSVEBuffer() + offset;
       }
     }
+  } else if (IsPAuth(reg)) {
+    error = ReadPAuthMask();
+    if (error.Fail())
+      return error;
+
+    offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
+    assert(offset < GetPACMaskSize());
+    src = (uint8_t *)GetPACMask() + offset;
+  } else if (IsMTE(reg)) {
+    error = ReadMTEControl();
+    if (error.Fail())
+      return error;
+
+    offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
+    assert(offset < GetMTEControlSize());
+    src = (uint8_t *)GetMTEControl() + offset;
   } else
     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
                   "write strategy unknown");
@@ -385,6 +441,17 @@
         return WriteAllSVE();
       }
     }
+  } else if (IsMTE(reg)) {
+    error = ReadMTEControl();
+    if (error.Fail())
+      return error;
+
+    offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
+    assert(offset < GetMTEControlSize());
+    dst = (uint8_t *)GetMTEControl() + offset;
+    ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
+
+    return WriteMTEControl();
   }
 
   return Status("Failed to write register value");
@@ -473,6 +540,14 @@
   return GetRegisterInfo().IsSVEReg(reg);
 }
 
+bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const {
+  return GetRegisterInfo().IsPAuthReg(reg);
+}
+
+bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const {
+  return GetRegisterInfo().IsMTEReg(reg);
+}
+
 uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
 
@@ -1030,6 +1105,8 @@
   m_fpu_is_valid = false;
   m_sve_buffer_is_valid = false;
   m_sve_header_is_valid = false;
+  m_pac_mask_is_valid = false;
+  m_mte_ctrl_is_valid = false;
 
   // Update SVE registers in case there is change in configuration.
   ConfigureRegisterContext();
@@ -1047,7 +1124,26 @@
 
   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
 
-  m_sve_header_is_valid = true;
+  if (error.Success())
+    m_sve_header_is_valid = true;
+
+  return error;
+}
+
+Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
+  Status error;
+
+  if (m_pac_mask_is_valid)
+    return error;
+
+  struct iovec ioVec;
+  ioVec.iov_base = GetPACMask();
+  ioVec.iov_len = GetPACMaskSize();
+
+  error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
+
+  if (error.Success())
+    m_pac_mask_is_valid = true;
 
   return error;
 }
@@ -1107,6 +1203,40 @@
   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
 }
 
+Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
+  Status error;
+
+  if (m_mte_ctrl_is_valid)
+    return error;
+
+  struct iovec ioVec;
+  ioVec.iov_base = GetMTEControl();
+  ioVec.iov_len = GetMTEControlSize();
+
+  error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
+
+  if (error.Success())
+    m_mte_ctrl_is_valid = true;
+
+  return error;
+}
+
+Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
+  Status error;
+
+  error = ReadMTEControl();
+  if (error.Fail())
+    return error;
+
+  struct iovec ioVec;
+  ioVec.iov_base = GetMTEControl();
+  ioVec.iov_len = GetMTEControlSize();
+
+  m_mte_ctrl_is_valid = false;
+
+  return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
+}
+
 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
   // ConfigureRegisterContext gets called from InvalidateAllRegisters
   // on every stop and configures SVE vector length.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to