1 //===-- UnwindTable.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/Symbol/UnwindTable.h"
11 
12 #include <stdio.h>
13 
14 #include "lldb/lldb-forward.h"
15 
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Symbol/ObjectFile.h"
19 #include "lldb/Symbol/FuncUnwinders.h"
20 #include "lldb/Symbol/SymbolContext.h"
21 #include "lldb/Symbol/DWARFCallFrameInfo.h"
22 #include "lldb/Utility/UnwindAssemblyProfiler.h"
23 
24 // There is one UnwindTable object per ObjectFile.
25 // It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
26 // Each Unwind object has multiple UnwindPlans for different scenarios.
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 UnwindTable::UnwindTable (ObjectFile& objfile) : m_object_file(objfile),
32                                                  m_unwinds(),
33                                                  m_initialized(false),
34                                                  m_eh_frame(NULL),
35                                                  m_assembly_profiler(NULL)
36 {
37 }
38 
39 // We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
40 // until needed for something.
41 
42 void
43 UnwindTable::initialize ()
44 {
45     if (m_initialized)
46         return;
47 
48     SectionList* sl = m_object_file.GetSectionList ();
49     if (sl)
50     {
51         SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
52         if (sect.get())
53         {
54             m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
55         }
56     }
57 
58     ArchSpec arch;
59     ConstString str;
60     m_object_file.GetTargetTriple (str);
61     arch.SetArchFromTargetTriple (str.GetCString());
62     m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch);
63 
64     m_initialized = true;
65 }
66 
67 UnwindTable::~UnwindTable ()
68 {
69     if (m_eh_frame)
70         delete m_eh_frame;
71 }
72 
73 FuncUnwindersSP
74 UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
75 {
76     FuncUnwindersSP no_unwind_found;
77 
78     initialize();
79 
80     // Create a FuncUnwinders object for the binary search below
81     AddressRange search_range(addr, 1);
82     FuncUnwindersSP search_unwind(new FuncUnwinders (*this, NULL, search_range));
83 
84     const_iterator idx;
85     idx = std::lower_bound (m_unwinds.begin(), m_unwinds.end(), search_unwind);
86 
87     bool found_match = true;
88     if (m_unwinds.size() == 0)
89     {
90         found_match = false;
91     }
92     else if (idx == m_unwinds.end())
93     {
94         --idx;
95     }
96     if (idx != m_unwinds.begin() && (*idx)->GetFunctionStartAddress().GetOffset() != addr.GetOffset())
97     {
98        --idx;
99     }
100     if (found_match && (*idx)->ContainsAddress (addr))
101     {
102         return *idx;
103     }
104 
105     AddressRange range;
106     if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
107     {
108         FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
109         m_unwinds.push_back (unw);
110         std::sort (m_unwinds.begin(), m_unwinds.end());
111         return unw;
112     }
113     else
114     {
115         // Does the eh_frame unwind info has a function bounds defined for this addr?
116         if (m_eh_frame->GetAddressRange (addr, range))
117         {
118             FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
119             m_unwinds.push_back (unw);
120             std::sort (m_unwinds.begin(), m_unwinds.end());
121             return unw;
122             // FIXME we should create a syntheic Symbol based on the address range with a synthesized symbol name
123         }
124     }
125     return no_unwind_found;
126 }
127 
128 DWARFCallFrameInfo *
129 UnwindTable::GetEHFrameInfo ()
130 {
131     initialize();
132     return m_eh_frame;
133 }
134