xref: /freebsd-src/contrib/llvm-project/lldb/source/Target/RegisterContextUnwind.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- RegisterContextUnwind.cpp -----------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "lldb/Target/RegisterContextUnwind.h"
105ffd83dbSDimitry Andric #include "lldb/Core/Address.h"
115ffd83dbSDimitry Andric #include "lldb/Core/AddressRange.h"
125ffd83dbSDimitry Andric #include "lldb/Core/Module.h"
135ffd83dbSDimitry Andric #include "lldb/Core/Value.h"
14753f127fSDimitry Andric #include "lldb/Expression/DWARFExpressionList.h"
155ffd83dbSDimitry Andric #include "lldb/Symbol/ArmUnwindInfo.h"
165ffd83dbSDimitry Andric #include "lldb/Symbol/CallFrameInfo.h"
175ffd83dbSDimitry Andric #include "lldb/Symbol/DWARFCallFrameInfo.h"
185ffd83dbSDimitry Andric #include "lldb/Symbol/FuncUnwinders.h"
195ffd83dbSDimitry Andric #include "lldb/Symbol/Function.h"
205ffd83dbSDimitry Andric #include "lldb/Symbol/ObjectFile.h"
215ffd83dbSDimitry Andric #include "lldb/Symbol/Symbol.h"
225ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h"
235ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolFile.h"
245ffd83dbSDimitry Andric #include "lldb/Target/ABI.h"
255ffd83dbSDimitry Andric #include "lldb/Target/DynamicLoader.h"
265ffd83dbSDimitry Andric #include "lldb/Target/ExecutionContext.h"
27fe6060f1SDimitry Andric #include "lldb/Target/LanguageRuntime.h"
285ffd83dbSDimitry Andric #include "lldb/Target/Platform.h"
295ffd83dbSDimitry Andric #include "lldb/Target/Process.h"
305ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h"
315ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h"
325ffd83dbSDimitry Andric #include "lldb/Target/Target.h"
335ffd83dbSDimitry Andric #include "lldb/Target/Thread.h"
345ffd83dbSDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
3581ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
365ffd83dbSDimitry Andric #include "lldb/Utility/Log.h"
375ffd83dbSDimitry Andric #include "lldb/Utility/RegisterValue.h"
3881ad6265SDimitry Andric #include "lldb/Utility/VASPrintf.h"
395ffd83dbSDimitry Andric #include "lldb/lldb-private.h"
4006c3fb27SDimitry Andric 
4106c3fb27SDimitry Andric #include <cassert>
425ffd83dbSDimitry Andric #include <memory>
435ffd83dbSDimitry Andric 
445ffd83dbSDimitry Andric using namespace lldb;
455ffd83dbSDimitry Andric using namespace lldb_private;
465ffd83dbSDimitry Andric 
475ffd83dbSDimitry Andric static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) {
485ffd83dbSDimitry Andric   if (sym_ctx.symbol)
495ffd83dbSDimitry Andric     return sym_ctx.symbol->GetName();
505ffd83dbSDimitry Andric   else if (sym_ctx.function)
515ffd83dbSDimitry Andric     return sym_ctx.function->GetName();
525ffd83dbSDimitry Andric   return ConstString();
535ffd83dbSDimitry Andric }
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric RegisterContextUnwind::RegisterContextUnwind(Thread &thread,
565ffd83dbSDimitry Andric                                              const SharedPtr &next_frame,
575ffd83dbSDimitry Andric                                              SymbolContext &sym_ctx,
585ffd83dbSDimitry Andric                                              uint32_t frame_number,
595ffd83dbSDimitry Andric                                              UnwindLLDB &unwind_lldb)
605ffd83dbSDimitry Andric     : RegisterContext(thread, frame_number), m_thread(thread),
615ffd83dbSDimitry Andric       m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(),
625ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp(), m_all_registers_available(false),
635ffd83dbSDimitry Andric       m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS),
64fe6060f1SDimitry Andric       m_afa(LLDB_INVALID_ADDRESS), m_start_pc(), m_current_pc(),
65fe6060f1SDimitry Andric       m_current_offset(0), m_current_offset_backed_up_one(0),
66fe6060f1SDimitry Andric       m_behaves_like_zeroth_frame(false), m_sym_ctx(sym_ctx),
67fe6060f1SDimitry Andric       m_sym_ctx_valid(false), m_frame_number(frame_number), m_registers(),
68fe6060f1SDimitry Andric       m_parent_unwind(unwind_lldb) {
695ffd83dbSDimitry Andric   m_sym_ctx.Clear(false);
705ffd83dbSDimitry Andric   m_sym_ctx_valid = false;
715ffd83dbSDimitry Andric 
725ffd83dbSDimitry Andric   if (IsFrameZero()) {
735ffd83dbSDimitry Andric     InitializeZerothFrame();
745ffd83dbSDimitry Andric   } else {
755ffd83dbSDimitry Andric     InitializeNonZerothFrame();
765ffd83dbSDimitry Andric   }
775ffd83dbSDimitry Andric 
785ffd83dbSDimitry Andric   // This same code exists over in the GetFullUnwindPlanForFrame() but it may
795ffd83dbSDimitry Andric   // not have been executed yet
805ffd83dbSDimitry Andric   if (IsFrameZero() || next_frame->m_frame_type == eTrapHandlerFrame ||
815ffd83dbSDimitry Andric       next_frame->m_frame_type == eDebuggerFrame) {
825ffd83dbSDimitry Andric     m_all_registers_available = true;
835ffd83dbSDimitry Andric   }
845ffd83dbSDimitry Andric }
855ffd83dbSDimitry Andric 
865ffd83dbSDimitry Andric bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC(
8781ad6265SDimitry Andric     lldb::UnwindPlanSP unwind_plan_sp) {
885ffd83dbSDimitry Andric   if (!unwind_plan_sp)
895ffd83dbSDimitry Andric     return false;
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric   // check if m_current_pc is valid
925ffd83dbSDimitry Andric   if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
935ffd83dbSDimitry Andric     // yes - current offset can be used as is
945ffd83dbSDimitry Andric     return true;
955ffd83dbSDimitry Andric   }
965ffd83dbSDimitry Andric 
975ffd83dbSDimitry Andric   // if m_current_offset <= 0, we've got nothing else to try
985ffd83dbSDimitry Andric   if (m_current_offset <= 0)
995ffd83dbSDimitry Andric     return false;
1005ffd83dbSDimitry Andric 
1015ffd83dbSDimitry Andric   // check pc - 1 to see if it's valid
1025ffd83dbSDimitry Andric   Address pc_minus_one(m_current_pc);
1035ffd83dbSDimitry Andric   pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1);
1045ffd83dbSDimitry Andric   if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) {
1055ffd83dbSDimitry Andric     return true;
1065ffd83dbSDimitry Andric   }
1075ffd83dbSDimitry Andric 
1085ffd83dbSDimitry Andric   return false;
1095ffd83dbSDimitry Andric }
1105ffd83dbSDimitry Andric 
1115ffd83dbSDimitry Andric // Initialize a RegisterContextUnwind which is the first frame of a stack -- the
1125ffd83dbSDimitry Andric // zeroth frame or currently executing frame.
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric void RegisterContextUnwind::InitializeZerothFrame() {
11581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Unwind);
1165ffd83dbSDimitry Andric   ExecutionContext exe_ctx(m_thread.shared_from_this());
1175ffd83dbSDimitry Andric   RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();
1185ffd83dbSDimitry Andric 
1195ffd83dbSDimitry Andric   if (reg_ctx_sp.get() == nullptr) {
1205ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
1215ffd83dbSDimitry Andric     UnwindLogMsg("frame does not have a register context");
1225ffd83dbSDimitry Andric     return;
1235ffd83dbSDimitry Andric   }
1245ffd83dbSDimitry Andric 
1255ffd83dbSDimitry Andric   addr_t current_pc = reg_ctx_sp->GetPC();
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric   if (current_pc == LLDB_INVALID_ADDRESS) {
1285ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
1295ffd83dbSDimitry Andric     UnwindLogMsg("frame does not have a pc");
1305ffd83dbSDimitry Andric     return;
1315ffd83dbSDimitry Andric   }
1325ffd83dbSDimitry Andric 
1335ffd83dbSDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1345ffd83dbSDimitry Andric 
1355ffd83dbSDimitry Andric   // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
1365ffd83dbSDimitry Andric   // this will strip bit zero in case we read a PC from memory or from the LR.
1375ffd83dbSDimitry Andric   // (which would be a no-op in frame 0 where we get it from the register set,
1385ffd83dbSDimitry Andric   // but still a good idea to make the call here for other ABIs that may
1395ffd83dbSDimitry Andric   // exist.)
14006c3fb27SDimitry Andric   if (ABISP abi_sp = process->GetABI())
14106c3fb27SDimitry Andric     current_pc = abi_sp->FixCodeAddress(current_pc);
1425ffd83dbSDimitry Andric 
143fe6060f1SDimitry Andric   UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
144fe6060f1SDimitry Andric       m_thread, this, m_behaves_like_zeroth_frame);
145fe6060f1SDimitry Andric   if (lang_runtime_plan_sp.get()) {
146fe6060f1SDimitry Andric     UnwindLogMsg("This is an async frame");
147fe6060f1SDimitry Andric   }
148fe6060f1SDimitry Andric 
1495ffd83dbSDimitry Andric   // Initialize m_current_pc, an Address object, based on current_pc, an
1505ffd83dbSDimitry Andric   // addr_t.
1515ffd83dbSDimitry Andric   m_current_pc.SetLoadAddress(current_pc, &process->GetTarget());
1525ffd83dbSDimitry Andric 
1535ffd83dbSDimitry Andric   // If we don't have a Module for some reason, we're not going to find
1545ffd83dbSDimitry Andric   // symbol/function information - just stick in some reasonable defaults and
1555ffd83dbSDimitry Andric   // hope we can unwind past this frame.
1565ffd83dbSDimitry Andric   ModuleSP pc_module_sp(m_current_pc.GetModule());
1575ffd83dbSDimitry Andric   if (!m_current_pc.IsValid() || !pc_module_sp) {
1585ffd83dbSDimitry Andric     UnwindLogMsg("using architectural default unwind method");
1595ffd83dbSDimitry Andric   }
1605ffd83dbSDimitry Andric 
1615ffd83dbSDimitry Andric   AddressRange addr_range;
1625ffd83dbSDimitry Andric   m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
1635ffd83dbSDimitry Andric 
1645ffd83dbSDimitry Andric   if (m_sym_ctx.symbol) {
1655ffd83dbSDimitry Andric     UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'",
1665ffd83dbSDimitry Andric                  current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
1675ffd83dbSDimitry Andric   } else if (m_sym_ctx.function) {
1685ffd83dbSDimitry Andric     UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'",
1695ffd83dbSDimitry Andric                  current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
1705ffd83dbSDimitry Andric   } else {
1715ffd83dbSDimitry Andric     UnwindLogMsg("with pc value of 0x%" PRIx64
1725ffd83dbSDimitry Andric                  ", no symbol/function name is known.",
1735ffd83dbSDimitry Andric                  current_pc);
1745ffd83dbSDimitry Andric   }
1755ffd83dbSDimitry Andric 
1765ffd83dbSDimitry Andric   if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
1775ffd83dbSDimitry Andric     m_frame_type = eTrapHandlerFrame;
1785ffd83dbSDimitry Andric   } else {
1795ffd83dbSDimitry Andric     // FIXME:  Detect eDebuggerFrame here.
1805ffd83dbSDimitry Andric     m_frame_type = eNormalFrame;
1815ffd83dbSDimitry Andric   }
1825ffd83dbSDimitry Andric 
1835ffd83dbSDimitry Andric   // If we were able to find a symbol/function, set addr_range to the bounds of
1845ffd83dbSDimitry Andric   // that symbol/function. else treat the current pc value as the start_pc and
1855ffd83dbSDimitry Andric   // record no offset.
1865ffd83dbSDimitry Andric   if (addr_range.GetBaseAddress().IsValid()) {
1875ffd83dbSDimitry Andric     m_start_pc = addr_range.GetBaseAddress();
1885ffd83dbSDimitry Andric     if (m_current_pc.GetSection() == m_start_pc.GetSection()) {
1895ffd83dbSDimitry Andric       m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
1905ffd83dbSDimitry Andric     } else if (m_current_pc.GetModule() == m_start_pc.GetModule()) {
1915ffd83dbSDimitry Andric       // This means that whatever symbol we kicked up isn't really correct ---
1925ffd83dbSDimitry Andric       // we should not cross section boundaries ... We really should NULL out
1935ffd83dbSDimitry Andric       // the function/symbol in this case unless there is a bad assumption here
1945ffd83dbSDimitry Andric       // due to inlined functions?
1955ffd83dbSDimitry Andric       m_current_offset =
1965ffd83dbSDimitry Andric           m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress();
1975ffd83dbSDimitry Andric     }
1985ffd83dbSDimitry Andric     m_current_offset_backed_up_one = m_current_offset;
1995ffd83dbSDimitry Andric   } else {
2005ffd83dbSDimitry Andric     m_start_pc = m_current_pc;
2015ffd83dbSDimitry Andric     m_current_offset = -1;
2025ffd83dbSDimitry Andric     m_current_offset_backed_up_one = -1;
2035ffd83dbSDimitry Andric   }
2045ffd83dbSDimitry Andric 
2055ffd83dbSDimitry Andric   // We've set m_frame_type and m_sym_ctx before these calls.
2065ffd83dbSDimitry Andric 
2075ffd83dbSDimitry Andric   m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame();
2085ffd83dbSDimitry Andric   m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
2095ffd83dbSDimitry Andric 
2105ffd83dbSDimitry Andric   UnwindPlan::RowSP active_row;
2115ffd83dbSDimitry Andric   lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
212fe6060f1SDimitry Andric 
213fe6060f1SDimitry Andric   // If we have LanguageRuntime UnwindPlan for this unwind, use those
214fe6060f1SDimitry Andric   // rules to find the caller frame instead of the function's normal
215fe6060f1SDimitry Andric   // UnwindPlans.  The full unwind plan for this frame will be
216fe6060f1SDimitry Andric   // the LanguageRuntime-provided unwind plan, and there will not be a
217fe6060f1SDimitry Andric   // fast unwind plan.
218fe6060f1SDimitry Andric   if (lang_runtime_plan_sp.get()) {
219fe6060f1SDimitry Andric     active_row =
220fe6060f1SDimitry Andric         lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset);
221fe6060f1SDimitry Andric     row_register_kind = lang_runtime_plan_sp->GetRegisterKind();
222fe6060f1SDimitry Andric     if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(),
223fe6060f1SDimitry Andric                           m_cfa)) {
224fe6060f1SDimitry Andric       UnwindLogMsg("Cannot set cfa");
225fe6060f1SDimitry Andric     } else {
226fe6060f1SDimitry Andric       m_full_unwind_plan_sp = lang_runtime_plan_sp;
227fe6060f1SDimitry Andric       if (log) {
228fe6060f1SDimitry Andric         StreamString active_row_strm;
229fe6060f1SDimitry Andric         active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread,
230fe6060f1SDimitry Andric                          m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
231fe6060f1SDimitry Andric         UnwindLogMsg("async active row: %s", active_row_strm.GetData());
232fe6060f1SDimitry Andric       }
233fe6060f1SDimitry Andric       UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
234fe6060f1SDimitry Andric       UnwindLogMsg(
235fe6060f1SDimitry Andric           "initialized async frame current pc is 0x%" PRIx64
236fe6060f1SDimitry Andric           " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
237fe6060f1SDimitry Andric           (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
238fe6060f1SDimitry Andric           (uint64_t)m_cfa, (uint64_t)m_afa);
239fe6060f1SDimitry Andric 
240fe6060f1SDimitry Andric       return;
241fe6060f1SDimitry Andric     }
242fe6060f1SDimitry Andric   }
243fe6060f1SDimitry Andric 
2445ffd83dbSDimitry Andric   if (m_full_unwind_plan_sp &&
2455ffd83dbSDimitry Andric       m_full_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
2465ffd83dbSDimitry Andric     active_row =
2475ffd83dbSDimitry Andric         m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
2485ffd83dbSDimitry Andric     row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
2495ffd83dbSDimitry Andric     if (active_row.get() && log) {
2505ffd83dbSDimitry Andric       StreamString active_row_strm;
2515ffd83dbSDimitry Andric       active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread,
2525ffd83dbSDimitry Andric                        m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
2535ffd83dbSDimitry Andric       UnwindLogMsg("%s", active_row_strm.GetData());
2545ffd83dbSDimitry Andric     }
2555ffd83dbSDimitry Andric   }
2565ffd83dbSDimitry Andric 
2575ffd83dbSDimitry Andric   if (!active_row.get()) {
2585ffd83dbSDimitry Andric     UnwindLogMsg("could not find an unwindplan row for this frame's pc");
2595ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
2605ffd83dbSDimitry Andric     return;
2615ffd83dbSDimitry Andric   }
2625ffd83dbSDimitry Andric 
2635ffd83dbSDimitry Andric   if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
2645ffd83dbSDimitry Andric     // Try the fall back unwind plan since the
2655ffd83dbSDimitry Andric     // full unwind plan failed.
2665ffd83dbSDimitry Andric     FuncUnwindersSP func_unwinders_sp;
2675ffd83dbSDimitry Andric     UnwindPlanSP call_site_unwind_plan;
2685ffd83dbSDimitry Andric     bool cfa_status = false;
2695ffd83dbSDimitry Andric 
2705ffd83dbSDimitry Andric     if (m_sym_ctx_valid) {
2715ffd83dbSDimitry Andric       func_unwinders_sp =
2725ffd83dbSDimitry Andric           pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress(
2735ffd83dbSDimitry Andric               m_current_pc, m_sym_ctx);
2745ffd83dbSDimitry Andric     }
2755ffd83dbSDimitry Andric 
2765ffd83dbSDimitry Andric     if (func_unwinders_sp.get() != nullptr)
2775ffd83dbSDimitry Andric       call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(
2785ffd83dbSDimitry Andric           process->GetTarget(), m_thread);
2795ffd83dbSDimitry Andric 
2805ffd83dbSDimitry Andric     if (call_site_unwind_plan.get() != nullptr) {
2815ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp = call_site_unwind_plan;
2825ffd83dbSDimitry Andric       if (TryFallbackUnwindPlan())
2835ffd83dbSDimitry Andric         cfa_status = true;
2845ffd83dbSDimitry Andric     }
2855ffd83dbSDimitry Andric     if (!cfa_status) {
2865ffd83dbSDimitry Andric       UnwindLogMsg("could not read CFA value for first frame.");
2875ffd83dbSDimitry Andric       m_frame_type = eNotAValidFrame;
2885ffd83dbSDimitry Andric       return;
2895ffd83dbSDimitry Andric     }
2905ffd83dbSDimitry Andric   } else
2915ffd83dbSDimitry Andric     ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
2925ffd83dbSDimitry Andric 
29306c3fb27SDimitry Andric   if (m_cfa == LLDB_INVALID_ADDRESS && m_afa == LLDB_INVALID_ADDRESS) {
29406c3fb27SDimitry Andric     UnwindLogMsg(
29506c3fb27SDimitry Andric         "could not read CFA or AFA values for first frame, not valid.");
29606c3fb27SDimitry Andric     m_frame_type = eNotAValidFrame;
29706c3fb27SDimitry Andric     return;
29806c3fb27SDimitry Andric   }
29906c3fb27SDimitry Andric 
3005ffd83dbSDimitry Andric   UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
3015ffd83dbSDimitry Andric                " afa is 0x%" PRIx64 " using %s UnwindPlan",
3025ffd83dbSDimitry Andric                (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
3035ffd83dbSDimitry Andric                (uint64_t)m_cfa,
3045ffd83dbSDimitry Andric                (uint64_t)m_afa,
3055ffd83dbSDimitry Andric                m_full_unwind_plan_sp->GetSourceName().GetCString());
3065ffd83dbSDimitry Andric }
3075ffd83dbSDimitry Andric 
3085ffd83dbSDimitry Andric // Initialize a RegisterContextUnwind for the non-zeroth frame -- rely on the
3095ffd83dbSDimitry Andric // RegisterContextUnwind "below" it to provide things like its current pc value.
3105ffd83dbSDimitry Andric 
3115ffd83dbSDimitry Andric void RegisterContextUnwind::InitializeNonZerothFrame() {
31281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Unwind);
3135ffd83dbSDimitry Andric   if (IsFrameZero()) {
3145ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
3155ffd83dbSDimitry Andric     UnwindLogMsg("non-zeroth frame tests positive for IsFrameZero -- that "
3165ffd83dbSDimitry Andric                  "shouldn't happen.");
3175ffd83dbSDimitry Andric     return;
3185ffd83dbSDimitry Andric   }
3195ffd83dbSDimitry Andric 
3205ffd83dbSDimitry Andric   if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) {
3215ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
3225ffd83dbSDimitry Andric     UnwindLogMsg("Could not get next frame, marking this frame as invalid.");
3235ffd83dbSDimitry Andric     return;
3245ffd83dbSDimitry Andric   }
3255ffd83dbSDimitry Andric   if (!m_thread.GetRegisterContext()) {
3265ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
3275ffd83dbSDimitry Andric     UnwindLogMsg("Could not get register context for this thread, marking this "
3285ffd83dbSDimitry Andric                  "frame as invalid.");
3295ffd83dbSDimitry Andric     return;
3305ffd83dbSDimitry Andric   }
3315ffd83dbSDimitry Andric 
332fe6060f1SDimitry Andric   ExecutionContext exe_ctx(m_thread.shared_from_this());
333fe6060f1SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
334fe6060f1SDimitry Andric 
335fe6060f1SDimitry Andric   // Some languages may have a logical parent stack frame which is
336fe6060f1SDimitry Andric   // not a real stack frame, but the programmer would consider it to
337fe6060f1SDimitry Andric   // be the caller of the frame, e.g. Swift asynchronous frames.
338fe6060f1SDimitry Andric   //
339fe6060f1SDimitry Andric   // A LanguageRuntime may provide an UnwindPlan that is used in this
340fe6060f1SDimitry Andric   // stack trace base on the RegisterContext contents, intsead
341fe6060f1SDimitry Andric   // of the normal UnwindPlans we would use for the return-pc.
342fe6060f1SDimitry Andric   UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
343fe6060f1SDimitry Andric       m_thread, this, m_behaves_like_zeroth_frame);
344fe6060f1SDimitry Andric   if (lang_runtime_plan_sp.get()) {
345fe6060f1SDimitry Andric     UnwindLogMsg("This is an async frame");
346fe6060f1SDimitry Andric   }
347fe6060f1SDimitry Andric 
3485ffd83dbSDimitry Andric   addr_t pc;
3495ffd83dbSDimitry Andric   if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) {
3505ffd83dbSDimitry Andric     UnwindLogMsg("could not get pc value");
3515ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
3525ffd83dbSDimitry Andric     return;
3535ffd83dbSDimitry Andric   }
3545ffd83dbSDimitry Andric 
3555ffd83dbSDimitry Andric   // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
3565ffd83dbSDimitry Andric   // this will strip bit zero in case we read a PC from memory or from the LR.
35706c3fb27SDimitry Andric   ABISP abi_sp = process->GetABI();
35806c3fb27SDimitry Andric   if (abi_sp)
35906c3fb27SDimitry Andric     pc = abi_sp->FixCodeAddress(pc);
3605ffd83dbSDimitry Andric 
3615ffd83dbSDimitry Andric   if (log) {
3625ffd83dbSDimitry Andric     UnwindLogMsg("pc = 0x%" PRIx64, pc);
3635ffd83dbSDimitry Andric     addr_t reg_val;
36406c3fb27SDimitry Andric     if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) {
36506c3fb27SDimitry Andric       if (abi_sp)
36606c3fb27SDimitry Andric         reg_val = abi_sp->FixDataAddress(reg_val);
3675ffd83dbSDimitry Andric       UnwindLogMsg("fp = 0x%" PRIx64, reg_val);
36806c3fb27SDimitry Andric     }
36906c3fb27SDimitry Andric     if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) {
37006c3fb27SDimitry Andric       if (abi_sp)
37106c3fb27SDimitry Andric         reg_val = abi_sp->FixDataAddress(reg_val);
3725ffd83dbSDimitry Andric       UnwindLogMsg("sp = 0x%" PRIx64, reg_val);
3735ffd83dbSDimitry Andric     }
37406c3fb27SDimitry Andric   }
3755ffd83dbSDimitry Andric 
3765ffd83dbSDimitry Andric   // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap
3775ffd83dbSDimitry Andric   // handler function
3785ffd83dbSDimitry Andric   bool above_trap_handler = false;
3795ffd83dbSDimitry Andric   if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
3805ffd83dbSDimitry Andric       GetNextFrame()->IsTrapHandlerFrame())
3815ffd83dbSDimitry Andric     above_trap_handler = true;
3825ffd83dbSDimitry Andric 
3835ffd83dbSDimitry Andric   if (pc == 0 || pc == 0x1) {
3845ffd83dbSDimitry Andric     if (!above_trap_handler) {
3855ffd83dbSDimitry Andric       m_frame_type = eNotAValidFrame;
3865ffd83dbSDimitry Andric       UnwindLogMsg("this frame has a pc of 0x0");
3875ffd83dbSDimitry Andric       return;
3885ffd83dbSDimitry Andric     }
3895ffd83dbSDimitry Andric   }
3905ffd83dbSDimitry Andric 
3915ffd83dbSDimitry Andric   const bool allow_section_end = true;
3925ffd83dbSDimitry Andric   m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end);
3935ffd83dbSDimitry Andric 
3945ffd83dbSDimitry Andric   // If we don't have a Module for some reason, we're not going to find
3955ffd83dbSDimitry Andric   // symbol/function information - just stick in some reasonable defaults and
3965ffd83dbSDimitry Andric   // hope we can unwind past this frame.  If we're above a trap handler,
3975ffd83dbSDimitry Andric   // we may be at a bogus address because we jumped through a bogus function
3985ffd83dbSDimitry Andric   // pointer and trapped, so don't force the arch default unwind plan in that
3995ffd83dbSDimitry Andric   // case.
4005ffd83dbSDimitry Andric   ModuleSP pc_module_sp(m_current_pc.GetModule());
4015ffd83dbSDimitry Andric   if ((!m_current_pc.IsValid() || !pc_module_sp) &&
4025ffd83dbSDimitry Andric       above_trap_handler == false) {
4035ffd83dbSDimitry Andric     UnwindLogMsg("using architectural default unwind method");
4045ffd83dbSDimitry Andric 
4055ffd83dbSDimitry Andric     // Test the pc value to see if we know it's in an unmapped/non-executable
4065ffd83dbSDimitry Andric     // region of memory.
4075ffd83dbSDimitry Andric     uint32_t permissions;
4085ffd83dbSDimitry Andric     if (process->GetLoadAddressPermissions(pc, permissions) &&
4095ffd83dbSDimitry Andric         (permissions & ePermissionsExecutable) == 0) {
4105ffd83dbSDimitry Andric       // If this is the second frame off the stack, we may have unwound the
4115ffd83dbSDimitry Andric       // first frame incorrectly.  But using the architecture default unwind
4125ffd83dbSDimitry Andric       // plan may get us back on track -- albeit possibly skipping a real
4135ffd83dbSDimitry Andric       // frame.  Give this frame a clearly-invalid pc and see if we can get any
4145ffd83dbSDimitry Andric       // further.
4155ffd83dbSDimitry Andric       if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
4165ffd83dbSDimitry Andric           GetNextFrame()->IsFrameZero()) {
4175ffd83dbSDimitry Andric         UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable "
4185ffd83dbSDimitry Andric                                               "memory but on frame 1 -- "
4195ffd83dbSDimitry Andric                                               "allowing it once.",
4205ffd83dbSDimitry Andric                      (uint64_t)pc);
4215ffd83dbSDimitry Andric         m_frame_type = eSkipFrame;
4225ffd83dbSDimitry Andric       } else {
4235ffd83dbSDimitry Andric         // anywhere other than the second frame, a non-executable pc means
4245ffd83dbSDimitry Andric         // we're off in the weeds -- stop now.
4255ffd83dbSDimitry Andric         m_frame_type = eNotAValidFrame;
4265ffd83dbSDimitry Andric         UnwindLogMsg("pc is in a non-executable section of memory and this "
4275ffd83dbSDimitry Andric                      "isn't the 2nd frame in the stack walk.");
4285ffd83dbSDimitry Andric         return;
4295ffd83dbSDimitry Andric       }
4305ffd83dbSDimitry Andric     }
4315ffd83dbSDimitry Andric 
43206c3fb27SDimitry Andric     if (abi_sp) {
4335ffd83dbSDimitry Andric       m_fast_unwind_plan_sp.reset();
4345ffd83dbSDimitry Andric       m_full_unwind_plan_sp =
4355ffd83dbSDimitry Andric           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
43606c3fb27SDimitry Andric       abi_sp->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
4375ffd83dbSDimitry Andric       if (m_frame_type != eSkipFrame) // don't override eSkipFrame
4385ffd83dbSDimitry Andric       {
4395ffd83dbSDimitry Andric         m_frame_type = eNormalFrame;
4405ffd83dbSDimitry Andric       }
4415ffd83dbSDimitry Andric       m_all_registers_available = false;
4425ffd83dbSDimitry Andric       m_current_offset = -1;
4435ffd83dbSDimitry Andric       m_current_offset_backed_up_one = -1;
4445ffd83dbSDimitry Andric       RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
4455ffd83dbSDimitry Andric       UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
4465ffd83dbSDimitry Andric       if (row.get()) {
4475ffd83dbSDimitry Andric         if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) {
4485ffd83dbSDimitry Andric           UnwindLogMsg("failed to get cfa value");
4495ffd83dbSDimitry Andric           if (m_frame_type != eSkipFrame) // don't override eSkipFrame
4505ffd83dbSDimitry Andric           {
4515ffd83dbSDimitry Andric             m_frame_type = eNotAValidFrame;
4525ffd83dbSDimitry Andric           }
4535ffd83dbSDimitry Andric           return;
4545ffd83dbSDimitry Andric         }
4555ffd83dbSDimitry Andric 
4565ffd83dbSDimitry Andric         ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa);
4575ffd83dbSDimitry Andric 
4585ffd83dbSDimitry Andric         // A couple of sanity checks..
4595ffd83dbSDimitry Andric         if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) {
4605ffd83dbSDimitry Andric           UnwindLogMsg("could not find a valid cfa address");
4615ffd83dbSDimitry Andric           m_frame_type = eNotAValidFrame;
4625ffd83dbSDimitry Andric           return;
4635ffd83dbSDimitry Andric         }
4645ffd83dbSDimitry Andric 
4655ffd83dbSDimitry Andric         // m_cfa should point into the stack memory; if we can query memory
4665ffd83dbSDimitry Andric         // region permissions, see if the memory is allocated & readable.
4675ffd83dbSDimitry Andric         if (process->GetLoadAddressPermissions(m_cfa, permissions) &&
4685ffd83dbSDimitry Andric             (permissions & ePermissionsReadable) == 0) {
4695ffd83dbSDimitry Andric           m_frame_type = eNotAValidFrame;
4705ffd83dbSDimitry Andric           UnwindLogMsg(
4715ffd83dbSDimitry Andric               "the CFA points to a region of memory that is not readable");
4725ffd83dbSDimitry Andric           return;
4735ffd83dbSDimitry Andric         }
4745ffd83dbSDimitry Andric       } else {
4755ffd83dbSDimitry Andric         UnwindLogMsg("could not find a row for function offset zero");
4765ffd83dbSDimitry Andric         m_frame_type = eNotAValidFrame;
4775ffd83dbSDimitry Andric         return;
4785ffd83dbSDimitry Andric       }
4795ffd83dbSDimitry Andric 
4805ffd83dbSDimitry Andric       if (CheckIfLoopingStack()) {
4815ffd83dbSDimitry Andric         TryFallbackUnwindPlan();
4825ffd83dbSDimitry Andric         if (CheckIfLoopingStack()) {
4835ffd83dbSDimitry Andric           UnwindLogMsg("same CFA address as next frame, assuming the unwind is "
4845ffd83dbSDimitry Andric                        "looping - stopping");
4855ffd83dbSDimitry Andric           m_frame_type = eNotAValidFrame;
4865ffd83dbSDimitry Andric           return;
4875ffd83dbSDimitry Andric         }
4885ffd83dbSDimitry Andric       }
4895ffd83dbSDimitry Andric 
4905ffd83dbSDimitry Andric       UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
4915ffd83dbSDimitry Andric                    (uint64_t)m_cfa, (uint64_t)m_afa);
4925ffd83dbSDimitry Andric       return;
4935ffd83dbSDimitry Andric     }
4945ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
4955ffd83dbSDimitry Andric     UnwindLogMsg("could not find any symbol for this pc, or a default unwind "
4965ffd83dbSDimitry Andric                  "plan, to continue unwind.");
4975ffd83dbSDimitry Andric     return;
4985ffd83dbSDimitry Andric   }
4995ffd83dbSDimitry Andric 
5005ffd83dbSDimitry Andric   AddressRange addr_range;
5015ffd83dbSDimitry Andric   m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
5025ffd83dbSDimitry Andric 
5035ffd83dbSDimitry Andric   if (m_sym_ctx.symbol) {
5045ffd83dbSDimitry Andric     UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc,
5055ffd83dbSDimitry Andric                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
5065ffd83dbSDimitry Andric   } else if (m_sym_ctx.function) {
5075ffd83dbSDimitry Andric     UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", pc,
5085ffd83dbSDimitry Andric                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
5095ffd83dbSDimitry Andric   } else {
5105ffd83dbSDimitry Andric     UnwindLogMsg("with pc value of 0x%" PRIx64
5115ffd83dbSDimitry Andric                  ", no symbol/function name is known.",
5125ffd83dbSDimitry Andric                  pc);
5135ffd83dbSDimitry Andric   }
5145ffd83dbSDimitry Andric 
5155ffd83dbSDimitry Andric   bool decr_pc_and_recompute_addr_range;
5165ffd83dbSDimitry Andric 
5175ffd83dbSDimitry Andric   if (!m_sym_ctx_valid) {
5185ffd83dbSDimitry Andric     // Always decrement and recompute if the symbol lookup failed
5195ffd83dbSDimitry Andric     decr_pc_and_recompute_addr_range = true;
5205ffd83dbSDimitry Andric   } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame ||
5215ffd83dbSDimitry Andric              GetNextFrame()->m_frame_type == eDebuggerFrame) {
5225ffd83dbSDimitry Andric     // Don't decrement if we're "above" an asynchronous event like
5235ffd83dbSDimitry Andric     // sigtramp.
5245ffd83dbSDimitry Andric     decr_pc_and_recompute_addr_range = false;
5255ffd83dbSDimitry Andric   } else if (!addr_range.GetBaseAddress().IsValid() ||
5265ffd83dbSDimitry Andric              addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() ||
5275ffd83dbSDimitry Andric              addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) {
52881ad6265SDimitry Andric     // If our "current" pc isn't the start of a function, decrement the pc
52981ad6265SDimitry Andric     // if we're up the stack.
53081ad6265SDimitry Andric     if (m_behaves_like_zeroth_frame)
5315ffd83dbSDimitry Andric       decr_pc_and_recompute_addr_range = false;
53281ad6265SDimitry Andric     else
53381ad6265SDimitry Andric       decr_pc_and_recompute_addr_range = true;
5345ffd83dbSDimitry Andric   } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
5355ffd83dbSDimitry Andric     // Signal dispatch may set the return address of the handler it calls to
5365ffd83dbSDimitry Andric     // point to the first byte of a return trampoline (like __kernel_rt_sigreturn),
5375ffd83dbSDimitry Andric     // so do not decrement and recompute if the symbol we already found is a trap
5385ffd83dbSDimitry Andric     // handler.
5395ffd83dbSDimitry Andric     decr_pc_and_recompute_addr_range = false;
540fe6060f1SDimitry Andric   } else if (m_behaves_like_zeroth_frame) {
541fe6060f1SDimitry Andric     decr_pc_and_recompute_addr_range = false;
5425ffd83dbSDimitry Andric   } else {
5435ffd83dbSDimitry Andric     // Decrement to find the function containing the call.
5445ffd83dbSDimitry Andric     decr_pc_and_recompute_addr_range = true;
5455ffd83dbSDimitry Andric   }
5465ffd83dbSDimitry Andric 
5475ffd83dbSDimitry Andric   // We need to back up the pc by 1 byte and re-search for the Symbol to handle
5485ffd83dbSDimitry Andric   // the case where the "saved pc" value is pointing to the next function, e.g.
5495ffd83dbSDimitry Andric   // if a function ends with a CALL instruction.
5505ffd83dbSDimitry Andric   // FIXME this may need to be an architectural-dependent behavior; if so we'll
5515ffd83dbSDimitry Andric   // need to add a member function
5525ffd83dbSDimitry Andric   // to the ABI plugin and consult that.
5535ffd83dbSDimitry Andric   if (decr_pc_and_recompute_addr_range) {
5545ffd83dbSDimitry Andric     UnwindLogMsg("Backing up the pc value of 0x%" PRIx64
5555ffd83dbSDimitry Andric                  " by 1 and re-doing symbol lookup; old symbol was %s",
5565ffd83dbSDimitry Andric                  pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
5575ffd83dbSDimitry Andric     Address temporary_pc;
5585ffd83dbSDimitry Andric     temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget());
5595ffd83dbSDimitry Andric     m_sym_ctx.Clear(false);
5605ffd83dbSDimitry Andric     m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
5615ffd83dbSDimitry Andric 
5625ffd83dbSDimitry Andric     UnwindLogMsg("Symbol is now %s",
5635ffd83dbSDimitry Andric                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
5645ffd83dbSDimitry Andric   }
5655ffd83dbSDimitry Andric 
5665ffd83dbSDimitry Andric   // If we were able to find a symbol/function, set addr_range_ptr to the
5675ffd83dbSDimitry Andric   // bounds of that symbol/function. else treat the current pc value as the
5685ffd83dbSDimitry Andric   // start_pc and record no offset.
5695ffd83dbSDimitry Andric   if (addr_range.GetBaseAddress().IsValid()) {
5705ffd83dbSDimitry Andric     m_start_pc = addr_range.GetBaseAddress();
5715ffd83dbSDimitry Andric     m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget());
5725ffd83dbSDimitry Andric     m_current_offset_backed_up_one = m_current_offset;
5735ffd83dbSDimitry Andric     if (decr_pc_and_recompute_addr_range &&
5745ffd83dbSDimitry Andric         m_current_offset_backed_up_one > 0) {
5755ffd83dbSDimitry Andric       m_current_offset_backed_up_one--;
5765ffd83dbSDimitry Andric       if (m_sym_ctx_valid) {
5775ffd83dbSDimitry Andric         m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget());
5785ffd83dbSDimitry Andric       }
5795ffd83dbSDimitry Andric     }
5805ffd83dbSDimitry Andric   } else {
5815ffd83dbSDimitry Andric     m_start_pc = m_current_pc;
5825ffd83dbSDimitry Andric     m_current_offset = -1;
5835ffd83dbSDimitry Andric     m_current_offset_backed_up_one = -1;
5845ffd83dbSDimitry Andric   }
5855ffd83dbSDimitry Andric 
5865ffd83dbSDimitry Andric   if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
5875ffd83dbSDimitry Andric     m_frame_type = eTrapHandlerFrame;
5885ffd83dbSDimitry Andric   } else {
5895ffd83dbSDimitry Andric     // FIXME:  Detect eDebuggerFrame here.
5905ffd83dbSDimitry Andric     if (m_frame_type != eSkipFrame) // don't override eSkipFrame
5915ffd83dbSDimitry Andric     {
5925ffd83dbSDimitry Andric       m_frame_type = eNormalFrame;
5935ffd83dbSDimitry Andric     }
5945ffd83dbSDimitry Andric   }
5955ffd83dbSDimitry Andric 
5965ffd83dbSDimitry Andric   UnwindPlan::RowSP active_row;
5975ffd83dbSDimitry Andric   RegisterKind row_register_kind = eRegisterKindGeneric;
5985ffd83dbSDimitry Andric 
599fe6060f1SDimitry Andric   // If we have LanguageRuntime UnwindPlan for this unwind, use those
600fe6060f1SDimitry Andric   // rules to find the caller frame instead of the function's normal
601fe6060f1SDimitry Andric   // UnwindPlans.  The full unwind plan for this frame will be
602fe6060f1SDimitry Andric   // the LanguageRuntime-provided unwind plan, and there will not be a
603fe6060f1SDimitry Andric   // fast unwind plan.
604fe6060f1SDimitry Andric   if (lang_runtime_plan_sp.get()) {
605fe6060f1SDimitry Andric     active_row =
606fe6060f1SDimitry Andric         lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset);
607fe6060f1SDimitry Andric     row_register_kind = lang_runtime_plan_sp->GetRegisterKind();
608fe6060f1SDimitry Andric     if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(),
609fe6060f1SDimitry Andric                           m_cfa)) {
610fe6060f1SDimitry Andric       UnwindLogMsg("Cannot set cfa");
611fe6060f1SDimitry Andric     } else {
612fe6060f1SDimitry Andric       m_full_unwind_plan_sp = lang_runtime_plan_sp;
613fe6060f1SDimitry Andric       if (log) {
614fe6060f1SDimitry Andric         StreamString active_row_strm;
615fe6060f1SDimitry Andric         active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread,
616fe6060f1SDimitry Andric                          m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
617fe6060f1SDimitry Andric         UnwindLogMsg("async active row: %s", active_row_strm.GetData());
618fe6060f1SDimitry Andric       }
619fe6060f1SDimitry Andric       UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
620fe6060f1SDimitry Andric       UnwindLogMsg(
621fe6060f1SDimitry Andric           "initialized async frame current pc is 0x%" PRIx64
622fe6060f1SDimitry Andric           " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
623fe6060f1SDimitry Andric           (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
624fe6060f1SDimitry Andric           (uint64_t)m_cfa, (uint64_t)m_afa);
625fe6060f1SDimitry Andric 
626fe6060f1SDimitry Andric       return;
627fe6060f1SDimitry Andric     }
628fe6060f1SDimitry Andric   }
629fe6060f1SDimitry Andric 
630fe6060f1SDimitry Andric   // We've set m_frame_type and m_sym_ctx before this call.
631fe6060f1SDimitry Andric   m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame();
632fe6060f1SDimitry Andric 
6335ffd83dbSDimitry Andric   // Try to get by with just the fast UnwindPlan if possible - the full
6345ffd83dbSDimitry Andric   // UnwindPlan may be expensive to get (e.g. if we have to parse the entire
6355ffd83dbSDimitry Andric   // eh_frame section of an ObjectFile for the first time.)
6365ffd83dbSDimitry Andric 
6375ffd83dbSDimitry Andric   if (m_fast_unwind_plan_sp &&
6385ffd83dbSDimitry Andric       m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
6395ffd83dbSDimitry Andric     active_row =
6405ffd83dbSDimitry Andric         m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
6415ffd83dbSDimitry Andric     row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind();
6425ffd83dbSDimitry Andric     PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp);
6435ffd83dbSDimitry Andric     if (active_row.get() && log) {
6445ffd83dbSDimitry Andric       StreamString active_row_strm;
6455ffd83dbSDimitry Andric       active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread,
6465ffd83dbSDimitry Andric                        m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
647fe6060f1SDimitry Andric       UnwindLogMsg("Using fast unwind plan '%s'",
648fe6060f1SDimitry Andric                    m_fast_unwind_plan_sp->GetSourceName().AsCString());
6495ffd83dbSDimitry Andric       UnwindLogMsg("active row: %s", active_row_strm.GetData());
6505ffd83dbSDimitry Andric     }
6515ffd83dbSDimitry Andric   } else {
6525ffd83dbSDimitry Andric     m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
65381ad6265SDimitry Andric     if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp)) {
65481ad6265SDimitry Andric       active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(
65581ad6265SDimitry Andric           m_current_offset_backed_up_one);
6565ffd83dbSDimitry Andric       row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
6575ffd83dbSDimitry Andric       PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
6585ffd83dbSDimitry Andric       if (active_row.get() && log) {
6595ffd83dbSDimitry Andric         StreamString active_row_strm;
6605ffd83dbSDimitry Andric         active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
6615ffd83dbSDimitry Andric                          &m_thread,
6625ffd83dbSDimitry Andric                          m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
663fe6060f1SDimitry Andric         UnwindLogMsg("Using full unwind plan '%s'",
664fe6060f1SDimitry Andric                      m_full_unwind_plan_sp->GetSourceName().AsCString());
6655ffd83dbSDimitry Andric         UnwindLogMsg("active row: %s", active_row_strm.GetData());
6665ffd83dbSDimitry Andric       }
6675ffd83dbSDimitry Andric     }
6685ffd83dbSDimitry Andric   }
6695ffd83dbSDimitry Andric 
6705ffd83dbSDimitry Andric   if (!active_row.get()) {
6715ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
6725ffd83dbSDimitry Andric     UnwindLogMsg("could not find unwind row for this pc");
6735ffd83dbSDimitry Andric     return;
6745ffd83dbSDimitry Andric   }
6755ffd83dbSDimitry Andric 
6765ffd83dbSDimitry Andric   if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
6775ffd83dbSDimitry Andric     UnwindLogMsg("failed to get cfa");
6785ffd83dbSDimitry Andric     m_frame_type = eNotAValidFrame;
6795ffd83dbSDimitry Andric     return;
6805ffd83dbSDimitry Andric   }
6815ffd83dbSDimitry Andric 
6825ffd83dbSDimitry Andric   ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
6835ffd83dbSDimitry Andric 
6845ffd83dbSDimitry Andric   UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
6855ffd83dbSDimitry Andric 
6865ffd83dbSDimitry Andric   if (CheckIfLoopingStack()) {
6875ffd83dbSDimitry Andric     TryFallbackUnwindPlan();
6885ffd83dbSDimitry Andric     if (CheckIfLoopingStack()) {
6895ffd83dbSDimitry Andric       UnwindLogMsg("same CFA address as next frame, assuming the unwind is "
6905ffd83dbSDimitry Andric                    "looping - stopping");
6915ffd83dbSDimitry Andric       m_frame_type = eNotAValidFrame;
6925ffd83dbSDimitry Andric       return;
6935ffd83dbSDimitry Andric     }
6945ffd83dbSDimitry Andric   }
6955ffd83dbSDimitry Andric 
6965ffd83dbSDimitry Andric   UnwindLogMsg("initialized frame current pc is 0x%" PRIx64
6975ffd83dbSDimitry Andric                " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
6985ffd83dbSDimitry Andric                (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
6995ffd83dbSDimitry Andric                (uint64_t)m_cfa,
7005ffd83dbSDimitry Andric                (uint64_t)m_afa);
7015ffd83dbSDimitry Andric }
7025ffd83dbSDimitry Andric 
7035ffd83dbSDimitry Andric bool RegisterContextUnwind::CheckIfLoopingStack() {
7045ffd83dbSDimitry Andric   // If we have a bad stack setup, we can get the same CFA value multiple times
7055ffd83dbSDimitry Andric   // -- or even more devious, we can actually oscillate between two CFA values.
7065ffd83dbSDimitry Andric   // Detect that here and break out to avoid a possible infinite loop in lldb
7075ffd83dbSDimitry Andric   // trying to unwind the stack. To detect when we have the same CFA value
7085ffd83dbSDimitry Andric   // multiple times, we compare the
7095ffd83dbSDimitry Andric   // CFA of the current
7105ffd83dbSDimitry Andric   // frame with the 2nd next frame because in some specail case (e.g. signal
7115ffd83dbSDimitry Andric   // hanlders, hand written assembly without ABI compliance) we can have 2
7125ffd83dbSDimitry Andric   // frames with the same
7135ffd83dbSDimitry Andric   // CFA (in theory we
7145ffd83dbSDimitry Andric   // can have arbitrary number of frames with the same CFA, but more then 2 is
7155f757f3fSDimitry Andric   // very unlikely)
7165ffd83dbSDimitry Andric 
7175ffd83dbSDimitry Andric   RegisterContextUnwind::SharedPtr next_frame = GetNextFrame();
7185ffd83dbSDimitry Andric   if (next_frame) {
7195ffd83dbSDimitry Andric     RegisterContextUnwind::SharedPtr next_next_frame =
7205ffd83dbSDimitry Andric         next_frame->GetNextFrame();
7215ffd83dbSDimitry Andric     addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
7225ffd83dbSDimitry Andric     if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa)) {
7235ffd83dbSDimitry Andric       if (next_next_frame_cfa == m_cfa) {
7245ffd83dbSDimitry Andric         // We have a loop in the stack unwind
7255ffd83dbSDimitry Andric         return true;
7265ffd83dbSDimitry Andric       }
7275ffd83dbSDimitry Andric     }
7285ffd83dbSDimitry Andric   }
7295ffd83dbSDimitry Andric   return false;
7305ffd83dbSDimitry Andric }
7315ffd83dbSDimitry Andric 
7325ffd83dbSDimitry Andric bool RegisterContextUnwind::IsFrameZero() const { return m_frame_number == 0; }
7335ffd83dbSDimitry Andric 
734fe6060f1SDimitry Andric bool RegisterContextUnwind::BehavesLikeZerothFrame() const {
735fe6060f1SDimitry Andric   if (m_frame_number == 0)
736fe6060f1SDimitry Andric     return true;
737fe6060f1SDimitry Andric   if (m_behaves_like_zeroth_frame)
738fe6060f1SDimitry Andric     return true;
739fe6060f1SDimitry Andric   return false;
740fe6060f1SDimitry Andric }
741fe6060f1SDimitry Andric 
7425ffd83dbSDimitry Andric // Find a fast unwind plan for this frame, if possible.
7435ffd83dbSDimitry Andric //
7445ffd83dbSDimitry Andric // On entry to this method,
7455ffd83dbSDimitry Andric //
7465ffd83dbSDimitry Andric //   1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame
7475ffd83dbSDimitry Andric //   if either of those are correct,
7485ffd83dbSDimitry Andric //   2. m_sym_ctx should already be filled in, and
7495ffd83dbSDimitry Andric //   3. m_current_pc should have the current pc value for this frame
7505ffd83dbSDimitry Andric //   4. m_current_offset_backed_up_one should have the current byte offset into
7515ffd83dbSDimitry Andric //   the function, maybe backed up by 1, -1 if unknown
7525ffd83dbSDimitry Andric 
7535ffd83dbSDimitry Andric UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() {
7545ffd83dbSDimitry Andric   UnwindPlanSP unwind_plan_sp;
7555ffd83dbSDimitry Andric   ModuleSP pc_module_sp(m_current_pc.GetModule());
7565ffd83dbSDimitry Andric 
7575ffd83dbSDimitry Andric   if (!m_current_pc.IsValid() || !pc_module_sp ||
7585ffd83dbSDimitry Andric       pc_module_sp->GetObjectFile() == nullptr)
7595ffd83dbSDimitry Andric     return unwind_plan_sp;
7605ffd83dbSDimitry Andric 
7615ffd83dbSDimitry Andric   if (IsFrameZero())
7625ffd83dbSDimitry Andric     return unwind_plan_sp;
7635ffd83dbSDimitry Andric 
7645ffd83dbSDimitry Andric   FuncUnwindersSP func_unwinders_sp(
7655ffd83dbSDimitry Andric       pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress(
7665ffd83dbSDimitry Andric           m_current_pc, m_sym_ctx));
7675ffd83dbSDimitry Andric   if (!func_unwinders_sp)
7685ffd83dbSDimitry Andric     return unwind_plan_sp;
7695ffd83dbSDimitry Andric 
7705ffd83dbSDimitry Andric   // If we're in _sigtramp(), unwinding past this frame requires special
7715ffd83dbSDimitry Andric   // knowledge.
7725ffd83dbSDimitry Andric   if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame)
7735ffd83dbSDimitry Andric     return unwind_plan_sp;
7745ffd83dbSDimitry Andric 
7755ffd83dbSDimitry Andric   unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind(
7765ffd83dbSDimitry Andric       *m_thread.CalculateTarget(), m_thread);
7775ffd83dbSDimitry Andric   if (unwind_plan_sp) {
7785ffd83dbSDimitry Andric     if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
7795ffd83dbSDimitry Andric       m_frame_type = eNormalFrame;
7805ffd83dbSDimitry Andric       return unwind_plan_sp;
7815ffd83dbSDimitry Andric     } else {
7825ffd83dbSDimitry Andric       unwind_plan_sp.reset();
7835ffd83dbSDimitry Andric     }
7845ffd83dbSDimitry Andric   }
7855ffd83dbSDimitry Andric   return unwind_plan_sp;
7865ffd83dbSDimitry Andric }
7875ffd83dbSDimitry Andric 
7885ffd83dbSDimitry Andric // On entry to this method,
7895ffd83dbSDimitry Andric //
7905ffd83dbSDimitry Andric //   1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame
7915ffd83dbSDimitry Andric //   if either of those are correct,
7925ffd83dbSDimitry Andric //   2. m_sym_ctx should already be filled in, and
7935ffd83dbSDimitry Andric //   3. m_current_pc should have the current pc value for this frame
7945ffd83dbSDimitry Andric //   4. m_current_offset_backed_up_one should have the current byte offset into
7955ffd83dbSDimitry Andric //   the function, maybe backed up by 1, -1 if unknown
7965ffd83dbSDimitry Andric 
7975ffd83dbSDimitry Andric UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
7985ffd83dbSDimitry Andric   UnwindPlanSP unwind_plan_sp;
7995ffd83dbSDimitry Andric   UnwindPlanSP arch_default_unwind_plan_sp;
8005ffd83dbSDimitry Andric   ExecutionContext exe_ctx(m_thread.shared_from_this());
8015ffd83dbSDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
8025ffd83dbSDimitry Andric   ABI *abi = process ? process->GetABI().get() : nullptr;
8035ffd83dbSDimitry Andric   if (abi) {
8045ffd83dbSDimitry Andric     arch_default_unwind_plan_sp =
8055ffd83dbSDimitry Andric         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
8065ffd83dbSDimitry Andric     abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
8075ffd83dbSDimitry Andric   } else {
8085ffd83dbSDimitry Andric     UnwindLogMsg(
8095ffd83dbSDimitry Andric         "unable to get architectural default UnwindPlan from ABI plugin");
8105ffd83dbSDimitry Andric   }
8115ffd83dbSDimitry Andric 
8125ffd83dbSDimitry Andric   if (IsFrameZero() || GetNextFrame()->m_frame_type == eTrapHandlerFrame ||
8135ffd83dbSDimitry Andric       GetNextFrame()->m_frame_type == eDebuggerFrame) {
814fe6060f1SDimitry Andric     m_behaves_like_zeroth_frame = true;
8155ffd83dbSDimitry Andric     // If this frame behaves like a 0th frame (currently executing or
8165ffd83dbSDimitry Andric     // interrupted asynchronously), all registers can be retrieved.
8175ffd83dbSDimitry Andric     m_all_registers_available = true;
8185ffd83dbSDimitry Andric   }
8195ffd83dbSDimitry Andric 
8205ffd83dbSDimitry Andric   // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer)
8215ffd83dbSDimitry Andric   // so the pc is 0x0 in the zeroth frame, we need to use the "unwind at first
8225ffd83dbSDimitry Andric   // instruction" arch default UnwindPlan Also, if this Process can report on
8235ffd83dbSDimitry Andric   // memory region attributes, any non-executable region means we jumped
8245ffd83dbSDimitry Andric   // through a bad function pointer - handle the same way as 0x0. Note, if we
8255ffd83dbSDimitry Andric   // have a symbol context & a symbol, we don't want to follow this code path.
8265ffd83dbSDimitry Andric   // This is for jumping to memory regions without any information available.
8275ffd83dbSDimitry Andric 
8285ffd83dbSDimitry Andric   if ((!m_sym_ctx_valid ||
8295ffd83dbSDimitry Andric        (m_sym_ctx.function == nullptr && m_sym_ctx.symbol == nullptr)) &&
830fe6060f1SDimitry Andric       m_behaves_like_zeroth_frame && m_current_pc.IsValid()) {
8315ffd83dbSDimitry Andric     uint32_t permissions;
8325ffd83dbSDimitry Andric     addr_t current_pc_addr =
8335ffd83dbSDimitry Andric         m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr());
8345ffd83dbSDimitry Andric     if (current_pc_addr == 0 ||
8355ffd83dbSDimitry Andric         (process &&
8365ffd83dbSDimitry Andric          process->GetLoadAddressPermissions(current_pc_addr, permissions) &&
8375ffd83dbSDimitry Andric          (permissions & ePermissionsExecutable) == 0)) {
8385ffd83dbSDimitry Andric       if (abi) {
8395ffd83dbSDimitry Andric         unwind_plan_sp =
8405ffd83dbSDimitry Andric             std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
8415ffd83dbSDimitry Andric         abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
8425ffd83dbSDimitry Andric         m_frame_type = eNormalFrame;
8435ffd83dbSDimitry Andric         return unwind_plan_sp;
8445ffd83dbSDimitry Andric       }
8455ffd83dbSDimitry Andric     }
8465ffd83dbSDimitry Andric   }
8475ffd83dbSDimitry Andric 
8485ffd83dbSDimitry Andric   // No Module for the current pc, try using the architecture default unwind.
8495ffd83dbSDimitry Andric   ModuleSP pc_module_sp(m_current_pc.GetModule());
8505ffd83dbSDimitry Andric   if (!m_current_pc.IsValid() || !pc_module_sp ||
8515ffd83dbSDimitry Andric       pc_module_sp->GetObjectFile() == nullptr) {
8525ffd83dbSDimitry Andric     m_frame_type = eNormalFrame;
8535ffd83dbSDimitry Andric     return arch_default_unwind_plan_sp;
8545ffd83dbSDimitry Andric   }
8555ffd83dbSDimitry Andric 
8565ffd83dbSDimitry Andric   FuncUnwindersSP func_unwinders_sp;
8575ffd83dbSDimitry Andric   if (m_sym_ctx_valid) {
8585ffd83dbSDimitry Andric     func_unwinders_sp =
8595ffd83dbSDimitry Andric         pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress(
8605ffd83dbSDimitry Andric             m_current_pc, m_sym_ctx);
8615ffd83dbSDimitry Andric   }
8625ffd83dbSDimitry Andric 
8635ffd83dbSDimitry Andric   // No FuncUnwinders available for this pc (stripped function symbols, lldb
8645ffd83dbSDimitry Andric   // could not augment its function table with another source, like
8655ffd83dbSDimitry Andric   // LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). See if eh_frame or the
8665ffd83dbSDimitry Andric   // .ARM.exidx tables have unwind information for this address, else fall back
8675ffd83dbSDimitry Andric   // to the architectural default unwind.
8685ffd83dbSDimitry Andric   if (!func_unwinders_sp) {
8695ffd83dbSDimitry Andric     m_frame_type = eNormalFrame;
8705ffd83dbSDimitry Andric 
8715ffd83dbSDimitry Andric     if (!pc_module_sp || !pc_module_sp->GetObjectFile() ||
8725ffd83dbSDimitry Andric         !m_current_pc.IsValid())
8735ffd83dbSDimitry Andric       return arch_default_unwind_plan_sp;
8745ffd83dbSDimitry Andric 
8755ffd83dbSDimitry Andric     // Even with -fomit-frame-pointer, we can try eh_frame to get back on
8765ffd83dbSDimitry Andric     // track.
8775ffd83dbSDimitry Andric     DWARFCallFrameInfo *eh_frame =
8785ffd83dbSDimitry Andric         pc_module_sp->GetUnwindTable().GetEHFrameInfo();
8795ffd83dbSDimitry Andric     if (eh_frame) {
8805ffd83dbSDimitry Andric       unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
8815ffd83dbSDimitry Andric       if (eh_frame->GetUnwindPlan(m_current_pc, *unwind_plan_sp))
8825ffd83dbSDimitry Andric         return unwind_plan_sp;
8835ffd83dbSDimitry Andric       else
8845ffd83dbSDimitry Andric         unwind_plan_sp.reset();
8855ffd83dbSDimitry Andric     }
8865ffd83dbSDimitry Andric 
8875ffd83dbSDimitry Andric     ArmUnwindInfo *arm_exidx =
8885ffd83dbSDimitry Andric         pc_module_sp->GetUnwindTable().GetArmUnwindInfo();
8895ffd83dbSDimitry Andric     if (arm_exidx) {
8905ffd83dbSDimitry Andric       unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
8915ffd83dbSDimitry Andric       if (arm_exidx->GetUnwindPlan(exe_ctx.GetTargetRef(), m_current_pc,
8925ffd83dbSDimitry Andric                                    *unwind_plan_sp))
8935ffd83dbSDimitry Andric         return unwind_plan_sp;
8945ffd83dbSDimitry Andric       else
8955ffd83dbSDimitry Andric         unwind_plan_sp.reset();
8965ffd83dbSDimitry Andric     }
8975ffd83dbSDimitry Andric 
8985ffd83dbSDimitry Andric     CallFrameInfo *object_file_unwind =
8995ffd83dbSDimitry Andric         pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo();
9005ffd83dbSDimitry Andric     if (object_file_unwind) {
9015ffd83dbSDimitry Andric       unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
9025ffd83dbSDimitry Andric       if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp))
9035ffd83dbSDimitry Andric         return unwind_plan_sp;
9045ffd83dbSDimitry Andric       else
9055ffd83dbSDimitry Andric         unwind_plan_sp.reset();
9065ffd83dbSDimitry Andric     }
9075ffd83dbSDimitry Andric 
9085ffd83dbSDimitry Andric     return arch_default_unwind_plan_sp;
9095ffd83dbSDimitry Andric   }
9105ffd83dbSDimitry Andric 
9115ffd83dbSDimitry Andric   if (m_frame_type == eTrapHandlerFrame && process) {
9125ffd83dbSDimitry Andric     m_fast_unwind_plan_sp.reset();
913349cc55cSDimitry Andric 
914349cc55cSDimitry Andric     // On some platforms the unwind information for signal handlers is not
915349cc55cSDimitry Andric     // present or correct. Give the platform plugins a chance to provide
916349cc55cSDimitry Andric     // substitute plan. Otherwise, use eh_frame.
917349cc55cSDimitry Andric     if (m_sym_ctx_valid) {
918349cc55cSDimitry Andric       lldb::PlatformSP platform = process->GetTarget().GetPlatform();
919349cc55cSDimitry Andric       unwind_plan_sp = platform->GetTrapHandlerUnwindPlan(
920349cc55cSDimitry Andric           process->GetTarget().GetArchitecture().GetTriple(),
921349cc55cSDimitry Andric           GetSymbolOrFunctionName(m_sym_ctx));
922349cc55cSDimitry Andric 
923349cc55cSDimitry Andric       if (unwind_plan_sp)
924349cc55cSDimitry Andric         return unwind_plan_sp;
925349cc55cSDimitry Andric     }
926349cc55cSDimitry Andric 
9275ffd83dbSDimitry Andric     unwind_plan_sp =
9285ffd83dbSDimitry Andric         func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget());
9295ffd83dbSDimitry Andric     if (!unwind_plan_sp)
9305ffd83dbSDimitry Andric       unwind_plan_sp =
9315ffd83dbSDimitry Andric           func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget());
9325ffd83dbSDimitry Andric     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) &&
9335ffd83dbSDimitry Andric         unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) {
9345ffd83dbSDimitry Andric       return unwind_plan_sp;
9355ffd83dbSDimitry Andric     }
9365ffd83dbSDimitry Andric   }
9375ffd83dbSDimitry Andric 
9385ffd83dbSDimitry Andric   // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame
9395ffd83dbSDimitry Andric   // even when it's frame zero This comes up if we have hand-written functions
9405ffd83dbSDimitry Andric   // in a Module and hand-written eh_frame.  The assembly instruction
9415ffd83dbSDimitry Andric   // inspection may fail and the eh_frame CFI were probably written with some
9425ffd83dbSDimitry Andric   // care to do the right thing.  It'd be nice if there was a way to ask the
9435ffd83dbSDimitry Andric   // eh_frame directly if it is asynchronous (can be trusted at every
9445ffd83dbSDimitry Andric   // instruction point) or synchronous (the normal case - only at call sites).
9455ffd83dbSDimitry Andric   // But there is not.
9465ffd83dbSDimitry Andric   if (process && process->GetDynamicLoader() &&
9475ffd83dbSDimitry Andric       process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) {
9485ffd83dbSDimitry Andric     // We must specifically call the GetEHFrameUnwindPlan() method here --
9495ffd83dbSDimitry Andric     // normally we would call GetUnwindPlanAtCallSite() -- because CallSite may
9505ffd83dbSDimitry Andric     // return an unwind plan sourced from either eh_frame (that's what we
9515ffd83dbSDimitry Andric     // intend) or compact unwind (this won't work)
9525ffd83dbSDimitry Andric     unwind_plan_sp =
9535ffd83dbSDimitry Andric         func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget());
9545ffd83dbSDimitry Andric     if (!unwind_plan_sp)
9555ffd83dbSDimitry Andric       unwind_plan_sp =
9565ffd83dbSDimitry Andric           func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget());
9575ffd83dbSDimitry Andric     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
9585ffd83dbSDimitry Andric       UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the "
9595ffd83dbSDimitry Andric                           "DynamicLoader suggested we prefer it",
9605ffd83dbSDimitry Andric                           unwind_plan_sp->GetSourceName().GetCString());
9615ffd83dbSDimitry Andric       return unwind_plan_sp;
9625ffd83dbSDimitry Andric     }
9635ffd83dbSDimitry Andric   }
9645ffd83dbSDimitry Andric 
9655ffd83dbSDimitry Andric   // Typically the NonCallSite UnwindPlan is the unwind created by inspecting
9665ffd83dbSDimitry Andric   // the assembly language instructions
967fe6060f1SDimitry Andric   if (m_behaves_like_zeroth_frame && process) {
9685ffd83dbSDimitry Andric     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
9695ffd83dbSDimitry Andric         process->GetTarget(), m_thread);
9705ffd83dbSDimitry Andric     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
9715ffd83dbSDimitry Andric       if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
9725ffd83dbSDimitry Andric         // We probably have an UnwindPlan created by inspecting assembly
9735ffd83dbSDimitry Andric         // instructions. The assembly profilers work really well with compiler-
9745ffd83dbSDimitry Andric         // generated functions but hand- written assembly can be problematic.
9755ffd83dbSDimitry Andric         // We set the eh_frame based unwind plan as our fallback unwind plan if
9765ffd83dbSDimitry Andric         // instruction emulation doesn't work out even for non call sites if it
9775ffd83dbSDimitry Andric         // is available and use the architecture default unwind plan if it is
9785ffd83dbSDimitry Andric         // not available. The eh_frame unwind plan is more reliable even on non
9795ffd83dbSDimitry Andric         // call sites then the architecture default plan and for hand written
9805ffd83dbSDimitry Andric         // assembly code it is often written in a way that it valid at all
9815ffd83dbSDimitry Andric         // location what helps in the most common cases when the instruction
9825ffd83dbSDimitry Andric         // emulation fails.
9835ffd83dbSDimitry Andric         UnwindPlanSP call_site_unwind_plan =
9845ffd83dbSDimitry Andric             func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(),
9855ffd83dbSDimitry Andric                                                        m_thread);
9865ffd83dbSDimitry Andric         if (call_site_unwind_plan &&
9875ffd83dbSDimitry Andric             call_site_unwind_plan.get() != unwind_plan_sp.get() &&
9885ffd83dbSDimitry Andric             call_site_unwind_plan->GetSourceName() !=
9895ffd83dbSDimitry Andric                 unwind_plan_sp->GetSourceName()) {
9905ffd83dbSDimitry Andric           m_fallback_unwind_plan_sp = call_site_unwind_plan;
9915ffd83dbSDimitry Andric         } else {
9925ffd83dbSDimitry Andric           m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp;
9935ffd83dbSDimitry Andric         }
9945ffd83dbSDimitry Andric       }
9955ffd83dbSDimitry Andric       UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this "
9965ffd83dbSDimitry Andric                           "is the non-call site unwind plan and this is a "
9975ffd83dbSDimitry Andric                           "zeroth frame",
9985ffd83dbSDimitry Andric                           unwind_plan_sp->GetSourceName().GetCString());
9995ffd83dbSDimitry Andric       return unwind_plan_sp;
10005ffd83dbSDimitry Andric     }
10015ffd83dbSDimitry Andric 
10025ffd83dbSDimitry Andric     // If we're on the first instruction of a function, and we have an
10035ffd83dbSDimitry Andric     // architectural default UnwindPlan for the initial instruction of a
10045ffd83dbSDimitry Andric     // function, use that.
10055ffd83dbSDimitry Andric     if (m_current_offset == 0) {
10065ffd83dbSDimitry Andric       unwind_plan_sp =
10075ffd83dbSDimitry Andric           func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry(
10085ffd83dbSDimitry Andric               m_thread);
10095ffd83dbSDimitry Andric       if (unwind_plan_sp) {
10105ffd83dbSDimitry Andric         UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we are at "
10115ffd83dbSDimitry Andric                             "the first instruction of a function",
10125ffd83dbSDimitry Andric                             unwind_plan_sp->GetSourceName().GetCString());
10135ffd83dbSDimitry Andric         return unwind_plan_sp;
10145ffd83dbSDimitry Andric       }
10155ffd83dbSDimitry Andric     }
10165ffd83dbSDimitry Andric   }
10175ffd83dbSDimitry Andric 
10185ffd83dbSDimitry Andric   // Typically this is unwind info from an eh_frame section intended for
10195ffd83dbSDimitry Andric   // exception handling; only valid at call sites
10205ffd83dbSDimitry Andric   if (process) {
10215ffd83dbSDimitry Andric     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite(
10225ffd83dbSDimitry Andric         process->GetTarget(), m_thread);
10235ffd83dbSDimitry Andric   }
102481ad6265SDimitry Andric   if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) {
10255ffd83dbSDimitry Andric     UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this "
10265ffd83dbSDimitry Andric                         "is the call-site unwind plan",
10275ffd83dbSDimitry Andric                         unwind_plan_sp->GetSourceName().GetCString());
10285ffd83dbSDimitry Andric     return unwind_plan_sp;
10295ffd83dbSDimitry Andric   }
10305ffd83dbSDimitry Andric 
10315ffd83dbSDimitry Andric   // We'd prefer to use an UnwindPlan intended for call sites when we're at a
10325ffd83dbSDimitry Andric   // call site but if we've struck out on that, fall back to using the non-
10335ffd83dbSDimitry Andric   // call-site assembly inspection UnwindPlan if possible.
10345ffd83dbSDimitry Andric   if (process) {
10355ffd83dbSDimitry Andric     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
10365ffd83dbSDimitry Andric         process->GetTarget(), m_thread);
10375ffd83dbSDimitry Andric   }
10385ffd83dbSDimitry Andric   if (unwind_plan_sp &&
10395ffd83dbSDimitry Andric       unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
10405ffd83dbSDimitry Andric     // We probably have an UnwindPlan created by inspecting assembly
10415ffd83dbSDimitry Andric     // instructions. The assembly profilers work really well with compiler-
10425ffd83dbSDimitry Andric     // generated functions but hand- written assembly can be problematic. We
10435ffd83dbSDimitry Andric     // set the eh_frame based unwind plan as our fallback unwind plan if
10445ffd83dbSDimitry Andric     // instruction emulation doesn't work out even for non call sites if it is
10455ffd83dbSDimitry Andric     // available and use the architecture default unwind plan if it is not
10465ffd83dbSDimitry Andric     // available. The eh_frame unwind plan is more reliable even on non call
10475ffd83dbSDimitry Andric     // sites then the architecture default plan and for hand written assembly
10485ffd83dbSDimitry Andric     // code it is often written in a way that it valid at all location what
10495ffd83dbSDimitry Andric     // helps in the most common cases when the instruction emulation fails.
10505ffd83dbSDimitry Andric     UnwindPlanSP call_site_unwind_plan =
10515ffd83dbSDimitry Andric         func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(),
10525ffd83dbSDimitry Andric                                                    m_thread);
10535ffd83dbSDimitry Andric     if (call_site_unwind_plan &&
10545ffd83dbSDimitry Andric         call_site_unwind_plan.get() != unwind_plan_sp.get() &&
10555ffd83dbSDimitry Andric         call_site_unwind_plan->GetSourceName() !=
10565ffd83dbSDimitry Andric             unwind_plan_sp->GetSourceName()) {
10575ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp = call_site_unwind_plan;
10585ffd83dbSDimitry Andric     } else {
10595ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp;
10605ffd83dbSDimitry Andric     }
10615ffd83dbSDimitry Andric   }
10625ffd83dbSDimitry Andric 
106381ad6265SDimitry Andric   if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) {
10645ffd83dbSDimitry Andric     UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we "
10655ffd83dbSDimitry Andric                         "failed to find a call-site unwind plan that would work",
10665ffd83dbSDimitry Andric                         unwind_plan_sp->GetSourceName().GetCString());
10675ffd83dbSDimitry Andric     return unwind_plan_sp;
10685ffd83dbSDimitry Andric   }
10695ffd83dbSDimitry Andric 
10705ffd83dbSDimitry Andric   // If nothing else, use the architectural default UnwindPlan and hope that
10715ffd83dbSDimitry Andric   // does the job.
10725ffd83dbSDimitry Andric   if (arch_default_unwind_plan_sp)
10735ffd83dbSDimitry Andric     UnwindLogMsgVerbose(
10745ffd83dbSDimitry Andric         "frame uses %s for full UnwindPlan because we are falling back "
10755ffd83dbSDimitry Andric         "to the arch default plan",
10765ffd83dbSDimitry Andric         arch_default_unwind_plan_sp->GetSourceName().GetCString());
10775ffd83dbSDimitry Andric   else
10785ffd83dbSDimitry Andric     UnwindLogMsg(
10795ffd83dbSDimitry Andric         "Unable to find any UnwindPlan for full unwind of this frame.");
10805ffd83dbSDimitry Andric 
10815ffd83dbSDimitry Andric   return arch_default_unwind_plan_sp;
10825ffd83dbSDimitry Andric }
10835ffd83dbSDimitry Andric 
10845ffd83dbSDimitry Andric void RegisterContextUnwind::InvalidateAllRegisters() {
10855ffd83dbSDimitry Andric   m_frame_type = eNotAValidFrame;
10865ffd83dbSDimitry Andric }
10875ffd83dbSDimitry Andric 
10885ffd83dbSDimitry Andric size_t RegisterContextUnwind::GetRegisterCount() {
10895ffd83dbSDimitry Andric   return m_thread.GetRegisterContext()->GetRegisterCount();
10905ffd83dbSDimitry Andric }
10915ffd83dbSDimitry Andric 
10925ffd83dbSDimitry Andric const RegisterInfo *RegisterContextUnwind::GetRegisterInfoAtIndex(size_t reg) {
10935ffd83dbSDimitry Andric   return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
10945ffd83dbSDimitry Andric }
10955ffd83dbSDimitry Andric 
10965ffd83dbSDimitry Andric size_t RegisterContextUnwind::GetRegisterSetCount() {
10975ffd83dbSDimitry Andric   return m_thread.GetRegisterContext()->GetRegisterSetCount();
10985ffd83dbSDimitry Andric }
10995ffd83dbSDimitry Andric 
11005ffd83dbSDimitry Andric const RegisterSet *RegisterContextUnwind::GetRegisterSet(size_t reg_set) {
11015ffd83dbSDimitry Andric   return m_thread.GetRegisterContext()->GetRegisterSet(reg_set);
11025ffd83dbSDimitry Andric }
11035ffd83dbSDimitry Andric 
11045ffd83dbSDimitry Andric uint32_t RegisterContextUnwind::ConvertRegisterKindToRegisterNumber(
11055ffd83dbSDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
11065ffd83dbSDimitry Andric   return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
11075ffd83dbSDimitry Andric       kind, num);
11085ffd83dbSDimitry Andric }
11095ffd83dbSDimitry Andric 
11105ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadRegisterValueFromRegisterLocation(
11115ffd83dbSDimitry Andric     lldb_private::UnwindLLDB::RegisterLocation regloc,
11125ffd83dbSDimitry Andric     const RegisterInfo *reg_info, RegisterValue &value) {
11135ffd83dbSDimitry Andric   if (!IsValid())
11145ffd83dbSDimitry Andric     return false;
11155ffd83dbSDimitry Andric   bool success = false;
11165ffd83dbSDimitry Andric 
11175ffd83dbSDimitry Andric   switch (regloc.type) {
11185ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: {
11195ffd83dbSDimitry Andric     const RegisterInfo *other_reg_info =
11205ffd83dbSDimitry Andric         GetRegisterInfoAtIndex(regloc.location.register_number);
11215ffd83dbSDimitry Andric 
11225ffd83dbSDimitry Andric     if (!other_reg_info)
11235ffd83dbSDimitry Andric       return false;
11245ffd83dbSDimitry Andric 
11255ffd83dbSDimitry Andric     success =
11265ffd83dbSDimitry Andric         m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value);
11275ffd83dbSDimitry Andric   } break;
11285ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterInRegister: {
11295ffd83dbSDimitry Andric     const RegisterInfo *other_reg_info =
11305ffd83dbSDimitry Andric         GetRegisterInfoAtIndex(regloc.location.register_number);
11315ffd83dbSDimitry Andric 
11325ffd83dbSDimitry Andric     if (!other_reg_info)
11335ffd83dbSDimitry Andric       return false;
11345ffd83dbSDimitry Andric 
11355ffd83dbSDimitry Andric     if (IsFrameZero()) {
11365ffd83dbSDimitry Andric       success =
11375ffd83dbSDimitry Andric           m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value);
11385ffd83dbSDimitry Andric     } else {
11395ffd83dbSDimitry Andric       success = GetNextFrame()->ReadRegister(other_reg_info, value);
11405ffd83dbSDimitry Andric     }
11415ffd83dbSDimitry Andric   } break;
11425ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
11435ffd83dbSDimitry Andric     success =
11445ffd83dbSDimitry Andric         value.SetUInt(regloc.location.inferred_value, reg_info->byte_size);
11455ffd83dbSDimitry Andric     break;
11465ffd83dbSDimitry Andric 
11475ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
11485ffd83dbSDimitry Andric     break;
11495ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
11505ffd83dbSDimitry Andric     llvm_unreachable("FIXME debugger inferior function call unwind");
11515ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: {
11525ffd83dbSDimitry Andric     Status error(ReadRegisterValueFromMemory(
11535ffd83dbSDimitry Andric         reg_info, regloc.location.target_memory_location, reg_info->byte_size,
11545ffd83dbSDimitry Andric         value));
11555ffd83dbSDimitry Andric     success = error.Success();
11565ffd83dbSDimitry Andric   } break;
11575ffd83dbSDimitry Andric   default:
11585ffd83dbSDimitry Andric     llvm_unreachable("Unknown RegisterLocation type.");
11595ffd83dbSDimitry Andric   }
11605ffd83dbSDimitry Andric   return success;
11615ffd83dbSDimitry Andric }
11625ffd83dbSDimitry Andric 
11635ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteRegisterValueToRegisterLocation(
11645ffd83dbSDimitry Andric     lldb_private::UnwindLLDB::RegisterLocation regloc,
11655ffd83dbSDimitry Andric     const RegisterInfo *reg_info, const RegisterValue &value) {
11665ffd83dbSDimitry Andric   if (!IsValid())
11675ffd83dbSDimitry Andric     return false;
11685ffd83dbSDimitry Andric 
11695ffd83dbSDimitry Andric   bool success = false;
11705ffd83dbSDimitry Andric 
11715ffd83dbSDimitry Andric   switch (regloc.type) {
11725ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: {
11735ffd83dbSDimitry Andric     const RegisterInfo *other_reg_info =
11745ffd83dbSDimitry Andric         GetRegisterInfoAtIndex(regloc.location.register_number);
11755ffd83dbSDimitry Andric     success =
11765ffd83dbSDimitry Andric         m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value);
11775ffd83dbSDimitry Andric   } break;
11785ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterInRegister: {
11795ffd83dbSDimitry Andric     const RegisterInfo *other_reg_info =
11805ffd83dbSDimitry Andric         GetRegisterInfoAtIndex(regloc.location.register_number);
11815ffd83dbSDimitry Andric     if (IsFrameZero()) {
11825ffd83dbSDimitry Andric       success =
11835ffd83dbSDimitry Andric           m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value);
11845ffd83dbSDimitry Andric     } else {
11855ffd83dbSDimitry Andric       success = GetNextFrame()->WriteRegister(other_reg_info, value);
11865ffd83dbSDimitry Andric     }
11875ffd83dbSDimitry Andric   } break;
11885ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
11895ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
11905ffd83dbSDimitry Andric     break;
11915ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
11925ffd83dbSDimitry Andric     llvm_unreachable("FIXME debugger inferior function call unwind");
11935ffd83dbSDimitry Andric   case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: {
11945ffd83dbSDimitry Andric     Status error(WriteRegisterValueToMemory(
11955ffd83dbSDimitry Andric         reg_info, regloc.location.target_memory_location, reg_info->byte_size,
11965ffd83dbSDimitry Andric         value));
11975ffd83dbSDimitry Andric     success = error.Success();
11985ffd83dbSDimitry Andric   } break;
11995ffd83dbSDimitry Andric   default:
12005ffd83dbSDimitry Andric     llvm_unreachable("Unknown RegisterLocation type.");
12015ffd83dbSDimitry Andric   }
12025ffd83dbSDimitry Andric   return success;
12035ffd83dbSDimitry Andric }
12045ffd83dbSDimitry Andric 
12055ffd83dbSDimitry Andric bool RegisterContextUnwind::IsValid() const {
12065ffd83dbSDimitry Andric   return m_frame_type != eNotAValidFrame;
12075ffd83dbSDimitry Andric }
12085ffd83dbSDimitry Andric 
12095ffd83dbSDimitry Andric // After the final stack frame in a stack walk we'll get one invalid
12105ffd83dbSDimitry Andric // (eNotAValidFrame) stack frame -- one past the end of the stack walk.  But
12115ffd83dbSDimitry Andric // higher-level code will need to tell the difference between "the unwind plan
12125ffd83dbSDimitry Andric // below this frame failed" versus "we successfully completed the stack walk"
12135ffd83dbSDimitry Andric // so this method helps to disambiguate that.
12145ffd83dbSDimitry Andric 
12155ffd83dbSDimitry Andric bool RegisterContextUnwind::IsTrapHandlerFrame() const {
12165ffd83dbSDimitry Andric   return m_frame_type == eTrapHandlerFrame;
12175ffd83dbSDimitry Andric }
12185ffd83dbSDimitry Andric 
12195ffd83dbSDimitry Andric // A skip frame is a bogus frame on the stack -- but one where we're likely to
12205ffd83dbSDimitry Andric // find a real frame farther
12215ffd83dbSDimitry Andric // up the stack if we keep looking.  It's always the second frame in an unwind
12225ffd83dbSDimitry Andric // (i.e. the first frame after frame zero) where unwinding can be the
12235ffd83dbSDimitry Andric // trickiest.  Ideally we'll mark up this frame in some way so the user knows
12245ffd83dbSDimitry Andric // we're displaying bad data and we may have skipped one frame of their real
12255ffd83dbSDimitry Andric // program in the process of getting back on track.
12265ffd83dbSDimitry Andric 
12275ffd83dbSDimitry Andric bool RegisterContextUnwind::IsSkipFrame() const {
12285ffd83dbSDimitry Andric   return m_frame_type == eSkipFrame;
12295ffd83dbSDimitry Andric }
12305ffd83dbSDimitry Andric 
12315ffd83dbSDimitry Andric bool RegisterContextUnwind::IsTrapHandlerSymbol(
12325ffd83dbSDimitry Andric     lldb_private::Process *process,
12335ffd83dbSDimitry Andric     const lldb_private::SymbolContext &m_sym_ctx) const {
12345ffd83dbSDimitry Andric   PlatformSP platform_sp(process->GetTarget().GetPlatform());
12355ffd83dbSDimitry Andric   if (platform_sp) {
12365ffd83dbSDimitry Andric     const std::vector<ConstString> trap_handler_names(
12375ffd83dbSDimitry Andric         platform_sp->GetTrapHandlerSymbolNames());
12385ffd83dbSDimitry Andric     for (ConstString name : trap_handler_names) {
12395ffd83dbSDimitry Andric       if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
12405ffd83dbSDimitry Andric           (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) {
12415ffd83dbSDimitry Andric         return true;
12425ffd83dbSDimitry Andric       }
12435ffd83dbSDimitry Andric     }
12445ffd83dbSDimitry Andric   }
12455ffd83dbSDimitry Andric   const std::vector<ConstString> user_specified_trap_handler_names(
12465ffd83dbSDimitry Andric       m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames());
12475ffd83dbSDimitry Andric   for (ConstString name : user_specified_trap_handler_names) {
12485ffd83dbSDimitry Andric     if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
12495ffd83dbSDimitry Andric         (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) {
12505ffd83dbSDimitry Andric       return true;
12515ffd83dbSDimitry Andric     }
12525ffd83dbSDimitry Andric   }
12535ffd83dbSDimitry Andric 
12545ffd83dbSDimitry Andric   return false;
12555ffd83dbSDimitry Andric }
12565ffd83dbSDimitry Andric 
12575ffd83dbSDimitry Andric // Answer the question: Where did THIS frame save the CALLER frame ("previous"
12585ffd83dbSDimitry Andric // frame)'s register value?
12595ffd83dbSDimitry Andric 
12605ffd83dbSDimitry Andric enum UnwindLLDB::RegisterSearchResult
12615ffd83dbSDimitry Andric RegisterContextUnwind::SavedLocationForRegister(
12625ffd83dbSDimitry Andric     uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc) {
12635ffd83dbSDimitry Andric   RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum);
126481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Unwind);
12655ffd83dbSDimitry Andric 
12665ffd83dbSDimitry Andric   // Have we already found this register location?
12675ffd83dbSDimitry Andric   if (!m_registers.empty()) {
12685ffd83dbSDimitry Andric     std::map<uint32_t,
12695ffd83dbSDimitry Andric              lldb_private::UnwindLLDB::RegisterLocation>::const_iterator
12705ffd83dbSDimitry Andric         iterator;
12715ffd83dbSDimitry Andric     iterator = m_registers.find(regnum.GetAsKind(eRegisterKindLLDB));
12725ffd83dbSDimitry Andric     if (iterator != m_registers.end()) {
12735ffd83dbSDimitry Andric       regloc = iterator->second;
12745ffd83dbSDimitry Andric       UnwindLogMsg("supplying caller's saved %s (%d)'s location, cached",
12755ffd83dbSDimitry Andric                    regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
12765ffd83dbSDimitry Andric       return UnwindLLDB::RegisterSearchResult::eRegisterFound;
12775ffd83dbSDimitry Andric     }
12785ffd83dbSDimitry Andric   }
12795ffd83dbSDimitry Andric 
12805ffd83dbSDimitry Andric   // Look through the available UnwindPlans for the register location.
12815ffd83dbSDimitry Andric 
12825ffd83dbSDimitry Andric   UnwindPlan::Row::RegisterLocation unwindplan_regloc;
12835ffd83dbSDimitry Andric   bool have_unwindplan_regloc = false;
12845ffd83dbSDimitry Andric   RegisterKind unwindplan_registerkind = kNumRegisterKinds;
12855ffd83dbSDimitry Andric 
12865ffd83dbSDimitry Andric   if (m_fast_unwind_plan_sp) {
12875ffd83dbSDimitry Andric     UnwindPlan::RowSP active_row =
12885ffd83dbSDimitry Andric         m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
12895ffd83dbSDimitry Andric     unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind();
12905ffd83dbSDimitry Andric     if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) {
12915ffd83dbSDimitry Andric       UnwindLogMsg("could not convert lldb regnum %s (%d) into %d RegisterKind "
12925ffd83dbSDimitry Andric                    "reg numbering scheme",
12935ffd83dbSDimitry Andric                    regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
12945ffd83dbSDimitry Andric                    (int)unwindplan_registerkind);
12955ffd83dbSDimitry Andric       return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
12965ffd83dbSDimitry Andric     }
1297fe6060f1SDimitry Andric     // The architecture default unwind plan marks unknown registers as
1298fe6060f1SDimitry Andric     // Undefined so that we don't forward them up the stack when a
1299fe6060f1SDimitry Andric     // jitted stack frame may have overwritten them.  But when the
1300fe6060f1SDimitry Andric     // arch default unwind plan is used as the Fast Unwind Plan, we
1301fe6060f1SDimitry Andric     // need to recognize this & switch over to the Full Unwind Plan
1302fe6060f1SDimitry Andric     // to see what unwind rule that (more knoweldgeable, probably)
1303fe6060f1SDimitry Andric     // UnwindPlan has.  If the full UnwindPlan says the register
1304fe6060f1SDimitry Andric     // location is Undefined, then it really is.
13055ffd83dbSDimitry Andric     if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
1306fe6060f1SDimitry Andric                                     unwindplan_regloc) &&
1307fe6060f1SDimitry Andric         !unwindplan_regloc.IsUndefined()) {
13085ffd83dbSDimitry Andric       UnwindLogMsg(
13095ffd83dbSDimitry Andric           "supplying caller's saved %s (%d)'s location using FastUnwindPlan",
13105ffd83dbSDimitry Andric           regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
13115ffd83dbSDimitry Andric       have_unwindplan_regloc = true;
13125ffd83dbSDimitry Andric     }
13135ffd83dbSDimitry Andric   }
13145ffd83dbSDimitry Andric 
13155ffd83dbSDimitry Andric   if (!have_unwindplan_regloc) {
13165ffd83dbSDimitry Andric     // m_full_unwind_plan_sp being NULL means that we haven't tried to find a
13175ffd83dbSDimitry Andric     // full UnwindPlan yet
1318fe6060f1SDimitry Andric     bool got_new_full_unwindplan = false;
1319fe6060f1SDimitry Andric     if (!m_full_unwind_plan_sp) {
13205ffd83dbSDimitry Andric       m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
1321fe6060f1SDimitry Andric       got_new_full_unwindplan = true;
1322fe6060f1SDimitry Andric     }
13235ffd83dbSDimitry Andric 
13245ffd83dbSDimitry Andric     if (m_full_unwind_plan_sp) {
13255ffd83dbSDimitry Andric       RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
13265ffd83dbSDimitry Andric                                LLDB_REGNUM_GENERIC_PC);
13275ffd83dbSDimitry Andric 
13285ffd83dbSDimitry Andric       UnwindPlan::RowSP active_row =
132981ad6265SDimitry Andric           m_full_unwind_plan_sp->GetRowForFunctionOffset(
133081ad6265SDimitry Andric               m_current_offset_backed_up_one);
13315ffd83dbSDimitry Andric       unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind();
13325ffd83dbSDimitry Andric 
1333fe6060f1SDimitry Andric       if (got_new_full_unwindplan && active_row.get() && log) {
1334fe6060f1SDimitry Andric         StreamString active_row_strm;
1335fe6060f1SDimitry Andric         ExecutionContext exe_ctx(m_thread.shared_from_this());
1336fe6060f1SDimitry Andric         active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
1337fe6060f1SDimitry Andric                          &m_thread,
1338fe6060f1SDimitry Andric                          m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
1339fe6060f1SDimitry Andric         UnwindLogMsg("Using full unwind plan '%s'",
1340fe6060f1SDimitry Andric                      m_full_unwind_plan_sp->GetSourceName().AsCString());
1341fe6060f1SDimitry Andric         UnwindLogMsg("active row: %s", active_row_strm.GetData());
1342fe6060f1SDimitry Andric       }
13435ffd83dbSDimitry Andric       RegisterNumber return_address_reg;
13445ffd83dbSDimitry Andric 
13455ffd83dbSDimitry Andric       // If we're fetching the saved pc and this UnwindPlan defines a
13465ffd83dbSDimitry Andric       // ReturnAddress register (e.g. lr on arm), look for the return address
13475ffd83dbSDimitry Andric       // register number in the UnwindPlan's row.
13485ffd83dbSDimitry Andric       if (pc_regnum.IsValid() && pc_regnum == regnum &&
13495ffd83dbSDimitry Andric           m_full_unwind_plan_sp->GetReturnAddressRegister() !=
13505ffd83dbSDimitry Andric               LLDB_INVALID_REGNUM) {
13515ffd83dbSDimitry Andric         // If this is a trap handler frame, we should have access to
13525ffd83dbSDimitry Andric         // the complete register context when the interrupt/async
13535ffd83dbSDimitry Andric         // signal was received, we should fetch the actual saved $pc
13545ffd83dbSDimitry Andric         // value instead of the Return Address register.
13555ffd83dbSDimitry Andric         // If $pc is not available, fall back to the RA reg.
13565ffd83dbSDimitry Andric         UnwindPlan::Row::RegisterLocation scratch;
13575ffd83dbSDimitry Andric         if (m_frame_type == eTrapHandlerFrame &&
13585ffd83dbSDimitry Andric             active_row->GetRegisterInfo
13595ffd83dbSDimitry Andric               (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
13605ffd83dbSDimitry Andric           UnwindLogMsg("Providing pc register instead of rewriting to "
13615ffd83dbSDimitry Andric                        "RA reg because this is a trap handler and there is "
13625ffd83dbSDimitry Andric                        "a location for the saved pc register value.");
13635ffd83dbSDimitry Andric         } else {
13645ffd83dbSDimitry Andric           return_address_reg.init(
13655ffd83dbSDimitry Andric               m_thread, m_full_unwind_plan_sp->GetRegisterKind(),
13665ffd83dbSDimitry Andric               m_full_unwind_plan_sp->GetReturnAddressRegister());
13675ffd83dbSDimitry Andric           regnum = return_address_reg;
13685ffd83dbSDimitry Andric           UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a "
13695ffd83dbSDimitry Andric                        "RA reg; getting %s (%d) instead",
13705ffd83dbSDimitry Andric                        return_address_reg.GetName(),
13715ffd83dbSDimitry Andric                        return_address_reg.GetAsKind(eRegisterKindLLDB));
13725ffd83dbSDimitry Andric         }
13735ffd83dbSDimitry Andric       } else {
13745ffd83dbSDimitry Andric         if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) {
13755ffd83dbSDimitry Andric           if (unwindplan_registerkind == eRegisterKindGeneric) {
13765ffd83dbSDimitry Andric             UnwindLogMsg("could not convert lldb regnum %s (%d) into "
13775ffd83dbSDimitry Andric                          "eRegisterKindGeneric reg numbering scheme",
13785ffd83dbSDimitry Andric                          regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
13795ffd83dbSDimitry Andric           } else {
13805ffd83dbSDimitry Andric             UnwindLogMsg("could not convert lldb regnum %s (%d) into %d "
13815ffd83dbSDimitry Andric                          "RegisterKind reg numbering scheme",
13825ffd83dbSDimitry Andric                          regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
13835ffd83dbSDimitry Andric                          (int)unwindplan_registerkind);
13845ffd83dbSDimitry Andric           }
13855ffd83dbSDimitry Andric           return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
13865ffd83dbSDimitry Andric         }
13875ffd83dbSDimitry Andric       }
13885ffd83dbSDimitry Andric 
13895ffd83dbSDimitry Andric       if (regnum.IsValid() &&
13905ffd83dbSDimitry Andric           active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
13915ffd83dbSDimitry Andric                                       unwindplan_regloc)) {
13925ffd83dbSDimitry Andric         have_unwindplan_regloc = true;
13935ffd83dbSDimitry Andric         UnwindLogMsg(
13945ffd83dbSDimitry Andric             "supplying caller's saved %s (%d)'s location using %s UnwindPlan",
13955ffd83dbSDimitry Andric             regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
13965ffd83dbSDimitry Andric             m_full_unwind_plan_sp->GetSourceName().GetCString());
13975ffd83dbSDimitry Andric       }
13985ffd83dbSDimitry Andric 
13995ffd83dbSDimitry Andric       // This is frame 0 and we're retrieving the PC and it's saved in a Return
14005ffd83dbSDimitry Andric       // Address register and it hasn't been saved anywhere yet -- that is,
14015ffd83dbSDimitry Andric       // it's still live in the actual register. Handle this specially.
14025ffd83dbSDimitry Andric 
14035ffd83dbSDimitry Andric       if (!have_unwindplan_regloc && return_address_reg.IsValid() &&
1404*0fca6ea1SDimitry Andric           BehavesLikeZerothFrame()) {
14055ffd83dbSDimitry Andric         if (return_address_reg.GetAsKind(eRegisterKindLLDB) !=
14065ffd83dbSDimitry Andric             LLDB_INVALID_REGNUM) {
14075ffd83dbSDimitry Andric           lldb_private::UnwindLLDB::RegisterLocation new_regloc;
14085ffd83dbSDimitry Andric           new_regloc.type =
14095ffd83dbSDimitry Andric               UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext;
14105ffd83dbSDimitry Andric           new_regloc.location.register_number =
14115ffd83dbSDimitry Andric               return_address_reg.GetAsKind(eRegisterKindLLDB);
14125ffd83dbSDimitry Andric           m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc;
14135ffd83dbSDimitry Andric           regloc = new_regloc;
14145ffd83dbSDimitry Andric           UnwindLogMsg("supplying caller's register %s (%d) from the live "
14155ffd83dbSDimitry Andric                        "RegisterContext at frame 0, saved in %d",
14165ffd83dbSDimitry Andric                        return_address_reg.GetName(),
14175ffd83dbSDimitry Andric                        return_address_reg.GetAsKind(eRegisterKindLLDB),
14185ffd83dbSDimitry Andric                        return_address_reg.GetAsKind(eRegisterKindLLDB));
14195ffd83dbSDimitry Andric           return UnwindLLDB::RegisterSearchResult::eRegisterFound;
14205ffd83dbSDimitry Andric         }
14215ffd83dbSDimitry Andric       }
14225ffd83dbSDimitry Andric 
14235ffd83dbSDimitry Andric       // If this architecture stores the return address in a register (it
14245ffd83dbSDimitry Andric       // defines a Return Address register) and we're on a non-zero stack frame
14255ffd83dbSDimitry Andric       // and the Full UnwindPlan says that the pc is stored in the
14265ffd83dbSDimitry Andric       // RA registers (e.g. lr on arm), then we know that the full unwindplan is
14275ffd83dbSDimitry Andric       // not trustworthy -- this
14285ffd83dbSDimitry Andric       // is an impossible situation and the instruction emulation code has
14295ffd83dbSDimitry Andric       // likely been misled. If this stack frame meets those criteria, we need
14305ffd83dbSDimitry Andric       // to throw away the Full UnwindPlan that the instruction emulation came
14315ffd83dbSDimitry Andric       // up with and fall back to the architecture's Default UnwindPlan so the
14325ffd83dbSDimitry Andric       // stack walk can get past this point.
14335ffd83dbSDimitry Andric 
14345ffd83dbSDimitry Andric       // Special note:  If the Full UnwindPlan was generated from the compiler,
14355ffd83dbSDimitry Andric       // don't second-guess it when we're at a call site location.
14365ffd83dbSDimitry Andric 
14375ffd83dbSDimitry Andric       // arch_default_ra_regnum is the return address register # in the Full
14385ffd83dbSDimitry Andric       // UnwindPlan register numbering
14395ffd83dbSDimitry Andric       RegisterNumber arch_default_ra_regnum(m_thread, eRegisterKindGeneric,
14405ffd83dbSDimitry Andric                                             LLDB_REGNUM_GENERIC_RA);
14415ffd83dbSDimitry Andric 
14425ffd83dbSDimitry Andric       if (arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) !=
14435ffd83dbSDimitry Andric               LLDB_INVALID_REGNUM &&
14445ffd83dbSDimitry Andric           pc_regnum == regnum && unwindplan_regloc.IsInOtherRegister() &&
14455ffd83dbSDimitry Andric           unwindplan_regloc.GetRegisterNumber() ==
14465ffd83dbSDimitry Andric               arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) &&
14475ffd83dbSDimitry Andric           m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes &&
14485ffd83dbSDimitry Andric           !m_all_registers_available) {
14495ffd83dbSDimitry Andric         UnwindLogMsg("%s UnwindPlan tried to restore the pc from the link "
14505ffd83dbSDimitry Andric                      "register but this is a non-zero frame",
14515ffd83dbSDimitry Andric                      m_full_unwind_plan_sp->GetSourceName().GetCString());
14525ffd83dbSDimitry Andric 
14535ffd83dbSDimitry Andric         // Throw away the full unwindplan; install the arch default unwindplan
14545ffd83dbSDimitry Andric         if (ForceSwitchToFallbackUnwindPlan()) {
14555ffd83dbSDimitry Andric           // Update for the possibly new unwind plan
14565ffd83dbSDimitry Andric           unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind();
14575ffd83dbSDimitry Andric           UnwindPlan::RowSP active_row =
14585ffd83dbSDimitry Andric               m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
14595ffd83dbSDimitry Andric 
14605ffd83dbSDimitry Andric           // Sanity check: Verify that we can fetch a pc value and CFA value
14615ffd83dbSDimitry Andric           // with this unwind plan
14625ffd83dbSDimitry Andric 
14635ffd83dbSDimitry Andric           RegisterNumber arch_default_pc_reg(m_thread, eRegisterKindGeneric,
14645ffd83dbSDimitry Andric                                              LLDB_REGNUM_GENERIC_PC);
14655ffd83dbSDimitry Andric           bool can_fetch_pc_value = false;
14665ffd83dbSDimitry Andric           bool can_fetch_cfa = false;
14675ffd83dbSDimitry Andric           addr_t cfa_value;
14685ffd83dbSDimitry Andric           if (active_row) {
14695ffd83dbSDimitry Andric             if (arch_default_pc_reg.GetAsKind(unwindplan_registerkind) !=
14705ffd83dbSDimitry Andric                     LLDB_INVALID_REGNUM &&
14715ffd83dbSDimitry Andric                 active_row->GetRegisterInfo(
14725ffd83dbSDimitry Andric                     arch_default_pc_reg.GetAsKind(unwindplan_registerkind),
14735ffd83dbSDimitry Andric                     unwindplan_regloc)) {
14745ffd83dbSDimitry Andric               can_fetch_pc_value = true;
14755ffd83dbSDimitry Andric             }
14765ffd83dbSDimitry Andric             if (ReadFrameAddress(unwindplan_registerkind,
14775ffd83dbSDimitry Andric                                  active_row->GetCFAValue(), cfa_value)) {
14785ffd83dbSDimitry Andric               can_fetch_cfa = true;
14795ffd83dbSDimitry Andric             }
14805ffd83dbSDimitry Andric           }
14815ffd83dbSDimitry Andric 
14825ffd83dbSDimitry Andric           have_unwindplan_regloc = can_fetch_pc_value && can_fetch_cfa;
14835ffd83dbSDimitry Andric         } else {
14845ffd83dbSDimitry Andric           // We were unable to fall back to another unwind plan
14855ffd83dbSDimitry Andric           have_unwindplan_regloc = false;
14865ffd83dbSDimitry Andric         }
14875ffd83dbSDimitry Andric       }
14885ffd83dbSDimitry Andric     }
14895ffd83dbSDimitry Andric   }
14905ffd83dbSDimitry Andric 
14915ffd83dbSDimitry Andric   ExecutionContext exe_ctx(m_thread.shared_from_this());
14925ffd83dbSDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
14935ffd83dbSDimitry Andric   if (!have_unwindplan_regloc) {
14945ffd83dbSDimitry Andric     // If the UnwindPlan failed to give us an unwind location for this
14955ffd83dbSDimitry Andric     // register, we may be able to fall back to some ABI-defined default.  For
14965ffd83dbSDimitry Andric     // example, some ABIs allow to determine the caller's SP via the CFA. Also,
14975ffd83dbSDimitry Andric     // the ABI may set volatile registers to the undefined state.
14985ffd83dbSDimitry Andric     ABI *abi = process ? process->GetABI().get() : nullptr;
14995ffd83dbSDimitry Andric     if (abi) {
15005ffd83dbSDimitry Andric       const RegisterInfo *reg_info =
15015ffd83dbSDimitry Andric           GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB));
15025ffd83dbSDimitry Andric       if (reg_info &&
15035ffd83dbSDimitry Andric           abi->GetFallbackRegisterLocation(reg_info, unwindplan_regloc)) {
15045ffd83dbSDimitry Andric         UnwindLogMsg(
15055ffd83dbSDimitry Andric             "supplying caller's saved %s (%d)'s location using ABI default",
15065ffd83dbSDimitry Andric             regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
15075ffd83dbSDimitry Andric         have_unwindplan_regloc = true;
15085ffd83dbSDimitry Andric       }
15095ffd83dbSDimitry Andric     }
15105ffd83dbSDimitry Andric   }
15115ffd83dbSDimitry Andric 
15125ffd83dbSDimitry Andric   if (!have_unwindplan_regloc) {
15135ffd83dbSDimitry Andric     if (IsFrameZero()) {
15145ffd83dbSDimitry Andric       // This is frame 0 - we should return the actual live register context
15155ffd83dbSDimitry Andric       // value
15165ffd83dbSDimitry Andric       lldb_private::UnwindLLDB::RegisterLocation new_regloc;
15175ffd83dbSDimitry Andric       new_regloc.type =
15185ffd83dbSDimitry Andric           UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext;
15195ffd83dbSDimitry Andric       new_regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB);
15205ffd83dbSDimitry Andric       m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc;
15215ffd83dbSDimitry Andric       regloc = new_regloc;
15225ffd83dbSDimitry Andric       UnwindLogMsg("supplying caller's register %s (%d) from the live "
15235ffd83dbSDimitry Andric                    "RegisterContext at frame 0",
15245ffd83dbSDimitry Andric                    regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
15255ffd83dbSDimitry Andric       return UnwindLLDB::RegisterSearchResult::eRegisterFound;
15265ffd83dbSDimitry Andric     } else {
152704eeddc0SDimitry Andric       std::string unwindplan_name;
15285ffd83dbSDimitry Andric       if (m_full_unwind_plan_sp) {
15295ffd83dbSDimitry Andric         unwindplan_name += "via '";
15305ffd83dbSDimitry Andric         unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString();
15315ffd83dbSDimitry Andric         unwindplan_name += "'";
15325ffd83dbSDimitry Andric       }
15335ffd83dbSDimitry Andric       UnwindLogMsg("no save location for %s (%d) %s", regnum.GetName(),
15345ffd83dbSDimitry Andric                    regnum.GetAsKind(eRegisterKindLLDB),
15355ffd83dbSDimitry Andric                    unwindplan_name.c_str());
15365ffd83dbSDimitry Andric     }
15375ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
15385ffd83dbSDimitry Andric   }
15395ffd83dbSDimitry Andric 
15405ffd83dbSDimitry Andric   // unwindplan_regloc has valid contents about where to retrieve the register
15415ffd83dbSDimitry Andric   if (unwindplan_regloc.IsUnspecified()) {
1542972a253aSDimitry Andric     lldb_private::UnwindLLDB::RegisterLocation new_regloc = {};
15435ffd83dbSDimitry Andric     new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
15445ffd83dbSDimitry Andric     m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc;
15455ffd83dbSDimitry Andric     UnwindLogMsg("save location for %s (%d) is unspecified, continue searching",
15465ffd83dbSDimitry Andric                  regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
15475ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
15485ffd83dbSDimitry Andric   }
15495ffd83dbSDimitry Andric 
15505ffd83dbSDimitry Andric   if (unwindplan_regloc.IsUndefined()) {
15515ffd83dbSDimitry Andric     UnwindLogMsg(
15525ffd83dbSDimitry Andric         "did not supply reg location for %s (%d) because it is volatile",
15535ffd83dbSDimitry Andric         regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
15545ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
15555ffd83dbSDimitry Andric   }
15565ffd83dbSDimitry Andric 
15575ffd83dbSDimitry Andric   if (unwindplan_regloc.IsSame()) {
1558*0fca6ea1SDimitry Andric     if (!m_all_registers_available &&
15595ffd83dbSDimitry Andric         (regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC ||
15605ffd83dbSDimitry Andric          regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) {
15615ffd83dbSDimitry Andric       UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or "
1562*0fca6ea1SDimitry Andric                    "return address reg on a frame which does not have all "
1563*0fca6ea1SDimitry Andric                    "registers available -- treat as if we have no information",
15645ffd83dbSDimitry Andric                    regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
15655ffd83dbSDimitry Andric       return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
15665ffd83dbSDimitry Andric     } else {
15675ffd83dbSDimitry Andric       regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
15685ffd83dbSDimitry Andric       regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB);
15695ffd83dbSDimitry Andric       m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
15705ffd83dbSDimitry Andric       UnwindLogMsg(
15715ffd83dbSDimitry Andric           "supplying caller's register %s (%d), saved in register %s (%d)",
15725ffd83dbSDimitry Andric           regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
15735ffd83dbSDimitry Andric           regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
15745ffd83dbSDimitry Andric       return UnwindLLDB::RegisterSearchResult::eRegisterFound;
15755ffd83dbSDimitry Andric     }
15765ffd83dbSDimitry Andric   }
15775ffd83dbSDimitry Andric 
15785ffd83dbSDimitry Andric   if (unwindplan_regloc.IsCFAPlusOffset()) {
15795ffd83dbSDimitry Andric     int offset = unwindplan_regloc.GetOffset();
15805ffd83dbSDimitry Andric     regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
15815ffd83dbSDimitry Andric     regloc.location.inferred_value = m_cfa + offset;
15825ffd83dbSDimitry Andric     m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
15835ffd83dbSDimitry Andric     UnwindLogMsg("supplying caller's register %s (%d), value is CFA plus "
15845ffd83dbSDimitry Andric                  "offset %d [value is 0x%" PRIx64 "]",
15855ffd83dbSDimitry Andric                  regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
15865ffd83dbSDimitry Andric                  regloc.location.inferred_value);
15875ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterFound;
15885ffd83dbSDimitry Andric   }
15895ffd83dbSDimitry Andric 
15905ffd83dbSDimitry Andric   if (unwindplan_regloc.IsAtCFAPlusOffset()) {
15915ffd83dbSDimitry Andric     int offset = unwindplan_regloc.GetOffset();
15925ffd83dbSDimitry Andric     regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
15935ffd83dbSDimitry Andric     regloc.location.target_memory_location = m_cfa + offset;
15945ffd83dbSDimitry Andric     m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
15955ffd83dbSDimitry Andric     UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
15965ffd83dbSDimitry Andric                  "CFA plus offset %d [saved at 0x%" PRIx64 "]",
15975ffd83dbSDimitry Andric                  regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
15985ffd83dbSDimitry Andric                  regloc.location.target_memory_location);
15995ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterFound;
16005ffd83dbSDimitry Andric   }
16015ffd83dbSDimitry Andric 
16025ffd83dbSDimitry Andric   if (unwindplan_regloc.IsAFAPlusOffset()) {
16035ffd83dbSDimitry Andric     if (m_afa == LLDB_INVALID_ADDRESS)
16045ffd83dbSDimitry Andric         return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
16055ffd83dbSDimitry Andric 
16065ffd83dbSDimitry Andric     int offset = unwindplan_regloc.GetOffset();
16075ffd83dbSDimitry Andric     regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
16085ffd83dbSDimitry Andric     regloc.location.inferred_value = m_afa + offset;
16095ffd83dbSDimitry Andric     m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
16105ffd83dbSDimitry Andric     UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus "
16115ffd83dbSDimitry Andric                  "offset %d [value is 0x%" PRIx64 "]",
16125ffd83dbSDimitry Andric                  regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
16135ffd83dbSDimitry Andric                  regloc.location.inferred_value);
16145ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterFound;
16155ffd83dbSDimitry Andric   }
16165ffd83dbSDimitry Andric 
16175ffd83dbSDimitry Andric   if (unwindplan_regloc.IsAtAFAPlusOffset()) {
16185ffd83dbSDimitry Andric     if (m_afa == LLDB_INVALID_ADDRESS)
16195ffd83dbSDimitry Andric         return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
16205ffd83dbSDimitry Andric 
16215ffd83dbSDimitry Andric     int offset = unwindplan_regloc.GetOffset();
16225ffd83dbSDimitry Andric     regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
16235ffd83dbSDimitry Andric     regloc.location.target_memory_location = m_afa + offset;
16245ffd83dbSDimitry Andric     m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
16255ffd83dbSDimitry Andric     UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
16265ffd83dbSDimitry Andric                  "AFA plus offset %d [saved at 0x%" PRIx64 "]",
16275ffd83dbSDimitry Andric                  regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
16285ffd83dbSDimitry Andric                  regloc.location.target_memory_location);
16295ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterFound;
16305ffd83dbSDimitry Andric   }
16315ffd83dbSDimitry Andric 
16325ffd83dbSDimitry Andric   if (unwindplan_regloc.IsInOtherRegister()) {
16335ffd83dbSDimitry Andric     uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
16345ffd83dbSDimitry Andric     RegisterNumber row_regnum(m_thread, unwindplan_registerkind,
16355ffd83dbSDimitry Andric                               unwindplan_regnum);
16365ffd83dbSDimitry Andric     if (row_regnum.GetAsKind(eRegisterKindLLDB) == LLDB_INVALID_REGNUM) {
16375ffd83dbSDimitry Andric       UnwindLogMsg("could not supply caller's %s (%d) location - was saved in "
16385ffd83dbSDimitry Andric                    "another reg but couldn't convert that regnum",
16395ffd83dbSDimitry Andric                    regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
16405ffd83dbSDimitry Andric       return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
16415ffd83dbSDimitry Andric     }
16425ffd83dbSDimitry Andric     regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
16435ffd83dbSDimitry Andric     regloc.location.register_number = row_regnum.GetAsKind(eRegisterKindLLDB);
16445ffd83dbSDimitry Andric     m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
16455ffd83dbSDimitry Andric     UnwindLogMsg(
16465ffd83dbSDimitry Andric         "supplying caller's register %s (%d), saved in register %s (%d)",
16475ffd83dbSDimitry Andric         regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
16485ffd83dbSDimitry Andric         row_regnum.GetName(), row_regnum.GetAsKind(eRegisterKindLLDB));
16495ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterFound;
16505ffd83dbSDimitry Andric   }
16515ffd83dbSDimitry Andric 
16525ffd83dbSDimitry Andric   if (unwindplan_regloc.IsDWARFExpression() ||
16535ffd83dbSDimitry Andric       unwindplan_regloc.IsAtDWARFExpression()) {
16545ffd83dbSDimitry Andric     DataExtractor dwarfdata(unwindplan_regloc.GetDWARFExpressionBytes(),
16555ffd83dbSDimitry Andric                             unwindplan_regloc.GetDWARFExpressionLength(),
16565ffd83dbSDimitry Andric                             process->GetByteOrder(),
16575ffd83dbSDimitry Andric                             process->GetAddressByteSize());
16585ffd83dbSDimitry Andric     ModuleSP opcode_ctx;
1659753f127fSDimitry Andric     DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
1660753f127fSDimitry Andric     dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind(
1661753f127fSDimitry Andric         unwindplan_registerkind);
16625ffd83dbSDimitry Andric     Value cfa_val = Scalar(m_cfa);
1663fe6060f1SDimitry Andric     cfa_val.SetValueType(Value::ValueType::LoadAddress);
1664*0fca6ea1SDimitry Andric     llvm::Expected<Value> result =
1665*0fca6ea1SDimitry Andric         dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr);
1666*0fca6ea1SDimitry Andric     if (!result) {
1667*0fca6ea1SDimitry Andric       LLDB_LOG_ERROR(log, result.takeError(),
1668*0fca6ea1SDimitry Andric                      "DWARF expression failed to evaluate: {0}");
1669*0fca6ea1SDimitry Andric     } else {
16705ffd83dbSDimitry Andric       addr_t val;
1671*0fca6ea1SDimitry Andric       val = result->GetScalar().ULongLong();
16725ffd83dbSDimitry Andric       if (unwindplan_regloc.IsDWARFExpression()) {
16735ffd83dbSDimitry Andric         regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
16745ffd83dbSDimitry Andric         regloc.location.inferred_value = val;
16755ffd83dbSDimitry Andric         m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
16765ffd83dbSDimitry Andric         UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression "
16775ffd83dbSDimitry Andric                      "(IsDWARFExpression)",
16785ffd83dbSDimitry Andric                      regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
16795ffd83dbSDimitry Andric         return UnwindLLDB::RegisterSearchResult::eRegisterFound;
16805ffd83dbSDimitry Andric       } else {
16815ffd83dbSDimitry Andric         regloc.type =
16825ffd83dbSDimitry Andric             UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
16835ffd83dbSDimitry Andric         regloc.location.target_memory_location = val;
16845ffd83dbSDimitry Andric         m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
16855ffd83dbSDimitry Andric         UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression "
16865ffd83dbSDimitry Andric                      "(IsAtDWARFExpression)",
16875ffd83dbSDimitry Andric                      regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
16885ffd83dbSDimitry Andric         return UnwindLLDB::RegisterSearchResult::eRegisterFound;
16895ffd83dbSDimitry Andric       }
16905ffd83dbSDimitry Andric     }
16915ffd83dbSDimitry Andric     UnwindLogMsg("tried to use IsDWARFExpression or IsAtDWARFExpression for %s "
16925ffd83dbSDimitry Andric                  "(%d) but failed",
16935ffd83dbSDimitry Andric                  regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
16945ffd83dbSDimitry Andric     return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
16955ffd83dbSDimitry Andric   }
16965ffd83dbSDimitry Andric 
16975ffd83dbSDimitry Andric   UnwindLogMsg("no save location for %s (%d) in this stack frame",
16985ffd83dbSDimitry Andric                regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
16995ffd83dbSDimitry Andric 
17005ffd83dbSDimitry Andric   // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are
17015ffd83dbSDimitry Andric   // unsupported.
17025ffd83dbSDimitry Andric 
17035ffd83dbSDimitry Andric   return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
17045ffd83dbSDimitry Andric }
17055ffd83dbSDimitry Andric 
17065ffd83dbSDimitry Andric // TryFallbackUnwindPlan() -- this method is a little tricky.
17075ffd83dbSDimitry Andric //
17085ffd83dbSDimitry Andric // When this is called, the frame above -- the caller frame, the "previous"
17095ffd83dbSDimitry Andric // frame -- is invalid or bad.
17105ffd83dbSDimitry Andric //
17115ffd83dbSDimitry Andric // Instead of stopping the stack walk here, we'll try a different UnwindPlan
17125ffd83dbSDimitry Andric // and see if we can get a valid frame above us.
17135ffd83dbSDimitry Andric //
17145ffd83dbSDimitry Andric // This most often happens when an unwind plan based on assembly instruction
17155ffd83dbSDimitry Andric // inspection is not correct -- mostly with hand-written assembly functions or
17165ffd83dbSDimitry Andric // functions where the stack frame is set up "out of band", e.g. the kernel
17175ffd83dbSDimitry Andric // saved the register context and then called an asynchronous trap handler like
17185ffd83dbSDimitry Andric // _sigtramp.
17195ffd83dbSDimitry Andric //
17205ffd83dbSDimitry Andric // Often in these cases, if we just do a dumb stack walk we'll get past this
17215ffd83dbSDimitry Andric // tricky frame and our usual techniques can continue to be used.
17225ffd83dbSDimitry Andric 
17235ffd83dbSDimitry Andric bool RegisterContextUnwind::TryFallbackUnwindPlan() {
17245ffd83dbSDimitry Andric   if (m_fallback_unwind_plan_sp.get() == nullptr)
17255ffd83dbSDimitry Andric     return false;
17265ffd83dbSDimitry Andric 
17275ffd83dbSDimitry Andric   if (m_full_unwind_plan_sp.get() == nullptr)
17285ffd83dbSDimitry Andric     return false;
17295ffd83dbSDimitry Andric 
17305ffd83dbSDimitry Andric   if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() ||
17315ffd83dbSDimitry Andric       m_full_unwind_plan_sp->GetSourceName() ==
17325ffd83dbSDimitry Andric           m_fallback_unwind_plan_sp->GetSourceName()) {
17335ffd83dbSDimitry Andric     return false;
17345ffd83dbSDimitry Andric   }
17355ffd83dbSDimitry Andric 
17365ffd83dbSDimitry Andric   // If a compiler generated unwind plan failed, trying the arch default
17375ffd83dbSDimitry Andric   // unwindplan isn't going to do any better.
17385ffd83dbSDimitry Andric   if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
17395ffd83dbSDimitry Andric     return false;
17405ffd83dbSDimitry Andric 
17415ffd83dbSDimitry Andric   // Get the caller's pc value and our own CFA value. Swap in the fallback
17425ffd83dbSDimitry Andric   // unwind plan, re-fetch the caller's pc value and CFA value. If they're the
17435ffd83dbSDimitry Andric   // same, then the fallback unwind plan provides no benefit.
17445ffd83dbSDimitry Andric 
17455ffd83dbSDimitry Andric   RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
17465ffd83dbSDimitry Andric                            LLDB_REGNUM_GENERIC_PC);
17475ffd83dbSDimitry Andric 
17485ffd83dbSDimitry Andric   addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
17495ffd83dbSDimitry Andric   addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
1750972a253aSDimitry Andric   UnwindLLDB::RegisterLocation regloc = {};
17515ffd83dbSDimitry Andric   if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
17525ffd83dbSDimitry Andric                                regloc) ==
17535ffd83dbSDimitry Andric       UnwindLLDB::RegisterSearchResult::eRegisterFound) {
17545ffd83dbSDimitry Andric     const RegisterInfo *reg_info =
17555ffd83dbSDimitry Andric         GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB));
17565ffd83dbSDimitry Andric     if (reg_info) {
17575ffd83dbSDimitry Andric       RegisterValue reg_value;
17585ffd83dbSDimitry Andric       if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
17595ffd83dbSDimitry Andric         old_caller_pc_value = reg_value.GetAsUInt64();
1760fe6060f1SDimitry Andric         if (ProcessSP process_sp = m_thread.GetProcess()) {
176106c3fb27SDimitry Andric           if (ABISP abi_sp = process_sp->GetABI())
176206c3fb27SDimitry Andric             old_caller_pc_value = abi_sp->FixCodeAddress(old_caller_pc_value);
1763fe6060f1SDimitry Andric         }
17645ffd83dbSDimitry Andric       }
17655ffd83dbSDimitry Andric     }
17665ffd83dbSDimitry Andric   }
17675ffd83dbSDimitry Andric 
17685ffd83dbSDimitry Andric   // This is a tricky wrinkle!  If SavedLocationForRegister() detects a really
17695ffd83dbSDimitry Andric   // impossible register location for the full unwind plan, it may call
17705ffd83dbSDimitry Andric   // ForceSwitchToFallbackUnwindPlan() which in turn replaces the full
17715ffd83dbSDimitry Andric   // unwindplan with the fallback... in short, we're done, we're using the
17725ffd83dbSDimitry Andric   // fallback UnwindPlan. We checked if m_fallback_unwind_plan_sp was nullptr
17735ffd83dbSDimitry Andric   // at the top -- the only way it became nullptr since then is via
17745ffd83dbSDimitry Andric   // SavedLocationForRegister().
17755ffd83dbSDimitry Andric   if (m_fallback_unwind_plan_sp.get() == nullptr)
17765ffd83dbSDimitry Andric     return true;
17775ffd83dbSDimitry Andric 
17785ffd83dbSDimitry Andric   // Switch the full UnwindPlan to be the fallback UnwindPlan.  If we decide
17795ffd83dbSDimitry Andric   // this isn't working, we need to restore. We'll also need to save & restore
17805ffd83dbSDimitry Andric   // the value of the m_cfa ivar.  Save is down below a bit in 'old_cfa'.
17815ffd83dbSDimitry Andric   UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
17825ffd83dbSDimitry Andric   addr_t old_cfa = m_cfa;
17835ffd83dbSDimitry Andric   addr_t old_afa = m_afa;
17845ffd83dbSDimitry Andric 
17855ffd83dbSDimitry Andric   m_registers.clear();
17865ffd83dbSDimitry Andric 
17875ffd83dbSDimitry Andric   m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
17885ffd83dbSDimitry Andric 
17895ffd83dbSDimitry Andric   UnwindPlan::RowSP active_row =
179081ad6265SDimitry Andric       m_fallback_unwind_plan_sp->GetRowForFunctionOffset(
179181ad6265SDimitry Andric           m_current_offset_backed_up_one);
17925ffd83dbSDimitry Andric 
17935ffd83dbSDimitry Andric   if (active_row &&
17945ffd83dbSDimitry Andric       active_row->GetCFAValue().GetValueType() !=
17955ffd83dbSDimitry Andric           UnwindPlan::Row::FAValue::unspecified) {
17965ffd83dbSDimitry Andric     addr_t new_cfa;
17975ffd83dbSDimitry Andric     if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
17985ffd83dbSDimitry Andric                             active_row->GetCFAValue(), new_cfa) ||
17995ffd83dbSDimitry Andric         new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
18005ffd83dbSDimitry Andric       UnwindLogMsg("failed to get cfa with fallback unwindplan");
18015ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp.reset();
18025ffd83dbSDimitry Andric       m_full_unwind_plan_sp = original_full_unwind_plan_sp;
18035ffd83dbSDimitry Andric       return false;
18045ffd83dbSDimitry Andric     }
18055ffd83dbSDimitry Andric     m_cfa = new_cfa;
18065ffd83dbSDimitry Andric 
18075ffd83dbSDimitry Andric     ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
18085ffd83dbSDimitry Andric                      active_row->GetAFAValue(), m_afa);
18095ffd83dbSDimitry Andric 
18105ffd83dbSDimitry Andric     if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
18115ffd83dbSDimitry Andric                                  regloc) ==
18125ffd83dbSDimitry Andric         UnwindLLDB::RegisterSearchResult::eRegisterFound) {
18135ffd83dbSDimitry Andric       const RegisterInfo *reg_info =
18145ffd83dbSDimitry Andric           GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB));
18155ffd83dbSDimitry Andric       if (reg_info) {
18165ffd83dbSDimitry Andric         RegisterValue reg_value;
18175ffd83dbSDimitry Andric         if (ReadRegisterValueFromRegisterLocation(regloc, reg_info,
18185ffd83dbSDimitry Andric                                                   reg_value)) {
18195ffd83dbSDimitry Andric           new_caller_pc_value = reg_value.GetAsUInt64();
1820fe6060f1SDimitry Andric           if (ProcessSP process_sp = m_thread.GetProcess()) {
182106c3fb27SDimitry Andric             if (ABISP abi_sp = process_sp->GetABI())
182206c3fb27SDimitry Andric               new_caller_pc_value = abi_sp->FixCodeAddress(new_caller_pc_value);
1823fe6060f1SDimitry Andric           }
18245ffd83dbSDimitry Andric         }
18255ffd83dbSDimitry Andric       }
18265ffd83dbSDimitry Andric     }
18275ffd83dbSDimitry Andric 
18285ffd83dbSDimitry Andric     if (new_caller_pc_value == LLDB_INVALID_ADDRESS) {
18295ffd83dbSDimitry Andric       UnwindLogMsg("failed to get a pc value for the caller frame with the "
18305ffd83dbSDimitry Andric                    "fallback unwind plan");
18315ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp.reset();
18325ffd83dbSDimitry Andric       m_full_unwind_plan_sp = original_full_unwind_plan_sp;
18335ffd83dbSDimitry Andric       m_cfa = old_cfa;
18345ffd83dbSDimitry Andric       m_afa = old_afa;
18355ffd83dbSDimitry Andric       return false;
18365ffd83dbSDimitry Andric     }
18375ffd83dbSDimitry Andric 
18385ffd83dbSDimitry Andric     if (old_caller_pc_value == new_caller_pc_value &&
18395ffd83dbSDimitry Andric         m_cfa == old_cfa &&
18405ffd83dbSDimitry Andric         m_afa == old_afa) {
18415ffd83dbSDimitry Andric       UnwindLogMsg("fallback unwind plan got the same values for this frame "
18425ffd83dbSDimitry Andric                    "CFA and caller frame pc, not using");
18435ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp.reset();
18445ffd83dbSDimitry Andric       m_full_unwind_plan_sp = original_full_unwind_plan_sp;
18455ffd83dbSDimitry Andric       return false;
18465ffd83dbSDimitry Andric     }
18475ffd83dbSDimitry Andric 
18485ffd83dbSDimitry Andric     UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' "
18495ffd83dbSDimitry Andric                  "because UnwindPlan '%s' failed.",
18505ffd83dbSDimitry Andric                  m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
18515ffd83dbSDimitry Andric                  original_full_unwind_plan_sp->GetSourceName().GetCString());
18525ffd83dbSDimitry Andric 
18535ffd83dbSDimitry Andric     // We've copied the fallback unwind plan into the full - now clear the
18545ffd83dbSDimitry Andric     // fallback.
18555ffd83dbSDimitry Andric     m_fallback_unwind_plan_sp.reset();
18565ffd83dbSDimitry Andric     PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
18575ffd83dbSDimitry Andric   }
18585ffd83dbSDimitry Andric 
18595ffd83dbSDimitry Andric   return true;
18605ffd83dbSDimitry Andric }
18615ffd83dbSDimitry Andric 
18625ffd83dbSDimitry Andric bool RegisterContextUnwind::ForceSwitchToFallbackUnwindPlan() {
18635ffd83dbSDimitry Andric   if (m_fallback_unwind_plan_sp.get() == nullptr)
18645ffd83dbSDimitry Andric     return false;
18655ffd83dbSDimitry Andric 
18665ffd83dbSDimitry Andric   if (m_full_unwind_plan_sp.get() == nullptr)
18675ffd83dbSDimitry Andric     return false;
18685ffd83dbSDimitry Andric 
18695ffd83dbSDimitry Andric   if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() ||
18705ffd83dbSDimitry Andric       m_full_unwind_plan_sp->GetSourceName() ==
18715ffd83dbSDimitry Andric           m_fallback_unwind_plan_sp->GetSourceName()) {
18725ffd83dbSDimitry Andric     return false;
18735ffd83dbSDimitry Andric   }
18745ffd83dbSDimitry Andric 
18755ffd83dbSDimitry Andric   UnwindPlan::RowSP active_row =
18765ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
18775ffd83dbSDimitry Andric 
18785ffd83dbSDimitry Andric   if (active_row &&
18795ffd83dbSDimitry Andric       active_row->GetCFAValue().GetValueType() !=
18805ffd83dbSDimitry Andric           UnwindPlan::Row::FAValue::unspecified) {
18815ffd83dbSDimitry Andric     addr_t new_cfa;
18825ffd83dbSDimitry Andric     if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
18835ffd83dbSDimitry Andric                             active_row->GetCFAValue(), new_cfa) ||
18845ffd83dbSDimitry Andric         new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
18855ffd83dbSDimitry Andric       UnwindLogMsg("failed to get cfa with fallback unwindplan");
18865ffd83dbSDimitry Andric       m_fallback_unwind_plan_sp.reset();
18875ffd83dbSDimitry Andric       return false;
18885ffd83dbSDimitry Andric     }
18895ffd83dbSDimitry Andric 
18905ffd83dbSDimitry Andric     ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
18915ffd83dbSDimitry Andric                      active_row->GetAFAValue(), m_afa);
18925ffd83dbSDimitry Andric 
18935ffd83dbSDimitry Andric     m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
18945ffd83dbSDimitry Andric     m_fallback_unwind_plan_sp.reset();
18955ffd83dbSDimitry Andric 
18965ffd83dbSDimitry Andric     m_registers.clear();
18975ffd83dbSDimitry Andric 
18985ffd83dbSDimitry Andric     m_cfa = new_cfa;
18995ffd83dbSDimitry Andric 
19005ffd83dbSDimitry Andric     PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
19015ffd83dbSDimitry Andric 
19025ffd83dbSDimitry Andric     UnwindLogMsg("switched unconditionally to the fallback unwindplan %s",
19035ffd83dbSDimitry Andric                  m_full_unwind_plan_sp->GetSourceName().GetCString());
19045ffd83dbSDimitry Andric     return true;
19055ffd83dbSDimitry Andric   }
19065ffd83dbSDimitry Andric   return false;
19075ffd83dbSDimitry Andric }
19085ffd83dbSDimitry Andric 
19095ffd83dbSDimitry Andric void RegisterContextUnwind::PropagateTrapHandlerFlagFromUnwindPlan(
19105ffd83dbSDimitry Andric     lldb::UnwindPlanSP unwind_plan) {
19115ffd83dbSDimitry Andric   if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) {
19125ffd83dbSDimitry Andric     // Unwind plan does not indicate trap handler.  Do nothing.  We may
19135ffd83dbSDimitry Andric     // already be flagged as trap handler flag due to the symbol being
19145ffd83dbSDimitry Andric     // in the trap handler symbol list, and that should take precedence.
19155ffd83dbSDimitry Andric     return;
19165ffd83dbSDimitry Andric   } else if (m_frame_type != eNormalFrame) {
19175ffd83dbSDimitry Andric     // If this is already a trap handler frame, nothing to do.
19185ffd83dbSDimitry Andric     // If this is a skip or debug or invalid frame, don't override that.
19195ffd83dbSDimitry Andric     return;
19205ffd83dbSDimitry Andric   }
19215ffd83dbSDimitry Andric 
19225ffd83dbSDimitry Andric   m_frame_type = eTrapHandlerFrame;
19235ffd83dbSDimitry Andric 
19245ffd83dbSDimitry Andric   if (m_current_offset_backed_up_one != m_current_offset) {
19255ffd83dbSDimitry Andric     // We backed up the pc by 1 to compute the symbol context, but
19265ffd83dbSDimitry Andric     // now need to undo that because the pc of the trap handler
19275ffd83dbSDimitry Andric     // frame may in fact be the first instruction of a signal return
19285ffd83dbSDimitry Andric     // trampoline, rather than the instruction after a call.  This
19295ffd83dbSDimitry Andric     // happens on systems where the signal handler dispatch code, rather
19305ffd83dbSDimitry Andric     // than calling the handler and being returned to, jumps to the
19315ffd83dbSDimitry Andric     // handler after pushing the address of a return trampoline on the
19325ffd83dbSDimitry Andric     // stack -- on these systems, when the handler returns, control will
19335ffd83dbSDimitry Andric     // be transferred to the return trampoline, so that's the best
19345ffd83dbSDimitry Andric     // symbol we can present in the callstack.
19355ffd83dbSDimitry Andric     UnwindLogMsg("Resetting current offset and re-doing symbol lookup; "
19365ffd83dbSDimitry Andric                  "old symbol was %s",
19375ffd83dbSDimitry Andric                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
19385ffd83dbSDimitry Andric     m_current_offset_backed_up_one = m_current_offset;
19395ffd83dbSDimitry Andric 
19405ffd83dbSDimitry Andric     AddressRange addr_range;
19415ffd83dbSDimitry Andric     m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
19425ffd83dbSDimitry Andric 
19435ffd83dbSDimitry Andric     UnwindLogMsg("Symbol is now %s",
19445ffd83dbSDimitry Andric                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
19455ffd83dbSDimitry Andric 
19465ffd83dbSDimitry Andric     ExecutionContext exe_ctx(m_thread.shared_from_this());
19475ffd83dbSDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
19485ffd83dbSDimitry Andric     Target *target = &process->GetTarget();
19495ffd83dbSDimitry Andric 
19505ffd83dbSDimitry Andric     m_start_pc = addr_range.GetBaseAddress();
19515ffd83dbSDimitry Andric     m_current_offset =
19525ffd83dbSDimitry Andric         m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target);
19535ffd83dbSDimitry Andric   }
19545ffd83dbSDimitry Andric }
19555ffd83dbSDimitry Andric 
19565ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadFrameAddress(
19575ffd83dbSDimitry Andric     lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa,
19585ffd83dbSDimitry Andric     addr_t &address) {
19595ffd83dbSDimitry Andric   RegisterValue reg_value;
19605ffd83dbSDimitry Andric 
19615ffd83dbSDimitry Andric   address = LLDB_INVALID_ADDRESS;
19625ffd83dbSDimitry Andric   addr_t cfa_reg_contents;
196306c3fb27SDimitry Andric   ABISP abi_sp = m_thread.GetProcess()->GetABI();
19645ffd83dbSDimitry Andric 
19655ffd83dbSDimitry Andric   switch (fa.GetValueType()) {
19665ffd83dbSDimitry Andric   case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
19675ffd83dbSDimitry Andric     RegisterNumber cfa_reg(m_thread, row_register_kind,
19685ffd83dbSDimitry Andric                            fa.GetRegisterNumber());
19695ffd83dbSDimitry Andric     if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
19705ffd83dbSDimitry Andric       const RegisterInfo *reg_info =
19715ffd83dbSDimitry Andric           GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
19725ffd83dbSDimitry Andric       RegisterValue reg_value;
19735ffd83dbSDimitry Andric       if (reg_info) {
197406c3fb27SDimitry Andric         if (abi_sp)
197506c3fb27SDimitry Andric           cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
19765ffd83dbSDimitry Andric         Status error = ReadRegisterValueFromMemory(
19775ffd83dbSDimitry Andric             reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
19785ffd83dbSDimitry Andric         if (error.Success()) {
19795ffd83dbSDimitry Andric           address = reg_value.GetAsUInt64();
198006c3fb27SDimitry Andric           if (abi_sp)
1981fe6060f1SDimitry Andric             address = abi_sp->FixCodeAddress(address);
19825ffd83dbSDimitry Andric           UnwindLogMsg(
19835ffd83dbSDimitry Andric               "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
19845ffd83dbSDimitry Andric               ", CFA value is 0x%" PRIx64,
19855ffd83dbSDimitry Andric               cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
19865ffd83dbSDimitry Andric               cfa_reg_contents, address);
19875ffd83dbSDimitry Andric           return true;
19885ffd83dbSDimitry Andric         } else {
19895ffd83dbSDimitry Andric           UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64
19905ffd83dbSDimitry Andric                        "] but memory read failed.",
19915ffd83dbSDimitry Andric                        cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
19925ffd83dbSDimitry Andric                        cfa_reg_contents);
19935ffd83dbSDimitry Andric         }
19945ffd83dbSDimitry Andric       }
19955ffd83dbSDimitry Andric     }
19965ffd83dbSDimitry Andric     break;
19975ffd83dbSDimitry Andric   }
19985ffd83dbSDimitry Andric   case UnwindPlan::Row::FAValue::isRegisterPlusOffset: {
19995ffd83dbSDimitry Andric     RegisterNumber cfa_reg(m_thread, row_register_kind,
20005ffd83dbSDimitry Andric                            fa.GetRegisterNumber());
20015ffd83dbSDimitry Andric     if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
200206c3fb27SDimitry Andric       if (abi_sp)
200306c3fb27SDimitry Andric         cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
20045ffd83dbSDimitry Andric       if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
20055ffd83dbSDimitry Andric           cfa_reg_contents == 1) {
20065ffd83dbSDimitry Andric         UnwindLogMsg(
20075ffd83dbSDimitry Andric             "Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
20085ffd83dbSDimitry Andric             cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
20095ffd83dbSDimitry Andric             cfa_reg_contents);
20105ffd83dbSDimitry Andric         cfa_reg_contents = LLDB_INVALID_ADDRESS;
20115ffd83dbSDimitry Andric         return false;
20125ffd83dbSDimitry Andric       }
20135ffd83dbSDimitry Andric       address = cfa_reg_contents + fa.GetOffset();
20145ffd83dbSDimitry Andric       UnwindLogMsg(
20155ffd83dbSDimitry Andric           "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64
20165ffd83dbSDimitry Andric           ", offset is %d",
20175ffd83dbSDimitry Andric           address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
20185ffd83dbSDimitry Andric           cfa_reg_contents, fa.GetOffset());
20195ffd83dbSDimitry Andric       return true;
20205ffd83dbSDimitry Andric     }
20215ffd83dbSDimitry Andric     break;
20225ffd83dbSDimitry Andric   }
20235ffd83dbSDimitry Andric   case UnwindPlan::Row::FAValue::isDWARFExpression: {
20245ffd83dbSDimitry Andric     ExecutionContext exe_ctx(m_thread.shared_from_this());
20255ffd83dbSDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
20265ffd83dbSDimitry Andric     DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(),
20275ffd83dbSDimitry Andric                             fa.GetDWARFExpressionLength(),
20285ffd83dbSDimitry Andric                             process->GetByteOrder(),
20295ffd83dbSDimitry Andric                             process->GetAddressByteSize());
20305ffd83dbSDimitry Andric     ModuleSP opcode_ctx;
2031753f127fSDimitry Andric     DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
2032753f127fSDimitry Andric     dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind(
2033753f127fSDimitry Andric         row_register_kind);
2034*0fca6ea1SDimitry Andric     llvm::Expected<Value> result =
2035*0fca6ea1SDimitry Andric         dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr);
2036*0fca6ea1SDimitry Andric     if (result) {
2037*0fca6ea1SDimitry Andric       address = result->GetScalar().ULongLong();
2038fe6060f1SDimitry Andric       if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
2039fe6060f1SDimitry Andric         address = abi_sp->FixCodeAddress(address);
20405ffd83dbSDimitry Andric 
20415ffd83dbSDimitry Andric       UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64,
20425ffd83dbSDimitry Andric                    address);
20435ffd83dbSDimitry Andric       return true;
20445ffd83dbSDimitry Andric     }
20455ffd83dbSDimitry Andric     UnwindLogMsg("Failed to set CFA value via DWARF expression: %s",
2046*0fca6ea1SDimitry Andric                  llvm::toString(result.takeError()).c_str());
20475ffd83dbSDimitry Andric     break;
20485ffd83dbSDimitry Andric   }
20495ffd83dbSDimitry Andric   case UnwindPlan::Row::FAValue::isRaSearch: {
20505ffd83dbSDimitry Andric     Process &process = *m_thread.GetProcess();
20515ffd83dbSDimitry Andric     lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset());
20525ffd83dbSDimitry Andric     if (return_address_hint == LLDB_INVALID_ADDRESS)
20535ffd83dbSDimitry Andric       return false;
20545ffd83dbSDimitry Andric     const unsigned max_iterations = 256;
20555ffd83dbSDimitry Andric     for (unsigned i = 0; i < max_iterations; ++i) {
20565ffd83dbSDimitry Andric       Status st;
20575ffd83dbSDimitry Andric       lldb::addr_t candidate_addr =
20585ffd83dbSDimitry Andric           return_address_hint + i * process.GetAddressByteSize();
20595ffd83dbSDimitry Andric       lldb::addr_t candidate =
20605ffd83dbSDimitry Andric           process.ReadPointerFromMemory(candidate_addr, st);
20615ffd83dbSDimitry Andric       if (st.Fail()) {
20625ffd83dbSDimitry Andric         UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr,
20635ffd83dbSDimitry Andric                      st.AsCString());
20645ffd83dbSDimitry Andric         return false;
20655ffd83dbSDimitry Andric       }
20665ffd83dbSDimitry Andric       Address addr;
20675ffd83dbSDimitry Andric       uint32_t permissions;
20685ffd83dbSDimitry Andric       if (process.GetLoadAddressPermissions(candidate, permissions) &&
20695ffd83dbSDimitry Andric           permissions & lldb::ePermissionsExecutable) {
20705ffd83dbSDimitry Andric         address = candidate_addr;
20715ffd83dbSDimitry Andric         UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address);
20725ffd83dbSDimitry Andric         return true;
20735ffd83dbSDimitry Andric       }
20745ffd83dbSDimitry Andric     }
20755ffd83dbSDimitry Andric     UnwindLogMsg("No suitable CFA found");
20765ffd83dbSDimitry Andric     break;
20775ffd83dbSDimitry Andric   }
20785ffd83dbSDimitry Andric   default:
20795ffd83dbSDimitry Andric     return false;
20805ffd83dbSDimitry Andric   }
20815ffd83dbSDimitry Andric   return false;
20825ffd83dbSDimitry Andric }
20835ffd83dbSDimitry Andric 
20845ffd83dbSDimitry Andric lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
20855ffd83dbSDimitry Andric   addr_t hint;
20865ffd83dbSDimitry Andric   if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint))
20875ffd83dbSDimitry Andric     return LLDB_INVALID_ADDRESS;
20885ffd83dbSDimitry Andric   if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
20895ffd83dbSDimitry Andric     return LLDB_INVALID_ADDRESS;
209006c3fb27SDimitry Andric   if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
209106c3fb27SDimitry Andric     hint = abi_sp->FixCodeAddress(hint);
20925ffd83dbSDimitry Andric 
20935ffd83dbSDimitry Andric   hint += plan_offset;
20945ffd83dbSDimitry Andric 
20955ffd83dbSDimitry Andric   if (auto next = GetNextFrame()) {
20965ffd83dbSDimitry Andric     if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol)
20975ffd83dbSDimitry Andric       return LLDB_INVALID_ADDRESS;
20985ffd83dbSDimitry Andric     if (auto expected_size =
20995ffd83dbSDimitry Andric             next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize(
21005ffd83dbSDimitry Andric                 *next->m_sym_ctx.symbol))
21015ffd83dbSDimitry Andric       hint += *expected_size;
21025ffd83dbSDimitry Andric     else {
21035ffd83dbSDimitry Andric       UnwindLogMsgVerbose("Could not retrieve parameter size: %s",
21045ffd83dbSDimitry Andric                           llvm::toString(expected_size.takeError()).c_str());
21055ffd83dbSDimitry Andric       return LLDB_INVALID_ADDRESS;
21065ffd83dbSDimitry Andric     }
21075ffd83dbSDimitry Andric   }
21085ffd83dbSDimitry Andric   return hint;
21095ffd83dbSDimitry Andric }
21105ffd83dbSDimitry Andric 
21115ffd83dbSDimitry Andric // Retrieve a general purpose register value for THIS frame, as saved by the
21125ffd83dbSDimitry Andric // NEXT frame, i.e. the frame that
21135ffd83dbSDimitry Andric // this frame called.  e.g.
21145ffd83dbSDimitry Andric //
21155ffd83dbSDimitry Andric //  foo () { }
21165ffd83dbSDimitry Andric //  bar () { foo (); }
21175ffd83dbSDimitry Andric //  main () { bar (); }
21185ffd83dbSDimitry Andric //
21195ffd83dbSDimitry Andric //  stopped in foo() so
21205ffd83dbSDimitry Andric //     frame 0 - foo
21215ffd83dbSDimitry Andric //     frame 1 - bar
21225ffd83dbSDimitry Andric //     frame 2 - main
21235ffd83dbSDimitry Andric //  and this RegisterContext is for frame 1 (bar) - if we want to get the pc
21245ffd83dbSDimitry Andric //  value for frame 1, we need to ask
21255ffd83dbSDimitry Andric //  where frame 0 (the "next" frame) saved that and retrieve the value.
21265ffd83dbSDimitry Andric 
21275ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
21285ffd83dbSDimitry Andric                                          uint32_t regnum, addr_t &value) {
21295ffd83dbSDimitry Andric   if (!IsValid())
21305ffd83dbSDimitry Andric     return false;
21315ffd83dbSDimitry Andric 
21325ffd83dbSDimitry Andric   uint32_t lldb_regnum;
21335ffd83dbSDimitry Andric   if (register_kind == eRegisterKindLLDB) {
21345ffd83dbSDimitry Andric     lldb_regnum = regnum;
21355ffd83dbSDimitry Andric   } else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
21365ffd83dbSDimitry Andric                  register_kind, regnum, eRegisterKindLLDB, lldb_regnum)) {
21375ffd83dbSDimitry Andric     return false;
21385ffd83dbSDimitry Andric   }
21395ffd83dbSDimitry Andric 
21405ffd83dbSDimitry Andric   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
214106c3fb27SDimitry Andric   assert(reg_info);
214206c3fb27SDimitry Andric   if (!reg_info) {
214306c3fb27SDimitry Andric     UnwindLogMsg(
214406c3fb27SDimitry Andric         "Could not find RegisterInfo definition for lldb register number %d",
214506c3fb27SDimitry Andric         lldb_regnum);
214606c3fb27SDimitry Andric     return false;
214706c3fb27SDimitry Andric   }
214806c3fb27SDimitry Andric 
214906c3fb27SDimitry Andric   uint32_t generic_regnum = LLDB_INVALID_REGNUM;
215006c3fb27SDimitry Andric   if (register_kind == eRegisterKindGeneric)
215106c3fb27SDimitry Andric     generic_regnum = regnum;
215206c3fb27SDimitry Andric   else
215306c3fb27SDimitry Andric     m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
215406c3fb27SDimitry Andric         register_kind, regnum, eRegisterKindGeneric, generic_regnum);
215506c3fb27SDimitry Andric   ABISP abi_sp = m_thread.GetProcess()->GetABI();
215606c3fb27SDimitry Andric 
21575ffd83dbSDimitry Andric   RegisterValue reg_value;
21585ffd83dbSDimitry Andric   // if this is frame 0 (currently executing frame), get the requested reg
21595ffd83dbSDimitry Andric   // contents from the actual thread registers
21605ffd83dbSDimitry Andric   if (IsFrameZero()) {
21615ffd83dbSDimitry Andric     if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) {
21625ffd83dbSDimitry Andric       value = reg_value.GetAsUInt64();
216306c3fb27SDimitry Andric       if (abi_sp && generic_regnum != LLDB_INVALID_REGNUM) {
216406c3fb27SDimitry Andric         if (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
216506c3fb27SDimitry Andric             generic_regnum == LLDB_REGNUM_GENERIC_RA)
216606c3fb27SDimitry Andric           value = abi_sp->FixCodeAddress(value);
216706c3fb27SDimitry Andric         if (generic_regnum == LLDB_REGNUM_GENERIC_SP ||
216806c3fb27SDimitry Andric             generic_regnum == LLDB_REGNUM_GENERIC_FP)
216906c3fb27SDimitry Andric           value = abi_sp->FixDataAddress(value);
217006c3fb27SDimitry Andric       }
21715ffd83dbSDimitry Andric       return true;
21725ffd83dbSDimitry Andric     }
21735ffd83dbSDimitry Andric     return false;
21745ffd83dbSDimitry Andric   }
21755ffd83dbSDimitry Andric 
21765ffd83dbSDimitry Andric   bool pc_register = false;
217706c3fb27SDimitry Andric   if (generic_regnum != LLDB_INVALID_REGNUM &&
21785ffd83dbSDimitry Andric       (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
217906c3fb27SDimitry Andric        generic_regnum == LLDB_REGNUM_GENERIC_RA))
21805ffd83dbSDimitry Andric     pc_register = true;
21815ffd83dbSDimitry Andric 
21825ffd83dbSDimitry Andric   lldb_private::UnwindLLDB::RegisterLocation regloc;
21835ffd83dbSDimitry Andric   if (!m_parent_unwind.SearchForSavedLocationForRegister(
21845ffd83dbSDimitry Andric           lldb_regnum, regloc, m_frame_number - 1, pc_register)) {
21855ffd83dbSDimitry Andric     return false;
21865ffd83dbSDimitry Andric   }
21875ffd83dbSDimitry Andric   if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
21885ffd83dbSDimitry Andric     value = reg_value.GetAsUInt64();
2189fe6060f1SDimitry Andric     if (pc_register) {
219006c3fb27SDimitry Andric       if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) {
219106c3fb27SDimitry Andric         value = abi_sp->FixCodeAddress(value);
2192fe6060f1SDimitry Andric       }
2193fe6060f1SDimitry Andric     }
21945ffd83dbSDimitry Andric     return true;
21955ffd83dbSDimitry Andric   }
21965ffd83dbSDimitry Andric   return false;
21975ffd83dbSDimitry Andric }
21985ffd83dbSDimitry Andric 
21995ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadGPRValue(const RegisterNumber &regnum,
22005ffd83dbSDimitry Andric                                          addr_t &value) {
22015ffd83dbSDimitry Andric   return ReadGPRValue(regnum.GetRegisterKind(), regnum.GetRegisterNumber(),
22025ffd83dbSDimitry Andric                       value);
22035ffd83dbSDimitry Andric }
22045ffd83dbSDimitry Andric 
22055ffd83dbSDimitry Andric // Find the value of a register in THIS frame
22065ffd83dbSDimitry Andric 
22075ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
22085ffd83dbSDimitry Andric                                          RegisterValue &value) {
22095ffd83dbSDimitry Andric   if (!IsValid())
22105ffd83dbSDimitry Andric     return false;
22115ffd83dbSDimitry Andric 
22125ffd83dbSDimitry Andric   const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
22135ffd83dbSDimitry Andric   UnwindLogMsgVerbose("looking for register saved location for reg %d",
22145ffd83dbSDimitry Andric                       lldb_regnum);
22155ffd83dbSDimitry Andric 
22165ffd83dbSDimitry Andric   // If this is the 0th frame, hand this over to the live register context
22175ffd83dbSDimitry Andric   if (IsFrameZero()) {
22185ffd83dbSDimitry Andric     UnwindLogMsgVerbose("passing along to the live register context for reg %d",
22195ffd83dbSDimitry Andric                         lldb_regnum);
22205ffd83dbSDimitry Andric     return m_thread.GetRegisterContext()->ReadRegister(reg_info, value);
22215ffd83dbSDimitry Andric   }
22225ffd83dbSDimitry Andric 
22235ffd83dbSDimitry Andric   bool is_pc_regnum = false;
22245ffd83dbSDimitry Andric   if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC ||
22255ffd83dbSDimitry Andric       reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) {
22265ffd83dbSDimitry Andric     is_pc_regnum = true;
22275ffd83dbSDimitry Andric   }
22285ffd83dbSDimitry Andric 
22295ffd83dbSDimitry Andric   lldb_private::UnwindLLDB::RegisterLocation regloc;
22305ffd83dbSDimitry Andric   // Find out where the NEXT frame saved THIS frame's register contents
22315ffd83dbSDimitry Andric   if (!m_parent_unwind.SearchForSavedLocationForRegister(
22325ffd83dbSDimitry Andric           lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum))
22335ffd83dbSDimitry Andric     return false;
22345ffd83dbSDimitry Andric 
2235fe6060f1SDimitry Andric   bool result = ReadRegisterValueFromRegisterLocation(regloc, reg_info, value);
2236fe6060f1SDimitry Andric   if (result) {
2237fe6060f1SDimitry Andric     if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
2238fe6060f1SDimitry Andric       addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
2239fe6060f1SDimitry Andric       if (reg_value != LLDB_INVALID_ADDRESS) {
224006c3fb27SDimitry Andric         if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
224106c3fb27SDimitry Andric           value = abi_sp->FixCodeAddress(reg_value);
2242fe6060f1SDimitry Andric       }
2243fe6060f1SDimitry Andric     }
2244fe6060f1SDimitry Andric   }
2245fe6060f1SDimitry Andric   return result;
22465ffd83dbSDimitry Andric }
22475ffd83dbSDimitry Andric 
22485ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info,
22495ffd83dbSDimitry Andric                                           const RegisterValue &value) {
22505ffd83dbSDimitry Andric   if (!IsValid())
22515ffd83dbSDimitry Andric     return false;
22525ffd83dbSDimitry Andric 
22535ffd83dbSDimitry Andric   const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
22545ffd83dbSDimitry Andric   UnwindLogMsgVerbose("looking for register saved location for reg %d",
22555ffd83dbSDimitry Andric                       lldb_regnum);
22565ffd83dbSDimitry Andric 
22575ffd83dbSDimitry Andric   // If this is the 0th frame, hand this over to the live register context
22585ffd83dbSDimitry Andric   if (IsFrameZero()) {
22595ffd83dbSDimitry Andric     UnwindLogMsgVerbose("passing along to the live register context for reg %d",
22605ffd83dbSDimitry Andric                         lldb_regnum);
22615ffd83dbSDimitry Andric     return m_thread.GetRegisterContext()->WriteRegister(reg_info, value);
22625ffd83dbSDimitry Andric   }
22635ffd83dbSDimitry Andric 
22645ffd83dbSDimitry Andric   lldb_private::UnwindLLDB::RegisterLocation regloc;
22655ffd83dbSDimitry Andric   // Find out where the NEXT frame saved THIS frame's register contents
22665ffd83dbSDimitry Andric   if (!m_parent_unwind.SearchForSavedLocationForRegister(
22675ffd83dbSDimitry Andric           lldb_regnum, regloc, m_frame_number - 1, false))
22685ffd83dbSDimitry Andric     return false;
22695ffd83dbSDimitry Andric 
22705ffd83dbSDimitry Andric   return WriteRegisterValueToRegisterLocation(regloc, reg_info, value);
22715ffd83dbSDimitry Andric }
22725ffd83dbSDimitry Andric 
22735ffd83dbSDimitry Andric // Don't need to implement this one
227481ad6265SDimitry Andric bool RegisterContextUnwind::ReadAllRegisterValues(
227581ad6265SDimitry Andric     lldb::WritableDataBufferSP &data_sp) {
22765ffd83dbSDimitry Andric   return false;
22775ffd83dbSDimitry Andric }
22785ffd83dbSDimitry Andric 
22795ffd83dbSDimitry Andric // Don't need to implement this one
22805ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteAllRegisterValues(
22815ffd83dbSDimitry Andric     const lldb::DataBufferSP &data_sp) {
22825ffd83dbSDimitry Andric   return false;
22835ffd83dbSDimitry Andric }
22845ffd83dbSDimitry Andric 
22855ffd83dbSDimitry Andric // Retrieve the pc value for THIS from
22865ffd83dbSDimitry Andric 
22875ffd83dbSDimitry Andric bool RegisterContextUnwind::GetCFA(addr_t &cfa) {
22885ffd83dbSDimitry Andric   if (!IsValid()) {
22895ffd83dbSDimitry Andric     return false;
22905ffd83dbSDimitry Andric   }
22915ffd83dbSDimitry Andric   if (m_cfa == LLDB_INVALID_ADDRESS) {
22925ffd83dbSDimitry Andric     return false;
22935ffd83dbSDimitry Andric   }
22945ffd83dbSDimitry Andric   cfa = m_cfa;
22955ffd83dbSDimitry Andric   return true;
22965ffd83dbSDimitry Andric }
22975ffd83dbSDimitry Andric 
22985ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetNextFrame() const {
22995ffd83dbSDimitry Andric   RegisterContextUnwind::SharedPtr regctx;
23005ffd83dbSDimitry Andric   if (m_frame_number == 0)
23015ffd83dbSDimitry Andric     return regctx;
23025ffd83dbSDimitry Andric   return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number - 1);
23035ffd83dbSDimitry Andric }
23045ffd83dbSDimitry Andric 
23055ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetPrevFrame() const {
23065ffd83dbSDimitry Andric   RegisterContextUnwind::SharedPtr regctx;
23075ffd83dbSDimitry Andric   return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number + 1);
23085ffd83dbSDimitry Andric }
23095ffd83dbSDimitry Andric 
23105ffd83dbSDimitry Andric // Retrieve the address of the start of the function of THIS frame
23115ffd83dbSDimitry Andric 
23125ffd83dbSDimitry Andric bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) {
23135ffd83dbSDimitry Andric   if (!IsValid())
23145ffd83dbSDimitry Andric     return false;
23155ffd83dbSDimitry Andric 
23165ffd83dbSDimitry Andric   if (!m_start_pc.IsValid()) {
23175ffd83dbSDimitry Andric         bool read_successfully = ReadPC (start_pc);
23185ffd83dbSDimitry Andric         if (read_successfully)
23195ffd83dbSDimitry Andric         {
23205ffd83dbSDimitry Andric             ProcessSP process_sp (m_thread.GetProcess());
23215ffd83dbSDimitry Andric             if (process_sp)
23225ffd83dbSDimitry Andric             {
232306c3fb27SDimitry Andric               if (ABISP abi_sp = process_sp->GetABI())
232406c3fb27SDimitry Andric                 start_pc = abi_sp->FixCodeAddress(start_pc);
23255ffd83dbSDimitry Andric             }
23265ffd83dbSDimitry Andric         }
23275ffd83dbSDimitry Andric         return read_successfully;
23285ffd83dbSDimitry Andric   }
23295ffd83dbSDimitry Andric   start_pc = m_start_pc.GetLoadAddress(CalculateTarget().get());
23305ffd83dbSDimitry Andric   return true;
23315ffd83dbSDimitry Andric }
23325ffd83dbSDimitry Andric 
23335ffd83dbSDimitry Andric // Retrieve the current pc value for THIS frame, as saved by the NEXT frame.
23345ffd83dbSDimitry Andric 
23355ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadPC(addr_t &pc) {
23365ffd83dbSDimitry Andric   if (!IsValid())
23375ffd83dbSDimitry Andric     return false;
23385ffd83dbSDimitry Andric 
23395ffd83dbSDimitry Andric   bool above_trap_handler = false;
23405ffd83dbSDimitry Andric   if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
23415ffd83dbSDimitry Andric       GetNextFrame()->IsTrapHandlerFrame())
23425ffd83dbSDimitry Andric     above_trap_handler = true;
23435ffd83dbSDimitry Andric 
23445ffd83dbSDimitry Andric   if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) {
23455ffd83dbSDimitry Andric     // A pc value of 0 or 1 is impossible in the middle of the stack -- it
23465ffd83dbSDimitry Andric     // indicates the end of a stack walk.
23475ffd83dbSDimitry Andric     // On the currently executing frame (or such a frame interrupted
23485ffd83dbSDimitry Andric     // asynchronously by sigtramp et al) this may occur if code has jumped
23495ffd83dbSDimitry Andric     // through a NULL pointer -- we want to be able to unwind past that frame
23505ffd83dbSDimitry Andric     // to help find the bug.
23515ffd83dbSDimitry Andric 
235206c3fb27SDimitry Andric     if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
235306c3fb27SDimitry Andric       pc = abi_sp->FixCodeAddress(pc);
23545ffd83dbSDimitry Andric 
23555ffd83dbSDimitry Andric     return !(m_all_registers_available == false &&
23565ffd83dbSDimitry Andric              above_trap_handler == false && (pc == 0 || pc == 1));
23575ffd83dbSDimitry Andric   } else {
23585ffd83dbSDimitry Andric     return false;
23595ffd83dbSDimitry Andric   }
23605ffd83dbSDimitry Andric }
23615ffd83dbSDimitry Andric 
23625ffd83dbSDimitry Andric void RegisterContextUnwind::UnwindLogMsg(const char *fmt, ...) {
236381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Unwind);
236481ad6265SDimitry Andric   if (!log)
236581ad6265SDimitry Andric     return;
236681ad6265SDimitry Andric 
23675ffd83dbSDimitry Andric   va_list args;
23685ffd83dbSDimitry Andric   va_start(args, fmt);
23695ffd83dbSDimitry Andric 
237081ad6265SDimitry Andric   llvm::SmallString<0> logmsg;
237181ad6265SDimitry Andric   if (VASprintf(logmsg, fmt, args)) {
23725ffd83dbSDimitry Andric     LLDB_LOGF(log, "%*sth%d/fr%u %s",
23735ffd83dbSDimitry Andric               m_frame_number < 100 ? m_frame_number : 100, "",
237481ad6265SDimitry Andric               m_thread.GetIndexID(), m_frame_number, logmsg.c_str());
23755ffd83dbSDimitry Andric   }
237681ad6265SDimitry Andric   va_end(args);
23775ffd83dbSDimitry Andric }
23785ffd83dbSDimitry Andric 
23795ffd83dbSDimitry Andric void RegisterContextUnwind::UnwindLogMsgVerbose(const char *fmt, ...) {
238081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Unwind);
238181ad6265SDimitry Andric   if (!log || !log->GetVerbose())
238281ad6265SDimitry Andric     return;
238381ad6265SDimitry Andric 
23845ffd83dbSDimitry Andric   va_list args;
23855ffd83dbSDimitry Andric   va_start(args, fmt);
23865ffd83dbSDimitry Andric 
238781ad6265SDimitry Andric   llvm::SmallString<0> logmsg;
238881ad6265SDimitry Andric   if (VASprintf(logmsg, fmt, args)) {
23895ffd83dbSDimitry Andric     LLDB_LOGF(log, "%*sth%d/fr%u %s",
23905ffd83dbSDimitry Andric               m_frame_number < 100 ? m_frame_number : 100, "",
239181ad6265SDimitry Andric               m_thread.GetIndexID(), m_frame_number, logmsg.c_str());
23925ffd83dbSDimitry Andric   }
239381ad6265SDimitry Andric   va_end(args);
23945ffd83dbSDimitry Andric }
2395