1//===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
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
31using namespace lldb;
32using namespace lldb_private;
33
34/// constructor
35
36FuncUnwinders::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
58FuncUnwinders::~FuncUnwinders() {}
59
60UnwindPlanSP 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
80UnwindPlanSP 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
105lldb::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
125UnwindPlanSP 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
143UnwindPlanSP 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
161UnwindPlanSP 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
181namespace {
182class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver {
183public:
184  RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {}
185
186  const RegisterInfo *ResolveName(llvm::StringRef name) const {
187    return m_ctx.GetRegisterInfoByName(name);
188  }
189  const RegisterInfo *ResolveNumber(lldb::RegisterKind kind,
190                                    uint32_t number) const {
191    return m_ctx.GetRegisterInfo(kind, number);
192  }
193
194private:
195  RegisterContext &m_ctx;
196};
197} // namespace
198
199UnwindPlanSP 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
213UnwindPlanSP
214FuncUnwinders::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
245UnwindPlanSP 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
286UnwindPlanSP 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
327UnwindPlanSP 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.
352LazyBool 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
383UnwindPlanSP 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
434UnwindPlanSP 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
454UnwindPlanSP 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
477UnwindPlanSP
478FuncUnwinders::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
503Address &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
516const Address &FuncUnwinders::GetFunctionStartAddress() const {
517  return m_range.GetBaseAddress();
518}
519
520lldb::UnwindAssemblySP
521FuncUnwinders::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
530Address 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
546Address 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