xref: /freebsd-src/contrib/llvm-project/lldb/source/Target/RegisterContextUnwind.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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 &regloc) {
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 &regnum,
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