1 //===-- FuncUnwinders.cpp -------------------------------------------------===//
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
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"
32 using namespace lldb_private
;
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() {}
58 FuncUnwinders::~FuncUnwinders() = default;
60 UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtCallSite(Target
&target
,
62 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
64 if (UnwindPlanSP plan_sp
= GetObjectFileUnwindPlan(target
))
66 if (UnwindPlanSP plan_sp
= GetSymbolFileUnwindPlan(thread
))
68 if (UnwindPlanSP plan_sp
= GetDebugFrameUnwindPlan(target
))
70 if (UnwindPlanSP plan_sp
= GetEHFrameUnwindPlan(target
))
72 if (UnwindPlanSP plan_sp
= GetCompactUnwindUnwindPlan(target
))
74 if (UnwindPlanSP plan_sp
= GetArmUnwindUnwindPlan(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();
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();
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
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();
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();
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
;
182 class RegisterContextToInfo
: public SymbolFile::RegisterInfoResolver
{
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
);
195 RegisterContext
&m_ctx
;
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
;
214 FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target
&target
,
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();
240 m_unwind_plan_object_file_augmented_sp
.reset();
242 return m_unwind_plan_object_file_augmented_sp
;
245 UnwindPlanSP
FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target
&target
,
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
);
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();
281 m_unwind_plan_eh_frame_augmented_sp
.reset();
283 return m_unwind_plan_eh_frame_augmented_sp
;
286 UnwindPlanSP
FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target
&target
,
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
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();
323 m_unwind_plan_debug_frame_augmented_sp
.reset();
324 return m_unwind_plan_debug_frame_augmented_sp
;
327 UnwindPlanSP
FuncUnwinders::GetAssemblyUnwindPlan(Target
&target
,
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
,
385 UnwindPlanSP eh_frame_sp
= GetEHFrameUnwindPlan(target
);
387 eh_frame_sp
= GetDebugFrameUnwindPlan(target
);
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
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
) {
422 if (UnwindPlanSP plan_sp
= GetSymbolFileUnwindPlan(thread
))
424 if (UnwindPlanSP plan_sp
= GetDebugFrameAugmentedUnwindPlan(target
, thread
))
426 if (UnwindPlanSP plan_sp
= GetEHFrameAugmentedUnwindPlan(target
, thread
))
428 if (UnwindPlanSP plan_sp
= GetObjectFileAugmentedUnwindPlan(target
, thread
))
434 UnwindPlanSP
FuncUnwinders::GetUnwindPlanFastUnwind(Target
&target
,
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;
462 ProcessSP
process_sp(thread
.CalculateProcess());
464 ABI
*abi
= process_sp
->GetABI().get();
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
;
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;
487 ProcessSP
process_sp(thread
.CalculateProcess());
489 ABI
*abi
= process_sp
->GetABI().get();
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
) {
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();
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
;