zequanwu created this revision.
zequanwu added reviewers: labath, clayborg, jasonmolenda.
Herald added subscribers: atanasyan, jrtc27, kbarton, nemanjai, sdardis.
Herald added a project: All.
zequanwu requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This adds stack scanning as fallback unwind plan to find a value that looks like
return address. If the return address is not valid, continue scanning from next
locatoin on stack when trying fallback unwind and the active row is `raSearch`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124198

Files:
  lldb/include/lldb/Symbol/UnwindPlan.h
  lldb/include/lldb/Target/ABI.h
  lldb/include/lldb/Target/RegisterContextUnwind.h
  lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
  lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
  lldb/source/Plugins/ABI/ARC/ABISysV_arc.h
  lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h
  lldb/source/Plugins/ABI/ARM/ABISysV_arm.h
  lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.h
  lldb/source/Plugins/ABI/Mips/ABISysV_mips.h
  lldb/source/Plugins/ABI/Mips/ABISysV_mips64.h
  lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.h
  lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h
  lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.h
  lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h
  lldb/source/Plugins/ABI/X86/ABISysV_i386.h
  lldb/source/Plugins/ABI/X86/ABISysV_x86_64.h
  lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
  lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
  lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/source/Symbol/UnwindPlan.cpp
  lldb/source/Target/RegisterContextUnwind.cpp
  lldb/test/Shell/SymbolFile/Breakpad/unwind-via-raSearch.test

Index: lldb/test/Shell/SymbolFile/Breakpad/unwind-via-raSearch.test
===================================================================
--- lldb/test/Shell/SymbolFile/Breakpad/unwind-via-raSearch.test
+++ lldb/test/Shell/SymbolFile/Breakpad/unwind-via-raSearch.test
@@ -16,13 +16,13 @@
 # CHECK: This UnwindPlan is valid at all instruction locations: no.
 # CHECK: This UnwindPlan is for a trap handler function: no.
 # CHECK: Address range of this UnwindPlan: [unwind-via-stack-win.exe..module_image + 4112-0x0000107d)
-# CHECK: row[0]:    0: CFA=RaSearch@SP+0 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus  eip=DW_OP_pick 0x0, DW_OP_deref
+# CHECK: row[0]:    0: CFA=RaSearch@SP+0, offset=+0 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus  eip=DW_OP_pick 0x0, DW_OP_deref
 
 image show-unwind -n nonzero_frame_size
 # CHECK-LABEL: image show-unwind -n nonzero_frame_size
 # CHECK: UNWIND PLANS for unwind-via-stack-win.exe`nonzero_frame_size
 # CHECK: Symbol file UnwindPlan:
-# CHECK: row[0]:    0: CFA=RaSearch@SP+12 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus  eip=DW_OP_pick 0x0, DW_OP_deref
+# CHECK: row[0]:    0: CFA=RaSearch@SP+12, offset=+0 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus  eip=DW_OP_pick 0x0, DW_OP_deref
 
 # Then, some invalid rules.
 image show-unwind -n complex_rasearch
Index: lldb/source/Target/RegisterContextUnwind.cpp
===================================================================
--- lldb/source/Target/RegisterContextUnwind.cpp
+++ lldb/source/Target/RegisterContextUnwind.cpp
@@ -285,7 +285,18 @@
         cfa_status = true;
     }
     if (!cfa_status) {
-      UnwindLogMsg("could not read CFA value for first frame.");
+      UnwindLogMsg("could not read CFA value for first frame. Trying stack "
+                   "walking unwind plan.");
+      if (abi) {
+        UnwindPlanSP stack_walk_unwind_plan =
+            std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
+        if (abi->CreateStackWalkingUnwindPlan(*stack_walk_unwind_plan)) {
+          m_fallback_unwind_plan_sp = stack_walk_unwind_plan;
+          cfa_status = TryFallbackUnwindPlan();
+        }
+      }
+    }
+    if (!cfa_status) {
       m_frame_type = eNotAValidFrame;
       return;
     }
