[Lldb-commits] [lldb] e11df58 - Upstream debugserver arm64e support.

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Wed Dec 4 15:23:50 PST 2019


Author: Jason Molenda
Date: 2019-12-04T15:20:56-08:00
New Revision: e11df585800596df2052a475f6191673b8f1a5c1

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

LOG: Upstream debugserver arm64e support.

The changes are minor; primarily debugserver needs to go through
accessor functions/macros when changing pc/fp/sp/lr, and debugserver
needs to clear any existing pointer auth bits from values in two
cases.  debugserver can fetch the number of bits used for addressing
from a sysctl, and will include that in the qHostInfo reply.  Update
qHostInfo documentation to document it.

Added: 
    

Modified: 
    lldb/docs/lldb-gdb-remote.txt
    lldb/tools/debugserver/source/DNB.cpp
    lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
    lldb/tools/debugserver/source/RNBRemote.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt
index e3f11488df64..06cd09d77c41 100644
--- a/lldb/docs/lldb-gdb-remote.txt
+++ b/lldb/docs/lldb-gdb-remote.txt
@@ -790,6 +790,13 @@ distribution_id: optional. For linux, specifies distribution id (e.g. ubuntu, fe
 osmajor: optional, specifies the major version number of the OS (e.g. for macOS 10.12.2, it would be 10)
 osminor: optional, specifies the minor version number of the OS (e.g. for macOS 10.12.2, it would be 12)
 ospatch: optional, specifies the patch level number of the OS (e.g. for macOS 10.12.2, it would be 2)
+addressing_bits: optional, specifies how many bits in addresses are
+		 significant for addressing, base 10.  If bits 38..0
+		 in a 64-bit pointer are significant for addressing,
+		 then the value is 39.  This is needed on e.g. Aarch64
+		 v8.3 ABIs that use pointer authentication, so lldb
+		 knows which bits to clear/set to get the actual
+		 addresses.
 
 //----------------------------------------------------------------------
 // "qGDBServerVersion"

diff  --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index c9f2e34e2798..8d9c691f9d33 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -1722,6 +1722,8 @@ nub_bool_t DNBSetArchitecture(const char *arch) {
     else if (strstr(arch, "arm64_32") == arch || 
              strstr(arch, "aarch64_32") == arch)
       return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64_32);
+    else if (strstr(arch, "arm64e") == arch)
+      return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64);
     else if (strstr(arch, "arm64") == arch || strstr(arch, "armv8") == arch ||
              strstr(arch, "aarch64") == arch)
       return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64);

diff  --git a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
index 1bf14d97056c..e8c40910567c 100644
--- a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
@@ -26,6 +26,10 @@
 #include <inttypes.h>
 #include <sys/sysctl.h>
 
+#if __has_feature(ptrauth_calls)
+#include <ptrauth.h>
+#endif
+
 // Break only in privileged or user mode
 // (PAC bits in the DBGWVRn_EL1 watchpoint control register)
 #define S_USER ((uint32_t)(2u << 1))
@@ -93,7 +97,11 @@ uint32_t DNBArchMachARM64::GetCPUType() { return CPU_TYPE_ARM64; }
 uint64_t DNBArchMachARM64::GetPC(uint64_t failValue) {
   // Get program counter
   if (GetGPRState(false) == KERN_SUCCESS)
+#if defined(__LP64__)
+    return arm_thread_state64_get_pc(m_state.context.gpr);
+#else
     return m_state.context.gpr.__pc;
+#endif
   return failValue;
 }
 
