Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp
39587 views
1
//===-- UnwindTable.cpp ---------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "lldb/Symbol/UnwindTable.h"
10
11
#include <cstdio>
12
#include <optional>
13
14
#include "lldb/Core/Module.h"
15
#include "lldb/Core/Section.h"
16
#include "lldb/Symbol/ArmUnwindInfo.h"
17
#include "lldb/Symbol/CallFrameInfo.h"
18
#include "lldb/Symbol/CompactUnwindInfo.h"
19
#include "lldb/Symbol/DWARFCallFrameInfo.h"
20
#include "lldb/Symbol/FuncUnwinders.h"
21
#include "lldb/Symbol/ObjectFile.h"
22
#include "lldb/Symbol/SymbolContext.h"
23
#include "lldb/Symbol/SymbolVendor.h"
24
25
// There is one UnwindTable object per ObjectFile. It contains a list of Unwind
26
// objects -- one per function, populated lazily -- for the ObjectFile. Each
27
// Unwind object has multiple UnwindPlans for different scenarios.
28
29
using namespace lldb;
30
using namespace lldb_private;
31
32
UnwindTable::UnwindTable(Module &module)
33
: m_module(module), m_unwinds(), m_initialized(false), m_mutex(),
34
m_object_file_unwind_up(), m_eh_frame_up(), m_compact_unwind_up(),
35
m_arm_unwind_up() {}
36
37
// We can't do some of this initialization when the ObjectFile is running its
38
// ctor; delay doing it until needed for something.
39
40
void UnwindTable::Initialize() {
41
if (m_initialized)
42
return;
43
44
std::lock_guard<std::mutex> guard(m_mutex);
45
46
if (m_initialized) // check again once we've acquired the lock
47
return;
48
m_initialized = true;
49
ObjectFile *object_file = m_module.GetObjectFile();
50
if (!object_file)
51
return;
52
53
m_object_file_unwind_up = object_file->CreateCallFrameInfo();
54
55
SectionList *sl = m_module.GetSectionList();
56
if (!sl)
57
return;
58
59
SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
60
if (sect.get()) {
61
m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>(
62
*object_file, sect, DWARFCallFrameInfo::EH);
63
}
64
65
sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
66
if (sect) {
67
m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>(
68
*object_file, sect, DWARFCallFrameInfo::DWARF);
69
}
70
71
sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
72
if (sect) {
73
m_compact_unwind_up =
74
std::make_unique<CompactUnwindInfo>(*object_file, sect);
75
}
76
77
sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
78
if (sect) {
79
SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
80
if (sect_extab.get()) {
81
m_arm_unwind_up =
82
std::make_unique<ArmUnwindInfo>(*object_file, sect, sect_extab);
83
}
84
}
85
}
86
87
void UnwindTable::Update() {
88
if (!m_initialized)
89
return Initialize();
90
91
std::lock_guard<std::mutex> guard(m_mutex);
92
93
ObjectFile *object_file = m_module.GetObjectFile();
94
if (!object_file)
95
return;
96
97
if (!m_object_file_unwind_up)
98
m_object_file_unwind_up = object_file->CreateCallFrameInfo();
99
100
SectionList *sl = m_module.GetSectionList();
101
if (!sl)
102
return;
103
104
SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
105
if (!m_eh_frame_up && sect) {
106
m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>(
107
*object_file, sect, DWARFCallFrameInfo::EH);
108
}
109
110
sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
111
if (!m_debug_frame_up && sect) {
112
m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>(
113
*object_file, sect, DWARFCallFrameInfo::DWARF);
114
}
115
116
sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
117
if (!m_compact_unwind_up && sect) {
118
m_compact_unwind_up =
119
std::make_unique<CompactUnwindInfo>(*object_file, sect);
120
}
121
122
sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
123
if (!m_arm_unwind_up && sect) {
124
SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
125
if (sect_extab.get()) {
126
m_arm_unwind_up =
127
std::make_unique<ArmUnwindInfo>(*object_file, sect, sect_extab);
128
}
129
}
130
}
131
132
UnwindTable::~UnwindTable() = default;
133
134
std::optional<AddressRange>
135
UnwindTable::GetAddressRange(const Address &addr, const SymbolContext &sc) {
136
AddressRange range;
137
138
// First check the unwind info from the object file plugin
139
if (m_object_file_unwind_up &&
140
m_object_file_unwind_up->GetAddressRange(addr, range))
141
return range;
142
143
// Check the symbol context
144
if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
145
false, range) &&
146
range.GetBaseAddress().IsValid())
147
return range;
148
149
// Does the eh_frame unwind info has a function bounds for this addr?
150
if (m_eh_frame_up && m_eh_frame_up->GetAddressRange(addr, range))
151
return range;
152
153
// Try debug_frame as well
154
if (m_debug_frame_up && m_debug_frame_up->GetAddressRange(addr, range))
155
return range;
156
157
return std::nullopt;
158
}
159
160
FuncUnwindersSP
161
UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr,
162
SymbolContext &sc) {
163
Initialize();
164
165
std::lock_guard<std::mutex> guard(m_mutex);
166
167
// There is an UnwindTable per object file, so we can safely use file handles
168
addr_t file_addr = addr.GetFileAddress();
169
iterator end = m_unwinds.end();
170
iterator insert_pos = end;
171
if (!m_unwinds.empty()) {
172
insert_pos = m_unwinds.lower_bound(file_addr);
173
iterator pos = insert_pos;
174
if ((pos == m_unwinds.end()) ||
175
(pos != m_unwinds.begin() &&
176
pos->second->GetFunctionStartAddress() != addr))
177
--pos;
178
179
if (pos->second->ContainsAddress(addr))
180
return pos->second;
181
}
182
183
auto range_or = GetAddressRange(addr, sc);
184
if (!range_or)
185
return nullptr;
186
187
FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, *range_or));
188
m_unwinds.insert(insert_pos,
189
std::make_pair(range_or->GetBaseAddress().GetFileAddress(),
190
func_unwinder_sp));
191
return func_unwinder_sp;
192
}
193
194
// Ignore any existing FuncUnwinders for this function, create a new one and
195
// don't add it to the UnwindTable. This is intended for use by target modules
196
// show-unwind where we want to create new UnwindPlans, not re-use existing
197
// ones.
198
FuncUnwindersSP UnwindTable::GetUncachedFuncUnwindersContainingAddress(
199
const Address &addr, const SymbolContext &sc) {
200
Initialize();
201
202
auto range_or = GetAddressRange(addr, sc);
203
if (!range_or)
204
return nullptr;
205
206
return std::make_shared<FuncUnwinders>(*this, *range_or);
207
}
208
209
void UnwindTable::Dump(Stream &s) {
210
std::lock_guard<std::mutex> guard(m_mutex);
211
s.Format("UnwindTable for '{0}':\n", m_module.GetFileSpec());
212
const_iterator begin = m_unwinds.begin();
213
const_iterator end = m_unwinds.end();
214
for (const_iterator pos = begin; pos != end; ++pos) {
215
s.Printf("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance(begin, pos),
216
pos->first);
217
}
218
s.EOL();
219
}
220
221
lldb_private::CallFrameInfo *UnwindTable::GetObjectFileUnwindInfo() {
222
Initialize();
223
return m_object_file_unwind_up.get();
224
}
225
226
DWARFCallFrameInfo *UnwindTable::GetEHFrameInfo() {
227
Initialize();
228
return m_eh_frame_up.get();
229
}
230
231
DWARFCallFrameInfo *UnwindTable::GetDebugFrameInfo() {
232
Initialize();
233
return m_debug_frame_up.get();
234
}
235
236
CompactUnwindInfo *UnwindTable::GetCompactUnwindInfo() {
237
Initialize();
238
return m_compact_unwind_up.get();
239
}
240
241
ArmUnwindInfo *UnwindTable::GetArmUnwindInfo() {
242
Initialize();
243
return m_arm_unwind_up.get();
244
}
245
246
SymbolFile *UnwindTable::GetSymbolFile() { return m_module.GetSymbolFile(); }
247
248
ArchSpec UnwindTable::GetArchitecture() { return m_module.GetArchitecture(); }
249
250
bool UnwindTable::GetAllowAssemblyEmulationUnwindPlans() {
251
if (ObjectFile *object_file = m_module.GetObjectFile())
252
return object_file->AllowAssemblyEmulationUnwindPlans();
253
return false;
254
}
255
256