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