@@ -101,7 +109,17 @@ kern_return_t DNBArchMachARM64::SetPC(uint64_t value) {
   // Get program counter
   kern_return_t err = GetGPRState(false);
   if (err == KERN_SUCCESS) {
+#if defined(__LP64__)
+#if __has_feature(ptrauth_calls)
+    // The incoming value could be garbage.  Strip it to avoid
+    // trapping when it gets resigned in the thread state.
+    value = (uint64_t) ptrauth_strip((void*) value, ptrauth_key_function_pointer);
+    value = (uint64_t) ptrauth_sign_unauthenticated((void*) value, ptrauth_key_function_pointer, 0);
+#endif
+    arm_thread_state64_set_pc_fptr (m_state.context.gpr, (void*) value);
+#else
     m_state.context.gpr.__pc = value;
+#endif
     err = SetGPRState();
   }
   return err == KERN_SUCCESS;
@@ -110,7 +128,11 @@ kern_return_t DNBArchMachARM64::SetPC(uint64_t value) {
 uint64_t DNBArchMachARM64::GetSP(uint64_t failValue) {
   // Get stack pointer
   if (GetGPRState(false) == KERN_SUCCESS)
+#if defined(__LP64__)
+    return arm_thread_state64_get_sp(m_state.context.gpr);
+#else
     return m_state.context.gpr.__sp;
+#endif
   return failValue;
 }
 
@@ -167,8 +189,15 @@ kern_return_t DNBArchMachARM64::GetGPRState(bool force) {
         x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[0], x[11],
         x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], x[20], x[21],
         x[22], x[23], x[24], x[25], x[26], x[27], x[28],
+#if defined(__LP64__)
+        (uint64_t) arm_thread_state64_get_fp (m_state.context.gpr),
+        (uint64_t) arm_thread_state64_get_lr (m_state.context.gpr),
+        (uint64_t) arm_thread_state64_get_sp (m_state.context.gpr),
+        (uint64_t) arm_thread_state64_get_pc (m_state.context.gpr),
+#else
         m_state.context.gpr.__fp, m_state.context.gpr.__lr,
         m_state.context.gpr.__sp, m_state.context.gpr.__pc,
+#endif
         m_state.context.gpr.__cpsr);
   }
   m_state.SetError(set, Read, kret);
@@ -564,12 +593,20 @@ kern_return_t DNBArchMachARM64::EnableHardwareSingleStep(bool enable) {
   if (enable) {
     DNBLogThreadedIf(LOG_STEP,
                      "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx",
+#if defined(__LP64__)
+                     __FUNCTION__, (uint64_t)arm_thread_state64_get_pc (m_state.context.gpr));
+#else
                      __FUNCTION__, (uint64_t)m_state.context.gpr.__pc);
+#endif
     m_state.dbg.__mdscr_el1 |= SS_ENABLE;
   } else {
     DNBLogThreadedIf(LOG_STEP,
                      "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx",
+#if defined(__LP64__)
+                     __FUNCTION__, (uint64_t)arm_thread_state64_get_pc (m_state.context.gpr));
+#else
                      __FUNCTION__, (uint64_t)m_state.context.gpr.__pc);
+#endif
     m_state.dbg.__mdscr_el1 &= ~(SS_ENABLE);
   }
 
