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