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