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/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/CompactUnwindInfo.h" 15 #include "lldb/Symbol/ObjectFile.h" 16 #include "lldb/Symbol/UnwindPlan.h" 17 #include "lldb/Symbol/UnwindTable.h" 18 #include "lldb/Target/ABI.h" 19 #include "lldb/Target/ExecutionContext.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Thread.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/UnwindAssembly.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 29 FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) : 30 m_unwind_table (unwind_table), 31 m_range (range), 32 m_mutex (Mutex::eMutexTypeRecursive), 33 m_unwind_plan_call_site_sp (), 34 m_unwind_plan_non_call_site_sp (), 35 m_unwind_plan_fast_sp (), 36 m_unwind_plan_arch_default_sp (), 37 m_tried_unwind_at_call_site (false), 38 m_tried_unwind_at_non_call_site (false), 39 m_tried_unwind_fast (false), 40 m_tried_unwind_arch_default (false), 41 m_tried_unwind_arch_default_at_func_entry (false), 42 m_first_non_prologue_insn () 43 { 44 } 45 46 FuncUnwinders::~FuncUnwinders () 47 { 48 } 49 50 UnwindPlanSP 51 FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset) 52 { 53 Mutex::Locker locker (m_mutex); 54 if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == nullptr) 55 { 56 m_tried_unwind_at_call_site = true; 57 58 // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a 59 // function does not cover the entire range of the function and so the FDE only lists a subset of the 60 // address range. If we try to look up the unwind info by the starting address of the function 61 // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE. We need to use the actual byte offset 62 // into the function when looking it up. 63 64 if (m_range.GetBaseAddress().IsValid()) 65 { 66 Address current_pc (m_range.GetBaseAddress ()); 67 if (current_offset != -1) 68 current_pc.SetOffset (current_pc.GetOffset() + current_offset); 69 70 CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); 71 if (compact_unwind) 72 { 73 m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 74 if (!compact_unwind->GetUnwindPlan (target, current_pc, *m_unwind_plan_call_site_sp)) 75 m_unwind_plan_call_site_sp.reset(); 76 } 77 if (m_unwind_plan_call_site_sp.get() == nullptr) 78 { 79 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); 80 if (eh_frame) 81 { 82 m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 83 if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp)) 84 m_unwind_plan_call_site_sp.reset(); 85 } 86 } 87 } 88 } 89 return m_unwind_plan_call_site_sp; 90 } 91 92 UnwindPlanSP 93 FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset) 94 { 95 Mutex::Locker locker (m_mutex); 96 if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr) 97 { 98 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); 99 if (assembly_profiler_sp) 100 { 101 if (target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_32_i386 102 || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64 103 || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h) 104 { 105 // For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler 106 // to augment it into asynchronous unwind table. 107 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); 108 if (eh_frame) 109 { 110 UnwindPlanSP unwind_plan (new UnwindPlan (lldb::eRegisterKindGeneric)); 111 if (m_range.GetBaseAddress().IsValid()) 112 { 113 Address current_pc (m_range.GetBaseAddress ()); 114 if (current_offset != -1) 115 current_pc.SetOffset (current_pc.GetOffset() + current_offset); 116 if (eh_frame->GetUnwindPlan (current_pc, *unwind_plan)) 117 { 118 if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *unwind_plan)) 119 { 120 m_unwind_plan_non_call_site_sp = unwind_plan; 121 return m_unwind_plan_non_call_site_sp; 122 } 123 } 124 } 125 } 126 } 127 128 m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 129 if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp)) 130 m_unwind_plan_non_call_site_sp.reset(); 131 } 132 } 133 return m_unwind_plan_non_call_site_sp; 134 } 135 136 UnwindPlanSP 137 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) 138 { 139 Mutex::Locker locker (m_mutex); 140 if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr) 141 { 142 m_tried_unwind_fast = true; 143 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); 144 if (assembly_profiler_sp) 145 { 146 m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 147 if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) 148 m_unwind_plan_fast_sp.reset(); 149 } 150 } 151 return m_unwind_plan_fast_sp; 152 } 153 154 UnwindPlanSP 155 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) 156 { 157 Mutex::Locker locker (m_mutex); 158 if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr) 159 { 160 m_tried_unwind_arch_default = true; 161 Address current_pc; 162 ProcessSP process_sp (thread.CalculateProcess()); 163 if (process_sp) 164 { 165 ABI *abi = process_sp->GetABI().get(); 166 if (abi) 167 { 168 m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 169 if (m_unwind_plan_arch_default_sp) 170 abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp); 171 } 172 } 173 } 174 175 return m_unwind_plan_arch_default_sp; 176 } 177 178 UnwindPlanSP 179 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) 180 { 181 Mutex::Locker locker (m_mutex); 182 if (m_tried_unwind_arch_default_at_func_entry == false 183 && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr) 184 { 185 m_tried_unwind_arch_default_at_func_entry = true; 186 Address current_pc; 187 ProcessSP process_sp (thread.CalculateProcess()); 188 if (process_sp) 189 { 190 ABI *abi = process_sp->GetABI().get(); 191 if (abi) 192 { 193 m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 194 if (m_unwind_plan_arch_default_at_func_entry_sp) 195 abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp); 196 } 197 } 198 } 199 200 return m_unwind_plan_arch_default_at_func_entry_sp; 201 } 202 203 204 Address& 205 FuncUnwinders::GetFirstNonPrologueInsn (Target& target) 206 { 207 if (m_first_non_prologue_insn.IsValid()) 208 return m_first_non_prologue_insn; 209 ExecutionContext exe_ctx (target.shared_from_this(), false); 210 UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); 211 if (assembly_profiler_sp) 212 assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn); 213 return m_first_non_prologue_insn; 214 } 215 216 const Address& 217 FuncUnwinders::GetFunctionStartAddress () const 218 { 219 return m_range.GetBaseAddress(); 220 } 221 222 lldb::UnwindAssemblySP 223 FuncUnwinders::GetUnwindAssemblyProfiler () 224 { 225 UnwindAssemblySP assembly_profiler_sp; 226 ArchSpec arch; 227 if (m_unwind_table.GetArchitecture (arch)) 228 { 229 assembly_profiler_sp = UnwindAssembly::FindPlugin (arch); 230 } 231 return assembly_profiler_sp; 232 } 233 234 Address 235 FuncUnwinders::GetLSDAAddress (Target &target) 236 { 237 Address lsda_addr; 238 Mutex::Locker locker (m_mutex); 239 240 GetUnwindPlanAtCallSite (target, -1); 241 242 if (m_unwind_plan_call_site_sp && m_unwind_plan_call_site_sp->GetLSDAAddress().IsValid()) 243 { 244 lsda_addr = m_unwind_plan_call_site_sp->GetLSDAAddress().IsValid(); 245 } 246 247 return lsda_addr; 248 } 249 250 251 Address 252 FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target) 253 { 254 Address personality_addr; 255 Mutex::Locker locker (m_mutex); 256 257 GetUnwindPlanAtCallSite (target, -1); 258 259 if (m_unwind_plan_call_site_sp && m_unwind_plan_call_site_sp->GetPersonalityFunctionPtr().IsValid()) 260 { 261 personality_addr = m_unwind_plan_call_site_sp->GetPersonalityFunctionPtr().IsValid(); 262 } 263 264 return personality_addr; 265 } 266