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