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"
11 #include "lldb/Core/AddressRange.h"
16 #include "lldb/Symbol/ObjectFile.h"
17 #include "lldb/Symbol/SymbolFile.h"
18 #include "lldb/Symbol/UnwindPlan.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 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 /// constructor
35 
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() {}
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 
89  if (m_range.GetBaseAddress().IsValid()) {
90  Address current_pc(m_range.GetBaseAddress());
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 
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() ||
110 
112  if (m_range.GetBaseAddress().IsValid()) {
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 
131  if (m_range.GetBaseAddress().IsValid()) {
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 
149  if (m_range.GetBaseAddress().IsValid()) {
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 
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) {
172  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
173  if (!arm_unwind_info->GetUnwindPlan(target, current_pc,
176  }
177  }
179 }
180 
181 namespace {
182 class RegisterContextToInfo: public SymbolFile::RegisterInfoResolver {
183 public:
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 
194 private:
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 
213 UnwindPlanSP
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  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
338  if (assembly_profiler_sp) {
340  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
341  if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
342  m_range, thread, *m_unwind_plan_assembly_sp)) {
344  }
345  }
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.
353  Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
354  LazyBool plans_are_identical = eLazyBoolCalculate;
355 
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()) {
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 
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 =
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 
414  thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
416  thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
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 
435  Thread &thread) {
436  std::lock_guard<std::recursive_mutex> guard(m_mutex);
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) {
445  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
446  if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
448  m_unwind_plan_fast_sp.reset();
449  }
450  }
451  return m_unwind_plan_fast_sp;
452 }
453 
455  std::lock_guard<std::recursive_mutex> guard(m_mutex);
458 
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) {
467  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
470  }
471  }
472  }
473 
475 }
476 
477 UnwindPlanSP
479  std::lock_guard<std::recursive_mutex> guard(m_mutex);
483 
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) {
492  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
496  }
497  }
498  }
499 
501 }
502 
504  std::lock_guard<std::recursive_mutex> guard(m_mutex);
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,
514 }
515 
517  return m_range.GetBaseAddress();
518 }
519 
520 lldb::UnwindAssemblySP
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 
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 
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 }
Address GetLSDAAddress(Target &target)
lldb::UnwindPlanSP GetEHFrameUnwindPlan(Target &target)
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
lldb::UnwindPlanSP m_unwind_plan_fast_sp
Core GetCore() const
Definition: ArchSpec.h:413
A class that represents a running process on the host machine.
lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp
const ArchSpec & GetArchitecture() const
Definition: Target.h:942
insn ptr reg, stack ptr reg, etc not specific to any particular target
lldb_private::CompactUnwindInfo * GetCompactUnwindInfo()
virtual bool CreateDefaultUnwindPlan(UnwindPlan &unwind_plan)=0
lldb::UnwindPlanSP GetDebugFrameUnwindPlan(Target &target)
SymbolFile * GetSymbolFile()
virtual bool CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan)=0
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp
An architecture specification class.
Definition: ArchSpec.h:33
lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp
uint32_t GetAsKind(lldb::RegisterKind kind)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Address & GetFirstNonPrologueInsn(Target &target)
lldb::UnwindPlanSP m_unwind_plan_symbol_file_sp
lldb::UnwindPlanSP GetCompactUnwindUnwindPlan(Target &target)
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp
static lldb::UnwindAssemblySP FindPlugin(const ArchSpec &arch)
lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread)
lldb::UnwindAssemblySP GetUnwindAssemblyProfiler(Target &target)
lldb::UnwindPlanSP GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread)
RegisterKind
Register numbering types.
lldb&#39;s internal register numbers
lldb::UnwindPlanSP m_unwind_plan_debug_frame_sp
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:377
lldb_private::CallFrameInfo * GetObjectFileUnwindInfo()
lldb::UnwindPlanSP GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread)
lldb::UnwindPlanSP GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread)
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::UnwindPlanSP GetSymbolFileUnwindPlan(Thread &thread)
lldb::UnwindPlanSP GetArmUnwindUnwindPlan(Target &target)
lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target, lldb_private::Thread &thread)
lldb::ProcessSP CalculateProcess() override
Definition: Thread.cpp:1398
std::recursive_mutex m_mutex
lldb::UnwindPlanSP m_unwind_plan_debug_frame_augmented_sp
A section + offset based address class.
Definition: Address.h:59
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:332
ArmUnwindInfo * GetArmUnwindInfo()
lldb::UnwindPlanSP GetObjectFileAugmentedUnwindPlan(Target &target, Thread &thread)
lldb::UnwindPlanSP m_unwind_plan_object_file_augmented_sp
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::UnwindPlanSP m_unwind_plan_object_file_sp
bool GetAllowAssemblyEmulationUnwindPlans()
std::vector< lldb::UnwindPlanSP > m_unwind_plan_compact_unwind
Definition: SBAddress.h:15
lldb::UnwindPlanSP GetEHFrameAugmentedUnwindPlan(Target &target, Thread &thread)
A class to represent register numbers, and able to convert between different register numbering schem...
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:210
lldb::UnwindPlanSP m_unwind_plan_assembly_sp
lldb_private::LazyBool CompareUnwindPlansForIdenticalInitialPCLocation(Thread &thread, const lldb::UnwindPlanSP &a, const lldb::UnwindPlanSP &b)
Address GetPersonalityRoutinePtrAddress(Target &target)
virtual bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan)=0
const Address & GetFunctionStartAddress() const
lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp
lldb_private::DWARFCallFrameInfo * GetEHFrameInfo()
lldb::UnwindPlanSP GetUnwindPlanFastUnwind(Target &target, lldb_private::Thread &thread)
A section + offset based address range class.
Definition: AddressRange.h:25
lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread)
lldb_private::DWARFCallFrameInfo * GetDebugFrameInfo()
lldb::UnwindPlanSP GetObjectFileUnwindPlan(Target &target)