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" 405ffd83dbSDimitry Andric #include <memory> 415ffd83dbSDimitry Andric 425ffd83dbSDimitry Andric using namespace lldb; 435ffd83dbSDimitry Andric using namespace lldb_private; 445ffd83dbSDimitry Andric 455ffd83dbSDimitry Andric static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) { 465ffd83dbSDimitry Andric if (sym_ctx.symbol) 475ffd83dbSDimitry Andric return sym_ctx.symbol->GetName(); 485ffd83dbSDimitry Andric else if (sym_ctx.function) 495ffd83dbSDimitry Andric return sym_ctx.function->GetName(); 505ffd83dbSDimitry Andric return ConstString(); 515ffd83dbSDimitry Andric } 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric RegisterContextUnwind::RegisterContextUnwind(Thread &thread, 545ffd83dbSDimitry Andric const SharedPtr &next_frame, 555ffd83dbSDimitry Andric SymbolContext &sym_ctx, 565ffd83dbSDimitry Andric uint32_t frame_number, 575ffd83dbSDimitry Andric UnwindLLDB &unwind_lldb) 585ffd83dbSDimitry Andric : RegisterContext(thread, frame_number), m_thread(thread), 595ffd83dbSDimitry Andric m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(), 605ffd83dbSDimitry Andric m_fallback_unwind_plan_sp(), m_all_registers_available(false), 615ffd83dbSDimitry Andric m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS), 62fe6060f1SDimitry Andric m_afa(LLDB_INVALID_ADDRESS), m_start_pc(), m_current_pc(), 63fe6060f1SDimitry Andric m_current_offset(0), m_current_offset_backed_up_one(0), 64fe6060f1SDimitry Andric m_behaves_like_zeroth_frame(false), m_sym_ctx(sym_ctx), 65fe6060f1SDimitry Andric m_sym_ctx_valid(false), m_frame_number(frame_number), m_registers(), 66fe6060f1SDimitry Andric m_parent_unwind(unwind_lldb) { 675ffd83dbSDimitry Andric m_sym_ctx.Clear(false); 685ffd83dbSDimitry Andric m_sym_ctx_valid = false; 695ffd83dbSDimitry Andric 705ffd83dbSDimitry Andric if (IsFrameZero()) { 715ffd83dbSDimitry Andric InitializeZerothFrame(); 725ffd83dbSDimitry Andric } else { 735ffd83dbSDimitry Andric InitializeNonZerothFrame(); 745ffd83dbSDimitry Andric } 755ffd83dbSDimitry Andric 765ffd83dbSDimitry Andric // This same code exists over in the GetFullUnwindPlanForFrame() but it may 775ffd83dbSDimitry Andric // not have been executed yet 785ffd83dbSDimitry Andric if (IsFrameZero() || next_frame->m_frame_type == eTrapHandlerFrame || 795ffd83dbSDimitry Andric next_frame->m_frame_type == eDebuggerFrame) { 805ffd83dbSDimitry Andric m_all_registers_available = true; 815ffd83dbSDimitry Andric } 825ffd83dbSDimitry Andric } 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC( 8581ad6265SDimitry Andric lldb::UnwindPlanSP unwind_plan_sp) { 865ffd83dbSDimitry Andric if (!unwind_plan_sp) 875ffd83dbSDimitry Andric return false; 885ffd83dbSDimitry Andric 895ffd83dbSDimitry Andric // check if m_current_pc is valid 905ffd83dbSDimitry Andric if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 915ffd83dbSDimitry Andric // yes - current offset can be used as is 925ffd83dbSDimitry Andric return true; 935ffd83dbSDimitry Andric } 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric // if m_current_offset <= 0, we've got nothing else to try 965ffd83dbSDimitry Andric if (m_current_offset <= 0) 975ffd83dbSDimitry Andric return false; 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric // check pc - 1 to see if it's valid 1005ffd83dbSDimitry Andric Address pc_minus_one(m_current_pc); 1015ffd83dbSDimitry Andric pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1); 1025ffd83dbSDimitry Andric if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) { 1035ffd83dbSDimitry Andric return true; 1045ffd83dbSDimitry Andric } 1055ffd83dbSDimitry Andric 1065ffd83dbSDimitry Andric return false; 1075ffd83dbSDimitry Andric } 1085ffd83dbSDimitry Andric 1095ffd83dbSDimitry Andric // Initialize a RegisterContextUnwind which is the first frame of a stack -- the 1105ffd83dbSDimitry Andric // zeroth frame or currently executing frame. 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric void RegisterContextUnwind::InitializeZerothFrame() { 11381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 1145ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 1155ffd83dbSDimitry Andric RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric if (reg_ctx_sp.get() == nullptr) { 1185ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 1195ffd83dbSDimitry Andric UnwindLogMsg("frame does not have a register context"); 1205ffd83dbSDimitry Andric return; 1215ffd83dbSDimitry Andric } 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric addr_t current_pc = reg_ctx_sp->GetPC(); 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric if (current_pc == LLDB_INVALID_ADDRESS) { 1265ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 1275ffd83dbSDimitry Andric UnwindLogMsg("frame does not have a pc"); 1285ffd83dbSDimitry Andric return; 1295ffd83dbSDimitry Andric } 1305ffd83dbSDimitry Andric 1315ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 1325ffd83dbSDimitry Andric 1335ffd83dbSDimitry Andric // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs 1345ffd83dbSDimitry Andric // this will strip bit zero in case we read a PC from memory or from the LR. 1355ffd83dbSDimitry Andric // (which would be a no-op in frame 0 where we get it from the register set, 1365ffd83dbSDimitry Andric // but still a good idea to make the call here for other ABIs that may 1375ffd83dbSDimitry Andric // exist.) 1385ffd83dbSDimitry Andric ABI *abi = process->GetABI().get(); 1395ffd83dbSDimitry Andric if (abi) 1405ffd83dbSDimitry Andric current_pc = abi->FixCodeAddress(current_pc); 1415ffd83dbSDimitry Andric 142fe6060f1SDimitry Andric UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan( 143fe6060f1SDimitry Andric m_thread, this, m_behaves_like_zeroth_frame); 144fe6060f1SDimitry Andric if (lang_runtime_plan_sp.get()) { 145fe6060f1SDimitry Andric UnwindLogMsg("This is an async frame"); 146fe6060f1SDimitry Andric } 147fe6060f1SDimitry Andric 1485ffd83dbSDimitry Andric // Initialize m_current_pc, an Address object, based on current_pc, an 1495ffd83dbSDimitry Andric // addr_t. 1505ffd83dbSDimitry Andric m_current_pc.SetLoadAddress(current_pc, &process->GetTarget()); 1515ffd83dbSDimitry Andric 1525ffd83dbSDimitry Andric // If we don't have a Module for some reason, we're not going to find 1535ffd83dbSDimitry Andric // symbol/function information - just stick in some reasonable defaults and 1545ffd83dbSDimitry Andric // hope we can unwind past this frame. 1555ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 1565ffd83dbSDimitry Andric if (!m_current_pc.IsValid() || !pc_module_sp) { 1575ffd83dbSDimitry Andric UnwindLogMsg("using architectural default unwind method"); 1585ffd83dbSDimitry Andric } 1595ffd83dbSDimitry Andric 1605ffd83dbSDimitry Andric AddressRange addr_range; 1615ffd83dbSDimitry Andric m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 1625ffd83dbSDimitry Andric 1635ffd83dbSDimitry Andric if (m_sym_ctx.symbol) { 1645ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", 1655ffd83dbSDimitry Andric current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 1665ffd83dbSDimitry Andric } else if (m_sym_ctx.function) { 1675ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", 1685ffd83dbSDimitry Andric current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 1695ffd83dbSDimitry Andric } else { 1705ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 1715ffd83dbSDimitry Andric ", no symbol/function name is known.", 1725ffd83dbSDimitry Andric current_pc); 1735ffd83dbSDimitry Andric } 1745ffd83dbSDimitry Andric 1755ffd83dbSDimitry Andric if (IsTrapHandlerSymbol(process, m_sym_ctx)) { 1765ffd83dbSDimitry Andric m_frame_type = eTrapHandlerFrame; 1775ffd83dbSDimitry Andric } else { 1785ffd83dbSDimitry Andric // FIXME: Detect eDebuggerFrame here. 1795ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 1805ffd83dbSDimitry Andric } 1815ffd83dbSDimitry Andric 1825ffd83dbSDimitry Andric // If we were able to find a symbol/function, set addr_range to the bounds of 1835ffd83dbSDimitry Andric // that symbol/function. else treat the current pc value as the start_pc and 1845ffd83dbSDimitry Andric // record no offset. 1855ffd83dbSDimitry Andric if (addr_range.GetBaseAddress().IsValid()) { 1865ffd83dbSDimitry Andric m_start_pc = addr_range.GetBaseAddress(); 1875ffd83dbSDimitry Andric if (m_current_pc.GetSection() == m_start_pc.GetSection()) { 1885ffd83dbSDimitry Andric m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset(); 1895ffd83dbSDimitry Andric } else if (m_current_pc.GetModule() == m_start_pc.GetModule()) { 1905ffd83dbSDimitry Andric // This means that whatever symbol we kicked up isn't really correct --- 1915ffd83dbSDimitry Andric // we should not cross section boundaries ... We really should NULL out 1925ffd83dbSDimitry Andric // the function/symbol in this case unless there is a bad assumption here 1935ffd83dbSDimitry Andric // due to inlined functions? 1945ffd83dbSDimitry Andric m_current_offset = 1955ffd83dbSDimitry Andric m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress(); 1965ffd83dbSDimitry Andric } 1975ffd83dbSDimitry Andric m_current_offset_backed_up_one = m_current_offset; 1985ffd83dbSDimitry Andric } else { 1995ffd83dbSDimitry Andric m_start_pc = m_current_pc; 2005ffd83dbSDimitry Andric m_current_offset = -1; 2015ffd83dbSDimitry Andric m_current_offset_backed_up_one = -1; 2025ffd83dbSDimitry Andric } 2035ffd83dbSDimitry Andric 2045ffd83dbSDimitry Andric // We've set m_frame_type and m_sym_ctx before these calls. 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame(); 2075ffd83dbSDimitry Andric m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); 2085ffd83dbSDimitry Andric 2095ffd83dbSDimitry Andric UnwindPlan::RowSP active_row; 2105ffd83dbSDimitry Andric lldb::RegisterKind row_register_kind = eRegisterKindGeneric; 211fe6060f1SDimitry Andric 212fe6060f1SDimitry Andric // If we have LanguageRuntime UnwindPlan for this unwind, use those 213fe6060f1SDimitry Andric // rules to find the caller frame instead of the function's normal 214fe6060f1SDimitry Andric // UnwindPlans. The full unwind plan for this frame will be 215fe6060f1SDimitry Andric // the LanguageRuntime-provided unwind plan, and there will not be a 216fe6060f1SDimitry Andric // fast unwind plan. 217fe6060f1SDimitry Andric if (lang_runtime_plan_sp.get()) { 218fe6060f1SDimitry Andric active_row = 219fe6060f1SDimitry Andric lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset); 220fe6060f1SDimitry Andric row_register_kind = lang_runtime_plan_sp->GetRegisterKind(); 221fe6060f1SDimitry Andric if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), 222fe6060f1SDimitry Andric m_cfa)) { 223fe6060f1SDimitry Andric UnwindLogMsg("Cannot set cfa"); 224fe6060f1SDimitry Andric } else { 225fe6060f1SDimitry Andric m_full_unwind_plan_sp = lang_runtime_plan_sp; 226fe6060f1SDimitry Andric if (log) { 227fe6060f1SDimitry Andric StreamString active_row_strm; 228fe6060f1SDimitry Andric active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread, 229fe6060f1SDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 230fe6060f1SDimitry Andric UnwindLogMsg("async active row: %s", active_row_strm.GetData()); 231fe6060f1SDimitry Andric } 232fe6060f1SDimitry Andric UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa); 233fe6060f1SDimitry Andric UnwindLogMsg( 234fe6060f1SDimitry Andric "initialized async frame current pc is 0x%" PRIx64 235fe6060f1SDimitry Andric " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64, 236fe6060f1SDimitry Andric (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), 237fe6060f1SDimitry Andric (uint64_t)m_cfa, (uint64_t)m_afa); 238fe6060f1SDimitry Andric 239fe6060f1SDimitry Andric return; 240fe6060f1SDimitry Andric } 241fe6060f1SDimitry Andric } 242fe6060f1SDimitry Andric 2435ffd83dbSDimitry Andric if (m_full_unwind_plan_sp && 2445ffd83dbSDimitry Andric m_full_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 2455ffd83dbSDimitry Andric active_row = 2465ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 2475ffd83dbSDimitry Andric row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); 2485ffd83dbSDimitry Andric if (active_row.get() && log) { 2495ffd83dbSDimitry Andric StreamString active_row_strm; 2505ffd83dbSDimitry Andric active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, 2515ffd83dbSDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 2525ffd83dbSDimitry Andric UnwindLogMsg("%s", active_row_strm.GetData()); 2535ffd83dbSDimitry Andric } 2545ffd83dbSDimitry Andric } 2555ffd83dbSDimitry Andric 2565ffd83dbSDimitry Andric if (!active_row.get()) { 2575ffd83dbSDimitry Andric UnwindLogMsg("could not find an unwindplan row for this frame's pc"); 2585ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 2595ffd83dbSDimitry Andric return; 2605ffd83dbSDimitry Andric } 2615ffd83dbSDimitry Andric 2625ffd83dbSDimitry Andric if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) { 2635ffd83dbSDimitry Andric // Try the fall back unwind plan since the 2645ffd83dbSDimitry Andric // full unwind plan failed. 2655ffd83dbSDimitry Andric FuncUnwindersSP func_unwinders_sp; 2665ffd83dbSDimitry Andric UnwindPlanSP call_site_unwind_plan; 2675ffd83dbSDimitry Andric bool cfa_status = false; 2685ffd83dbSDimitry Andric 2695ffd83dbSDimitry Andric if (m_sym_ctx_valid) { 2705ffd83dbSDimitry Andric func_unwinders_sp = 2715ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress( 2725ffd83dbSDimitry Andric m_current_pc, m_sym_ctx); 2735ffd83dbSDimitry Andric } 2745ffd83dbSDimitry Andric 2755ffd83dbSDimitry Andric if (func_unwinders_sp.get() != nullptr) 2765ffd83dbSDimitry Andric call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite( 2775ffd83dbSDimitry Andric process->GetTarget(), m_thread); 2785ffd83dbSDimitry Andric 2795ffd83dbSDimitry Andric if (call_site_unwind_plan.get() != nullptr) { 2805ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = call_site_unwind_plan; 2815ffd83dbSDimitry Andric if (TryFallbackUnwindPlan()) 2825ffd83dbSDimitry Andric cfa_status = true; 2835ffd83dbSDimitry Andric } 2845ffd83dbSDimitry Andric if (!cfa_status) { 2855ffd83dbSDimitry Andric UnwindLogMsg("could not read CFA value for first frame."); 2865ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 2875ffd83dbSDimitry Andric return; 2885ffd83dbSDimitry Andric } 2895ffd83dbSDimitry Andric } else 2905ffd83dbSDimitry Andric ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa); 2915ffd83dbSDimitry Andric 2925ffd83dbSDimitry Andric UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 2935ffd83dbSDimitry Andric " afa is 0x%" PRIx64 " using %s UnwindPlan", 2945ffd83dbSDimitry Andric (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), 2955ffd83dbSDimitry Andric (uint64_t)m_cfa, 2965ffd83dbSDimitry Andric (uint64_t)m_afa, 2975ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 2985ffd83dbSDimitry Andric } 2995ffd83dbSDimitry Andric 3005ffd83dbSDimitry Andric // Initialize a RegisterContextUnwind for the non-zeroth frame -- rely on the 3015ffd83dbSDimitry Andric // RegisterContextUnwind "below" it to provide things like its current pc value. 3025ffd83dbSDimitry Andric 3035ffd83dbSDimitry Andric void RegisterContextUnwind::InitializeNonZerothFrame() { 30481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 3055ffd83dbSDimitry Andric if (IsFrameZero()) { 3065ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 3075ffd83dbSDimitry Andric UnwindLogMsg("non-zeroth frame tests positive for IsFrameZero -- that " 3085ffd83dbSDimitry Andric "shouldn't happen."); 3095ffd83dbSDimitry Andric return; 3105ffd83dbSDimitry Andric } 3115ffd83dbSDimitry Andric 3125ffd83dbSDimitry Andric if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) { 3135ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 3145ffd83dbSDimitry Andric UnwindLogMsg("Could not get next frame, marking this frame as invalid."); 3155ffd83dbSDimitry Andric return; 3165ffd83dbSDimitry Andric } 3175ffd83dbSDimitry Andric if (!m_thread.GetRegisterContext()) { 3185ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 3195ffd83dbSDimitry Andric UnwindLogMsg("Could not get register context for this thread, marking this " 3205ffd83dbSDimitry Andric "frame as invalid."); 3215ffd83dbSDimitry Andric return; 3225ffd83dbSDimitry Andric } 3235ffd83dbSDimitry Andric 324fe6060f1SDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 325fe6060f1SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 326fe6060f1SDimitry Andric 327fe6060f1SDimitry Andric // Some languages may have a logical parent stack frame which is 328fe6060f1SDimitry Andric // not a real stack frame, but the programmer would consider it to 329fe6060f1SDimitry Andric // be the caller of the frame, e.g. Swift asynchronous frames. 330fe6060f1SDimitry Andric // 331fe6060f1SDimitry Andric // A LanguageRuntime may provide an UnwindPlan that is used in this 332fe6060f1SDimitry Andric // stack trace base on the RegisterContext contents, intsead 333fe6060f1SDimitry Andric // of the normal UnwindPlans we would use for the return-pc. 334fe6060f1SDimitry Andric UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan( 335fe6060f1SDimitry Andric m_thread, this, m_behaves_like_zeroth_frame); 336fe6060f1SDimitry Andric if (lang_runtime_plan_sp.get()) { 337fe6060f1SDimitry Andric UnwindLogMsg("This is an async frame"); 338fe6060f1SDimitry Andric } 339fe6060f1SDimitry Andric 3405ffd83dbSDimitry Andric addr_t pc; 3415ffd83dbSDimitry Andric if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { 3425ffd83dbSDimitry Andric UnwindLogMsg("could not get pc value"); 3435ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 3445ffd83dbSDimitry Andric return; 3455ffd83dbSDimitry Andric } 3465ffd83dbSDimitry Andric 3475ffd83dbSDimitry Andric // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs 3485ffd83dbSDimitry Andric // this will strip bit zero in case we read a PC from memory or from the LR. 3495ffd83dbSDimitry Andric ABI *abi = process->GetABI().get(); 3505ffd83dbSDimitry Andric if (abi) 3515ffd83dbSDimitry Andric pc = abi->FixCodeAddress(pc); 3525ffd83dbSDimitry Andric 3535ffd83dbSDimitry Andric if (log) { 3545ffd83dbSDimitry Andric UnwindLogMsg("pc = 0x%" PRIx64, pc); 3555ffd83dbSDimitry Andric addr_t reg_val; 3565ffd83dbSDimitry Andric if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) 3575ffd83dbSDimitry Andric UnwindLogMsg("fp = 0x%" PRIx64, reg_val); 3585ffd83dbSDimitry Andric if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) 3595ffd83dbSDimitry Andric UnwindLogMsg("sp = 0x%" PRIx64, reg_val); 3605ffd83dbSDimitry Andric } 3615ffd83dbSDimitry Andric 3625ffd83dbSDimitry Andric // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap 3635ffd83dbSDimitry Andric // handler function 3645ffd83dbSDimitry Andric bool above_trap_handler = false; 3655ffd83dbSDimitry Andric if (GetNextFrame().get() && GetNextFrame()->IsValid() && 3665ffd83dbSDimitry Andric GetNextFrame()->IsTrapHandlerFrame()) 3675ffd83dbSDimitry Andric above_trap_handler = true; 3685ffd83dbSDimitry Andric 3695ffd83dbSDimitry Andric if (pc == 0 || pc == 0x1) { 3705ffd83dbSDimitry Andric if (!above_trap_handler) { 3715ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 3725ffd83dbSDimitry Andric UnwindLogMsg("this frame has a pc of 0x0"); 3735ffd83dbSDimitry Andric return; 3745ffd83dbSDimitry Andric } 3755ffd83dbSDimitry Andric } 3765ffd83dbSDimitry Andric 3775ffd83dbSDimitry Andric const bool allow_section_end = true; 3785ffd83dbSDimitry Andric m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end); 3795ffd83dbSDimitry Andric 3805ffd83dbSDimitry Andric // If we don't have a Module for some reason, we're not going to find 3815ffd83dbSDimitry Andric // symbol/function information - just stick in some reasonable defaults and 3825ffd83dbSDimitry Andric // hope we can unwind past this frame. If we're above a trap handler, 3835ffd83dbSDimitry Andric // we may be at a bogus address because we jumped through a bogus function 3845ffd83dbSDimitry Andric // pointer and trapped, so don't force the arch default unwind plan in that 3855ffd83dbSDimitry Andric // case. 3865ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 3875ffd83dbSDimitry Andric if ((!m_current_pc.IsValid() || !pc_module_sp) && 3885ffd83dbSDimitry Andric above_trap_handler == false) { 3895ffd83dbSDimitry Andric UnwindLogMsg("using architectural default unwind method"); 3905ffd83dbSDimitry Andric 3915ffd83dbSDimitry Andric // Test the pc value to see if we know it's in an unmapped/non-executable 3925ffd83dbSDimitry Andric // region of memory. 3935ffd83dbSDimitry Andric uint32_t permissions; 3945ffd83dbSDimitry Andric if (process->GetLoadAddressPermissions(pc, permissions) && 3955ffd83dbSDimitry Andric (permissions & ePermissionsExecutable) == 0) { 3965ffd83dbSDimitry Andric // If this is the second frame off the stack, we may have unwound the 3975ffd83dbSDimitry Andric // first frame incorrectly. But using the architecture default unwind 3985ffd83dbSDimitry Andric // plan may get us back on track -- albeit possibly skipping a real 3995ffd83dbSDimitry Andric // frame. Give this frame a clearly-invalid pc and see if we can get any 4005ffd83dbSDimitry Andric // further. 4015ffd83dbSDimitry Andric if (GetNextFrame().get() && GetNextFrame()->IsValid() && 4025ffd83dbSDimitry Andric GetNextFrame()->IsFrameZero()) { 4035ffd83dbSDimitry Andric UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable " 4045ffd83dbSDimitry Andric "memory but on frame 1 -- " 4055ffd83dbSDimitry Andric "allowing it once.", 4065ffd83dbSDimitry Andric (uint64_t)pc); 4075ffd83dbSDimitry Andric m_frame_type = eSkipFrame; 4085ffd83dbSDimitry Andric } else { 4095ffd83dbSDimitry Andric // anywhere other than the second frame, a non-executable pc means 4105ffd83dbSDimitry Andric // we're off in the weeds -- stop now. 4115ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4125ffd83dbSDimitry Andric UnwindLogMsg("pc is in a non-executable section of memory and this " 4135ffd83dbSDimitry Andric "isn't the 2nd frame in the stack walk."); 4145ffd83dbSDimitry Andric return; 4155ffd83dbSDimitry Andric } 4165ffd83dbSDimitry Andric } 4175ffd83dbSDimitry Andric 4185ffd83dbSDimitry Andric if (abi) { 4195ffd83dbSDimitry Andric m_fast_unwind_plan_sp.reset(); 4205ffd83dbSDimitry Andric m_full_unwind_plan_sp = 4215ffd83dbSDimitry Andric std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 4225ffd83dbSDimitry Andric abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp); 4235ffd83dbSDimitry Andric if (m_frame_type != eSkipFrame) // don't override eSkipFrame 4245ffd83dbSDimitry Andric { 4255ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 4265ffd83dbSDimitry Andric } 4275ffd83dbSDimitry Andric m_all_registers_available = false; 4285ffd83dbSDimitry Andric m_current_offset = -1; 4295ffd83dbSDimitry Andric m_current_offset_backed_up_one = -1; 4305ffd83dbSDimitry Andric RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); 4315ffd83dbSDimitry Andric UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0); 4325ffd83dbSDimitry Andric if (row.get()) { 4335ffd83dbSDimitry Andric if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) { 4345ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa value"); 4355ffd83dbSDimitry Andric if (m_frame_type != eSkipFrame) // don't override eSkipFrame 4365ffd83dbSDimitry Andric { 4375ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4385ffd83dbSDimitry Andric } 4395ffd83dbSDimitry Andric return; 4405ffd83dbSDimitry Andric } 4415ffd83dbSDimitry Andric 4425ffd83dbSDimitry Andric ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa); 4435ffd83dbSDimitry Andric 4445ffd83dbSDimitry Andric // A couple of sanity checks.. 4455ffd83dbSDimitry Andric if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) { 4465ffd83dbSDimitry Andric UnwindLogMsg("could not find a valid cfa address"); 4475ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4485ffd83dbSDimitry Andric return; 4495ffd83dbSDimitry Andric } 4505ffd83dbSDimitry Andric 4515ffd83dbSDimitry Andric // m_cfa should point into the stack memory; if we can query memory 4525ffd83dbSDimitry Andric // region permissions, see if the memory is allocated & readable. 4535ffd83dbSDimitry Andric if (process->GetLoadAddressPermissions(m_cfa, permissions) && 4545ffd83dbSDimitry Andric (permissions & ePermissionsReadable) == 0) { 4555ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4565ffd83dbSDimitry Andric UnwindLogMsg( 4575ffd83dbSDimitry Andric "the CFA points to a region of memory that is not readable"); 4585ffd83dbSDimitry Andric return; 4595ffd83dbSDimitry Andric } 4605ffd83dbSDimitry Andric } else { 4615ffd83dbSDimitry Andric UnwindLogMsg("could not find a row for function offset zero"); 4625ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4635ffd83dbSDimitry Andric return; 4645ffd83dbSDimitry Andric } 4655ffd83dbSDimitry Andric 4665ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 4675ffd83dbSDimitry Andric TryFallbackUnwindPlan(); 4685ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 4695ffd83dbSDimitry Andric UnwindLogMsg("same CFA address as next frame, assuming the unwind is " 4705ffd83dbSDimitry Andric "looping - stopping"); 4715ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4725ffd83dbSDimitry Andric return; 4735ffd83dbSDimitry Andric } 4745ffd83dbSDimitry Andric } 4755ffd83dbSDimitry Andric 4765ffd83dbSDimitry Andric UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64, 4775ffd83dbSDimitry Andric (uint64_t)m_cfa, (uint64_t)m_afa); 4785ffd83dbSDimitry Andric return; 4795ffd83dbSDimitry Andric } 4805ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 4815ffd83dbSDimitry Andric UnwindLogMsg("could not find any symbol for this pc, or a default unwind " 4825ffd83dbSDimitry Andric "plan, to continue unwind."); 4835ffd83dbSDimitry Andric return; 4845ffd83dbSDimitry Andric } 4855ffd83dbSDimitry Andric 4865ffd83dbSDimitry Andric AddressRange addr_range; 4875ffd83dbSDimitry Andric m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 4885ffd83dbSDimitry Andric 4895ffd83dbSDimitry Andric if (m_sym_ctx.symbol) { 4905ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc, 4915ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 4925ffd83dbSDimitry Andric } else if (m_sym_ctx.function) { 4935ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", pc, 4945ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 4955ffd83dbSDimitry Andric } else { 4965ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 4975ffd83dbSDimitry Andric ", no symbol/function name is known.", 4985ffd83dbSDimitry Andric pc); 4995ffd83dbSDimitry Andric } 5005ffd83dbSDimitry Andric 5015ffd83dbSDimitry Andric bool decr_pc_and_recompute_addr_range; 5025ffd83dbSDimitry Andric 5035ffd83dbSDimitry Andric if (!m_sym_ctx_valid) { 5045ffd83dbSDimitry Andric // Always decrement and recompute if the symbol lookup failed 5055ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = true; 5065ffd83dbSDimitry Andric } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame || 5075ffd83dbSDimitry Andric GetNextFrame()->m_frame_type == eDebuggerFrame) { 5085ffd83dbSDimitry Andric // Don't decrement if we're "above" an asynchronous event like 5095ffd83dbSDimitry Andric // sigtramp. 5105ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = false; 5115ffd83dbSDimitry Andric } else if (!addr_range.GetBaseAddress().IsValid() || 5125ffd83dbSDimitry Andric addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() || 5135ffd83dbSDimitry Andric addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) { 51481ad6265SDimitry Andric // If our "current" pc isn't the start of a function, decrement the pc 51581ad6265SDimitry Andric // if we're up the stack. 51681ad6265SDimitry Andric if (m_behaves_like_zeroth_frame) 5175ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = false; 51881ad6265SDimitry Andric else 51981ad6265SDimitry Andric decr_pc_and_recompute_addr_range = true; 5205ffd83dbSDimitry Andric } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) { 5215ffd83dbSDimitry Andric // Signal dispatch may set the return address of the handler it calls to 5225ffd83dbSDimitry Andric // point to the first byte of a return trampoline (like __kernel_rt_sigreturn), 5235ffd83dbSDimitry Andric // so do not decrement and recompute if the symbol we already found is a trap 5245ffd83dbSDimitry Andric // handler. 5255ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = false; 526fe6060f1SDimitry Andric } else if (m_behaves_like_zeroth_frame) { 527fe6060f1SDimitry Andric decr_pc_and_recompute_addr_range = false; 5285ffd83dbSDimitry Andric } else { 5295ffd83dbSDimitry Andric // Decrement to find the function containing the call. 5305ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = true; 5315ffd83dbSDimitry Andric } 5325ffd83dbSDimitry Andric 5335ffd83dbSDimitry Andric // We need to back up the pc by 1 byte and re-search for the Symbol to handle 5345ffd83dbSDimitry Andric // the case where the "saved pc" value is pointing to the next function, e.g. 5355ffd83dbSDimitry Andric // if a function ends with a CALL instruction. 5365ffd83dbSDimitry Andric // FIXME this may need to be an architectural-dependent behavior; if so we'll 5375ffd83dbSDimitry Andric // need to add a member function 5385ffd83dbSDimitry Andric // to the ABI plugin and consult that. 5395ffd83dbSDimitry Andric if (decr_pc_and_recompute_addr_range) { 5405ffd83dbSDimitry Andric UnwindLogMsg("Backing up the pc value of 0x%" PRIx64 5415ffd83dbSDimitry Andric " by 1 and re-doing symbol lookup; old symbol was %s", 5425ffd83dbSDimitry Andric pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 5435ffd83dbSDimitry Andric Address temporary_pc; 5445ffd83dbSDimitry Andric temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget()); 5455ffd83dbSDimitry Andric m_sym_ctx.Clear(false); 5465ffd83dbSDimitry Andric m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 5475ffd83dbSDimitry Andric 5485ffd83dbSDimitry Andric UnwindLogMsg("Symbol is now %s", 5495ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 5505ffd83dbSDimitry Andric } 5515ffd83dbSDimitry Andric 5525ffd83dbSDimitry Andric // If we were able to find a symbol/function, set addr_range_ptr to the 5535ffd83dbSDimitry Andric // bounds of that symbol/function. else treat the current pc value as the 5545ffd83dbSDimitry Andric // start_pc and record no offset. 5555ffd83dbSDimitry Andric if (addr_range.GetBaseAddress().IsValid()) { 5565ffd83dbSDimitry Andric m_start_pc = addr_range.GetBaseAddress(); 5575ffd83dbSDimitry Andric m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget()); 5585ffd83dbSDimitry Andric m_current_offset_backed_up_one = m_current_offset; 5595ffd83dbSDimitry Andric if (decr_pc_and_recompute_addr_range && 5605ffd83dbSDimitry Andric m_current_offset_backed_up_one > 0) { 5615ffd83dbSDimitry Andric m_current_offset_backed_up_one--; 5625ffd83dbSDimitry Andric if (m_sym_ctx_valid) { 5635ffd83dbSDimitry Andric m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget()); 5645ffd83dbSDimitry Andric } 5655ffd83dbSDimitry Andric } 5665ffd83dbSDimitry Andric } else { 5675ffd83dbSDimitry Andric m_start_pc = m_current_pc; 5685ffd83dbSDimitry Andric m_current_offset = -1; 5695ffd83dbSDimitry Andric m_current_offset_backed_up_one = -1; 5705ffd83dbSDimitry Andric } 5715ffd83dbSDimitry Andric 5725ffd83dbSDimitry Andric if (IsTrapHandlerSymbol(process, m_sym_ctx)) { 5735ffd83dbSDimitry Andric m_frame_type = eTrapHandlerFrame; 5745ffd83dbSDimitry Andric } else { 5755ffd83dbSDimitry Andric // FIXME: Detect eDebuggerFrame here. 5765ffd83dbSDimitry Andric if (m_frame_type != eSkipFrame) // don't override eSkipFrame 5775ffd83dbSDimitry Andric { 5785ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 5795ffd83dbSDimitry Andric } 5805ffd83dbSDimitry Andric } 5815ffd83dbSDimitry Andric 5825ffd83dbSDimitry Andric UnwindPlan::RowSP active_row; 5835ffd83dbSDimitry Andric RegisterKind row_register_kind = eRegisterKindGeneric; 5845ffd83dbSDimitry Andric 585fe6060f1SDimitry Andric // If we have LanguageRuntime UnwindPlan for this unwind, use those 586fe6060f1SDimitry Andric // rules to find the caller frame instead of the function's normal 587fe6060f1SDimitry Andric // UnwindPlans. The full unwind plan for this frame will be 588fe6060f1SDimitry Andric // the LanguageRuntime-provided unwind plan, and there will not be a 589fe6060f1SDimitry Andric // fast unwind plan. 590fe6060f1SDimitry Andric if (lang_runtime_plan_sp.get()) { 591fe6060f1SDimitry Andric active_row = 592fe6060f1SDimitry Andric lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset); 593fe6060f1SDimitry Andric row_register_kind = lang_runtime_plan_sp->GetRegisterKind(); 594fe6060f1SDimitry Andric if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), 595fe6060f1SDimitry Andric m_cfa)) { 596fe6060f1SDimitry Andric UnwindLogMsg("Cannot set cfa"); 597fe6060f1SDimitry Andric } else { 598fe6060f1SDimitry Andric m_full_unwind_plan_sp = lang_runtime_plan_sp; 599fe6060f1SDimitry Andric if (log) { 600fe6060f1SDimitry Andric StreamString active_row_strm; 601fe6060f1SDimitry Andric active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread, 602fe6060f1SDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 603fe6060f1SDimitry Andric UnwindLogMsg("async active row: %s", active_row_strm.GetData()); 604fe6060f1SDimitry Andric } 605fe6060f1SDimitry Andric UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa); 606fe6060f1SDimitry Andric UnwindLogMsg( 607fe6060f1SDimitry Andric "initialized async frame current pc is 0x%" PRIx64 608fe6060f1SDimitry Andric " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64, 609fe6060f1SDimitry Andric (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), 610fe6060f1SDimitry Andric (uint64_t)m_cfa, (uint64_t)m_afa); 611fe6060f1SDimitry Andric 612fe6060f1SDimitry Andric return; 613fe6060f1SDimitry Andric } 614fe6060f1SDimitry Andric } 615fe6060f1SDimitry Andric 616fe6060f1SDimitry Andric // We've set m_frame_type and m_sym_ctx before this call. 617fe6060f1SDimitry Andric m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame(); 618fe6060f1SDimitry Andric 6195ffd83dbSDimitry Andric // Try to get by with just the fast UnwindPlan if possible - the full 6205ffd83dbSDimitry Andric // UnwindPlan may be expensive to get (e.g. if we have to parse the entire 6215ffd83dbSDimitry Andric // eh_frame section of an ObjectFile for the first time.) 6225ffd83dbSDimitry Andric 6235ffd83dbSDimitry Andric if (m_fast_unwind_plan_sp && 6245ffd83dbSDimitry Andric m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 6255ffd83dbSDimitry Andric active_row = 6265ffd83dbSDimitry Andric m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 6275ffd83dbSDimitry Andric row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind(); 6285ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp); 6295ffd83dbSDimitry Andric if (active_row.get() && log) { 6305ffd83dbSDimitry Andric StreamString active_row_strm; 6315ffd83dbSDimitry Andric active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, 6325ffd83dbSDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 633fe6060f1SDimitry Andric UnwindLogMsg("Using fast unwind plan '%s'", 634fe6060f1SDimitry Andric m_fast_unwind_plan_sp->GetSourceName().AsCString()); 6355ffd83dbSDimitry Andric UnwindLogMsg("active row: %s", active_row_strm.GetData()); 6365ffd83dbSDimitry Andric } 6375ffd83dbSDimitry Andric } else { 6385ffd83dbSDimitry Andric m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); 63981ad6265SDimitry Andric if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp)) { 64081ad6265SDimitry Andric active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset( 64181ad6265SDimitry Andric m_current_offset_backed_up_one); 6425ffd83dbSDimitry Andric row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); 6435ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); 6445ffd83dbSDimitry Andric if (active_row.get() && log) { 6455ffd83dbSDimitry Andric StreamString active_row_strm; 6465ffd83dbSDimitry Andric active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), 6475ffd83dbSDimitry Andric &m_thread, 6485ffd83dbSDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 649fe6060f1SDimitry Andric UnwindLogMsg("Using full unwind plan '%s'", 650fe6060f1SDimitry Andric m_full_unwind_plan_sp->GetSourceName().AsCString()); 6515ffd83dbSDimitry Andric UnwindLogMsg("active row: %s", active_row_strm.GetData()); 6525ffd83dbSDimitry Andric } 6535ffd83dbSDimitry Andric } 6545ffd83dbSDimitry Andric } 6555ffd83dbSDimitry Andric 6565ffd83dbSDimitry Andric if (!active_row.get()) { 6575ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 6585ffd83dbSDimitry Andric UnwindLogMsg("could not find unwind row for this pc"); 6595ffd83dbSDimitry Andric return; 6605ffd83dbSDimitry Andric } 6615ffd83dbSDimitry Andric 6625ffd83dbSDimitry Andric if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) { 6635ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa"); 6645ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 6655ffd83dbSDimitry Andric return; 6665ffd83dbSDimitry Andric } 6675ffd83dbSDimitry Andric 6685ffd83dbSDimitry Andric ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa); 6695ffd83dbSDimitry Andric 6705ffd83dbSDimitry Andric UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa); 6715ffd83dbSDimitry Andric 6725ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 6735ffd83dbSDimitry Andric TryFallbackUnwindPlan(); 6745ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 6755ffd83dbSDimitry Andric UnwindLogMsg("same CFA address as next frame, assuming the unwind is " 6765ffd83dbSDimitry Andric "looping - stopping"); 6775ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 6785ffd83dbSDimitry Andric return; 6795ffd83dbSDimitry Andric } 6805ffd83dbSDimitry Andric } 6815ffd83dbSDimitry Andric 6825ffd83dbSDimitry Andric UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 6835ffd83dbSDimitry Andric " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64, 6845ffd83dbSDimitry Andric (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), 6855ffd83dbSDimitry Andric (uint64_t)m_cfa, 6865ffd83dbSDimitry Andric (uint64_t)m_afa); 6875ffd83dbSDimitry Andric } 6885ffd83dbSDimitry Andric 6895ffd83dbSDimitry Andric bool RegisterContextUnwind::CheckIfLoopingStack() { 6905ffd83dbSDimitry Andric // If we have a bad stack setup, we can get the same CFA value multiple times 6915ffd83dbSDimitry Andric // -- or even more devious, we can actually oscillate between two CFA values. 6925ffd83dbSDimitry Andric // Detect that here and break out to avoid a possible infinite loop in lldb 6935ffd83dbSDimitry Andric // trying to unwind the stack. To detect when we have the same CFA value 6945ffd83dbSDimitry Andric // multiple times, we compare the 6955ffd83dbSDimitry Andric // CFA of the current 6965ffd83dbSDimitry Andric // frame with the 2nd next frame because in some specail case (e.g. signal 6975ffd83dbSDimitry Andric // hanlders, hand written assembly without ABI compliance) we can have 2 6985ffd83dbSDimitry Andric // frames with the same 6995ffd83dbSDimitry Andric // CFA (in theory we 7005ffd83dbSDimitry Andric // can have arbitrary number of frames with the same CFA, but more then 2 is 7015ffd83dbSDimitry Andric // very very unlikely) 7025ffd83dbSDimitry Andric 7035ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr next_frame = GetNextFrame(); 7045ffd83dbSDimitry Andric if (next_frame) { 7055ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr next_next_frame = 7065ffd83dbSDimitry Andric next_frame->GetNextFrame(); 7075ffd83dbSDimitry Andric addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; 7085ffd83dbSDimitry Andric if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa)) { 7095ffd83dbSDimitry Andric if (next_next_frame_cfa == m_cfa) { 7105ffd83dbSDimitry Andric // We have a loop in the stack unwind 7115ffd83dbSDimitry Andric return true; 7125ffd83dbSDimitry Andric } 7135ffd83dbSDimitry Andric } 7145ffd83dbSDimitry Andric } 7155ffd83dbSDimitry Andric return false; 7165ffd83dbSDimitry Andric } 7175ffd83dbSDimitry Andric 7185ffd83dbSDimitry Andric bool RegisterContextUnwind::IsFrameZero() const { return m_frame_number == 0; } 7195ffd83dbSDimitry Andric 720fe6060f1SDimitry Andric bool RegisterContextUnwind::BehavesLikeZerothFrame() const { 721fe6060f1SDimitry Andric if (m_frame_number == 0) 722fe6060f1SDimitry Andric return true; 723fe6060f1SDimitry Andric if (m_behaves_like_zeroth_frame) 724fe6060f1SDimitry Andric return true; 725fe6060f1SDimitry Andric return false; 726fe6060f1SDimitry Andric } 727fe6060f1SDimitry Andric 7285ffd83dbSDimitry Andric // Find a fast unwind plan for this frame, if possible. 7295ffd83dbSDimitry Andric // 7305ffd83dbSDimitry Andric // On entry to this method, 7315ffd83dbSDimitry Andric // 7325ffd83dbSDimitry Andric // 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame 7335ffd83dbSDimitry Andric // if either of those are correct, 7345ffd83dbSDimitry Andric // 2. m_sym_ctx should already be filled in, and 7355ffd83dbSDimitry Andric // 3. m_current_pc should have the current pc value for this frame 7365ffd83dbSDimitry Andric // 4. m_current_offset_backed_up_one should have the current byte offset into 7375ffd83dbSDimitry Andric // the function, maybe backed up by 1, -1 if unknown 7385ffd83dbSDimitry Andric 7395ffd83dbSDimitry Andric UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() { 7405ffd83dbSDimitry Andric UnwindPlanSP unwind_plan_sp; 7415ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 7425ffd83dbSDimitry Andric 7435ffd83dbSDimitry Andric if (!m_current_pc.IsValid() || !pc_module_sp || 7445ffd83dbSDimitry Andric pc_module_sp->GetObjectFile() == nullptr) 7455ffd83dbSDimitry Andric return unwind_plan_sp; 7465ffd83dbSDimitry Andric 7475ffd83dbSDimitry Andric if (IsFrameZero()) 7485ffd83dbSDimitry Andric return unwind_plan_sp; 7495ffd83dbSDimitry Andric 7505ffd83dbSDimitry Andric FuncUnwindersSP func_unwinders_sp( 7515ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress( 7525ffd83dbSDimitry Andric m_current_pc, m_sym_ctx)); 7535ffd83dbSDimitry Andric if (!func_unwinders_sp) 7545ffd83dbSDimitry Andric return unwind_plan_sp; 7555ffd83dbSDimitry Andric 7565ffd83dbSDimitry Andric // If we're in _sigtramp(), unwinding past this frame requires special 7575ffd83dbSDimitry Andric // knowledge. 7585ffd83dbSDimitry Andric if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame) 7595ffd83dbSDimitry Andric return unwind_plan_sp; 7605ffd83dbSDimitry Andric 7615ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind( 7625ffd83dbSDimitry Andric *m_thread.CalculateTarget(), m_thread); 7635ffd83dbSDimitry Andric if (unwind_plan_sp) { 7645ffd83dbSDimitry Andric if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 7655ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 7665ffd83dbSDimitry Andric return unwind_plan_sp; 7675ffd83dbSDimitry Andric } else { 7685ffd83dbSDimitry Andric unwind_plan_sp.reset(); 7695ffd83dbSDimitry Andric } 7705ffd83dbSDimitry Andric } 7715ffd83dbSDimitry Andric return unwind_plan_sp; 7725ffd83dbSDimitry Andric } 7735ffd83dbSDimitry Andric 7745ffd83dbSDimitry Andric // On entry to this method, 7755ffd83dbSDimitry Andric // 7765ffd83dbSDimitry Andric // 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame 7775ffd83dbSDimitry Andric // if either of those are correct, 7785ffd83dbSDimitry Andric // 2. m_sym_ctx should already be filled in, and 7795ffd83dbSDimitry Andric // 3. m_current_pc should have the current pc value for this frame 7805ffd83dbSDimitry Andric // 4. m_current_offset_backed_up_one should have the current byte offset into 7815ffd83dbSDimitry Andric // the function, maybe backed up by 1, -1 if unknown 7825ffd83dbSDimitry Andric 7835ffd83dbSDimitry Andric UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() { 7845ffd83dbSDimitry Andric UnwindPlanSP unwind_plan_sp; 7855ffd83dbSDimitry Andric UnwindPlanSP arch_default_unwind_plan_sp; 7865ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 7875ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 7885ffd83dbSDimitry Andric ABI *abi = process ? process->GetABI().get() : nullptr; 7895ffd83dbSDimitry Andric if (abi) { 7905ffd83dbSDimitry Andric arch_default_unwind_plan_sp = 7915ffd83dbSDimitry Andric std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 7925ffd83dbSDimitry Andric abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp); 7935ffd83dbSDimitry Andric } else { 7945ffd83dbSDimitry Andric UnwindLogMsg( 7955ffd83dbSDimitry Andric "unable to get architectural default UnwindPlan from ABI plugin"); 7965ffd83dbSDimitry Andric } 7975ffd83dbSDimitry Andric 7985ffd83dbSDimitry Andric if (IsFrameZero() || GetNextFrame()->m_frame_type == eTrapHandlerFrame || 7995ffd83dbSDimitry Andric GetNextFrame()->m_frame_type == eDebuggerFrame) { 800fe6060f1SDimitry Andric m_behaves_like_zeroth_frame = true; 8015ffd83dbSDimitry Andric // If this frame behaves like a 0th frame (currently executing or 8025ffd83dbSDimitry Andric // interrupted asynchronously), all registers can be retrieved. 8035ffd83dbSDimitry Andric m_all_registers_available = true; 8045ffd83dbSDimitry Andric } 8055ffd83dbSDimitry Andric 8065ffd83dbSDimitry Andric // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer) 8075ffd83dbSDimitry Andric // so the pc is 0x0 in the zeroth frame, we need to use the "unwind at first 8085ffd83dbSDimitry Andric // instruction" arch default UnwindPlan Also, if this Process can report on 8095ffd83dbSDimitry Andric // memory region attributes, any non-executable region means we jumped 8105ffd83dbSDimitry Andric // through a bad function pointer - handle the same way as 0x0. Note, if we 8115ffd83dbSDimitry Andric // have a symbol context & a symbol, we don't want to follow this code path. 8125ffd83dbSDimitry Andric // This is for jumping to memory regions without any information available. 8135ffd83dbSDimitry Andric 8145ffd83dbSDimitry Andric if ((!m_sym_ctx_valid || 8155ffd83dbSDimitry Andric (m_sym_ctx.function == nullptr && m_sym_ctx.symbol == nullptr)) && 816fe6060f1SDimitry Andric m_behaves_like_zeroth_frame && m_current_pc.IsValid()) { 8175ffd83dbSDimitry Andric uint32_t permissions; 8185ffd83dbSDimitry Andric addr_t current_pc_addr = 8195ffd83dbSDimitry Andric m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()); 8205ffd83dbSDimitry Andric if (current_pc_addr == 0 || 8215ffd83dbSDimitry Andric (process && 8225ffd83dbSDimitry Andric process->GetLoadAddressPermissions(current_pc_addr, permissions) && 8235ffd83dbSDimitry Andric (permissions & ePermissionsExecutable) == 0)) { 8245ffd83dbSDimitry Andric if (abi) { 8255ffd83dbSDimitry Andric unwind_plan_sp = 8265ffd83dbSDimitry Andric std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 8275ffd83dbSDimitry Andric abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp); 8285ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 8295ffd83dbSDimitry Andric return unwind_plan_sp; 8305ffd83dbSDimitry Andric } 8315ffd83dbSDimitry Andric } 8325ffd83dbSDimitry Andric } 8335ffd83dbSDimitry Andric 8345ffd83dbSDimitry Andric // No Module for the current pc, try using the architecture default unwind. 8355ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 8365ffd83dbSDimitry Andric if (!m_current_pc.IsValid() || !pc_module_sp || 8375ffd83dbSDimitry Andric pc_module_sp->GetObjectFile() == nullptr) { 8385ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 8395ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 8405ffd83dbSDimitry Andric } 8415ffd83dbSDimitry Andric 8425ffd83dbSDimitry Andric FuncUnwindersSP func_unwinders_sp; 8435ffd83dbSDimitry Andric if (m_sym_ctx_valid) { 8445ffd83dbSDimitry Andric func_unwinders_sp = 8455ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress( 8465ffd83dbSDimitry Andric m_current_pc, m_sym_ctx); 8475ffd83dbSDimitry Andric } 8485ffd83dbSDimitry Andric 8495ffd83dbSDimitry Andric // No FuncUnwinders available for this pc (stripped function symbols, lldb 8505ffd83dbSDimitry Andric // could not augment its function table with another source, like 8515ffd83dbSDimitry Andric // LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). See if eh_frame or the 8525ffd83dbSDimitry Andric // .ARM.exidx tables have unwind information for this address, else fall back 8535ffd83dbSDimitry Andric // to the architectural default unwind. 8545ffd83dbSDimitry Andric if (!func_unwinders_sp) { 8555ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 8565ffd83dbSDimitry Andric 8575ffd83dbSDimitry Andric if (!pc_module_sp || !pc_module_sp->GetObjectFile() || 8585ffd83dbSDimitry Andric !m_current_pc.IsValid()) 8595ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 8605ffd83dbSDimitry Andric 8615ffd83dbSDimitry Andric // Even with -fomit-frame-pointer, we can try eh_frame to get back on 8625ffd83dbSDimitry Andric // track. 8635ffd83dbSDimitry Andric DWARFCallFrameInfo *eh_frame = 8645ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetEHFrameInfo(); 8655ffd83dbSDimitry Andric if (eh_frame) { 8665ffd83dbSDimitry Andric unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 8675ffd83dbSDimitry Andric if (eh_frame->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) 8685ffd83dbSDimitry Andric return unwind_plan_sp; 8695ffd83dbSDimitry Andric else 8705ffd83dbSDimitry Andric unwind_plan_sp.reset(); 8715ffd83dbSDimitry Andric } 8725ffd83dbSDimitry Andric 8735ffd83dbSDimitry Andric ArmUnwindInfo *arm_exidx = 8745ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetArmUnwindInfo(); 8755ffd83dbSDimitry Andric if (arm_exidx) { 8765ffd83dbSDimitry Andric unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 8775ffd83dbSDimitry Andric if (arm_exidx->GetUnwindPlan(exe_ctx.GetTargetRef(), m_current_pc, 8785ffd83dbSDimitry Andric *unwind_plan_sp)) 8795ffd83dbSDimitry Andric return unwind_plan_sp; 8805ffd83dbSDimitry Andric else 8815ffd83dbSDimitry Andric unwind_plan_sp.reset(); 8825ffd83dbSDimitry Andric } 8835ffd83dbSDimitry Andric 8845ffd83dbSDimitry Andric CallFrameInfo *object_file_unwind = 8855ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo(); 8865ffd83dbSDimitry Andric if (object_file_unwind) { 8875ffd83dbSDimitry Andric unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 8885ffd83dbSDimitry Andric if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) 8895ffd83dbSDimitry Andric return unwind_plan_sp; 8905ffd83dbSDimitry Andric else 8915ffd83dbSDimitry Andric unwind_plan_sp.reset(); 8925ffd83dbSDimitry Andric } 8935ffd83dbSDimitry Andric 8945ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 8955ffd83dbSDimitry Andric } 8965ffd83dbSDimitry Andric 8975ffd83dbSDimitry Andric if (m_frame_type == eTrapHandlerFrame && process) { 8985ffd83dbSDimitry Andric m_fast_unwind_plan_sp.reset(); 899349cc55cSDimitry Andric 900349cc55cSDimitry Andric // On some platforms the unwind information for signal handlers is not 901349cc55cSDimitry Andric // present or correct. Give the platform plugins a chance to provide 902349cc55cSDimitry Andric // substitute plan. Otherwise, use eh_frame. 903349cc55cSDimitry Andric if (m_sym_ctx_valid) { 904349cc55cSDimitry Andric lldb::PlatformSP platform = process->GetTarget().GetPlatform(); 905349cc55cSDimitry Andric unwind_plan_sp = platform->GetTrapHandlerUnwindPlan( 906349cc55cSDimitry Andric process->GetTarget().GetArchitecture().GetTriple(), 907349cc55cSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx)); 908349cc55cSDimitry Andric 909349cc55cSDimitry Andric if (unwind_plan_sp) 910349cc55cSDimitry Andric return unwind_plan_sp; 911349cc55cSDimitry Andric } 912349cc55cSDimitry Andric 9135ffd83dbSDimitry Andric unwind_plan_sp = 9145ffd83dbSDimitry Andric func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); 9155ffd83dbSDimitry Andric if (!unwind_plan_sp) 9165ffd83dbSDimitry Andric unwind_plan_sp = 9175ffd83dbSDimitry Andric func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); 9185ffd83dbSDimitry Andric if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) && 9195ffd83dbSDimitry Andric unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { 9205ffd83dbSDimitry Andric return unwind_plan_sp; 9215ffd83dbSDimitry Andric } 9225ffd83dbSDimitry Andric } 9235ffd83dbSDimitry Andric 9245ffd83dbSDimitry Andric // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame 9255ffd83dbSDimitry Andric // even when it's frame zero This comes up if we have hand-written functions 9265ffd83dbSDimitry Andric // in a Module and hand-written eh_frame. The assembly instruction 9275ffd83dbSDimitry Andric // inspection may fail and the eh_frame CFI were probably written with some 9285ffd83dbSDimitry Andric // care to do the right thing. It'd be nice if there was a way to ask the 9295ffd83dbSDimitry Andric // eh_frame directly if it is asynchronous (can be trusted at every 9305ffd83dbSDimitry Andric // instruction point) or synchronous (the normal case - only at call sites). 9315ffd83dbSDimitry Andric // But there is not. 9325ffd83dbSDimitry Andric if (process && process->GetDynamicLoader() && 9335ffd83dbSDimitry Andric process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) { 9345ffd83dbSDimitry Andric // We must specifically call the GetEHFrameUnwindPlan() method here -- 9355ffd83dbSDimitry Andric // normally we would call GetUnwindPlanAtCallSite() -- because CallSite may 9365ffd83dbSDimitry Andric // return an unwind plan sourced from either eh_frame (that's what we 9375ffd83dbSDimitry Andric // intend) or compact unwind (this won't work) 9385ffd83dbSDimitry Andric unwind_plan_sp = 9395ffd83dbSDimitry Andric func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); 9405ffd83dbSDimitry Andric if (!unwind_plan_sp) 9415ffd83dbSDimitry Andric unwind_plan_sp = 9425ffd83dbSDimitry Andric func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); 9435ffd83dbSDimitry Andric if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 9445ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the " 9455ffd83dbSDimitry Andric "DynamicLoader suggested we prefer it", 9465ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 9475ffd83dbSDimitry Andric return unwind_plan_sp; 9485ffd83dbSDimitry Andric } 9495ffd83dbSDimitry Andric } 9505ffd83dbSDimitry Andric 9515ffd83dbSDimitry Andric // Typically the NonCallSite UnwindPlan is the unwind created by inspecting 9525ffd83dbSDimitry Andric // the assembly language instructions 953fe6060f1SDimitry Andric if (m_behaves_like_zeroth_frame && process) { 9545ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite( 9555ffd83dbSDimitry Andric process->GetTarget(), m_thread); 9565ffd83dbSDimitry Andric if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 9575ffd83dbSDimitry Andric if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { 9585ffd83dbSDimitry Andric // We probably have an UnwindPlan created by inspecting assembly 9595ffd83dbSDimitry Andric // instructions. The assembly profilers work really well with compiler- 9605ffd83dbSDimitry Andric // generated functions but hand- written assembly can be problematic. 9615ffd83dbSDimitry Andric // We set the eh_frame based unwind plan as our fallback unwind plan if 9625ffd83dbSDimitry Andric // instruction emulation doesn't work out even for non call sites if it 9635ffd83dbSDimitry Andric // is available and use the architecture default unwind plan if it is 9645ffd83dbSDimitry Andric // not available. The eh_frame unwind plan is more reliable even on non 9655ffd83dbSDimitry Andric // call sites then the architecture default plan and for hand written 9665ffd83dbSDimitry Andric // assembly code it is often written in a way that it valid at all 9675ffd83dbSDimitry Andric // location what helps in the most common cases when the instruction 9685ffd83dbSDimitry Andric // emulation fails. 9695ffd83dbSDimitry Andric UnwindPlanSP call_site_unwind_plan = 9705ffd83dbSDimitry Andric func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), 9715ffd83dbSDimitry Andric m_thread); 9725ffd83dbSDimitry Andric if (call_site_unwind_plan && 9735ffd83dbSDimitry Andric call_site_unwind_plan.get() != unwind_plan_sp.get() && 9745ffd83dbSDimitry Andric call_site_unwind_plan->GetSourceName() != 9755ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName()) { 9765ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = call_site_unwind_plan; 9775ffd83dbSDimitry Andric } else { 9785ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; 9795ffd83dbSDimitry Andric } 9805ffd83dbSDimitry Andric } 9815ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this " 9825ffd83dbSDimitry Andric "is the non-call site unwind plan and this is a " 9835ffd83dbSDimitry Andric "zeroth frame", 9845ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 9855ffd83dbSDimitry Andric return unwind_plan_sp; 9865ffd83dbSDimitry Andric } 9875ffd83dbSDimitry Andric 9885ffd83dbSDimitry Andric // If we're on the first instruction of a function, and we have an 9895ffd83dbSDimitry Andric // architectural default UnwindPlan for the initial instruction of a 9905ffd83dbSDimitry Andric // function, use that. 9915ffd83dbSDimitry Andric if (m_current_offset == 0) { 9925ffd83dbSDimitry Andric unwind_plan_sp = 9935ffd83dbSDimitry Andric func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry( 9945ffd83dbSDimitry Andric m_thread); 9955ffd83dbSDimitry Andric if (unwind_plan_sp) { 9965ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we are at " 9975ffd83dbSDimitry Andric "the first instruction of a function", 9985ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 9995ffd83dbSDimitry Andric return unwind_plan_sp; 10005ffd83dbSDimitry Andric } 10015ffd83dbSDimitry Andric } 10025ffd83dbSDimitry Andric } 10035ffd83dbSDimitry Andric 10045ffd83dbSDimitry Andric // Typically this is unwind info from an eh_frame section intended for 10055ffd83dbSDimitry Andric // exception handling; only valid at call sites 10065ffd83dbSDimitry Andric if (process) { 10075ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite( 10085ffd83dbSDimitry Andric process->GetTarget(), m_thread); 10095ffd83dbSDimitry Andric } 101081ad6265SDimitry Andric if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) { 10115ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this " 10125ffd83dbSDimitry Andric "is the call-site unwind plan", 10135ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 10145ffd83dbSDimitry Andric return unwind_plan_sp; 10155ffd83dbSDimitry Andric } 10165ffd83dbSDimitry Andric 10175ffd83dbSDimitry Andric // We'd prefer to use an UnwindPlan intended for call sites when we're at a 10185ffd83dbSDimitry Andric // call site but if we've struck out on that, fall back to using the non- 10195ffd83dbSDimitry Andric // call-site assembly inspection UnwindPlan if possible. 10205ffd83dbSDimitry Andric if (process) { 10215ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite( 10225ffd83dbSDimitry Andric process->GetTarget(), m_thread); 10235ffd83dbSDimitry Andric } 10245ffd83dbSDimitry Andric if (unwind_plan_sp && 10255ffd83dbSDimitry Andric unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { 10265ffd83dbSDimitry Andric // We probably have an UnwindPlan created by inspecting assembly 10275ffd83dbSDimitry Andric // instructions. The assembly profilers work really well with compiler- 10285ffd83dbSDimitry Andric // generated functions but hand- written assembly can be problematic. We 10295ffd83dbSDimitry Andric // set the eh_frame based unwind plan as our fallback unwind plan if 10305ffd83dbSDimitry Andric // instruction emulation doesn't work out even for non call sites if it is 10315ffd83dbSDimitry Andric // available and use the architecture default unwind plan if it is not 10325ffd83dbSDimitry Andric // available. The eh_frame unwind plan is more reliable even on non call 10335ffd83dbSDimitry Andric // sites then the architecture default plan and for hand written assembly 10345ffd83dbSDimitry Andric // code it is often written in a way that it valid at all location what 10355ffd83dbSDimitry Andric // helps in the most common cases when the instruction emulation fails. 10365ffd83dbSDimitry Andric UnwindPlanSP call_site_unwind_plan = 10375ffd83dbSDimitry Andric func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), 10385ffd83dbSDimitry Andric m_thread); 10395ffd83dbSDimitry Andric if (call_site_unwind_plan && 10405ffd83dbSDimitry Andric call_site_unwind_plan.get() != unwind_plan_sp.get() && 10415ffd83dbSDimitry Andric call_site_unwind_plan->GetSourceName() != 10425ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName()) { 10435ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = call_site_unwind_plan; 10445ffd83dbSDimitry Andric } else { 10455ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; 10465ffd83dbSDimitry Andric } 10475ffd83dbSDimitry Andric } 10485ffd83dbSDimitry Andric 104981ad6265SDimitry Andric if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) { 10505ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we " 10515ffd83dbSDimitry Andric "failed to find a call-site unwind plan that would work", 10525ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 10535ffd83dbSDimitry Andric return unwind_plan_sp; 10545ffd83dbSDimitry Andric } 10555ffd83dbSDimitry Andric 10565ffd83dbSDimitry Andric // If nothing else, use the architectural default UnwindPlan and hope that 10575ffd83dbSDimitry Andric // does the job. 10585ffd83dbSDimitry Andric if (arch_default_unwind_plan_sp) 10595ffd83dbSDimitry Andric UnwindLogMsgVerbose( 10605ffd83dbSDimitry Andric "frame uses %s for full UnwindPlan because we are falling back " 10615ffd83dbSDimitry Andric "to the arch default plan", 10625ffd83dbSDimitry Andric arch_default_unwind_plan_sp->GetSourceName().GetCString()); 10635ffd83dbSDimitry Andric else 10645ffd83dbSDimitry Andric UnwindLogMsg( 10655ffd83dbSDimitry Andric "Unable to find any UnwindPlan for full unwind of this frame."); 10665ffd83dbSDimitry Andric 10675ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 10685ffd83dbSDimitry Andric } 10695ffd83dbSDimitry Andric 10705ffd83dbSDimitry Andric void RegisterContextUnwind::InvalidateAllRegisters() { 10715ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 10725ffd83dbSDimitry Andric } 10735ffd83dbSDimitry Andric 10745ffd83dbSDimitry Andric size_t RegisterContextUnwind::GetRegisterCount() { 10755ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterCount(); 10765ffd83dbSDimitry Andric } 10775ffd83dbSDimitry Andric 10785ffd83dbSDimitry Andric const RegisterInfo *RegisterContextUnwind::GetRegisterInfoAtIndex(size_t reg) { 10795ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); 10805ffd83dbSDimitry Andric } 10815ffd83dbSDimitry Andric 10825ffd83dbSDimitry Andric size_t RegisterContextUnwind::GetRegisterSetCount() { 10835ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterSetCount(); 10845ffd83dbSDimitry Andric } 10855ffd83dbSDimitry Andric 10865ffd83dbSDimitry Andric const RegisterSet *RegisterContextUnwind::GetRegisterSet(size_t reg_set) { 10875ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterSet(reg_set); 10885ffd83dbSDimitry Andric } 10895ffd83dbSDimitry Andric 10905ffd83dbSDimitry Andric uint32_t RegisterContextUnwind::ConvertRegisterKindToRegisterNumber( 10915ffd83dbSDimitry Andric lldb::RegisterKind kind, uint32_t num) { 10925ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 10935ffd83dbSDimitry Andric kind, num); 10945ffd83dbSDimitry Andric } 10955ffd83dbSDimitry Andric 10965ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadRegisterValueFromRegisterLocation( 10975ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc, 10985ffd83dbSDimitry Andric const RegisterInfo *reg_info, RegisterValue &value) { 10995ffd83dbSDimitry Andric if (!IsValid()) 11005ffd83dbSDimitry Andric return false; 11015ffd83dbSDimitry Andric bool success = false; 11025ffd83dbSDimitry Andric 11035ffd83dbSDimitry Andric switch (regloc.type) { 11045ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: { 11055ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 11065ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 11075ffd83dbSDimitry Andric 11085ffd83dbSDimitry Andric if (!other_reg_info) 11095ffd83dbSDimitry Andric return false; 11105ffd83dbSDimitry Andric 11115ffd83dbSDimitry Andric success = 11125ffd83dbSDimitry Andric m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value); 11135ffd83dbSDimitry Andric } break; 11145ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInRegister: { 11155ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 11165ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 11175ffd83dbSDimitry Andric 11185ffd83dbSDimitry Andric if (!other_reg_info) 11195ffd83dbSDimitry Andric return false; 11205ffd83dbSDimitry Andric 11215ffd83dbSDimitry Andric if (IsFrameZero()) { 11225ffd83dbSDimitry Andric success = 11235ffd83dbSDimitry Andric m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value); 11245ffd83dbSDimitry Andric } else { 11255ffd83dbSDimitry Andric success = GetNextFrame()->ReadRegister(other_reg_info, value); 11265ffd83dbSDimitry Andric } 11275ffd83dbSDimitry Andric } break; 11285ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterValueInferred: 11295ffd83dbSDimitry Andric success = 11305ffd83dbSDimitry Andric value.SetUInt(regloc.location.inferred_value, reg_info->byte_size); 11315ffd83dbSDimitry Andric break; 11325ffd83dbSDimitry Andric 11335ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterNotSaved: 11345ffd83dbSDimitry Andric break; 11355ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: 11365ffd83dbSDimitry Andric llvm_unreachable("FIXME debugger inferior function call unwind"); 11375ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { 11385ffd83dbSDimitry Andric Status error(ReadRegisterValueFromMemory( 11395ffd83dbSDimitry Andric reg_info, regloc.location.target_memory_location, reg_info->byte_size, 11405ffd83dbSDimitry Andric value)); 11415ffd83dbSDimitry Andric success = error.Success(); 11425ffd83dbSDimitry Andric } break; 11435ffd83dbSDimitry Andric default: 11445ffd83dbSDimitry Andric llvm_unreachable("Unknown RegisterLocation type."); 11455ffd83dbSDimitry Andric } 11465ffd83dbSDimitry Andric return success; 11475ffd83dbSDimitry Andric } 11485ffd83dbSDimitry Andric 11495ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteRegisterValueToRegisterLocation( 11505ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc, 11515ffd83dbSDimitry Andric const RegisterInfo *reg_info, const RegisterValue &value) { 11525ffd83dbSDimitry Andric if (!IsValid()) 11535ffd83dbSDimitry Andric return false; 11545ffd83dbSDimitry Andric 11555ffd83dbSDimitry Andric bool success = false; 11565ffd83dbSDimitry Andric 11575ffd83dbSDimitry Andric switch (regloc.type) { 11585ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: { 11595ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 11605ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 11615ffd83dbSDimitry Andric success = 11625ffd83dbSDimitry Andric m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value); 11635ffd83dbSDimitry Andric } break; 11645ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInRegister: { 11655ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 11665ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 11675ffd83dbSDimitry Andric if (IsFrameZero()) { 11685ffd83dbSDimitry Andric success = 11695ffd83dbSDimitry Andric m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value); 11705ffd83dbSDimitry Andric } else { 11715ffd83dbSDimitry Andric success = GetNextFrame()->WriteRegister(other_reg_info, value); 11725ffd83dbSDimitry Andric } 11735ffd83dbSDimitry Andric } break; 11745ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterValueInferred: 11755ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterNotSaved: 11765ffd83dbSDimitry Andric break; 11775ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: 11785ffd83dbSDimitry Andric llvm_unreachable("FIXME debugger inferior function call unwind"); 11795ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { 11805ffd83dbSDimitry Andric Status error(WriteRegisterValueToMemory( 11815ffd83dbSDimitry Andric reg_info, regloc.location.target_memory_location, reg_info->byte_size, 11825ffd83dbSDimitry Andric value)); 11835ffd83dbSDimitry Andric success = error.Success(); 11845ffd83dbSDimitry Andric } break; 11855ffd83dbSDimitry Andric default: 11865ffd83dbSDimitry Andric llvm_unreachable("Unknown RegisterLocation type."); 11875ffd83dbSDimitry Andric } 11885ffd83dbSDimitry Andric return success; 11895ffd83dbSDimitry Andric } 11905ffd83dbSDimitry Andric 11915ffd83dbSDimitry Andric bool RegisterContextUnwind::IsValid() const { 11925ffd83dbSDimitry Andric return m_frame_type != eNotAValidFrame; 11935ffd83dbSDimitry Andric } 11945ffd83dbSDimitry Andric 11955ffd83dbSDimitry Andric // After the final stack frame in a stack walk we'll get one invalid 11965ffd83dbSDimitry Andric // (eNotAValidFrame) stack frame -- one past the end of the stack walk. But 11975ffd83dbSDimitry Andric // higher-level code will need to tell the difference between "the unwind plan 11985ffd83dbSDimitry Andric // below this frame failed" versus "we successfully completed the stack walk" 11995ffd83dbSDimitry Andric // so this method helps to disambiguate that. 12005ffd83dbSDimitry Andric 12015ffd83dbSDimitry Andric bool RegisterContextUnwind::IsTrapHandlerFrame() const { 12025ffd83dbSDimitry Andric return m_frame_type == eTrapHandlerFrame; 12035ffd83dbSDimitry Andric } 12045ffd83dbSDimitry Andric 12055ffd83dbSDimitry Andric // A skip frame is a bogus frame on the stack -- but one where we're likely to 12065ffd83dbSDimitry Andric // find a real frame farther 12075ffd83dbSDimitry Andric // up the stack if we keep looking. It's always the second frame in an unwind 12085ffd83dbSDimitry Andric // (i.e. the first frame after frame zero) where unwinding can be the 12095ffd83dbSDimitry Andric // trickiest. Ideally we'll mark up this frame in some way so the user knows 12105ffd83dbSDimitry Andric // we're displaying bad data and we may have skipped one frame of their real 12115ffd83dbSDimitry Andric // program in the process of getting back on track. 12125ffd83dbSDimitry Andric 12135ffd83dbSDimitry Andric bool RegisterContextUnwind::IsSkipFrame() const { 12145ffd83dbSDimitry Andric return m_frame_type == eSkipFrame; 12155ffd83dbSDimitry Andric } 12165ffd83dbSDimitry Andric 12175ffd83dbSDimitry Andric bool RegisterContextUnwind::IsTrapHandlerSymbol( 12185ffd83dbSDimitry Andric lldb_private::Process *process, 12195ffd83dbSDimitry Andric const lldb_private::SymbolContext &m_sym_ctx) const { 12205ffd83dbSDimitry Andric PlatformSP platform_sp(process->GetTarget().GetPlatform()); 12215ffd83dbSDimitry Andric if (platform_sp) { 12225ffd83dbSDimitry Andric const std::vector<ConstString> trap_handler_names( 12235ffd83dbSDimitry Andric platform_sp->GetTrapHandlerSymbolNames()); 12245ffd83dbSDimitry Andric for (ConstString name : trap_handler_names) { 12255ffd83dbSDimitry Andric if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || 12265ffd83dbSDimitry Andric (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) { 12275ffd83dbSDimitry Andric return true; 12285ffd83dbSDimitry Andric } 12295ffd83dbSDimitry Andric } 12305ffd83dbSDimitry Andric } 12315ffd83dbSDimitry Andric const std::vector<ConstString> user_specified_trap_handler_names( 12325ffd83dbSDimitry Andric m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames()); 12335ffd83dbSDimitry Andric for (ConstString name : user_specified_trap_handler_names) { 12345ffd83dbSDimitry Andric if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || 12355ffd83dbSDimitry Andric (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) { 12365ffd83dbSDimitry Andric return true; 12375ffd83dbSDimitry Andric } 12385ffd83dbSDimitry Andric } 12395ffd83dbSDimitry Andric 12405ffd83dbSDimitry Andric return false; 12415ffd83dbSDimitry Andric } 12425ffd83dbSDimitry Andric 12435ffd83dbSDimitry Andric // Answer the question: Where did THIS frame save the CALLER frame ("previous" 12445ffd83dbSDimitry Andric // frame)'s register value? 12455ffd83dbSDimitry Andric 12465ffd83dbSDimitry Andric enum UnwindLLDB::RegisterSearchResult 12475ffd83dbSDimitry Andric RegisterContextUnwind::SavedLocationForRegister( 12485ffd83dbSDimitry Andric uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { 12495ffd83dbSDimitry Andric RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum); 125081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 12515ffd83dbSDimitry Andric 12525ffd83dbSDimitry Andric // Have we already found this register location? 12535ffd83dbSDimitry Andric if (!m_registers.empty()) { 12545ffd83dbSDimitry Andric std::map<uint32_t, 12555ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation>::const_iterator 12565ffd83dbSDimitry Andric iterator; 12575ffd83dbSDimitry Andric iterator = m_registers.find(regnum.GetAsKind(eRegisterKindLLDB)); 12585ffd83dbSDimitry Andric if (iterator != m_registers.end()) { 12595ffd83dbSDimitry Andric regloc = iterator->second; 12605ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's saved %s (%d)'s location, cached", 12615ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 12625ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 12635ffd83dbSDimitry Andric } 12645ffd83dbSDimitry Andric } 12655ffd83dbSDimitry Andric 12665ffd83dbSDimitry Andric // Look through the available UnwindPlans for the register location. 12675ffd83dbSDimitry Andric 12685ffd83dbSDimitry Andric UnwindPlan::Row::RegisterLocation unwindplan_regloc; 12695ffd83dbSDimitry Andric bool have_unwindplan_regloc = false; 12705ffd83dbSDimitry Andric RegisterKind unwindplan_registerkind = kNumRegisterKinds; 12715ffd83dbSDimitry Andric 12725ffd83dbSDimitry Andric if (m_fast_unwind_plan_sp) { 12735ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 12745ffd83dbSDimitry Andric m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 12755ffd83dbSDimitry Andric unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind(); 12765ffd83dbSDimitry Andric if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) { 12775ffd83dbSDimitry Andric UnwindLogMsg("could not convert lldb regnum %s (%d) into %d RegisterKind " 12785ffd83dbSDimitry Andric "reg numbering scheme", 12795ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 12805ffd83dbSDimitry Andric (int)unwindplan_registerkind); 12815ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 12825ffd83dbSDimitry Andric } 1283fe6060f1SDimitry Andric // The architecture default unwind plan marks unknown registers as 1284fe6060f1SDimitry Andric // Undefined so that we don't forward them up the stack when a 1285fe6060f1SDimitry Andric // jitted stack frame may have overwritten them. But when the 1286fe6060f1SDimitry Andric // arch default unwind plan is used as the Fast Unwind Plan, we 1287fe6060f1SDimitry Andric // need to recognize this & switch over to the Full Unwind Plan 1288fe6060f1SDimitry Andric // to see what unwind rule that (more knoweldgeable, probably) 1289fe6060f1SDimitry Andric // UnwindPlan has. If the full UnwindPlan says the register 1290fe6060f1SDimitry Andric // location is Undefined, then it really is. 12915ffd83dbSDimitry Andric if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), 1292fe6060f1SDimitry Andric unwindplan_regloc) && 1293fe6060f1SDimitry Andric !unwindplan_regloc.IsUndefined()) { 12945ffd83dbSDimitry Andric UnwindLogMsg( 12955ffd83dbSDimitry Andric "supplying caller's saved %s (%d)'s location using FastUnwindPlan", 12965ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 12975ffd83dbSDimitry Andric have_unwindplan_regloc = true; 12985ffd83dbSDimitry Andric } 12995ffd83dbSDimitry Andric } 13005ffd83dbSDimitry Andric 13015ffd83dbSDimitry Andric if (!have_unwindplan_regloc) { 13025ffd83dbSDimitry Andric // m_full_unwind_plan_sp being NULL means that we haven't tried to find a 13035ffd83dbSDimitry Andric // full UnwindPlan yet 1304fe6060f1SDimitry Andric bool got_new_full_unwindplan = false; 1305fe6060f1SDimitry Andric if (!m_full_unwind_plan_sp) { 13065ffd83dbSDimitry Andric m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); 1307fe6060f1SDimitry Andric got_new_full_unwindplan = true; 1308fe6060f1SDimitry Andric } 13095ffd83dbSDimitry Andric 13105ffd83dbSDimitry Andric if (m_full_unwind_plan_sp) { 13115ffd83dbSDimitry Andric RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, 13125ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_PC); 13135ffd83dbSDimitry Andric 13145ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 131581ad6265SDimitry Andric m_full_unwind_plan_sp->GetRowForFunctionOffset( 131681ad6265SDimitry Andric m_current_offset_backed_up_one); 13175ffd83dbSDimitry Andric unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); 13185ffd83dbSDimitry Andric 1319fe6060f1SDimitry Andric if (got_new_full_unwindplan && active_row.get() && log) { 1320fe6060f1SDimitry Andric StreamString active_row_strm; 1321fe6060f1SDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 1322fe6060f1SDimitry Andric active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), 1323fe6060f1SDimitry Andric &m_thread, 1324fe6060f1SDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 1325fe6060f1SDimitry Andric UnwindLogMsg("Using full unwind plan '%s'", 1326fe6060f1SDimitry Andric m_full_unwind_plan_sp->GetSourceName().AsCString()); 1327fe6060f1SDimitry Andric UnwindLogMsg("active row: %s", active_row_strm.GetData()); 1328fe6060f1SDimitry Andric } 13295ffd83dbSDimitry Andric RegisterNumber return_address_reg; 13305ffd83dbSDimitry Andric 13315ffd83dbSDimitry Andric // If we're fetching the saved pc and this UnwindPlan defines a 13325ffd83dbSDimitry Andric // ReturnAddress register (e.g. lr on arm), look for the return address 13335ffd83dbSDimitry Andric // register number in the UnwindPlan's row. 13345ffd83dbSDimitry Andric if (pc_regnum.IsValid() && pc_regnum == regnum && 13355ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetReturnAddressRegister() != 13365ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) { 13375ffd83dbSDimitry Andric // If this is a trap handler frame, we should have access to 13385ffd83dbSDimitry Andric // the complete register context when the interrupt/async 13395ffd83dbSDimitry Andric // signal was received, we should fetch the actual saved $pc 13405ffd83dbSDimitry Andric // value instead of the Return Address register. 13415ffd83dbSDimitry Andric // If $pc is not available, fall back to the RA reg. 13425ffd83dbSDimitry Andric UnwindPlan::Row::RegisterLocation scratch; 13435ffd83dbSDimitry Andric if (m_frame_type == eTrapHandlerFrame && 13445ffd83dbSDimitry Andric active_row->GetRegisterInfo 13455ffd83dbSDimitry Andric (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) { 13465ffd83dbSDimitry Andric UnwindLogMsg("Providing pc register instead of rewriting to " 13475ffd83dbSDimitry Andric "RA reg because this is a trap handler and there is " 13485ffd83dbSDimitry Andric "a location for the saved pc register value."); 13495ffd83dbSDimitry Andric } else { 13505ffd83dbSDimitry Andric return_address_reg.init( 13515ffd83dbSDimitry Andric m_thread, m_full_unwind_plan_sp->GetRegisterKind(), 13525ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetReturnAddressRegister()); 13535ffd83dbSDimitry Andric regnum = return_address_reg; 13545ffd83dbSDimitry Andric UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a " 13555ffd83dbSDimitry Andric "RA reg; getting %s (%d) instead", 13565ffd83dbSDimitry Andric return_address_reg.GetName(), 13575ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB)); 13585ffd83dbSDimitry Andric } 13595ffd83dbSDimitry Andric } else { 13605ffd83dbSDimitry Andric if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) { 13615ffd83dbSDimitry Andric if (unwindplan_registerkind == eRegisterKindGeneric) { 13625ffd83dbSDimitry Andric UnwindLogMsg("could not convert lldb regnum %s (%d) into " 13635ffd83dbSDimitry Andric "eRegisterKindGeneric reg numbering scheme", 13645ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 13655ffd83dbSDimitry Andric } else { 13665ffd83dbSDimitry Andric UnwindLogMsg("could not convert lldb regnum %s (%d) into %d " 13675ffd83dbSDimitry Andric "RegisterKind reg numbering scheme", 13685ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 13695ffd83dbSDimitry Andric (int)unwindplan_registerkind); 13705ffd83dbSDimitry Andric } 13715ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 13725ffd83dbSDimitry Andric } 13735ffd83dbSDimitry Andric } 13745ffd83dbSDimitry Andric 13755ffd83dbSDimitry Andric if (regnum.IsValid() && 13765ffd83dbSDimitry Andric active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), 13775ffd83dbSDimitry Andric unwindplan_regloc)) { 13785ffd83dbSDimitry Andric have_unwindplan_regloc = true; 13795ffd83dbSDimitry Andric UnwindLogMsg( 13805ffd83dbSDimitry Andric "supplying caller's saved %s (%d)'s location using %s UnwindPlan", 13815ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 13825ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 13835ffd83dbSDimitry Andric } 13845ffd83dbSDimitry Andric 13855ffd83dbSDimitry Andric // This is frame 0 and we're retrieving the PC and it's saved in a Return 13865ffd83dbSDimitry Andric // Address register and it hasn't been saved anywhere yet -- that is, 13875ffd83dbSDimitry Andric // it's still live in the actual register. Handle this specially. 13885ffd83dbSDimitry Andric 13895ffd83dbSDimitry Andric if (!have_unwindplan_regloc && return_address_reg.IsValid() && 13905ffd83dbSDimitry Andric IsFrameZero()) { 13915ffd83dbSDimitry Andric if (return_address_reg.GetAsKind(eRegisterKindLLDB) != 13925ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) { 13935ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation new_regloc; 13945ffd83dbSDimitry Andric new_regloc.type = 13955ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; 13965ffd83dbSDimitry Andric new_regloc.location.register_number = 13975ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB); 13985ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; 13995ffd83dbSDimitry Andric regloc = new_regloc; 14005ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the live " 14015ffd83dbSDimitry Andric "RegisterContext at frame 0, saved in %d", 14025ffd83dbSDimitry Andric return_address_reg.GetName(), 14035ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB), 14045ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB)); 14055ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 14065ffd83dbSDimitry Andric } 14075ffd83dbSDimitry Andric } 14085ffd83dbSDimitry Andric 14095ffd83dbSDimitry Andric // If this architecture stores the return address in a register (it 14105ffd83dbSDimitry Andric // defines a Return Address register) and we're on a non-zero stack frame 14115ffd83dbSDimitry Andric // and the Full UnwindPlan says that the pc is stored in the 14125ffd83dbSDimitry Andric // RA registers (e.g. lr on arm), then we know that the full unwindplan is 14135ffd83dbSDimitry Andric // not trustworthy -- this 14145ffd83dbSDimitry Andric // is an impossible situation and the instruction emulation code has 14155ffd83dbSDimitry Andric // likely been misled. If this stack frame meets those criteria, we need 14165ffd83dbSDimitry Andric // to throw away the Full UnwindPlan that the instruction emulation came 14175ffd83dbSDimitry Andric // up with and fall back to the architecture's Default UnwindPlan so the 14185ffd83dbSDimitry Andric // stack walk can get past this point. 14195ffd83dbSDimitry Andric 14205ffd83dbSDimitry Andric // Special note: If the Full UnwindPlan was generated from the compiler, 14215ffd83dbSDimitry Andric // don't second-guess it when we're at a call site location. 14225ffd83dbSDimitry Andric 14235ffd83dbSDimitry Andric // arch_default_ra_regnum is the return address register # in the Full 14245ffd83dbSDimitry Andric // UnwindPlan register numbering 14255ffd83dbSDimitry Andric RegisterNumber arch_default_ra_regnum(m_thread, eRegisterKindGeneric, 14265ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_RA); 14275ffd83dbSDimitry Andric 14285ffd83dbSDimitry Andric if (arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) != 14295ffd83dbSDimitry Andric LLDB_INVALID_REGNUM && 14305ffd83dbSDimitry Andric pc_regnum == regnum && unwindplan_regloc.IsInOtherRegister() && 14315ffd83dbSDimitry Andric unwindplan_regloc.GetRegisterNumber() == 14325ffd83dbSDimitry Andric arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) && 14335ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes && 14345ffd83dbSDimitry Andric !m_all_registers_available) { 14355ffd83dbSDimitry Andric UnwindLogMsg("%s UnwindPlan tried to restore the pc from the link " 14365ffd83dbSDimitry Andric "register but this is a non-zero frame", 14375ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 14385ffd83dbSDimitry Andric 14395ffd83dbSDimitry Andric // Throw away the full unwindplan; install the arch default unwindplan 14405ffd83dbSDimitry Andric if (ForceSwitchToFallbackUnwindPlan()) { 14415ffd83dbSDimitry Andric // Update for the possibly new unwind plan 14425ffd83dbSDimitry Andric unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); 14435ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 14445ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 14455ffd83dbSDimitry Andric 14465ffd83dbSDimitry Andric // Sanity check: Verify that we can fetch a pc value and CFA value 14475ffd83dbSDimitry Andric // with this unwind plan 14485ffd83dbSDimitry Andric 14495ffd83dbSDimitry Andric RegisterNumber arch_default_pc_reg(m_thread, eRegisterKindGeneric, 14505ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_PC); 14515ffd83dbSDimitry Andric bool can_fetch_pc_value = false; 14525ffd83dbSDimitry Andric bool can_fetch_cfa = false; 14535ffd83dbSDimitry Andric addr_t cfa_value; 14545ffd83dbSDimitry Andric if (active_row) { 14555ffd83dbSDimitry Andric if (arch_default_pc_reg.GetAsKind(unwindplan_registerkind) != 14565ffd83dbSDimitry Andric LLDB_INVALID_REGNUM && 14575ffd83dbSDimitry Andric active_row->GetRegisterInfo( 14585ffd83dbSDimitry Andric arch_default_pc_reg.GetAsKind(unwindplan_registerkind), 14595ffd83dbSDimitry Andric unwindplan_regloc)) { 14605ffd83dbSDimitry Andric can_fetch_pc_value = true; 14615ffd83dbSDimitry Andric } 14625ffd83dbSDimitry Andric if (ReadFrameAddress(unwindplan_registerkind, 14635ffd83dbSDimitry Andric active_row->GetCFAValue(), cfa_value)) { 14645ffd83dbSDimitry Andric can_fetch_cfa = true; 14655ffd83dbSDimitry Andric } 14665ffd83dbSDimitry Andric } 14675ffd83dbSDimitry Andric 14685ffd83dbSDimitry Andric have_unwindplan_regloc = can_fetch_pc_value && can_fetch_cfa; 14695ffd83dbSDimitry Andric } else { 14705ffd83dbSDimitry Andric // We were unable to fall back to another unwind plan 14715ffd83dbSDimitry Andric have_unwindplan_regloc = false; 14725ffd83dbSDimitry Andric } 14735ffd83dbSDimitry Andric } 14745ffd83dbSDimitry Andric } 14755ffd83dbSDimitry Andric } 14765ffd83dbSDimitry Andric 14775ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 14785ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 14795ffd83dbSDimitry Andric if (!have_unwindplan_regloc) { 14805ffd83dbSDimitry Andric // If the UnwindPlan failed to give us an unwind location for this 14815ffd83dbSDimitry Andric // register, we may be able to fall back to some ABI-defined default. For 14825ffd83dbSDimitry Andric // example, some ABIs allow to determine the caller's SP via the CFA. Also, 14835ffd83dbSDimitry Andric // the ABI may set volatile registers to the undefined state. 14845ffd83dbSDimitry Andric ABI *abi = process ? process->GetABI().get() : nullptr; 14855ffd83dbSDimitry Andric if (abi) { 14865ffd83dbSDimitry Andric const RegisterInfo *reg_info = 14875ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB)); 14885ffd83dbSDimitry Andric if (reg_info && 14895ffd83dbSDimitry Andric abi->GetFallbackRegisterLocation(reg_info, unwindplan_regloc)) { 14905ffd83dbSDimitry Andric UnwindLogMsg( 14915ffd83dbSDimitry Andric "supplying caller's saved %s (%d)'s location using ABI default", 14925ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 14935ffd83dbSDimitry Andric have_unwindplan_regloc = true; 14945ffd83dbSDimitry Andric } 14955ffd83dbSDimitry Andric } 14965ffd83dbSDimitry Andric } 14975ffd83dbSDimitry Andric 14985ffd83dbSDimitry Andric if (!have_unwindplan_regloc) { 14995ffd83dbSDimitry Andric if (IsFrameZero()) { 15005ffd83dbSDimitry Andric // This is frame 0 - we should return the actual live register context 15015ffd83dbSDimitry Andric // value 15025ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation new_regloc; 15035ffd83dbSDimitry Andric new_regloc.type = 15045ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; 15055ffd83dbSDimitry Andric new_regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); 15065ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; 15075ffd83dbSDimitry Andric regloc = new_regloc; 15085ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the live " 15095ffd83dbSDimitry Andric "RegisterContext at frame 0", 15105ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 15115ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 15125ffd83dbSDimitry Andric } else { 151304eeddc0SDimitry Andric std::string unwindplan_name; 15145ffd83dbSDimitry Andric if (m_full_unwind_plan_sp) { 15155ffd83dbSDimitry Andric unwindplan_name += "via '"; 15165ffd83dbSDimitry Andric unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString(); 15175ffd83dbSDimitry Andric unwindplan_name += "'"; 15185ffd83dbSDimitry Andric } 15195ffd83dbSDimitry Andric UnwindLogMsg("no save location for %s (%d) %s", regnum.GetName(), 15205ffd83dbSDimitry Andric regnum.GetAsKind(eRegisterKindLLDB), 15215ffd83dbSDimitry Andric unwindplan_name.c_str()); 15225ffd83dbSDimitry Andric } 15235ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 15245ffd83dbSDimitry Andric } 15255ffd83dbSDimitry Andric 15265ffd83dbSDimitry Andric // unwindplan_regloc has valid contents about where to retrieve the register 15275ffd83dbSDimitry Andric if (unwindplan_regloc.IsUnspecified()) { 1528*972a253aSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation new_regloc = {}; 15295ffd83dbSDimitry Andric new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved; 15305ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; 15315ffd83dbSDimitry Andric UnwindLogMsg("save location for %s (%d) is unspecified, continue searching", 15325ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 15335ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 15345ffd83dbSDimitry Andric } 15355ffd83dbSDimitry Andric 15365ffd83dbSDimitry Andric if (unwindplan_regloc.IsUndefined()) { 15375ffd83dbSDimitry Andric UnwindLogMsg( 15385ffd83dbSDimitry Andric "did not supply reg location for %s (%d) because it is volatile", 15395ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 15405ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; 15415ffd83dbSDimitry Andric } 15425ffd83dbSDimitry Andric 15435ffd83dbSDimitry Andric if (unwindplan_regloc.IsSame()) { 15445ffd83dbSDimitry Andric if (!IsFrameZero() && 15455ffd83dbSDimitry Andric (regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC || 15465ffd83dbSDimitry Andric regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) { 15475ffd83dbSDimitry Andric UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or " 15485ffd83dbSDimitry Andric "return address reg on a non-zero frame -- treat as if we " 15495ffd83dbSDimitry Andric "have no information", 15505ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 15515ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 15525ffd83dbSDimitry Andric } else { 15535ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; 15545ffd83dbSDimitry Andric regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); 15555ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 15565ffd83dbSDimitry Andric UnwindLogMsg( 15575ffd83dbSDimitry Andric "supplying caller's register %s (%d), saved in register %s (%d)", 15585ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 15595ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 15605ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 15615ffd83dbSDimitry Andric } 15625ffd83dbSDimitry Andric } 15635ffd83dbSDimitry Andric 15645ffd83dbSDimitry Andric if (unwindplan_regloc.IsCFAPlusOffset()) { 15655ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 15665ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; 15675ffd83dbSDimitry Andric regloc.location.inferred_value = m_cfa + offset; 15685ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 15695ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d), value is CFA plus " 15705ffd83dbSDimitry Andric "offset %d [value is 0x%" PRIx64 "]", 15715ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 15725ffd83dbSDimitry Andric regloc.location.inferred_value); 15735ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 15745ffd83dbSDimitry Andric } 15755ffd83dbSDimitry Andric 15765ffd83dbSDimitry Andric if (unwindplan_regloc.IsAtCFAPlusOffset()) { 15775ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 15785ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; 15795ffd83dbSDimitry Andric regloc.location.target_memory_location = m_cfa + offset; 15805ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 15815ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at " 15825ffd83dbSDimitry Andric "CFA plus offset %d [saved at 0x%" PRIx64 "]", 15835ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 15845ffd83dbSDimitry Andric regloc.location.target_memory_location); 15855ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 15865ffd83dbSDimitry Andric } 15875ffd83dbSDimitry Andric 15885ffd83dbSDimitry Andric if (unwindplan_regloc.IsAFAPlusOffset()) { 15895ffd83dbSDimitry Andric if (m_afa == LLDB_INVALID_ADDRESS) 15905ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 15915ffd83dbSDimitry Andric 15925ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 15935ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; 15945ffd83dbSDimitry Andric regloc.location.inferred_value = m_afa + offset; 15955ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 15965ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus " 15975ffd83dbSDimitry Andric "offset %d [value is 0x%" PRIx64 "]", 15985ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 15995ffd83dbSDimitry Andric regloc.location.inferred_value); 16005ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 16015ffd83dbSDimitry Andric } 16025ffd83dbSDimitry Andric 16035ffd83dbSDimitry Andric if (unwindplan_regloc.IsAtAFAPlusOffset()) { 16045ffd83dbSDimitry Andric if (m_afa == LLDB_INVALID_ADDRESS) 16055ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 16065ffd83dbSDimitry Andric 16075ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 16085ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; 16095ffd83dbSDimitry Andric regloc.location.target_memory_location = m_afa + offset; 16105ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 16115ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at " 16125ffd83dbSDimitry Andric "AFA plus offset %d [saved at 0x%" PRIx64 "]", 16135ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 16145ffd83dbSDimitry Andric regloc.location.target_memory_location); 16155ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 16165ffd83dbSDimitry Andric } 16175ffd83dbSDimitry Andric 16185ffd83dbSDimitry Andric if (unwindplan_regloc.IsInOtherRegister()) { 16195ffd83dbSDimitry Andric uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber(); 16205ffd83dbSDimitry Andric RegisterNumber row_regnum(m_thread, unwindplan_registerkind, 16215ffd83dbSDimitry Andric unwindplan_regnum); 16225ffd83dbSDimitry Andric if (row_regnum.GetAsKind(eRegisterKindLLDB) == LLDB_INVALID_REGNUM) { 16235ffd83dbSDimitry Andric UnwindLogMsg("could not supply caller's %s (%d) location - was saved in " 16245ffd83dbSDimitry Andric "another reg but couldn't convert that regnum", 16255ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 16265ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 16275ffd83dbSDimitry Andric } 16285ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; 16295ffd83dbSDimitry Andric regloc.location.register_number = row_regnum.GetAsKind(eRegisterKindLLDB); 16305ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 16315ffd83dbSDimitry Andric UnwindLogMsg( 16325ffd83dbSDimitry Andric "supplying caller's register %s (%d), saved in register %s (%d)", 16335ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 16345ffd83dbSDimitry Andric row_regnum.GetName(), row_regnum.GetAsKind(eRegisterKindLLDB)); 16355ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 16365ffd83dbSDimitry Andric } 16375ffd83dbSDimitry Andric 16385ffd83dbSDimitry Andric if (unwindplan_regloc.IsDWARFExpression() || 16395ffd83dbSDimitry Andric unwindplan_regloc.IsAtDWARFExpression()) { 16405ffd83dbSDimitry Andric DataExtractor dwarfdata(unwindplan_regloc.GetDWARFExpressionBytes(), 16415ffd83dbSDimitry Andric unwindplan_regloc.GetDWARFExpressionLength(), 16425ffd83dbSDimitry Andric process->GetByteOrder(), 16435ffd83dbSDimitry Andric process->GetAddressByteSize()); 16445ffd83dbSDimitry Andric ModuleSP opcode_ctx; 1645753f127fSDimitry Andric DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr); 1646753f127fSDimitry Andric dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind( 1647753f127fSDimitry Andric unwindplan_registerkind); 16485ffd83dbSDimitry Andric Value cfa_val = Scalar(m_cfa); 1649fe6060f1SDimitry Andric cfa_val.SetValueType(Value::ValueType::LoadAddress); 16505ffd83dbSDimitry Andric Value result; 16515ffd83dbSDimitry Andric Status error; 16525ffd83dbSDimitry Andric if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result, 16535ffd83dbSDimitry Andric &error)) { 16545ffd83dbSDimitry Andric addr_t val; 16555ffd83dbSDimitry Andric val = result.GetScalar().ULongLong(); 16565ffd83dbSDimitry Andric if (unwindplan_regloc.IsDWARFExpression()) { 16575ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; 16585ffd83dbSDimitry Andric regloc.location.inferred_value = val; 16595ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 16605ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression " 16615ffd83dbSDimitry Andric "(IsDWARFExpression)", 16625ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 16635ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 16645ffd83dbSDimitry Andric } else { 16655ffd83dbSDimitry Andric regloc.type = 16665ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; 16675ffd83dbSDimitry Andric regloc.location.target_memory_location = val; 16685ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 16695ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression " 16705ffd83dbSDimitry Andric "(IsAtDWARFExpression)", 16715ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 16725ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 16735ffd83dbSDimitry Andric } 16745ffd83dbSDimitry Andric } 16755ffd83dbSDimitry Andric UnwindLogMsg("tried to use IsDWARFExpression or IsAtDWARFExpression for %s " 16765ffd83dbSDimitry Andric "(%d) but failed", 16775ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 16785ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 16795ffd83dbSDimitry Andric } 16805ffd83dbSDimitry Andric 16815ffd83dbSDimitry Andric UnwindLogMsg("no save location for %s (%d) in this stack frame", 16825ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 16835ffd83dbSDimitry Andric 16845ffd83dbSDimitry Andric // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are 16855ffd83dbSDimitry Andric // unsupported. 16865ffd83dbSDimitry Andric 16875ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 16885ffd83dbSDimitry Andric } 16895ffd83dbSDimitry Andric 16905ffd83dbSDimitry Andric // TryFallbackUnwindPlan() -- this method is a little tricky. 16915ffd83dbSDimitry Andric // 16925ffd83dbSDimitry Andric // When this is called, the frame above -- the caller frame, the "previous" 16935ffd83dbSDimitry Andric // frame -- is invalid or bad. 16945ffd83dbSDimitry Andric // 16955ffd83dbSDimitry Andric // Instead of stopping the stack walk here, we'll try a different UnwindPlan 16965ffd83dbSDimitry Andric // and see if we can get a valid frame above us. 16975ffd83dbSDimitry Andric // 16985ffd83dbSDimitry Andric // This most often happens when an unwind plan based on assembly instruction 16995ffd83dbSDimitry Andric // inspection is not correct -- mostly with hand-written assembly functions or 17005ffd83dbSDimitry Andric // functions where the stack frame is set up "out of band", e.g. the kernel 17015ffd83dbSDimitry Andric // saved the register context and then called an asynchronous trap handler like 17025ffd83dbSDimitry Andric // _sigtramp. 17035ffd83dbSDimitry Andric // 17045ffd83dbSDimitry Andric // Often in these cases, if we just do a dumb stack walk we'll get past this 17055ffd83dbSDimitry Andric // tricky frame and our usual techniques can continue to be used. 17065ffd83dbSDimitry Andric 17075ffd83dbSDimitry Andric bool RegisterContextUnwind::TryFallbackUnwindPlan() { 17085ffd83dbSDimitry Andric if (m_fallback_unwind_plan_sp.get() == nullptr) 17095ffd83dbSDimitry Andric return false; 17105ffd83dbSDimitry Andric 17115ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == nullptr) 17125ffd83dbSDimitry Andric return false; 17135ffd83dbSDimitry Andric 17145ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || 17155ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName() == 17165ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetSourceName()) { 17175ffd83dbSDimitry Andric return false; 17185ffd83dbSDimitry Andric } 17195ffd83dbSDimitry Andric 17205ffd83dbSDimitry Andric // If a compiler generated unwind plan failed, trying the arch default 17215ffd83dbSDimitry Andric // unwindplan isn't going to do any better. 17225ffd83dbSDimitry Andric if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) 17235ffd83dbSDimitry Andric return false; 17245ffd83dbSDimitry Andric 17255ffd83dbSDimitry Andric // Get the caller's pc value and our own CFA value. Swap in the fallback 17265ffd83dbSDimitry Andric // unwind plan, re-fetch the caller's pc value and CFA value. If they're the 17275ffd83dbSDimitry Andric // same, then the fallback unwind plan provides no benefit. 17285ffd83dbSDimitry Andric 17295ffd83dbSDimitry Andric RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, 17305ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_PC); 17315ffd83dbSDimitry Andric 17325ffd83dbSDimitry Andric addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS; 17335ffd83dbSDimitry Andric addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS; 1734*972a253aSDimitry Andric UnwindLLDB::RegisterLocation regloc = {}; 17355ffd83dbSDimitry Andric if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB), 17365ffd83dbSDimitry Andric regloc) == 17375ffd83dbSDimitry Andric UnwindLLDB::RegisterSearchResult::eRegisterFound) { 17385ffd83dbSDimitry Andric const RegisterInfo *reg_info = 17395ffd83dbSDimitry Andric GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB)); 17405ffd83dbSDimitry Andric if (reg_info) { 17415ffd83dbSDimitry Andric RegisterValue reg_value; 17425ffd83dbSDimitry Andric if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { 17435ffd83dbSDimitry Andric old_caller_pc_value = reg_value.GetAsUInt64(); 1744fe6060f1SDimitry Andric if (ProcessSP process_sp = m_thread.GetProcess()) { 1745fe6060f1SDimitry Andric if (ABISP abi = process_sp->GetABI()) 1746fe6060f1SDimitry Andric old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value); 1747fe6060f1SDimitry Andric } 17485ffd83dbSDimitry Andric } 17495ffd83dbSDimitry Andric } 17505ffd83dbSDimitry Andric } 17515ffd83dbSDimitry Andric 17525ffd83dbSDimitry Andric // This is a tricky wrinkle! If SavedLocationForRegister() detects a really 17535ffd83dbSDimitry Andric // impossible register location for the full unwind plan, it may call 17545ffd83dbSDimitry Andric // ForceSwitchToFallbackUnwindPlan() which in turn replaces the full 17555ffd83dbSDimitry Andric // unwindplan with the fallback... in short, we're done, we're using the 17565ffd83dbSDimitry Andric // fallback UnwindPlan. We checked if m_fallback_unwind_plan_sp was nullptr 17575ffd83dbSDimitry Andric // at the top -- the only way it became nullptr since then is via 17585ffd83dbSDimitry Andric // SavedLocationForRegister(). 17595ffd83dbSDimitry Andric if (m_fallback_unwind_plan_sp.get() == nullptr) 17605ffd83dbSDimitry Andric return true; 17615ffd83dbSDimitry Andric 17625ffd83dbSDimitry Andric // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide 17635ffd83dbSDimitry Andric // this isn't working, we need to restore. We'll also need to save & restore 17645ffd83dbSDimitry Andric // the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'. 17655ffd83dbSDimitry Andric UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; 17665ffd83dbSDimitry Andric addr_t old_cfa = m_cfa; 17675ffd83dbSDimitry Andric addr_t old_afa = m_afa; 17685ffd83dbSDimitry Andric 17695ffd83dbSDimitry Andric m_registers.clear(); 17705ffd83dbSDimitry Andric 17715ffd83dbSDimitry Andric m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; 17725ffd83dbSDimitry Andric 17735ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 177481ad6265SDimitry Andric m_fallback_unwind_plan_sp->GetRowForFunctionOffset( 177581ad6265SDimitry Andric m_current_offset_backed_up_one); 17765ffd83dbSDimitry Andric 17775ffd83dbSDimitry Andric if (active_row && 17785ffd83dbSDimitry Andric active_row->GetCFAValue().GetValueType() != 17795ffd83dbSDimitry Andric UnwindPlan::Row::FAValue::unspecified) { 17805ffd83dbSDimitry Andric addr_t new_cfa; 17815ffd83dbSDimitry Andric if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 17825ffd83dbSDimitry Andric active_row->GetCFAValue(), new_cfa) || 17835ffd83dbSDimitry Andric new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) { 17845ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa with fallback unwindplan"); 17855ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 17865ffd83dbSDimitry Andric m_full_unwind_plan_sp = original_full_unwind_plan_sp; 17875ffd83dbSDimitry Andric return false; 17885ffd83dbSDimitry Andric } 17895ffd83dbSDimitry Andric m_cfa = new_cfa; 17905ffd83dbSDimitry Andric 17915ffd83dbSDimitry Andric ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 17925ffd83dbSDimitry Andric active_row->GetAFAValue(), m_afa); 17935ffd83dbSDimitry Andric 17945ffd83dbSDimitry Andric if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB), 17955ffd83dbSDimitry Andric regloc) == 17965ffd83dbSDimitry Andric UnwindLLDB::RegisterSearchResult::eRegisterFound) { 17975ffd83dbSDimitry Andric const RegisterInfo *reg_info = 17985ffd83dbSDimitry Andric GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB)); 17995ffd83dbSDimitry Andric if (reg_info) { 18005ffd83dbSDimitry Andric RegisterValue reg_value; 18015ffd83dbSDimitry Andric if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, 18025ffd83dbSDimitry Andric reg_value)) { 18035ffd83dbSDimitry Andric new_caller_pc_value = reg_value.GetAsUInt64(); 1804fe6060f1SDimitry Andric if (ProcessSP process_sp = m_thread.GetProcess()) { 1805fe6060f1SDimitry Andric if (ABISP abi = process_sp->GetABI()) 1806fe6060f1SDimitry Andric new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value); 1807fe6060f1SDimitry Andric } 18085ffd83dbSDimitry Andric } 18095ffd83dbSDimitry Andric } 18105ffd83dbSDimitry Andric } 18115ffd83dbSDimitry Andric 18125ffd83dbSDimitry Andric if (new_caller_pc_value == LLDB_INVALID_ADDRESS) { 18135ffd83dbSDimitry Andric UnwindLogMsg("failed to get a pc value for the caller frame with the " 18145ffd83dbSDimitry Andric "fallback unwind plan"); 18155ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 18165ffd83dbSDimitry Andric m_full_unwind_plan_sp = original_full_unwind_plan_sp; 18175ffd83dbSDimitry Andric m_cfa = old_cfa; 18185ffd83dbSDimitry Andric m_afa = old_afa; 18195ffd83dbSDimitry Andric return false; 18205ffd83dbSDimitry Andric } 18215ffd83dbSDimitry Andric 18225ffd83dbSDimitry Andric if (old_caller_pc_value == new_caller_pc_value && 18235ffd83dbSDimitry Andric m_cfa == old_cfa && 18245ffd83dbSDimitry Andric m_afa == old_afa) { 18255ffd83dbSDimitry Andric UnwindLogMsg("fallback unwind plan got the same values for this frame " 18265ffd83dbSDimitry Andric "CFA and caller frame pc, not using"); 18275ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 18285ffd83dbSDimitry Andric m_full_unwind_plan_sp = original_full_unwind_plan_sp; 18295ffd83dbSDimitry Andric return false; 18305ffd83dbSDimitry Andric } 18315ffd83dbSDimitry Andric 18325ffd83dbSDimitry Andric UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' " 18335ffd83dbSDimitry Andric "because UnwindPlan '%s' failed.", 18345ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetSourceName().GetCString(), 18355ffd83dbSDimitry Andric original_full_unwind_plan_sp->GetSourceName().GetCString()); 18365ffd83dbSDimitry Andric 18375ffd83dbSDimitry Andric // We've copied the fallback unwind plan into the full - now clear the 18385ffd83dbSDimitry Andric // fallback. 18395ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 18405ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); 18415ffd83dbSDimitry Andric } 18425ffd83dbSDimitry Andric 18435ffd83dbSDimitry Andric return true; 18445ffd83dbSDimitry Andric } 18455ffd83dbSDimitry Andric 18465ffd83dbSDimitry Andric bool RegisterContextUnwind::ForceSwitchToFallbackUnwindPlan() { 18475ffd83dbSDimitry Andric if (m_fallback_unwind_plan_sp.get() == nullptr) 18485ffd83dbSDimitry Andric return false; 18495ffd83dbSDimitry Andric 18505ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == nullptr) 18515ffd83dbSDimitry Andric return false; 18525ffd83dbSDimitry Andric 18535ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || 18545ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName() == 18555ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetSourceName()) { 18565ffd83dbSDimitry Andric return false; 18575ffd83dbSDimitry Andric } 18585ffd83dbSDimitry Andric 18595ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 18605ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 18615ffd83dbSDimitry Andric 18625ffd83dbSDimitry Andric if (active_row && 18635ffd83dbSDimitry Andric active_row->GetCFAValue().GetValueType() != 18645ffd83dbSDimitry Andric UnwindPlan::Row::FAValue::unspecified) { 18655ffd83dbSDimitry Andric addr_t new_cfa; 18665ffd83dbSDimitry Andric if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 18675ffd83dbSDimitry Andric active_row->GetCFAValue(), new_cfa) || 18685ffd83dbSDimitry Andric new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) { 18695ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa with fallback unwindplan"); 18705ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 18715ffd83dbSDimitry Andric return false; 18725ffd83dbSDimitry Andric } 18735ffd83dbSDimitry Andric 18745ffd83dbSDimitry Andric ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 18755ffd83dbSDimitry Andric active_row->GetAFAValue(), m_afa); 18765ffd83dbSDimitry Andric 18775ffd83dbSDimitry Andric m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; 18785ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 18795ffd83dbSDimitry Andric 18805ffd83dbSDimitry Andric m_registers.clear(); 18815ffd83dbSDimitry Andric 18825ffd83dbSDimitry Andric m_cfa = new_cfa; 18835ffd83dbSDimitry Andric 18845ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); 18855ffd83dbSDimitry Andric 18865ffd83dbSDimitry Andric UnwindLogMsg("switched unconditionally to the fallback unwindplan %s", 18875ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 18885ffd83dbSDimitry Andric return true; 18895ffd83dbSDimitry Andric } 18905ffd83dbSDimitry Andric return false; 18915ffd83dbSDimitry Andric } 18925ffd83dbSDimitry Andric 18935ffd83dbSDimitry Andric void RegisterContextUnwind::PropagateTrapHandlerFlagFromUnwindPlan( 18945ffd83dbSDimitry Andric lldb::UnwindPlanSP unwind_plan) { 18955ffd83dbSDimitry Andric if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) { 18965ffd83dbSDimitry Andric // Unwind plan does not indicate trap handler. Do nothing. We may 18975ffd83dbSDimitry Andric // already be flagged as trap handler flag due to the symbol being 18985ffd83dbSDimitry Andric // in the trap handler symbol list, and that should take precedence. 18995ffd83dbSDimitry Andric return; 19005ffd83dbSDimitry Andric } else if (m_frame_type != eNormalFrame) { 19015ffd83dbSDimitry Andric // If this is already a trap handler frame, nothing to do. 19025ffd83dbSDimitry Andric // If this is a skip or debug or invalid frame, don't override that. 19035ffd83dbSDimitry Andric return; 19045ffd83dbSDimitry Andric } 19055ffd83dbSDimitry Andric 19065ffd83dbSDimitry Andric m_frame_type = eTrapHandlerFrame; 19075ffd83dbSDimitry Andric 19085ffd83dbSDimitry Andric if (m_current_offset_backed_up_one != m_current_offset) { 19095ffd83dbSDimitry Andric // We backed up the pc by 1 to compute the symbol context, but 19105ffd83dbSDimitry Andric // now need to undo that because the pc of the trap handler 19115ffd83dbSDimitry Andric // frame may in fact be the first instruction of a signal return 19125ffd83dbSDimitry Andric // trampoline, rather than the instruction after a call. This 19135ffd83dbSDimitry Andric // happens on systems where the signal handler dispatch code, rather 19145ffd83dbSDimitry Andric // than calling the handler and being returned to, jumps to the 19155ffd83dbSDimitry Andric // handler after pushing the address of a return trampoline on the 19165ffd83dbSDimitry Andric // stack -- on these systems, when the handler returns, control will 19175ffd83dbSDimitry Andric // be transferred to the return trampoline, so that's the best 19185ffd83dbSDimitry Andric // symbol we can present in the callstack. 19195ffd83dbSDimitry Andric UnwindLogMsg("Resetting current offset and re-doing symbol lookup; " 19205ffd83dbSDimitry Andric "old symbol was %s", 19215ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 19225ffd83dbSDimitry Andric m_current_offset_backed_up_one = m_current_offset; 19235ffd83dbSDimitry Andric 19245ffd83dbSDimitry Andric AddressRange addr_range; 19255ffd83dbSDimitry Andric m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 19265ffd83dbSDimitry Andric 19275ffd83dbSDimitry Andric UnwindLogMsg("Symbol is now %s", 19285ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 19295ffd83dbSDimitry Andric 19305ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 19315ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 19325ffd83dbSDimitry Andric Target *target = &process->GetTarget(); 19335ffd83dbSDimitry Andric 19345ffd83dbSDimitry Andric m_start_pc = addr_range.GetBaseAddress(); 19355ffd83dbSDimitry Andric m_current_offset = 19365ffd83dbSDimitry Andric m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target); 19375ffd83dbSDimitry Andric } 19385ffd83dbSDimitry Andric } 19395ffd83dbSDimitry Andric 19405ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadFrameAddress( 19415ffd83dbSDimitry Andric lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa, 19425ffd83dbSDimitry Andric addr_t &address) { 19435ffd83dbSDimitry Andric RegisterValue reg_value; 19445ffd83dbSDimitry Andric 19455ffd83dbSDimitry Andric address = LLDB_INVALID_ADDRESS; 19465ffd83dbSDimitry Andric addr_t cfa_reg_contents; 19475ffd83dbSDimitry Andric 19485ffd83dbSDimitry Andric switch (fa.GetValueType()) { 19495ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isRegisterDereferenced: { 19505ffd83dbSDimitry Andric RegisterNumber cfa_reg(m_thread, row_register_kind, 19515ffd83dbSDimitry Andric fa.GetRegisterNumber()); 19525ffd83dbSDimitry Andric if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { 19535ffd83dbSDimitry Andric const RegisterInfo *reg_info = 19545ffd83dbSDimitry Andric GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB)); 19555ffd83dbSDimitry Andric RegisterValue reg_value; 19565ffd83dbSDimitry Andric if (reg_info) { 19575ffd83dbSDimitry Andric Status error = ReadRegisterValueFromMemory( 19585ffd83dbSDimitry Andric reg_info, cfa_reg_contents, reg_info->byte_size, reg_value); 19595ffd83dbSDimitry Andric if (error.Success()) { 19605ffd83dbSDimitry Andric address = reg_value.GetAsUInt64(); 1961fe6060f1SDimitry Andric if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) 1962fe6060f1SDimitry Andric address = abi_sp->FixCodeAddress(address); 19635ffd83dbSDimitry Andric UnwindLogMsg( 19645ffd83dbSDimitry Andric "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 19655ffd83dbSDimitry Andric ", CFA value is 0x%" PRIx64, 19665ffd83dbSDimitry Andric cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 19675ffd83dbSDimitry Andric cfa_reg_contents, address); 19685ffd83dbSDimitry Andric return true; 19695ffd83dbSDimitry Andric } else { 19705ffd83dbSDimitry Andric UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64 19715ffd83dbSDimitry Andric "] but memory read failed.", 19725ffd83dbSDimitry Andric cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 19735ffd83dbSDimitry Andric cfa_reg_contents); 19745ffd83dbSDimitry Andric } 19755ffd83dbSDimitry Andric } 19765ffd83dbSDimitry Andric } 19775ffd83dbSDimitry Andric break; 19785ffd83dbSDimitry Andric } 19795ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isRegisterPlusOffset: { 19805ffd83dbSDimitry Andric RegisterNumber cfa_reg(m_thread, row_register_kind, 19815ffd83dbSDimitry Andric fa.GetRegisterNumber()); 19825ffd83dbSDimitry Andric if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { 19835ffd83dbSDimitry Andric if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || 19845ffd83dbSDimitry Andric cfa_reg_contents == 1) { 19855ffd83dbSDimitry Andric UnwindLogMsg( 19865ffd83dbSDimitry Andric "Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, 19875ffd83dbSDimitry Andric cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 19885ffd83dbSDimitry Andric cfa_reg_contents); 19895ffd83dbSDimitry Andric cfa_reg_contents = LLDB_INVALID_ADDRESS; 19905ffd83dbSDimitry Andric return false; 19915ffd83dbSDimitry Andric } 19925ffd83dbSDimitry Andric address = cfa_reg_contents + fa.GetOffset(); 19935ffd83dbSDimitry Andric UnwindLogMsg( 19945ffd83dbSDimitry Andric "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 19955ffd83dbSDimitry Andric ", offset is %d", 19965ffd83dbSDimitry Andric address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 19975ffd83dbSDimitry Andric cfa_reg_contents, fa.GetOffset()); 19985ffd83dbSDimitry Andric return true; 19995ffd83dbSDimitry Andric } 20005ffd83dbSDimitry Andric break; 20015ffd83dbSDimitry Andric } 20025ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isDWARFExpression: { 20035ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 20045ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 20055ffd83dbSDimitry Andric DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(), 20065ffd83dbSDimitry Andric fa.GetDWARFExpressionLength(), 20075ffd83dbSDimitry Andric process->GetByteOrder(), 20085ffd83dbSDimitry Andric process->GetAddressByteSize()); 20095ffd83dbSDimitry Andric ModuleSP opcode_ctx; 2010753f127fSDimitry Andric DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr); 2011753f127fSDimitry Andric dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind( 2012753f127fSDimitry Andric row_register_kind); 20135ffd83dbSDimitry Andric Value result; 20145ffd83dbSDimitry Andric Status error; 20155ffd83dbSDimitry Andric if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, 20165ffd83dbSDimitry Andric &error)) { 20175ffd83dbSDimitry Andric address = result.GetScalar().ULongLong(); 2018fe6060f1SDimitry Andric if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) 2019fe6060f1SDimitry Andric address = abi_sp->FixCodeAddress(address); 20205ffd83dbSDimitry Andric 20215ffd83dbSDimitry Andric UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64, 20225ffd83dbSDimitry Andric address); 20235ffd83dbSDimitry Andric return true; 20245ffd83dbSDimitry Andric } 20255ffd83dbSDimitry Andric UnwindLogMsg("Failed to set CFA value via DWARF expression: %s", 20265ffd83dbSDimitry Andric error.AsCString()); 20275ffd83dbSDimitry Andric break; 20285ffd83dbSDimitry Andric } 20295ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isRaSearch: { 20305ffd83dbSDimitry Andric Process &process = *m_thread.GetProcess(); 20315ffd83dbSDimitry Andric lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset()); 20325ffd83dbSDimitry Andric if (return_address_hint == LLDB_INVALID_ADDRESS) 20335ffd83dbSDimitry Andric return false; 20345ffd83dbSDimitry Andric const unsigned max_iterations = 256; 20355ffd83dbSDimitry Andric for (unsigned i = 0; i < max_iterations; ++i) { 20365ffd83dbSDimitry Andric Status st; 20375ffd83dbSDimitry Andric lldb::addr_t candidate_addr = 20385ffd83dbSDimitry Andric return_address_hint + i * process.GetAddressByteSize(); 20395ffd83dbSDimitry Andric lldb::addr_t candidate = 20405ffd83dbSDimitry Andric process.ReadPointerFromMemory(candidate_addr, st); 20415ffd83dbSDimitry Andric if (st.Fail()) { 20425ffd83dbSDimitry Andric UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr, 20435ffd83dbSDimitry Andric st.AsCString()); 20445ffd83dbSDimitry Andric return false; 20455ffd83dbSDimitry Andric } 20465ffd83dbSDimitry Andric Address addr; 20475ffd83dbSDimitry Andric uint32_t permissions; 20485ffd83dbSDimitry Andric if (process.GetLoadAddressPermissions(candidate, permissions) && 20495ffd83dbSDimitry Andric permissions & lldb::ePermissionsExecutable) { 20505ffd83dbSDimitry Andric address = candidate_addr; 20515ffd83dbSDimitry Andric UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address); 20525ffd83dbSDimitry Andric return true; 20535ffd83dbSDimitry Andric } 20545ffd83dbSDimitry Andric } 20555ffd83dbSDimitry Andric UnwindLogMsg("No suitable CFA found"); 20565ffd83dbSDimitry Andric break; 20575ffd83dbSDimitry Andric } 20585ffd83dbSDimitry Andric default: 20595ffd83dbSDimitry Andric return false; 20605ffd83dbSDimitry Andric } 20615ffd83dbSDimitry Andric return false; 20625ffd83dbSDimitry Andric } 20635ffd83dbSDimitry Andric 20645ffd83dbSDimitry Andric lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) { 20655ffd83dbSDimitry Andric addr_t hint; 20665ffd83dbSDimitry Andric if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint)) 20675ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 20685ffd83dbSDimitry Andric if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol) 20695ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 20705ffd83dbSDimitry Andric 20715ffd83dbSDimitry Andric hint += plan_offset; 20725ffd83dbSDimitry Andric 20735ffd83dbSDimitry Andric if (auto next = GetNextFrame()) { 20745ffd83dbSDimitry Andric if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol) 20755ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 20765ffd83dbSDimitry Andric if (auto expected_size = 20775ffd83dbSDimitry Andric next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize( 20785ffd83dbSDimitry Andric *next->m_sym_ctx.symbol)) 20795ffd83dbSDimitry Andric hint += *expected_size; 20805ffd83dbSDimitry Andric else { 20815ffd83dbSDimitry Andric UnwindLogMsgVerbose("Could not retrieve parameter size: %s", 20825ffd83dbSDimitry Andric llvm::toString(expected_size.takeError()).c_str()); 20835ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 20845ffd83dbSDimitry Andric } 20855ffd83dbSDimitry Andric } 20865ffd83dbSDimitry Andric return hint; 20875ffd83dbSDimitry Andric } 20885ffd83dbSDimitry Andric 20895ffd83dbSDimitry Andric // Retrieve a general purpose register value for THIS frame, as saved by the 20905ffd83dbSDimitry Andric // NEXT frame, i.e. the frame that 20915ffd83dbSDimitry Andric // this frame called. e.g. 20925ffd83dbSDimitry Andric // 20935ffd83dbSDimitry Andric // foo () { } 20945ffd83dbSDimitry Andric // bar () { foo (); } 20955ffd83dbSDimitry Andric // main () { bar (); } 20965ffd83dbSDimitry Andric // 20975ffd83dbSDimitry Andric // stopped in foo() so 20985ffd83dbSDimitry Andric // frame 0 - foo 20995ffd83dbSDimitry Andric // frame 1 - bar 21005ffd83dbSDimitry Andric // frame 2 - main 21015ffd83dbSDimitry Andric // and this RegisterContext is for frame 1 (bar) - if we want to get the pc 21025ffd83dbSDimitry Andric // value for frame 1, we need to ask 21035ffd83dbSDimitry Andric // where frame 0 (the "next" frame) saved that and retrieve the value. 21045ffd83dbSDimitry Andric 21055ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind, 21065ffd83dbSDimitry Andric uint32_t regnum, addr_t &value) { 21075ffd83dbSDimitry Andric if (!IsValid()) 21085ffd83dbSDimitry Andric return false; 21095ffd83dbSDimitry Andric 21105ffd83dbSDimitry Andric uint32_t lldb_regnum; 21115ffd83dbSDimitry Andric if (register_kind == eRegisterKindLLDB) { 21125ffd83dbSDimitry Andric lldb_regnum = regnum; 21135ffd83dbSDimitry Andric } else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds( 21145ffd83dbSDimitry Andric register_kind, regnum, eRegisterKindLLDB, lldb_regnum)) { 21155ffd83dbSDimitry Andric return false; 21165ffd83dbSDimitry Andric } 21175ffd83dbSDimitry Andric 21185ffd83dbSDimitry Andric const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum); 21195ffd83dbSDimitry Andric RegisterValue reg_value; 21205ffd83dbSDimitry Andric // if this is frame 0 (currently executing frame), get the requested reg 21215ffd83dbSDimitry Andric // contents from the actual thread registers 21225ffd83dbSDimitry Andric if (IsFrameZero()) { 21235ffd83dbSDimitry Andric if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) { 21245ffd83dbSDimitry Andric value = reg_value.GetAsUInt64(); 21255ffd83dbSDimitry Andric return true; 21265ffd83dbSDimitry Andric } 21275ffd83dbSDimitry Andric return false; 21285ffd83dbSDimitry Andric } 21295ffd83dbSDimitry Andric 21305ffd83dbSDimitry Andric bool pc_register = false; 21315ffd83dbSDimitry Andric uint32_t generic_regnum; 21325ffd83dbSDimitry Andric if (register_kind == eRegisterKindGeneric && 21335ffd83dbSDimitry Andric (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) { 21345ffd83dbSDimitry Andric pc_register = true; 21355ffd83dbSDimitry Andric } else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds( 21365ffd83dbSDimitry Andric register_kind, regnum, eRegisterKindGeneric, generic_regnum) && 21375ffd83dbSDimitry Andric (generic_regnum == LLDB_REGNUM_GENERIC_PC || 21385ffd83dbSDimitry Andric generic_regnum == LLDB_REGNUM_GENERIC_RA)) { 21395ffd83dbSDimitry Andric pc_register = true; 21405ffd83dbSDimitry Andric } 21415ffd83dbSDimitry Andric 21425ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc; 21435ffd83dbSDimitry Andric if (!m_parent_unwind.SearchForSavedLocationForRegister( 21445ffd83dbSDimitry Andric lldb_regnum, regloc, m_frame_number - 1, pc_register)) { 21455ffd83dbSDimitry Andric return false; 21465ffd83dbSDimitry Andric } 21475ffd83dbSDimitry Andric if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { 21485ffd83dbSDimitry Andric value = reg_value.GetAsUInt64(); 2149fe6060f1SDimitry Andric if (pc_register) { 2150fe6060f1SDimitry Andric if (ProcessSP process_sp = m_thread.GetProcess()) { 2151fe6060f1SDimitry Andric if (ABISP abi = process_sp->GetABI()) 2152fe6060f1SDimitry Andric value = abi->FixCodeAddress(value); 2153fe6060f1SDimitry Andric } 2154fe6060f1SDimitry Andric } 21555ffd83dbSDimitry Andric return true; 21565ffd83dbSDimitry Andric } 21575ffd83dbSDimitry Andric return false; 21585ffd83dbSDimitry Andric } 21595ffd83dbSDimitry Andric 21605ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadGPRValue(const RegisterNumber ®num, 21615ffd83dbSDimitry Andric addr_t &value) { 21625ffd83dbSDimitry Andric return ReadGPRValue(regnum.GetRegisterKind(), regnum.GetRegisterNumber(), 21635ffd83dbSDimitry Andric value); 21645ffd83dbSDimitry Andric } 21655ffd83dbSDimitry Andric 21665ffd83dbSDimitry Andric // Find the value of a register in THIS frame 21675ffd83dbSDimitry Andric 21685ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info, 21695ffd83dbSDimitry Andric RegisterValue &value) { 21705ffd83dbSDimitry Andric if (!IsValid()) 21715ffd83dbSDimitry Andric return false; 21725ffd83dbSDimitry Andric 21735ffd83dbSDimitry Andric const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; 21745ffd83dbSDimitry Andric UnwindLogMsgVerbose("looking for register saved location for reg %d", 21755ffd83dbSDimitry Andric lldb_regnum); 21765ffd83dbSDimitry Andric 21775ffd83dbSDimitry Andric // If this is the 0th frame, hand this over to the live register context 21785ffd83dbSDimitry Andric if (IsFrameZero()) { 21795ffd83dbSDimitry Andric UnwindLogMsgVerbose("passing along to the live register context for reg %d", 21805ffd83dbSDimitry Andric lldb_regnum); 21815ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->ReadRegister(reg_info, value); 21825ffd83dbSDimitry Andric } 21835ffd83dbSDimitry Andric 21845ffd83dbSDimitry Andric bool is_pc_regnum = false; 21855ffd83dbSDimitry Andric if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC || 21865ffd83dbSDimitry Andric reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) { 21875ffd83dbSDimitry Andric is_pc_regnum = true; 21885ffd83dbSDimitry Andric } 21895ffd83dbSDimitry Andric 21905ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc; 21915ffd83dbSDimitry Andric // Find out where the NEXT frame saved THIS frame's register contents 21925ffd83dbSDimitry Andric if (!m_parent_unwind.SearchForSavedLocationForRegister( 21935ffd83dbSDimitry Andric lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum)) 21945ffd83dbSDimitry Andric return false; 21955ffd83dbSDimitry Andric 2196fe6060f1SDimitry Andric bool result = ReadRegisterValueFromRegisterLocation(regloc, reg_info, value); 2197fe6060f1SDimitry Andric if (result) { 2198fe6060f1SDimitry Andric if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) { 2199fe6060f1SDimitry Andric addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS); 2200fe6060f1SDimitry Andric if (reg_value != LLDB_INVALID_ADDRESS) { 2201fe6060f1SDimitry Andric if(ProcessSP process_sp = m_thread.GetProcess()) { 2202fe6060f1SDimitry Andric if (ABISP abi = process_sp->GetABI()) 2203fe6060f1SDimitry Andric value = abi->FixCodeAddress(reg_value); 2204fe6060f1SDimitry Andric } 2205fe6060f1SDimitry Andric } 2206fe6060f1SDimitry Andric } 2207fe6060f1SDimitry Andric } 2208fe6060f1SDimitry Andric return result; 22095ffd83dbSDimitry Andric } 22105ffd83dbSDimitry Andric 22115ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info, 22125ffd83dbSDimitry Andric const RegisterValue &value) { 22135ffd83dbSDimitry Andric if (!IsValid()) 22145ffd83dbSDimitry Andric return false; 22155ffd83dbSDimitry Andric 22165ffd83dbSDimitry Andric const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; 22175ffd83dbSDimitry Andric UnwindLogMsgVerbose("looking for register saved location for reg %d", 22185ffd83dbSDimitry Andric lldb_regnum); 22195ffd83dbSDimitry Andric 22205ffd83dbSDimitry Andric // If this is the 0th frame, hand this over to the live register context 22215ffd83dbSDimitry Andric if (IsFrameZero()) { 22225ffd83dbSDimitry Andric UnwindLogMsgVerbose("passing along to the live register context for reg %d", 22235ffd83dbSDimitry Andric lldb_regnum); 22245ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->WriteRegister(reg_info, value); 22255ffd83dbSDimitry Andric } 22265ffd83dbSDimitry Andric 22275ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc; 22285ffd83dbSDimitry Andric // Find out where the NEXT frame saved THIS frame's register contents 22295ffd83dbSDimitry Andric if (!m_parent_unwind.SearchForSavedLocationForRegister( 22305ffd83dbSDimitry Andric lldb_regnum, regloc, m_frame_number - 1, false)) 22315ffd83dbSDimitry Andric return false; 22325ffd83dbSDimitry Andric 22335ffd83dbSDimitry Andric return WriteRegisterValueToRegisterLocation(regloc, reg_info, value); 22345ffd83dbSDimitry Andric } 22355ffd83dbSDimitry Andric 22365ffd83dbSDimitry Andric // Don't need to implement this one 223781ad6265SDimitry Andric bool RegisterContextUnwind::ReadAllRegisterValues( 223881ad6265SDimitry Andric lldb::WritableDataBufferSP &data_sp) { 22395ffd83dbSDimitry Andric return false; 22405ffd83dbSDimitry Andric } 22415ffd83dbSDimitry Andric 22425ffd83dbSDimitry Andric // Don't need to implement this one 22435ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteAllRegisterValues( 22445ffd83dbSDimitry Andric const lldb::DataBufferSP &data_sp) { 22455ffd83dbSDimitry Andric return false; 22465ffd83dbSDimitry Andric } 22475ffd83dbSDimitry Andric 22485ffd83dbSDimitry Andric // Retrieve the pc value for THIS from 22495ffd83dbSDimitry Andric 22505ffd83dbSDimitry Andric bool RegisterContextUnwind::GetCFA(addr_t &cfa) { 22515ffd83dbSDimitry Andric if (!IsValid()) { 22525ffd83dbSDimitry Andric return false; 22535ffd83dbSDimitry Andric } 22545ffd83dbSDimitry Andric if (m_cfa == LLDB_INVALID_ADDRESS) { 22555ffd83dbSDimitry Andric return false; 22565ffd83dbSDimitry Andric } 22575ffd83dbSDimitry Andric cfa = m_cfa; 22585ffd83dbSDimitry Andric return true; 22595ffd83dbSDimitry Andric } 22605ffd83dbSDimitry Andric 22615ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetNextFrame() const { 22625ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr regctx; 22635ffd83dbSDimitry Andric if (m_frame_number == 0) 22645ffd83dbSDimitry Andric return regctx; 22655ffd83dbSDimitry Andric return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number - 1); 22665ffd83dbSDimitry Andric } 22675ffd83dbSDimitry Andric 22685ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetPrevFrame() const { 22695ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr regctx; 22705ffd83dbSDimitry Andric return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number + 1); 22715ffd83dbSDimitry Andric } 22725ffd83dbSDimitry Andric 22735ffd83dbSDimitry Andric // Retrieve the address of the start of the function of THIS frame 22745ffd83dbSDimitry Andric 22755ffd83dbSDimitry Andric bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) { 22765ffd83dbSDimitry Andric if (!IsValid()) 22775ffd83dbSDimitry Andric return false; 22785ffd83dbSDimitry Andric 22795ffd83dbSDimitry Andric if (!m_start_pc.IsValid()) { 22805ffd83dbSDimitry Andric bool read_successfully = ReadPC (start_pc); 22815ffd83dbSDimitry Andric if (read_successfully) 22825ffd83dbSDimitry Andric { 22835ffd83dbSDimitry Andric ProcessSP process_sp (m_thread.GetProcess()); 22845ffd83dbSDimitry Andric if (process_sp) 22855ffd83dbSDimitry Andric { 22865ffd83dbSDimitry Andric ABI *abi = process_sp->GetABI().get(); 22875ffd83dbSDimitry Andric if (abi) 22885ffd83dbSDimitry Andric start_pc = abi->FixCodeAddress(start_pc); 22895ffd83dbSDimitry Andric } 22905ffd83dbSDimitry Andric } 22915ffd83dbSDimitry Andric return read_successfully; 22925ffd83dbSDimitry Andric } 22935ffd83dbSDimitry Andric start_pc = m_start_pc.GetLoadAddress(CalculateTarget().get()); 22945ffd83dbSDimitry Andric return true; 22955ffd83dbSDimitry Andric } 22965ffd83dbSDimitry Andric 22975ffd83dbSDimitry Andric // Retrieve the current pc value for THIS frame, as saved by the NEXT frame. 22985ffd83dbSDimitry Andric 22995ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadPC(addr_t &pc) { 23005ffd83dbSDimitry Andric if (!IsValid()) 23015ffd83dbSDimitry Andric return false; 23025ffd83dbSDimitry Andric 23035ffd83dbSDimitry Andric bool above_trap_handler = false; 23045ffd83dbSDimitry Andric if (GetNextFrame().get() && GetNextFrame()->IsValid() && 23055ffd83dbSDimitry Andric GetNextFrame()->IsTrapHandlerFrame()) 23065ffd83dbSDimitry Andric above_trap_handler = true; 23075ffd83dbSDimitry Andric 23085ffd83dbSDimitry Andric if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { 23095ffd83dbSDimitry Andric // A pc value of 0 or 1 is impossible in the middle of the stack -- it 23105ffd83dbSDimitry Andric // indicates the end of a stack walk. 23115ffd83dbSDimitry Andric // On the currently executing frame (or such a frame interrupted 23125ffd83dbSDimitry Andric // asynchronously by sigtramp et al) this may occur if code has jumped 23135ffd83dbSDimitry Andric // through a NULL pointer -- we want to be able to unwind past that frame 23145ffd83dbSDimitry Andric // to help find the bug. 23155ffd83dbSDimitry Andric 23165ffd83dbSDimitry Andric ProcessSP process_sp (m_thread.GetProcess()); 23175ffd83dbSDimitry Andric if (process_sp) 23185ffd83dbSDimitry Andric { 23195ffd83dbSDimitry Andric ABI *abi = process_sp->GetABI().get(); 23205ffd83dbSDimitry Andric if (abi) 23215ffd83dbSDimitry Andric pc = abi->FixCodeAddress(pc); 23225ffd83dbSDimitry Andric } 23235ffd83dbSDimitry Andric 23245ffd83dbSDimitry Andric return !(m_all_registers_available == false && 23255ffd83dbSDimitry Andric above_trap_handler == false && (pc == 0 || pc == 1)); 23265ffd83dbSDimitry Andric } else { 23275ffd83dbSDimitry Andric return false; 23285ffd83dbSDimitry Andric } 23295ffd83dbSDimitry Andric } 23305ffd83dbSDimitry Andric 23315ffd83dbSDimitry Andric void RegisterContextUnwind::UnwindLogMsg(const char *fmt, ...) { 233281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 233381ad6265SDimitry Andric if (!log) 233481ad6265SDimitry Andric return; 233581ad6265SDimitry Andric 23365ffd83dbSDimitry Andric va_list args; 23375ffd83dbSDimitry Andric va_start(args, fmt); 23385ffd83dbSDimitry Andric 233981ad6265SDimitry Andric llvm::SmallString<0> logmsg; 234081ad6265SDimitry Andric if (VASprintf(logmsg, fmt, args)) { 23415ffd83dbSDimitry Andric LLDB_LOGF(log, "%*sth%d/fr%u %s", 23425ffd83dbSDimitry Andric m_frame_number < 100 ? m_frame_number : 100, "", 234381ad6265SDimitry Andric m_thread.GetIndexID(), m_frame_number, logmsg.c_str()); 23445ffd83dbSDimitry Andric } 234581ad6265SDimitry Andric va_end(args); 23465ffd83dbSDimitry Andric } 23475ffd83dbSDimitry Andric 23485ffd83dbSDimitry Andric void RegisterContextUnwind::UnwindLogMsgVerbose(const char *fmt, ...) { 234981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 235081ad6265SDimitry Andric if (!log || !log->GetVerbose()) 235181ad6265SDimitry Andric return; 235281ad6265SDimitry Andric 23535ffd83dbSDimitry Andric va_list args; 23545ffd83dbSDimitry Andric va_start(args, fmt); 23555ffd83dbSDimitry Andric 235681ad6265SDimitry Andric llvm::SmallString<0> logmsg; 235781ad6265SDimitry Andric if (VASprintf(logmsg, fmt, args)) { 23585ffd83dbSDimitry Andric LLDB_LOGF(log, "%*sth%d/fr%u %s", 23595ffd83dbSDimitry Andric m_frame_number < 100 ? m_frame_number : 100, "", 236081ad6265SDimitry Andric m_thread.GetIndexID(), m_frame_number, logmsg.c_str()); 23615ffd83dbSDimitry Andric } 236281ad6265SDimitry Andric va_end(args); 23635ffd83dbSDimitry Andric } 2364