[Lldb-commits] [lldb] 69a3269 - Support AArch64 PAC elf-core register read

Muhammad Omair Javaid via lldb-commits lldb-commits at lists.llvm.org
Mon May 3 04:06:19 PDT 2021


Author: Muhammad Omair Javaid
Date: 2021-05-03T16:04:47+05:00
New Revision: 69a3269250715e31ec49be94065c1c8787a3d305

URL: https://github.com/llvm/llvm-project/commit/69a3269250715e31ec49be94065c1c8787a3d305
DIFF: https://github.com/llvm/llvm-project/commit/69a3269250715e31ec49be94065c1c8787a3d305.diff

LOG: Support AArch64 PAC elf-core register read

This adds support for reading AArch64 Pointer Authentication regset
from elf-core file. Also includes a test-case for the same. Furthermore
there is also a slight refactoring of RegisterContextPOSIXCore_arm64
members and constructor. linux-aarch64-pac.core file is generated using
lldb/test/API/functionalities/postmortem/elf-core/main.c with following
clang arguments:
-march=armv8.5-a -mbranch-protection=pac-ret+leaf -nostdlib -static -g

Reviewed By: DavidSpickett

Differential Revision: https://reviews.llvm.org/D99941

Added: 
    lldb/test/API/functionalities/postmortem/elf-core/linux-aarch64-pac.core

Modified: 
    lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
    lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
    lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
    lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 06b200e19f1e2..c4e7eda1e5d69 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -43,6 +43,10 @@ bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const {
   return m_register_info_up->IsSVEReg(reg);
 }
 
+bool RegisterContextPOSIX_arm64::IsPAuth(unsigned reg) const {
+  return m_register_info_up->IsPAuthReg(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 a3f07bb2823b1..7c301599d3af6 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -54,6 +54,7 @@ class RegisterContextPOSIX_arm64 : public lldb_private::RegisterContext {
   size_t GetFPUSize() { return sizeof(RegisterInfoPOSIX_arm64::FPU); }
 
   bool IsSVE(unsigned reg) const;
+  bool IsPAuth(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/RegisterInfoPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
index df6e44faefbfb..ba873ba4436ba 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -109,6 +109,7 @@ class RegisterInfoPOSIX_arm64
   }
 
   bool IsSVEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskSVE); }
+  bool IsPAuthEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); }
 
   bool IsSVEReg(unsigned reg) const;
   bool IsSVEZReg(unsigned reg) const;

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 9379316d1042d..34fd16da38885 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -21,32 +21,43 @@ std::unique_ptr<RegisterContextCorePOSIX_arm64>
 RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
                                        const DataExtractor &gpregset,
                                        llvm::ArrayRef<CoreNote> notes) {
-  DataExtractor sveregset =
-      getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc);
-
   Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault;
-  if (sveregset.GetByteSize() > sizeof(sve::user_sve_header))
+
+  DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc);
+  if (sve_data.GetByteSize() > sizeof(sve::user_sve_header))
     opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
+
+  // Pointer Authentication register set data is based on struct
+  // user_pac_mask declared in ptrace.h. See reference implementation
+  // in Linux kernel source at arch/arm64/include/uapi/asm/ptrace.h.
+  DataExtractor pac_data = getRegset(notes, arch.GetTriple(), AARCH64_PAC_Desc);
+  if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2)
+    opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
+
   auto register_info_up =
       std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
   return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
       new RegisterContextCorePOSIX_arm64(thread, std::move(register_info_up),
-                                         gpregset, sveregset, notes));
+                                         gpregset, notes));
 }
 
 RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
     Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
-    const DataExtractor &gpregset, const DataExtractor &sveregset,
-    llvm::ArrayRef<CoreNote> notes)
-    : RegisterContextPOSIX_arm64(thread, std::move(register_info)),
-      m_sveregset(sveregset) {
-  m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
-                                                  gpregset.GetByteSize());
-  m_gpr.SetData(m_gpr_buffer);
-  m_gpr.SetByteOrder(gpregset.GetByteOrder());
-
-  m_fpregset = getRegset(
-      notes, m_register_info_up->GetTargetArchitecture().GetTriple(), FPR_Desc);
+    const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
+    : RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
+  m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
+                                                      gpregset.GetByteSize()));
+  m_gpr_data.SetByteOrder(gpregset.GetByteOrder());
+
+  const llvm::Triple &target_triple =
+      m_register_info_up->GetTargetArchitecture().GetTriple();
+  m_fpr_data = getRegset(notes, target_triple, FPR_Desc);
+
+  if (m_register_info_up->IsSVEEnabled())
+    m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc);
+
+  if (m_register_info_up->IsPAuthEnabled())
+    m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc);
 
   ConfigureRegisterContext();
 }
