LLDB mainline
FuncUnwinders.cpp
Go to the documentation of this file.
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
10#include "lldb/Core/Address.h"
20#include "lldb/Target/ABI.h"
22#include "lldb/Target/Process.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
28
29#include <memory>
30
31using namespace lldb;
32using namespace lldb_private;
33
34/// constructor
35
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
59
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
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
86 return UnwindPlanSP();
87
90 Address current_pc(m_range.GetBaseAddress());
92 if (compact_unwind) {
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
106 std::lock_guard<std::recursive_mutex> guard(m_mutex);
110
114 if (object_file_frame) {
116 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
117 if (!object_file_frame->GetUnwindPlan(m_range,
120 }
121 }
123}
124
126 std::lock_guard<std::recursive_mutex> guard(m_mutex);
129
133 if (eh_frame) {
135 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
138 }
139 }
141}
142
144 std::lock_guard<std::recursive_mutex> guard(m_mutex);
147
151 if (debug_frame) {
153 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
156 }
157 }
159}
160
162 std::lock_guard<std::recursive_mutex> guard(m_mutex);
165
168 Address current_pc(m_range.GetBaseAddress());
169 ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
170 if (arm_unwind_info) {
172 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
173 if (!arm_unwind_info->GetUnwindPlan(target, current_pc,
176 }
177 }
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 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
194private:
195 RegisterContext &m_ctx;
196};
197} // namespace
198
200 std::lock_guard<std::recursive_mutex> guard(m_mutex);
203
205 if (SymbolFile *symfile = m_unwind_table.GetSymbolFile()) {
206 m_unwind_plan_symbol_file_sp = symfile->GetUnwindPlan(
208 RegisterContextToInfo(*thread.GetRegisterContext()));
209 }
211}
212
215 Thread &thread) {
216 std::lock_guard<std::recursive_mutex> guard(m_mutex);
220
222
223 UnwindPlanSP object_file_unwind_plan = GetObjectFileUnwindPlan(target);
224 if (!object_file_unwind_plan)
226
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(
238 }
239 } else {
241 }
243}
244
246 Thread &thread) {
247 std::lock_guard<std::recursive_mutex> guard(m_mutex);
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.
260 }
261
263
264 UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target);
265 if (!eh_frame_plan)
267
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(
279 }
280 } else {
282 }
284}
285
287 Thread &thread) {
288 std::lock_guard<std::recursive_mutex> guard(m_mutex);
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.
301 }
302
304
305 UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target);
306 if (!debug_frame_plan)
308
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(
321 }
322 } else
325}
326
328 Thread &thread) {
329 std::lock_guard<std::recursive_mutex> guard(m_mutex);
333 }
334
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) {
350 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
351 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
352 range, thread, *m_unwind_plan_assembly_sp)) {
354 }
355 }
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.
363 Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
364 LazyBool plans_are_identical = eLazyBoolCalculate;
365
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()) {
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
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 =
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
424 thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
426 thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
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
445 Thread &thread) {
446 std::lock_guard<std::recursive_mutex> guard(m_mutex);
449
450 m_tried_unwind_fast = true;
451
452 UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
453 if (assembly_profiler_sp) {
455 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
456 if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
458 m_unwind_plan_fast_sp.reset();
459 }
460 }
462}
463
465 std::lock_guard<std::recursive_mutex> guard(m_mutex);
468
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) {
477 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
480 }
481 }
482 }
483
485}
486
489 std::lock_guard<std::recursive_mutex> guard(m_mutex);
493
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) {
502 std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
506 }
507 }
508 }
509
511}
512
514 std::lock_guard<std::recursive_mutex> guard(m_mutex);
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,
524}
525
527 return m_range.GetBaseAddress();
528}
529
532 UnwindAssemblySP assembly_profiler_sp;
534 arch.MergeFrom(target.GetArchitecture());
535 assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
536 }
537 return assembly_profiler_sp;
538}
539
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
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}
A class to represent register numbers, and able to convert between different register numbering schem...
uint32_t GetAsKind(lldb::RegisterKind kind)
virtual bool CreateDefaultUnwindPlan(UnwindPlan &unwind_plan)=0
virtual bool CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan)=0
A section + offset based address range class.
Definition: AddressRange.h:25
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:211
void SetByteSize(lldb::addr_t byte_size)
Set accessor for the byte size of this range.
Definition: AddressRange.h:239
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
Definition: AddressRange.h:223
A section + offset based address class.
Definition: Address.h:62
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:355
An architecture specification class.
Definition: ArchSpec.h:31
Core GetCore() const
Definition: ArchSpec.h:440
bool GetUnwindPlan(Target &target, const Address &addr, UnwindPlan &unwind_plan)
virtual bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan)=0
bool GetUnwindPlan(Target &target, Address addr, UnwindPlan &unwind_plan)
bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan)
Return an UnwindPlan based on the call frame information encoded in the FDE of this DWARFCallFrameInf...
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Address & GetFirstNonPrologueInsn(Target &target)
lldb::UnwindPlanSP m_unwind_plan_debug_frame_augmented_sp
lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread)
lldb::UnwindPlanSP GetEHFrameUnwindPlan(Target &target)
lldb::UnwindPlanSP GetUnwindPlanFastUnwind(Target &target, lldb_private::Thread &thread)
std::vector< lldb::UnwindPlanSP > m_unwind_plan_compact_unwind
lldb::UnwindPlanSP GetObjectFileAugmentedUnwindPlan(Target &target, Thread &thread)
Address GetLSDAAddress(Target &target)
lldb::UnwindPlanSP m_unwind_plan_object_file_sp
lldb_private::LazyBool CompareUnwindPlansForIdenticalInitialPCLocation(Thread &thread, const lldb::UnwindPlanSP &a, const lldb::UnwindPlanSP &b)
const Address & GetFunctionStartAddress() const
lldb::UnwindPlanSP m_unwind_plan_assembly_sp
lldb::UnwindPlanSP GetEHFrameAugmentedUnwindPlan(Target &target, Thread &thread)
lldb::UnwindPlanSP GetDebugFrameUnwindPlan(Target &target)
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp
lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target, lldb_private::Thread &thread)
lldb::UnwindPlanSP m_unwind_plan_debug_frame_sp
FuncUnwinders(lldb_private::UnwindTable &unwind_table, AddressRange range)
constructor
std::recursive_mutex m_mutex
lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp
lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp
lldb::UnwindPlanSP GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread)
Address GetPersonalityRoutinePtrAddress(Target &target)
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp
lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp
lldb::UnwindPlanSP GetCompactUnwindUnwindPlan(Target &target)
lldb::UnwindPlanSP GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread)
lldb::UnwindPlanSP m_unwind_plan_fast_sp
lldb::UnwindPlanSP m_unwind_plan_symbol_file_sp
lldb::UnwindAssemblySP GetUnwindAssemblyProfiler(Target &target)
lldb::UnwindPlanSP GetArmUnwindUnwindPlan(Target &target)
lldb::UnwindPlanSP GetObjectFileUnwindPlan(Target &target)
lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread)
lldb::UnwindPlanSP GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread)
lldb::UnwindPlanSP m_unwind_plan_object_file_augmented_sp
lldb::UnwindPlanSP GetSymbolFileUnwindPlan(Thread &thread)
Provides public interface for all SymbolFiles.
Definition: SymbolFile.h:50
const ArchSpec & GetArchitecture() const
Definition: Target.h:1039
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP CalculateProcess() override
Definition: Thread.cpp:1416
static lldb::UnwindAssemblySP FindPlugin(const ArchSpec &arch)
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:429
lldb_private::DWARFCallFrameInfo * GetEHFrameInfo()
bool GetAllowAssemblyEmulationUnwindPlans()
ArmUnwindInfo * GetArmUnwindInfo()
SymbolFile * GetSymbolFile()
lldb_private::DWARFCallFrameInfo * GetDebugFrameInfo()
lldb_private::CompactUnwindInfo * GetCompactUnwindInfo()
lldb_private::CallFrameInfo * GetObjectFileUnwindInfo()
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:56
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
std::shared_ptr< lldb_private::UnwindPlan > UnwindPlanSP
Definition: lldb-forward.h:483
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::UnwindAssembly > UnwindAssemblySP
Definition: lldb-forward.h:482
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...