@@ -1409,10 +1446,28 @@ const DNBRegisterInfo DNBArchMachARM64::g_gpr_registers[] = {
     DEFINE_GPR_IDX(26, x26, NULL, INVALID_NUB_REGNUM),
     DEFINE_GPR_IDX(27, x27, NULL, INVALID_NUB_REGNUM),
     DEFINE_GPR_IDX(28, x28, NULL, INVALID_NUB_REGNUM),
-    DEFINE_GPR_NAME(fp, "x29", GENERIC_REGNUM_FP),
-    DEFINE_GPR_NAME(lr, "x30", GENERIC_REGNUM_RA),
-    DEFINE_GPR_NAME(sp, "xsp", GENERIC_REGNUM_SP),
-    DEFINE_GPR_NAME(pc, NULL, GENERIC_REGNUM_PC),
+    // For the G/g packet we want to show where the offset into the regctx
+    // is for fp/lr/sp/pc, but we cannot directly access them on arm64e
+    // devices (and therefore can't offsetof() them)) - add the offset based
+    // on the last accessible register by hand for advertising the location
+    // in the regctx to lldb.  We'll go through the accessor functions when
+    // we read/write them here.
+    {
+       e_regSetGPR, gpr_fp, "fp", "x29", Uint, Hex, 8, GPR_OFFSET_IDX(28) + 8,
+       dwarf_fp, dwarf_fp, GENERIC_REGNUM_FP, debugserver_gpr_fp, NULL, NULL
+    },
+    {
+       e_regSetGPR, gpr_lr, "lr", "x30", Uint, Hex, 8, GPR_OFFSET_IDX(28) + 16,
+       dwarf_lr, dwarf_lr, GENERIC_REGNUM_RA, debugserver_gpr_lr, NULL, NULL
+    },
+    {
+       e_regSetGPR, gpr_sp, "sp", "xsp", Uint, Hex, 8, GPR_OFFSET_IDX(28) + 24,
+       dwarf_sp, dwarf_sp, GENERIC_REGNUM_SP, debugserver_gpr_sp, NULL, NULL
+    },
+    {
+       e_regSetGPR, gpr_pc, "pc", NULL, Uint, Hex, 8, GPR_OFFSET_IDX(28) + 32,
+       dwarf_pc, dwarf_pc, GENERIC_REGNUM_PC, debugserver_gpr_pc, NULL, NULL
+    },
 
     // in armv7 we specify that writing to the CPSR should invalidate r8-12, sp,
     // lr.
@@ -1769,7 +1824,20 @@ bool DNBArchMachARM64::GetRegisterValue(uint32_t set, uint32_t reg,
     switch (set) {
     case e_regSetGPR:
       if (reg <= gpr_pc) {
+#if defined(__LP64__)
+        if (reg == gpr_pc)
+          value->value.uint64 = arm_thread_state64_get_pc (m_state.context.gpr);
+        else if (reg == gpr_lr)
+          value->value.uint64 = arm_thread_state64_get_lr (m_state.context.gpr);
+        else if (reg == gpr_sp)
+          value->value.uint64 = arm_thread_state64_get_sp (m_state.context.gpr);
+        else if (reg == gpr_fp)
+          value->value.uint64 = arm_thread_state64_get_fp (m_state.context.gpr);
+        else
+        value->value.uint64 = m_state.context.gpr.__x[reg];
+#else
         value->value.uint64 = m_state.context.gpr.__x[reg];
+#endif
         return true;
       } else if (reg == gpr_cpsr) {
         value->value.uint32 = m_state.context.gpr.__cpsr;
@@ -1859,7 +1927,27 @@ bool DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg,
     switch (set) {
     case e_regSetGPR:
       if (reg <= gpr_pc) {
+#if defined(__LP64__)
+          uint64_t signed_value = value->value.uint64;
+#if __has_feature(ptrauth_calls)
+          // The incoming value could be garbage.  Strip it to avoid
+          // trapping when it gets resigned in the thread state.
+          signed_value = (uint64_t) ptrauth_strip((void*) signed_value, ptrauth_key_function_pointer);
+          signed_value = (uint64_t) ptrauth_sign_unauthenticated((void*) signed_value, ptrauth_key_function_pointer, 0);
+#endif
+        if (reg == gpr_pc) 
+         arm_thread_state64_set_pc_fptr (m_state.context.gpr, (void*) signed_value);
+        else if (reg == gpr_lr)
+          arm_thread_state64_set_lr_fptr (m_state.context.gpr, (void*) signed_value);
+        else if (reg == gpr_sp)
+          arm_thread_state64_set_sp (m_state.context.gpr, value->value.uint64);
+        else if (reg == gpr_fp)
+          arm_thread_state64_set_fp (m_state.context.gpr, value->value.uint64);
+        else
+          m_state.context.gpr.__x[reg] = value->value.uint64;
+#else
         m_state.context.gpr.__x[reg] = value->value.uint64;
+#endif
         success = true;
       } else if (reg == gpr_cpsr) {
         m_state.context.gpr.__cpsr = value->value.uint32;

diff  --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 61bdf0d8dac6..64e3bc49abc8 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -4643,6 +4643,24 @@ static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
   return g_host_cputype != 0;
 }
 
+static bool GetAddressingBits(uint32_t &addressing_bits) {
+  static uint32_t g_addressing_bits = 0;
+  static bool g_tried_addressing_bits_syscall = false;
+  if (g_tried_addressing_bits_syscall == false) {
+    size_t len = sizeof (uint32_t);
+    if (::sysctlbyname("machdep.virtual_address_size",
+          &g_addressing_bits, &len, NULL, 0) != 0) {
+      g_addressing_bits = 0;
+    }
+  }
+  g_tried_addressing_bits_syscall = true;
+  addressing_bits = g_addressing_bits;
+  if (addressing_bits > 0)
+    return true;
+  else
+    return false;
+}
+
 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
   std::ostringstream strm;
 
@@ -4655,6 +4673,11 @@ rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
   }
 
+  uint32_t addressing_bits = 0;
+  if (GetAddressingBits(addressing_bits)) {
+    strm << "addressing_bits:" << std::dec << addressing_bits << ';';
+  }
+
   // The OS in the triple should be "ios" or "macosx" which doesn't match our
   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
   // this for now.


        


More information about the lldb-commits mailing list