omjavaid created this revision.
omjavaid added a reviewer: labath.
Herald added a subscriber: kristof.beyls.
omjavaid requested review of this revision.

This is the first patch in series for supporting Arm64 dynamic features in 
LLDB. Arm64 has dynamic features like SVE, Pointer Authentication and MTE which 
means LLDB needs to decide at run time which registers it needs to pull in for 
the current executable based on underlying support for a certain feature.

This patch makes necessary adjustments to RegisterInfoPOSIX_arm64 to make way 
for dynamic register infos and dynamic register sets. This patch does not add 
any new feature per se but makes way for adding new dynamic register sets in 
following up patches.


https://reviews.llvm.org/D96458

Files:
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
  lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp

Index: lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -70,15 +70,18 @@
              sve::ptrace_regs_sve)
       m_sve_state = SVEState::Full;
 
-    if (sve::vl_valid(m_sve_vector_length))
-      m_register_info_up->ConfigureVectorRegisterInfos(
-          sve::vq_from_vl(m_sve_vector_length));
-    else {
+    if (!sve::vl_valid(m_sve_vector_length)) {
       m_sve_state = SVEState::Disabled;
       m_sve_vector_length = 0;
     }
   } else
     m_sve_state = SVEState::Disabled;
+
+  if (m_sve_state != SVEState::Disabled) {
+    m_register_info_up->ConfigureRegisterInfos(ARM64_REGS_CONFIG_SVE);
+    m_register_info_up->ConfigureVectorLength(
+        sve::vq_from_vl(m_sve_vector_length));
+  }
 }
 
 uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset(
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
@@ -14,6 +14,9 @@
 #include "lldb/lldb-private.h"
 #include <map>
 
+#define ARM64_REGS_CONFIG_DEFAULT 0x00
+#define ARM64_REGS_CONFIG_SVE 0x01
+
 enum class SVEState { Unknown, Disabled, FPSIMD, Full };
 
 class RegisterInfoPOSIX_arm64
@@ -85,7 +88,9 @@
 
   size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override;
 
-  uint32_t ConfigureVectorRegisterInfos(uint32_t sve_vq);
+  void ConfigureRegisterInfos(uint32_t opt_regsets);
+
+  uint32_t ConfigureVectorLength(uint32_t mode);
 
   bool VectorSizeIsValid(uint32_t vq) {
     if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax)
@@ -95,6 +100,7 @@
 
   bool IsSVEEnabled() const { return m_vector_reg_vq > eVectorQuadwordAArch64; }
 
+  bool IsSVEReg(unsigned reg) const;
   bool IsSVEZReg(unsigned reg) const;
   bool IsSVEPReg(unsigned reg) const;
   bool IsSVERegVG(unsigned reg) const;
@@ -115,6 +121,16 @@
 
   const lldb_private::RegisterInfo *m_register_info_p;
   uint32_t m_register_info_count;
+
+  const lldb_private::RegisterSet *m_register_set_p;
+  uint32_t m_register_set_count;
+
+  std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range;
+
+  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;
 };
 
 #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
@@ -203,10 +203,17 @@
     const lldb_private::ArchSpec &target_arch)
     : lldb_private::RegisterInfoAndSetInterface(target_arch),
       m_register_info_p(GetRegisterInfoPtr(target_arch)),
-      m_register_info_count(GetRegisterInfoCount(target_arch)) {
+      m_register_info_count(GetRegisterInfoCount(target_arch)),
+      m_register_set_p(g_reg_sets_arm64),
+      m_register_set_count(k_num_register_sets - 1) {
+  m_per_regset_regnum_range[GPRegSet] = std::make_pair(gpr_x0, gpr_w28);
+  m_per_regset_regnum_range[FPRegSet] = std::make_pair(fpu_v0, fpu_fpcr);
 }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const {
+  if (m_reg_infos_is_dynamic)
+    return m_register_info_count;
+
   if (IsSVEEnabled())
     return k_num_gpr_registers + k_num_fpr_registers + k_num_sve_registers;
 
@@ -227,31 +234,69 @@
 }
 
 size_t RegisterInfoPOSIX_arm64::GetRegisterSetCount() const {
-  if (IsSVEEnabled())
-    return k_num_register_sets;
-  return k_num_register_sets - 1;
+  return m_register_set_count;
 }
 
 size_t RegisterInfoPOSIX_arm64::GetRegisterSetFromRegisterIndex(
     uint32_t reg_index) const {
-  if (reg_index <= gpr_w28)
-    return GPRegSet;
-  if (reg_index <= fpu_fpcr)
-    return FPRegSet;
-  if (reg_index <= sve_ffr)
-    return SVERegSet;
+  for (const auto &regset_range : m_per_regset_regnum_range) {
+    if (reg_index >= regset_range.second.first &&
+        reg_index <= regset_range.second.second)
+      return regset_range.first;
+  }
   return LLDB_INVALID_REGNUM;
 }
 
 const lldb_private::RegisterSet *
 RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const {
   if (set_index < GetRegisterSetCount())
-    return &g_reg_sets_arm64[set_index];
+    return &m_register_set_p[set_index];
   return nullptr;
 }
 
-uint32_t
-RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) {
+void RegisterInfoPOSIX_arm64::ConfigureRegisterInfos(uint32_t opt_regsets) {
+  // TODO: Comment Here
+  if (opt_regsets > ARM64_REGS_CONFIG_SVE) {
+    m_reg_infos_is_dynamic = true;
+  }
+
+  if (m_reg_infos_is_dynamic) {
+    const lldb_private::RegisterInfo *reginfo_start, *reginfo_end;
+    const lldb_private::RegisterSet *regset_start = g_reg_sets_arm64;
+    if (opt_regsets & ARM64_REGS_CONFIG_SVE) {
+      reginfo_start = g_register_infos_arm64_sve_le;
+      reginfo_end = g_register_infos_arm64_sve_le + sve_ffr + 1;
+      m_per_regset_regnum_range[m_register_set_count] =
+          std::make_pair(sve_vg, sve_ffr);
+      m_register_set_count++;
+    } else {
+      reginfo_start = g_register_infos_arm64_le;
+      reginfo_end = g_register_infos_arm64_le + fpu_fpcr + 1;
+    }
+
+    std::copy(reginfo_start, reginfo_end,
+              std::back_inserter(m_dynamic_reg_infos));
+    std::copy(regset_start, regset_start + m_register_set_count,
+              std::back_inserter(m_dynamic_reg_sets));
+
+    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();
+    m_register_set_count = m_dynamic_reg_sets.size();
+  } else {
+    if (opt_regsets & ARM64_REGS_CONFIG_SVE) {
+      m_register_info_p = g_register_infos_arm64_sve_le;
+      m_register_info_count =
+          static_cast<uint32_t>(sizeof(g_register_infos_arm64_sve_le) /
+                                sizeof(g_register_infos_arm64_sve_le[0]));
+      m_per_regset_regnum_range[m_register_set_count] =
+          std::make_pair(sve_vg, sve_ffr);
+      m_register_set_count++;
+    }
+  }
+}
+
+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.
   // Also if an invalid or previously set vector length is passed to this
@@ -266,28 +311,15 @@
 
   m_vector_reg_vq = sve_vq;
 
-  if (sve_vq == eVectorQuadwordAArch64) {
-    m_register_info_count =
-        static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) /
-                              sizeof(g_register_infos_arm64_le[0]));
-    m_register_info_p = g_register_infos_arm64_le;
-
+  if (sve_vq == eVectorQuadwordAArch64)
     return m_vector_reg_vq;