@@ -384,7 +395,7 @@
   // symbol/function information - just stick in some reasonable defaults and
   // hope we can unwind past this frame.  If we're above a trap handler,
   // we may be at a bogus address because we jumped through a bogus function
-  // pointer and trapped, so don't force the arch default unwind plan in that 
+  // pointer and trapped, so don't force the arch default unwind plan in that
   // case.
   ModuleSP pc_module_sp(m_current_pc.GetModule());
   if ((!m_current_pc.IsValid() || !pc_module_sp) &&
@@ -660,9 +671,20 @@
   }
 
   if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
-    UnwindLogMsg("failed to get cfa");
-    m_frame_type = eNotAValidFrame;
-    return;
+    UnwindLogMsg("failed to get cfa. Trying stack walking unwind plan.");
+    bool cfa_status = false;
+    if (abi) {
+      UnwindPlanSP stack_walk_unwind_plan =
+          std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
+      if (abi->CreateStackWalkingUnwindPlan(*stack_walk_unwind_plan)) {
+        m_fallback_unwind_plan_sp = stack_walk_unwind_plan;
+        cfa_status = TryFallbackUnwindPlan();
+      }
+    }
+    if (!cfa_status) {
+      m_frame_type = eNotAValidFrame;
+      return;
+    }
   }
 
   ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
@@ -1287,7 +1309,7 @@
     // arch default unwind plan is used as the Fast Unwind Plan, we
     // need to recognize this & switch over to the Full Unwind Plan
     // to see what unwind rule that (more knoweldgeable, probably)
-    // UnwindPlan has.  If the full UnwindPlan says the register 
+    // UnwindPlan has.  If the full UnwindPlan says the register
     // location is Undefined, then it really is.
     if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
                                     unwindplan_regloc) &&
@@ -1335,14 +1357,14 @@
           m_full_unwind_plan_sp->GetReturnAddressRegister() !=
               LLDB_INVALID_REGNUM) {
         // If this is a trap handler frame, we should have access to
-        // the complete register context when the interrupt/async 
+        // the complete register context when the interrupt/async
         // signal was received, we should fetch the actual saved $pc
         // value instead of the Return Address register.
         // If $pc is not available, fall back to the RA reg.
         UnwindPlan::Row::RegisterLocation scratch;
         if (m_frame_type == eTrapHandlerFrame &&
-            active_row->GetRegisterInfo 
-              (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
+            active_row->GetRegisterInfo(
+                pc_regnum.GetAsKind(unwindplan_registerkind), scratch)) {
           UnwindLogMsg("Providing pc register instead of rewriting to "
                        "RA reg because this is a trap handler and there is "
                        "a location for the saved pc register value.");
@@ -1710,12 +1732,6 @@
   if (m_full_unwind_plan_sp.get() == nullptr)
     return false;
 
-  if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() ||
-      m_full_unwind_plan_sp->GetSourceName() ==
-          m_fallback_unwind_plan_sp->GetSourceName()) {
-    return false;
-  }
-
   // If a compiler generated unwind plan failed, trying the arch default
   // unwindplan isn't going to do any better.
   if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
@@ -1771,71 +1787,86 @@
 
   UnwindPlan::RowSP active_row =
       m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
-
+  UnwindPlan::Row::FAValue &fa = active_row->GetCFAValue();
   if (active_row &&
-      active_row->GetCFAValue().GetValueType() !=
-          UnwindPlan::Row::FAValue::unspecified) {
+      fa.GetValueType() != UnwindPlan::Row::FAValue::unspecified) {
     addr_t new_cfa;
-    if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
-                            active_row->GetCFAValue(), new_cfa) ||
-        new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
-      UnwindLogMsg("failed to get cfa with fallback unwindplan");
-      m_fallback_unwind_plan_sp.reset();
-      m_full_unwind_plan_sp = original_full_unwind_plan_sp;
-      return false;
+    // If itn's not first attempt and ra search, update ra search offset before
+    // searching for cfa. Previous attempts may fail due to bad pc.
+    if (fa.IsRaSearch() && old_cfa != LLDB_INVALID_ADDRESS) {
+      addr_t sp;
+      if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp)) {
+        UnwindLogMsg("failed to get cfa with fallback unwindplan");
+        m_fallback_unwind_plan_sp.reset();
+        m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+        return false;
+      }
+      Process &process = *m_thread.GetProcess();
+      // It's the next stack offset location so that sp + next_search_offset ==
+      // old_cfa + process.GetAddressByteSize().
+      addr_t next_search_offset =
+          old_cfa - sp - fa.GetOffset() + process.GetAddressByteSize();
+      fa.SetRaSearch(next_search_offset, fa.GetOffset());
     }
