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 ®loc) { 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 ®num, 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