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