-    m_cfa = new_cfa;
-
-    ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
-                     active_row->GetAFAValue(), m_afa);
+    if (ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), fa,
+                         new_cfa) ||
+        new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
 
-    if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
-                                 regloc) ==
-        UnwindLLDB::RegisterSearchResult::eRegisterFound) {
-      const RegisterInfo *reg_info =
-          GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB));
-      if (reg_info) {
-        RegisterValue reg_value;
-        if (ReadRegisterValueFromRegisterLocation(regloc, reg_info,
-                                                  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);
+      m_cfa = new_cfa;
+
+      ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+                       active_row->GetAFAValue(), m_afa);
+
+      if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
+                                   regloc) ==
+          UnwindLLDB::RegisterSearchResult::eRegisterFound) {
+        const RegisterInfo *reg_info =
+            GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB));
+        if (reg_info) {
+          RegisterValue reg_value;
+          if (ReadRegisterValueFromRegisterLocation(regloc, reg_info,
+                                                    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 (new_caller_pc_value == LLDB_INVALID_ADDRESS) {
-      UnwindLogMsg("failed to get a pc value for the caller frame with the "
-                   "fallback unwind plan");
-      m_fallback_unwind_plan_sp.reset();
-      m_full_unwind_plan_sp = original_full_unwind_plan_sp;
-      m_cfa = old_cfa;
-      m_afa = old_afa;
-      return false;
-    }
+      if (new_caller_pc_value == LLDB_INVALID_ADDRESS) {
+        UnwindLogMsg("failed to get a pc value for the caller frame with the "
+                     "fallback unwind plan");
+        m_fallback_unwind_plan_sp.reset();
+        m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+        m_cfa = old_cfa;
+        m_afa = old_afa;
+        return false;
+      }
+
+      if (old_caller_pc_value == new_caller_pc_value && m_cfa == old_cfa &&
+          m_afa == old_afa) {
+        UnwindLogMsg("fallback unwind plan got the same values for this frame "
+                     "CFA and caller frame pc, not using");
+        m_fallback_unwind_plan_sp.reset();
+        m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+        return false;
+      }
+
+      UnwindLogMsg(
+          "trying to unwind from this function with the UnwindPlan '%s' "
+          "because UnwindPlan '%s' failed.",
+          m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
+          original_full_unwind_plan_sp->GetSourceName().GetCString());
 
-    if (old_caller_pc_value == new_caller_pc_value &&
-        m_cfa == old_cfa &&
-        m_afa == old_afa) {
-      UnwindLogMsg("fallback unwind plan got the same values for this frame "
-                   "CFA and caller frame pc, not using");
+      PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
+    } else {
+      UnwindLogMsg("failed to get cfa with fallback unwindplan");
       m_fallback_unwind_plan_sp.reset();
       m_full_unwind_plan_sp = original_full_unwind_plan_sp;
       return false;
     }
-
-    UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' "
-                 "because UnwindPlan '%s' failed.",
-                 m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
-                 original_full_unwind_plan_sp->GetSourceName().GetCString());
-
-    // We've copied the fallback unwind plan into the full - now clear the
-    // fallback.
-    m_fallback_unwind_plan_sp.reset();
-    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
   }
 
   return true;
@@ -2025,16 +2056,21 @@
   }
   case UnwindPlan::Row::FAValue::isRaSearch: {
     Process &process = *m_thread.GetProcess();
-    lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset());
-    if (return_address_hint == LLDB_INVALID_ADDRESS)
+    addr_t sp;
+    if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp))
       return false;
