xref: /freebsd/contrib/llvm-project/lldb/source/Symbol/FuncUnwinders.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1 //===-- FuncUnwinders.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Symbol/FuncUnwinders.h"
10 #include "lldb/Core/Address.h"
11 #include "lldb/Core/AddressRange.h"
12 #include "lldb/Symbol/ArmUnwindInfo.h"
13 #include "lldb/Symbol/CallFrameInfo.h"
14 #include "lldb/Symbol/CompactUnwindInfo.h"
15 #include "lldb/Symbol/DWARFCallFrameInfo.h"
16 #include "lldb/Symbol/ObjectFile.h"
17 #include "lldb/Symbol/SymbolFile.h"
18 #include "lldb/Symbol/UnwindPlan.h"
19 #include "lldb/Symbol/UnwindTable.h"
20 #include "lldb/Target/ABI.h"
21 #include "lldb/Target/ExecutionContext.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/RegisterContext.h"
24 #include "lldb/Target/RegisterNumber.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Target/UnwindAssembly.h"
28 
29 #include <memory>
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 /// constructor
35 
FuncUnwinders(UnwindTable & unwind_table,AddressRange range)36 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
37     : m_unwind_table(unwind_table), m_range(range), m_mutex(),
38       m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(),
39       m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(),
40       m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(),
41       m_unwind_plan_arch_default_sp(),
42       m_unwind_plan_arch_default_at_func_entry_sp(),
43       m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
44       m_tried_unwind_plan_object_file(false),
45       m_tried_unwind_plan_debug_frame(false),
46       m_tried_unwind_plan_object_file_augmented(false),
47       m_tried_unwind_plan_eh_frame_augmented(false),
48       m_tried_unwind_plan_debug_frame_augmented(false),
49       m_tried_unwind_plan_compact_unwind(false),
50       m_tried_unwind_plan_arm_unwind(false),
51       m_tried_unwind_plan_symbol_file(false), m_tried_unwind_fast(false),
52       m_tried_unwind_arch_default(false),
53       m_tried_unwind_arch_default_at_func_entry(false),
54       m_first_non_prologue_insn() {}
55 
56 /// destructor
57 
58 FuncUnwinders::~FuncUnwinders() = default;
59 
GetUnwindPlanAtCallSite(Target & target,Thread & thread)60 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target,
61                                                     Thread &thread) {
62   std::lock_guard<std::recursive_mutex> guard(m_mutex);
63 
64   if (UnwindPlanSP plan_sp = GetObjectFileUnwindPlan(target))
65     return plan_sp;
66   if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))
67     return plan_sp;
68   if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target))
69     return plan_sp;
70   if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target))
71     return plan_sp;
72   if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target))
73     return plan_sp;
74   if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target))
75     return plan_sp;
76 
77   return nullptr;
78 }
79 
GetCompactUnwindUnwindPlan(Target & target)80 UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) {
81   std::lock_guard<std::recursive_mutex> guard(m_mutex);
82   if (m_unwind_plan_compact_unwind.size() > 0)
83     return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact
84                                             // unwind plans for one func
85   if (m_tried_unwind_plan_compact_unwind)
86     return UnwindPlanSP();
87 
88   m_tried_unwind_plan_compact_unwind = true;
89   if (m_range.GetBaseAddress().IsValid()) {
90     Address current_pc(m_range.GetBaseAddress());
91     CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
92     if (compact_unwind) {
93       UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric));
94       if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) {
95         m_unwind_plan_compact_unwind.push_back(unwind_plan_sp);
96         return m_unwind_plan_compact_unwind[0]; // FIXME support multiple
97                                                 // compact unwind plans for one
98                                                 // func
99       }
100     }
101   }
102   return UnwindPlanSP();
103 }
104 
GetObjectFileUnwindPlan(Target & target)105 lldb::UnwindPlanSP FuncUnwinders::GetObjectFileUnwindPlan(Target &target) {
106   std::lock_guard<std::recursive_mutex> guard(m_mutex);
107   if (m_unwind_plan_object_file_sp.get() ||
108       m_tried_unwind_plan_object_file)
109     return m_unwind_plan_object_file_sp;
110 
111   m_tried_unwind_plan_object_file = true;
112   if (m_range.GetBaseAddress().IsValid()) {
113     CallFrameInfo *object_file_frame = m_unwind_table.GetObjectFileUnwindInfo();
114     if (object_file_frame) {
115       m_unwind_plan_object_file_sp =
116           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
117       if (!object_file_frame->GetUnwindPlan(m_range,
118                                             *m_unwind_plan_object_file_sp))
119         m_unwind_plan_object_file_sp.reset();
120     }
121   }
122   return m_unwind_plan_object_file_sp;
123 }
124 
GetEHFrameUnwindPlan(Target & target)125 UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target) {
126   std::lock_guard<std::recursive_mutex> guard(m_mutex);
127   if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)
128     return m_unwind_plan_eh_frame_sp;
129 
130   m_tried_unwind_plan_eh_frame = true;
131   if (m_range.GetBaseAddress().IsValid()) {
132     DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
133     if (eh_frame) {
134       m_unwind_plan_eh_frame_sp =
135           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
136       if (!eh_frame->GetUnwindPlan(m_range, *m_unwind_plan_eh_frame_sp))
137         m_unwind_plan_eh_frame_sp.reset();
138     }
139   }
140   return m_unwind_plan_eh_frame_sp;
141 }
142 
GetDebugFrameUnwindPlan(Target & target)143 UnwindPlanSP FuncUnwinders::GetDebugFrameUnwindPlan(Target &target) {
144   std::lock_guard<std::recursive_mutex> guard(m_mutex);
145   if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame)
146     return m_unwind_plan_debug_frame_sp;
147 
148   m_tried_unwind_plan_debug_frame = true;
149   if (m_range.GetBaseAddress().IsValid()) {
150     DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();
151     if (debug_frame) {
152       m_unwind_plan_debug_frame_sp =
153           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
154       if (!debug_frame->GetUnwindPlan(m_range, *m_unwind_plan_debug_frame_sp))
155         m_unwind_plan_debug_frame_sp.reset();
156     }
157   }
158   return m_unwind_plan_debug_frame_sp;
159 }
160 
GetArmUnwindUnwindPlan(Target & target)161 UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target) {
162   std::lock_guard<std::recursive_mutex> guard(m_mutex);
163   if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
164     return m_unwind_plan_arm_unwind_sp;
165 
166   m_tried_unwind_plan_arm_unwind = true;
167   if (m_range.GetBaseAddress().IsValid()) {
168     Address current_pc(m_range.GetBaseAddress());
169     ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
170     if (arm_unwind_info) {
171       m_unwind_plan_arm_unwind_sp =
172           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
173       if (!arm_unwind_info->GetUnwindPlan(target, current_pc,
174                                           *m_unwind_plan_arm_unwind_sp))
175         m_unwind_plan_arm_unwind_sp.reset();
176     }
177   }
178   return m_unwind_plan_arm_unwind_sp;
179 }
180 
181 namespace {
182 class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver {
183 public:
RegisterContextToInfo(RegisterContext & ctx)184   RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {}
185 
ResolveName(llvm::StringRef name) const186   const RegisterInfo *ResolveName(llvm::StringRef name) const override {
187     return m_ctx.GetRegisterInfoByName(name);
188   }
ResolveNumber(lldb::RegisterKind kind,uint32_t number) const189   const RegisterInfo *ResolveNumber(lldb::RegisterKind kind,
190                                     uint32_t number) const override {
191     return m_ctx.GetRegisterInfo(kind, number);
192   }
193 
194 private:
195   RegisterContext &m_ctx;
196 };
197 } // namespace
198 
GetSymbolFileUnwindPlan(Thread & thread)199 UnwindPlanSP FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) {
200   std::lock_guard<std::recursive_mutex> guard(m_mutex);
201   if (m_unwind_plan_symbol_file_sp.get() || m_tried_unwind_plan_symbol_file)
202     return m_unwind_plan_symbol_file_sp;
203 
204   m_tried_unwind_plan_symbol_file = true;
205   if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) {
206     m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan(
207         m_range.GetBaseAddress(),
208         RegisterContextToInfo(*thread.GetRegisterContext()));
209   }
210   return m_unwind_plan_symbol_file_sp;
211 }
212 
213 UnwindPlanSP
GetObjectFileAugmentedUnwindPlan(Target & target,Thread & thread)214 FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target &target,
215                                                      Thread &thread) {
216   std::lock_guard<std::recursive_mutex> guard(m_mutex);
217   if (m_unwind_plan_object_file_augmented_sp.get() ||
218       m_tried_unwind_plan_object_file_augmented)
219     return m_unwind_plan_object_file_augmented_sp;
220 
221   m_tried_unwind_plan_object_file_augmented = true;
222 
223   UnwindPlanSP object_file_unwind_plan = GetObjectFileUnwindPlan(target);
224   if (!object_file_unwind_plan)
225     return m_unwind_plan_object_file_augmented_sp;
226 
227   m_unwind_plan_object_file_augmented_sp =
228       std::make_shared<UnwindPlan>(*object_file_unwind_plan);
229 
230   // Augment the instructions with epilogue descriptions if necessary
231   // so the UnwindPlan can be used at any instruction in the function.
232 
233   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
234   if (assembly_profiler_sp) {
235     if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
236             m_range, thread, *m_unwind_plan_object_file_augmented_sp)) {
237       m_unwind_plan_object_file_augmented_sp.reset();
238     }
239   } else {
240     m_unwind_plan_object_file_augmented_sp.reset();
241   }
242   return m_unwind_plan_object_file_augmented_sp;
243 }
244 
GetEHFrameAugmentedUnwindPlan(Target & target,Thread & thread)245 UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target,
246                                                           Thread &thread) {
247   std::lock_guard<std::recursive_mutex> guard(m_mutex);
248   if (m_unwind_plan_eh_frame_augmented_sp.get() ||
249       m_tried_unwind_plan_eh_frame_augmented)
250     return m_unwind_plan_eh_frame_augmented_sp;
251 
252   // Only supported on x86 architectures where we get eh_frame from the
253   // compiler that describes the prologue instructions perfectly, and sometimes
254   // the epilogue instructions too.
255   if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
256       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
257       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
258     m_tried_unwind_plan_eh_frame_augmented = true;
259     return m_unwind_plan_eh_frame_augmented_sp;
260   }
261 
262   m_tried_unwind_plan_eh_frame_augmented = true;
263 
264   UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target);
265   if (!eh_frame_plan)
266     return m_unwind_plan_eh_frame_augmented_sp;
267 
268   m_unwind_plan_eh_frame_augmented_sp =
269       std::make_shared<UnwindPlan>(*eh_frame_plan);
270 
271   // Augment the eh_frame instructions with epilogue descriptions if necessary
272   // so the UnwindPlan can be used at any instruction in the function.
273 
274   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
275   if (assembly_profiler_sp) {
276     if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
277             m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) {
278       m_unwind_plan_eh_frame_augmented_sp.reset();
279     }
280   } else {
281     m_unwind_plan_eh_frame_augmented_sp.reset();
282   }
283   return m_unwind_plan_eh_frame_augmented_sp;
284 }
285 
GetDebugFrameAugmentedUnwindPlan(Target & target,Thread & thread)286 UnwindPlanSP FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target,
287                                                              Thread &thread) {
288   std::lock_guard<std::recursive_mutex> guard(m_mutex);
289   if (m_unwind_plan_debug_frame_augmented_sp.get() ||
290       m_tried_unwind_plan_debug_frame_augmented)
291     return m_unwind_plan_debug_frame_augmented_sp;
292 
293   // Only supported on x86 architectures where we get debug_frame from the
294   // compiler that describes the prologue instructions perfectly, and sometimes
295   // the epilogue instructions too.
296   if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
297       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
298       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
299     m_tried_unwind_plan_debug_frame_augmented = true;
300     return m_unwind_plan_debug_frame_augmented_sp;
301   }
302 
303   m_tried_unwind_plan_debug_frame_augmented = true;
304 
305   UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target);
306   if (!debug_frame_plan)
307     return m_unwind_plan_debug_frame_augmented_sp;
308 
309   m_unwind_plan_debug_frame_augmented_sp =
310       std::make_shared<UnwindPlan>(*debug_frame_plan);
311 
312   // Augment the debug_frame instructions with epilogue descriptions if
313   // necessary so the UnwindPlan can be used at any instruction in the
314   // function.
315 
316   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
317   if (assembly_profiler_sp) {
318     if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
319             m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) {
320       m_unwind_plan_debug_frame_augmented_sp.reset();
321     }
322   } else
323     m_unwind_plan_debug_frame_augmented_sp.reset();
324   return m_unwind_plan_debug_frame_augmented_sp;
325 }
326 
GetAssemblyUnwindPlan(Target & target,Thread & thread)327 UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
328                                                   Thread &thread) {
329   std::lock_guard<std::recursive_mutex> guard(m_mutex);
330   if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||
331       !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) {
332     return m_unwind_plan_assembly_sp;
333   }
334 
335   m_tried_unwind_plan_assembly = true;
336 
337   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
338   if (assembly_profiler_sp) {
339     m_unwind_plan_assembly_sp =
340         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
341     if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
342             m_range, thread, *m_unwind_plan_assembly_sp)) {
343       m_unwind_plan_assembly_sp.reset();
344     }
345   }
346   return m_unwind_plan_assembly_sp;
347 }
348 
349 // This method compares the pc unwind rule in the first row of two UnwindPlans.
350 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
351 // sp"), then it will return LazyBoolTrue.
CompareUnwindPlansForIdenticalInitialPCLocation(Thread & thread,const UnwindPlanSP & a,const UnwindPlanSP & b)352 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
353     Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
354   LazyBool plans_are_identical = eLazyBoolCalculate;
355 
356   RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
357   uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
358 
359   if (a.get() && b.get()) {
360     UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
361     UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
362 
363     if (a_first_row.get() && b_first_row.get()) {
364       UnwindPlan::Row::RegisterLocation a_pc_regloc;
365       UnwindPlan::Row::RegisterLocation b_pc_regloc;
366 
367       a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
368       b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
369 
370       plans_are_identical = eLazyBoolYes;
371 
372       if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
373         plans_are_identical = eLazyBoolNo;
374       }
375       if (a_pc_regloc != b_pc_regloc) {
376         plans_are_identical = eLazyBoolNo;
377       }
378     }
379   }
380   return plans_are_identical;
381 }
382 
GetUnwindPlanAtNonCallSite(Target & target,Thread & thread)383 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
384                                                        Thread &thread) {
385   UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target);
386   if (!eh_frame_sp)
387     eh_frame_sp = GetDebugFrameUnwindPlan(target);
388   if (!eh_frame_sp)
389     eh_frame_sp = GetObjectFileUnwindPlan(target);
390   UnwindPlanSP arch_default_at_entry_sp =
391       GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread);
392   UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);
393   UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread);
394 
395   // This point of this code is to detect when a function is using a non-
396   // standard ABI, and the eh_frame correctly describes that alternate ABI.
397   // This is addressing a specific situation on x86_64 linux systems where one
398   // function in a library pushes a value on the stack and jumps to another
399   // function.  So using an assembly instruction based unwind will not work
400   // when you're in the second function - the stack has been modified in a non-
401   // ABI way.  But we have eh_frame that correctly describes how to unwind from
402   // this location.  So we're looking to see if the initial pc register save
403   // location from the eh_frame is different from the assembly unwind, the arch
404   // default unwind, and the arch default at initial function entry.
405   //
406   // We may have eh_frame that describes the entire function -- or we may have
407   // eh_frame that only describes the unwind after the prologue has executed --
408   // so we need to check both the arch default (once the prologue has executed)
409   // and the arch default at initial function entry.  And we may be running on
410   // a target where we have only some of the assembly/arch default unwind plans
411   // available.
412 
413   if (CompareUnwindPlansForIdenticalInitialPCLocation(
414           thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
415       CompareUnwindPlansForIdenticalInitialPCLocation(
416           thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
417       CompareUnwindPlansForIdenticalInitialPCLocation(
418           thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {
419     return eh_frame_sp;
420   }
421 
422   if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))
423     return plan_sp;
424   if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread))
425     return plan_sp;
426   if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread))
427     return plan_sp;
428   if (UnwindPlanSP plan_sp = GetObjectFileAugmentedUnwindPlan(target, thread))
429     return plan_sp;
430 
431   return assembly_sp;
432 }
433 
GetUnwindPlanFastUnwind(Target & target,Thread & thread)434 UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target,
435                                                     Thread &thread) {
436   std::lock_guard<std::recursive_mutex> guard(m_mutex);
437   if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
438     return m_unwind_plan_fast_sp;
439 
440   m_tried_unwind_fast = true;
441 
442   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
443   if (assembly_profiler_sp) {
444     m_unwind_plan_fast_sp =
445         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
446     if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
447                                                  *m_unwind_plan_fast_sp)) {
448       m_unwind_plan_fast_sp.reset();
449     }
450   }
451   return m_unwind_plan_fast_sp;
452 }
453 
GetUnwindPlanArchitectureDefault(Thread & thread)454 UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) {
455   std::lock_guard<std::recursive_mutex> guard(m_mutex);
456   if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
457     return m_unwind_plan_arch_default_sp;
458 
459   m_tried_unwind_arch_default = true;
460 
461   Address current_pc;
462   ProcessSP process_sp(thread.CalculateProcess());
463   if (process_sp) {
464     ABI *abi = process_sp->GetABI().get();
465     if (abi) {
466       m_unwind_plan_arch_default_sp =
467           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
468       if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {
469         m_unwind_plan_arch_default_sp.reset();
470       }
471     }
472   }
473 
474   return m_unwind_plan_arch_default_sp;
475 }
476 
477 UnwindPlanSP
GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread & thread)478 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
479   std::lock_guard<std::recursive_mutex> guard(m_mutex);
480   if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||
481       m_tried_unwind_arch_default_at_func_entry)
482     return m_unwind_plan_arch_default_at_func_entry_sp;
483 
484   m_tried_unwind_arch_default_at_func_entry = true;
485 
486   Address current_pc;
487   ProcessSP process_sp(thread.CalculateProcess());
488   if (process_sp) {
489     ABI *abi = process_sp->GetABI().get();
490     if (abi) {
491       m_unwind_plan_arch_default_at_func_entry_sp =
492           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
493       if (!abi->CreateFunctionEntryUnwindPlan(
494               *m_unwind_plan_arch_default_at_func_entry_sp)) {
495         m_unwind_plan_arch_default_at_func_entry_sp.reset();
496       }
497     }
498   }
499 
500   return m_unwind_plan_arch_default_at_func_entry_sp;
501 }
502 
GetFirstNonPrologueInsn(Target & target)503 Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
504   std::lock_guard<std::recursive_mutex> guard(m_mutex);
505   if (m_first_non_prologue_insn.IsValid())
506     return m_first_non_prologue_insn;
507 
508   ExecutionContext exe_ctx(target.shared_from_this(), false);
509   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
510   if (assembly_profiler_sp)
511     assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
512                                                m_first_non_prologue_insn);
513   return m_first_non_prologue_insn;
514 }
515 
GetFunctionStartAddress() const516 const Address &FuncUnwinders::GetFunctionStartAddress() const {
517   return m_range.GetBaseAddress();
518 }
519 
520 lldb::UnwindAssemblySP
GetUnwindAssemblyProfiler(Target & target)521 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
522   UnwindAssemblySP assembly_profiler_sp;
523   if (ArchSpec arch = m_unwind_table.GetArchitecture()) {
524     arch.MergeFrom(target.GetArchitecture());
525     assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
526   }
527   return assembly_profiler_sp;
528 }
529 
GetLSDAAddress(Target & target)530 Address FuncUnwinders::GetLSDAAddress(Target &target) {
531   Address lsda_addr;
532 
533   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
534   if (unwind_plan_sp.get() == nullptr) {
535     unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
536   }
537   if (unwind_plan_sp.get() == nullptr) {
538     unwind_plan_sp = GetObjectFileUnwindPlan(target);
539   }
540   if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
541     lsda_addr = unwind_plan_sp->GetLSDAAddress();
542   }
543   return lsda_addr;
544 }
545 
GetPersonalityRoutinePtrAddress(Target & target)546 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
547   Address personality_addr;
548 
549   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
550   if (unwind_plan_sp.get() == nullptr) {
551     unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
552   }
553   if (unwind_plan_sp.get() == nullptr) {
554     unwind_plan_sp = GetObjectFileUnwindPlan(target);
555   }
556   if (unwind_plan_sp.get() &&
557       unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
558     personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
559   }
560 
561   return personality_addr;
562 }
563