LLDB  mainline
FuncUnwinders.cpp
Go to the documentation of this file.
1 //===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
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"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Symbol/UnwindPlan.h"
18 #include "lldb/Target/ABI.h"
20 #include "lldb/Target/Process.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
25 
26 #include <memory>
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 /// constructor
32 
33 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
34  : m_unwind_table(unwind_table), m_range(range), m_mutex(),
35  m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(),
36  m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(),
37  m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(),
38  m_unwind_plan_arch_default_sp(),
39  m_unwind_plan_arch_default_at_func_entry_sp(),
40  m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
41  m_tried_unwind_plan_debug_frame(false),
42  m_tried_unwind_plan_eh_frame_augmented(false),
43  m_tried_unwind_plan_debug_frame_augmented(false),
44  m_tried_unwind_plan_compact_unwind(false),
45  m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false),
46  m_tried_unwind_arch_default(false),
47  m_tried_unwind_arch_default_at_func_entry(false),
48  m_first_non_prologue_insn() {}
49 
50 /// destructor
51 
53 
55  std::lock_guard<std::recursive_mutex> guard(m_mutex);
56 
57  if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target))
58  return plan_sp;
59  if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target))
60  return plan_sp;
61  if (UnwindPlanSP plan_sp = GetCompactUnwindUnwindPlan(target))
62  return plan_sp;
63  if (UnwindPlanSP plan_sp = GetArmUnwindUnwindPlan(target))
64  return plan_sp;
65 
66  return nullptr;
67 }
68 
70  std::lock_guard<std::recursive_mutex> guard(m_mutex);
71  if (m_unwind_plan_compact_unwind.size() > 0)
72  return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact
73  // unwind plans for one func
74  if (m_tried_unwind_plan_compact_unwind)
75  return UnwindPlanSP();
76 
77  m_tried_unwind_plan_compact_unwind = true;
78  if (m_range.GetBaseAddress().IsValid()) {
79  Address current_pc(m_range.GetBaseAddress());
80  CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
81  if (compact_unwind) {
82  UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric));
83  if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) {
84  m_unwind_plan_compact_unwind.push_back(unwind_plan_sp);
85  return m_unwind_plan_compact_unwind[0]; // FIXME support multiple
86  // compact unwind plans for one
87  // func
88  }
89  }
90  }
91  return UnwindPlanSP();
92 }
93 
95  std::lock_guard<std::recursive_mutex> guard(m_mutex);
96  if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)
97  return m_unwind_plan_eh_frame_sp;
98 
99  m_tried_unwind_plan_eh_frame = true;
100  if (m_range.GetBaseAddress().IsValid()) {
101  DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
102  if (eh_frame) {
103  m_unwind_plan_eh_frame_sp =
104  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
105  if (!eh_frame->GetUnwindPlan(m_range, *m_unwind_plan_eh_frame_sp))
106  m_unwind_plan_eh_frame_sp.reset();
107  }
108  }
109  return m_unwind_plan_eh_frame_sp;
110 }
111 
113  std::lock_guard<std::recursive_mutex> guard(m_mutex);
114  if (m_unwind_plan_debug_frame_sp || m_tried_unwind_plan_debug_frame)
115  return m_unwind_plan_debug_frame_sp;
116 
117  m_tried_unwind_plan_debug_frame = true;
118  if (m_range.GetBaseAddress().IsValid()) {
119  DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();
120  if (debug_frame) {
121  m_unwind_plan_debug_frame_sp =
122  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
123  if (!debug_frame->GetUnwindPlan(m_range, *m_unwind_plan_debug_frame_sp))
124  m_unwind_plan_debug_frame_sp.reset();
125  }
126  }
127  return m_unwind_plan_debug_frame_sp;
128 }
129 
131  std::lock_guard<std::recursive_mutex> guard(m_mutex);
132  if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
133  return m_unwind_plan_arm_unwind_sp;
134 
135  m_tried_unwind_plan_arm_unwind = true;
136  if (m_range.GetBaseAddress().IsValid()) {
137  Address current_pc(m_range.GetBaseAddress());
138  ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
139  if (arm_unwind_info) {
140  m_unwind_plan_arm_unwind_sp =
141  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
142  if (!arm_unwind_info->GetUnwindPlan(target, current_pc,
143  *m_unwind_plan_arm_unwind_sp))
144  m_unwind_plan_arm_unwind_sp.reset();
145  }
146  }
147  return m_unwind_plan_arm_unwind_sp;
148 }
149 
151  Thread &thread) {
152  std::lock_guard<std::recursive_mutex> guard(m_mutex);
153  if (m_unwind_plan_eh_frame_augmented_sp.get() ||
154  m_tried_unwind_plan_eh_frame_augmented)
155  return m_unwind_plan_eh_frame_augmented_sp;
156 
157  // Only supported on x86 architectures where we get eh_frame from the
158  // compiler that describes the prologue instructions perfectly, and sometimes
159  // the epilogue instructions too.
163  m_tried_unwind_plan_eh_frame_augmented = true;
164  return m_unwind_plan_eh_frame_augmented_sp;
165  }
166 
167  m_tried_unwind_plan_eh_frame_augmented = true;
168 
169  UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target);
170  if (!eh_frame_plan)
171  return m_unwind_plan_eh_frame_augmented_sp;
172 
173  m_unwind_plan_eh_frame_augmented_sp =
174  std::make_shared<UnwindPlan>(*eh_frame_plan);
175 
176  // Augment the eh_frame instructions with epilogue descriptions if necessary
177  // so the UnwindPlan can be used at any instruction in the function.
178 
179  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
180  if (assembly_profiler_sp) {
181  if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
182  m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) {
183  m_unwind_plan_eh_frame_augmented_sp.reset();
184  }
185  } else {
186  m_unwind_plan_eh_frame_augmented_sp.reset();
187  }
188  return m_unwind_plan_eh_frame_augmented_sp;
189 }
190 
192  Thread &thread) {
193  std::lock_guard<std::recursive_mutex> guard(m_mutex);
194  if (m_unwind_plan_debug_frame_augmented_sp.get() ||
195  m_tried_unwind_plan_debug_frame_augmented)
196  return m_unwind_plan_debug_frame_augmented_sp;
197 
198  // Only supported on x86 architectures where we get debug_frame from the
199  // compiler that describes the prologue instructions perfectly, and sometimes
200  // the epilogue instructions too.
204  m_tried_unwind_plan_debug_frame_augmented = true;
205  return m_unwind_plan_debug_frame_augmented_sp;
206  }
207 
208  m_tried_unwind_plan_debug_frame_augmented = true;
209 
210  UnwindPlanSP debug_frame_plan = GetDebugFrameUnwindPlan(target);
211  if (!debug_frame_plan)
212  return m_unwind_plan_debug_frame_augmented_sp;
213 
214  m_unwind_plan_debug_frame_augmented_sp =
215  std::make_shared<UnwindPlan>(*debug_frame_plan);
216 
217  // Augment the debug_frame instructions with epilogue descriptions if
218  // necessary so the UnwindPlan can be used at any instruction in the
219  // function.
220 
221  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
222  if (assembly_profiler_sp) {
223  if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
224  m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) {
225  m_unwind_plan_debug_frame_augmented_sp.reset();
226  }
227  } else
228  m_unwind_plan_debug_frame_augmented_sp.reset();
229  return m_unwind_plan_debug_frame_augmented_sp;
230 }
231 
233  Thread &thread) {
234  std::lock_guard<std::recursive_mutex> guard(m_mutex);
235  if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||
236  !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) {
237  return m_unwind_plan_assembly_sp;
238  }
239 
240  m_tried_unwind_plan_assembly = true;
241 
242  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
243  if (assembly_profiler_sp) {
244  m_unwind_plan_assembly_sp =
245  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
246  if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
247  m_range, thread, *m_unwind_plan_assembly_sp)) {
248  m_unwind_plan_assembly_sp.reset();
249  }
250  }
251  return m_unwind_plan_assembly_sp;
252 }
253 
254 // This method compares the pc unwind rule in the first row of two UnwindPlans.
255 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
256 // sp"), then it will return LazyBoolTrue.
257 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
258  Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
259  LazyBool plans_are_identical = eLazyBoolCalculate;
260 
262  uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
263 
264  if (a.get() && b.get()) {
265  UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
266  UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
267 
268  if (a_first_row.get() && b_first_row.get()) {
271 
272  a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
273  b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
274 
275  plans_are_identical = eLazyBoolYes;
276 
277  if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
278  plans_are_identical = eLazyBoolNo;
279  }
280  if (a_pc_regloc != b_pc_regloc) {
281  plans_are_identical = eLazyBoolNo;
282  }
283  }
284  }
285  return plans_are_identical;
286 }
287 
289  Thread &thread) {
290  UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target);
291  if (!eh_frame_sp)
292  eh_frame_sp = GetDebugFrameUnwindPlan(target);
293  UnwindPlanSP arch_default_at_entry_sp =
295  UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);
296  UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan(target, thread);
297 
298  // This point of this code is to detect when a function is using a non-
299  // standard ABI, and the eh_frame correctly describes that alternate ABI.
300  // This is addressing a specific situation on x86_64 linux systems where one
301  // function in a library pushes a value on the stack and jumps to another
302  // function. So using an assembly instruction based unwind will not work
303  // when you're in the second function - the stack has been modified in a non-
304  // ABI way. But we have eh_frame that correctly describes how to unwind from
305  // this location. So we're looking to see if the initial pc register save
306  // location from the eh_frame is different from the assembly unwind, the arch
307  // default unwind, and the arch default at initial function entry.
308  //
309  // We may have eh_frame that describes the entire function -- or we may have
310  // eh_frame that only describes the unwind after the prologue has executed --
311  // so we need to check both the arch default (once the prologue has executed)
312  // and the arch default at initial function entry. And we may be running on
313  // a target where we have only some of the assembly/arch default unwind plans
314  // available.
315 
316  if (CompareUnwindPlansForIdenticalInitialPCLocation(
317  thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
318  CompareUnwindPlansForIdenticalInitialPCLocation(
319  thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
320  CompareUnwindPlansForIdenticalInitialPCLocation(
321  thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {
322  return eh_frame_sp;
323  }
324 
325  if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread))
326  return plan_sp;
327  if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread))
328  return plan_sp;
329 
330  return assembly_sp;
331 }
332 
334  Thread &thread) {
335  std::lock_guard<std::recursive_mutex> guard(m_mutex);
336  if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
337  return m_unwind_plan_fast_sp;
338 
339  m_tried_unwind_fast = true;
340 
341  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
342  if (assembly_profiler_sp) {
343  m_unwind_plan_fast_sp =
344  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
345  if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
346  *m_unwind_plan_fast_sp)) {
347  m_unwind_plan_fast_sp.reset();
348  }
349  }
350  return m_unwind_plan_fast_sp;
351 }
352 
354  std::lock_guard<std::recursive_mutex> guard(m_mutex);
355  if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
356  return m_unwind_plan_arch_default_sp;
357 
358  m_tried_unwind_arch_default = true;
359 
360  Address current_pc;
361  ProcessSP process_sp(thread.CalculateProcess());
362  if (process_sp) {
363  ABI *abi = process_sp->GetABI().get();
364  if (abi) {
365  m_unwind_plan_arch_default_sp =
366  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
367  if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {
368  m_unwind_plan_arch_default_sp.reset();
369  }
370  }
371  }
372 
373  return m_unwind_plan_arch_default_sp;
374 }
375 
376 UnwindPlanSP
378  std::lock_guard<std::recursive_mutex> guard(m_mutex);
379  if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||
380  m_tried_unwind_arch_default_at_func_entry)
381  return m_unwind_plan_arch_default_at_func_entry_sp;
382 
383  m_tried_unwind_arch_default_at_func_entry = true;
384 
385  Address current_pc;
386  ProcessSP process_sp(thread.CalculateProcess());
387  if (process_sp) {
388  ABI *abi = process_sp->GetABI().get();
389  if (abi) {
390  m_unwind_plan_arch_default_at_func_entry_sp =
391  std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
393  *m_unwind_plan_arch_default_at_func_entry_sp)) {
394  m_unwind_plan_arch_default_at_func_entry_sp.reset();
395  }
396  }
397  }
398 
399  return m_unwind_plan_arch_default_at_func_entry_sp;
400 }
401 
403  std::lock_guard<std::recursive_mutex> guard(m_mutex);
404  if (m_first_non_prologue_insn.IsValid())
405  return m_first_non_prologue_insn;
406 
407  ExecutionContext exe_ctx(target.shared_from_this(), false);
408  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
409  if (assembly_profiler_sp)
410  assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
411  m_first_non_prologue_insn);
412  return m_first_non_prologue_insn;
413 }
414 
416  return m_range.GetBaseAddress();
417 }
418 
419 lldb::UnwindAssemblySP
420 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
421  UnwindAssemblySP assembly_profiler_sp;
422  if (ArchSpec arch = m_unwind_table.GetArchitecture()) {
423  arch.MergeFrom(target.GetArchitecture());
424  assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
425  }
426  return assembly_profiler_sp;
427 }
428 
430  Address lsda_addr;
431 
432  UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
433  if (unwind_plan_sp.get() == nullptr) {
434  unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
435  }
436  if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
437  lsda_addr = unwind_plan_sp->GetLSDAAddress();
438  }
439  return lsda_addr;
440 }
441 
443  Address personality_addr;
444 
445  UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target);
446  if (unwind_plan_sp.get() == nullptr) {
447  unwind_plan_sp = GetCompactUnwindUnwindPlan(target);
448  }
449  if (unwind_plan_sp.get() &&
450  unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
451  personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
452  }
453 
454  return personality_addr;
455 }
Address GetLSDAAddress(Target &target)
lldb::UnwindPlanSP GetEHFrameUnwindPlan(Target &target)
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
Core GetCore() const
Definition: ArchSpec.h:410
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const ArchSpec & GetArchitecture() const
Definition: Target.h:941
lldb_private::CompactUnwindInfo * GetCompactUnwindInfo()
virtual bool CreateDefaultUnwindPlan(UnwindPlan &unwind_plan)=0
lldb::UnwindPlanSP GetDebugFrameUnwindPlan(Target &target)
virtual bool CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan)=0
An architecture specification class.
Definition: ArchSpec.h:32
uint32_t GetAsKind(lldb::RegisterKind kind)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Address & GetFirstNonPrologueInsn(Target &target)
lldb::UnwindPlanSP GetCompactUnwindUnwindPlan(Target &target)
static lldb::UnwindAssemblySP FindPlugin(const ArchSpec &arch)
lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread)
lldb::UnwindPlanSP GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread)
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:366
lldb::UnwindPlanSP GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread)
lldb::UnwindPlanSP GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread)
lldb::UnwindPlanSP GetArmUnwindUnwindPlan(Target &target)
lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target, lldb_private::Thread &thread)
lldb::ProcessSP CalculateProcess() override
Definition: Thread.cpp:1592
A section + offset based address class.
Definition: Address.h:80
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:343
ArmUnwindInfo * GetArmUnwindInfo()
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 GetUnwindPlanAtCallSite(Target &target)
bool GetAllowAssemblyEmulationUnwindPlans()
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:220
Address GetPersonalityRoutinePtrAddress(Target &target)
const Address & GetFunctionStartAddress() const
lldb_private::DWARFCallFrameInfo * GetEHFrameInfo()
lldb::UnwindPlanSP GetUnwindPlanFastUnwind(Target &target, lldb_private::Thread &thread)
A section + offset based address range class.
Definition: AddressRange.h:32
lldb_private::DWARFCallFrameInfo * GetDebugFrameInfo()