Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 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 | |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 10 | #include "lldb/Core/AddressRange.h" |
| 11 | #include "lldb/Core/Address.h" |
Greg Clayton | 97eecb1 | 2011-04-25 18:36:36 +0000 | [diff] [blame] | 12 | #include "lldb/Symbol/FuncUnwinders.h" |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 13 | #include "lldb/Symbol/DWARFCallFrameInfo.h" |
Greg Clayton | 97eecb1 | 2011-04-25 18:36:36 +0000 | [diff] [blame] | 14 | #include "lldb/Symbol/ObjectFile.h" |
| 15 | #include "lldb/Symbol/UnwindPlan.h" |
| 16 | #include "lldb/Symbol/UnwindTable.h" |
Greg Clayton | 75906e4 | 2011-05-11 18:39:18 +0000 | [diff] [blame] | 17 | #include "lldb/Target/ABI.h" |
| 18 | #include "lldb/Target/Process.h" |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 19 | #include "lldb/Target/Thread.h" |
| 20 | #include "lldb/Target/Target.h" |
Greg Clayton | 8badcb2 | 2011-04-25 21:14:26 +0000 | [diff] [blame] | 21 | #include "lldb/Target/UnwindAssembly.h" |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 22 | |
| 23 | using namespace lldb; |
| 24 | using namespace lldb_private; |
| 25 | |
| 26 | |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 27 | FuncUnwinders::FuncUnwinders |
| 28 | ( |
| 29 | UnwindTable& unwind_table, |
Greg Clayton | 8badcb2 | 2011-04-25 21:14:26 +0000 | [diff] [blame] | 30 | UnwindAssembly *assembly_profiler, |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 31 | AddressRange range |
| 32 | ) : |
| 33 | m_unwind_table(unwind_table), |
| 34 | m_assembly_profiler(assembly_profiler), |
| 35 | m_range(range), |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 36 | m_mutex (Mutex::eMutexTypeNormal), |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 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 (), |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 41 | m_tried_unwind_at_call_site (false), |
| 42 | m_tried_unwind_at_non_call_site (false), |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 43 | m_tried_unwind_fast (false), |
| 44 | m_tried_unwind_arch_default (false), |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 45 | m_first_non_prologue_insn() |
| 46 | { |
| 47 | } |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 48 | |
| 49 | FuncUnwinders::~FuncUnwinders () |
| 50 | { |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 51 | } |
| 52 | |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 53 | UnwindPlanSP |
Jason Molenda | e4b0784 | 2010-11-12 05:23:10 +0000 | [diff] [blame] | 54 | FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset) |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 55 | { |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 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 |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 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. |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 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); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 69 | if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == NULL) |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 70 | { |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 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. |
| 77 | |
| 78 | if (m_range.GetBaseAddress().IsValid()) |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 79 | { |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 80 | Address current_pc (m_range.GetBaseAddress ()); |
| 81 | if (current_offset != -1) |
| 82 | current_pc.SetOffset (current_pc.GetOffset() + current_offset); |
| 83 | |
| 84 | DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); |
| 85 | if (eh_frame) |
| 86 | { |
Greg Clayton | 75906e4 | 2011-05-11 18:39:18 +0000 | [diff] [blame] | 87 | m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 88 | if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp)) |
| 89 | m_unwind_plan_call_site_sp.reset(); |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 90 | } |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 91 | } |
| 92 | } |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 93 | return m_unwind_plan_call_site_sp; |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 94 | } |
| 95 | |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 96 | UnwindPlanSP |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 97 | FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread) |
| 98 | { |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 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 auto_ptr member variable, and have another thread enter this function |
| 104 | // and return the partially filled pointer contained in the auto_ptr. |
| 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); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 112 | if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL) |
Jason Molenda | 8280cbe | 2010-10-25 11:12:07 +0000 | [diff] [blame] | 113 | { |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 114 | m_tried_unwind_at_non_call_site = true; |
Greg Clayton | 75906e4 | 2011-05-11 18:39:18 +0000 | [diff] [blame] | 115 | m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 116 | if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp)) |
| 117 | m_unwind_plan_non_call_site_sp.reset(); |
Jason Molenda | 8280cbe | 2010-10-25 11:12:07 +0000 | [diff] [blame] | 118 | } |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 119 | return m_unwind_plan_non_call_site_sp; |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 120 | } |
| 121 | |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 122 | UnwindPlanSP |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 123 | FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) |
| 124 | { |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 125 | // Lock the mutex to ensure we can always give out the most appropriate |
| 126 | // information. We want to make sure if someone requests an unwind |
| 127 | // plan, that they get one and don't run into a race condition where one |
| 128 | // thread has started to create the unwind plan and has put it into |
| 129 | // the auto_ptr member variable, and have another thread enter this function |
| 130 | // and return the partially filled pointer contained in the auto_ptr. |
| 131 | // We also want to make sure that we lock out other unwind plans from |
| 132 | // being accessed until this one is done creating itself in case someone |
| 133 | // had some code like: |
| 134 | // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) |
| 135 | // if (best_unwind_plan == NULL) |
| 136 | // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) |
| 137 | Mutex::Locker locker (m_mutex); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 138 | if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL) |
Jason Molenda | 8280cbe | 2010-10-25 11:12:07 +0000 | [diff] [blame] | 139 | { |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 140 | m_tried_unwind_fast = true; |
Greg Clayton | 75906e4 | 2011-05-11 18:39:18 +0000 | [diff] [blame] | 141 | m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 142 | if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) |
| 143 | m_unwind_plan_fast_sp.reset(); |
Jason Molenda | 8280cbe | 2010-10-25 11:12:07 +0000 | [diff] [blame] | 144 | } |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 145 | return m_unwind_plan_fast_sp; |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 146 | } |
| 147 | |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 148 | UnwindPlanSP |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 149 | FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) |
| 150 | { |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 151 | // Lock the mutex to ensure we can always give out the most appropriate |
| 152 | // information. We want to make sure if someone requests an unwind |
| 153 | // plan, that they get one and don't run into a race condition where one |
| 154 | // thread has started to create the unwind plan and has put it into |
| 155 | // the auto_ptr member variable, and have another thread enter this function |
| 156 | // and return the partially filled pointer contained in the auto_ptr. |
| 157 | // We also want to make sure that we lock out other unwind plans from |
| 158 | // being accessed until this one is done creating itself in case someone |
| 159 | // had some code like: |
| 160 | // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) |
| 161 | // if (best_unwind_plan == NULL) |
| 162 | // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) |
| 163 | Mutex::Locker locker (m_mutex); |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 164 | if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL) |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 165 | { |
Greg Clayton | 5382281 | 2011-01-08 21:19:00 +0000 | [diff] [blame] | 166 | m_tried_unwind_arch_default = true; |
Greg Clayton | e2f9064 | 2011-01-08 00:05:12 +0000 | [diff] [blame] | 167 | Address current_pc; |
| 168 | Target *target = thread.CalculateTarget(); |
| 169 | if (target) |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 170 | { |
Greg Clayton | 75906e4 | 2011-05-11 18:39:18 +0000 | [diff] [blame] | 171 | ABI *abi = thread.GetProcess().GetABI().get(); |
| 172 | if (abi) |
| 173 | { |
| 174 | m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); |
| 175 | if (m_unwind_plan_arch_default_sp) |
| 176 | abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp); |
| 177 | } |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 178 | } |
| 179 | } |
| 180 | |
Greg Clayton | c3c4661 | 2011-02-15 00:19:15 +0000 | [diff] [blame] | 181 | return m_unwind_plan_arch_default_sp; |
Jason Molenda | 3a4ea24 | 2010-09-10 07:49:16 +0000 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | Address& |
| 185 | FuncUnwinders::GetFirstNonPrologueInsn (Target& target) |
| 186 | { |
| 187 | if (m_first_non_prologue_insn.IsValid()) |
| 188 | return m_first_non_prologue_insn; |
| 189 | m_assembly_profiler->FirstNonPrologueInsn (m_range, target, NULL, m_first_non_prologue_insn); |
| 190 | return m_first_non_prologue_insn; |
| 191 | } |
| 192 | |
| 193 | const Address& |
| 194 | FuncUnwinders::GetFunctionStartAddress () const |
| 195 | { |
| 196 | return m_range.GetBaseAddress(); |
| 197 | } |
| 198 | |