[TableGen] Allow bit fields in SearchableTables.
[llvm-project.git] / lldb / source / Symbol / FuncUnwinders.cpp
blobd67c0a828eb350bba440a08155fa5b887f010842
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 //===----------------------------------------------------------------------===//
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"
29 #include <memory>
31 using namespace lldb;
32 using namespace lldb_private;
34 /// constructor
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() {}
56 /// destructor
58 FuncUnwinders::~FuncUnwinders() = default;
60 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target,
61 Thread &thread) {
62 std::lock_guard<std::recursive_mutex> guard(m_mutex);
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;
77 return nullptr;
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();
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
102 return UnwindPlanSP();
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;
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();
122 return m_unwind_plan_object_file_sp;
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;
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();
140 return m_unwind_plan_eh_frame_sp;
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;
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();
158 return m_unwind_plan_debug_frame_sp;
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;
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();
178 return m_unwind_plan_arm_unwind_sp;
181 namespace {
182 class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver {
183 public:
184 RegisterContextToInfo(RegisterContext &ctx) : m_ctx(ctx) {}
186 const RegisterInfo *ResolveName(llvm::StringRef name) const override {
187 return m_ctx.GetRegisterInfoByName(name);
189 const RegisterInfo *ResolveNumber(lldb::RegisterKind kind,
190 uint32_t number) const override {
191 return m_ctx.GetRegisterInfo(kind, number);
194 private:
195 RegisterContext &m_ctx;
197 } // namespace
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;
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()));
210 return m_unwind_plan_symbol_file_sp;
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;
221 m_tried_unwind_plan_object_file_augmented = true;
223 UnwindPlanSP object_file_unwind_plan = GetObjectFileUnwindPlan(target);
224 if (!object_file_unwind_plan)
225 return m_unwind_plan_object_file_augmented_sp;
227 m_unwind_plan_object_file_augmented_sp =
228 std::make_shared<UnwindPlan>(*object_file_unwind_plan);
230 // Augment the instructions with epilogue descriptions if necessary
231 // so the UnwindPlan can be used at any instruction in the function.
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();
239 } else {
240 m_unwind_plan_object_file_augmented_sp.reset();
242 return m_unwind_plan_object_file_augmented_sp;
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;
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;
262 m_tried_unwind_plan_eh_frame_augmented = true;
264 UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target);
265 if (!eh_frame_plan)
266 return m_unwind_plan_eh_frame_augmented_sp;
268 m_unwind_plan_eh_frame_augmented_sp =
269 std::make_shared<UnwindPlan>(*eh_frame_plan);
271 // Augment the eh_frame instructions with epilogue descriptions if necessary
272 // so the UnwindPlan can be used at any instruction in the function.
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();
280 } else {
281 m_unwind_plan_eh_frame_augmented_sp.reset();
283 return m_unwind_plan_eh_frame_augmented_sp;
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;
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;
303 m_tried_unwind_plan_debug_frame_augmented = true;
305 UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target);
306 if (!debug_frame_plan)
307 return m_unwind_plan_debug_frame_augmented_sp;
309 m_unwind_plan_debug_frame_augmented_sp =
310 std::make_shared<UnwindPlan>(*debug_frame_plan);
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.
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();
322 } else
323 m_unwind_plan_debug_frame_augmented_sp.reset();
324 return m_unwind_plan_debug_frame_augmented_sp;
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;
335 m_tried_unwind_plan_assembly = true;
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();
346 return m_unwind_plan_assembly_sp;
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.
352 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
353 Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
354 LazyBool plans_are_identical = eLazyBoolCalculate;
356 RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
357 uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
359 if (a.get() && b.get()) {
360 UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
361 UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
363 if (a_first_row.get() && b_first_row.get()) {
364 UnwindPlan::Row::RegisterLocation a_pc_regloc;
365 UnwindPlan::Row::RegisterLocation b_pc_regloc;
367 a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
368 b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
370 plans_are_identical = eLazyBoolYes;
372 if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
373 plans_are_identical = eLazyBoolNo;
375 if (a_pc_regloc != b_pc_regloc) {
376 plans_are_identical = eLazyBoolNo;
380 return plans_are_identical;
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);
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.
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.
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;
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;
431 return assembly_sp;
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;
440 m_tried_unwind_fast = true;
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();
451 return m_unwind_plan_fast_sp;
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;
459 m_tried_unwind_arch_default = true;
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();
474 return m_unwind_plan_arch_default_sp;
477 UnwindPlanSP
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;
484 m_tried_unwind_arch_default_at_func_entry = true;
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();
500 return m_unwind_plan_arch_default_at_func_entry_sp;
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;
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;
516 const Address &FuncUnwinders::GetFunctionStartAddress() const {
517 return m_range.GetBaseAddress();
520 lldb::UnwindAssemblySP
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);
527 return assembly_profiler_sp;
530 Address FuncUnwinders::GetLSDAAddress(Target &target) {
531 Address lsda_addr;
533 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
534 if (unwind_plan_sp.get() == nullptr) {
535 unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
537 if (unwind_plan_sp.get() == nullptr) {
538 unwind_plan_sp = GetObjectFileUnwindPlan(target);
540 if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
541 lsda_addr = unwind_plan_sp->GetLSDAAddress();
543 return lsda_addr;
546 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
547 Address personality_addr;
549 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
550 if (unwind_plan_sp.get() == nullptr) {
551 unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
553 if (unwind_plan_sp.get() == nullptr) {
554 unwind_plan_sp = GetObjectFileUnwindPlan(target);
556 if (unwind_plan_sp.get() &&
557 unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
558 personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
561 return personality_addr;