1 //===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Core/AddressRange.h"
11 #include "lldb/Core/Address.h"
12 #include "lldb/Symbol/FuncUnwinders.h"
13 #include "lldb/Symbol/ArmUnwindInfo.h"
14 #include "lldb/Symbol/DWARFCallFrameInfo.h"
15 #include "lldb/Symbol/CompactUnwindInfo.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/Thread.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/UnwindAssembly.h"
25 #include "lldb/Utility/RegisterNumber.h"
28 using namespace lldb_private;
30 //------------------------------------------------
32 //------------------------------------------------
34 FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
35 : m_unwind_table(unwind_table),
38 m_unwind_plan_assembly_sp(),
39 m_unwind_plan_eh_frame_sp(),
40 m_unwind_plan_eh_frame_augmented_sp(),
41 m_unwind_plan_compact_unwind(),
42 m_unwind_plan_arm_unwind_sp(),
43 m_unwind_plan_fast_sp(),
44 m_unwind_plan_arch_default_sp(),
45 m_unwind_plan_arch_default_at_func_entry_sp(),
46 m_tried_unwind_plan_assembly(false),
47 m_tried_unwind_plan_eh_frame(false),
48 m_tried_unwind_plan_eh_frame_augmented(false),
49 m_tried_unwind_plan_compact_unwind(false),
50 m_tried_unwind_plan_arm_unwind(false),
51 m_tried_unwind_fast(false),
52 m_tried_unwind_arch_default(false),
53 m_tried_unwind_arch_default_at_func_entry(false),
54 m_first_non_prologue_insn()
58 //------------------------------------------------
60 //------------------------------------------------
62 FuncUnwinders::~FuncUnwinders ()
67 FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset)
69 std::lock_guard<std::recursive_mutex> guard(m_mutex);
71 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset);
73 return unwind_plan_sp;
75 unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
77 return unwind_plan_sp;
79 unwind_plan_sp = GetArmUnwindUnwindPlan (target, current_offset);
81 return unwind_plan_sp;
87 FuncUnwinders::GetCompactUnwindUnwindPlan (Target &target, int current_offset)
89 if (m_unwind_plan_compact_unwind.size() > 0)
90 return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func
91 if (m_tried_unwind_plan_compact_unwind)
92 return UnwindPlanSP();
94 std::lock_guard<std::recursive_mutex> guard(m_mutex);
95 m_tried_unwind_plan_compact_unwind = true;
96 if (m_range.GetBaseAddress().IsValid())
98 Address current_pc (m_range.GetBaseAddress ());
99 if (current_offset != -1)
100 current_pc.SetOffset (current_pc.GetOffset() + current_offset);
101 CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo();
104 UnwindPlanSP unwind_plan_sp (new UnwindPlan (lldb::eRegisterKindGeneric));
105 if (compact_unwind->GetUnwindPlan (target, current_pc, *unwind_plan_sp))
107 m_unwind_plan_compact_unwind.push_back (unwind_plan_sp);
108 return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func
112 return UnwindPlanSP();
116 FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset)
118 if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame)
119 return m_unwind_plan_eh_frame_sp;
121 std::lock_guard<std::recursive_mutex> guard(m_mutex);
122 m_tried_unwind_plan_eh_frame = true;
123 if (m_range.GetBaseAddress().IsValid())
125 Address current_pc (m_range.GetBaseAddress ());
126 if (current_offset != -1)
127 current_pc.SetOffset (current_pc.GetOffset() + current_offset);
128 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
131 m_unwind_plan_eh_frame_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
132 if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_sp))
133 m_unwind_plan_eh_frame_sp.reset();
136 return m_unwind_plan_eh_frame_sp;
140 FuncUnwinders::GetArmUnwindUnwindPlan (Target &target, int current_offset)
142 if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
143 return m_unwind_plan_arm_unwind_sp;
145 std::lock_guard<std::recursive_mutex> guard(m_mutex);
146 m_tried_unwind_plan_arm_unwind = true;
147 if (m_range.GetBaseAddress().IsValid())
149 Address current_pc (m_range.GetBaseAddress ());
150 if (current_offset != -1)
151 current_pc.SetOffset (current_pc.GetOffset() + current_offset);
152 ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
155 m_unwind_plan_arm_unwind_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
156 if (!arm_unwind_info->GetUnwindPlan (target, current_pc, *m_unwind_plan_arm_unwind_sp))
157 m_unwind_plan_arm_unwind_sp.reset();
160 return m_unwind_plan_arm_unwind_sp;
164 FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset)
166 if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented)
167 return m_unwind_plan_eh_frame_augmented_sp;
169 // Only supported on x86 architectures where we get eh_frame from the compiler that describes
170 // the prologue instructions perfectly, and sometimes the epilogue instructions too.
171 if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386
172 && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64
173 && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h)
175 m_tried_unwind_plan_eh_frame_augmented = true;
176 return m_unwind_plan_eh_frame_augmented_sp;
179 std::lock_guard<std::recursive_mutex> guard(m_mutex);
180 m_tried_unwind_plan_eh_frame_augmented = true;
182 UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan (target, current_offset);
184 return m_unwind_plan_eh_frame_augmented_sp;
186 m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan));
188 // Augment the eh_frame instructions with epilogue descriptions if necessary so the
189 // UnwindPlan can be used at any instruction in the function.
191 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target));
192 if (assembly_profiler_sp)
194 if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *m_unwind_plan_eh_frame_augmented_sp))
196 m_unwind_plan_eh_frame_augmented_sp.reset();
201 m_unwind_plan_eh_frame_augmented_sp.reset();
203 return m_unwind_plan_eh_frame_augmented_sp;
208 FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset)
210 if (m_unwind_plan_assembly_sp.get()
211 || m_tried_unwind_plan_assembly
212 || m_unwind_table.GetAllowAssemblyEmulationUnwindPlans () == false)
214 return m_unwind_plan_assembly_sp;
217 std::lock_guard<std::recursive_mutex> guard(m_mutex);
218 m_tried_unwind_plan_assembly = true;
220 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target));
221 if (assembly_profiler_sp)
223 m_unwind_plan_assembly_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
224 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_assembly_sp))
226 m_unwind_plan_assembly_sp.reset();
229 return m_unwind_plan_assembly_sp;
232 // This method compares the pc unwind rule in the first row of two UnwindPlans.
233 // If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is sp"),
234 // then it will return LazyBoolTrue.
236 FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation (Thread& thread, const UnwindPlanSP &a, const UnwindPlanSP &b)
238 LazyBool plans_are_identical = eLazyBoolCalculate;
240 RegisterNumber pc_reg (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
241 uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind (eRegisterKindLLDB);
243 if (a.get() && b.get())
245 UnwindPlan::RowSP a_first_row = a->GetRowAtIndex (0);
246 UnwindPlan::RowSP b_first_row = b->GetRowAtIndex (0);
248 if (a_first_row.get() && b_first_row.get())
250 UnwindPlan::Row::RegisterLocation a_pc_regloc;
251 UnwindPlan::Row::RegisterLocation b_pc_regloc;
253 a_first_row->GetRegisterInfo (pc_reg_lldb_regnum, a_pc_regloc);
254 b_first_row->GetRegisterInfo (pc_reg_lldb_regnum, b_pc_regloc);
256 plans_are_identical = eLazyBoolYes;
258 if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue())
260 plans_are_identical = eLazyBoolNo;
262 if (a_pc_regloc != b_pc_regloc)
264 plans_are_identical = eLazyBoolNo;
268 return plans_are_identical;
272 FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset)
274 UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan (target, current_offset);
275 UnwindPlanSP arch_default_at_entry_sp = GetUnwindPlanArchitectureDefaultAtFunctionEntry (thread);
276 UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault (thread);
277 UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan (target, thread, current_offset);
279 // This point of this code is to detect when a function is using a non-standard ABI, and the eh_frame
280 // correctly describes that alternate ABI. This is addressing a specific situation on x86_64 linux
281 // systems where one function in a library pushes a value on the stack and jumps to another function.
282 // So using an assembly instruction based unwind will not work when you're in the second function -
283 // the stack has been modified in a non-ABI way. But we have eh_frame that correctly describes how to
284 // unwind from this location. So we're looking to see if the initial pc register save location from
285 // the eh_frame is different from the assembly unwind, the arch default unwind, and the arch default at
286 // initial function entry.
288 // We may have eh_frame that describes the entire function -- or we may have eh_frame that only describes
289 // the unwind after the prologue has executed -- so we need to check both the arch default (once the prologue
290 // has executed) and the arch default at initial function entry. And we may be running on a target where
291 // we have only some of the assembly/arch default unwind plans available.
293 if (CompareUnwindPlansForIdenticalInitialPCLocation (thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo
294 && CompareUnwindPlansForIdenticalInitialPCLocation (thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo
295 && CompareUnwindPlansForIdenticalInitialPCLocation (thread, assembly_sp, arch_default_sp) == eLazyBoolNo)
300 UnwindPlanSP eh_frame_augmented_sp = GetEHFrameAugmentedUnwindPlan (target, thread, current_offset);
301 if (eh_frame_augmented_sp)
303 return eh_frame_augmented_sp;
310 FuncUnwinders::GetUnwindPlanFastUnwind (Target& target, Thread& thread)
312 if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast)
313 return m_unwind_plan_fast_sp;
315 std::lock_guard<std::recursive_mutex> guard(m_mutex);
316 m_tried_unwind_fast = true;
318 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target));
319 if (assembly_profiler_sp)
321 m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
322 if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
324 m_unwind_plan_fast_sp.reset();
327 return m_unwind_plan_fast_sp;
331 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
333 if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default)
334 return m_unwind_plan_arch_default_sp;
336 std::lock_guard<std::recursive_mutex> guard(m_mutex);
337 m_tried_unwind_arch_default = true;
340 ProcessSP process_sp (thread.CalculateProcess());
343 ABI *abi = process_sp->GetABI().get();
346 m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
347 if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp))
349 m_unwind_plan_arch_default_sp.reset();
354 return m_unwind_plan_arch_default_sp;
358 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
360 if (m_unwind_plan_arch_default_at_func_entry_sp.get() || m_tried_unwind_arch_default_at_func_entry)
361 return m_unwind_plan_arch_default_at_func_entry_sp;
363 std::lock_guard<std::recursive_mutex> guard(m_mutex);
364 m_tried_unwind_arch_default_at_func_entry = true;
367 ProcessSP process_sp (thread.CalculateProcess());
370 ABI *abi = process_sp->GetABI().get();
373 m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
374 if (!abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp))
376 m_unwind_plan_arch_default_at_func_entry_sp.reset();
381 return m_unwind_plan_arch_default_at_func_entry_sp;
386 FuncUnwinders::GetFirstNonPrologueInsn (Target& target)
388 if (m_first_non_prologue_insn.IsValid())
389 return m_first_non_prologue_insn;
391 std::lock_guard<std::recursive_mutex> guard(m_mutex);
392 ExecutionContext exe_ctx (target.shared_from_this(), false);
393 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target));
394 if (assembly_profiler_sp)
395 assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
396 return m_first_non_prologue_insn;
400 FuncUnwinders::GetFunctionStartAddress () const
402 return m_range.GetBaseAddress();
405 lldb::UnwindAssemblySP
406 FuncUnwinders::GetUnwindAssemblyProfiler (Target& target)
408 UnwindAssemblySP assembly_profiler_sp;
410 if (m_unwind_table.GetArchitecture (arch))
412 arch.MergeFrom (target.GetArchitecture ());
413 assembly_profiler_sp = UnwindAssembly::FindPlugin (arch);
415 return assembly_profiler_sp;
419 FuncUnwinders::GetLSDAAddress (Target &target)
423 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1);
424 if (unwind_plan_sp.get() == nullptr)
426 unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1);
428 if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid())
430 lsda_addr = unwind_plan_sp->GetLSDAAddress();
437 FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target)
439 Address personality_addr;
441 UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1);
442 if (unwind_plan_sp.get() == nullptr)
444 unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1);
446 if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid())
448 personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr();
451 return personality_addr;