1*5ffd83dbSDimitry Andric //===-- RegisterContextUnwind.cpp -----------------------------------------===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5ffd83dbSDimitry Andric // 7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric 9*5ffd83dbSDimitry Andric #include "lldb/Target/RegisterContextUnwind.h" 10*5ffd83dbSDimitry Andric #include "lldb/Core/Address.h" 11*5ffd83dbSDimitry Andric #include "lldb/Core/AddressRange.h" 12*5ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 13*5ffd83dbSDimitry Andric #include "lldb/Core/Value.h" 14*5ffd83dbSDimitry Andric #include "lldb/Expression/DWARFExpression.h" 15*5ffd83dbSDimitry Andric #include "lldb/Symbol/ArmUnwindInfo.h" 16*5ffd83dbSDimitry Andric #include "lldb/Symbol/CallFrameInfo.h" 17*5ffd83dbSDimitry Andric #include "lldb/Symbol/DWARFCallFrameInfo.h" 18*5ffd83dbSDimitry Andric #include "lldb/Symbol/FuncUnwinders.h" 19*5ffd83dbSDimitry Andric #include "lldb/Symbol/Function.h" 20*5ffd83dbSDimitry Andric #include "lldb/Symbol/ObjectFile.h" 21*5ffd83dbSDimitry Andric #include "lldb/Symbol/Symbol.h" 22*5ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h" 23*5ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolFile.h" 24*5ffd83dbSDimitry Andric #include "lldb/Target/ABI.h" 25*5ffd83dbSDimitry Andric #include "lldb/Target/DynamicLoader.h" 26*5ffd83dbSDimitry Andric #include "lldb/Target/ExecutionContext.h" 27*5ffd83dbSDimitry Andric #include "lldb/Target/Platform.h" 28*5ffd83dbSDimitry Andric #include "lldb/Target/Process.h" 29*5ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h" 30*5ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h" 31*5ffd83dbSDimitry Andric #include "lldb/Target/Target.h" 32*5ffd83dbSDimitry Andric #include "lldb/Target/Thread.h" 33*5ffd83dbSDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 34*5ffd83dbSDimitry Andric #include "lldb/Utility/Log.h" 35*5ffd83dbSDimitry Andric #include "lldb/Utility/RegisterValue.h" 36*5ffd83dbSDimitry Andric #include "lldb/lldb-private.h" 37*5ffd83dbSDimitry Andric 38*5ffd83dbSDimitry Andric #include <memory> 39*5ffd83dbSDimitry Andric 40*5ffd83dbSDimitry Andric using namespace lldb; 41*5ffd83dbSDimitry Andric using namespace lldb_private; 42*5ffd83dbSDimitry Andric 43*5ffd83dbSDimitry Andric static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) { 44*5ffd83dbSDimitry Andric if (sym_ctx.symbol) 45*5ffd83dbSDimitry Andric return sym_ctx.symbol->GetName(); 46*5ffd83dbSDimitry Andric else if (sym_ctx.function) 47*5ffd83dbSDimitry Andric return sym_ctx.function->GetName(); 48*5ffd83dbSDimitry Andric return ConstString(); 49*5ffd83dbSDimitry Andric } 50*5ffd83dbSDimitry Andric 51*5ffd83dbSDimitry Andric RegisterContextUnwind::RegisterContextUnwind(Thread &thread, 52*5ffd83dbSDimitry Andric const SharedPtr &next_frame, 53*5ffd83dbSDimitry Andric SymbolContext &sym_ctx, 54*5ffd83dbSDimitry Andric uint32_t frame_number, 55*5ffd83dbSDimitry Andric UnwindLLDB &unwind_lldb) 56*5ffd83dbSDimitry Andric : RegisterContext(thread, frame_number), m_thread(thread), 57*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(), 58*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp(), m_all_registers_available(false), 59*5ffd83dbSDimitry Andric m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS), 60*5ffd83dbSDimitry Andric m_afa(LLDB_INVALID_ADDRESS), m_start_pc(), 61*5ffd83dbSDimitry Andric m_current_pc(), m_current_offset(0), m_current_offset_backed_up_one(0), 62*5ffd83dbSDimitry Andric m_sym_ctx(sym_ctx), m_sym_ctx_valid(false), m_frame_number(frame_number), 63*5ffd83dbSDimitry Andric m_registers(), m_parent_unwind(unwind_lldb) { 64*5ffd83dbSDimitry Andric m_sym_ctx.Clear(false); 65*5ffd83dbSDimitry Andric m_sym_ctx_valid = false; 66*5ffd83dbSDimitry Andric 67*5ffd83dbSDimitry Andric if (IsFrameZero()) { 68*5ffd83dbSDimitry Andric InitializeZerothFrame(); 69*5ffd83dbSDimitry Andric } else { 70*5ffd83dbSDimitry Andric InitializeNonZerothFrame(); 71*5ffd83dbSDimitry Andric } 72*5ffd83dbSDimitry Andric 73*5ffd83dbSDimitry Andric // This same code exists over in the GetFullUnwindPlanForFrame() but it may 74*5ffd83dbSDimitry Andric // not have been executed yet 75*5ffd83dbSDimitry Andric if (IsFrameZero() || next_frame->m_frame_type == eTrapHandlerFrame || 76*5ffd83dbSDimitry Andric next_frame->m_frame_type == eDebuggerFrame) { 77*5ffd83dbSDimitry Andric m_all_registers_available = true; 78*5ffd83dbSDimitry Andric } 79*5ffd83dbSDimitry Andric } 80*5ffd83dbSDimitry Andric 81*5ffd83dbSDimitry Andric bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC( 82*5ffd83dbSDimitry Andric lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset) { 83*5ffd83dbSDimitry Andric if (!unwind_plan_sp) 84*5ffd83dbSDimitry Andric return false; 85*5ffd83dbSDimitry Andric 86*5ffd83dbSDimitry Andric // check if m_current_pc is valid 87*5ffd83dbSDimitry Andric if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 88*5ffd83dbSDimitry Andric // yes - current offset can be used as is 89*5ffd83dbSDimitry Andric valid_pc_offset = m_current_offset; 90*5ffd83dbSDimitry Andric return true; 91*5ffd83dbSDimitry Andric } 92*5ffd83dbSDimitry Andric 93*5ffd83dbSDimitry Andric // if m_current_offset <= 0, we've got nothing else to try 94*5ffd83dbSDimitry Andric if (m_current_offset <= 0) 95*5ffd83dbSDimitry Andric return false; 96*5ffd83dbSDimitry Andric 97*5ffd83dbSDimitry Andric // check pc - 1 to see if it's valid 98*5ffd83dbSDimitry Andric Address pc_minus_one(m_current_pc); 99*5ffd83dbSDimitry Andric pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1); 100*5ffd83dbSDimitry Andric if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) { 101*5ffd83dbSDimitry Andric // *valid_pc_offset = m_current_offset - 1; 102*5ffd83dbSDimitry Andric valid_pc_offset = m_current_pc.GetOffset() - 1; 103*5ffd83dbSDimitry Andric return true; 104*5ffd83dbSDimitry Andric } 105*5ffd83dbSDimitry Andric 106*5ffd83dbSDimitry Andric return false; 107*5ffd83dbSDimitry Andric } 108*5ffd83dbSDimitry Andric 109*5ffd83dbSDimitry Andric // Initialize a RegisterContextUnwind which is the first frame of a stack -- the 110*5ffd83dbSDimitry Andric // zeroth frame or currently executing frame. 111*5ffd83dbSDimitry Andric 112*5ffd83dbSDimitry Andric void RegisterContextUnwind::InitializeZerothFrame() { 113*5ffd83dbSDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 114*5ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 115*5ffd83dbSDimitry Andric RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); 116*5ffd83dbSDimitry Andric 117*5ffd83dbSDimitry Andric if (reg_ctx_sp.get() == nullptr) { 118*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 119*5ffd83dbSDimitry Andric UnwindLogMsg("frame does not have a register context"); 120*5ffd83dbSDimitry Andric return; 121*5ffd83dbSDimitry Andric } 122*5ffd83dbSDimitry Andric 123*5ffd83dbSDimitry Andric addr_t current_pc = reg_ctx_sp->GetPC(); 124*5ffd83dbSDimitry Andric 125*5ffd83dbSDimitry Andric if (current_pc == LLDB_INVALID_ADDRESS) { 126*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 127*5ffd83dbSDimitry Andric UnwindLogMsg("frame does not have a pc"); 128*5ffd83dbSDimitry Andric return; 129*5ffd83dbSDimitry Andric } 130*5ffd83dbSDimitry Andric 131*5ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 132*5ffd83dbSDimitry Andric 133*5ffd83dbSDimitry Andric // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs 134*5ffd83dbSDimitry Andric // this will strip bit zero in case we read a PC from memory or from the LR. 135*5ffd83dbSDimitry Andric // (which would be a no-op in frame 0 where we get it from the register set, 136*5ffd83dbSDimitry Andric // but still a good idea to make the call here for other ABIs that may 137*5ffd83dbSDimitry Andric // exist.) 138*5ffd83dbSDimitry Andric ABI *abi = process->GetABI().get(); 139*5ffd83dbSDimitry Andric if (abi) 140*5ffd83dbSDimitry Andric current_pc = abi->FixCodeAddress(current_pc); 141*5ffd83dbSDimitry Andric 142*5ffd83dbSDimitry Andric // Initialize m_current_pc, an Address object, based on current_pc, an 143*5ffd83dbSDimitry Andric // addr_t. 144*5ffd83dbSDimitry Andric m_current_pc.SetLoadAddress(current_pc, &process->GetTarget()); 145*5ffd83dbSDimitry Andric 146*5ffd83dbSDimitry Andric // If we don't have a Module for some reason, we're not going to find 147*5ffd83dbSDimitry Andric // symbol/function information - just stick in some reasonable defaults and 148*5ffd83dbSDimitry Andric // hope we can unwind past this frame. 149*5ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 150*5ffd83dbSDimitry Andric if (!m_current_pc.IsValid() || !pc_module_sp) { 151*5ffd83dbSDimitry Andric UnwindLogMsg("using architectural default unwind method"); 152*5ffd83dbSDimitry Andric } 153*5ffd83dbSDimitry Andric 154*5ffd83dbSDimitry Andric AddressRange addr_range; 155*5ffd83dbSDimitry Andric m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 156*5ffd83dbSDimitry Andric 157*5ffd83dbSDimitry Andric if (m_sym_ctx.symbol) { 158*5ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", 159*5ffd83dbSDimitry Andric current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 160*5ffd83dbSDimitry Andric } else if (m_sym_ctx.function) { 161*5ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", 162*5ffd83dbSDimitry Andric current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 163*5ffd83dbSDimitry Andric } else { 164*5ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 165*5ffd83dbSDimitry Andric ", no symbol/function name is known.", 166*5ffd83dbSDimitry Andric current_pc); 167*5ffd83dbSDimitry Andric } 168*5ffd83dbSDimitry Andric 169*5ffd83dbSDimitry Andric if (IsTrapHandlerSymbol(process, m_sym_ctx)) { 170*5ffd83dbSDimitry Andric m_frame_type = eTrapHandlerFrame; 171*5ffd83dbSDimitry Andric } else { 172*5ffd83dbSDimitry Andric // FIXME: Detect eDebuggerFrame here. 173*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 174*5ffd83dbSDimitry Andric } 175*5ffd83dbSDimitry Andric 176*5ffd83dbSDimitry Andric // If we were able to find a symbol/function, set addr_range to the bounds of 177*5ffd83dbSDimitry Andric // that symbol/function. else treat the current pc value as the start_pc and 178*5ffd83dbSDimitry Andric // record no offset. 179*5ffd83dbSDimitry Andric if (addr_range.GetBaseAddress().IsValid()) { 180*5ffd83dbSDimitry Andric m_start_pc = addr_range.GetBaseAddress(); 181*5ffd83dbSDimitry Andric if (m_current_pc.GetSection() == m_start_pc.GetSection()) { 182*5ffd83dbSDimitry Andric m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset(); 183*5ffd83dbSDimitry Andric } else if (m_current_pc.GetModule() == m_start_pc.GetModule()) { 184*5ffd83dbSDimitry Andric // This means that whatever symbol we kicked up isn't really correct --- 185*5ffd83dbSDimitry Andric // we should not cross section boundaries ... We really should NULL out 186*5ffd83dbSDimitry Andric // the function/symbol in this case unless there is a bad assumption here 187*5ffd83dbSDimitry Andric // due to inlined functions? 188*5ffd83dbSDimitry Andric m_current_offset = 189*5ffd83dbSDimitry Andric m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress(); 190*5ffd83dbSDimitry Andric } 191*5ffd83dbSDimitry Andric m_current_offset_backed_up_one = m_current_offset; 192*5ffd83dbSDimitry Andric } else { 193*5ffd83dbSDimitry Andric m_start_pc = m_current_pc; 194*5ffd83dbSDimitry Andric m_current_offset = -1; 195*5ffd83dbSDimitry Andric m_current_offset_backed_up_one = -1; 196*5ffd83dbSDimitry Andric } 197*5ffd83dbSDimitry Andric 198*5ffd83dbSDimitry Andric // We've set m_frame_type and m_sym_ctx before these calls. 199*5ffd83dbSDimitry Andric 200*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame(); 201*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); 202*5ffd83dbSDimitry Andric 203*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row; 204*5ffd83dbSDimitry Andric lldb::RegisterKind row_register_kind = eRegisterKindGeneric; 205*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp && 206*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 207*5ffd83dbSDimitry Andric active_row = 208*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 209*5ffd83dbSDimitry Andric row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); 210*5ffd83dbSDimitry Andric if (active_row.get() && log) { 211*5ffd83dbSDimitry Andric StreamString active_row_strm; 212*5ffd83dbSDimitry Andric active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, 213*5ffd83dbSDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 214*5ffd83dbSDimitry Andric UnwindLogMsg("%s", active_row_strm.GetData()); 215*5ffd83dbSDimitry Andric } 216*5ffd83dbSDimitry Andric } 217*5ffd83dbSDimitry Andric 218*5ffd83dbSDimitry Andric if (!active_row.get()) { 219*5ffd83dbSDimitry Andric UnwindLogMsg("could not find an unwindplan row for this frame's pc"); 220*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 221*5ffd83dbSDimitry Andric return; 222*5ffd83dbSDimitry Andric } 223*5ffd83dbSDimitry Andric 224*5ffd83dbSDimitry Andric if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) { 225*5ffd83dbSDimitry Andric // Try the fall back unwind plan since the 226*5ffd83dbSDimitry Andric // full unwind plan failed. 227*5ffd83dbSDimitry Andric FuncUnwindersSP func_unwinders_sp; 228*5ffd83dbSDimitry Andric UnwindPlanSP call_site_unwind_plan; 229*5ffd83dbSDimitry Andric bool cfa_status = false; 230*5ffd83dbSDimitry Andric 231*5ffd83dbSDimitry Andric if (m_sym_ctx_valid) { 232*5ffd83dbSDimitry Andric func_unwinders_sp = 233*5ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress( 234*5ffd83dbSDimitry Andric m_current_pc, m_sym_ctx); 235*5ffd83dbSDimitry Andric } 236*5ffd83dbSDimitry Andric 237*5ffd83dbSDimitry Andric if (func_unwinders_sp.get() != nullptr) 238*5ffd83dbSDimitry Andric call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite( 239*5ffd83dbSDimitry Andric process->GetTarget(), m_thread); 240*5ffd83dbSDimitry Andric 241*5ffd83dbSDimitry Andric if (call_site_unwind_plan.get() != nullptr) { 242*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = call_site_unwind_plan; 243*5ffd83dbSDimitry Andric if (TryFallbackUnwindPlan()) 244*5ffd83dbSDimitry Andric cfa_status = true; 245*5ffd83dbSDimitry Andric } 246*5ffd83dbSDimitry Andric if (!cfa_status) { 247*5ffd83dbSDimitry Andric UnwindLogMsg("could not read CFA value for first frame."); 248*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 249*5ffd83dbSDimitry Andric return; 250*5ffd83dbSDimitry Andric } 251*5ffd83dbSDimitry Andric } else 252*5ffd83dbSDimitry Andric ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa); 253*5ffd83dbSDimitry Andric 254*5ffd83dbSDimitry Andric UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 255*5ffd83dbSDimitry Andric " afa is 0x%" PRIx64 " using %s UnwindPlan", 256*5ffd83dbSDimitry Andric (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), 257*5ffd83dbSDimitry Andric (uint64_t)m_cfa, 258*5ffd83dbSDimitry Andric (uint64_t)m_afa, 259*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 260*5ffd83dbSDimitry Andric } 261*5ffd83dbSDimitry Andric 262*5ffd83dbSDimitry Andric // Initialize a RegisterContextUnwind for the non-zeroth frame -- rely on the 263*5ffd83dbSDimitry Andric // RegisterContextUnwind "below" it to provide things like its current pc value. 264*5ffd83dbSDimitry Andric 265*5ffd83dbSDimitry Andric void RegisterContextUnwind::InitializeNonZerothFrame() { 266*5ffd83dbSDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 267*5ffd83dbSDimitry Andric if (IsFrameZero()) { 268*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 269*5ffd83dbSDimitry Andric UnwindLogMsg("non-zeroth frame tests positive for IsFrameZero -- that " 270*5ffd83dbSDimitry Andric "shouldn't happen."); 271*5ffd83dbSDimitry Andric return; 272*5ffd83dbSDimitry Andric } 273*5ffd83dbSDimitry Andric 274*5ffd83dbSDimitry Andric if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) { 275*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 276*5ffd83dbSDimitry Andric UnwindLogMsg("Could not get next frame, marking this frame as invalid."); 277*5ffd83dbSDimitry Andric return; 278*5ffd83dbSDimitry Andric } 279*5ffd83dbSDimitry Andric if (!m_thread.GetRegisterContext()) { 280*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 281*5ffd83dbSDimitry Andric UnwindLogMsg("Could not get register context for this thread, marking this " 282*5ffd83dbSDimitry Andric "frame as invalid."); 283*5ffd83dbSDimitry Andric return; 284*5ffd83dbSDimitry Andric } 285*5ffd83dbSDimitry Andric 286*5ffd83dbSDimitry Andric addr_t pc; 287*5ffd83dbSDimitry Andric if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { 288*5ffd83dbSDimitry Andric UnwindLogMsg("could not get pc value"); 289*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 290*5ffd83dbSDimitry Andric return; 291*5ffd83dbSDimitry Andric } 292*5ffd83dbSDimitry Andric 293*5ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 294*5ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 295*5ffd83dbSDimitry Andric // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs 296*5ffd83dbSDimitry Andric // this will strip bit zero in case we read a PC from memory or from the LR. 297*5ffd83dbSDimitry Andric ABI *abi = process->GetABI().get(); 298*5ffd83dbSDimitry Andric if (abi) 299*5ffd83dbSDimitry Andric pc = abi->FixCodeAddress(pc); 300*5ffd83dbSDimitry Andric 301*5ffd83dbSDimitry Andric if (log) { 302*5ffd83dbSDimitry Andric UnwindLogMsg("pc = 0x%" PRIx64, pc); 303*5ffd83dbSDimitry Andric addr_t reg_val; 304*5ffd83dbSDimitry Andric if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) 305*5ffd83dbSDimitry Andric UnwindLogMsg("fp = 0x%" PRIx64, reg_val); 306*5ffd83dbSDimitry Andric if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) 307*5ffd83dbSDimitry Andric UnwindLogMsg("sp = 0x%" PRIx64, reg_val); 308*5ffd83dbSDimitry Andric } 309*5ffd83dbSDimitry Andric 310*5ffd83dbSDimitry Andric // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap 311*5ffd83dbSDimitry Andric // handler function 312*5ffd83dbSDimitry Andric bool above_trap_handler = false; 313*5ffd83dbSDimitry Andric if (GetNextFrame().get() && GetNextFrame()->IsValid() && 314*5ffd83dbSDimitry Andric GetNextFrame()->IsTrapHandlerFrame()) 315*5ffd83dbSDimitry Andric above_trap_handler = true; 316*5ffd83dbSDimitry Andric 317*5ffd83dbSDimitry Andric if (pc == 0 || pc == 0x1) { 318*5ffd83dbSDimitry Andric if (!above_trap_handler) { 319*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 320*5ffd83dbSDimitry Andric UnwindLogMsg("this frame has a pc of 0x0"); 321*5ffd83dbSDimitry Andric return; 322*5ffd83dbSDimitry Andric } 323*5ffd83dbSDimitry Andric } 324*5ffd83dbSDimitry Andric 325*5ffd83dbSDimitry Andric const bool allow_section_end = true; 326*5ffd83dbSDimitry Andric m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end); 327*5ffd83dbSDimitry Andric 328*5ffd83dbSDimitry Andric // If we don't have a Module for some reason, we're not going to find 329*5ffd83dbSDimitry Andric // symbol/function information - just stick in some reasonable defaults and 330*5ffd83dbSDimitry Andric // hope we can unwind past this frame. If we're above a trap handler, 331*5ffd83dbSDimitry Andric // we may be at a bogus address because we jumped through a bogus function 332*5ffd83dbSDimitry Andric // pointer and trapped, so don't force the arch default unwind plan in that 333*5ffd83dbSDimitry Andric // case. 334*5ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 335*5ffd83dbSDimitry Andric if ((!m_current_pc.IsValid() || !pc_module_sp) && 336*5ffd83dbSDimitry Andric above_trap_handler == false) { 337*5ffd83dbSDimitry Andric UnwindLogMsg("using architectural default unwind method"); 338*5ffd83dbSDimitry Andric 339*5ffd83dbSDimitry Andric // Test the pc value to see if we know it's in an unmapped/non-executable 340*5ffd83dbSDimitry Andric // region of memory. 341*5ffd83dbSDimitry Andric uint32_t permissions; 342*5ffd83dbSDimitry Andric if (process->GetLoadAddressPermissions(pc, permissions) && 343*5ffd83dbSDimitry Andric (permissions & ePermissionsExecutable) == 0) { 344*5ffd83dbSDimitry Andric // If this is the second frame off the stack, we may have unwound the 345*5ffd83dbSDimitry Andric // first frame incorrectly. But using the architecture default unwind 346*5ffd83dbSDimitry Andric // plan may get us back on track -- albeit possibly skipping a real 347*5ffd83dbSDimitry Andric // frame. Give this frame a clearly-invalid pc and see if we can get any 348*5ffd83dbSDimitry Andric // further. 349*5ffd83dbSDimitry Andric if (GetNextFrame().get() && GetNextFrame()->IsValid() && 350*5ffd83dbSDimitry Andric GetNextFrame()->IsFrameZero()) { 351*5ffd83dbSDimitry Andric UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable " 352*5ffd83dbSDimitry Andric "memory but on frame 1 -- " 353*5ffd83dbSDimitry Andric "allowing it once.", 354*5ffd83dbSDimitry Andric (uint64_t)pc); 355*5ffd83dbSDimitry Andric m_frame_type = eSkipFrame; 356*5ffd83dbSDimitry Andric } else { 357*5ffd83dbSDimitry Andric // anywhere other than the second frame, a non-executable pc means 358*5ffd83dbSDimitry Andric // we're off in the weeds -- stop now. 359*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 360*5ffd83dbSDimitry Andric UnwindLogMsg("pc is in a non-executable section of memory and this " 361*5ffd83dbSDimitry Andric "isn't the 2nd frame in the stack walk."); 362*5ffd83dbSDimitry Andric return; 363*5ffd83dbSDimitry Andric } 364*5ffd83dbSDimitry Andric } 365*5ffd83dbSDimitry Andric 366*5ffd83dbSDimitry Andric if (abi) { 367*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp.reset(); 368*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = 369*5ffd83dbSDimitry Andric std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 370*5ffd83dbSDimitry Andric abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp); 371*5ffd83dbSDimitry Andric if (m_frame_type != eSkipFrame) // don't override eSkipFrame 372*5ffd83dbSDimitry Andric { 373*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 374*5ffd83dbSDimitry Andric } 375*5ffd83dbSDimitry Andric m_all_registers_available = false; 376*5ffd83dbSDimitry Andric m_current_offset = -1; 377*5ffd83dbSDimitry Andric m_current_offset_backed_up_one = -1; 378*5ffd83dbSDimitry Andric RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); 379*5ffd83dbSDimitry Andric UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0); 380*5ffd83dbSDimitry Andric if (row.get()) { 381*5ffd83dbSDimitry Andric if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) { 382*5ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa value"); 383*5ffd83dbSDimitry Andric if (m_frame_type != eSkipFrame) // don't override eSkipFrame 384*5ffd83dbSDimitry Andric { 385*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 386*5ffd83dbSDimitry Andric } 387*5ffd83dbSDimitry Andric return; 388*5ffd83dbSDimitry Andric } 389*5ffd83dbSDimitry Andric 390*5ffd83dbSDimitry Andric ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa); 391*5ffd83dbSDimitry Andric 392*5ffd83dbSDimitry Andric // A couple of sanity checks.. 393*5ffd83dbSDimitry Andric if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) { 394*5ffd83dbSDimitry Andric UnwindLogMsg("could not find a valid cfa address"); 395*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 396*5ffd83dbSDimitry Andric return; 397*5ffd83dbSDimitry Andric } 398*5ffd83dbSDimitry Andric 399*5ffd83dbSDimitry Andric // m_cfa should point into the stack memory; if we can query memory 400*5ffd83dbSDimitry Andric // region permissions, see if the memory is allocated & readable. 401*5ffd83dbSDimitry Andric if (process->GetLoadAddressPermissions(m_cfa, permissions) && 402*5ffd83dbSDimitry Andric (permissions & ePermissionsReadable) == 0) { 403*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 404*5ffd83dbSDimitry Andric UnwindLogMsg( 405*5ffd83dbSDimitry Andric "the CFA points to a region of memory that is not readable"); 406*5ffd83dbSDimitry Andric return; 407*5ffd83dbSDimitry Andric } 408*5ffd83dbSDimitry Andric } else { 409*5ffd83dbSDimitry Andric UnwindLogMsg("could not find a row for function offset zero"); 410*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 411*5ffd83dbSDimitry Andric return; 412*5ffd83dbSDimitry Andric } 413*5ffd83dbSDimitry Andric 414*5ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 415*5ffd83dbSDimitry Andric TryFallbackUnwindPlan(); 416*5ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 417*5ffd83dbSDimitry Andric UnwindLogMsg("same CFA address as next frame, assuming the unwind is " 418*5ffd83dbSDimitry Andric "looping - stopping"); 419*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 420*5ffd83dbSDimitry Andric return; 421*5ffd83dbSDimitry Andric } 422*5ffd83dbSDimitry Andric } 423*5ffd83dbSDimitry Andric 424*5ffd83dbSDimitry Andric UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64, 425*5ffd83dbSDimitry Andric (uint64_t)m_cfa, (uint64_t)m_afa); 426*5ffd83dbSDimitry Andric return; 427*5ffd83dbSDimitry Andric } 428*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 429*5ffd83dbSDimitry Andric UnwindLogMsg("could not find any symbol for this pc, or a default unwind " 430*5ffd83dbSDimitry Andric "plan, to continue unwind."); 431*5ffd83dbSDimitry Andric return; 432*5ffd83dbSDimitry Andric } 433*5ffd83dbSDimitry Andric 434*5ffd83dbSDimitry Andric AddressRange addr_range; 435*5ffd83dbSDimitry Andric m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 436*5ffd83dbSDimitry Andric 437*5ffd83dbSDimitry Andric if (m_sym_ctx.symbol) { 438*5ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc, 439*5ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 440*5ffd83dbSDimitry Andric } else if (m_sym_ctx.function) { 441*5ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", pc, 442*5ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 443*5ffd83dbSDimitry Andric } else { 444*5ffd83dbSDimitry Andric UnwindLogMsg("with pc value of 0x%" PRIx64 445*5ffd83dbSDimitry Andric ", no symbol/function name is known.", 446*5ffd83dbSDimitry Andric pc); 447*5ffd83dbSDimitry Andric } 448*5ffd83dbSDimitry Andric 449*5ffd83dbSDimitry Andric bool decr_pc_and_recompute_addr_range; 450*5ffd83dbSDimitry Andric 451*5ffd83dbSDimitry Andric if (!m_sym_ctx_valid) { 452*5ffd83dbSDimitry Andric // Always decrement and recompute if the symbol lookup failed 453*5ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = true; 454*5ffd83dbSDimitry Andric } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame || 455*5ffd83dbSDimitry Andric GetNextFrame()->m_frame_type == eDebuggerFrame) { 456*5ffd83dbSDimitry Andric // Don't decrement if we're "above" an asynchronous event like 457*5ffd83dbSDimitry Andric // sigtramp. 458*5ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = false; 459*5ffd83dbSDimitry Andric } else if (!addr_range.GetBaseAddress().IsValid() || 460*5ffd83dbSDimitry Andric addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() || 461*5ffd83dbSDimitry Andric addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) { 462*5ffd83dbSDimitry Andric // If our "current" pc isn't the start of a function, no need 463*5ffd83dbSDimitry Andric // to decrement and recompute. 464*5ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = false; 465*5ffd83dbSDimitry Andric } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) { 466*5ffd83dbSDimitry Andric // Signal dispatch may set the return address of the handler it calls to 467*5ffd83dbSDimitry Andric // point to the first byte of a return trampoline (like __kernel_rt_sigreturn), 468*5ffd83dbSDimitry Andric // so do not decrement and recompute if the symbol we already found is a trap 469*5ffd83dbSDimitry Andric // handler. 470*5ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = false; 471*5ffd83dbSDimitry Andric } else { 472*5ffd83dbSDimitry Andric // Decrement to find the function containing the call. 473*5ffd83dbSDimitry Andric decr_pc_and_recompute_addr_range = true; 474*5ffd83dbSDimitry Andric } 475*5ffd83dbSDimitry Andric 476*5ffd83dbSDimitry Andric // We need to back up the pc by 1 byte and re-search for the Symbol to handle 477*5ffd83dbSDimitry Andric // the case where the "saved pc" value is pointing to the next function, e.g. 478*5ffd83dbSDimitry Andric // if a function ends with a CALL instruction. 479*5ffd83dbSDimitry Andric // FIXME this may need to be an architectural-dependent behavior; if so we'll 480*5ffd83dbSDimitry Andric // need to add a member function 481*5ffd83dbSDimitry Andric // to the ABI plugin and consult that. 482*5ffd83dbSDimitry Andric if (decr_pc_and_recompute_addr_range) { 483*5ffd83dbSDimitry Andric UnwindLogMsg("Backing up the pc value of 0x%" PRIx64 484*5ffd83dbSDimitry Andric " by 1 and re-doing symbol lookup; old symbol was %s", 485*5ffd83dbSDimitry Andric pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 486*5ffd83dbSDimitry Andric Address temporary_pc; 487*5ffd83dbSDimitry Andric temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget()); 488*5ffd83dbSDimitry Andric m_sym_ctx.Clear(false); 489*5ffd83dbSDimitry Andric m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 490*5ffd83dbSDimitry Andric 491*5ffd83dbSDimitry Andric UnwindLogMsg("Symbol is now %s", 492*5ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 493*5ffd83dbSDimitry Andric } 494*5ffd83dbSDimitry Andric 495*5ffd83dbSDimitry Andric // If we were able to find a symbol/function, set addr_range_ptr to the 496*5ffd83dbSDimitry Andric // bounds of that symbol/function. else treat the current pc value as the 497*5ffd83dbSDimitry Andric // start_pc and record no offset. 498*5ffd83dbSDimitry Andric if (addr_range.GetBaseAddress().IsValid()) { 499*5ffd83dbSDimitry Andric m_start_pc = addr_range.GetBaseAddress(); 500*5ffd83dbSDimitry Andric m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget()); 501*5ffd83dbSDimitry Andric m_current_offset_backed_up_one = m_current_offset; 502*5ffd83dbSDimitry Andric if (decr_pc_and_recompute_addr_range && 503*5ffd83dbSDimitry Andric m_current_offset_backed_up_one > 0) { 504*5ffd83dbSDimitry Andric m_current_offset_backed_up_one--; 505*5ffd83dbSDimitry Andric if (m_sym_ctx_valid) { 506*5ffd83dbSDimitry Andric m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget()); 507*5ffd83dbSDimitry Andric } 508*5ffd83dbSDimitry Andric } 509*5ffd83dbSDimitry Andric } else { 510*5ffd83dbSDimitry Andric m_start_pc = m_current_pc; 511*5ffd83dbSDimitry Andric m_current_offset = -1; 512*5ffd83dbSDimitry Andric m_current_offset_backed_up_one = -1; 513*5ffd83dbSDimitry Andric } 514*5ffd83dbSDimitry Andric 515*5ffd83dbSDimitry Andric if (IsTrapHandlerSymbol(process, m_sym_ctx)) { 516*5ffd83dbSDimitry Andric m_frame_type = eTrapHandlerFrame; 517*5ffd83dbSDimitry Andric } else { 518*5ffd83dbSDimitry Andric // FIXME: Detect eDebuggerFrame here. 519*5ffd83dbSDimitry Andric if (m_frame_type != eSkipFrame) // don't override eSkipFrame 520*5ffd83dbSDimitry Andric { 521*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 522*5ffd83dbSDimitry Andric } 523*5ffd83dbSDimitry Andric } 524*5ffd83dbSDimitry Andric 525*5ffd83dbSDimitry Andric // We've set m_frame_type and m_sym_ctx before this call. 526*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame(); 527*5ffd83dbSDimitry Andric 528*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row; 529*5ffd83dbSDimitry Andric RegisterKind row_register_kind = eRegisterKindGeneric; 530*5ffd83dbSDimitry Andric 531*5ffd83dbSDimitry Andric // Try to get by with just the fast UnwindPlan if possible - the full 532*5ffd83dbSDimitry Andric // UnwindPlan may be expensive to get (e.g. if we have to parse the entire 533*5ffd83dbSDimitry Andric // eh_frame section of an ObjectFile for the first time.) 534*5ffd83dbSDimitry Andric 535*5ffd83dbSDimitry Andric if (m_fast_unwind_plan_sp && 536*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 537*5ffd83dbSDimitry Andric active_row = 538*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 539*5ffd83dbSDimitry Andric row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind(); 540*5ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp); 541*5ffd83dbSDimitry Andric if (active_row.get() && log) { 542*5ffd83dbSDimitry Andric StreamString active_row_strm; 543*5ffd83dbSDimitry Andric active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, 544*5ffd83dbSDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 545*5ffd83dbSDimitry Andric UnwindLogMsg("active row: %s", active_row_strm.GetData()); 546*5ffd83dbSDimitry Andric } 547*5ffd83dbSDimitry Andric } else { 548*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); 549*5ffd83dbSDimitry Andric int valid_offset = -1; 550*5ffd83dbSDimitry Andric if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) { 551*5ffd83dbSDimitry Andric active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset); 552*5ffd83dbSDimitry Andric row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); 553*5ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); 554*5ffd83dbSDimitry Andric if (active_row.get() && log) { 555*5ffd83dbSDimitry Andric StreamString active_row_strm; 556*5ffd83dbSDimitry Andric active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), 557*5ffd83dbSDimitry Andric &m_thread, 558*5ffd83dbSDimitry Andric m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); 559*5ffd83dbSDimitry Andric UnwindLogMsg("active row: %s", active_row_strm.GetData()); 560*5ffd83dbSDimitry Andric } 561*5ffd83dbSDimitry Andric } 562*5ffd83dbSDimitry Andric } 563*5ffd83dbSDimitry Andric 564*5ffd83dbSDimitry Andric if (!active_row.get()) { 565*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 566*5ffd83dbSDimitry Andric UnwindLogMsg("could not find unwind row for this pc"); 567*5ffd83dbSDimitry Andric return; 568*5ffd83dbSDimitry Andric } 569*5ffd83dbSDimitry Andric 570*5ffd83dbSDimitry Andric if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) { 571*5ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa"); 572*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 573*5ffd83dbSDimitry Andric return; 574*5ffd83dbSDimitry Andric } 575*5ffd83dbSDimitry Andric 576*5ffd83dbSDimitry Andric ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa); 577*5ffd83dbSDimitry Andric 578*5ffd83dbSDimitry Andric UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa); 579*5ffd83dbSDimitry Andric 580*5ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 581*5ffd83dbSDimitry Andric TryFallbackUnwindPlan(); 582*5ffd83dbSDimitry Andric if (CheckIfLoopingStack()) { 583*5ffd83dbSDimitry Andric UnwindLogMsg("same CFA address as next frame, assuming the unwind is " 584*5ffd83dbSDimitry Andric "looping - stopping"); 585*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 586*5ffd83dbSDimitry Andric return; 587*5ffd83dbSDimitry Andric } 588*5ffd83dbSDimitry Andric } 589*5ffd83dbSDimitry Andric 590*5ffd83dbSDimitry Andric UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 591*5ffd83dbSDimitry Andric " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64, 592*5ffd83dbSDimitry Andric (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), 593*5ffd83dbSDimitry Andric (uint64_t)m_cfa, 594*5ffd83dbSDimitry Andric (uint64_t)m_afa); 595*5ffd83dbSDimitry Andric } 596*5ffd83dbSDimitry Andric 597*5ffd83dbSDimitry Andric bool RegisterContextUnwind::CheckIfLoopingStack() { 598*5ffd83dbSDimitry Andric // If we have a bad stack setup, we can get the same CFA value multiple times 599*5ffd83dbSDimitry Andric // -- or even more devious, we can actually oscillate between two CFA values. 600*5ffd83dbSDimitry Andric // Detect that here and break out to avoid a possible infinite loop in lldb 601*5ffd83dbSDimitry Andric // trying to unwind the stack. To detect when we have the same CFA value 602*5ffd83dbSDimitry Andric // multiple times, we compare the 603*5ffd83dbSDimitry Andric // CFA of the current 604*5ffd83dbSDimitry Andric // frame with the 2nd next frame because in some specail case (e.g. signal 605*5ffd83dbSDimitry Andric // hanlders, hand written assembly without ABI compliance) we can have 2 606*5ffd83dbSDimitry Andric // frames with the same 607*5ffd83dbSDimitry Andric // CFA (in theory we 608*5ffd83dbSDimitry Andric // can have arbitrary number of frames with the same CFA, but more then 2 is 609*5ffd83dbSDimitry Andric // very very unlikely) 610*5ffd83dbSDimitry Andric 611*5ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr next_frame = GetNextFrame(); 612*5ffd83dbSDimitry Andric if (next_frame) { 613*5ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr next_next_frame = 614*5ffd83dbSDimitry Andric next_frame->GetNextFrame(); 615*5ffd83dbSDimitry Andric addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; 616*5ffd83dbSDimitry Andric if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa)) { 617*5ffd83dbSDimitry Andric if (next_next_frame_cfa == m_cfa) { 618*5ffd83dbSDimitry Andric // We have a loop in the stack unwind 619*5ffd83dbSDimitry Andric return true; 620*5ffd83dbSDimitry Andric } 621*5ffd83dbSDimitry Andric } 622*5ffd83dbSDimitry Andric } 623*5ffd83dbSDimitry Andric return false; 624*5ffd83dbSDimitry Andric } 625*5ffd83dbSDimitry Andric 626*5ffd83dbSDimitry Andric bool RegisterContextUnwind::IsFrameZero() const { return m_frame_number == 0; } 627*5ffd83dbSDimitry Andric 628*5ffd83dbSDimitry Andric // Find a fast unwind plan for this frame, if possible. 629*5ffd83dbSDimitry Andric // 630*5ffd83dbSDimitry Andric // On entry to this method, 631*5ffd83dbSDimitry Andric // 632*5ffd83dbSDimitry Andric // 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame 633*5ffd83dbSDimitry Andric // if either of those are correct, 634*5ffd83dbSDimitry Andric // 2. m_sym_ctx should already be filled in, and 635*5ffd83dbSDimitry Andric // 3. m_current_pc should have the current pc value for this frame 636*5ffd83dbSDimitry Andric // 4. m_current_offset_backed_up_one should have the current byte offset into 637*5ffd83dbSDimitry Andric // the function, maybe backed up by 1, -1 if unknown 638*5ffd83dbSDimitry Andric 639*5ffd83dbSDimitry Andric UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() { 640*5ffd83dbSDimitry Andric UnwindPlanSP unwind_plan_sp; 641*5ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 642*5ffd83dbSDimitry Andric 643*5ffd83dbSDimitry Andric if (!m_current_pc.IsValid() || !pc_module_sp || 644*5ffd83dbSDimitry Andric pc_module_sp->GetObjectFile() == nullptr) 645*5ffd83dbSDimitry Andric return unwind_plan_sp; 646*5ffd83dbSDimitry Andric 647*5ffd83dbSDimitry Andric if (IsFrameZero()) 648*5ffd83dbSDimitry Andric return unwind_plan_sp; 649*5ffd83dbSDimitry Andric 650*5ffd83dbSDimitry Andric FuncUnwindersSP func_unwinders_sp( 651*5ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress( 652*5ffd83dbSDimitry Andric m_current_pc, m_sym_ctx)); 653*5ffd83dbSDimitry Andric if (!func_unwinders_sp) 654*5ffd83dbSDimitry Andric return unwind_plan_sp; 655*5ffd83dbSDimitry Andric 656*5ffd83dbSDimitry Andric // If we're in _sigtramp(), unwinding past this frame requires special 657*5ffd83dbSDimitry Andric // knowledge. 658*5ffd83dbSDimitry Andric if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame) 659*5ffd83dbSDimitry Andric return unwind_plan_sp; 660*5ffd83dbSDimitry Andric 661*5ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind( 662*5ffd83dbSDimitry Andric *m_thread.CalculateTarget(), m_thread); 663*5ffd83dbSDimitry Andric if (unwind_plan_sp) { 664*5ffd83dbSDimitry Andric if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 665*5ffd83dbSDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 666*5ffd83dbSDimitry Andric if (log && log->GetVerbose()) { 667*5ffd83dbSDimitry Andric if (m_fast_unwind_plan_sp) 668*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame, and has a fast UnwindPlan"); 669*5ffd83dbSDimitry Andric else 670*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame"); 671*5ffd83dbSDimitry Andric } 672*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 673*5ffd83dbSDimitry Andric return unwind_plan_sp; 674*5ffd83dbSDimitry Andric } else { 675*5ffd83dbSDimitry Andric unwind_plan_sp.reset(); 676*5ffd83dbSDimitry Andric } 677*5ffd83dbSDimitry Andric } 678*5ffd83dbSDimitry Andric return unwind_plan_sp; 679*5ffd83dbSDimitry Andric } 680*5ffd83dbSDimitry Andric 681*5ffd83dbSDimitry Andric // On entry to this method, 682*5ffd83dbSDimitry Andric // 683*5ffd83dbSDimitry Andric // 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame 684*5ffd83dbSDimitry Andric // if either of those are correct, 685*5ffd83dbSDimitry Andric // 2. m_sym_ctx should already be filled in, and 686*5ffd83dbSDimitry Andric // 3. m_current_pc should have the current pc value for this frame 687*5ffd83dbSDimitry Andric // 4. m_current_offset_backed_up_one should have the current byte offset into 688*5ffd83dbSDimitry Andric // the function, maybe backed up by 1, -1 if unknown 689*5ffd83dbSDimitry Andric 690*5ffd83dbSDimitry Andric UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() { 691*5ffd83dbSDimitry Andric UnwindPlanSP unwind_plan_sp; 692*5ffd83dbSDimitry Andric UnwindPlanSP arch_default_unwind_plan_sp; 693*5ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 694*5ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 695*5ffd83dbSDimitry Andric ABI *abi = process ? process->GetABI().get() : nullptr; 696*5ffd83dbSDimitry Andric if (abi) { 697*5ffd83dbSDimitry Andric arch_default_unwind_plan_sp = 698*5ffd83dbSDimitry Andric std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 699*5ffd83dbSDimitry Andric abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp); 700*5ffd83dbSDimitry Andric } else { 701*5ffd83dbSDimitry Andric UnwindLogMsg( 702*5ffd83dbSDimitry Andric "unable to get architectural default UnwindPlan from ABI plugin"); 703*5ffd83dbSDimitry Andric } 704*5ffd83dbSDimitry Andric 705*5ffd83dbSDimitry Andric bool behaves_like_zeroth_frame = false; 706*5ffd83dbSDimitry Andric if (IsFrameZero() || GetNextFrame()->m_frame_type == eTrapHandlerFrame || 707*5ffd83dbSDimitry Andric GetNextFrame()->m_frame_type == eDebuggerFrame) { 708*5ffd83dbSDimitry Andric behaves_like_zeroth_frame = true; 709*5ffd83dbSDimitry Andric // If this frame behaves like a 0th frame (currently executing or 710*5ffd83dbSDimitry Andric // interrupted asynchronously), all registers can be retrieved. 711*5ffd83dbSDimitry Andric m_all_registers_available = true; 712*5ffd83dbSDimitry Andric } 713*5ffd83dbSDimitry Andric 714*5ffd83dbSDimitry Andric // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer) 715*5ffd83dbSDimitry Andric // so the pc is 0x0 in the zeroth frame, we need to use the "unwind at first 716*5ffd83dbSDimitry Andric // instruction" arch default UnwindPlan Also, if this Process can report on 717*5ffd83dbSDimitry Andric // memory region attributes, any non-executable region means we jumped 718*5ffd83dbSDimitry Andric // through a bad function pointer - handle the same way as 0x0. Note, if we 719*5ffd83dbSDimitry Andric // have a symbol context & a symbol, we don't want to follow this code path. 720*5ffd83dbSDimitry Andric // This is for jumping to memory regions without any information available. 721*5ffd83dbSDimitry Andric 722*5ffd83dbSDimitry Andric if ((!m_sym_ctx_valid || 723*5ffd83dbSDimitry Andric (m_sym_ctx.function == nullptr && m_sym_ctx.symbol == nullptr)) && 724*5ffd83dbSDimitry Andric behaves_like_zeroth_frame && m_current_pc.IsValid()) { 725*5ffd83dbSDimitry Andric uint32_t permissions; 726*5ffd83dbSDimitry Andric addr_t current_pc_addr = 727*5ffd83dbSDimitry Andric m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()); 728*5ffd83dbSDimitry Andric if (current_pc_addr == 0 || 729*5ffd83dbSDimitry Andric (process && 730*5ffd83dbSDimitry Andric process->GetLoadAddressPermissions(current_pc_addr, permissions) && 731*5ffd83dbSDimitry Andric (permissions & ePermissionsExecutable) == 0)) { 732*5ffd83dbSDimitry Andric if (abi) { 733*5ffd83dbSDimitry Andric unwind_plan_sp = 734*5ffd83dbSDimitry Andric std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 735*5ffd83dbSDimitry Andric abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp); 736*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 737*5ffd83dbSDimitry Andric return unwind_plan_sp; 738*5ffd83dbSDimitry Andric } 739*5ffd83dbSDimitry Andric } 740*5ffd83dbSDimitry Andric } 741*5ffd83dbSDimitry Andric 742*5ffd83dbSDimitry Andric // No Module for the current pc, try using the architecture default unwind. 743*5ffd83dbSDimitry Andric ModuleSP pc_module_sp(m_current_pc.GetModule()); 744*5ffd83dbSDimitry Andric if (!m_current_pc.IsValid() || !pc_module_sp || 745*5ffd83dbSDimitry Andric pc_module_sp->GetObjectFile() == nullptr) { 746*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 747*5ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 748*5ffd83dbSDimitry Andric } 749*5ffd83dbSDimitry Andric 750*5ffd83dbSDimitry Andric FuncUnwindersSP func_unwinders_sp; 751*5ffd83dbSDimitry Andric if (m_sym_ctx_valid) { 752*5ffd83dbSDimitry Andric func_unwinders_sp = 753*5ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress( 754*5ffd83dbSDimitry Andric m_current_pc, m_sym_ctx); 755*5ffd83dbSDimitry Andric } 756*5ffd83dbSDimitry Andric 757*5ffd83dbSDimitry Andric // No FuncUnwinders available for this pc (stripped function symbols, lldb 758*5ffd83dbSDimitry Andric // could not augment its function table with another source, like 759*5ffd83dbSDimitry Andric // LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). See if eh_frame or the 760*5ffd83dbSDimitry Andric // .ARM.exidx tables have unwind information for this address, else fall back 761*5ffd83dbSDimitry Andric // to the architectural default unwind. 762*5ffd83dbSDimitry Andric if (!func_unwinders_sp) { 763*5ffd83dbSDimitry Andric m_frame_type = eNormalFrame; 764*5ffd83dbSDimitry Andric 765*5ffd83dbSDimitry Andric if (!pc_module_sp || !pc_module_sp->GetObjectFile() || 766*5ffd83dbSDimitry Andric !m_current_pc.IsValid()) 767*5ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 768*5ffd83dbSDimitry Andric 769*5ffd83dbSDimitry Andric // Even with -fomit-frame-pointer, we can try eh_frame to get back on 770*5ffd83dbSDimitry Andric // track. 771*5ffd83dbSDimitry Andric DWARFCallFrameInfo *eh_frame = 772*5ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetEHFrameInfo(); 773*5ffd83dbSDimitry Andric if (eh_frame) { 774*5ffd83dbSDimitry Andric unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 775*5ffd83dbSDimitry Andric if (eh_frame->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) 776*5ffd83dbSDimitry Andric return unwind_plan_sp; 777*5ffd83dbSDimitry Andric else 778*5ffd83dbSDimitry Andric unwind_plan_sp.reset(); 779*5ffd83dbSDimitry Andric } 780*5ffd83dbSDimitry Andric 781*5ffd83dbSDimitry Andric ArmUnwindInfo *arm_exidx = 782*5ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetArmUnwindInfo(); 783*5ffd83dbSDimitry Andric if (arm_exidx) { 784*5ffd83dbSDimitry Andric unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 785*5ffd83dbSDimitry Andric if (arm_exidx->GetUnwindPlan(exe_ctx.GetTargetRef(), m_current_pc, 786*5ffd83dbSDimitry Andric *unwind_plan_sp)) 787*5ffd83dbSDimitry Andric return unwind_plan_sp; 788*5ffd83dbSDimitry Andric else 789*5ffd83dbSDimitry Andric unwind_plan_sp.reset(); 790*5ffd83dbSDimitry Andric } 791*5ffd83dbSDimitry Andric 792*5ffd83dbSDimitry Andric CallFrameInfo *object_file_unwind = 793*5ffd83dbSDimitry Andric pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo(); 794*5ffd83dbSDimitry Andric if (object_file_unwind) { 795*5ffd83dbSDimitry Andric unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); 796*5ffd83dbSDimitry Andric if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) 797*5ffd83dbSDimitry Andric return unwind_plan_sp; 798*5ffd83dbSDimitry Andric else 799*5ffd83dbSDimitry Andric unwind_plan_sp.reset(); 800*5ffd83dbSDimitry Andric } 801*5ffd83dbSDimitry Andric 802*5ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 803*5ffd83dbSDimitry Andric } 804*5ffd83dbSDimitry Andric 805*5ffd83dbSDimitry Andric // If we're in _sigtramp(), unwinding past this frame requires special 806*5ffd83dbSDimitry Andric // knowledge. On Mac OS X this knowledge is properly encoded in the eh_frame 807*5ffd83dbSDimitry Andric // section, so prefer that if available. On other platforms we may need to 808*5ffd83dbSDimitry Andric // provide a platform-specific UnwindPlan which encodes the details of how to 809*5ffd83dbSDimitry Andric // unwind out of sigtramp. 810*5ffd83dbSDimitry Andric if (m_frame_type == eTrapHandlerFrame && process) { 811*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp.reset(); 812*5ffd83dbSDimitry Andric unwind_plan_sp = 813*5ffd83dbSDimitry Andric func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); 814*5ffd83dbSDimitry Andric if (!unwind_plan_sp) 815*5ffd83dbSDimitry Andric unwind_plan_sp = 816*5ffd83dbSDimitry Andric func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); 817*5ffd83dbSDimitry Andric if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) && 818*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { 819*5ffd83dbSDimitry Andric return unwind_plan_sp; 820*5ffd83dbSDimitry Andric } 821*5ffd83dbSDimitry Andric } 822*5ffd83dbSDimitry Andric 823*5ffd83dbSDimitry Andric // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame 824*5ffd83dbSDimitry Andric // even when it's frame zero This comes up if we have hand-written functions 825*5ffd83dbSDimitry Andric // in a Module and hand-written eh_frame. The assembly instruction 826*5ffd83dbSDimitry Andric // inspection may fail and the eh_frame CFI were probably written with some 827*5ffd83dbSDimitry Andric // care to do the right thing. It'd be nice if there was a way to ask the 828*5ffd83dbSDimitry Andric // eh_frame directly if it is asynchronous (can be trusted at every 829*5ffd83dbSDimitry Andric // instruction point) or synchronous (the normal case - only at call sites). 830*5ffd83dbSDimitry Andric // But there is not. 831*5ffd83dbSDimitry Andric if (process && process->GetDynamicLoader() && 832*5ffd83dbSDimitry Andric process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) { 833*5ffd83dbSDimitry Andric // We must specifically call the GetEHFrameUnwindPlan() method here -- 834*5ffd83dbSDimitry Andric // normally we would call GetUnwindPlanAtCallSite() -- because CallSite may 835*5ffd83dbSDimitry Andric // return an unwind plan sourced from either eh_frame (that's what we 836*5ffd83dbSDimitry Andric // intend) or compact unwind (this won't work) 837*5ffd83dbSDimitry Andric unwind_plan_sp = 838*5ffd83dbSDimitry Andric func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); 839*5ffd83dbSDimitry Andric if (!unwind_plan_sp) 840*5ffd83dbSDimitry Andric unwind_plan_sp = 841*5ffd83dbSDimitry Andric func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); 842*5ffd83dbSDimitry Andric if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 843*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the " 844*5ffd83dbSDimitry Andric "DynamicLoader suggested we prefer it", 845*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 846*5ffd83dbSDimitry Andric return unwind_plan_sp; 847*5ffd83dbSDimitry Andric } 848*5ffd83dbSDimitry Andric } 849*5ffd83dbSDimitry Andric 850*5ffd83dbSDimitry Andric // Typically the NonCallSite UnwindPlan is the unwind created by inspecting 851*5ffd83dbSDimitry Andric // the assembly language instructions 852*5ffd83dbSDimitry Andric if (behaves_like_zeroth_frame && process) { 853*5ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite( 854*5ffd83dbSDimitry Andric process->GetTarget(), m_thread); 855*5ffd83dbSDimitry Andric if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { 856*5ffd83dbSDimitry Andric if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { 857*5ffd83dbSDimitry Andric // We probably have an UnwindPlan created by inspecting assembly 858*5ffd83dbSDimitry Andric // instructions. The assembly profilers work really well with compiler- 859*5ffd83dbSDimitry Andric // generated functions but hand- written assembly can be problematic. 860*5ffd83dbSDimitry Andric // We set the eh_frame based unwind plan as our fallback unwind plan if 861*5ffd83dbSDimitry Andric // instruction emulation doesn't work out even for non call sites if it 862*5ffd83dbSDimitry Andric // is available and use the architecture default unwind plan if it is 863*5ffd83dbSDimitry Andric // not available. The eh_frame unwind plan is more reliable even on non 864*5ffd83dbSDimitry Andric // call sites then the architecture default plan and for hand written 865*5ffd83dbSDimitry Andric // assembly code it is often written in a way that it valid at all 866*5ffd83dbSDimitry Andric // location what helps in the most common cases when the instruction 867*5ffd83dbSDimitry Andric // emulation fails. 868*5ffd83dbSDimitry Andric UnwindPlanSP call_site_unwind_plan = 869*5ffd83dbSDimitry Andric func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), 870*5ffd83dbSDimitry Andric m_thread); 871*5ffd83dbSDimitry Andric if (call_site_unwind_plan && 872*5ffd83dbSDimitry Andric call_site_unwind_plan.get() != unwind_plan_sp.get() && 873*5ffd83dbSDimitry Andric call_site_unwind_plan->GetSourceName() != 874*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName()) { 875*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = call_site_unwind_plan; 876*5ffd83dbSDimitry Andric } else { 877*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; 878*5ffd83dbSDimitry Andric } 879*5ffd83dbSDimitry Andric } 880*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this " 881*5ffd83dbSDimitry Andric "is the non-call site unwind plan and this is a " 882*5ffd83dbSDimitry Andric "zeroth frame", 883*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 884*5ffd83dbSDimitry Andric return unwind_plan_sp; 885*5ffd83dbSDimitry Andric } 886*5ffd83dbSDimitry Andric 887*5ffd83dbSDimitry Andric // If we're on the first instruction of a function, and we have an 888*5ffd83dbSDimitry Andric // architectural default UnwindPlan for the initial instruction of a 889*5ffd83dbSDimitry Andric // function, use that. 890*5ffd83dbSDimitry Andric if (m_current_offset == 0) { 891*5ffd83dbSDimitry Andric unwind_plan_sp = 892*5ffd83dbSDimitry Andric func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry( 893*5ffd83dbSDimitry Andric m_thread); 894*5ffd83dbSDimitry Andric if (unwind_plan_sp) { 895*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we are at " 896*5ffd83dbSDimitry Andric "the first instruction of a function", 897*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 898*5ffd83dbSDimitry Andric return unwind_plan_sp; 899*5ffd83dbSDimitry Andric } 900*5ffd83dbSDimitry Andric } 901*5ffd83dbSDimitry Andric } 902*5ffd83dbSDimitry Andric 903*5ffd83dbSDimitry Andric // Typically this is unwind info from an eh_frame section intended for 904*5ffd83dbSDimitry Andric // exception handling; only valid at call sites 905*5ffd83dbSDimitry Andric if (process) { 906*5ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite( 907*5ffd83dbSDimitry Andric process->GetTarget(), m_thread); 908*5ffd83dbSDimitry Andric } 909*5ffd83dbSDimitry Andric int valid_offset = -1; 910*5ffd83dbSDimitry Andric if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { 911*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this " 912*5ffd83dbSDimitry Andric "is the call-site unwind plan", 913*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 914*5ffd83dbSDimitry Andric return unwind_plan_sp; 915*5ffd83dbSDimitry Andric } 916*5ffd83dbSDimitry Andric 917*5ffd83dbSDimitry Andric // We'd prefer to use an UnwindPlan intended for call sites when we're at a 918*5ffd83dbSDimitry Andric // call site but if we've struck out on that, fall back to using the non- 919*5ffd83dbSDimitry Andric // call-site assembly inspection UnwindPlan if possible. 920*5ffd83dbSDimitry Andric if (process) { 921*5ffd83dbSDimitry Andric unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite( 922*5ffd83dbSDimitry Andric process->GetTarget(), m_thread); 923*5ffd83dbSDimitry Andric } 924*5ffd83dbSDimitry Andric if (unwind_plan_sp && 925*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { 926*5ffd83dbSDimitry Andric // We probably have an UnwindPlan created by inspecting assembly 927*5ffd83dbSDimitry Andric // instructions. The assembly profilers work really well with compiler- 928*5ffd83dbSDimitry Andric // generated functions but hand- written assembly can be problematic. We 929*5ffd83dbSDimitry Andric // set the eh_frame based unwind plan as our fallback unwind plan if 930*5ffd83dbSDimitry Andric // instruction emulation doesn't work out even for non call sites if it is 931*5ffd83dbSDimitry Andric // available and use the architecture default unwind plan if it is not 932*5ffd83dbSDimitry Andric // available. The eh_frame unwind plan is more reliable even on non call 933*5ffd83dbSDimitry Andric // sites then the architecture default plan and for hand written assembly 934*5ffd83dbSDimitry Andric // code it is often written in a way that it valid at all location what 935*5ffd83dbSDimitry Andric // helps in the most common cases when the instruction emulation fails. 936*5ffd83dbSDimitry Andric UnwindPlanSP call_site_unwind_plan = 937*5ffd83dbSDimitry Andric func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), 938*5ffd83dbSDimitry Andric m_thread); 939*5ffd83dbSDimitry Andric if (call_site_unwind_plan && 940*5ffd83dbSDimitry Andric call_site_unwind_plan.get() != unwind_plan_sp.get() && 941*5ffd83dbSDimitry Andric call_site_unwind_plan->GetSourceName() != 942*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName()) { 943*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = call_site_unwind_plan; 944*5ffd83dbSDimitry Andric } else { 945*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; 946*5ffd83dbSDimitry Andric } 947*5ffd83dbSDimitry Andric } 948*5ffd83dbSDimitry Andric 949*5ffd83dbSDimitry Andric if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { 950*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we " 951*5ffd83dbSDimitry Andric "failed to find a call-site unwind plan that would work", 952*5ffd83dbSDimitry Andric unwind_plan_sp->GetSourceName().GetCString()); 953*5ffd83dbSDimitry Andric return unwind_plan_sp; 954*5ffd83dbSDimitry Andric } 955*5ffd83dbSDimitry Andric 956*5ffd83dbSDimitry Andric // If nothing else, use the architectural default UnwindPlan and hope that 957*5ffd83dbSDimitry Andric // does the job. 958*5ffd83dbSDimitry Andric if (arch_default_unwind_plan_sp) 959*5ffd83dbSDimitry Andric UnwindLogMsgVerbose( 960*5ffd83dbSDimitry Andric "frame uses %s for full UnwindPlan because we are falling back " 961*5ffd83dbSDimitry Andric "to the arch default plan", 962*5ffd83dbSDimitry Andric arch_default_unwind_plan_sp->GetSourceName().GetCString()); 963*5ffd83dbSDimitry Andric else 964*5ffd83dbSDimitry Andric UnwindLogMsg( 965*5ffd83dbSDimitry Andric "Unable to find any UnwindPlan for full unwind of this frame."); 966*5ffd83dbSDimitry Andric 967*5ffd83dbSDimitry Andric return arch_default_unwind_plan_sp; 968*5ffd83dbSDimitry Andric } 969*5ffd83dbSDimitry Andric 970*5ffd83dbSDimitry Andric void RegisterContextUnwind::InvalidateAllRegisters() { 971*5ffd83dbSDimitry Andric m_frame_type = eNotAValidFrame; 972*5ffd83dbSDimitry Andric } 973*5ffd83dbSDimitry Andric 974*5ffd83dbSDimitry Andric size_t RegisterContextUnwind::GetRegisterCount() { 975*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterCount(); 976*5ffd83dbSDimitry Andric } 977*5ffd83dbSDimitry Andric 978*5ffd83dbSDimitry Andric const RegisterInfo *RegisterContextUnwind::GetRegisterInfoAtIndex(size_t reg) { 979*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); 980*5ffd83dbSDimitry Andric } 981*5ffd83dbSDimitry Andric 982*5ffd83dbSDimitry Andric size_t RegisterContextUnwind::GetRegisterSetCount() { 983*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterSetCount(); 984*5ffd83dbSDimitry Andric } 985*5ffd83dbSDimitry Andric 986*5ffd83dbSDimitry Andric const RegisterSet *RegisterContextUnwind::GetRegisterSet(size_t reg_set) { 987*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->GetRegisterSet(reg_set); 988*5ffd83dbSDimitry Andric } 989*5ffd83dbSDimitry Andric 990*5ffd83dbSDimitry Andric uint32_t RegisterContextUnwind::ConvertRegisterKindToRegisterNumber( 991*5ffd83dbSDimitry Andric lldb::RegisterKind kind, uint32_t num) { 992*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 993*5ffd83dbSDimitry Andric kind, num); 994*5ffd83dbSDimitry Andric } 995*5ffd83dbSDimitry Andric 996*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadRegisterValueFromRegisterLocation( 997*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc, 998*5ffd83dbSDimitry Andric const RegisterInfo *reg_info, RegisterValue &value) { 999*5ffd83dbSDimitry Andric if (!IsValid()) 1000*5ffd83dbSDimitry Andric return false; 1001*5ffd83dbSDimitry Andric bool success = false; 1002*5ffd83dbSDimitry Andric 1003*5ffd83dbSDimitry Andric switch (regloc.type) { 1004*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: { 1005*5ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 1006*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 1007*5ffd83dbSDimitry Andric 1008*5ffd83dbSDimitry Andric if (!other_reg_info) 1009*5ffd83dbSDimitry Andric return false; 1010*5ffd83dbSDimitry Andric 1011*5ffd83dbSDimitry Andric success = 1012*5ffd83dbSDimitry Andric m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value); 1013*5ffd83dbSDimitry Andric } break; 1014*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInRegister: { 1015*5ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 1016*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 1017*5ffd83dbSDimitry Andric 1018*5ffd83dbSDimitry Andric if (!other_reg_info) 1019*5ffd83dbSDimitry Andric return false; 1020*5ffd83dbSDimitry Andric 1021*5ffd83dbSDimitry Andric if (IsFrameZero()) { 1022*5ffd83dbSDimitry Andric success = 1023*5ffd83dbSDimitry Andric m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value); 1024*5ffd83dbSDimitry Andric } else { 1025*5ffd83dbSDimitry Andric success = GetNextFrame()->ReadRegister(other_reg_info, value); 1026*5ffd83dbSDimitry Andric } 1027*5ffd83dbSDimitry Andric } break; 1028*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterValueInferred: 1029*5ffd83dbSDimitry Andric success = 1030*5ffd83dbSDimitry Andric value.SetUInt(regloc.location.inferred_value, reg_info->byte_size); 1031*5ffd83dbSDimitry Andric break; 1032*5ffd83dbSDimitry Andric 1033*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterNotSaved: 1034*5ffd83dbSDimitry Andric break; 1035*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: 1036*5ffd83dbSDimitry Andric llvm_unreachable("FIXME debugger inferior function call unwind"); 1037*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { 1038*5ffd83dbSDimitry Andric Status error(ReadRegisterValueFromMemory( 1039*5ffd83dbSDimitry Andric reg_info, regloc.location.target_memory_location, reg_info->byte_size, 1040*5ffd83dbSDimitry Andric value)); 1041*5ffd83dbSDimitry Andric success = error.Success(); 1042*5ffd83dbSDimitry Andric } break; 1043*5ffd83dbSDimitry Andric default: 1044*5ffd83dbSDimitry Andric llvm_unreachable("Unknown RegisterLocation type."); 1045*5ffd83dbSDimitry Andric } 1046*5ffd83dbSDimitry Andric return success; 1047*5ffd83dbSDimitry Andric } 1048*5ffd83dbSDimitry Andric 1049*5ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteRegisterValueToRegisterLocation( 1050*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc, 1051*5ffd83dbSDimitry Andric const RegisterInfo *reg_info, const RegisterValue &value) { 1052*5ffd83dbSDimitry Andric if (!IsValid()) 1053*5ffd83dbSDimitry Andric return false; 1054*5ffd83dbSDimitry Andric 1055*5ffd83dbSDimitry Andric bool success = false; 1056*5ffd83dbSDimitry Andric 1057*5ffd83dbSDimitry Andric switch (regloc.type) { 1058*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: { 1059*5ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 1060*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 1061*5ffd83dbSDimitry Andric success = 1062*5ffd83dbSDimitry Andric m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value); 1063*5ffd83dbSDimitry Andric } break; 1064*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterInRegister: { 1065*5ffd83dbSDimitry Andric const RegisterInfo *other_reg_info = 1066*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regloc.location.register_number); 1067*5ffd83dbSDimitry Andric if (IsFrameZero()) { 1068*5ffd83dbSDimitry Andric success = 1069*5ffd83dbSDimitry Andric m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value); 1070*5ffd83dbSDimitry Andric } else { 1071*5ffd83dbSDimitry Andric success = GetNextFrame()->WriteRegister(other_reg_info, value); 1072*5ffd83dbSDimitry Andric } 1073*5ffd83dbSDimitry Andric } break; 1074*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterValueInferred: 1075*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterNotSaved: 1076*5ffd83dbSDimitry Andric break; 1077*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: 1078*5ffd83dbSDimitry Andric llvm_unreachable("FIXME debugger inferior function call unwind"); 1079*5ffd83dbSDimitry Andric case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { 1080*5ffd83dbSDimitry Andric Status error(WriteRegisterValueToMemory( 1081*5ffd83dbSDimitry Andric reg_info, regloc.location.target_memory_location, reg_info->byte_size, 1082*5ffd83dbSDimitry Andric value)); 1083*5ffd83dbSDimitry Andric success = error.Success(); 1084*5ffd83dbSDimitry Andric } break; 1085*5ffd83dbSDimitry Andric default: 1086*5ffd83dbSDimitry Andric llvm_unreachable("Unknown RegisterLocation type."); 1087*5ffd83dbSDimitry Andric } 1088*5ffd83dbSDimitry Andric return success; 1089*5ffd83dbSDimitry Andric } 1090*5ffd83dbSDimitry Andric 1091*5ffd83dbSDimitry Andric bool RegisterContextUnwind::IsValid() const { 1092*5ffd83dbSDimitry Andric return m_frame_type != eNotAValidFrame; 1093*5ffd83dbSDimitry Andric } 1094*5ffd83dbSDimitry Andric 1095*5ffd83dbSDimitry Andric // After the final stack frame in a stack walk we'll get one invalid 1096*5ffd83dbSDimitry Andric // (eNotAValidFrame) stack frame -- one past the end of the stack walk. But 1097*5ffd83dbSDimitry Andric // higher-level code will need to tell the difference between "the unwind plan 1098*5ffd83dbSDimitry Andric // below this frame failed" versus "we successfully completed the stack walk" 1099*5ffd83dbSDimitry Andric // so this method helps to disambiguate that. 1100*5ffd83dbSDimitry Andric 1101*5ffd83dbSDimitry Andric bool RegisterContextUnwind::IsTrapHandlerFrame() const { 1102*5ffd83dbSDimitry Andric return m_frame_type == eTrapHandlerFrame; 1103*5ffd83dbSDimitry Andric } 1104*5ffd83dbSDimitry Andric 1105*5ffd83dbSDimitry Andric // A skip frame is a bogus frame on the stack -- but one where we're likely to 1106*5ffd83dbSDimitry Andric // find a real frame farther 1107*5ffd83dbSDimitry Andric // up the stack if we keep looking. It's always the second frame in an unwind 1108*5ffd83dbSDimitry Andric // (i.e. the first frame after frame zero) where unwinding can be the 1109*5ffd83dbSDimitry Andric // trickiest. Ideally we'll mark up this frame in some way so the user knows 1110*5ffd83dbSDimitry Andric // we're displaying bad data and we may have skipped one frame of their real 1111*5ffd83dbSDimitry Andric // program in the process of getting back on track. 1112*5ffd83dbSDimitry Andric 1113*5ffd83dbSDimitry Andric bool RegisterContextUnwind::IsSkipFrame() const { 1114*5ffd83dbSDimitry Andric return m_frame_type == eSkipFrame; 1115*5ffd83dbSDimitry Andric } 1116*5ffd83dbSDimitry Andric 1117*5ffd83dbSDimitry Andric bool RegisterContextUnwind::IsTrapHandlerSymbol( 1118*5ffd83dbSDimitry Andric lldb_private::Process *process, 1119*5ffd83dbSDimitry Andric const lldb_private::SymbolContext &m_sym_ctx) const { 1120*5ffd83dbSDimitry Andric PlatformSP platform_sp(process->GetTarget().GetPlatform()); 1121*5ffd83dbSDimitry Andric if (platform_sp) { 1122*5ffd83dbSDimitry Andric const std::vector<ConstString> trap_handler_names( 1123*5ffd83dbSDimitry Andric platform_sp->GetTrapHandlerSymbolNames()); 1124*5ffd83dbSDimitry Andric for (ConstString name : trap_handler_names) { 1125*5ffd83dbSDimitry Andric if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || 1126*5ffd83dbSDimitry Andric (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) { 1127*5ffd83dbSDimitry Andric return true; 1128*5ffd83dbSDimitry Andric } 1129*5ffd83dbSDimitry Andric } 1130*5ffd83dbSDimitry Andric } 1131*5ffd83dbSDimitry Andric const std::vector<ConstString> user_specified_trap_handler_names( 1132*5ffd83dbSDimitry Andric m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames()); 1133*5ffd83dbSDimitry Andric for (ConstString name : user_specified_trap_handler_names) { 1134*5ffd83dbSDimitry Andric if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || 1135*5ffd83dbSDimitry Andric (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) { 1136*5ffd83dbSDimitry Andric return true; 1137*5ffd83dbSDimitry Andric } 1138*5ffd83dbSDimitry Andric } 1139*5ffd83dbSDimitry Andric 1140*5ffd83dbSDimitry Andric return false; 1141*5ffd83dbSDimitry Andric } 1142*5ffd83dbSDimitry Andric 1143*5ffd83dbSDimitry Andric // Answer the question: Where did THIS frame save the CALLER frame ("previous" 1144*5ffd83dbSDimitry Andric // frame)'s register value? 1145*5ffd83dbSDimitry Andric 1146*5ffd83dbSDimitry Andric enum UnwindLLDB::RegisterSearchResult 1147*5ffd83dbSDimitry Andric RegisterContextUnwind::SavedLocationForRegister( 1148*5ffd83dbSDimitry Andric uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { 1149*5ffd83dbSDimitry Andric RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum); 1150*5ffd83dbSDimitry Andric 1151*5ffd83dbSDimitry Andric // Have we already found this register location? 1152*5ffd83dbSDimitry Andric if (!m_registers.empty()) { 1153*5ffd83dbSDimitry Andric std::map<uint32_t, 1154*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation>::const_iterator 1155*5ffd83dbSDimitry Andric iterator; 1156*5ffd83dbSDimitry Andric iterator = m_registers.find(regnum.GetAsKind(eRegisterKindLLDB)); 1157*5ffd83dbSDimitry Andric if (iterator != m_registers.end()) { 1158*5ffd83dbSDimitry Andric regloc = iterator->second; 1159*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's saved %s (%d)'s location, cached", 1160*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1161*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1162*5ffd83dbSDimitry Andric } 1163*5ffd83dbSDimitry Andric } 1164*5ffd83dbSDimitry Andric 1165*5ffd83dbSDimitry Andric // Look through the available UnwindPlans for the register location. 1166*5ffd83dbSDimitry Andric 1167*5ffd83dbSDimitry Andric UnwindPlan::Row::RegisterLocation unwindplan_regloc; 1168*5ffd83dbSDimitry Andric bool have_unwindplan_regloc = false; 1169*5ffd83dbSDimitry Andric RegisterKind unwindplan_registerkind = kNumRegisterKinds; 1170*5ffd83dbSDimitry Andric 1171*5ffd83dbSDimitry Andric if (m_fast_unwind_plan_sp) { 1172*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 1173*5ffd83dbSDimitry Andric m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 1174*5ffd83dbSDimitry Andric unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind(); 1175*5ffd83dbSDimitry Andric if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) { 1176*5ffd83dbSDimitry Andric UnwindLogMsg("could not convert lldb regnum %s (%d) into %d RegisterKind " 1177*5ffd83dbSDimitry Andric "reg numbering scheme", 1178*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 1179*5ffd83dbSDimitry Andric (int)unwindplan_registerkind); 1180*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1181*5ffd83dbSDimitry Andric } 1182*5ffd83dbSDimitry Andric if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), 1183*5ffd83dbSDimitry Andric unwindplan_regloc)) { 1184*5ffd83dbSDimitry Andric UnwindLogMsg( 1185*5ffd83dbSDimitry Andric "supplying caller's saved %s (%d)'s location using FastUnwindPlan", 1186*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1187*5ffd83dbSDimitry Andric have_unwindplan_regloc = true; 1188*5ffd83dbSDimitry Andric } 1189*5ffd83dbSDimitry Andric } 1190*5ffd83dbSDimitry Andric 1191*5ffd83dbSDimitry Andric if (!have_unwindplan_regloc) { 1192*5ffd83dbSDimitry Andric // m_full_unwind_plan_sp being NULL means that we haven't tried to find a 1193*5ffd83dbSDimitry Andric // full UnwindPlan yet 1194*5ffd83dbSDimitry Andric if (!m_full_unwind_plan_sp) 1195*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); 1196*5ffd83dbSDimitry Andric 1197*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp) { 1198*5ffd83dbSDimitry Andric RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, 1199*5ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_PC); 1200*5ffd83dbSDimitry Andric 1201*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 1202*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 1203*5ffd83dbSDimitry Andric unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); 1204*5ffd83dbSDimitry Andric 1205*5ffd83dbSDimitry Andric RegisterNumber return_address_reg; 1206*5ffd83dbSDimitry Andric 1207*5ffd83dbSDimitry Andric // If we're fetching the saved pc and this UnwindPlan defines a 1208*5ffd83dbSDimitry Andric // ReturnAddress register (e.g. lr on arm), look for the return address 1209*5ffd83dbSDimitry Andric // register number in the UnwindPlan's row. 1210*5ffd83dbSDimitry Andric if (pc_regnum.IsValid() && pc_regnum == regnum && 1211*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetReturnAddressRegister() != 1212*5ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) { 1213*5ffd83dbSDimitry Andric // If this is a trap handler frame, we should have access to 1214*5ffd83dbSDimitry Andric // the complete register context when the interrupt/async 1215*5ffd83dbSDimitry Andric // signal was received, we should fetch the actual saved $pc 1216*5ffd83dbSDimitry Andric // value instead of the Return Address register. 1217*5ffd83dbSDimitry Andric // If $pc is not available, fall back to the RA reg. 1218*5ffd83dbSDimitry Andric UnwindPlan::Row::RegisterLocation scratch; 1219*5ffd83dbSDimitry Andric if (m_frame_type == eTrapHandlerFrame && 1220*5ffd83dbSDimitry Andric active_row->GetRegisterInfo 1221*5ffd83dbSDimitry Andric (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) { 1222*5ffd83dbSDimitry Andric UnwindLogMsg("Providing pc register instead of rewriting to " 1223*5ffd83dbSDimitry Andric "RA reg because this is a trap handler and there is " 1224*5ffd83dbSDimitry Andric "a location for the saved pc register value."); 1225*5ffd83dbSDimitry Andric } else { 1226*5ffd83dbSDimitry Andric return_address_reg.init( 1227*5ffd83dbSDimitry Andric m_thread, m_full_unwind_plan_sp->GetRegisterKind(), 1228*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetReturnAddressRegister()); 1229*5ffd83dbSDimitry Andric regnum = return_address_reg; 1230*5ffd83dbSDimitry Andric UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a " 1231*5ffd83dbSDimitry Andric "RA reg; getting %s (%d) instead", 1232*5ffd83dbSDimitry Andric return_address_reg.GetName(), 1233*5ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB)); 1234*5ffd83dbSDimitry Andric } 1235*5ffd83dbSDimitry Andric } else { 1236*5ffd83dbSDimitry Andric if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) { 1237*5ffd83dbSDimitry Andric if (unwindplan_registerkind == eRegisterKindGeneric) { 1238*5ffd83dbSDimitry Andric UnwindLogMsg("could not convert lldb regnum %s (%d) into " 1239*5ffd83dbSDimitry Andric "eRegisterKindGeneric reg numbering scheme", 1240*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1241*5ffd83dbSDimitry Andric } else { 1242*5ffd83dbSDimitry Andric UnwindLogMsg("could not convert lldb regnum %s (%d) into %d " 1243*5ffd83dbSDimitry Andric "RegisterKind reg numbering scheme", 1244*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 1245*5ffd83dbSDimitry Andric (int)unwindplan_registerkind); 1246*5ffd83dbSDimitry Andric } 1247*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1248*5ffd83dbSDimitry Andric } 1249*5ffd83dbSDimitry Andric } 1250*5ffd83dbSDimitry Andric 1251*5ffd83dbSDimitry Andric if (regnum.IsValid() && 1252*5ffd83dbSDimitry Andric active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), 1253*5ffd83dbSDimitry Andric unwindplan_regloc)) { 1254*5ffd83dbSDimitry Andric have_unwindplan_regloc = true; 1255*5ffd83dbSDimitry Andric UnwindLogMsg( 1256*5ffd83dbSDimitry Andric "supplying caller's saved %s (%d)'s location using %s UnwindPlan", 1257*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 1258*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 1259*5ffd83dbSDimitry Andric } 1260*5ffd83dbSDimitry Andric 1261*5ffd83dbSDimitry Andric // This is frame 0 and we're retrieving the PC and it's saved in a Return 1262*5ffd83dbSDimitry Andric // Address register and it hasn't been saved anywhere yet -- that is, 1263*5ffd83dbSDimitry Andric // it's still live in the actual register. Handle this specially. 1264*5ffd83dbSDimitry Andric 1265*5ffd83dbSDimitry Andric if (!have_unwindplan_regloc && return_address_reg.IsValid() && 1266*5ffd83dbSDimitry Andric IsFrameZero()) { 1267*5ffd83dbSDimitry Andric if (return_address_reg.GetAsKind(eRegisterKindLLDB) != 1268*5ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) { 1269*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation new_regloc; 1270*5ffd83dbSDimitry Andric new_regloc.type = 1271*5ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; 1272*5ffd83dbSDimitry Andric new_regloc.location.register_number = 1273*5ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB); 1274*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; 1275*5ffd83dbSDimitry Andric regloc = new_regloc; 1276*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the live " 1277*5ffd83dbSDimitry Andric "RegisterContext at frame 0, saved in %d", 1278*5ffd83dbSDimitry Andric return_address_reg.GetName(), 1279*5ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB), 1280*5ffd83dbSDimitry Andric return_address_reg.GetAsKind(eRegisterKindLLDB)); 1281*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1282*5ffd83dbSDimitry Andric } 1283*5ffd83dbSDimitry Andric } 1284*5ffd83dbSDimitry Andric 1285*5ffd83dbSDimitry Andric // If this architecture stores the return address in a register (it 1286*5ffd83dbSDimitry Andric // defines a Return Address register) and we're on a non-zero stack frame 1287*5ffd83dbSDimitry Andric // and the Full UnwindPlan says that the pc is stored in the 1288*5ffd83dbSDimitry Andric // RA registers (e.g. lr on arm), then we know that the full unwindplan is 1289*5ffd83dbSDimitry Andric // not trustworthy -- this 1290*5ffd83dbSDimitry Andric // is an impossible situation and the instruction emulation code has 1291*5ffd83dbSDimitry Andric // likely been misled. If this stack frame meets those criteria, we need 1292*5ffd83dbSDimitry Andric // to throw away the Full UnwindPlan that the instruction emulation came 1293*5ffd83dbSDimitry Andric // up with and fall back to the architecture's Default UnwindPlan so the 1294*5ffd83dbSDimitry Andric // stack walk can get past this point. 1295*5ffd83dbSDimitry Andric 1296*5ffd83dbSDimitry Andric // Special note: If the Full UnwindPlan was generated from the compiler, 1297*5ffd83dbSDimitry Andric // don't second-guess it when we're at a call site location. 1298*5ffd83dbSDimitry Andric 1299*5ffd83dbSDimitry Andric // arch_default_ra_regnum is the return address register # in the Full 1300*5ffd83dbSDimitry Andric // UnwindPlan register numbering 1301*5ffd83dbSDimitry Andric RegisterNumber arch_default_ra_regnum(m_thread, eRegisterKindGeneric, 1302*5ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_RA); 1303*5ffd83dbSDimitry Andric 1304*5ffd83dbSDimitry Andric if (arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) != 1305*5ffd83dbSDimitry Andric LLDB_INVALID_REGNUM && 1306*5ffd83dbSDimitry Andric pc_regnum == regnum && unwindplan_regloc.IsInOtherRegister() && 1307*5ffd83dbSDimitry Andric unwindplan_regloc.GetRegisterNumber() == 1308*5ffd83dbSDimitry Andric arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) && 1309*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes && 1310*5ffd83dbSDimitry Andric !m_all_registers_available) { 1311*5ffd83dbSDimitry Andric UnwindLogMsg("%s UnwindPlan tried to restore the pc from the link " 1312*5ffd83dbSDimitry Andric "register but this is a non-zero frame", 1313*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 1314*5ffd83dbSDimitry Andric 1315*5ffd83dbSDimitry Andric // Throw away the full unwindplan; install the arch default unwindplan 1316*5ffd83dbSDimitry Andric if (ForceSwitchToFallbackUnwindPlan()) { 1317*5ffd83dbSDimitry Andric // Update for the possibly new unwind plan 1318*5ffd83dbSDimitry Andric unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); 1319*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 1320*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 1321*5ffd83dbSDimitry Andric 1322*5ffd83dbSDimitry Andric // Sanity check: Verify that we can fetch a pc value and CFA value 1323*5ffd83dbSDimitry Andric // with this unwind plan 1324*5ffd83dbSDimitry Andric 1325*5ffd83dbSDimitry Andric RegisterNumber arch_default_pc_reg(m_thread, eRegisterKindGeneric, 1326*5ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_PC); 1327*5ffd83dbSDimitry Andric bool can_fetch_pc_value = false; 1328*5ffd83dbSDimitry Andric bool can_fetch_cfa = false; 1329*5ffd83dbSDimitry Andric addr_t cfa_value; 1330*5ffd83dbSDimitry Andric if (active_row) { 1331*5ffd83dbSDimitry Andric if (arch_default_pc_reg.GetAsKind(unwindplan_registerkind) != 1332*5ffd83dbSDimitry Andric LLDB_INVALID_REGNUM && 1333*5ffd83dbSDimitry Andric active_row->GetRegisterInfo( 1334*5ffd83dbSDimitry Andric arch_default_pc_reg.GetAsKind(unwindplan_registerkind), 1335*5ffd83dbSDimitry Andric unwindplan_regloc)) { 1336*5ffd83dbSDimitry Andric can_fetch_pc_value = true; 1337*5ffd83dbSDimitry Andric } 1338*5ffd83dbSDimitry Andric if (ReadFrameAddress(unwindplan_registerkind, 1339*5ffd83dbSDimitry Andric active_row->GetCFAValue(), cfa_value)) { 1340*5ffd83dbSDimitry Andric can_fetch_cfa = true; 1341*5ffd83dbSDimitry Andric } 1342*5ffd83dbSDimitry Andric } 1343*5ffd83dbSDimitry Andric 1344*5ffd83dbSDimitry Andric have_unwindplan_regloc = can_fetch_pc_value && can_fetch_cfa; 1345*5ffd83dbSDimitry Andric } else { 1346*5ffd83dbSDimitry Andric // We were unable to fall back to another unwind plan 1347*5ffd83dbSDimitry Andric have_unwindplan_regloc = false; 1348*5ffd83dbSDimitry Andric } 1349*5ffd83dbSDimitry Andric } 1350*5ffd83dbSDimitry Andric } 1351*5ffd83dbSDimitry Andric } 1352*5ffd83dbSDimitry Andric 1353*5ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 1354*5ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 1355*5ffd83dbSDimitry Andric if (!have_unwindplan_regloc) { 1356*5ffd83dbSDimitry Andric // If the UnwindPlan failed to give us an unwind location for this 1357*5ffd83dbSDimitry Andric // register, we may be able to fall back to some ABI-defined default. For 1358*5ffd83dbSDimitry Andric // example, some ABIs allow to determine the caller's SP via the CFA. Also, 1359*5ffd83dbSDimitry Andric // the ABI may set volatile registers to the undefined state. 1360*5ffd83dbSDimitry Andric ABI *abi = process ? process->GetABI().get() : nullptr; 1361*5ffd83dbSDimitry Andric if (abi) { 1362*5ffd83dbSDimitry Andric const RegisterInfo *reg_info = 1363*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB)); 1364*5ffd83dbSDimitry Andric if (reg_info && 1365*5ffd83dbSDimitry Andric abi->GetFallbackRegisterLocation(reg_info, unwindplan_regloc)) { 1366*5ffd83dbSDimitry Andric UnwindLogMsg( 1367*5ffd83dbSDimitry Andric "supplying caller's saved %s (%d)'s location using ABI default", 1368*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1369*5ffd83dbSDimitry Andric have_unwindplan_regloc = true; 1370*5ffd83dbSDimitry Andric } 1371*5ffd83dbSDimitry Andric } 1372*5ffd83dbSDimitry Andric } 1373*5ffd83dbSDimitry Andric 1374*5ffd83dbSDimitry Andric if (!have_unwindplan_regloc) { 1375*5ffd83dbSDimitry Andric if (IsFrameZero()) { 1376*5ffd83dbSDimitry Andric // This is frame 0 - we should return the actual live register context 1377*5ffd83dbSDimitry Andric // value 1378*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation new_regloc; 1379*5ffd83dbSDimitry Andric new_regloc.type = 1380*5ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; 1381*5ffd83dbSDimitry Andric new_regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); 1382*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; 1383*5ffd83dbSDimitry Andric regloc = new_regloc; 1384*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the live " 1385*5ffd83dbSDimitry Andric "RegisterContext at frame 0", 1386*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1387*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1388*5ffd83dbSDimitry Andric } else { 1389*5ffd83dbSDimitry Andric std::string unwindplan_name(""); 1390*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp) { 1391*5ffd83dbSDimitry Andric unwindplan_name += "via '"; 1392*5ffd83dbSDimitry Andric unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString(); 1393*5ffd83dbSDimitry Andric unwindplan_name += "'"; 1394*5ffd83dbSDimitry Andric } 1395*5ffd83dbSDimitry Andric UnwindLogMsg("no save location for %s (%d) %s", regnum.GetName(), 1396*5ffd83dbSDimitry Andric regnum.GetAsKind(eRegisterKindLLDB), 1397*5ffd83dbSDimitry Andric unwindplan_name.c_str()); 1398*5ffd83dbSDimitry Andric } 1399*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1400*5ffd83dbSDimitry Andric } 1401*5ffd83dbSDimitry Andric 1402*5ffd83dbSDimitry Andric // unwindplan_regloc has valid contents about where to retrieve the register 1403*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsUnspecified()) { 1404*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation new_regloc; 1405*5ffd83dbSDimitry Andric new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved; 1406*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; 1407*5ffd83dbSDimitry Andric UnwindLogMsg("save location for %s (%d) is unspecified, continue searching", 1408*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1409*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1410*5ffd83dbSDimitry Andric } 1411*5ffd83dbSDimitry Andric 1412*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsUndefined()) { 1413*5ffd83dbSDimitry Andric UnwindLogMsg( 1414*5ffd83dbSDimitry Andric "did not supply reg location for %s (%d) because it is volatile", 1415*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1416*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; 1417*5ffd83dbSDimitry Andric } 1418*5ffd83dbSDimitry Andric 1419*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsSame()) { 1420*5ffd83dbSDimitry Andric if (!IsFrameZero() && 1421*5ffd83dbSDimitry Andric (regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC || 1422*5ffd83dbSDimitry Andric regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) { 1423*5ffd83dbSDimitry Andric UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or " 1424*5ffd83dbSDimitry Andric "return address reg on a non-zero frame -- treat as if we " 1425*5ffd83dbSDimitry Andric "have no information", 1426*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1427*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1428*5ffd83dbSDimitry Andric } else { 1429*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; 1430*5ffd83dbSDimitry Andric regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); 1431*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1432*5ffd83dbSDimitry Andric UnwindLogMsg( 1433*5ffd83dbSDimitry Andric "supplying caller's register %s (%d), saved in register %s (%d)", 1434*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 1435*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1436*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1437*5ffd83dbSDimitry Andric } 1438*5ffd83dbSDimitry Andric } 1439*5ffd83dbSDimitry Andric 1440*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsCFAPlusOffset()) { 1441*5ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 1442*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; 1443*5ffd83dbSDimitry Andric regloc.location.inferred_value = m_cfa + offset; 1444*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1445*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d), value is CFA plus " 1446*5ffd83dbSDimitry Andric "offset %d [value is 0x%" PRIx64 "]", 1447*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 1448*5ffd83dbSDimitry Andric regloc.location.inferred_value); 1449*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1450*5ffd83dbSDimitry Andric } 1451*5ffd83dbSDimitry Andric 1452*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsAtCFAPlusOffset()) { 1453*5ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 1454*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; 1455*5ffd83dbSDimitry Andric regloc.location.target_memory_location = m_cfa + offset; 1456*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1457*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at " 1458*5ffd83dbSDimitry Andric "CFA plus offset %d [saved at 0x%" PRIx64 "]", 1459*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 1460*5ffd83dbSDimitry Andric regloc.location.target_memory_location); 1461*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1462*5ffd83dbSDimitry Andric } 1463*5ffd83dbSDimitry Andric 1464*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsAFAPlusOffset()) { 1465*5ffd83dbSDimitry Andric if (m_afa == LLDB_INVALID_ADDRESS) 1466*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1467*5ffd83dbSDimitry Andric 1468*5ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 1469*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; 1470*5ffd83dbSDimitry Andric regloc.location.inferred_value = m_afa + offset; 1471*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1472*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus " 1473*5ffd83dbSDimitry Andric "offset %d [value is 0x%" PRIx64 "]", 1474*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 1475*5ffd83dbSDimitry Andric regloc.location.inferred_value); 1476*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1477*5ffd83dbSDimitry Andric } 1478*5ffd83dbSDimitry Andric 1479*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsAtAFAPlusOffset()) { 1480*5ffd83dbSDimitry Andric if (m_afa == LLDB_INVALID_ADDRESS) 1481*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1482*5ffd83dbSDimitry Andric 1483*5ffd83dbSDimitry Andric int offset = unwindplan_regloc.GetOffset(); 1484*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; 1485*5ffd83dbSDimitry Andric regloc.location.target_memory_location = m_afa + offset; 1486*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1487*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at " 1488*5ffd83dbSDimitry Andric "AFA plus offset %d [saved at 0x%" PRIx64 "]", 1489*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, 1490*5ffd83dbSDimitry Andric regloc.location.target_memory_location); 1491*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1492*5ffd83dbSDimitry Andric } 1493*5ffd83dbSDimitry Andric 1494*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsInOtherRegister()) { 1495*5ffd83dbSDimitry Andric uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber(); 1496*5ffd83dbSDimitry Andric RegisterNumber row_regnum(m_thread, unwindplan_registerkind, 1497*5ffd83dbSDimitry Andric unwindplan_regnum); 1498*5ffd83dbSDimitry Andric if (row_regnum.GetAsKind(eRegisterKindLLDB) == LLDB_INVALID_REGNUM) { 1499*5ffd83dbSDimitry Andric UnwindLogMsg("could not supply caller's %s (%d) location - was saved in " 1500*5ffd83dbSDimitry Andric "another reg but couldn't convert that regnum", 1501*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1502*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1503*5ffd83dbSDimitry Andric } 1504*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; 1505*5ffd83dbSDimitry Andric regloc.location.register_number = row_regnum.GetAsKind(eRegisterKindLLDB); 1506*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1507*5ffd83dbSDimitry Andric UnwindLogMsg( 1508*5ffd83dbSDimitry Andric "supplying caller's register %s (%d), saved in register %s (%d)", 1509*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), 1510*5ffd83dbSDimitry Andric row_regnum.GetName(), row_regnum.GetAsKind(eRegisterKindLLDB)); 1511*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1512*5ffd83dbSDimitry Andric } 1513*5ffd83dbSDimitry Andric 1514*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsDWARFExpression() || 1515*5ffd83dbSDimitry Andric unwindplan_regloc.IsAtDWARFExpression()) { 1516*5ffd83dbSDimitry Andric DataExtractor dwarfdata(unwindplan_regloc.GetDWARFExpressionBytes(), 1517*5ffd83dbSDimitry Andric unwindplan_regloc.GetDWARFExpressionLength(), 1518*5ffd83dbSDimitry Andric process->GetByteOrder(), 1519*5ffd83dbSDimitry Andric process->GetAddressByteSize()); 1520*5ffd83dbSDimitry Andric ModuleSP opcode_ctx; 1521*5ffd83dbSDimitry Andric DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); 1522*5ffd83dbSDimitry Andric dwarfexpr.SetRegisterKind(unwindplan_registerkind); 1523*5ffd83dbSDimitry Andric Value cfa_val = Scalar(m_cfa); 1524*5ffd83dbSDimitry Andric cfa_val.SetValueType(Value::eValueTypeLoadAddress); 1525*5ffd83dbSDimitry Andric Value result; 1526*5ffd83dbSDimitry Andric Status error; 1527*5ffd83dbSDimitry Andric if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result, 1528*5ffd83dbSDimitry Andric &error)) { 1529*5ffd83dbSDimitry Andric addr_t val; 1530*5ffd83dbSDimitry Andric val = result.GetScalar().ULongLong(); 1531*5ffd83dbSDimitry Andric if (unwindplan_regloc.IsDWARFExpression()) { 1532*5ffd83dbSDimitry Andric regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; 1533*5ffd83dbSDimitry Andric regloc.location.inferred_value = val; 1534*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1535*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression " 1536*5ffd83dbSDimitry Andric "(IsDWARFExpression)", 1537*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1538*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1539*5ffd83dbSDimitry Andric } else { 1540*5ffd83dbSDimitry Andric regloc.type = 1541*5ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; 1542*5ffd83dbSDimitry Andric regloc.location.target_memory_location = val; 1543*5ffd83dbSDimitry Andric m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; 1544*5ffd83dbSDimitry Andric UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression " 1545*5ffd83dbSDimitry Andric "(IsAtDWARFExpression)", 1546*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1547*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterFound; 1548*5ffd83dbSDimitry Andric } 1549*5ffd83dbSDimitry Andric } 1550*5ffd83dbSDimitry Andric UnwindLogMsg("tried to use IsDWARFExpression or IsAtDWARFExpression for %s " 1551*5ffd83dbSDimitry Andric "(%d) but failed", 1552*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1553*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1554*5ffd83dbSDimitry Andric } 1555*5ffd83dbSDimitry Andric 1556*5ffd83dbSDimitry Andric UnwindLogMsg("no save location for %s (%d) in this stack frame", 1557*5ffd83dbSDimitry Andric regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); 1558*5ffd83dbSDimitry Andric 1559*5ffd83dbSDimitry Andric // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are 1560*5ffd83dbSDimitry Andric // unsupported. 1561*5ffd83dbSDimitry Andric 1562*5ffd83dbSDimitry Andric return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; 1563*5ffd83dbSDimitry Andric } 1564*5ffd83dbSDimitry Andric 1565*5ffd83dbSDimitry Andric // TryFallbackUnwindPlan() -- this method is a little tricky. 1566*5ffd83dbSDimitry Andric // 1567*5ffd83dbSDimitry Andric // When this is called, the frame above -- the caller frame, the "previous" 1568*5ffd83dbSDimitry Andric // frame -- is invalid or bad. 1569*5ffd83dbSDimitry Andric // 1570*5ffd83dbSDimitry Andric // Instead of stopping the stack walk here, we'll try a different UnwindPlan 1571*5ffd83dbSDimitry Andric // and see if we can get a valid frame above us. 1572*5ffd83dbSDimitry Andric // 1573*5ffd83dbSDimitry Andric // This most often happens when an unwind plan based on assembly instruction 1574*5ffd83dbSDimitry Andric // inspection is not correct -- mostly with hand-written assembly functions or 1575*5ffd83dbSDimitry Andric // functions where the stack frame is set up "out of band", e.g. the kernel 1576*5ffd83dbSDimitry Andric // saved the register context and then called an asynchronous trap handler like 1577*5ffd83dbSDimitry Andric // _sigtramp. 1578*5ffd83dbSDimitry Andric // 1579*5ffd83dbSDimitry Andric // Often in these cases, if we just do a dumb stack walk we'll get past this 1580*5ffd83dbSDimitry Andric // tricky frame and our usual techniques can continue to be used. 1581*5ffd83dbSDimitry Andric 1582*5ffd83dbSDimitry Andric bool RegisterContextUnwind::TryFallbackUnwindPlan() { 1583*5ffd83dbSDimitry Andric if (m_fallback_unwind_plan_sp.get() == nullptr) 1584*5ffd83dbSDimitry Andric return false; 1585*5ffd83dbSDimitry Andric 1586*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == nullptr) 1587*5ffd83dbSDimitry Andric return false; 1588*5ffd83dbSDimitry Andric 1589*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || 1590*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName() == 1591*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetSourceName()) { 1592*5ffd83dbSDimitry Andric return false; 1593*5ffd83dbSDimitry Andric } 1594*5ffd83dbSDimitry Andric 1595*5ffd83dbSDimitry Andric // If a compiler generated unwind plan failed, trying the arch default 1596*5ffd83dbSDimitry Andric // unwindplan isn't going to do any better. 1597*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) 1598*5ffd83dbSDimitry Andric return false; 1599*5ffd83dbSDimitry Andric 1600*5ffd83dbSDimitry Andric // Get the caller's pc value and our own CFA value. Swap in the fallback 1601*5ffd83dbSDimitry Andric // unwind plan, re-fetch the caller's pc value and CFA value. If they're the 1602*5ffd83dbSDimitry Andric // same, then the fallback unwind plan provides no benefit. 1603*5ffd83dbSDimitry Andric 1604*5ffd83dbSDimitry Andric RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, 1605*5ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_PC); 1606*5ffd83dbSDimitry Andric 1607*5ffd83dbSDimitry Andric addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS; 1608*5ffd83dbSDimitry Andric addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS; 1609*5ffd83dbSDimitry Andric UnwindLLDB::RegisterLocation regloc; 1610*5ffd83dbSDimitry Andric if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB), 1611*5ffd83dbSDimitry Andric regloc) == 1612*5ffd83dbSDimitry Andric UnwindLLDB::RegisterSearchResult::eRegisterFound) { 1613*5ffd83dbSDimitry Andric const RegisterInfo *reg_info = 1614*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB)); 1615*5ffd83dbSDimitry Andric if (reg_info) { 1616*5ffd83dbSDimitry Andric RegisterValue reg_value; 1617*5ffd83dbSDimitry Andric if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { 1618*5ffd83dbSDimitry Andric old_caller_pc_value = reg_value.GetAsUInt64(); 1619*5ffd83dbSDimitry Andric } 1620*5ffd83dbSDimitry Andric } 1621*5ffd83dbSDimitry Andric } 1622*5ffd83dbSDimitry Andric 1623*5ffd83dbSDimitry Andric // This is a tricky wrinkle! If SavedLocationForRegister() detects a really 1624*5ffd83dbSDimitry Andric // impossible register location for the full unwind plan, it may call 1625*5ffd83dbSDimitry Andric // ForceSwitchToFallbackUnwindPlan() which in turn replaces the full 1626*5ffd83dbSDimitry Andric // unwindplan with the fallback... in short, we're done, we're using the 1627*5ffd83dbSDimitry Andric // fallback UnwindPlan. We checked if m_fallback_unwind_plan_sp was nullptr 1628*5ffd83dbSDimitry Andric // at the top -- the only way it became nullptr since then is via 1629*5ffd83dbSDimitry Andric // SavedLocationForRegister(). 1630*5ffd83dbSDimitry Andric if (m_fallback_unwind_plan_sp.get() == nullptr) 1631*5ffd83dbSDimitry Andric return true; 1632*5ffd83dbSDimitry Andric 1633*5ffd83dbSDimitry Andric // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide 1634*5ffd83dbSDimitry Andric // this isn't working, we need to restore. We'll also need to save & restore 1635*5ffd83dbSDimitry Andric // the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'. 1636*5ffd83dbSDimitry Andric UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; 1637*5ffd83dbSDimitry Andric addr_t old_cfa = m_cfa; 1638*5ffd83dbSDimitry Andric addr_t old_afa = m_afa; 1639*5ffd83dbSDimitry Andric 1640*5ffd83dbSDimitry Andric m_registers.clear(); 1641*5ffd83dbSDimitry Andric 1642*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; 1643*5ffd83dbSDimitry Andric 1644*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 1645*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 1646*5ffd83dbSDimitry Andric 1647*5ffd83dbSDimitry Andric if (active_row && 1648*5ffd83dbSDimitry Andric active_row->GetCFAValue().GetValueType() != 1649*5ffd83dbSDimitry Andric UnwindPlan::Row::FAValue::unspecified) { 1650*5ffd83dbSDimitry Andric addr_t new_cfa; 1651*5ffd83dbSDimitry Andric if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 1652*5ffd83dbSDimitry Andric active_row->GetCFAValue(), new_cfa) || 1653*5ffd83dbSDimitry Andric new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) { 1654*5ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa with fallback unwindplan"); 1655*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 1656*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = original_full_unwind_plan_sp; 1657*5ffd83dbSDimitry Andric return false; 1658*5ffd83dbSDimitry Andric } 1659*5ffd83dbSDimitry Andric m_cfa = new_cfa; 1660*5ffd83dbSDimitry Andric 1661*5ffd83dbSDimitry Andric ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 1662*5ffd83dbSDimitry Andric active_row->GetAFAValue(), m_afa); 1663*5ffd83dbSDimitry Andric 1664*5ffd83dbSDimitry Andric if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB), 1665*5ffd83dbSDimitry Andric regloc) == 1666*5ffd83dbSDimitry Andric UnwindLLDB::RegisterSearchResult::eRegisterFound) { 1667*5ffd83dbSDimitry Andric const RegisterInfo *reg_info = 1668*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB)); 1669*5ffd83dbSDimitry Andric if (reg_info) { 1670*5ffd83dbSDimitry Andric RegisterValue reg_value; 1671*5ffd83dbSDimitry Andric if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, 1672*5ffd83dbSDimitry Andric reg_value)) { 1673*5ffd83dbSDimitry Andric new_caller_pc_value = reg_value.GetAsUInt64(); 1674*5ffd83dbSDimitry Andric } 1675*5ffd83dbSDimitry Andric } 1676*5ffd83dbSDimitry Andric } 1677*5ffd83dbSDimitry Andric 1678*5ffd83dbSDimitry Andric if (new_caller_pc_value == LLDB_INVALID_ADDRESS) { 1679*5ffd83dbSDimitry Andric UnwindLogMsg("failed to get a pc value for the caller frame with the " 1680*5ffd83dbSDimitry Andric "fallback unwind plan"); 1681*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 1682*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = original_full_unwind_plan_sp; 1683*5ffd83dbSDimitry Andric m_cfa = old_cfa; 1684*5ffd83dbSDimitry Andric m_afa = old_afa; 1685*5ffd83dbSDimitry Andric return false; 1686*5ffd83dbSDimitry Andric } 1687*5ffd83dbSDimitry Andric 1688*5ffd83dbSDimitry Andric if (old_caller_pc_value == new_caller_pc_value && 1689*5ffd83dbSDimitry Andric m_cfa == old_cfa && 1690*5ffd83dbSDimitry Andric m_afa == old_afa) { 1691*5ffd83dbSDimitry Andric UnwindLogMsg("fallback unwind plan got the same values for this frame " 1692*5ffd83dbSDimitry Andric "CFA and caller frame pc, not using"); 1693*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 1694*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = original_full_unwind_plan_sp; 1695*5ffd83dbSDimitry Andric return false; 1696*5ffd83dbSDimitry Andric } 1697*5ffd83dbSDimitry Andric 1698*5ffd83dbSDimitry Andric UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' " 1699*5ffd83dbSDimitry Andric "because UnwindPlan '%s' failed.", 1700*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetSourceName().GetCString(), 1701*5ffd83dbSDimitry Andric original_full_unwind_plan_sp->GetSourceName().GetCString()); 1702*5ffd83dbSDimitry Andric 1703*5ffd83dbSDimitry Andric // We've copied the fallback unwind plan into the full - now clear the 1704*5ffd83dbSDimitry Andric // fallback. 1705*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 1706*5ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); 1707*5ffd83dbSDimitry Andric } 1708*5ffd83dbSDimitry Andric 1709*5ffd83dbSDimitry Andric return true; 1710*5ffd83dbSDimitry Andric } 1711*5ffd83dbSDimitry Andric 1712*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ForceSwitchToFallbackUnwindPlan() { 1713*5ffd83dbSDimitry Andric if (m_fallback_unwind_plan_sp.get() == nullptr) 1714*5ffd83dbSDimitry Andric return false; 1715*5ffd83dbSDimitry Andric 1716*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == nullptr) 1717*5ffd83dbSDimitry Andric return false; 1718*5ffd83dbSDimitry Andric 1719*5ffd83dbSDimitry Andric if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || 1720*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName() == 1721*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetSourceName()) { 1722*5ffd83dbSDimitry Andric return false; 1723*5ffd83dbSDimitry Andric } 1724*5ffd83dbSDimitry Andric 1725*5ffd83dbSDimitry Andric UnwindPlan::RowSP active_row = 1726*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); 1727*5ffd83dbSDimitry Andric 1728*5ffd83dbSDimitry Andric if (active_row && 1729*5ffd83dbSDimitry Andric active_row->GetCFAValue().GetValueType() != 1730*5ffd83dbSDimitry Andric UnwindPlan::Row::FAValue::unspecified) { 1731*5ffd83dbSDimitry Andric addr_t new_cfa; 1732*5ffd83dbSDimitry Andric if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 1733*5ffd83dbSDimitry Andric active_row->GetCFAValue(), new_cfa) || 1734*5ffd83dbSDimitry Andric new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) { 1735*5ffd83dbSDimitry Andric UnwindLogMsg("failed to get cfa with fallback unwindplan"); 1736*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 1737*5ffd83dbSDimitry Andric return false; 1738*5ffd83dbSDimitry Andric } 1739*5ffd83dbSDimitry Andric 1740*5ffd83dbSDimitry Andric ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), 1741*5ffd83dbSDimitry Andric active_row->GetAFAValue(), m_afa); 1742*5ffd83dbSDimitry Andric 1743*5ffd83dbSDimitry Andric m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; 1744*5ffd83dbSDimitry Andric m_fallback_unwind_plan_sp.reset(); 1745*5ffd83dbSDimitry Andric 1746*5ffd83dbSDimitry Andric m_registers.clear(); 1747*5ffd83dbSDimitry Andric 1748*5ffd83dbSDimitry Andric m_cfa = new_cfa; 1749*5ffd83dbSDimitry Andric 1750*5ffd83dbSDimitry Andric PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); 1751*5ffd83dbSDimitry Andric 1752*5ffd83dbSDimitry Andric UnwindLogMsg("switched unconditionally to the fallback unwindplan %s", 1753*5ffd83dbSDimitry Andric m_full_unwind_plan_sp->GetSourceName().GetCString()); 1754*5ffd83dbSDimitry Andric return true; 1755*5ffd83dbSDimitry Andric } 1756*5ffd83dbSDimitry Andric return false; 1757*5ffd83dbSDimitry Andric } 1758*5ffd83dbSDimitry Andric 1759*5ffd83dbSDimitry Andric void RegisterContextUnwind::PropagateTrapHandlerFlagFromUnwindPlan( 1760*5ffd83dbSDimitry Andric lldb::UnwindPlanSP unwind_plan) { 1761*5ffd83dbSDimitry Andric if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) { 1762*5ffd83dbSDimitry Andric // Unwind plan does not indicate trap handler. Do nothing. We may 1763*5ffd83dbSDimitry Andric // already be flagged as trap handler flag due to the symbol being 1764*5ffd83dbSDimitry Andric // in the trap handler symbol list, and that should take precedence. 1765*5ffd83dbSDimitry Andric return; 1766*5ffd83dbSDimitry Andric } else if (m_frame_type != eNormalFrame) { 1767*5ffd83dbSDimitry Andric // If this is already a trap handler frame, nothing to do. 1768*5ffd83dbSDimitry Andric // If this is a skip or debug or invalid frame, don't override that. 1769*5ffd83dbSDimitry Andric return; 1770*5ffd83dbSDimitry Andric } 1771*5ffd83dbSDimitry Andric 1772*5ffd83dbSDimitry Andric m_frame_type = eTrapHandlerFrame; 1773*5ffd83dbSDimitry Andric 1774*5ffd83dbSDimitry Andric if (m_current_offset_backed_up_one != m_current_offset) { 1775*5ffd83dbSDimitry Andric // We backed up the pc by 1 to compute the symbol context, but 1776*5ffd83dbSDimitry Andric // now need to undo that because the pc of the trap handler 1777*5ffd83dbSDimitry Andric // frame may in fact be the first instruction of a signal return 1778*5ffd83dbSDimitry Andric // trampoline, rather than the instruction after a call. This 1779*5ffd83dbSDimitry Andric // happens on systems where the signal handler dispatch code, rather 1780*5ffd83dbSDimitry Andric // than calling the handler and being returned to, jumps to the 1781*5ffd83dbSDimitry Andric // handler after pushing the address of a return trampoline on the 1782*5ffd83dbSDimitry Andric // stack -- on these systems, when the handler returns, control will 1783*5ffd83dbSDimitry Andric // be transferred to the return trampoline, so that's the best 1784*5ffd83dbSDimitry Andric // symbol we can present in the callstack. 1785*5ffd83dbSDimitry Andric UnwindLogMsg("Resetting current offset and re-doing symbol lookup; " 1786*5ffd83dbSDimitry Andric "old symbol was %s", 1787*5ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 1788*5ffd83dbSDimitry Andric m_current_offset_backed_up_one = m_current_offset; 1789*5ffd83dbSDimitry Andric 1790*5ffd83dbSDimitry Andric AddressRange addr_range; 1791*5ffd83dbSDimitry Andric m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); 1792*5ffd83dbSDimitry Andric 1793*5ffd83dbSDimitry Andric UnwindLogMsg("Symbol is now %s", 1794*5ffd83dbSDimitry Andric GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); 1795*5ffd83dbSDimitry Andric 1796*5ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 1797*5ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 1798*5ffd83dbSDimitry Andric Target *target = &process->GetTarget(); 1799*5ffd83dbSDimitry Andric 1800*5ffd83dbSDimitry Andric m_start_pc = addr_range.GetBaseAddress(); 1801*5ffd83dbSDimitry Andric m_current_offset = 1802*5ffd83dbSDimitry Andric m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target); 1803*5ffd83dbSDimitry Andric } 1804*5ffd83dbSDimitry Andric } 1805*5ffd83dbSDimitry Andric 1806*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadFrameAddress( 1807*5ffd83dbSDimitry Andric lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa, 1808*5ffd83dbSDimitry Andric addr_t &address) { 1809*5ffd83dbSDimitry Andric RegisterValue reg_value; 1810*5ffd83dbSDimitry Andric 1811*5ffd83dbSDimitry Andric address = LLDB_INVALID_ADDRESS; 1812*5ffd83dbSDimitry Andric addr_t cfa_reg_contents; 1813*5ffd83dbSDimitry Andric 1814*5ffd83dbSDimitry Andric switch (fa.GetValueType()) { 1815*5ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isRegisterDereferenced: { 1816*5ffd83dbSDimitry Andric RegisterNumber cfa_reg(m_thread, row_register_kind, 1817*5ffd83dbSDimitry Andric fa.GetRegisterNumber()); 1818*5ffd83dbSDimitry Andric if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { 1819*5ffd83dbSDimitry Andric const RegisterInfo *reg_info = 1820*5ffd83dbSDimitry Andric GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB)); 1821*5ffd83dbSDimitry Andric RegisterValue reg_value; 1822*5ffd83dbSDimitry Andric if (reg_info) { 1823*5ffd83dbSDimitry Andric Status error = ReadRegisterValueFromMemory( 1824*5ffd83dbSDimitry Andric reg_info, cfa_reg_contents, reg_info->byte_size, reg_value); 1825*5ffd83dbSDimitry Andric if (error.Success()) { 1826*5ffd83dbSDimitry Andric address = reg_value.GetAsUInt64(); 1827*5ffd83dbSDimitry Andric UnwindLogMsg( 1828*5ffd83dbSDimitry Andric "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 1829*5ffd83dbSDimitry Andric ", CFA value is 0x%" PRIx64, 1830*5ffd83dbSDimitry Andric cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 1831*5ffd83dbSDimitry Andric cfa_reg_contents, address); 1832*5ffd83dbSDimitry Andric return true; 1833*5ffd83dbSDimitry Andric } else { 1834*5ffd83dbSDimitry Andric UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64 1835*5ffd83dbSDimitry Andric "] but memory read failed.", 1836*5ffd83dbSDimitry Andric cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 1837*5ffd83dbSDimitry Andric cfa_reg_contents); 1838*5ffd83dbSDimitry Andric } 1839*5ffd83dbSDimitry Andric } 1840*5ffd83dbSDimitry Andric } 1841*5ffd83dbSDimitry Andric break; 1842*5ffd83dbSDimitry Andric } 1843*5ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isRegisterPlusOffset: { 1844*5ffd83dbSDimitry Andric RegisterNumber cfa_reg(m_thread, row_register_kind, 1845*5ffd83dbSDimitry Andric fa.GetRegisterNumber()); 1846*5ffd83dbSDimitry Andric if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { 1847*5ffd83dbSDimitry Andric if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || 1848*5ffd83dbSDimitry Andric cfa_reg_contents == 1) { 1849*5ffd83dbSDimitry Andric UnwindLogMsg( 1850*5ffd83dbSDimitry Andric "Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, 1851*5ffd83dbSDimitry Andric cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 1852*5ffd83dbSDimitry Andric cfa_reg_contents); 1853*5ffd83dbSDimitry Andric cfa_reg_contents = LLDB_INVALID_ADDRESS; 1854*5ffd83dbSDimitry Andric return false; 1855*5ffd83dbSDimitry Andric } 1856*5ffd83dbSDimitry Andric address = cfa_reg_contents + fa.GetOffset(); 1857*5ffd83dbSDimitry Andric UnwindLogMsg( 1858*5ffd83dbSDimitry Andric "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 1859*5ffd83dbSDimitry Andric ", offset is %d", 1860*5ffd83dbSDimitry Andric address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), 1861*5ffd83dbSDimitry Andric cfa_reg_contents, fa.GetOffset()); 1862*5ffd83dbSDimitry Andric return true; 1863*5ffd83dbSDimitry Andric } 1864*5ffd83dbSDimitry Andric break; 1865*5ffd83dbSDimitry Andric } 1866*5ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isDWARFExpression: { 1867*5ffd83dbSDimitry Andric ExecutionContext exe_ctx(m_thread.shared_from_this()); 1868*5ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 1869*5ffd83dbSDimitry Andric DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(), 1870*5ffd83dbSDimitry Andric fa.GetDWARFExpressionLength(), 1871*5ffd83dbSDimitry Andric process->GetByteOrder(), 1872*5ffd83dbSDimitry Andric process->GetAddressByteSize()); 1873*5ffd83dbSDimitry Andric ModuleSP opcode_ctx; 1874*5ffd83dbSDimitry Andric DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); 1875*5ffd83dbSDimitry Andric dwarfexpr.SetRegisterKind(row_register_kind); 1876*5ffd83dbSDimitry Andric Value result; 1877*5ffd83dbSDimitry Andric Status error; 1878*5ffd83dbSDimitry Andric if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, 1879*5ffd83dbSDimitry Andric &error)) { 1880*5ffd83dbSDimitry Andric address = result.GetScalar().ULongLong(); 1881*5ffd83dbSDimitry Andric 1882*5ffd83dbSDimitry Andric UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64, 1883*5ffd83dbSDimitry Andric address); 1884*5ffd83dbSDimitry Andric return true; 1885*5ffd83dbSDimitry Andric } 1886*5ffd83dbSDimitry Andric UnwindLogMsg("Failed to set CFA value via DWARF expression: %s", 1887*5ffd83dbSDimitry Andric error.AsCString()); 1888*5ffd83dbSDimitry Andric break; 1889*5ffd83dbSDimitry Andric } 1890*5ffd83dbSDimitry Andric case UnwindPlan::Row::FAValue::isRaSearch: { 1891*5ffd83dbSDimitry Andric Process &process = *m_thread.GetProcess(); 1892*5ffd83dbSDimitry Andric lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset()); 1893*5ffd83dbSDimitry Andric if (return_address_hint == LLDB_INVALID_ADDRESS) 1894*5ffd83dbSDimitry Andric return false; 1895*5ffd83dbSDimitry Andric const unsigned max_iterations = 256; 1896*5ffd83dbSDimitry Andric for (unsigned i = 0; i < max_iterations; ++i) { 1897*5ffd83dbSDimitry Andric Status st; 1898*5ffd83dbSDimitry Andric lldb::addr_t candidate_addr = 1899*5ffd83dbSDimitry Andric return_address_hint + i * process.GetAddressByteSize(); 1900*5ffd83dbSDimitry Andric lldb::addr_t candidate = 1901*5ffd83dbSDimitry Andric process.ReadPointerFromMemory(candidate_addr, st); 1902*5ffd83dbSDimitry Andric if (st.Fail()) { 1903*5ffd83dbSDimitry Andric UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr, 1904*5ffd83dbSDimitry Andric st.AsCString()); 1905*5ffd83dbSDimitry Andric return false; 1906*5ffd83dbSDimitry Andric } 1907*5ffd83dbSDimitry Andric Address addr; 1908*5ffd83dbSDimitry Andric uint32_t permissions; 1909*5ffd83dbSDimitry Andric if (process.GetLoadAddressPermissions(candidate, permissions) && 1910*5ffd83dbSDimitry Andric permissions & lldb::ePermissionsExecutable) { 1911*5ffd83dbSDimitry Andric address = candidate_addr; 1912*5ffd83dbSDimitry Andric UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address); 1913*5ffd83dbSDimitry Andric return true; 1914*5ffd83dbSDimitry Andric } 1915*5ffd83dbSDimitry Andric } 1916*5ffd83dbSDimitry Andric UnwindLogMsg("No suitable CFA found"); 1917*5ffd83dbSDimitry Andric break; 1918*5ffd83dbSDimitry Andric } 1919*5ffd83dbSDimitry Andric default: 1920*5ffd83dbSDimitry Andric return false; 1921*5ffd83dbSDimitry Andric } 1922*5ffd83dbSDimitry Andric return false; 1923*5ffd83dbSDimitry Andric } 1924*5ffd83dbSDimitry Andric 1925*5ffd83dbSDimitry Andric lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) { 1926*5ffd83dbSDimitry Andric addr_t hint; 1927*5ffd83dbSDimitry Andric if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint)) 1928*5ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 1929*5ffd83dbSDimitry Andric if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol) 1930*5ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 1931*5ffd83dbSDimitry Andric 1932*5ffd83dbSDimitry Andric hint += plan_offset; 1933*5ffd83dbSDimitry Andric 1934*5ffd83dbSDimitry Andric if (auto next = GetNextFrame()) { 1935*5ffd83dbSDimitry Andric if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol) 1936*5ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 1937*5ffd83dbSDimitry Andric if (auto expected_size = 1938*5ffd83dbSDimitry Andric next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize( 1939*5ffd83dbSDimitry Andric *next->m_sym_ctx.symbol)) 1940*5ffd83dbSDimitry Andric hint += *expected_size; 1941*5ffd83dbSDimitry Andric else { 1942*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("Could not retrieve parameter size: %s", 1943*5ffd83dbSDimitry Andric llvm::toString(expected_size.takeError()).c_str()); 1944*5ffd83dbSDimitry Andric return LLDB_INVALID_ADDRESS; 1945*5ffd83dbSDimitry Andric } 1946*5ffd83dbSDimitry Andric } 1947*5ffd83dbSDimitry Andric return hint; 1948*5ffd83dbSDimitry Andric } 1949*5ffd83dbSDimitry Andric 1950*5ffd83dbSDimitry Andric // Retrieve a general purpose register value for THIS frame, as saved by the 1951*5ffd83dbSDimitry Andric // NEXT frame, i.e. the frame that 1952*5ffd83dbSDimitry Andric // this frame called. e.g. 1953*5ffd83dbSDimitry Andric // 1954*5ffd83dbSDimitry Andric // foo () { } 1955*5ffd83dbSDimitry Andric // bar () { foo (); } 1956*5ffd83dbSDimitry Andric // main () { bar (); } 1957*5ffd83dbSDimitry Andric // 1958*5ffd83dbSDimitry Andric // stopped in foo() so 1959*5ffd83dbSDimitry Andric // frame 0 - foo 1960*5ffd83dbSDimitry Andric // frame 1 - bar 1961*5ffd83dbSDimitry Andric // frame 2 - main 1962*5ffd83dbSDimitry Andric // and this RegisterContext is for frame 1 (bar) - if we want to get the pc 1963*5ffd83dbSDimitry Andric // value for frame 1, we need to ask 1964*5ffd83dbSDimitry Andric // where frame 0 (the "next" frame) saved that and retrieve the value. 1965*5ffd83dbSDimitry Andric 1966*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind, 1967*5ffd83dbSDimitry Andric uint32_t regnum, addr_t &value) { 1968*5ffd83dbSDimitry Andric if (!IsValid()) 1969*5ffd83dbSDimitry Andric return false; 1970*5ffd83dbSDimitry Andric 1971*5ffd83dbSDimitry Andric uint32_t lldb_regnum; 1972*5ffd83dbSDimitry Andric if (register_kind == eRegisterKindLLDB) { 1973*5ffd83dbSDimitry Andric lldb_regnum = regnum; 1974*5ffd83dbSDimitry Andric } else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds( 1975*5ffd83dbSDimitry Andric register_kind, regnum, eRegisterKindLLDB, lldb_regnum)) { 1976*5ffd83dbSDimitry Andric return false; 1977*5ffd83dbSDimitry Andric } 1978*5ffd83dbSDimitry Andric 1979*5ffd83dbSDimitry Andric const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum); 1980*5ffd83dbSDimitry Andric RegisterValue reg_value; 1981*5ffd83dbSDimitry Andric // if this is frame 0 (currently executing frame), get the requested reg 1982*5ffd83dbSDimitry Andric // contents from the actual thread registers 1983*5ffd83dbSDimitry Andric if (IsFrameZero()) { 1984*5ffd83dbSDimitry Andric if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) { 1985*5ffd83dbSDimitry Andric value = reg_value.GetAsUInt64(); 1986*5ffd83dbSDimitry Andric return true; 1987*5ffd83dbSDimitry Andric } 1988*5ffd83dbSDimitry Andric return false; 1989*5ffd83dbSDimitry Andric } 1990*5ffd83dbSDimitry Andric 1991*5ffd83dbSDimitry Andric bool pc_register = false; 1992*5ffd83dbSDimitry Andric uint32_t generic_regnum; 1993*5ffd83dbSDimitry Andric if (register_kind == eRegisterKindGeneric && 1994*5ffd83dbSDimitry Andric (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) { 1995*5ffd83dbSDimitry Andric pc_register = true; 1996*5ffd83dbSDimitry Andric } else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds( 1997*5ffd83dbSDimitry Andric register_kind, regnum, eRegisterKindGeneric, generic_regnum) && 1998*5ffd83dbSDimitry Andric (generic_regnum == LLDB_REGNUM_GENERIC_PC || 1999*5ffd83dbSDimitry Andric generic_regnum == LLDB_REGNUM_GENERIC_RA)) { 2000*5ffd83dbSDimitry Andric pc_register = true; 2001*5ffd83dbSDimitry Andric } 2002*5ffd83dbSDimitry Andric 2003*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc; 2004*5ffd83dbSDimitry Andric if (!m_parent_unwind.SearchForSavedLocationForRegister( 2005*5ffd83dbSDimitry Andric lldb_regnum, regloc, m_frame_number - 1, pc_register)) { 2006*5ffd83dbSDimitry Andric return false; 2007*5ffd83dbSDimitry Andric } 2008*5ffd83dbSDimitry Andric if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { 2009*5ffd83dbSDimitry Andric value = reg_value.GetAsUInt64(); 2010*5ffd83dbSDimitry Andric return true; 2011*5ffd83dbSDimitry Andric } 2012*5ffd83dbSDimitry Andric return false; 2013*5ffd83dbSDimitry Andric } 2014*5ffd83dbSDimitry Andric 2015*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadGPRValue(const RegisterNumber ®num, 2016*5ffd83dbSDimitry Andric addr_t &value) { 2017*5ffd83dbSDimitry Andric return ReadGPRValue(regnum.GetRegisterKind(), regnum.GetRegisterNumber(), 2018*5ffd83dbSDimitry Andric value); 2019*5ffd83dbSDimitry Andric } 2020*5ffd83dbSDimitry Andric 2021*5ffd83dbSDimitry Andric // Find the value of a register in THIS frame 2022*5ffd83dbSDimitry Andric 2023*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info, 2024*5ffd83dbSDimitry Andric RegisterValue &value) { 2025*5ffd83dbSDimitry Andric if (!IsValid()) 2026*5ffd83dbSDimitry Andric return false; 2027*5ffd83dbSDimitry Andric 2028*5ffd83dbSDimitry Andric const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; 2029*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("looking for register saved location for reg %d", 2030*5ffd83dbSDimitry Andric lldb_regnum); 2031*5ffd83dbSDimitry Andric 2032*5ffd83dbSDimitry Andric // If this is the 0th frame, hand this over to the live register context 2033*5ffd83dbSDimitry Andric if (IsFrameZero()) { 2034*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("passing along to the live register context for reg %d", 2035*5ffd83dbSDimitry Andric lldb_regnum); 2036*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->ReadRegister(reg_info, value); 2037*5ffd83dbSDimitry Andric } 2038*5ffd83dbSDimitry Andric 2039*5ffd83dbSDimitry Andric bool is_pc_regnum = false; 2040*5ffd83dbSDimitry Andric if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC || 2041*5ffd83dbSDimitry Andric reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) { 2042*5ffd83dbSDimitry Andric is_pc_regnum = true; 2043*5ffd83dbSDimitry Andric } 2044*5ffd83dbSDimitry Andric 2045*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc; 2046*5ffd83dbSDimitry Andric // Find out where the NEXT frame saved THIS frame's register contents 2047*5ffd83dbSDimitry Andric if (!m_parent_unwind.SearchForSavedLocationForRegister( 2048*5ffd83dbSDimitry Andric lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum)) 2049*5ffd83dbSDimitry Andric return false; 2050*5ffd83dbSDimitry Andric 2051*5ffd83dbSDimitry Andric return ReadRegisterValueFromRegisterLocation(regloc, reg_info, value); 2052*5ffd83dbSDimitry Andric } 2053*5ffd83dbSDimitry Andric 2054*5ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info, 2055*5ffd83dbSDimitry Andric const RegisterValue &value) { 2056*5ffd83dbSDimitry Andric if (!IsValid()) 2057*5ffd83dbSDimitry Andric return false; 2058*5ffd83dbSDimitry Andric 2059*5ffd83dbSDimitry Andric const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; 2060*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("looking for register saved location for reg %d", 2061*5ffd83dbSDimitry Andric lldb_regnum); 2062*5ffd83dbSDimitry Andric 2063*5ffd83dbSDimitry Andric // If this is the 0th frame, hand this over to the live register context 2064*5ffd83dbSDimitry Andric if (IsFrameZero()) { 2065*5ffd83dbSDimitry Andric UnwindLogMsgVerbose("passing along to the live register context for reg %d", 2066*5ffd83dbSDimitry Andric lldb_regnum); 2067*5ffd83dbSDimitry Andric return m_thread.GetRegisterContext()->WriteRegister(reg_info, value); 2068*5ffd83dbSDimitry Andric } 2069*5ffd83dbSDimitry Andric 2070*5ffd83dbSDimitry Andric lldb_private::UnwindLLDB::RegisterLocation regloc; 2071*5ffd83dbSDimitry Andric // Find out where the NEXT frame saved THIS frame's register contents 2072*5ffd83dbSDimitry Andric if (!m_parent_unwind.SearchForSavedLocationForRegister( 2073*5ffd83dbSDimitry Andric lldb_regnum, regloc, m_frame_number - 1, false)) 2074*5ffd83dbSDimitry Andric return false; 2075*5ffd83dbSDimitry Andric 2076*5ffd83dbSDimitry Andric return WriteRegisterValueToRegisterLocation(regloc, reg_info, value); 2077*5ffd83dbSDimitry Andric } 2078*5ffd83dbSDimitry Andric 2079*5ffd83dbSDimitry Andric // Don't need to implement this one 2080*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) { 2081*5ffd83dbSDimitry Andric return false; 2082*5ffd83dbSDimitry Andric } 2083*5ffd83dbSDimitry Andric 2084*5ffd83dbSDimitry Andric // Don't need to implement this one 2085*5ffd83dbSDimitry Andric bool RegisterContextUnwind::WriteAllRegisterValues( 2086*5ffd83dbSDimitry Andric const lldb::DataBufferSP &data_sp) { 2087*5ffd83dbSDimitry Andric return false; 2088*5ffd83dbSDimitry Andric } 2089*5ffd83dbSDimitry Andric 2090*5ffd83dbSDimitry Andric // Retrieve the pc value for THIS from 2091*5ffd83dbSDimitry Andric 2092*5ffd83dbSDimitry Andric bool RegisterContextUnwind::GetCFA(addr_t &cfa) { 2093*5ffd83dbSDimitry Andric if (!IsValid()) { 2094*5ffd83dbSDimitry Andric return false; 2095*5ffd83dbSDimitry Andric } 2096*5ffd83dbSDimitry Andric if (m_cfa == LLDB_INVALID_ADDRESS) { 2097*5ffd83dbSDimitry Andric return false; 2098*5ffd83dbSDimitry Andric } 2099*5ffd83dbSDimitry Andric cfa = m_cfa; 2100*5ffd83dbSDimitry Andric return true; 2101*5ffd83dbSDimitry Andric } 2102*5ffd83dbSDimitry Andric 2103*5ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetNextFrame() const { 2104*5ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr regctx; 2105*5ffd83dbSDimitry Andric if (m_frame_number == 0) 2106*5ffd83dbSDimitry Andric return regctx; 2107*5ffd83dbSDimitry Andric return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number - 1); 2108*5ffd83dbSDimitry Andric } 2109*5ffd83dbSDimitry Andric 2110*5ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetPrevFrame() const { 2111*5ffd83dbSDimitry Andric RegisterContextUnwind::SharedPtr regctx; 2112*5ffd83dbSDimitry Andric return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number + 1); 2113*5ffd83dbSDimitry Andric } 2114*5ffd83dbSDimitry Andric 2115*5ffd83dbSDimitry Andric // Retrieve the address of the start of the function of THIS frame 2116*5ffd83dbSDimitry Andric 2117*5ffd83dbSDimitry Andric bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) { 2118*5ffd83dbSDimitry Andric if (!IsValid()) 2119*5ffd83dbSDimitry Andric return false; 2120*5ffd83dbSDimitry Andric 2121*5ffd83dbSDimitry Andric if (!m_start_pc.IsValid()) { 2122*5ffd83dbSDimitry Andric bool read_successfully = ReadPC (start_pc); 2123*5ffd83dbSDimitry Andric if (read_successfully) 2124*5ffd83dbSDimitry Andric { 2125*5ffd83dbSDimitry Andric ProcessSP process_sp (m_thread.GetProcess()); 2126*5ffd83dbSDimitry Andric if (process_sp) 2127*5ffd83dbSDimitry Andric { 2128*5ffd83dbSDimitry Andric ABI *abi = process_sp->GetABI().get(); 2129*5ffd83dbSDimitry Andric if (abi) 2130*5ffd83dbSDimitry Andric start_pc = abi->FixCodeAddress(start_pc); 2131*5ffd83dbSDimitry Andric } 2132*5ffd83dbSDimitry Andric } 2133*5ffd83dbSDimitry Andric return read_successfully; 2134*5ffd83dbSDimitry Andric } 2135*5ffd83dbSDimitry Andric start_pc = m_start_pc.GetLoadAddress(CalculateTarget().get()); 2136*5ffd83dbSDimitry Andric return true; 2137*5ffd83dbSDimitry Andric } 2138*5ffd83dbSDimitry Andric 2139*5ffd83dbSDimitry Andric // Retrieve the current pc value for THIS frame, as saved by the NEXT frame. 2140*5ffd83dbSDimitry Andric 2141*5ffd83dbSDimitry Andric bool RegisterContextUnwind::ReadPC(addr_t &pc) { 2142*5ffd83dbSDimitry Andric if (!IsValid()) 2143*5ffd83dbSDimitry Andric return false; 2144*5ffd83dbSDimitry Andric 2145*5ffd83dbSDimitry Andric bool above_trap_handler = false; 2146*5ffd83dbSDimitry Andric if (GetNextFrame().get() && GetNextFrame()->IsValid() && 2147*5ffd83dbSDimitry Andric GetNextFrame()->IsTrapHandlerFrame()) 2148*5ffd83dbSDimitry Andric above_trap_handler = true; 2149*5ffd83dbSDimitry Andric 2150*5ffd83dbSDimitry Andric if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { 2151*5ffd83dbSDimitry Andric // A pc value of 0 or 1 is impossible in the middle of the stack -- it 2152*5ffd83dbSDimitry Andric // indicates the end of a stack walk. 2153*5ffd83dbSDimitry Andric // On the currently executing frame (or such a frame interrupted 2154*5ffd83dbSDimitry Andric // asynchronously by sigtramp et al) this may occur if code has jumped 2155*5ffd83dbSDimitry Andric // through a NULL pointer -- we want to be able to unwind past that frame 2156*5ffd83dbSDimitry Andric // to help find the bug. 2157*5ffd83dbSDimitry Andric 2158*5ffd83dbSDimitry Andric ProcessSP process_sp (m_thread.GetProcess()); 2159*5ffd83dbSDimitry Andric if (process_sp) 2160*5ffd83dbSDimitry Andric { 2161*5ffd83dbSDimitry Andric ABI *abi = process_sp->GetABI().get(); 2162*5ffd83dbSDimitry Andric if (abi) 2163*5ffd83dbSDimitry Andric pc = abi->FixCodeAddress(pc); 2164*5ffd83dbSDimitry Andric } 2165*5ffd83dbSDimitry Andric 2166*5ffd83dbSDimitry Andric return !(m_all_registers_available == false && 2167*5ffd83dbSDimitry Andric above_trap_handler == false && (pc == 0 || pc == 1)); 2168*5ffd83dbSDimitry Andric } else { 2169*5ffd83dbSDimitry Andric return false; 2170*5ffd83dbSDimitry Andric } 2171*5ffd83dbSDimitry Andric } 2172*5ffd83dbSDimitry Andric 2173*5ffd83dbSDimitry Andric void RegisterContextUnwind::UnwindLogMsg(const char *fmt, ...) { 2174*5ffd83dbSDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 2175*5ffd83dbSDimitry Andric if (log) { 2176*5ffd83dbSDimitry Andric va_list args; 2177*5ffd83dbSDimitry Andric va_start(args, fmt); 2178*5ffd83dbSDimitry Andric 2179*5ffd83dbSDimitry Andric char *logmsg; 2180*5ffd83dbSDimitry Andric if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == nullptr) { 2181*5ffd83dbSDimitry Andric if (logmsg) 2182*5ffd83dbSDimitry Andric free(logmsg); 2183*5ffd83dbSDimitry Andric va_end(args); 2184*5ffd83dbSDimitry Andric return; 2185*5ffd83dbSDimitry Andric } 2186*5ffd83dbSDimitry Andric va_end(args); 2187*5ffd83dbSDimitry Andric 2188*5ffd83dbSDimitry Andric LLDB_LOGF(log, "%*sth%d/fr%u %s", 2189*5ffd83dbSDimitry Andric m_frame_number < 100 ? m_frame_number : 100, "", 2190*5ffd83dbSDimitry Andric m_thread.GetIndexID(), m_frame_number, logmsg); 2191*5ffd83dbSDimitry Andric free(logmsg); 2192*5ffd83dbSDimitry Andric } 2193*5ffd83dbSDimitry Andric } 2194*5ffd83dbSDimitry Andric 2195*5ffd83dbSDimitry Andric void RegisterContextUnwind::UnwindLogMsgVerbose(const char *fmt, ...) { 2196*5ffd83dbSDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 2197*5ffd83dbSDimitry Andric if (log && log->GetVerbose()) { 2198*5ffd83dbSDimitry Andric va_list args; 2199*5ffd83dbSDimitry Andric va_start(args, fmt); 2200*5ffd83dbSDimitry Andric 2201*5ffd83dbSDimitry Andric char *logmsg; 2202*5ffd83dbSDimitry Andric if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == nullptr) { 2203*5ffd83dbSDimitry Andric if (logmsg) 2204*5ffd83dbSDimitry Andric free(logmsg); 2205*5ffd83dbSDimitry Andric va_end(args); 2206*5ffd83dbSDimitry Andric return; 2207*5ffd83dbSDimitry Andric } 2208*5ffd83dbSDimitry Andric va_end(args); 2209*5ffd83dbSDimitry Andric 2210*5ffd83dbSDimitry Andric LLDB_LOGF(log, "%*sth%d/fr%u %s", 2211*5ffd83dbSDimitry Andric m_frame_number < 100 ? m_frame_number : 100, "", 2212*5ffd83dbSDimitry Andric m_thread.GetIndexID(), m_frame_number, logmsg); 2213*5ffd83dbSDimitry Andric free(logmsg); 2214*5ffd83dbSDimitry Andric } 2215*5ffd83dbSDimitry Andric } 2216