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