]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
MFV r320905: Import upstream fix for CVE-2017-11103.
[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/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Target/UnwindAssembly.h"
25 #include "lldb/Utility/RegisterNumber.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_eh_frame_augmented(false),
43       m_tried_unwind_plan_compact_unwind(false),
44       m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false),
45       m_tried_unwind_arch_default(false),
46       m_tried_unwind_arch_default_at_func_entry(false),
47       m_first_non_prologue_insn() {}
48
49 //------------------------------------------------
50 /// destructor
51 //------------------------------------------------
52
53 FuncUnwinders::~FuncUnwinders() {}
54
55 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target,
56                                                     int current_offset) {
57   std::lock_guard<std::recursive_mutex> guard(m_mutex);
58
59   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, current_offset);
60   if (unwind_plan_sp)
61     return unwind_plan_sp;
62
63   unwind_plan_sp = GetCompactUnwindUnwindPlan(target, current_offset);
64   if (unwind_plan_sp)
65     return unwind_plan_sp;
66
67   unwind_plan_sp = GetArmUnwindUnwindPlan(target, current_offset);
68   if (unwind_plan_sp)
69     return unwind_plan_sp;
70
71   return nullptr;
72 }
73
74 UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target,
75                                                        int current_offset) {
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   std::lock_guard<std::recursive_mutex> guard(m_mutex);
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   if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)
105     return m_unwind_plan_eh_frame_sp;
106
107   std::lock_guard<std::recursive_mutex> guard(m_mutex);
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.reset(
116           new 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::GetArmUnwindUnwindPlan(Target &target,
125                                                    int current_offset) {
126   if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
127     return m_unwind_plan_arm_unwind_sp;
128
129   std::lock_guard<std::recursive_mutex> guard(m_mutex);
130   m_tried_unwind_plan_arm_unwind = 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     ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
136     if (arm_unwind_info) {
137       m_unwind_plan_arm_unwind_sp.reset(
138           new UnwindPlan(lldb::eRegisterKindGeneric));
139       if (!arm_unwind_info->GetUnwindPlan(target, current_pc,
140                                           *m_unwind_plan_arm_unwind_sp))
141         m_unwind_plan_arm_unwind_sp.reset();
142     }
143   }
144   return m_unwind_plan_arm_unwind_sp;
145 }
146
147 UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target,
148                                                           Thread &thread,
149                                                           int current_offset) {
150   if (m_unwind_plan_eh_frame_augmented_sp.get() ||
151       m_tried_unwind_plan_eh_frame_augmented)
152     return m_unwind_plan_eh_frame_augmented_sp;
153
154   // Only supported on x86 architectures where we get eh_frame from the compiler
155   // that describes
156   // the prologue instructions perfectly, and sometimes the epilogue
157   // instructions too.
158   if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
159       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
160       target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
161     m_tried_unwind_plan_eh_frame_augmented = true;
162     return m_unwind_plan_eh_frame_augmented_sp;
163   }
164
165   std::lock_guard<std::recursive_mutex> guard(m_mutex);
166   m_tried_unwind_plan_eh_frame_augmented = true;
167
168   UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target, current_offset);
169   if (!eh_frame_plan)
170     return m_unwind_plan_eh_frame_augmented_sp;
171
172   m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan));
173
174   // Augment the eh_frame instructions with epilogue descriptions if necessary
175   // so the
176   // UnwindPlan can be used at any instruction in the function.
177
178   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
179   if (assembly_profiler_sp) {
180     if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
181             m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) {
182       m_unwind_plan_eh_frame_augmented_sp.reset();
183     }
184   } else {
185     m_unwind_plan_eh_frame_augmented_sp.reset();
186   }
187   return m_unwind_plan_eh_frame_augmented_sp;
188 }
189
190 UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
191                                                   Thread &thread,
192                                                   int current_offset) {
193   if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||
194       m_unwind_table.GetAllowAssemblyEmulationUnwindPlans() == false) {
195     return m_unwind_plan_assembly_sp;
196   }
197
198   std::lock_guard<std::recursive_mutex> guard(m_mutex);
199   m_tried_unwind_plan_assembly = true;
200
201   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
202   if (assembly_profiler_sp) {
203     m_unwind_plan_assembly_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric));
204     if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
205             m_range, thread, *m_unwind_plan_assembly_sp)) {
206       m_unwind_plan_assembly_sp.reset();
207     }
208   }
209   return m_unwind_plan_assembly_sp;
210 }
211
212 // This method compares the pc unwind rule in the first row of two UnwindPlans.
213 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
214 // sp"),
215 // then it will return LazyBoolTrue.
216 LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
217     Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
218   LazyBool plans_are_identical = eLazyBoolCalculate;
219
220   RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
221   uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
222
223   if (a.get() && b.get()) {
224     UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
225     UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
226
227     if (a_first_row.get() && b_first_row.get()) {
228       UnwindPlan::Row::RegisterLocation a_pc_regloc;
229       UnwindPlan::Row::RegisterLocation b_pc_regloc;
230
231       a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
232       b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
233
234       plans_are_identical = eLazyBoolYes;
235
236       if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
237         plans_are_identical = eLazyBoolNo;
238       }
239       if (a_pc_regloc != b_pc_regloc) {
240         plans_are_identical = eLazyBoolNo;
241       }
242     }
243   }
244   return plans_are_identical;
245 }
246
247 UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
248                                                        Thread &thread,
249                                                        int current_offset) {
250   UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target, current_offset);
251   UnwindPlanSP arch_default_at_entry_sp =
252       GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread);
253   UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);
254   UnwindPlanSP assembly_sp =
255       GetAssemblyUnwindPlan(target, thread, current_offset);
256
257   // This point of this code is to detect when a function is using a
258   // non-standard ABI, and the eh_frame
259   // correctly describes that alternate ABI.  This is addressing a specific
260   // situation on x86_64 linux
261   // systems where one function in a library pushes a value on the stack and
262   // jumps to another function.
263   // So using an assembly instruction based unwind will not work when you're in
264   // the second function -
265   // the stack has been modified in a non-ABI way.  But we have eh_frame that
266   // correctly describes how to
267   // unwind from this location.  So we're looking to see if the initial pc
268   // register save location from
269   // the eh_frame is different from the assembly unwind, the arch default
270   // unwind, and the arch default at
271   // initial function entry.
272   //
273   // We may have eh_frame that describes the entire function -- or we may have
274   // eh_frame that only describes
275   // the unwind after the prologue has executed -- so we need to check both the
276   // arch default (once the prologue
277   // has executed) and the arch default at initial function entry.  And we may
278   // be running on a target where
279   // we have only some of the assembly/arch default unwind plans available.
280
281   if (CompareUnwindPlansForIdenticalInitialPCLocation(
282           thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
283       CompareUnwindPlansForIdenticalInitialPCLocation(
284           thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
285       CompareUnwindPlansForIdenticalInitialPCLocation(
286           thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {
287     return eh_frame_sp;
288   }
289
290   UnwindPlanSP eh_frame_augmented_sp =
291       GetEHFrameAugmentedUnwindPlan(target, thread, current_offset);
292   if (eh_frame_augmented_sp) {
293     return eh_frame_augmented_sp;
294   }
295
296   return assembly_sp;
297 }
298
299 UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target,
300                                                     Thread &thread) {
301   if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
302     return m_unwind_plan_fast_sp;
303
304   std::lock_guard<std::recursive_mutex> guard(m_mutex);
305   m_tried_unwind_fast = true;
306
307   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
308   if (assembly_profiler_sp) {
309     m_unwind_plan_fast_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric));
310     if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
311                                                  *m_unwind_plan_fast_sp)) {
312       m_unwind_plan_fast_sp.reset();
313     }
314   }
315   return m_unwind_plan_fast_sp;
316 }
317
318 UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) {
319   if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
320     return m_unwind_plan_arch_default_sp;
321
322   std::lock_guard<std::recursive_mutex> guard(m_mutex);
323   m_tried_unwind_arch_default = true;
324
325   Address current_pc;
326   ProcessSP process_sp(thread.CalculateProcess());
327   if (process_sp) {
328     ABI *abi = process_sp->GetABI().get();
329     if (abi) {
330       m_unwind_plan_arch_default_sp.reset(
331           new UnwindPlan(lldb::eRegisterKindGeneric));
332       if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {
333         m_unwind_plan_arch_default_sp.reset();
334       }
335     }
336   }
337
338   return m_unwind_plan_arch_default_sp;
339 }
340
341 UnwindPlanSP
342 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
343   if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||
344       m_tried_unwind_arch_default_at_func_entry)
345     return m_unwind_plan_arch_default_at_func_entry_sp;
346
347   std::lock_guard<std::recursive_mutex> guard(m_mutex);
348   m_tried_unwind_arch_default_at_func_entry = true;
349
350   Address current_pc;
351   ProcessSP process_sp(thread.CalculateProcess());
352   if (process_sp) {
353     ABI *abi = process_sp->GetABI().get();
354     if (abi) {
355       m_unwind_plan_arch_default_at_func_entry_sp.reset(
356           new UnwindPlan(lldb::eRegisterKindGeneric));
357       if (!abi->CreateFunctionEntryUnwindPlan(
358               *m_unwind_plan_arch_default_at_func_entry_sp)) {
359         m_unwind_plan_arch_default_at_func_entry_sp.reset();
360       }
361     }
362   }
363
364   return m_unwind_plan_arch_default_at_func_entry_sp;
365 }
366
367 Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
368   if (m_first_non_prologue_insn.IsValid())
369     return m_first_non_prologue_insn;
370
371   std::lock_guard<std::recursive_mutex> guard(m_mutex);
372   ExecutionContext exe_ctx(target.shared_from_this(), false);
373   UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
374   if (assembly_profiler_sp)
375     assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
376                                                m_first_non_prologue_insn);
377   return m_first_non_prologue_insn;
378 }
379
380 const Address &FuncUnwinders::GetFunctionStartAddress() const {
381   return m_range.GetBaseAddress();
382 }
383
384 lldb::UnwindAssemblySP
385 FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
386   UnwindAssemblySP assembly_profiler_sp;
387   ArchSpec arch;
388   if (m_unwind_table.GetArchitecture(arch)) {
389     arch.MergeFrom(target.GetArchitecture());
390     assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
391   }
392   return assembly_profiler_sp;
393 }
394
395 Address FuncUnwinders::GetLSDAAddress(Target &target) {
396   Address lsda_addr;
397
398   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1);
399   if (unwind_plan_sp.get() == nullptr) {
400     unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1);
401   }
402   if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
403     lsda_addr = unwind_plan_sp->GetLSDAAddress();
404   }
405   return lsda_addr;
406 }
407
408 Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
409   Address personality_addr;
410
411   UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1);
412   if (unwind_plan_sp.get() == nullptr) {
413     unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1);
414   }
415   if (unwind_plan_sp.get() &&
416       unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
417     personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
418   }
419
420   return personality_addr;
421 }