+    addr_t return_address_hint = sp + fa.GetRaSearchOffset();
+    if (fa.IsFirstRaSearch())
+      return_address_hint += GetParameterStackSize();
     const unsigned max_iterations = 256;
     for (unsigned i = 0; i < max_iterations; ++i) {
       Status st;
-      lldb::addr_t candidate_addr =
+      addr_t candidate_addr =
           return_address_hint + i * process.GetAddressByteSize();
-      lldb::addr_t candidate =
-          process.ReadPointerFromMemory(candidate_addr, st);
+      if (!process.GetABI()->CallFrameAddressIsValid(candidate_addr +
+                                                     fa.GetOffset()))
+        continue;
+      addr_t candidate = process.ReadPointerFromMemory(candidate_addr, st);
       if (st.Fail()) {
         UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr,
                      st.AsCString());
@@ -2044,7 +2080,7 @@
       uint32_t permissions;
       if (process.GetLoadAddressPermissions(candidate, permissions) &&
           permissions & lldb::ePermissionsExecutable) {
-        address = candidate_addr;
+        address = candidate_addr + fa.GetOffset();
         UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address);
         return true;
       }
@@ -2058,29 +2094,21 @@
   return false;
 }
 
-lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
-  addr_t hint;
-  if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint))
-    return LLDB_INVALID_ADDRESS;
-  if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
-    return LLDB_INVALID_ADDRESS;
-
-  hint += plan_offset;
-
+addr_t RegisterContextUnwind::GetParameterStackSize() {
   if (auto next = GetNextFrame()) {
     if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol)
-      return LLDB_INVALID_ADDRESS;
+      return 0;
     if (auto expected_size =
             next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize(
                 *next->m_sym_ctx.symbol))
-      hint += *expected_size;
+      return *expected_size;
     else {
       UnwindLogMsgVerbose("Could not retrieve parameter size: %s",
                           llvm::toString(expected_size.takeError()).c_str());
-      return LLDB_INVALID_ADDRESS;
+      return 0;
     }
   }
-  return hint;
+  return 0;
 }
 
 // Retrieve a general purpose register value for THIS frame, as saved by the
Index: lldb/source/Symbol/UnwindPlan.cpp
===================================================================
--- lldb/source/Symbol/UnwindPlan.cpp
+++ lldb/source/Symbol/UnwindPlan.cpp
@@ -169,8 +169,11 @@
   if (m_type == rhs.m_type) {
     switch (m_type) {
     case unspecified:
+      return true;
     case isRaSearch:
-      return m_value.ra_search_offset == rhs.m_value.ra_search_offset;
+      return m_value.ra_search.search_offset ==
+                 rhs.m_value.ra_search.search_offset &&
+             m_value.ra_search.cfa_offset == rhs.m_value.ra_search.cfa_offset;
 
     case isRegisterPlusOffset:
       return m_value.reg.offset == rhs.m_value.reg.offset;
@@ -209,7 +212,7 @@
     s.PutCString("unspecified");
     break;
   case isRaSearch:
-    s.Printf("RaSearch@SP%+d", m_value.ra_search_offset);
+    s.Printf("RaSearch@SP%+d, offset=%+d", GetRaSearchOffset(), GetOffset());
     break;
   }
 }
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -1255,7 +1255,7 @@
   auto begin = scope.begin();
   auto end = scope.end();
   std::vector<clang::ParmVarDecl *> params;
-  while (begin != end && param_count > 0) {
+  for (uint32_t i = 0; i < param_count && begin != end;) {
     uint32_t record_offset = begin.offset();
     CVSymbol sym = *begin++;
 
@@ -1307,10 +1307,10 @@
 
     m_uid_to_decl[toOpaqueUid(param_uid)] = param;
     params.push_back(param);
-    --param_count;
+    ++i;
   }
 
-  if (!params.empty())
+  if (!params.empty() && params.size() == param_count)
     m_clang.SetFunctionParameters(&function_decl, params);
 }
 
