xref: /llvm-project/lldb/source/Symbol/FuncUnwinders.cpp (revision 3336d73126ae7ebaadf7c3a4d85e373eaae8cda6)
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 
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 
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 
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 
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 
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 
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 
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:
184   RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {}
185 
186   const RegisterInfo *ResolveName(llvm::StringRef name) const override {
187     return m_ctx.GetRegisterInfoByName(name);
188   }
189   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 
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
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 
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 
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 
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   // Don't analyze more than 10 megabytes of instructions,
338   // if a function is legitimately larger than that, we'll
339   // miss the epilogue instructions, but guard against a
340   // bogusly large function and analyzing large amounts of
341   // non-instruction data.
342   AddressRange range = m_range;
343   const addr_t func_size =
344       std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
345   range.SetByteSize(func_size);
346 
347   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
348   if (assembly_profiler_sp) {
349     m_unwind_plan_assembly_sp =
350         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
351     if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
352             range, thread, *m_unwind_plan_assembly_sp)) {
353       m_unwind_plan_assembly_sp.reset();
354     }
355   }
356   return m_unwind_plan_assembly_sp;
357 }
358 
359 // This method compares the pc unwind rule in the first row of two UnwindPlans.
360 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
361 // sp"), then it will return LazyBoolTrue.
362 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
363     Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
364   LazyBool plans_are_identical = eLazyBoolCalculate;
365 
366   RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
367   uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
368 
369   if (a.get() && b.get()) {
370     UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
371     UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
372 
373     if (a_first_row.get() && b_first_row.get()) {
374       UnwindPlan::Row::AbstractRegisterLocation a_pc_regloc;
375       UnwindPlan::Row::AbstractRegisterLocation b_pc_regloc;
376 
377       a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
378       b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
379 
380       plans_are_identical = eLazyBoolYes;
381 
382       if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
383         plans_are_identical = eLazyBoolNo;
384       }
385       if (a_pc_regloc != b_pc_regloc) {
386         plans_are_identical = eLazyBoolNo;
387       }
388     }
389   }
390   return plans_are_identical;
391 }
392 
393 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
394                                                        Thread &thread) {
395   UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target);
396   if (!eh_frame_sp)
397     eh_frame_sp = GetDebugFrameUnwindPlan(target);
398   if (!eh_frame_sp)
399     eh_frame_sp = GetObjectFileUnwindPlan(target);
400   UnwindPlanSP arch_default_at_entry_sp =
401       GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread);
402   UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);
403   UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread);
404 
405   // This point of this code is to detect when a function is using a non-
406   // standard ABI, and the eh_frame correctly describes that alternate ABI.
407   // This is addressing a specific situation on x86_64 linux systems where one
408   // function in a library pushes a value on the stack and jumps to another
409   // function.  So using an assembly instruction based unwind will not work
410   // when you're in the second function - the stack has been modified in a non-
411   // ABI way.  But we have eh_frame that correctly describes how to unwind from
412   // this location.  So we're looking to see if the initial pc register save
413   // location from the eh_frame is different from the assembly unwind, the arch
414   // default unwind, and the arch default at initial function entry.
415   //
416   // We may have eh_frame that describes the entire function -- or we may have
417   // eh_frame that only describes the unwind after the prologue has executed --
418   // so we need to check both the arch default (once the prologue has executed)
419   // and the arch default at initial function entry.  And we may be running on
420   // a target where we have only some of the assembly/arch default unwind plans
421   // available.
422 
423   if (CompareUnwindPlansForIdenticalInitialPCLocation(
424           thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
425       CompareUnwindPlansForIdenticalInitialPCLocation(
426           thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
427       CompareUnwindPlansForIdenticalInitialPCLocation(
428           thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {
429     return eh_frame_sp;
430   }
431 
432   if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread))
433     return plan_sp;
434   if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread))
435     return plan_sp;
436   if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread))
437     return plan_sp;
438   if (UnwindPlanSP plan_sp = GetObjectFileAugmentedUnwindPlan(target, thread))
439     return plan_sp;
440 
441   return assembly_sp;
442 }
443 
444 UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target,
445                                                     Thread &thread) {
446   std::lock_guard<std::recursive_mutex> guard(m_mutex);
447   if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
448     return m_unwind_plan_fast_sp;
449 
450   m_tried_unwind_fast = true;
451 
452   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
453   if (assembly_profiler_sp) {
454     m_unwind_plan_fast_sp =
455         std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
456     if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
457                                                  *m_unwind_plan_fast_sp)) {
458       m_unwind_plan_fast_sp.reset();
459     }
460   }
461   return m_unwind_plan_fast_sp;
462 }
463 
464 UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) {
465   std::lock_guard<std::recursive_mutex> guard(m_mutex);
466   if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
467     return m_unwind_plan_arch_default_sp;
468 
469   m_tried_unwind_arch_default = true;
470 
471   Address current_pc;
472   ProcessSP process_sp(thread.CalculateProcess());
473   if (process_sp) {
474     ABI *abi = process_sp->GetABI().get();
475     if (abi) {
476       m_unwind_plan_arch_default_sp =
477           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
478       if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {
479         m_unwind_plan_arch_default_sp.reset();
480       }
481     }
482   }
483 
484   return m_unwind_plan_arch_default_sp;
485 }
486 
487 UnwindPlanSP
488 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
489   std::lock_guard<std::recursive_mutex> guard(m_mutex);
490   if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||
491       m_tried_unwind_arch_default_at_func_entry)
492     return m_unwind_plan_arch_default_at_func_entry_sp;
493 
494   m_tried_unwind_arch_default_at_func_entry = true;
495 
496   Address current_pc;
497   ProcessSP process_sp(thread.CalculateProcess());
498   if (process_sp) {
499     ABI *abi = process_sp->GetABI().get();
500     if (abi) {
501       m_unwind_plan_arch_default_at_func_entry_sp =
502           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
503       if (!abi->CreateFunctionEntryUnwindPlan(
504               *m_unwind_plan_arch_default_at_func_entry_sp)) {
505         m_unwind_plan_arch_default_at_func_entry_sp.reset();
506       }
507     }
508   }
509 
510   return m_unwind_plan_arch_default_at_func_entry_sp;
511 }
512 
513 Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
514   std::lock_guard<std::recursive_mutex> guard(m_mutex);
515   if (m_first_non_prologue_insn.IsValid())
516     return m_first_non_prologue_insn;
517 
518   ExecutionContext exe_ctx(target.shared_from_this(), false);
519   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
520   if (assembly_profiler_sp)
521     assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
522                                                m_first_non_prologue_insn);
523   return m_first_non_prologue_insn;
524 }
525 
526 const Address &FuncUnwinders::GetFunctionStartAddress() const {
527   return m_range.GetBaseAddress();
528 }
529 
530 lldb::UnwindAssemblySP
531 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
532   UnwindAssemblySP assembly_profiler_sp;
533   if (ArchSpec arch = m_unwind_table.GetArchitecture()) {
534     arch.MergeFrom(target.GetArchitecture());
535     assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
536   }
537   return assembly_profiler_sp;
538 }
539 
540 Address FuncUnwinders::GetLSDAAddress(Target &target) {
541   Address lsda_addr;
542 
543   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
544   if (unwind_plan_sp.get() == nullptr) {
545     unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
546   }
547   if (unwind_plan_sp.get() == nullptr) {
548     unwind_plan_sp = GetObjectFileUnwindPlan(target);
549   }
550   if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
551     lsda_addr = unwind_plan_sp->GetLSDAAddress();
552   }
553   return lsda_addr;
554 }
555 
556 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
557   Address personality_addr;
558 
559   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
560   if (unwind_plan_sp.get() == nullptr) {
561     unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
562   }
563   if (unwind_plan_sp.get() == nullptr) {
564     unwind_plan_sp = GetObjectFileUnwindPlan(target);
565   }
566   if (unwind_plan_sp.get() &&
567       unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
568     personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
569   }
570 
571   return personality_addr;
572 }
573