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