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