Index: lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -740,8 +740,8 @@
   // clang will use T1, if it needs to realign the stack.
   auto *symbol = llvm::dyn_cast<postfix::SymbolNode>(it->second);
   if (symbol && symbol->GetName() == ".raSearch") {
-    row_sp->GetCFAValue().SetRaSearch(record->LocalSize +
-                                      record->SavedRegisterSize);
+    row_sp->GetCFAValue().SetRaSearch(
+        record->LocalSize + record->SavedRegisterSize, 0);
   } else {
     if (!postfix::ResolveSymbols(it->second, symbol_resolver)) {
       LLDB_LOG(log, "Resolving symbols in `{0}` failed.",
Index: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
+++ lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
@@ -33,6 +33,9 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
+++ lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
@@ -731,6 +731,27 @@
   return return_valobj_sp;
 }
 
+bool ABIWindows_x86_64::CreateStackWalkingUnwindPlan(UnwindPlan &unwind_plan) {
+  unwind_plan.Clear();
+  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
+
+  uint32_t sp_reg_num = dwarf_rsp;
+  uint32_t pc_reg_num = dwarf_rip;
+
+  UnwindPlan::RowSP row(new UnwindPlan::Row);
+  row->GetCFAValue().SetRaSearch(0, 8);
+  row->SetUnspecifiedRegistersAreUndefined(true);
+
+  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, true);
+  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+  unwind_plan.AppendRow(row);
+  unwind_plan.SetSourceName("x86_64 stack-walking unwind plan");
+  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
+  return true;
+}
+
 // This defines the CFA as rsp+8
 // the saved pc is at CFA-8 (i.e. rsp+0)
 // The saved rsp is CFA+0
Index: lldb/source/Plugins/ABI/X86/ABISysV_x86_64.h
===================================================================
--- lldb/source/Plugins/ABI/X86/ABISysV_x86_64.h
+++ lldb/source/Plugins/ABI/X86/ABISysV_x86_64.h
@@ -33,6 +33,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/X86/ABISysV_i386.h
===================================================================
--- lldb/source/Plugins/ABI/X86/ABISysV_i386.h
+++ lldb/source/Plugins/ABI/X86/ABISysV_i386.h
@@ -36,6 +36,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h
+++ lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h
@@ -30,6 +30,11 @@
   SetReturnValueObject(lldb::StackFrameSP &frame_sp,
                        lldb::ValueObjectSP &new_value) override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.h
===================================================================
--- lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.h
+++ lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.h
@@ -34,6 +34,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h
===================================================================
--- lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h
+++ lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h
@@ -34,6 +34,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.h
===================================================================
--- lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.h
+++ lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.h
@@ -34,6 +34,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/Mips/ABISysV_mips64.h
===================================================================
--- lldb/source/Plugins/ABI/Mips/ABISysV_mips64.h
+++ lldb/source/Plugins/ABI/Mips/ABISysV_mips64.h
@@ -34,6 +34,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/Mips/ABISysV_mips.h
===================================================================
--- lldb/source/Plugins/ABI/Mips/ABISysV_mips.h
+++ lldb/source/Plugins/ABI/Mips/ABISysV_mips.h
@@ -34,6 +34,11 @@
   GetReturnValueObjectImpl(lldb_private::Thread &thread,
                            lldb_private::CompilerType &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.h
===================================================================
--- lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.h
+++ lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.h
@@ -46,6 +46,11 @@
   lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread,
                                                llvm::Type &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/ARM/ABISysV_arm.h
===================================================================
--- lldb/source/Plugins/ABI/ARM/ABISysV_arm.h
+++ lldb/source/Plugins/ABI/ARM/ABISysV_arm.h
@@ -29,6 +29,11 @@
   SetReturnValueObject(lldb::StackFrameSP &frame_sp,
                        lldb::ValueObjectSP &new_value) override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h
===================================================================
--- lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h
+++ lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h
@@ -29,6 +29,11 @@
   SetReturnValueObject(lldb::StackFrameSP &frame_sp,
                        lldb::ValueObjectSP &new_value) override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/ARC/ABISysV_arc.h
===================================================================
--- lldb/source/Plugins/ABI/ARC/ABISysV_arc.h
+++ lldb/source/Plugins/ABI/ARC/ABISysV_arc.h
@@ -49,6 +49,11 @@
   lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread,
                                                llvm::Type &type) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
===================================================================
--- lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
+++ lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
@@ -30,6 +30,11 @@
   SetReturnValueObject(lldb::StackFrameSP &frame_sp,
                        lldb::ValueObjectSP &new_value) override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
===================================================================
--- lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
+++ lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
@@ -27,6 +27,11 @@
   bool GetArgumentValues(lldb_private::Thread &thread,
                          lldb_private::ValueList &values) const override;
 
+  bool
+  CreateStackWalkingUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override {
+    return false;
+  }
+
   bool
   CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
 
Index: lldb/include/lldb/Target/RegisterContextUnwind.h
===================================================================
--- lldb/include/lldb/Target/RegisterContextUnwind.h
+++ lldb/include/lldb/Target/RegisterContextUnwind.h
@@ -206,7 +206,7 @@
   bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp,
                                      int &valid_pc_offset);
 
