Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp
39587 views
1
//===-- Symbol.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/Symbol.h"
10
11
#include "lldb/Core/Address.h"
12
#include "lldb/Core/Debugger.h"
13
#include "lldb/Core/Module.h"
14
#include "lldb/Core/ModuleSpec.h"
15
#include "lldb/Core/Section.h"
16
#include "lldb/Symbol/Function.h"
17
#include "lldb/Symbol/ObjectFile.h"
18
#include "lldb/Symbol/SymbolVendor.h"
19
#include "lldb/Symbol/Symtab.h"
20
#include "lldb/Target/Process.h"
21
#include "lldb/Target/Target.h"
22
#include "lldb/Utility/DataEncoder.h"
23
#include "lldb/Utility/Stream.h"
24
#include "llvm/ADT/StringSwitch.h"
25
26
using namespace lldb;
27
using namespace lldb_private;
28
29
Symbol::Symbol()
30
: SymbolContextScope(), m_type_data_resolved(false), m_is_synthetic(false),
31
m_is_debug(false), m_is_external(false), m_size_is_sibling(false),
32
m_size_is_synthesized(false), m_size_is_valid(false),
33
m_demangled_is_synthesized(false), m_contains_linker_annotations(false),
34
m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(),
35
m_addr_range() {}
36
37
Symbol::Symbol(uint32_t symID, llvm::StringRef name, SymbolType type,
38
bool external, bool is_debug, bool is_trampoline,
39
bool is_artificial, const lldb::SectionSP &section_sp,
40
addr_t offset, addr_t size, bool size_is_valid,
41
bool contains_linker_annotations, uint32_t flags)
42
: SymbolContextScope(), m_uid(symID), m_type_data_resolved(false),
43
m_is_synthetic(is_artificial), m_is_debug(is_debug),
44
m_is_external(external), m_size_is_sibling(false),
45
m_size_is_synthesized(false), m_size_is_valid(size_is_valid || size > 0),
46
m_demangled_is_synthesized(false),
47
m_contains_linker_annotations(contains_linker_annotations),
48
m_is_weak(false), m_type(type), m_mangled(name),
49
m_addr_range(section_sp, offset, size), m_flags(flags) {}
50
51
Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type,
52
bool external, bool is_debug, bool is_trampoline,
53
bool is_artificial, const AddressRange &range,
54
bool size_is_valid, bool contains_linker_annotations,
55
uint32_t flags)
56
: SymbolContextScope(), m_uid(symID), m_type_data_resolved(false),
57
m_is_synthetic(is_artificial), m_is_debug(is_debug),
58
m_is_external(external), m_size_is_sibling(false),
59
m_size_is_synthesized(false),
60
m_size_is_valid(size_is_valid || range.GetByteSize() > 0),
61
m_demangled_is_synthesized(false),
62
m_contains_linker_annotations(contains_linker_annotations),
63
m_is_weak(false), m_type(type), m_mangled(mangled), m_addr_range(range),
64
m_flags(flags) {}
65
66
Symbol::Symbol(const Symbol &rhs)
67
: SymbolContextScope(rhs), m_uid(rhs.m_uid), m_type_data(rhs.m_type_data),
68
m_type_data_resolved(rhs.m_type_data_resolved),
69
m_is_synthetic(rhs.m_is_synthetic), m_is_debug(rhs.m_is_debug),
70
m_is_external(rhs.m_is_external),
71
m_size_is_sibling(rhs.m_size_is_sibling), m_size_is_synthesized(false),
72
m_size_is_valid(rhs.m_size_is_valid),
73
m_demangled_is_synthesized(rhs.m_demangled_is_synthesized),
74
m_contains_linker_annotations(rhs.m_contains_linker_annotations),
75
m_is_weak(rhs.m_is_weak), m_type(rhs.m_type), m_mangled(rhs.m_mangled),
76
m_addr_range(rhs.m_addr_range), m_flags(rhs.m_flags) {}
77
78
const Symbol &Symbol::operator=(const Symbol &rhs) {
79
if (this != &rhs) {
80
SymbolContextScope::operator=(rhs);
81
m_uid = rhs.m_uid;
82
m_type_data = rhs.m_type_data;
83
m_type_data_resolved = rhs.m_type_data_resolved;
84
m_is_synthetic = rhs.m_is_synthetic;
85
m_is_debug = rhs.m_is_debug;
86
m_is_external = rhs.m_is_external;
87
m_size_is_sibling = rhs.m_size_is_sibling;
88
m_size_is_synthesized = rhs.m_size_is_sibling;
89
m_size_is_valid = rhs.m_size_is_valid;
90
m_demangled_is_synthesized = rhs.m_demangled_is_synthesized;
91
m_contains_linker_annotations = rhs.m_contains_linker_annotations;
92
m_is_weak = rhs.m_is_weak;
93
m_type = rhs.m_type;
94
m_mangled = rhs.m_mangled;
95
m_addr_range = rhs.m_addr_range;
96
m_flags = rhs.m_flags;
97
}
98
return *this;
99
}
100
101
llvm::Expected<Symbol> Symbol::FromJSON(const JSONSymbol &symbol,
102
SectionList *section_list) {
103
if (!section_list)
104
return llvm::createStringError("no section list provided");
105
106
if (!symbol.value && !symbol.address)
107
return llvm::createStringError(
108
"symbol must contain either a value or an address");
109
110
if (symbol.value && symbol.address)
111
return llvm::createStringError(
112
"symbol cannot contain both a value and an address");
113
114
const uint64_t size = symbol.size.value_or(0);
115
const bool is_artificial = false;
116
const bool is_trampoline = false;
117
const bool is_debug = false;
118
const bool external = false;
119
const bool size_is_valid = symbol.size.has_value();
120
const bool contains_linker_annotations = false;
121
const uint32_t flags = 0;
122
123
if (symbol.address) {
124
if (SectionSP section_sp =
125
section_list->FindSectionContainingFileAddress(*symbol.address)) {
126
const uint64_t offset = *symbol.address - section_sp->GetFileAddress();
127
return Symbol(symbol.id.value_or(0), Mangled(symbol.name),
128
symbol.type.value_or(eSymbolTypeAny), external, is_debug,
129
is_trampoline, is_artificial,
130
AddressRange(section_sp, offset, size), size_is_valid,
131
contains_linker_annotations, flags);
132
}
133
return llvm::createStringError(
134
llvm::formatv("no section found for address: {0:x}", *symbol.address));
135
}
136
137
// Absolute symbols encode the integer value in the m_offset of the
138
// AddressRange object and the section is set to nothing.
139
return Symbol(symbol.id.value_or(0), Mangled(symbol.name),
140
symbol.type.value_or(eSymbolTypeAny), external, is_debug,
141
is_trampoline, is_artificial,
142
AddressRange(SectionSP(), *symbol.value, size), size_is_valid,
143
contains_linker_annotations, flags);
144
}
145
146
void Symbol::Clear() {
147
m_uid = UINT32_MAX;
148
m_mangled.Clear();
149
m_type_data = 0;
150
m_type_data_resolved = false;
151
m_is_synthetic = false;
152
m_is_debug = false;
153
m_is_external = false;
154
m_size_is_sibling = false;
155
m_size_is_synthesized = false;
156
m_size_is_valid = false;
157
m_demangled_is_synthesized = false;
158
m_contains_linker_annotations = false;
159
m_is_weak = false;
160
m_type = eSymbolTypeInvalid;
161
m_flags = 0;
162
m_addr_range.Clear();
163
}
164
165
bool Symbol::ValueIsAddress() const {
166
return (bool)m_addr_range.GetBaseAddress().GetSection();
167
}
168
169
ConstString Symbol::GetDisplayName() const {
170
return GetMangled().GetDisplayDemangledName();
171
}
172
173
ConstString Symbol::GetReExportedSymbolName() const {
174
if (m_type == eSymbolTypeReExported) {
175
// For eSymbolTypeReExported, the "const char *" from a ConstString is used
176
// as the offset in the address range base address. We can then make this
177
// back into a string that is the re-exported name.
178
intptr_t str_ptr = m_addr_range.GetBaseAddress().GetOffset();
179
if (str_ptr != 0)
180
return ConstString((const char *)str_ptr);
181
else
182
return GetName();
183
}
184
return ConstString();
185
}
186
187
FileSpec Symbol::GetReExportedSymbolSharedLibrary() const {
188
if (m_type == eSymbolTypeReExported) {
189
// For eSymbolTypeReExported, the "const char *" from a ConstString is used
190
// as the offset in the address range base address. We can then make this
191
// back into a string that is the re-exported name.
192
intptr_t str_ptr = m_addr_range.GetByteSize();
193
if (str_ptr != 0)
194
return FileSpec((const char *)str_ptr);
195
}
196
return FileSpec();
197
}
198
199
void Symbol::SetReExportedSymbolName(ConstString name) {
200
SetType(eSymbolTypeReExported);
201
// For eSymbolTypeReExported, the "const char *" from a ConstString is used
202
// as the offset in the address range base address.
203
m_addr_range.GetBaseAddress().SetOffset((uintptr_t)name.GetCString());
204
}
205
206
bool Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec) {
207
if (m_type == eSymbolTypeReExported) {
208
// For eSymbolTypeReExported, the "const char *" from a ConstString is used
209
// as the offset in the address range base address.
210
m_addr_range.SetByteSize(
211
(uintptr_t)ConstString(fspec.GetPath().c_str()).GetCString());
212
return true;
213
}
214
return false;
215
}
216
217
uint32_t Symbol::GetSiblingIndex() const {
218
return m_size_is_sibling ? m_addr_range.GetByteSize() : UINT32_MAX;
219
}
220
221
bool Symbol::IsTrampoline() const { return m_type == eSymbolTypeTrampoline; }
222
223
bool Symbol::IsIndirect() const { return m_type == eSymbolTypeResolver; }
224
225
void Symbol::GetDescription(
226
Stream *s, lldb::DescriptionLevel level, Target *target,
227
std::optional<Stream::HighlightSettings> settings) const {
228
s->Printf("id = {0x%8.8x}", m_uid);
229
230
if (m_addr_range.GetBaseAddress().GetSection()) {
231
if (ValueIsAddress()) {
232
const lldb::addr_t byte_size = GetByteSize();
233
if (byte_size > 0) {
234
s->PutCString(", range = ");
235
m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress,
236
Address::DumpStyleFileAddress);
237
} else {
238
s->PutCString(", address = ");
239
m_addr_range.GetBaseAddress().Dump(s, target,
240
Address::DumpStyleLoadAddress,
241
Address::DumpStyleFileAddress);
242
}
243
} else
244
s->Printf(", value = 0x%16.16" PRIx64,
245
m_addr_range.GetBaseAddress().GetOffset());
246
} else {
247
if (m_size_is_sibling)
248
s->Printf(", sibling = %5" PRIu64,
249
m_addr_range.GetBaseAddress().GetOffset());
250
else
251
s->Printf(", value = 0x%16.16" PRIx64,
252
m_addr_range.GetBaseAddress().GetOffset());
253
}
254
if (ConstString demangled = m_mangled.GetDemangledName()) {
255
s->PutCString(", name=\"");
256
s->PutCStringColorHighlighted(demangled.GetStringRef(), settings);
257
s->PutCString("\"");
258
}
259
if (ConstString mangled_name = m_mangled.GetMangledName()) {
260
s->PutCString(", mangled=\"");
261
s->PutCStringColorHighlighted(mangled_name.GetStringRef(), settings);
262
s->PutCString("\"");
263
}
264
}
265
266
void Symbol::Dump(Stream *s, Target *target, uint32_t index,
267
Mangled::NamePreference name_preference) const {
268
s->Printf("[%5u] %6u %c%c%c %-15s ", index, GetID(), m_is_debug ? 'D' : ' ',
269
m_is_synthetic ? 'S' : ' ', m_is_external ? 'X' : ' ',
270
GetTypeAsString());
271
272
// Make sure the size of the symbol is up to date before dumping
273
GetByteSize();
274
275
ConstString name = GetMangled().GetName(name_preference);
276
if (ValueIsAddress()) {
277
if (!m_addr_range.GetBaseAddress().Dump(s, nullptr,
278
Address::DumpStyleFileAddress))
279
s->Printf("%*s", 18, "");
280
281
s->PutChar(' ');
282
283
if (!m_addr_range.GetBaseAddress().Dump(s, target,
284
Address::DumpStyleLoadAddress))
285
s->Printf("%*s", 18, "");
286
287
const char *format = m_size_is_sibling ? " Sibling -> [%5llu] 0x%8.8x %s\n"
288
: " 0x%16.16" PRIx64 " 0x%8.8x %s\n";
289
s->Printf(format, GetByteSize(), m_flags, name.AsCString(""));
290
} else if (m_type == eSymbolTypeReExported) {
291
s->Printf(
292
" 0x%8.8x %s",
293
m_flags, name.AsCString(""));
294
295
ConstString reexport_name = GetReExportedSymbolName();
296
intptr_t shlib = m_addr_range.GetByteSize();
297
if (shlib)
298
s->Printf(" -> %s`%s\n", (const char *)shlib, reexport_name.GetCString());
299
else
300
s->Printf(" -> %s\n", reexport_name.GetCString());
301
} else {
302
const char *format =
303
m_size_is_sibling
304
? "0x%16.16" PRIx64
305
" Sibling -> [%5llu] 0x%8.8x %s\n"
306
: "0x%16.16" PRIx64 " 0x%16.16" PRIx64
307
" 0x%8.8x %s\n";
308
s->Printf(format, m_addr_range.GetBaseAddress().GetOffset(), GetByteSize(),
309
m_flags, name.AsCString(""));
310
}
311
}
312
313
uint32_t Symbol::GetPrologueByteSize() {
314
if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver) {
315
if (!m_type_data_resolved) {
316
m_type_data_resolved = true;
317
318
const Address &base_address = m_addr_range.GetBaseAddress();
319
Function *function = base_address.CalculateSymbolContextFunction();
320
if (function) {
321
// Functions have line entries which can also potentially have end of
322
// prologue information. So if this symbol points to a function, use
323
// the prologue information from there.
324
m_type_data = function->GetPrologueByteSize();
325
} else {
326
ModuleSP module_sp(base_address.GetModule());
327
SymbolContext sc;
328
if (module_sp) {
329
uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress(
330
base_address, eSymbolContextLineEntry, sc);
331
if (resolved_flags & eSymbolContextLineEntry) {
332
// Default to the end of the first line entry.
333
m_type_data = sc.line_entry.range.GetByteSize();
334
335
// Set address for next line.
336
Address addr(base_address);
337
addr.Slide(m_type_data);
338
339
// Check the first few instructions and look for one that has a
340
// line number that is different than the first entry. This is also
341
// done in Function::GetPrologueByteSize().
342
uint16_t total_offset = m_type_data;
343
for (int idx = 0; idx < 6; ++idx) {
344
SymbolContext sc_temp;
345
resolved_flags = module_sp->ResolveSymbolContextForAddress(
346
addr, eSymbolContextLineEntry, sc_temp);
347
// Make sure we got line number information...
348
if (!(resolved_flags & eSymbolContextLineEntry))
349
break;
350
351
// If this line number is different than our first one, use it
352
// and we're done.
353
if (sc_temp.line_entry.line != sc.line_entry.line) {
354
m_type_data = total_offset;
355
break;
356
}
357
358
// Slide addr up to the next line address.
359
addr.Slide(sc_temp.line_entry.range.GetByteSize());
360
total_offset += sc_temp.line_entry.range.GetByteSize();
361
// If we've gone too far, bail out.
362
if (total_offset >= m_addr_range.GetByteSize())
363
break;
364
}
365
366
// Sanity check - this may be a function in the middle of code that
367
// has debug information, but not for this symbol. So the line
368
// entries surrounding us won't lie inside our function. In that
369
// case, the line entry will be bigger than we are, so we do that
370
// quick check and if that is true, we just return 0.
371
if (m_type_data >= m_addr_range.GetByteSize())
372
m_type_data = 0;
373
} else {
374
// TODO: expose something in Process to figure out the
375
// size of a function prologue.
376
m_type_data = 0;
377
}
378
}
379
}
380
}
381
return m_type_data;
382
}
383
return 0;
384
}
385
386
bool Symbol::Compare(ConstString name, SymbolType type) const {
387
if (type == eSymbolTypeAny || m_type == type) {
388
const Mangled &mangled = GetMangled();
389
return mangled.GetMangledName() == name ||
390
mangled.GetDemangledName() == name;
391
}
392
return false;
393
}
394
395
#define ENUM_TO_CSTRING(x) \
396
case eSymbolType##x: \
397
return #x;
398
399
const char *Symbol::GetTypeAsString() const {
400
switch (m_type) {
401
ENUM_TO_CSTRING(Invalid);
402
ENUM_TO_CSTRING(Absolute);
403
ENUM_TO_CSTRING(Code);
404
ENUM_TO_CSTRING(Resolver);
405
ENUM_TO_CSTRING(Data);
406
ENUM_TO_CSTRING(Trampoline);
407
ENUM_TO_CSTRING(Runtime);
408
ENUM_TO_CSTRING(Exception);
409
ENUM_TO_CSTRING(SourceFile);
410
ENUM_TO_CSTRING(HeaderFile);
411
ENUM_TO_CSTRING(ObjectFile);
412
ENUM_TO_CSTRING(CommonBlock);
413
ENUM_TO_CSTRING(Block);
414
ENUM_TO_CSTRING(Local);
415
ENUM_TO_CSTRING(Param);
416
ENUM_TO_CSTRING(Variable);
417
ENUM_TO_CSTRING(VariableType);
418
ENUM_TO_CSTRING(LineEntry);
419
ENUM_TO_CSTRING(LineHeader);
420
ENUM_TO_CSTRING(ScopeBegin);
421
ENUM_TO_CSTRING(ScopeEnd);
422
ENUM_TO_CSTRING(Additional);
423
ENUM_TO_CSTRING(Compiler);
424
ENUM_TO_CSTRING(Instrumentation);
425
ENUM_TO_CSTRING(Undefined);
426
ENUM_TO_CSTRING(ObjCClass);
427
ENUM_TO_CSTRING(ObjCMetaClass);
428
ENUM_TO_CSTRING(ObjCIVar);
429
ENUM_TO_CSTRING(ReExported);
430
default:
431
break;
432
}
433
return "<unknown SymbolType>";
434
}
435
436
void Symbol::CalculateSymbolContext(SymbolContext *sc) {
437
// Symbols can reconstruct the symbol and the module in the symbol context
438
sc->symbol = this;
439
if (ValueIsAddress())
440
sc->module_sp = GetAddressRef().GetModule();
441
else
442
sc->module_sp.reset();
443
}
444
445
ModuleSP Symbol::CalculateSymbolContextModule() {
446
if (ValueIsAddress())
447
return GetAddressRef().GetModule();
448
return ModuleSP();
449
}
450
451
Symbol *Symbol::CalculateSymbolContextSymbol() { return this; }
452
453
void Symbol::DumpSymbolContext(Stream *s) {
454
bool dumped_module = false;
455
if (ValueIsAddress()) {
456
ModuleSP module_sp(GetAddressRef().GetModule());
457
if (module_sp) {
458
dumped_module = true;
459
module_sp->DumpSymbolContext(s);
460
}
461
}
462
if (dumped_module)
463
s->PutCString(", ");
464
465
s->Printf("Symbol{0x%8.8x}", GetID());
466
}
467
468
lldb::addr_t Symbol::GetByteSize() const { return m_addr_range.GetByteSize(); }
469
470
Symbol *Symbol::ResolveReExportedSymbolInModuleSpec(
471
Target &target, ConstString &reexport_name, ModuleSpec &module_spec,
472
ModuleList &seen_modules) const {
473
ModuleSP module_sp;
474
if (module_spec.GetFileSpec()) {
475
// Try searching for the module file spec first using the full path
476
module_sp = target.GetImages().FindFirstModule(module_spec);
477
if (!module_sp) {
478
// Next try and find the module by basename in case environment variables
479
// or other runtime trickery causes shared libraries to be loaded from
480
// alternate paths
481
module_spec.GetFileSpec().ClearDirectory();
482
module_sp = target.GetImages().FindFirstModule(module_spec);
483
}
484
}
485
486
if (module_sp) {
487
// There should not be cycles in the reexport list, but we don't want to
488
// crash if there are so make sure we haven't seen this before:
489
if (!seen_modules.AppendIfNeeded(module_sp))
490
return nullptr;
491
492
lldb_private::SymbolContextList sc_list;
493
module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny,
494
sc_list);
495
for (const SymbolContext &sc : sc_list) {
496
if (sc.symbol->IsExternal())
497
return sc.symbol;
498
}
499
// If we didn't find the symbol in this module, it may be because this
500
// module re-exports some whole other library. We have to search those as
501
// well:
502
seen_modules.Append(module_sp);
503
504
FileSpecList reexported_libraries =
505
module_sp->GetObjectFile()->GetReExportedLibraries();
506
size_t num_reexported_libraries = reexported_libraries.GetSize();
507
for (size_t idx = 0; idx < num_reexported_libraries; idx++) {
508
ModuleSpec reexported_module_spec;
509
reexported_module_spec.GetFileSpec() =
510
reexported_libraries.GetFileSpecAtIndex(idx);
511
Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec(
512
target, reexport_name, reexported_module_spec, seen_modules);
513
if (result_symbol)
514
return result_symbol;
515
}
516
}
517
return nullptr;
518
}
519
520
Symbol *Symbol::ResolveReExportedSymbol(Target &target) const {
521
ConstString reexport_name(GetReExportedSymbolName());
522
if (reexport_name) {
523
ModuleSpec module_spec;
524
ModuleList seen_modules;
525
module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary();
526
if (module_spec.GetFileSpec()) {
527
return ResolveReExportedSymbolInModuleSpec(target, reexport_name,
528
module_spec, seen_modules);
529
}
530
}
531
return nullptr;
532
}
533
534
lldb::addr_t Symbol::GetFileAddress() const {
535
if (ValueIsAddress())
536
return GetAddressRef().GetFileAddress();
537
else
538
return LLDB_INVALID_ADDRESS;
539
}
540
541
lldb::addr_t Symbol::GetLoadAddress(Target *target) const {
542
if (ValueIsAddress())
543
return GetAddressRef().GetLoadAddress(target);
544
else
545
return LLDB_INVALID_ADDRESS;
546
}
547
548
ConstString Symbol::GetName() const { return GetMangled().GetName(); }
549
550
ConstString Symbol::GetNameNoArguments() const {
551
return GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments);
552
}
553
554
lldb::addr_t Symbol::ResolveCallableAddress(Target &target) const {
555
if (GetType() == lldb::eSymbolTypeUndefined)
556
return LLDB_INVALID_ADDRESS;
557
558
Address func_so_addr;
559
560
bool is_indirect = IsIndirect();
561
if (GetType() == eSymbolTypeReExported) {
562
Symbol *reexported_symbol = ResolveReExportedSymbol(target);
563
if (reexported_symbol) {
564
func_so_addr = reexported_symbol->GetAddress();
565
is_indirect = reexported_symbol->IsIndirect();
566
}
567
} else {
568
func_so_addr = GetAddress();
569
is_indirect = IsIndirect();
570
}
571
572
if (func_so_addr.IsValid()) {
573
if (!target.GetProcessSP() && is_indirect) {
574
// can't resolve indirect symbols without calling a function...
575
return LLDB_INVALID_ADDRESS;
576
}
577
578
lldb::addr_t load_addr =
579
func_so_addr.GetCallableLoadAddress(&target, is_indirect);
580
581
if (load_addr != LLDB_INVALID_ADDRESS) {
582
return load_addr;
583
}
584
}
585
586
return LLDB_INVALID_ADDRESS;
587
}
588
589
lldb::DisassemblerSP Symbol::GetInstructions(const ExecutionContext &exe_ctx,
590
const char *flavor,
591
bool prefer_file_cache) {
592
ModuleSP module_sp(m_addr_range.GetBaseAddress().GetModule());
593
if (module_sp && exe_ctx.HasTargetScope()) {
594
return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
595
flavor, exe_ctx.GetTargetRef(),
596
m_addr_range, !prefer_file_cache);
597
}
598
return lldb::DisassemblerSP();
599
}
600
601
bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
602
bool prefer_file_cache, Stream &strm) {
603
lldb::DisassemblerSP disassembler_sp =
604
GetInstructions(exe_ctx, flavor, prefer_file_cache);
605
if (disassembler_sp) {
606
const bool show_address = true;
607
const bool show_bytes = false;
608
const bool show_control_flow_kind = false;
609
disassembler_sp->GetInstructionList().Dump(
610
&strm, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
611
return true;
612
}
613
return false;
614
}
615
616
bool Symbol::ContainsFileAddress(lldb::addr_t file_addr) const {
617
return m_addr_range.ContainsFileAddress(file_addr);
618
}
619
620
bool Symbol::IsSyntheticWithAutoGeneratedName() const {
621
if (!IsSynthetic())
622
return false;
623
if (!m_mangled)
624
return true;
625
ConstString demangled = m_mangled.GetDemangledName();
626
return demangled.GetStringRef().starts_with(GetSyntheticSymbolPrefix());
627
}
628
629
void Symbol::SynthesizeNameIfNeeded() const {
630
if (m_is_synthetic && !m_mangled) {
631
// Synthetic symbol names don't mean anything, but they do uniquely
632
// identify individual symbols so we give them a unique name. The name
633
// starts with the synthetic symbol prefix, followed by a unique number.
634
// Typically the UserID of a real symbol is the symbol table index of the
635
// symbol in the object file's symbol table(s), so it will be the same
636
// every time you read in the object file. We want the same persistence for
637
// synthetic symbols so that users can identify them across multiple debug
638
// sessions, to understand crashes in those symbols and to reliably set
639
// breakpoints on them.
640
llvm::SmallString<256> name;
641
llvm::raw_svector_ostream os(name);
642
os << GetSyntheticSymbolPrefix() << GetID();
643
m_mangled.SetDemangledName(ConstString(os.str()));
644
}
645
}
646
647
bool Symbol::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
648
const SectionList *section_list,
649
const StringTableReader &strtab) {
650
if (!data.ValidOffsetForDataOfSize(*offset_ptr, 8))
651
return false;
652
m_uid = data.GetU32(offset_ptr);
653
m_type_data = data.GetU16(offset_ptr);
654
const uint16_t bitfields = data.GetU16(offset_ptr);
655
m_type_data_resolved = (1u << 15 & bitfields) != 0;
656
m_is_synthetic = (1u << 14 & bitfields) != 0;
657
m_is_debug = (1u << 13 & bitfields) != 0;
658
m_is_external = (1u << 12 & bitfields) != 0;
659
m_size_is_sibling = (1u << 11 & bitfields) != 0;
660
m_size_is_synthesized = (1u << 10 & bitfields) != 0;
661
m_size_is_valid = (1u << 9 & bitfields) != 0;
662
m_demangled_is_synthesized = (1u << 8 & bitfields) != 0;
663
m_contains_linker_annotations = (1u << 7 & bitfields) != 0;
664
m_is_weak = (1u << 6 & bitfields) != 0;
665
m_type = bitfields & 0x003f;
666
if (!m_mangled.Decode(data, offset_ptr, strtab))
667
return false;
668
if (!data.ValidOffsetForDataOfSize(*offset_ptr, 20))
669
return false;
670
const bool is_addr = data.GetU8(offset_ptr) != 0;
671
const uint64_t value = data.GetU64(offset_ptr);
672
if (is_addr) {
673
m_addr_range.GetBaseAddress().ResolveAddressUsingFileSections(value,
674
section_list);
675
} else {
676
m_addr_range.GetBaseAddress().Clear();
677
m_addr_range.GetBaseAddress().SetOffset(value);
678
}
679
m_addr_range.SetByteSize(data.GetU64(offset_ptr));
680
m_flags = data.GetU32(offset_ptr);
681
return true;
682
}
683
684
/// The encoding format for the symbol is as follows:
685
///
686
/// uint32_t m_uid;
687
/// uint16_t m_type_data;
688
/// uint16_t bitfield_data;
689
/// Mangled mangled;
690
/// uint8_t is_addr;
691
/// uint64_t file_addr_or_value;
692
/// uint64_t size;
693
/// uint32_t flags;
694
///
695
/// The only tricky thing in this encoding is encoding all of the bits in the
696
/// bitfields. We use a trick to store all bitfields as a 16 bit value and we
697
/// do the same thing when decoding the symbol. There are test that ensure this
698
/// encoding works for each individual bit. Everything else is very easy to
699
/// store.
700
void Symbol::Encode(DataEncoder &file, ConstStringTable &strtab) const {
701
file.AppendU32(m_uid);
702
file.AppendU16(m_type_data);
703
uint16_t bitfields = m_type;
704
if (m_type_data_resolved)
705
bitfields |= 1u << 15;
706
if (m_is_synthetic)
707
bitfields |= 1u << 14;
708
if (m_is_debug)
709
bitfields |= 1u << 13;
710
if (m_is_external)
711
bitfields |= 1u << 12;
712
if (m_size_is_sibling)
713
bitfields |= 1u << 11;
714
if (m_size_is_synthesized)
715
bitfields |= 1u << 10;
716
if (m_size_is_valid)
717
bitfields |= 1u << 9;
718
if (m_demangled_is_synthesized)
719
bitfields |= 1u << 8;
720
if (m_contains_linker_annotations)
721
bitfields |= 1u << 7;
722
if (m_is_weak)
723
bitfields |= 1u << 6;
724
file.AppendU16(bitfields);
725
m_mangled.Encode(file, strtab);
726
// A symbol's value might be an address, or it might be a constant. If the
727
// symbol's base address doesn't have a section, then it is a constant value.
728
// If it does have a section, we will encode the file address and re-resolve
729
// the address when we decode it.
730
bool is_addr = m_addr_range.GetBaseAddress().GetSection().get() != nullptr;
731
file.AppendU8(is_addr);
732
file.AppendU64(m_addr_range.GetBaseAddress().GetFileAddress());
733
file.AppendU64(m_addr_range.GetByteSize());
734
file.AppendU32(m_flags);
735
}
736
737
bool Symbol::operator==(const Symbol &rhs) const {
738
if (m_uid != rhs.m_uid)
739
return false;
740
if (m_type_data != rhs.m_type_data)
741
return false;
742
if (m_type_data_resolved != rhs.m_type_data_resolved)
743
return false;
744
if (m_is_synthetic != rhs.m_is_synthetic)
745
return false;
746
if (m_is_debug != rhs.m_is_debug)
747
return false;
748
if (m_is_external != rhs.m_is_external)
749
return false;
750
if (m_size_is_sibling != rhs.m_size_is_sibling)
751
return false;
752
if (m_size_is_synthesized != rhs.m_size_is_synthesized)
753
return false;
754
if (m_size_is_valid != rhs.m_size_is_valid)
755
return false;
756
if (m_demangled_is_synthesized != rhs.m_demangled_is_synthesized)
757
return false;
758
if (m_contains_linker_annotations != rhs.m_contains_linker_annotations)
759
return false;
760
if (m_is_weak != rhs.m_is_weak)
761
return false;
762
if (m_type != rhs.m_type)
763
return false;
764
if (m_mangled != rhs.m_mangled)
765
return false;
766
if (m_addr_range.GetBaseAddress() != rhs.m_addr_range.GetBaseAddress())
767
return false;
768
if (m_addr_range.GetByteSize() != rhs.m_addr_range.GetByteSize())
769
return false;
770
if (m_flags != rhs.m_flags)
771
return false;
772
return true;
773
}
774
775
namespace llvm {
776
namespace json {
777
778
bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
779
llvm::json::Path path) {
780
llvm::json::ObjectMapper o(value, path);
781
const bool mapped = o && o.map("value", symbol.value) &&
782
o.map("address", symbol.address) &&
783
o.map("size", symbol.size) && o.map("id", symbol.id) &&
784
o.map("type", symbol.type) && o.map("name", symbol.name);
785
786
if (!mapped)
787
return false;
788
789
if (!symbol.value && !symbol.address) {
790
path.report("symbol must have either a value or an address");
791
return false;
792
}
793
794
if (symbol.value && symbol.address) {
795
path.report("symbol cannot have both a value and an address");
796
return false;
797
}
798
799
return true;
800
}
801
802
bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
803
llvm::json::Path path) {
804
if (auto str = value.getAsString()) {
805
type = llvm::StringSwitch<lldb::SymbolType>(*str)
806
.Case("absolute", eSymbolTypeAbsolute)
807
.Case("code", eSymbolTypeCode)
808
.Case("resolver", eSymbolTypeResolver)
809
.Case("data", eSymbolTypeData)
810
.Case("trampoline", eSymbolTypeTrampoline)
811
.Case("runtime", eSymbolTypeRuntime)
812
.Case("exception", eSymbolTypeException)
813
.Case("sourcefile", eSymbolTypeSourceFile)
814
.Case("headerfile", eSymbolTypeHeaderFile)
815
.Case("objectfile", eSymbolTypeObjectFile)
816
.Case("commonblock", eSymbolTypeCommonBlock)
817
.Case("block", eSymbolTypeBlock)
818
.Case("local", eSymbolTypeLocal)
819
.Case("param", eSymbolTypeParam)
820
.Case("variable", eSymbolTypeVariable)
821
.Case("variableType", eSymbolTypeVariableType)
822
.Case("lineentry", eSymbolTypeLineEntry)
823
.Case("lineheader", eSymbolTypeLineHeader)
824
.Case("scopebegin", eSymbolTypeScopeBegin)
825
.Case("scopeend", eSymbolTypeScopeEnd)
826
.Case("additional,", eSymbolTypeAdditional)
827
.Case("compiler", eSymbolTypeCompiler)
828
.Case("instrumentation", eSymbolTypeInstrumentation)
829
.Case("undefined", eSymbolTypeUndefined)
830
.Case("objcclass", eSymbolTypeObjCClass)
831
.Case("objcmetaClass", eSymbolTypeObjCMetaClass)
832
.Case("objcivar", eSymbolTypeObjCIVar)
833
.Case("reexporte", eSymbolTypeReExported)
834
.Default(eSymbolTypeInvalid);
835
836
if (type == eSymbolTypeInvalid) {
837
path.report("invalid symbol type");
838
return false;
839
}
840
841
return true;
842
}
843
path.report("expected string");
844
return false;
845
}
846
} // namespace json
847
} // namespace llvm
848
849