This revision was automatically updated to reflect the committed changes.
Closed by commit rG256c16e8f4e4: Change debugserver to clear PAC auth bits 
manually (authored by jasonmolenda).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136620

Files:
  lldb/tools/debugserver/source/DNB.cpp
  lldb/tools/debugserver/source/DNB.h
  lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
  lldb/tools/debugserver/source/RNBRemote.cpp

Index: lldb/tools/debugserver/source/RNBRemote.cpp
===================================================================
--- lldb/tools/debugserver/source/RNBRemote.cpp
+++ lldb/tools/debugserver/source/RNBRemote.cpp
@@ -4781,24 +4781,6 @@
   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;
 
@@ -4812,7 +4794,7 @@
   }
 
   uint32_t addressing_bits = 0;
-  if (GetAddressingBits(addressing_bits)) {
+  if (DNBGetAddressingBits(addressing_bits)) {
     strm << "addressing_bits:" << std::dec << addressing_bits << ';';
   }
 
Index: lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
===================================================================
--- lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
+++ lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp
@@ -94,11 +94,35 @@
 
 uint32_t DNBArchMachARM64::GetCPUType() { return CPU_TYPE_ARM64; }
 
+static uint64_t clear_pac_bits(uint64_t value) {
+  uint32_t addressing_bits = 0;
+  if (!DNBGetAddressingBits(addressing_bits))
+    return value;
+
+    // On arm64_32, no ptrauth bits to clear
+#if !defined(__LP64__)
+  return value;
+#endif
+
+  uint64_t mask = ((1ULL << addressing_bits) - 1);
+
+  // Normally PAC bit clearing needs to check b55 and either set the
+  // non-addressing bits, or clear them.  But the register values we
+  // get from thread_get_state on an arm64e process don't follow this
+  // convention?, at least when there's been a PAC auth failure in
+  // the inferior.
+  // Userland processes are always in low memory, so this
+  // hardcoding b55 == 0 PAC stripping behavior here.
+
+  return value & mask; // high bits cleared to 0
+}
+
 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);
+#if __has_feature(ptrauth_calls) && defined(__LP64__)
+    return clear_pac_bits(
+        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));
 #else
     return m_state.context.gpr.__pc;
 #endif
@@ -128,8 +152,9 @@
 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);
+#if __has_feature(ptrauth_calls) && defined(__LP64__)
+    return clear_pac_bits(
+        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_sp));
 #else
     return m_state.context.gpr.__sp;
 #endif
@@ -150,16 +175,20 @@
   if (DNBLogEnabledForAny(LOG_THREAD)) {
     uint64_t *x = &m_state.context.gpr.__x[0];
 
-#if defined(__LP64__)
-        uint64_t log_fp = arm_thread_state64_get_fp(m_state.context.gpr);
-        uint64_t log_lr = arm_thread_state64_get_lr(m_state.context.gpr);
-        uint64_t log_sp = arm_thread_state64_get_sp(m_state.context.gpr);
-        uint64_t log_pc = arm_thread_state64_get_pc(m_state.context.gpr);
+#if __has_feature(ptrauth_calls) && defined(__LP64__)
+    uint64_t log_fp = clear_pac_bits(
+        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_fp));
+    uint64_t log_lr = clear_pac_bits(
+        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_lr));
+    uint64_t log_sp = clear_pac_bits(
+        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_sp));
+    uint64_t log_pc = clear_pac_bits(
+        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));
 #else
-        uint64_t log_fp = m_state.context.gpr.__fp;
-        uint64_t log_lr = m_state.context.gpr.__lr;
-        uint64_t log_sp = m_state.context.gpr.__sp;
-        uint64_t log_pc = m_state.context.gpr.__pc;
+    uint64_t log_fp = m_state.context.gpr.__fp;
+    uint64_t log_lr = m_state.context.gpr.__lr;
+    uint64_t log_sp = m_state.context.gpr.__sp;
+    uint64_t log_pc = m_state.context.gpr.__pc;
 #endif
     DNBLogThreaded(
         "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs"
@@ -617,8 +646,9 @@
     return err.Status();
   }
 
-#if defined(__LP64__)
-  uint64_t pc = arm_thread_state64_get_pc (m_state.context.gpr);
+#if __has_feature(ptrauth_calls) && defined(__LP64__)
+  uint64_t pc = clear_pac_bits(
+      reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));
 #else
   uint64_t pc = m_state.context.gpr.__pc;
 #endif
@@ -1992,20 +2022,10 @@
     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);
+        if (reg == gpr_pc || reg == gpr_lr || reg == gpr_sp || reg == gpr_fp)
+          value->value.uint64 = clear_pac_bits(m_state.context.gpr.__x[reg]);
         else
-        value->value.uint64 = m_state.context.gpr.__x[reg];
-#else
-        value->value.uint64 = m_state.context.gpr.__x[reg];
-#endif
+          value->value.uint64 = m_state.context.gpr.__x[reg];
         return true;
       } else if (reg == gpr_cpsr) {
         value->value.uint32 = m_state.context.gpr.__cpsr;
Index: lldb/tools/debugserver/source/DNB.h
===================================================================
--- lldb/tools/debugserver/source/DNB.h
+++ lldb/tools/debugserver/source/DNB.h
@@ -245,4 +245,6 @@
 /// \return true if debugserver is running in translation
 /// (is an x86_64 process on arm64)
 bool DNBDebugserverIsTranslated();
+
+bool DNBGetAddressingBits(uint32_t &addressing_bits);
 #endif
Index: lldb/tools/debugserver/source/DNB.cpp
===================================================================
--- lldb/tools/debugserver/source/DNB.cpp
+++ lldb/tools/debugserver/source/DNB.cpp
@@ -1824,3 +1824,19 @@
     return false;
   return ret == 1;
 }
+
+bool DNBGetAddressingBits(uint32_t &addressing_bits) {
+  static uint32_t g_addressing_bits = 0;
+  static std::once_flag g_once_flag;
+  std::call_once(g_once_flag, [&](){
+    size_t len = sizeof(uint32_t);
+    if (::sysctlbyname("machdep.virtual_address_size", &g_addressing_bits, &len,
+                       NULL, 0) != 0) {
+      g_addressing_bits = 0;
+    }
+  }
+
+  addressing_bits = g_addressing_bits;
+
+  return addressing_bits > 0;
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to