1 //===-- Symbol.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Symbol/Symbol.h"
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"
27 using namespace lldb_private
;
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(),
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
§ion_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
) {}
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
,
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
),
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
) {}
78 const Symbol
&Symbol::operator=(const Symbol
&rhs
) {
80 SymbolContextScope::operator=(rhs
);
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
;
94 m_mangled
= rhs
.m_mangled
;
95 m_addr_range
= rhs
.m_addr_range
;
96 m_flags
= rhs
.m_flags
;
101 llvm::Expected
<Symbol
> Symbol::FromJSON(const JSONSymbol
&symbol
,
102 SectionList
*section_list
) {
104 return llvm::createStringError("no section list provided");
106 if (!symbol
.value
&& !symbol
.address
)
107 return llvm::createStringError(
108 "symbol must contain either a value or an address");
110 if (symbol
.value
&& symbol
.address
)
111 return llvm::createStringError(
112 "symbol cannot contain both a value and an address");
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;
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
);
133 return llvm::createStringError(
134 llvm::formatv("no section found for address: {0:x}", *symbol
.address
));
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
);
146 void Symbol::Clear() {
150 m_type_data_resolved
= false;
151 m_is_synthetic
= 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;
160 m_type
= eSymbolTypeInvalid
;
162 m_addr_range
.Clear();
165 bool Symbol::ValueIsAddress() const {
166 return (bool)m_addr_range
.GetBaseAddress().GetSection();
169 ConstString
Symbol::GetDisplayName() const {
170 return GetMangled().GetDisplayDemangledName();
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();
180 return ConstString((const char *)str_ptr
);
184 return ConstString();
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();
194 return FileSpec((const char *)str_ptr
);
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());
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());
217 uint32_t Symbol::GetSiblingIndex() const {
218 return m_size_is_sibling
? m_addr_range
.GetByteSize() : UINT32_MAX
;
221 bool Symbol::IsTrampoline() const { return m_type
== eSymbolTypeTrampoline
; }
223 bool Symbol::IsIndirect() const { return m_type
== eSymbolTypeResolver
; }
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
);
230 if (m_addr_range
.GetBaseAddress().GetSection()) {
231 if (ValueIsAddress()) {
232 const lldb::addr_t byte_size
= GetByteSize();
234 s
->PutCString(", range = ");
235 m_addr_range
.Dump(s
, target
, Address::DumpStyleLoadAddress
,
236 Address::DumpStyleFileAddress
);
238 s
->PutCString(", address = ");
239 m_addr_range
.GetBaseAddress().Dump(s
, target
,
240 Address::DumpStyleLoadAddress
,
241 Address::DumpStyleFileAddress
);
244 s
->Printf(", value = 0x%16.16" PRIx64
,
245 m_addr_range
.GetBaseAddress().GetOffset());
247 if (m_size_is_sibling
)
248 s
->Printf(", sibling = %5" PRIu64
,
249 m_addr_range
.GetBaseAddress().GetOffset());
251 s
->Printf(", value = 0x%16.16" PRIx64
,
252 m_addr_range
.GetBaseAddress().GetOffset());
254 if (ConstString demangled
= m_mangled
.GetDemangledName()) {
255 s
->PutCString(", name=\"");
256 s
->PutCStringColorHighlighted(demangled
.GetStringRef(), settings
);
259 if (ConstString mangled_name
= m_mangled
.GetMangledName()) {
260 s
->PutCString(", mangled=\"");
261 s
->PutCStringColorHighlighted(mangled_name
.GetStringRef(), settings
);
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' : ' ',
272 // Make sure the size of the symbol is up to date before dumping
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, "");
283 if (!m_addr_range
.GetBaseAddress().Dump(s
, target
,
284 Address::DumpStyleLoadAddress
))
285 s
->Printf("%*s", 18, "");
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
) {
293 m_flags
, name
.AsCString(""));
295 ConstString reexport_name
= GetReExportedSymbolName();
296 intptr_t shlib
= m_addr_range
.GetByteSize();
298 s
->Printf(" -> %s`%s\n", (const char *)shlib
, reexport_name
.GetCString());
300 s
->Printf(" -> %s\n", reexport_name
.GetCString());
305 " Sibling -> [%5llu] 0x%8.8x %s\n"
306 : "0x%16.16" PRIx64
" 0x%16.16" PRIx64
308 s
->Printf(format
, m_addr_range
.GetBaseAddress().GetOffset(), GetByteSize(),
309 m_flags
, name
.AsCString(""));
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;
318 const Address
&base_address
= m_addr_range
.GetBaseAddress();
319 Function
*function
= base_address
.CalculateSymbolContextFunction();
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();
326 ModuleSP
module_sp(base_address
.GetModule());
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();
335 // Set address for next line.
336 Address
addr(base_address
);
337 addr
.Slide(m_type_data
);
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
))
351 // If this line number is different than our first one, use it
353 if (sc_temp
.line_entry
.line
!= sc
.line_entry
.line
) {
354 m_type_data
= total_offset
;
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())
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())
374 // TODO: expose something in Process to figure out the
375 // size of a function prologue.
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
;
395 #define ENUM_TO_CSTRING(x) \
396 case eSymbolType##x: \
399 const char *Symbol::GetTypeAsString() const {
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
);
433 return "<unknown SymbolType>";
436 void Symbol::CalculateSymbolContext(SymbolContext
*sc
) {
437 // Symbols can reconstruct the symbol and the module in the symbol context
439 if (ValueIsAddress())
440 sc
->module_sp
= GetAddressRef().GetModule();
442 sc
->module_sp
.reset();
445 ModuleSP
Symbol::CalculateSymbolContextModule() {
446 if (ValueIsAddress())
447 return GetAddressRef().GetModule();
451 Symbol
*Symbol::CalculateSymbolContextSymbol() { return this; }
453 void Symbol::DumpSymbolContext(Stream
*s
) {
454 bool dumped_module
= false;
455 if (ValueIsAddress()) {
456 ModuleSP
module_sp(GetAddressRef().GetModule());
458 dumped_module
= true;
459 module_sp
->DumpSymbolContext(s
);
465 s
->Printf("Symbol{0x%8.8x}", GetID());
468 lldb::addr_t
Symbol::GetByteSize() const { return m_addr_range
.GetByteSize(); }
470 Symbol
*Symbol::ResolveReExportedSymbolInModuleSpec(
471 Target
&target
, ConstString
&reexport_name
, ModuleSpec
&module_spec
,
472 ModuleList
&seen_modules
) const {
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
);
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
481 module_spec
.GetFileSpec().ClearDirectory();
482 module_sp
= target
.GetImages().FindFirstModule(module_spec
);
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
))
492 lldb_private::SymbolContextList sc_list
;
493 module_sp
->FindSymbolsWithNameAndType(reexport_name
, eSymbolTypeAny
,
495 for (const SymbolContext
&sc
: sc_list
) {
496 if (sc
.symbol
->IsExternal())
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
502 seen_modules
.Append(module_sp
);
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
);
514 return result_symbol
;
520 Symbol
*Symbol::ResolveReExportedSymbol(Target
&target
) const {
521 ConstString
reexport_name(GetReExportedSymbolName());
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
);
534 lldb::addr_t
Symbol::GetFileAddress() const {
535 if (ValueIsAddress())
536 return GetAddressRef().GetFileAddress();
538 return LLDB_INVALID_ADDRESS
;
541 lldb::addr_t
Symbol::GetLoadAddress(Target
*target
) const {
542 if (ValueIsAddress())
543 return GetAddressRef().GetLoadAddress(target
);
545 return LLDB_INVALID_ADDRESS
;
548 ConstString
Symbol::GetName() const { return GetMangled().GetName(); }
550 ConstString
Symbol::GetNameNoArguments() const {
551 return GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments
);
554 lldb::addr_t
Symbol::ResolveCallableAddress(Target
&target
) const {
555 if (GetType() == lldb::eSymbolTypeUndefined
)
556 return LLDB_INVALID_ADDRESS
;
558 Address func_so_addr
;
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();
568 func_so_addr
= GetAddress();
569 is_indirect
= IsIndirect();
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
;
578 lldb::addr_t load_addr
=
579 func_so_addr
.GetCallableLoadAddress(&target
, is_indirect
);
581 if (load_addr
!= LLDB_INVALID_ADDRESS
) {
586 return LLDB_INVALID_ADDRESS
;
589 lldb::DisassemblerSP
Symbol::GetInstructions(const ExecutionContext
&exe_ctx
,
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(
595 module_sp
->GetArchitecture(), nullptr, flavor
, nullptr, nullptr,
596 exe_ctx
.GetTargetRef(), m_addr_range
, !prefer_file_cache
);
598 return lldb::DisassemblerSP();
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
);
616 bool Symbol::ContainsFileAddress(lldb::addr_t file_addr
) const {
617 return m_addr_range
.ContainsFileAddress(file_addr
);
620 bool Symbol::IsSyntheticWithAutoGeneratedName() const {
625 ConstString demangled
= m_mangled
.GetDemangledName();
626 return demangled
.GetStringRef().starts_with(GetSyntheticSymbolPrefix());
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()));
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))
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
))
668 if (!data
.ValidOffsetForDataOfSize(*offset_ptr
, 20))
670 const bool is_addr
= data
.GetU8(offset_ptr
) != 0;
671 const uint64_t value
= data
.GetU64(offset_ptr
);
673 m_addr_range
.GetBaseAddress().ResolveAddressUsingFileSections(value
,
676 m_addr_range
.GetBaseAddress().Clear();
677 m_addr_range
.GetBaseAddress().SetOffset(value
);
679 m_addr_range
.SetByteSize(data
.GetU64(offset_ptr
));
680 m_flags
= data
.GetU32(offset_ptr
);
684 /// The encoding format for the symbol is as follows:
687 /// uint16_t m_type_data;
688 /// uint16_t bitfield_data;
691 /// uint64_t file_addr_or_value;
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
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;
707 bitfields
|= 1u << 14;
709 bitfields
|= 1u << 13;
711 bitfields
|= 1u << 12;
712 if (m_size_is_sibling
)
713 bitfields
|= 1u << 11;
714 if (m_size_is_synthesized
)
715 bitfields
|= 1u << 10;
717 bitfields
|= 1u << 9;
718 if (m_demangled_is_synthesized
)
719 bitfields
|= 1u << 8;
720 if (m_contains_linker_annotations
)
721 bitfields
|= 1u << 7;
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
);
737 bool Symbol::operator==(const Symbol
&rhs
) const {
738 if (m_uid
!= rhs
.m_uid
)
740 if (m_type_data
!= rhs
.m_type_data
)
742 if (m_type_data_resolved
!= rhs
.m_type_data_resolved
)
744 if (m_is_synthetic
!= rhs
.m_is_synthetic
)
746 if (m_is_debug
!= rhs
.m_is_debug
)
748 if (m_is_external
!= rhs
.m_is_external
)
750 if (m_size_is_sibling
!= rhs
.m_size_is_sibling
)
752 if (m_size_is_synthesized
!= rhs
.m_size_is_synthesized
)
754 if (m_size_is_valid
!= rhs
.m_size_is_valid
)
756 if (m_demangled_is_synthesized
!= rhs
.m_demangled_is_synthesized
)
758 if (m_contains_linker_annotations
!= rhs
.m_contains_linker_annotations
)
760 if (m_is_weak
!= rhs
.m_is_weak
)
762 if (m_type
!= rhs
.m_type
)
764 if (m_mangled
!= rhs
.m_mangled
)
766 if (m_addr_range
.GetBaseAddress() != rhs
.m_addr_range
.GetBaseAddress())
768 if (m_addr_range
.GetByteSize() != rhs
.m_addr_range
.GetByteSize())
770 if (m_flags
!= rhs
.m_flags
)
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
);
789 if (!symbol
.value
&& !symbol
.address
) {
790 path
.report("symbol must have either a value or an address");
794 if (symbol
.value
&& symbol
.address
) {
795 path
.report("symbol cannot have both a value and an address");
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
);
836 if (type
== eSymbolTypeInvalid
) {
837 path
.report("invalid symbol type");
843 path
.report("expected string");