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