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 // 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
);
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();
356 return m_unwind_plan_assembly_sp
;
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
;
366 RegisterNumber
pc_reg(thread
, eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
367 uint32_t pc_reg_lldb_regnum
= pc_reg
.GetAsKind(eRegisterKindLLDB
);
369 if (a
.get() && b
.get()) {
370 UnwindPlan::RowSP a_first_row
= a
->GetRowAtIndex(0);
371 UnwindPlan::RowSP b_first_row
= b
->GetRowAtIndex(0);
373 if (a_first_row
.get() && b_first_row
.get()) {
374 UnwindPlan::Row::AbstractRegisterLocation a_pc_regloc
;
375 UnwindPlan::Row::AbstractRegisterLocation b_pc_regloc
;
377 a_first_row
->GetRegisterInfo(pc_reg_lldb_regnum
, a_pc_regloc
);
378 b_first_row
->GetRegisterInfo(pc_reg_lldb_regnum
, b_pc_regloc
);
380 plans_are_identical
= eLazyBoolYes
;
382 if (a_first_row
->GetCFAValue() != b_first_row
->GetCFAValue()) {
383 plans_are_identical
= eLazyBoolNo
;
385 if (a_pc_regloc
!= b_pc_regloc
) {
386 plans_are_identical
= eLazyBoolNo
;
390 return plans_are_identical
;
393 UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtNonCallSite(Target
&target
,
395 UnwindPlanSP eh_frame_sp
= GetEHFrameUnwindPlan(target
);
397 eh_frame_sp
= GetDebugFrameUnwindPlan(target
);
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
);
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.
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
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
) {
432 if (UnwindPlanSP plan_sp
= GetSymbolFileUnwindPlan(thread
))
434 if (UnwindPlanSP plan_sp
= GetDebugFrameAugmentedUnwindPlan(target
, thread
))
436 if (UnwindPlanSP plan_sp
= GetEHFrameAugmentedUnwindPlan(target
, thread
))
438 if (UnwindPlanSP plan_sp
= GetObjectFileAugmentedUnwindPlan(target
, thread
))
444 UnwindPlanSP
FuncUnwinders::GetUnwindPlanFastUnwind(Target
&target
,
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
;
450 m_tried_unwind_fast
= true;
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();
461 return m_unwind_plan_fast_sp
;
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
;
469 m_tried_unwind_arch_default
= true;
472 ProcessSP
process_sp(thread
.CalculateProcess());
474 ABI
*abi
= process_sp
->GetABI().get();
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();
484 return m_unwind_plan_arch_default_sp
;
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
;
494 m_tried_unwind_arch_default_at_func_entry
= true;
497 ProcessSP
process_sp(thread
.CalculateProcess());
499 ABI
*abi
= process_sp
->GetABI().get();
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();
510 return m_unwind_plan_arch_default_at_func_entry_sp
;
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
;
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
;
526 const Address
&FuncUnwinders::GetFunctionStartAddress() const {
527 return m_range
.GetBaseAddress();
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
);
537 return assembly_profiler_sp
;
540 Address
FuncUnwinders::GetLSDAAddress(Target
&target
) {
543 UnwindPlanSP unwind_plan_sp
= GetEHFrameUnwindPlan(target
);
544 if (unwind_plan_sp
.get() == nullptr) {
545 unwind_plan_sp
= GetCompactUnwindUnwindPlan(target
);
547 if (unwind_plan_sp
.get() == nullptr) {
548 unwind_plan_sp
= GetObjectFileUnwindPlan(target
);
550 if (unwind_plan_sp
.get() && unwind_plan_sp
->GetLSDAAddress().IsValid()) {
551 lsda_addr
= unwind_plan_sp
->GetLSDAAddress();
556 Address
FuncUnwinders::GetPersonalityRoutinePtrAddress(Target
&target
) {
557 Address personality_addr
;
559 UnwindPlanSP unwind_plan_sp
= GetEHFrameUnwindPlan(target
);
560 if (unwind_plan_sp
.get() == nullptr) {
561 unwind_plan_sp
= GetCompactUnwindUnwindPlan(target
);
563 if (unwind_plan_sp
.get() == nullptr) {
564 unwind_plan_sp
= GetObjectFileUnwindPlan(target
);
566 if (unwind_plan_sp
.get() &&
567 unwind_plan_sp
->GetPersonalityFunctionPtr().IsValid()) {
568 personality_addr
= unwind_plan_sp
->GetPersonalityFunctionPtr();
571 return personality_addr
;