FuncUnwinders.cpp revision 314564
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
27using namespace lldb;
28using namespace lldb_private;
29
30//------------------------------------------------
31/// constructor
32//------------------------------------------------
33
34FuncUnwinders::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
53FuncUnwinders::~FuncUnwinders() {}
54
55UnwindPlanSP 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
74UnwindPlanSP 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
102UnwindPlanSP 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
124UnwindPlanSP 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
147UnwindPlanSP 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
190UnwindPlanSP 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.
216LazyBool 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
247UnwindPlanSP 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
299UnwindPlanSP 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
318UnwindPlanSP 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
341UnwindPlanSP
342FuncUnwinders::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
367Address &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
380const Address &FuncUnwinders::GetFunctionStartAddress() const {
381  return m_range.GetBaseAddress();
382}
383
384lldb::UnwindAssemblySP
385FuncUnwinders::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
395Address 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
408Address 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}
422