blob: 12f77942d70e6f427972f7d58deaea0f5142f528 [file] [log] [blame]
Jason Molenda3a4ea242010-09-10 07:49:16 +00001//===-- 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 Molenda3a4ea242010-09-10 07:49:16 +000010#include "lldb/Core/AddressRange.h"
11#include "lldb/Core/Address.h"
Greg Clayton97eecb12011-04-25 18:36:36 +000012#include "lldb/Symbol/FuncUnwinders.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000013#include "lldb/Symbol/DWARFCallFrameInfo.h"
Greg Clayton97eecb12011-04-25 18:36:36 +000014#include "lldb/Symbol/ObjectFile.h"
15#include "lldb/Symbol/UnwindPlan.h"
16#include "lldb/Symbol/UnwindTable.h"
Greg Clayton75906e42011-05-11 18:39:18 +000017#include "lldb/Target/ABI.h"
18#include "lldb/Target/Process.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000019#include "lldb/Target/Thread.h"
20#include "lldb/Target/Target.h"
Greg Clayton8badcb22011-04-25 21:14:26 +000021#include "lldb/Target/UnwindAssembly.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000022
23using namespace lldb;
24using namespace lldb_private;
25
26
Greg Claytone2f90642011-01-08 00:05:12 +000027FuncUnwinders::FuncUnwinders
28(
29 UnwindTable& unwind_table,
Greg Clayton8badcb22011-04-25 21:14:26 +000030 UnwindAssembly *assembly_profiler,
Greg Claytone2f90642011-01-08 00:05:12 +000031 AddressRange range
32) :
33 m_unwind_table(unwind_table),
34 m_assembly_profiler(assembly_profiler),
35 m_range(range),
Greg Clayton53822812011-01-08 21:19:00 +000036 m_mutex (Mutex::eMutexTypeNormal),
Greg Claytonc3c46612011-02-15 00:19:15 +000037 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 Claytone2f90642011-01-08 00:05:12 +000041 m_tried_unwind_at_call_site (false),
42 m_tried_unwind_at_non_call_site (false),
Greg Clayton53822812011-01-08 21:19:00 +000043 m_tried_unwind_fast (false),
44 m_tried_unwind_arch_default (false),
Greg Claytone2f90642011-01-08 00:05:12 +000045 m_first_non_prologue_insn()
46{
47}
Jason Molenda3a4ea242010-09-10 07:49:16 +000048
49FuncUnwinders::~FuncUnwinders ()
50{
Jason Molenda3a4ea242010-09-10 07:49:16 +000051}
52
Greg Claytonc3c46612011-02-15 00:19:15 +000053UnwindPlanSP
Jason Molendae4b07842010-11-12 05:23:10 +000054FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
Jason Molenda3a4ea242010-09-10 07:49:16 +000055{
Greg Clayton53822812011-01-08 21:19:00 +000056 // 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 Claytonc3c46612011-02-15 00:19:15 +000060 // 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 Clayton53822812011-01-08 21:19:00 +000062 // 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 Claytonc3c46612011-02-15 00:19:15 +000069 if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == NULL)
Jason Molenda3a4ea242010-09-10 07:49:16 +000070 {
Greg Claytone2f90642011-01-08 00:05:12 +000071 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 Molenda3a4ea242010-09-10 07:49:16 +000079 {
Greg Claytone2f90642011-01-08 00:05:12 +000080 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 Clayton75906e42011-05-11 18:39:18 +000087 m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
Greg Claytonc3c46612011-02-15 00:19:15 +000088 if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
89 m_unwind_plan_call_site_sp.reset();
Greg Claytone2f90642011-01-08 00:05:12 +000090 }
Jason Molenda3a4ea242010-09-10 07:49:16 +000091 }
92 }
Greg Claytonc3c46612011-02-15 00:19:15 +000093 return m_unwind_plan_call_site_sp;
Jason Molenda3a4ea242010-09-10 07:49:16 +000094}
95
Greg Claytonc3c46612011-02-15 00:19:15 +000096UnwindPlanSP
Jason Molenda3a4ea242010-09-10 07:49:16 +000097FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
98{
Greg Clayton53822812011-01-08 21:19:00 +000099 // 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 Claytonc3c46612011-02-15 00:19:15 +0000112 if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL)
Jason Molenda8280cbe2010-10-25 11:12:07 +0000113 {
Greg Claytone2f90642011-01-08 00:05:12 +0000114 m_tried_unwind_at_non_call_site = true;
Greg Clayton75906e42011-05-11 18:39:18 +0000115 m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
Greg Claytonc3c46612011-02-15 00:19:15 +0000116 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 Molenda8280cbe2010-10-25 11:12:07 +0000118 }
Greg Claytonc3c46612011-02-15 00:19:15 +0000119 return m_unwind_plan_non_call_site_sp;
Jason Molenda3a4ea242010-09-10 07:49:16 +0000120}
121
Greg Claytonc3c46612011-02-15 00:19:15 +0000122UnwindPlanSP
Jason Molenda3a4ea242010-09-10 07:49:16 +0000123FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
124{
Greg Clayton53822812011-01-08 21:19:00 +0000125 // 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 Claytonc3c46612011-02-15 00:19:15 +0000138 if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL)
Jason Molenda8280cbe2010-10-25 11:12:07 +0000139 {
Greg Clayton53822812011-01-08 21:19:00 +0000140 m_tried_unwind_fast = true;
Greg Clayton75906e42011-05-11 18:39:18 +0000141 m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
Greg Claytonc3c46612011-02-15 00:19:15 +0000142 if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
143 m_unwind_plan_fast_sp.reset();
Jason Molenda8280cbe2010-10-25 11:12:07 +0000144 }
Greg Claytonc3c46612011-02-15 00:19:15 +0000145 return m_unwind_plan_fast_sp;
Jason Molenda3a4ea242010-09-10 07:49:16 +0000146}
147
Greg Claytonc3c46612011-02-15 00:19:15 +0000148UnwindPlanSP
Jason Molenda3a4ea242010-09-10 07:49:16 +0000149FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
150{
Greg Clayton53822812011-01-08 21:19:00 +0000151 // 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 Claytonc3c46612011-02-15 00:19:15 +0000164 if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL)
Jason Molenda3a4ea242010-09-10 07:49:16 +0000165 {
Greg Clayton53822812011-01-08 21:19:00 +0000166 m_tried_unwind_arch_default = true;
Greg Claytone2f90642011-01-08 00:05:12 +0000167 Address current_pc;
168 Target *target = thread.CalculateTarget();
169 if (target)
Jason Molenda3a4ea242010-09-10 07:49:16 +0000170 {
Greg Clayton75906e42011-05-11 18:39:18 +0000171 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 Molenda3a4ea242010-09-10 07:49:16 +0000178 }
179 }
180
Greg Claytonc3c46612011-02-15 00:19:15 +0000181 return m_unwind_plan_arch_default_sp;
Jason Molenda3a4ea242010-09-10 07:49:16 +0000182}
183
184Address&
185FuncUnwinders::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
193const Address&
194FuncUnwinders::GetFunctionStartAddress () const
195{
196 return m_range.GetBaseAddress();
197}
198