Author: Jason Molenda
Date: 2023-06-14T13:49:26-07:00
New Revision: 0ce7037b5edd0f1937c9d9572ab12528d26091ed

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

LOG: Clear non-addressable bits from pc/fp/sp in unwinds

Some Darwin corefiles can have the pc/fp/sp/lr in the
live register context signed with pointer authentication;
this patch changes RegisterContextUnwind to strip those
bits off of those values as we try to walk the stack.

Differential Revision: https://reviews.llvm.org/D152861
rdar://109185291

Added: 
    

Modified: 
    lldb/source/Target/RegisterContextUnwind.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Target/RegisterContextUnwind.cpp 
b/lldb/source/Target/RegisterContextUnwind.cpp
index bf31ebbd858ae..242c7d3f6b945 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -137,9 +137,8 @@ void RegisterContextUnwind::InitializeZerothFrame() {
   // (which would be a no-op in frame 0 where we get it from the register set,
   // but still a good idea to make the call here for other ABIs that may
   // exist.)
-  ABI *abi = process->GetABI().get();
-  if (abi)
-    current_pc = abi->FixCodeAddress(current_pc);
+  if (ABISP abi_sp = process->GetABI())
+    current_pc = abi_sp->FixCodeAddress(current_pc);
 
   UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
       m_thread, this, m_behaves_like_zeroth_frame);
@@ -355,17 +354,23 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
 
   // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
   // this will strip bit zero in case we read a PC from memory or from the LR.
-  ABI *abi = process->GetABI().get();
-  if (abi)
-    pc = abi->FixCodeAddress(pc);
+  ABISP abi_sp = process->GetABI();
+  if (abi_sp)
+    pc = abi_sp->FixCodeAddress(pc);
 
   if (log) {
     UnwindLogMsg("pc = 0x%" PRIx64, pc);
     addr_t reg_val;
-    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
+    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) {
+      if (abi_sp)
+        reg_val = abi_sp->FixDataAddress(reg_val);
       UnwindLogMsg("fp = 0x%" PRIx64, reg_val);
-    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
+    }
+    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) {
+      if (abi_sp)
+        reg_val = abi_sp->FixDataAddress(reg_val);
       UnwindLogMsg("sp = 0x%" PRIx64, reg_val);
+    }
   }
 
   // A pc of 0x0 means it's the end of the stack crawl unless we're above a 
trap
@@ -424,11 +429,11 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
       }
     }
 
-    if (abi) {
+    if (abi_sp) {
       m_fast_unwind_plan_sp.reset();
       m_full_unwind_plan_sp =
           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
-      abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
+      abi_sp->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
       if (m_frame_type != eSkipFrame) // don't override eSkipFrame
       {
         m_frame_type = eNormalFrame;
@@ -1751,8 +1756,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
       if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
         old_caller_pc_value = reg_value.GetAsUInt64();
         if (ProcessSP process_sp = m_thread.GetProcess()) {
-          if (ABISP abi = process_sp->GetABI())
-            old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value);
+          if (ABISP abi_sp = process_sp->GetABI())
+            old_caller_pc_value = abi_sp->FixCodeAddress(old_caller_pc_value);
         }
       }
     }
@@ -1811,8 +1816,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
                                                   reg_value)) {
           new_caller_pc_value = reg_value.GetAsUInt64();
           if (ProcessSP process_sp = m_thread.GetProcess()) {
-            if (ABISP abi = process_sp->GetABI())
-              new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value);
+            if (ABISP abi_sp = process_sp->GetABI())
+              new_caller_pc_value = 
abi_sp->FixCodeAddress(new_caller_pc_value);
           }
         }
       }