@@ -68,16 +79,16 @@ bool RegisterContextCorePOSIX_arm64::WriteFPR() {
 }
 
 const uint8_t *RegisterContextCorePOSIX_arm64::GetSVEBuffer(uint64_t offset) {
-  return m_sveregset.GetDataStart() + offset;
+  return m_sve_data.GetDataStart() + offset;
 }
 
 void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() {
-  if (m_sveregset.GetByteSize() > sizeof(sve::user_sve_header)) {
+  if (m_sve_data.GetByteSize() > sizeof(sve::user_sve_header)) {
     uint64_t sve_header_field_offset = 8;
-    m_sve_vector_length = m_sveregset.GetU16(&sve_header_field_offset);
+    m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset);
     sve_header_field_offset = 12;
     uint16_t sve_header_flags_field =
-        m_sveregset.GetU16(&sve_header_field_offset);
+        m_sve_data.GetU16(&sve_header_field_offset);
     if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
         sve::ptrace_regs_fpsimd)
       m_sve_state = SVEState::FPSIMD;
@@ -120,7 +131,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
 
   offset = reg_info->byte_offset;
   if (offset + reg_info->byte_size <= GetGPRSize()) {
-    uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+    uint64_t v = m_gpr_data.GetMaxU64(&offset, reg_info->byte_size);
     if (offset == reg_info->byte_offset + reg_info->byte_size) {
       value = v;
       return true;
@@ -135,8 +146,8 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
     if (m_sve_state == SVEState::Disabled) {
       // SVE is disabled take legacy route for FPU register access
       offset -= GetGPRSize();
-      if (offset < m_fpregset.GetByteSize()) {
-        value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset,
+      if (offset < m_fpr_data.GetByteSize()) {
+        value.SetFromMemoryData(reg_info, m_fpr_data.GetDataStart() + offset,
                                 reg_info->byte_size, lldb::eByteOrderLittle,
                                 error);
         return error.Success();
@@ -168,7 +179,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
       }
 
       assert(sve_reg_num != LLDB_INVALID_REGNUM);
-      assert(offset < m_sveregset.GetByteSize());
+      assert(offset < m_sve_data.GetByteSize());
       value.SetFromMemoryData(reg_info, GetSVEBuffer(offset),
                               reg_info->byte_size, lldb::eByteOrderLittle,
                               error);
@@ -190,7 +201,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
       if (IsSVEZ(reg)) {
         byte_size = 16;
         offset = CalculateSVEOffset(reg_info);
-        assert(offset < m_sveregset.GetByteSize());
+        assert(offset < m_sve_data.GetByteSize());
         src = GetSVEBuffer(offset);
       }
       value.SetFromMemoryData(reg_info, src, byte_size, lldb::eByteOrderLittle,
@@ -198,7 +209,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
     } break;
     case SVEState::Full:
       offset = CalculateSVEOffset(reg_info);
-      assert(offset < m_sveregset.GetByteSize());
+      assert(offset < m_sve_data.GetByteSize());
       value.SetFromMemoryData(reg_info, GetSVEBuffer(offset),
                               reg_info->byte_size, lldb::eByteOrderLittle,
                               error);
@@ -207,6 +218,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
     default:
       return false;
     }
+  } else if (IsPAuth(reg)) {
+    offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset();
+    assert(offset < m_pac_data.GetByteSize());
+    value.SetFromMemoryData(reg_info, m_pac_data.GetDataStart() + offset,
+                            reg_info->byte_size, lldb::eByteOrderLittle, error);
   } else
     return false;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index ec63eaa861119..3988e3539b897 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -42,7 +42,6 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
       lldb_private::Thread &thread,
       std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
       const lldb_private::DataExtractor &gpregset,
-      const lldb_private::DataExtractor &sveregset,
       llvm::ArrayRef<lldb_private::CoreNote> notes);
 
   bool ReadGPR() override;
@@ -54,10 +53,10 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
   bool WriteFPR() override;
 
 private:
-  lldb::DataBufferSP m_gpr_buffer;
-  lldb_private::DataExtractor m_gpr;
-  lldb_private::DataExtractor m_fpregset;
-  lldb_private::DataExtractor m_sveregset;
+  lldb_private::DataExtractor m_gpr_data;
+  lldb_private::DataExtractor m_fpr_data;
+  lldb_private::DataExtractor m_sve_data;
+  lldb_private::DataExtractor m_pac_data;
 
   SVEState m_sve_state;
   uint16_t m_sve_vector_length = 0;

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
index 25abd7ed54b7f..b048d39dbc527 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
@@ -111,6 +111,10 @@ constexpr RegsetDesc AARCH64_SVE_Desc[] = {
     {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SVE},
 };
 
+constexpr RegsetDesc AARCH64_PAC_Desc[] = {
+    {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK},
+};
+
 constexpr RegsetDesc PPC_VMX_Desc[] = {
     {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
     {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},

diff  --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index 26e85e34da730..6f8d05101baaf 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -443,6 +443,21 @@ def test_aarch64_sve_regs_full(self):
 
         self.expect("register read --all")
 
+    @skipIfLLVMTargetMissing("AArch64")
+    def test_aarch64_pac_regs(self):
+        # Test AArch64/Linux Pointer Authenication register read
+        target = self.dbg.CreateTarget(None)
+        self.assertTrue(target, VALID_TARGET)
+        process = target.LoadCore("linux-aarch64-pac.core")
+
+        values = {"data_mask": "0x007f00000000000", "code_mask": "0x007f00000000000"}
+
+        for regname, value in values.items():
+            self.expect("register read {}".format(regname),
+                        substrs=["{} = {}".format(regname, value)])
+
+        self.expect("register read --all")
+
     @skipIfLLVMTargetMissing("ARM")
     def test_arm_core(self):
         # check 32 bit ARM core file

diff  --git a/lldb/test/API/functionalities/postmortem/elf-core/linux-aarch64-pac.core b/lldb/test/API/functionalities/postmortem/elf-core/linux-aarch64-pac.core
new file mode 100644
index 0000000000000..3e89a36ec830e
Binary files /dev/null and b/lldb/test/API/functionalities/postmortem/elf-core/linux-aarch64-pac.core 
diff er


        


More information about the lldb-commits mailing list