-  lldb::addr_t GetReturnAddressHint(int32_t plan_offset);
+  lldb::addr_t GetParameterStackSize();
 
   lldb_private::Thread &m_thread;
 
Index: lldb/include/lldb/Target/ABI.h
===================================================================
--- lldb/include/lldb/Target/ABI.h
+++ lldb/include/lldb/Target/ABI.h
@@ -96,6 +96,8 @@
   lldb::ProcessSP GetProcessSP() const { return m_process_wp.lock(); }
 
 public:
+  virtual bool CreateStackWalkingUnwindPlan(UnwindPlan &unwind_plan) = 0;
+
   virtual bool CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) = 0;
 
   virtual bool CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) = 0;
Index: lldb/include/lldb/Symbol/UnwindPlan.h
===================================================================
--- lldb/include/lldb/Symbol/UnwindPlan.h
+++ lldb/include/lldb/Symbol/UnwindPlan.h
@@ -215,9 +215,16 @@
 
       bool IsUnspecified() const { return m_type == unspecified; }
 
-      void SetRaSearch(int32_t offset) {
+      bool IsRaSearch() const { return m_type == isRaSearch; }
+
+      void SetRaSearch(int32_t search_offset, int32_t cfa_offset) {
+        m_value.ra_search.search_offset = search_offset;
+        m_value.ra_search.cfa_offset = cfa_offset;
+        if (m_type == isRaSearch) {
+          // Not the first search.
+          m_value.ra_search.search_offset |= 1;
+        }
         m_type = isRaSearch;
-        m_value.ra_search_offset = offset;
       }
 
       bool IsRegisterPlusOffset() const {
@@ -255,12 +262,20 @@
 
       ValueType GetValueType() const { return m_type; }
 
+      int32_t GetRaSearchOffset() const {
+        return m_type == isRaSearch ? m_value.ra_search.search_offset & ~1 : 0;
+      }
+
+      bool IsFirstRaSearch() const {
+        return m_value.ra_search.search_offset % 2 == 0;
+      }
+
       int32_t GetOffset() const {
         switch (m_type) {
           case isRegisterPlusOffset:
             return m_value.reg.offset;
           case isRaSearch:
-            return m_value.ra_search_offset;
+            return m_value.ra_search.cfa_offset;
           default:
             return 0;
         }
@@ -316,7 +331,12 @@
           uint16_t length;
         } expr;
         // For m_type == isRaSearch
-        int32_t ra_search_offset;
+        struct {
+          // If last bit of search_offset is 0, it's the first try in this
+          // ra_search.
+          int32_t search_offset;
+          int32_t cfa_offset;
+        } ra_search;
       } m_value;
     }; // class FAValue
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to