@@ -1953,6 +1958,7 @@ bool RegisterContextUnwind::ReadFrameAddress(
 
   address = LLDB_INVALID_ADDRESS;
   addr_t cfa_reg_contents;
+  ABISP abi_sp = m_thread.GetProcess()->GetABI();
 
   switch (fa.GetValueType()) {
   case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
@@ -1963,11 +1969,13 @@ bool RegisterContextUnwind::ReadFrameAddress(
           GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
       RegisterValue reg_value;
       if (reg_info) {
+        if (abi_sp)
+          cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
         Status error = ReadRegisterValueFromMemory(
             reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
         if (error.Success()) {
           address = reg_value.GetAsUInt64();
-          if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+          if (abi_sp)
             address = abi_sp->FixCodeAddress(address);
           UnwindLogMsg(
               "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
@@ -1989,6 +1997,8 @@ bool RegisterContextUnwind::ReadFrameAddress(
     RegisterNumber cfa_reg(m_thread, row_register_kind,
                            fa.GetRegisterNumber());
     if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
+      if (abi_sp)
+        cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
       if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
           cfa_reg_contents == 1) {
         UnwindLogMsg(
@@ -2076,6 +2086,8 @@ lldb::addr_t 
RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
     return LLDB_INVALID_ADDRESS;
   if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
     return LLDB_INVALID_ADDRESS;
+  if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+    hint = abi_sp->FixCodeAddress(hint);
 
   hint += plan_offset;
 
@@ -2133,28 +2145,38 @@ bool 
RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
     return false;
   }
 
+  uint32_t generic_regnum = LLDB_INVALID_REGNUM;
+  if (register_kind == eRegisterKindGeneric)
+    generic_regnum = regnum;
+  else
+    m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
+        register_kind, regnum, eRegisterKindGeneric, generic_regnum);
+  ABISP abi_sp = m_thread.GetProcess()->GetABI();
+
   RegisterValue reg_value;
   // if this is frame 0 (currently executing frame), get the requested reg
   // contents from the actual thread registers
   if (IsFrameZero()) {
     if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) {
       value = reg_value.GetAsUInt64();
+      if (abi_sp && generic_regnum != LLDB_INVALID_REGNUM) {
+        if (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
+            generic_regnum == LLDB_REGNUM_GENERIC_RA)
+          value = abi_sp->FixCodeAddress(value);
+        if (generic_regnum == LLDB_REGNUM_GENERIC_SP ||
+            generic_regnum == LLDB_REGNUM_GENERIC_FP)
+          value = abi_sp->FixDataAddress(value);
+      }
       return true;
     }
     return false;
   }
 
   bool pc_register = false;
-  uint32_t generic_regnum;
-  if (register_kind == eRegisterKindGeneric &&
-      (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) {
+  if (generic_regnum != LLDB_INVALID_REGNUM &&
+      (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
+       generic_regnum == LLDB_REGNUM_GENERIC_RA))
     pc_register = true;
-  } else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
-                 register_kind, regnum, eRegisterKindGeneric, generic_regnum) 
&&
-             (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
-              generic_regnum == LLDB_REGNUM_GENERIC_RA)) {
-    pc_register = true;
-  }
 
   lldb_private::UnwindLLDB::RegisterLocation regloc;
   if (!m_parent_unwind.SearchForSavedLocationForRegister(
@@ -2164,9 +2186,8 @@ bool 
RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
   if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
     value = reg_value.GetAsUInt64();
     if (pc_register) {
-      if (ProcessSP process_sp = m_thread.GetProcess()) {
-        if (ABISP abi = process_sp->GetABI())
-          value = abi->FixCodeAddress(value);
+      if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) {
+        value = abi_sp->FixCodeAddress(value);
       }
     }
     return true;
@@ -2215,10 +2236,8 @@ bool RegisterContextUnwind::ReadRegister(const 
RegisterInfo *reg_info,
     if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
       addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
       if (reg_value != LLDB_INVALID_ADDRESS) {
-        if(ProcessSP process_sp = m_thread.GetProcess()) {
-          if (ABISP abi = process_sp->GetABI())
-            value = abi->FixCodeAddress(reg_value);
-        }
+        if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+          value = abi_sp->FixCodeAddress(reg_value);
       }
     }
   }
@@ -2300,9 +2319,8 @@ bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) {
             ProcessSP process_sp (m_thread.GetProcess());
             if (process_sp)
             {
-                ABI *abi = process_sp->GetABI().get();
-                if (abi)
-                    start_pc = abi->FixCodeAddress(start_pc);
+              if (ABISP abi_sp = process_sp->GetABI())
+                start_pc = abi_sp->FixCodeAddress(start_pc);
             }
         }
         return read_successfully;
@@ -2330,13 +2348,8 @@ bool RegisterContextUnwind::ReadPC(addr_t &pc) {
     // through a NULL pointer -- we want to be able to unwind past that frame
     // to help find the bug.
 
-    ProcessSP process_sp (m_thread.GetProcess());
-    if (process_sp)
-    {
-        ABI *abi = process_sp->GetABI().get();
-        if (abi)
-            pc = abi->FixCodeAddress(pc);
-    }
+    if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+      pc = abi_sp->FixCodeAddress(pc);
 
     return !(m_all_registers_available == false &&
              above_trap_handler == false && (pc == 0 || pc == 1));


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to