FuncUnwinders.cpp revision 341825
1139747Simp//===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
24Srgrimes//
34Srgrimes//                     The LLVM Compiler Infrastructure
44Srgrimes//
58876Srgrimes// This file is distributed under the University of Illinois Open Source
64Srgrimes// License. See LICENSE.TXT for details.
74Srgrimes//
84Srgrimes//===----------------------------------------------------------------------===//
94Srgrimes
104Srgrimes#include "lldb/Symbol/FuncUnwinders.h"
118876Srgrimes#include "lldb/Core/Address.h"
128876Srgrimes#include "lldb/Core/AddressRange.h"
134Srgrimes#include "lldb/Symbol/ArmUnwindInfo.h"
144Srgrimes#include "lldb/Symbol/CompactUnwindInfo.h"
158876Srgrimes#include "lldb/Symbol/DWARFCallFrameInfo.h"
164Srgrimes#include "lldb/Symbol/ObjectFile.h"
178876Srgrimes#include "lldb/Symbol/UnwindPlan.h"
184Srgrimes#include "lldb/Symbol/UnwindTable.h"
194Srgrimes#include "lldb/Target/ABI.h"
204Srgrimes#include "lldb/Target/ExecutionContext.h"
214Srgrimes#include "lldb/Target/Process.h"
228876Srgrimes#include "lldb/Target/RegisterNumber.h"
234Srgrimes#include "lldb/Target/Target.h"
244Srgrimes#include "lldb/Target/Thread.h"
254Srgrimes#include "lldb/Target/UnwindAssembly.h"
2650477Speter
274Srgrimesusing namespace lldb;
28623Srgrimesusing namespace lldb_private;
29716Swollman
3012472Sbde//------------------------------------------------
31716Swollman/// constructor
324Srgrimes//------------------------------------------------
334Srgrimes
344SrgrimesFuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
354Srgrimes    : m_unwind_table(unwind_table), m_range(range), m_mutex(),
36208509Sbz      m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(),
374Srgrimes      m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(),
38208509Sbz      m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(),
39208509Sbz      m_unwind_plan_arch_default_sp(),
40208509Sbz      m_unwind_plan_arch_default_at_func_entry_sp(),
41208509Sbz      m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
42208509Sbz      m_tried_unwind_plan_debug_frame(false),
434Srgrimes      m_tried_unwind_plan_eh_frame_augmented(false),
444Srgrimes      m_tried_unwind_plan_debug_frame_augmented(false),
454Srgrimes      m_tried_unwind_plan_compact_unwind(false),
46183360Sjhb      m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false),
4792756Salfred      m_tried_unwind_arch_default(false),
48174914Srwatson      m_tried_unwind_arch_default_at_func_entry(false),
494Srgrimes      m_first_non_prologue_insn() {}
504Srgrimes
514Srgrimes//------------------------------------------------
524Srgrimes/// destructor
534Srgrimes//------------------------------------------------
544Srgrimes
554SrgrimesFuncUnwinders::~FuncUnwinders() {}
564Srgrimes
5712472SbdeUnwindPlanSP 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
73UnwindPlanSP 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
101UnwindPlanSP 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
123UnwindPlanSP 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
146UnwindPlanSP 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
169UnwindPlanSP 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
178  // compiler that describes the prologue instructions perfectly, and sometimes
179  // the epilogue instructions too.
180  if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
181      target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
182      target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
183    m_tried_unwind_plan_eh_frame_augmented = true;
184    return m_unwind_plan_eh_frame_augmented_sp;
185  }
186
187  m_tried_unwind_plan_eh_frame_augmented = true;
188
189  UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target, current_offset);
190  if (!eh_frame_plan)
191    return m_unwind_plan_eh_frame_augmented_sp;
192
193  m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan));
194
195  // Augment the eh_frame instructions with epilogue descriptions if necessary
196  // so the UnwindPlan can be used at any instruction in the function.
197
198  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
199  if (assembly_profiler_sp) {
200    if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
201            m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) {
202      m_unwind_plan_eh_frame_augmented_sp.reset();
203    }
204  } else {
205    m_unwind_plan_eh_frame_augmented_sp.reset();
206  }
207  return m_unwind_plan_eh_frame_augmented_sp;
208}
209
210UnwindPlanSP
211FuncUnwinders::GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread,
212                                                int current_offset) {
213  std::lock_guard<std::recursive_mutex> guard(m_mutex);
214  if (m_unwind_plan_debug_frame_augmented_sp.get() ||
215      m_tried_unwind_plan_debug_frame_augmented)
216    return m_unwind_plan_debug_frame_augmented_sp;
217
218  // Only supported on x86 architectures where we get debug_frame from the
219  // compiler that describes the prologue instructions perfectly, and sometimes
220  // the epilogue instructions too.
221  if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 &&
222      target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 &&
223      target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) {
224    m_tried_unwind_plan_debug_frame_augmented = true;
225    return m_unwind_plan_debug_frame_augmented_sp;
226  }
227
228  m_tried_unwind_plan_debug_frame_augmented = true;
229
230  UnwindPlanSP debug_frame_plan =
231      GetDebugFrameUnwindPlan(target, current_offset);
232  if (!debug_frame_plan)
233    return m_unwind_plan_debug_frame_augmented_sp;
234
235  m_unwind_plan_debug_frame_augmented_sp.reset(
236      new UnwindPlan(*debug_frame_plan));
237
238  // Augment the debug_frame instructions with epilogue descriptions if
239  // necessary so the UnwindPlan can be used at any instruction in the
240  // function.
241
242  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
243  if (assembly_profiler_sp) {
244    if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite(
245            m_range, thread, *m_unwind_plan_debug_frame_augmented_sp)) {
246      m_unwind_plan_debug_frame_augmented_sp.reset();
247    }
248  } else
249    m_unwind_plan_debug_frame_augmented_sp.reset();
250  return m_unwind_plan_debug_frame_augmented_sp;
251}
252
253UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
254                                                  Thread &thread,
255                                                  int current_offset) {
256  std::lock_guard<std::recursive_mutex> guard(m_mutex);
257  if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||
258      m_unwind_table.GetAllowAssemblyEmulationUnwindPlans() == false) {
259    return m_unwind_plan_assembly_sp;
260  }
261
262  m_tried_unwind_plan_assembly = true;
263
264  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
265  if (assembly_profiler_sp) {
266    m_unwind_plan_assembly_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric));
267    if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
268            m_range, thread, *m_unwind_plan_assembly_sp)) {
269      m_unwind_plan_assembly_sp.reset();
270    }
271  }
272  return m_unwind_plan_assembly_sp;
273}
274
275// This method compares the pc unwind rule in the first row of two UnwindPlans.
276// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is
277// sp"), then it will return LazyBoolTrue.
278LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation(
279    Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) {
280  LazyBool plans_are_identical = eLazyBoolCalculate;
281
282  RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
283  uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB);
284
285  if (a.get() && b.get()) {
286    UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0);
287    UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0);
288
289    if (a_first_row.get() && b_first_row.get()) {
290      UnwindPlan::Row::RegisterLocation a_pc_regloc;
291      UnwindPlan::Row::RegisterLocation b_pc_regloc;
292
293      a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc);
294      b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc);
295
296      plans_are_identical = eLazyBoolYes;
297
298      if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) {
299        plans_are_identical = eLazyBoolNo;
300      }
301      if (a_pc_regloc != b_pc_regloc) {
302        plans_are_identical = eLazyBoolNo;
303      }
304    }
305  }
306  return plans_are_identical;
307}
308
309UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target,
310                                                       Thread &thread,
311                                                       int current_offset) {
312  UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target, current_offset);
313  if (!eh_frame_sp)
314    eh_frame_sp = GetDebugFrameUnwindPlan(target, current_offset);
315  UnwindPlanSP arch_default_at_entry_sp =
316      GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread);
317  UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread);
318  UnwindPlanSP assembly_sp =
319      GetAssemblyUnwindPlan(target, thread, current_offset);
320
321  // This point of this code is to detect when a function is using a non-
322  // standard ABI, and the eh_frame correctly describes that alternate ABI.
323  // This is addressing a specific situation on x86_64 linux systems where one
324  // function in a library pushes a value on the stack and jumps to another
325  // function.  So using an assembly instruction based unwind will not work
326  // when you're in the second function - the stack has been modified in a non-
327  // ABI way.  But we have eh_frame that correctly describes how to unwind from
328  // this location.  So we're looking to see if the initial pc register save
329  // location from the eh_frame is different from the assembly unwind, the arch
330  // default unwind, and the arch default at initial function entry.
331  //
332  // We may have eh_frame that describes the entire function -- or we may have
333  // eh_frame that only describes the unwind after the prologue has executed --
334  // so we need to check both the arch default (once the prologue has executed)
335  // and the arch default at initial function entry.  And we may be running on
336  // a target where we have only some of the assembly/arch default unwind plans
337  // available.
338
339  if (CompareUnwindPlansForIdenticalInitialPCLocation(
340          thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo &&
341      CompareUnwindPlansForIdenticalInitialPCLocation(
342          thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo &&
343      CompareUnwindPlansForIdenticalInitialPCLocation(
344          thread, assembly_sp, arch_default_sp) == eLazyBoolNo) {
345    return eh_frame_sp;
346  }
347
348  if (UnwindPlanSP plan_sp =
349          GetEHFrameAugmentedUnwindPlan(target, thread, current_offset))
350    return plan_sp;
351  if (UnwindPlanSP plan_sp =
352          GetDebugFrameAugmentedUnwindPlan(target, thread, current_offset))
353    return plan_sp;
354
355  return assembly_sp;
356}
357
358UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target,
359                                                    Thread &thread) {
360  std::lock_guard<std::recursive_mutex> guard(m_mutex);
361  if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
362    return m_unwind_plan_fast_sp;
363
364  m_tried_unwind_fast = true;
365
366  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
367  if (assembly_profiler_sp) {
368    m_unwind_plan_fast_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric));
369    if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread,
370                                                 *m_unwind_plan_fast_sp)) {
371      m_unwind_plan_fast_sp.reset();
372    }
373  }
374  return m_unwind_plan_fast_sp;
375}
376
377UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) {
378  std::lock_guard<std::recursive_mutex> guard(m_mutex);
379  if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
380    return m_unwind_plan_arch_default_sp;
381
382  m_tried_unwind_arch_default = true;
383
384  Address current_pc;
385  ProcessSP process_sp(thread.CalculateProcess());
386  if (process_sp) {
387    ABI *abi = process_sp->GetABI().get();
388    if (abi) {
389      m_unwind_plan_arch_default_sp.reset(
390          new UnwindPlan(lldb::eRegisterKindGeneric));
391      if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) {
392        m_unwind_plan_arch_default_sp.reset();
393      }
394    }
395  }
396
397  return m_unwind_plan_arch_default_sp;
398}
399
400UnwindPlanSP
401FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) {
402  std::lock_guard<std::recursive_mutex> guard(m_mutex);
403  if (m_unwind_plan_arch_default_at_func_entry_sp.get() ||
404      m_tried_unwind_arch_default_at_func_entry)
405    return m_unwind_plan_arch_default_at_func_entry_sp;
406
407  m_tried_unwind_arch_default_at_func_entry = true;
408
409  Address current_pc;
410  ProcessSP process_sp(thread.CalculateProcess());
411  if (process_sp) {
412    ABI *abi = process_sp->GetABI().get();
413    if (abi) {
414      m_unwind_plan_arch_default_at_func_entry_sp.reset(
415          new UnwindPlan(lldb::eRegisterKindGeneric));
416      if (!abi->CreateFunctionEntryUnwindPlan(
417              *m_unwind_plan_arch_default_at_func_entry_sp)) {
418        m_unwind_plan_arch_default_at_func_entry_sp.reset();
419      }
420    }
421  }
422
423  return m_unwind_plan_arch_default_at_func_entry_sp;
424}
425
426Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) {
427  std::lock_guard<std::recursive_mutex> guard(m_mutex);
428  if (m_first_non_prologue_insn.IsValid())
429    return m_first_non_prologue_insn;
430
431  ExecutionContext exe_ctx(target.shared_from_this(), false);
432  UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
433  if (assembly_profiler_sp)
434    assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx,
435                                               m_first_non_prologue_insn);
436  return m_first_non_prologue_insn;
437}
438
439const Address &FuncUnwinders::GetFunctionStartAddress() const {
440  return m_range.GetBaseAddress();
441}
442
443lldb::UnwindAssemblySP
444FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
445  UnwindAssemblySP assembly_profiler_sp;
446  ArchSpec arch;
447  if (m_unwind_table.GetArchitecture(arch)) {
448    arch.MergeFrom(target.GetArchitecture());
449    assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
450  }
451  return assembly_profiler_sp;
452}
453
454Address FuncUnwinders::GetLSDAAddress(Target &target) {
455  Address lsda_addr;
456
457  UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1);
458  if (unwind_plan_sp.get() == nullptr) {
459    unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1);
460  }
461  if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) {
462    lsda_addr = unwind_plan_sp->GetLSDAAddress();
463  }
464  return lsda_addr;
465}
466
467Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) {
468  Address personality_addr;
469
470  UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1);
471  if (unwind_plan_sp.get() == nullptr) {
472    unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1);
473  }
474  if (unwind_plan_sp.get() &&
475      unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) {
476    personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
477  }
478
479  return personality_addr;
480}
481