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/ObjectFile.h" 15 #include "lldb/Symbol/UnwindPlan.h" 16 #include "lldb/Symbol/UnwindTable.h" 17 #include "lldb/Target/ABI.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/Thread.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Target/UnwindAssembly.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 27 FuncUnwinders::FuncUnwinders 28 ( 29 UnwindTable& unwind_table, 30 UnwindAssembly *assembly_profiler, 31 AddressRange range 32 ) : 33 m_unwind_table(unwind_table), 34 m_assembly_profiler(assembly_profiler), 35 m_range(range), 36 m_mutex (Mutex::eMutexTypeNormal), 37 m_unwind_plan_call_site_sp (), 38 m_unwind_plan_non_call_site_sp (), 39 m_unwind_plan_fast_sp (), 40 m_unwind_plan_arch_default_sp (), 41 m_tried_unwind_at_call_site (false), 42 m_tried_unwind_at_non_call_site (false), 43 m_tried_unwind_fast (false), 44 m_tried_unwind_arch_default (false), 45 m_tried_unwind_arch_default_at_func_entry (false), 46 m_first_non_prologue_insn() 47 { 48 } 49 50 FuncUnwinders::~FuncUnwinders () 51 { 52 } 53 54 UnwindPlanSP 55 FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset) 56 { 57 // Lock the mutex to ensure we can always give out the most appropriate 58 // information. We want to make sure if someone requests a call site unwind 59 // plan, that they get one and don't run into a race condition where one 60 // thread has started to create the unwind plan and has put it into 61 // m_unwind_plan_call_site_sp, and have another thread enter this function 62 // and return the partially filled in m_unwind_plan_call_site_sp pointer. 63 // We also want to make sure that we lock out other unwind plans from 64 // being accessed until this one is done creating itself in case someone 65 // had some code like: 66 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) 67 // if (best_unwind_plan == NULL) 68 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) 69 Mutex::Locker locker (m_mutex); 70 if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == NULL) 71 { 72 m_tried_unwind_at_call_site = true; 73 // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a 74 // function does not cover the entire range of the function and so the FDE only lists a subset of the 75 // address range. If we try to look up the unwind info by the starting address of the function 76 // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE. We need to use the actual byte offset 77 // into the function when looking it up. 78 79 if (m_range.GetBaseAddress().IsValid()) 80 { 81 Address current_pc (m_range.GetBaseAddress ()); 82 if (current_offset != -1) 83 current_pc.SetOffset (current_pc.GetOffset() + current_offset); 84 85 DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); 86 if (eh_frame) 87 { 88 m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 89 if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp)) 90 m_unwind_plan_call_site_sp.reset(); 91 } 92 } 93 } 94 return m_unwind_plan_call_site_sp; 95 } 96 97 UnwindPlanSP 98 FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread) 99 { 100 // Lock the mutex to ensure we can always give out the most appropriate 101 // information. We want to make sure if someone requests an unwind 102 // plan, that they get one and don't run into a race condition where one 103 // thread has started to create the unwind plan and has put it into 104 // the auto_ptr member variable, and have another thread enter this function 105 // and return the partially filled pointer contained in the auto_ptr. 106 // We also want to make sure that we lock out other unwind plans from 107 // being accessed until this one is done creating itself in case someone 108 // had some code like: 109 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) 110 // if (best_unwind_plan == NULL) 111 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) 112 Mutex::Locker locker (m_mutex); 113 if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL) 114 { 115 m_tried_unwind_at_non_call_site = true; 116 m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 117 if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp)) 118 m_unwind_plan_non_call_site_sp.reset(); 119 } 120 return m_unwind_plan_non_call_site_sp; 121 } 122 123 UnwindPlanSP 124 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) 125 { 126 // Lock the mutex to ensure we can always give out the most appropriate 127 // information. We want to make sure if someone requests an unwind 128 // plan, that they get one and don't run into a race condition where one 129 // thread has started to create the unwind plan and has put it into 130 // the auto_ptr member variable, and have another thread enter this function 131 // and return the partially filled pointer contained in the auto_ptr. 132 // We also want to make sure that we lock out other unwind plans from 133 // being accessed until this one is done creating itself in case someone 134 // had some code like: 135 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) 136 // if (best_unwind_plan == NULL) 137 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) 138 Mutex::Locker locker (m_mutex); 139 if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL) 140 { 141 m_tried_unwind_fast = true; 142 m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 143 if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) 144 m_unwind_plan_fast_sp.reset(); 145 } 146 return m_unwind_plan_fast_sp; 147 } 148 149 UnwindPlanSP 150 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) 151 { 152 // Lock the mutex to ensure we can always give out the most appropriate 153 // information. We want to make sure if someone requests an unwind 154 // plan, that they get one and don't run into a race condition where one 155 // thread has started to create the unwind plan and has put it into 156 // the auto_ptr member variable, and have another thread enter this function 157 // and return the partially filled pointer contained in the auto_ptr. 158 // We also want to make sure that we lock out other unwind plans from 159 // being accessed until this one is done creating itself in case someone 160 // had some code like: 161 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) 162 // if (best_unwind_plan == NULL) 163 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) 164 Mutex::Locker locker (m_mutex); 165 if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL) 166 { 167 m_tried_unwind_arch_default = true; 168 Address current_pc; 169 Target *target = thread.CalculateTarget(); 170 if (target) 171 { 172 ABI *abi = thread.GetProcess().GetABI().get(); 173 if (abi) 174 { 175 m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 176 if (m_unwind_plan_arch_default_sp) 177 abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp); 178 } 179 } 180 } 181 182 return m_unwind_plan_arch_default_sp; 183 } 184 185 UnwindPlanSP 186 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) 187 { 188 // Lock the mutex to ensure we can always give out the most appropriate 189 // information. We want to make sure if someone requests an unwind 190 // plan, that they get one and don't run into a race condition where one 191 // thread has started to create the unwind plan and has put it into 192 // the auto_ptr member variable, and have another thread enter this function 193 // and return the partially filled pointer contained in the auto_ptr. 194 // We also want to make sure that we lock out other unwind plans from 195 // being accessed until this one is done creating itself in case someone 196 // had some code like: 197 // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) 198 // if (best_unwind_plan == NULL) 199 // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) 200 Mutex::Locker locker (m_mutex); 201 if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == NULL) 202 { 203 m_tried_unwind_arch_default_at_func_entry = true; 204 Address current_pc; 205 Target *target = thread.CalculateTarget(); 206 if (target) 207 { 208 ABI *abi = thread.GetProcess().GetABI().get(); 209 if (abi) 210 { 211 m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); 212 if (m_unwind_plan_arch_default_at_func_entry_sp) 213 abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp); 214 } 215 } 216 } 217 218 return m_unwind_plan_arch_default_sp; 219 } 220 221 222 Address& 223 FuncUnwinders::GetFirstNonPrologueInsn (Target& target) 224 { 225 if (m_first_non_prologue_insn.IsValid()) 226 return m_first_non_prologue_insn; 227 m_assembly_profiler->FirstNonPrologueInsn (m_range, target, NULL, m_first_non_prologue_insn); 228 return m_first_non_prologue_insn; 229 } 230 231 const Address& 232 FuncUnwinders::GetFunctionStartAddress () const 233 { 234 return m_range.GetBaseAddress(); 235 } 236 237