-  }
-
-  m_register_info_count =
-      static_cast<uint32_t>(sizeof(g_register_infos_arm64_sve_le) /
-                            sizeof(g_register_infos_arm64_sve_le[0]));
-
   std::vector<lldb_private::RegisterInfo> &reg_info_ref =
       m_per_vq_reg_infos[sve_vq];
 
   if (reg_info_ref.empty()) {
-    reg_info_ref = llvm::makeArrayRef(g_register_infos_arm64_sve_le,
-                                      m_register_info_count);
+    reg_info_ref = llvm::makeArrayRef(m_register_info_p, m_register_info_count);
 
     uint32_t offset = SVE_REGS_DEFAULT_OFFSET_LINUX;
-
     reg_info_ref[fpu_fpsr].byte_offset = offset;
     reg_info_ref[fpu_fpcr].byte_offset = offset + 4;
     reg_info_ref[sve_vg].byte_offset = offset + 8;
@@ -316,13 +348,25 @@
       offset += reg_info_ref[it].byte_size;
     }
 
+    for (uint32_t it = sve_ffr + 1; it < m_register_info_count; it++) {
+      reg_info_ref[it].byte_offset = offset;
+      offset += reg_info_ref[it].byte_size;
+    }
+
     m_per_vq_reg_infos[sve_vq] = reg_info_ref;
   }
 
-  m_register_info_p = reg_info_ref.data();
+  m_register_info_p = m_per_vq_reg_infos[sve_vq].data();
   return m_vector_reg_vq;
 }
 
+bool RegisterInfoPOSIX_arm64::IsSVEReg(unsigned reg) const {
+  if (m_vector_reg_vq > eVectorQuadwordAArch64)
+    return (sve_vg <= reg && reg <= sve_ffr);
+  else
+    return false;
+}
+
 bool RegisterInfoPOSIX_arm64::IsSVEZReg(unsigned reg) const {
   return (sve_z0 <= reg && reg <= sve_z31);
 }
Index: lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -40,8 +40,7 @@
 }
 
 bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const {
-  if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
-      RegisterInfoPOSIX_arm64::SVERegSet)
+  if (m_register_info_up->IsSVEReg(reg))
     return true;
   return false;
 }
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
@@ -451,8 +451,7 @@
 }
 
 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
-  if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
-      RegisterInfoPOSIX_arm64::SVERegSet)
+  if (GetRegisterInfo().IsSVEReg(reg))
     return true;
   return false;
 }
@@ -1095,11 +1094,19 @@
   // Read SVE configuration data and configure register infos.
   if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
     Status error = ReadSVEHeader();
-    if (!error.Success() && m_sve_state == SVEState::Unknown) {
-      m_sve_state = SVEState::Disabled;
-      GetRegisterInfo().ConfigureVectorRegisterInfos(
-          RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64);
-    } else {
+    uint32_t opt_regset = ARM64_REGS_CONFIG_DEFAULT;
+    if (m_sve_state == SVEState::Unknown) {
+      if (error.Success()) {
+        opt_regset |= ARM64_REGS_CONFIG_SVE;
+        GetRegisterInfo().ConfigureRegisterInfos(opt_regset);
+      } else {
+        m_sve_state = SVEState::Disabled;
+        GetRegisterInfo().ConfigureRegisterInfos(opt_regset);
+        return;
+      }
+    }
+
+    if (error.Success()) {
       if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)
         m_sve_state = SVEState::FPSIMD;
       else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE)
@@ -1108,7 +1115,8 @@
       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
       if (sve_vl_valid(m_sve_header.vl))
         vq = sve_vq_from_vl(m_sve_header.vl);
-      GetRegisterInfo().ConfigureVectorRegisterInfos(vq);
+
+      GetRegisterInfo().ConfigureVectorLength(vq);
       m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE));
     }
   }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to