FuncUnwinders.cpp revision 75906e4ec98af3717e415727a8d663a4e246bb4f
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
23using namespace lldb;
24using namespace lldb_private;
25
26
27FuncUnwinders::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_first_non_prologue_insn()
46{
47}
48
49FuncUnwinders::~FuncUnwinders ()
50{
51}
52
53UnwindPlanSP
54FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
55{
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
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.
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);
69    if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == NULL)
70    {
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())
79        {
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            {
87                m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
88                if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
89                    m_unwind_plan_call_site_sp.reset();
90            }
91        }
92    }
93    return m_unwind_plan_call_site_sp;
94}
95
96UnwindPlanSP
97FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
98{
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);
112    if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL)
113    {
114        m_tried_unwind_at_non_call_site = true;
115        m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
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();
118    }
119    return m_unwind_plan_non_call_site_sp;
120}
121
122UnwindPlanSP
123FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
124{
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);
138    if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL)
139    {
140        m_tried_unwind_fast = true;
141        m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
142        if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
143            m_unwind_plan_fast_sp.reset();
144    }
145    return m_unwind_plan_fast_sp;
146}
147
148UnwindPlanSP
149FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
150{
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);
164    if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL)
165    {
166        m_tried_unwind_arch_default = true;
167        Address current_pc;
168        Target *target = thread.CalculateTarget();
169        if (target)
170        {
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            }
178        }
179    }
180
181    return m_unwind_plan_arch_default_sp;
182}
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
199