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/DWARFCallFrameInfo.h"
14 #include "lldb/Symbol/ObjectFile.h"
15 #include "lldb/Symbol/UnwindPlan.h"
16 #include "lldb/Symbol/UnwindTable.h"
17 #include "lldb/Target/ABI.h"
18 #include "lldb/Target/ExecutionContext.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/Thread.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/UnwindAssembly.h"
25 using namespace lldb_private;
28 FuncUnwinders::FuncUnwinders
30 UnwindTable& unwind_table,
33 m_unwind_table(unwind_table),
35 m_mutex (Mutex::eMutexTypeRecursive),
36 m_unwind_plan_call_site_sp (),
37 m_unwind_plan_non_call_site_sp (),
38 m_unwind_plan_fast_sp (),
39 m_unwind_plan_arch_default_sp (),
40 m_tried_unwind_at_call_site (false),
41 m_tried_unwind_at_non_call_site (false),
42 m_tried_unwind_fast (false),
43 m_tried_unwind_arch_default (false),
44 m_tried_unwind_arch_default_at_func_entry (false),
45 m_first_non_prologue_insn()
49 FuncUnwinders::~FuncUnwinders ()
54 FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
56 // Lock the mutex to ensure we can always give out the most appropriate
57 // information. We want to make sure if someone requests a call site unwind
58 // plan, that they get one and don't run into a race condition where one
59 // thread has started to create the unwind plan and has put it into
60 // m_unwind_plan_call_site_sp, and have another thread enter this function
61 // and return the partially filled in m_unwind_plan_call_site_sp pointer.
62 // We also want to make sure that we lock out other unwind plans from
63 // being accessed until this one is done creating itself in case someone
64 // had some code like:
65 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
66 // if (best_unwind_plan == NULL)
67 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
68 Mutex::Locker locker (m_mutex);
69 if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == nullptr)
71 m_tried_unwind_at_call_site = true;
72 // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a
73 // function does not cover the entire range of the function and so the FDE only lists a subset of the
74 // address range. If we try to look up the unwind info by the starting address of the function
75 // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE. We need to use the actual byte offset
76 // into the function when looking it up.
78 if (m_range.GetBaseAddress().IsValid())
80 Address current_pc (m_range.GetBaseAddress ());
81 if (current_offset != -1)
82 current_pc.SetOffset (current_pc.GetOffset() + current_offset);
84 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
87 m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
88 if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
89 m_unwind_plan_call_site_sp.reset();
93 return m_unwind_plan_call_site_sp;
97 FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset)
99 // Lock the mutex to ensure we can always give out the most appropriate
100 // information. We want to make sure if someone requests an unwind
101 // plan, that they get one and don't run into a race condition where one
102 // thread has started to create the unwind plan and has put it into
103 // the unique pointer member variable, and have another thread enter this function
104 // and return the partially filled pointer contained in the unique pointer.
105 // We also want to make sure that we lock out other unwind plans from
106 // being accessed until this one is done creating itself in case someone
107 // had some code like:
108 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
109 // if (best_unwind_plan == NULL)
110 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
111 Mutex::Locker locker (m_mutex);
112 if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr)
114 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
115 if (assembly_profiler_sp)
117 if (target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_32_i386
118 || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64
119 || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h)
121 // For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler
122 // to augment it into asynchronous unwind table.
123 GetUnwindPlanAtCallSite(current_offset);
124 if (m_unwind_plan_call_site_sp) {
125 UnwindPlan* plan = new UnwindPlan (*m_unwind_plan_call_site_sp);
126 if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *plan)) {
127 m_unwind_plan_non_call_site_sp.reset (plan);
128 return m_unwind_plan_non_call_site_sp;
133 m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
134 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp))
135 m_unwind_plan_non_call_site_sp.reset();
138 return m_unwind_plan_non_call_site_sp;
142 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
144 // Lock the mutex to ensure we can always give out the most appropriate
145 // information. We want to make sure if someone requests an unwind
146 // plan, that they get one and don't run into a race condition where one
147 // thread has started to create the unwind plan and has put it into
148 // the unique pointer member variable, and have another thread enter this function
149 // and return the partially filled pointer contained in the unique pointer.
150 // We also want to make sure that we lock out other unwind plans from
151 // being accessed until this one is done creating itself in case someone
152 // had some code like:
153 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
154 // if (best_unwind_plan == NULL)
155 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
156 Mutex::Locker locker (m_mutex);
157 if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr)
159 m_tried_unwind_fast = true;
160 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
161 if (assembly_profiler_sp)
163 m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
164 if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
165 m_unwind_plan_fast_sp.reset();
168 return m_unwind_plan_fast_sp;
172 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
174 // Lock the mutex to ensure we can always give out the most appropriate
175 // information. We want to make sure if someone requests an unwind
176 // plan, that they get one and don't run into a race condition where one
177 // thread has started to create the unwind plan and has put it into
178 // the unique pointer member variable, and have another thread enter this function
179 // and return the partially filled pointer contained in the unique pointer.
180 // We also want to make sure that we lock out other unwind plans from
181 // being accessed until this one is done creating itself in case someone
182 // had some code like:
183 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
184 // if (best_unwind_plan == NULL)
185 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
186 Mutex::Locker locker (m_mutex);
187 if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr)
189 m_tried_unwind_arch_default = true;
191 ProcessSP process_sp (thread.CalculateProcess());
194 ABI *abi = process_sp->GetABI().get();
197 m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
198 if (m_unwind_plan_arch_default_sp)
199 abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp);
204 return m_unwind_plan_arch_default_sp;
208 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
210 // Lock the mutex to ensure we can always give out the most appropriate
211 // information. We want to make sure if someone requests an unwind
212 // plan, that they get one and don't run into a race condition where one
213 // thread has started to create the unwind plan and has put it into
214 // the unique pointer member variable, and have another thread enter this function
215 // and return the partially filled pointer contained in the unique pointer.
216 // We also want to make sure that we lock out other unwind plans from
217 // being accessed until this one is done creating itself in case someone
218 // had some code like:
219 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
220 // if (best_unwind_plan == NULL)
221 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
222 Mutex::Locker locker (m_mutex);
223 if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr)
225 m_tried_unwind_arch_default_at_func_entry = true;
227 ProcessSP process_sp (thread.CalculateProcess());
230 ABI *abi = process_sp->GetABI().get();
233 m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
234 if (m_unwind_plan_arch_default_at_func_entry_sp)
235 abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp);
240 return m_unwind_plan_arch_default_at_func_entry_sp;
245 FuncUnwinders::GetFirstNonPrologueInsn (Target& target)
247 if (m_first_non_prologue_insn.IsValid())
248 return m_first_non_prologue_insn;
249 ExecutionContext exe_ctx (target.shared_from_this(), false);
250 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
251 if (assembly_profiler_sp)
252 if (assembly_profiler_sp)
253 assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
254 return m_first_non_prologue_insn;
258 FuncUnwinders::GetFunctionStartAddress () const
260 return m_range.GetBaseAddress();
264 FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread)
266 UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread);
267 if (arch_default && m_tried_unwind_at_call_site)
269 m_unwind_plan_call_site_sp = arch_default;
273 lldb::UnwindAssemblySP
274 FuncUnwinders::GetUnwindAssemblyProfiler ()
276 UnwindAssemblySP assembly_profiler_sp;
278 if (m_unwind_table.GetArchitecture (arch))
280 assembly_profiler_sp = UnwindAssembly::FindPlugin (arch);
282 return assembly_profiler_sp;