LLDB mainline
Symbol.cpp
Go to the documentation of this file.
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
10
11#include "lldb/Core/Address.h"
13#include "lldb/Core/Debugger.h"
14#include "lldb/Core/Module.h"
16#include "lldb/Core/Section.h"
20#include "lldb/Symbol/Symtab.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Target/Target.h"
24#include "lldb/Utility/Stream.h"
25#include "llvm/ADT/StringSwitch.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
37
38Symbol::Symbol(uint32_t symID, llvm::StringRef name, SymbolType type,
39 bool external, bool is_debug, bool is_trampoline,
40 bool is_artificial, const lldb::SectionSP &section_sp,
41 addr_t offset, addr_t size, bool size_is_valid,
42 bool contains_linker_annotations, uint32_t flags)
44 m_is_synthetic(is_artificial), m_is_debug(is_debug),
45 m_is_external(external), m_size_is_sibling(false),
46 m_size_is_synthesized(false), m_size_is_valid(size_is_valid || size > 0),
48 m_contains_linker_annotations(contains_linker_annotations),
49 m_is_weak(false), m_type(type), m_mangled(name),
50 m_addr_or_reexport(*this), m_flags(flags) {
52 m_addr_or_reexport.GetReExportInfo(*this).Clear();
53 else
54 m_addr_or_reexport.SetAddressRange(*this,
55 AddressRange(section_sp, offset, size));
56}
57
58Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type,
59 bool external, bool is_debug, bool is_trampoline,
60 bool is_artificial, const AddressRange &range,
61 bool size_is_valid, bool contains_linker_annotations,
62 uint32_t flags)
64 m_is_synthetic(is_artificial), m_is_debug(is_debug),
65 m_is_external(external), m_size_is_sibling(false),
67 m_size_is_valid(size_is_valid || range.GetByteSize() > 0),
69 m_contains_linker_annotations(contains_linker_annotations),
70 m_is_weak(false), m_type(type), m_mangled(mangled),
71 m_addr_or_reexport(*this), m_flags(flags) {
73 m_addr_or_reexport.SetReExportInfo(*this, ReExportInfo());
74 else
75 m_addr_or_reexport.SetAddressRange(*this, range);
76}
77
97
98const Symbol &Symbol::operator=(const Symbol &rhs) {
99 if (this != &rhs) {
100 SymbolContextScope::operator=(rhs);
101 m_uid = rhs.m_uid;
112 m_is_weak = rhs.m_is_weak;
113 m_mangled = rhs.m_mangled;
115 m_addr_or_reexport.GetAddressRange(*this).Clear();
116 m_type = rhs.m_type;
117 if (rhs.m_type == eSymbolTypeReExported)
118 m_addr_or_reexport.SetReExportInfo(
119 *this, rhs.m_addr_or_reexport.GetReExportInfo(*this));
120 else
121 m_addr_or_reexport.SetAddressRange(
122 *this, rhs.m_addr_or_reexport.GetAddressRange(*this));
123 m_flags = rhs.m_flags;
124 }
125 return *this;
126}
127
128llvm::Expected<Symbol> Symbol::FromJSON(const JSONSymbol &symbol,
129 SectionList *section_list) {
130 if (!section_list)
131 return llvm::createStringError("no section list provided");
132
133 if (!symbol.value && !symbol.address)
134 return llvm::createStringError(
135 "symbol must contain either a value or an address");
136
137 if (symbol.value && symbol.address)
138 return llvm::createStringError(
139 "symbol cannot contain both a value and an address");
140
141 const uint64_t size = symbol.size.value_or(0);
142 const bool is_artificial = false;
143 const bool is_trampoline = false;
144 const bool is_debug = false;
145 const bool external = false;
146 const bool size_is_valid = symbol.size.has_value();
147 const bool contains_linker_annotations = false;
148 const uint32_t flags = 0;
149
150 if (symbol.address) {
151 if (SectionSP section_sp =
152 section_list->FindSectionContainingFileAddress(*symbol.address)) {
153 const uint64_t offset = *symbol.address - section_sp->GetFileAddress();
154 return Symbol(symbol.id.value_or(0), Mangled(symbol.name),
155 symbol.type.value_or(eSymbolTypeAny), external, is_debug,
156 is_trampoline, is_artificial,
157 AddressRange(section_sp, offset, size), size_is_valid,
158 contains_linker_annotations, flags);
159 }
160 return llvm::createStringError(
161 llvm::formatv("no section found for address: {0:x}", *symbol.address));
162 }
163
164 // Absolute symbols encode the integer value in the m_offset of the
165 // AddressRange object and the section is set to nothing.
166 return Symbol(symbol.id.value_or(0), Mangled(symbol.name),
167 symbol.type.value_or(eSymbolTypeAny), external, is_debug,
168 is_trampoline, is_artificial,
169 AddressRange(SectionSP(), *symbol.value, size), size_is_valid,
170 contains_linker_annotations, flags);
171}
172
175 m_mangled.Clear();
176 m_type_data = 0;
177 m_type_data_resolved = false;
178 m_is_synthetic = false;
179 m_is_debug = false;
180 m_is_external = false;
181 m_size_is_sibling = false;
182 m_size_is_synthesized = false;
183 m_size_is_valid = false;
186 m_is_weak = false;
188 m_flags = 0;
189 m_addr_or_reexport.GetAddressRange(*this).Clear();
190}
191
194 return false;
195 return (bool)m_addr_or_reexport.GetAddressRange(*this)
196 .GetBaseAddress()
197 .GetSection();
198}
199
203
206 return ConstString();
207
208 return m_addr_or_reexport.GetReExportInfo(*this).name;
209}
210
213 return FileSpec();
214 const Symbol::ReExportInfo &reexport =
215 m_addr_or_reexport.GetReExportInfo(*this);
216 if (reexport.library_up)
217 return *reexport.library_up;
218 else
219 return FileSpec();
220}
221
224 m_addr_or_reexport.GetAddressRange(*this).Clear();
226 m_addr_or_reexport.SetReExportInfo(*this, ReExportInfo());
228 m_addr_or_reexport.GetReExportInfo(*this).name = name;
229}
230
233 return false;
235 m_addr_or_reexport.GetAddressRange(*this).Clear();
237 m_addr_or_reexport.GetReExportInfo(*this).library_up =
238 std::make_unique<FileSpec>(fspec);
239 return true;
240}
241
242uint32_t Symbol::GetSiblingIndex() const {
243 return m_size_is_sibling
244 ? m_addr_or_reexport.GetAddressRange(*this).GetByteSize()
245 : UINT32_MAX;
246}
247
249
251
253 Stream *s, lldb::DescriptionLevel level, Target *target,
254 std::optional<Stream::HighlightSettings> settings) const {
255 s->Printf("id = {0x%8.8x}", m_uid);
256
257 if (m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().GetSection()) {
258 if (ValueIsAddress()) {
259 const lldb::addr_t byte_size = GetByteSize();
260 if (byte_size > 0) {
261 s->PutCString(", range = ");
262 m_addr_or_reexport.GetAddressRange(*this).Dump(
265 } else {
266 s->PutCString(", address = ");
267 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().Dump(
270 }
271 } else
272 s->Printf(", value = 0x%16.16" PRIx64,
273 m_addr_or_reexport.GetAddressRange(*this)
274 .GetBaseAddress()
275 .GetOffset());
276 } else {
278 s->Printf(", sibling = %5" PRIu64,
279 m_addr_or_reexport.GetAddressRange(*this)
280 .GetBaseAddress()
281 .GetOffset());
282 else
283 s->Printf(", value = 0x%16.16" PRIx64,
284 m_addr_or_reexport.GetAddressRange(*this)
285 .GetBaseAddress()
286 .GetOffset());
287 }
288 if (ConstString demangled = m_mangled.GetDemangledName()) {
289 s->PutCString(", name=\"");
290 s->PutCStringColorHighlighted(demangled.GetStringRef(), settings);
291 s->PutCString("\"");
292 }
293 if (ConstString mangled_name = m_mangled.GetMangledName()) {
294 s->PutCString(", mangled=\"");
295 s->PutCStringColorHighlighted(mangled_name.GetStringRef(), settings);
296 s->PutCString("\"");
297 }
298}
299
300void Symbol::Dump(Stream *s, Target *target, uint32_t index,
301 Mangled::NamePreference name_preference) const {
302 s->Printf("[%5u] %6u %c%c%c %-15s ", index, GetID(), m_is_debug ? 'D' : ' ',
303 m_is_synthetic ? 'S' : ' ', m_is_external ? 'X' : ' ',
305
306 // Make sure the size of the symbol is up to date before dumping
307 GetByteSize();
308
309 ConstString name = GetMangled().GetName(name_preference);
310 if (ValueIsAddress()) {
311 if (!m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().Dump(
313 s->Printf("%*s", 18, "");
314
315 s->PutChar(' ');
316
317 if (!m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().Dump(
319 s->Printf("%*s", 18, "");
320
321 const char *format = m_size_is_sibling ? " Sibling -> [%5llu] 0x%8.8x %s\n"
322 : " 0x%16.16" PRIx64 " 0x%8.8x %s\n";
323 s->Printf(format, GetByteSize(), m_flags, name.AsCString(""));
324 } else if (m_type == eSymbolTypeReExported) {
325 s->Printf(
326 " 0x%8.8x %s",
327 m_flags, name.AsCString(""));
328
330 if (shlib)
331 s->Printf(" -> %s`%s\n", shlib.GetPath().c_str(),
332 GetReExportedSymbolName().GetCString());
333 else
334 s->Printf(" -> %s\n", GetReExportedSymbolName().GetCString());
335 } else {
336 const char *format =
338 ? "0x%16.16" PRIx64
339 " Sibling -> [%5llu] 0x%8.8x %s\n"
340 : "0x%16.16" PRIx64 " 0x%16.16" PRIx64
341 " 0x%8.8x %s\n";
342 s->Printf(
343 format,
344 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().GetOffset(),
345 GetByteSize(), m_flags, name.AsCString(""));
346 }
347}
348
353
354 const Address &base_address =
355 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress();
356 Function *function = base_address.CalculateSymbolContextFunction();
357 if (function) {
358 // Functions have line entries which can also potentially have end of
359 // prologue information. So if this symbol points to a function, use
360 // the prologue information from there.
361 m_type_data = function->GetPrologueByteSize();
362 } else {
363 ModuleSP module_sp(base_address.GetModule());
364 SymbolContext sc;
365 if (module_sp) {
366 uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress(
367 base_address, eSymbolContextLineEntry, sc);
368 if (resolved_flags & eSymbolContextLineEntry) {
369 // Default to the end of the first line entry.
371
372 // Set address for next line.
373 Address addr(base_address);
374 addr.Slide(m_type_data);
375
376 // Check the first few instructions and look for one that has a
377 // line number that is different than the first entry. This is also
378 // done in Function::GetPrologueByteSize().
379 uint16_t total_offset = m_type_data;
380 for (int idx = 0; idx < 6; ++idx) {
381 SymbolContext sc_temp;
382 resolved_flags = module_sp->ResolveSymbolContextForAddress(
383 addr, eSymbolContextLineEntry, sc_temp);
384 // Make sure we got line number information...
385 if (!(resolved_flags & eSymbolContextLineEntry))
386 break;
387
388 // If this line number is different than our first one, use it
389 // and we're done.
390 if (sc_temp.line_entry.line != sc.line_entry.line) {
391 m_type_data = total_offset;
392 break;
393 }
394
395 // Slide addr up to the next line address.
396 addr.Slide(sc_temp.line_entry.range.GetByteSize());
397 total_offset += sc_temp.line_entry.range.GetByteSize();
398 // If we've gone too far, bail out.
399 if (total_offset >=
400 m_addr_or_reexport.GetAddressRange(*this).GetByteSize())
401 break;
402 }
403
404 // Sanity check - this may be a function in the middle of code that
405 // has debug information, but not for this symbol. So the line
406 // entries surrounding us won't lie inside our function. In that
407 // case, the line entry will be bigger than we are, so we do that
408 // quick check and if that is true, we just return 0.
409 if (m_type_data >=
410 m_addr_or_reexport.GetAddressRange(*this).GetByteSize())
411 m_type_data = 0;
412 } else {
413 // TODO: expose something in Process to figure out the
414 // size of a function prologue.
415 m_type_data = 0;
416 }
417 }
418 }
419 }
420 return m_type_data;
421 }
422 return 0;
423}
424
425bool Symbol::Compare(ConstString name, SymbolType type) const {
426 if (type == eSymbolTypeAny || m_type == type) {
427 const Mangled &mangled = GetMangled();
428 return mangled.GetMangledName() == name ||
429 mangled.GetDemangledName() == name;
430 }
431 return false;
432}
433
434const char *Symbol::GetTypeAsString() const {
435 return GetTypeAsString(static_cast<lldb::SymbolType>(m_type));
436}
437
439 // Symbols can reconstruct the symbol and the module in the symbol context
440 sc->symbol = this;
441 if (ValueIsAddress())
443 else
444 sc->module_sp.reset();
445}
446
452
454
456 bool dumped_module = false;
457 if (ValueIsAddress()) {
458 ModuleSP module_sp(GetAddressRef().GetModule());
459 if (module_sp) {
460 dumped_module = true;
461 module_sp->DumpSymbolContext(s);
462 }
463 }
464 if (dumped_module)
465 s->PutCString(", ");
466
467 s->Printf("Symbol{0x%8.8x}", GetID());
468}
469
472 return 0;
473 else
474 return m_addr_or_reexport.GetAddressRange(*this).GetByteSize();
475}
476
478 Target &target, ConstString reexport_name, ModuleSpec &module_spec,
479 ModuleList &seen_modules) const {
480 ModuleSP module_sp;
481 if (module_spec.GetFileSpec()) {
482 // Try searching for the module file spec first using the full path
483 module_sp = target.GetImages().FindFirstModule(module_spec);
484 if (!module_sp) {
485 // Next try and find the module by basename in case environment variables
486 // or other runtime trickery causes shared libraries to be loaded from
487 // alternate paths
488 module_spec.GetFileSpec().ClearDirectory();
489 module_sp = target.GetImages().FindFirstModule(module_spec);
490 }
491 }
492
493 if (module_sp) {
494 // There should not be cycles in the reexport list, but we don't want to
495 // crash if there are so make sure we haven't seen this before:
496 if (!seen_modules.AppendIfNeeded(module_sp))
497 return nullptr;
498
500 module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny,
501 sc_list);
502 for (const SymbolContext &sc : sc_list) {
503 if (!sc.symbol->IsExternal() && !sc.symbol->IsWeak())
504 continue;
505 if (sc.symbol->GetType() == eSymbolTypeUndefined)
506 continue;
507 // Don't return a symbol that itself only re-exports the definition
508 // (e.g. an ELF filter library's placeholder): the real definition is
509 // found by following the module-level re-exports below, which also
510 // guards against cycles.
511 if (sc.symbol->GetType() == eSymbolTypeReExported)
512 continue;
513 return sc.symbol;
514 }
515 // If we didn't find the symbol in this module, it may be because this
516 // module re-exports some whole other library. We have to search those as
517 // well:
518 seen_modules.Append(module_sp);
519
520 FileSpecList reexported_libraries =
521 module_sp->GetObjectFile()->GetReExportedLibraries();
522 size_t num_reexported_libraries = reexported_libraries.GetSize();
523 for (size_t idx = 0; idx < num_reexported_libraries; idx++) {
524 ModuleSpec reexported_module_spec;
525 reexported_module_spec.GetFileSpec() =
526 reexported_libraries.GetFileSpecAtIndex(idx);
528 target, reexport_name, reexported_module_spec, seen_modules);
529 if (result_symbol)
530 return result_symbol;
531 }
532 }
533 return nullptr;
534}
535
537 Target &target, const lldb::ModuleSP &containing_module_sp) const {
538 ConstString reexport_name(GetReExportedSymbolName());
539 ModuleList seen_modules;
540
541 if (reexport_name) {
542 // Search the library recorded on the symbol itself first.
543 ModuleSpec module_spec;
545 if (module_spec.GetFileSpec()) {
547 target, reexport_name, module_spec, seen_modules))
548 return result;
549 }
550 } else {
551 // This symbol isn't itself marked as a re-export. Some formats (ELF's
552 // DT_FILTER / DT_AUXILIARY) have no per-symbol tagging: the dynamic
553 // linker always resolves through the filtee(s) first and only falls
554 // back to the filter object's own definition if none of them provide
555 // it, even when the filter also provides a genuine implementation of
556 // the same symbol.
557 ObjectFile *object_file =
558 containing_module_sp ? containing_module_sp->GetObjectFile() : nullptr;
559 if (!object_file ||
561 return nullptr;
562
563 // Only exported (global or weak) definitions take part in dynamic
564 // linking, so local symbols are never shadowed by a filtee.
565 if (!IsExternal() && !IsWeak())
566 return nullptr;
567
568 // Use this symbol's own (version-suffix-stripped) name so the filtees
569 // below are searched for it.
570 reexport_name = GetName();
571 if (!reexport_name)
572 return nullptr;
574 reexport_name = ConstString(object_file->StripLinkerSymbolAnnotations(
575 reexport_name.GetStringRef()));
576 }
577
578 // The recorded library is only the first candidate: the module defining
579 // this symbol may re-export several libraries which must be searched in
580 // the order they are declared (e.g. an ELF filter library with multiple
581 // DT_FILTER / DT_AUXILIARY entries). seen_modules is shared with the
582 // search above so no library is searched twice.
583 if (containing_module_sp) {
584 if (ObjectFile *object_file = containing_module_sp->GetObjectFile()) {
585 FileSpecList reexported_libraries = object_file->GetReExportedLibraries();
586 const size_t count = reexported_libraries.GetSize();
587 for (size_t idx = 0; idx < count; ++idx) {
588 ModuleSpec reexported_module_spec;
589 reexported_module_spec.GetFileSpec() =
590 reexported_libraries.GetFileSpecAtIndex(idx);
592 target, reexport_name, reexported_module_spec, seen_modules))
593 return result;
594 }
595 }
596 }
597
598 return nullptr;
599}
600
602 if (ValueIsAddress())
603 return GetAddressRef().GetFileAddress();
604 else
606}
607
609 if (ValueIsAddress())
610 return GetAddressRef().GetLoadAddress(target);
611 else
613}
614
616
620
622 Target &target, const lldb::ModuleSP &containing_module_sp) const {
625
626 Address func_so_addr;
627
628 bool is_indirect = IsIndirect();
629 // A symbol from an ELF filter/auxiliary library is resolved through its
630 // filtee(s) first, falling back to its own definition only if none of them
631 // provide it, mirroring what the dynamic linker does.
632 if (Symbol *reexported_symbol =
633 ResolveReExportedSymbol(target, containing_module_sp)) {
634 func_so_addr = reexported_symbol->GetAddress();
635 is_indirect = reexported_symbol->IsIndirect();
636 } else if (GetType() != eSymbolTypeReExported) {
637 func_so_addr = GetAddress();
638 is_indirect = IsIndirect();
639 }
640
641 if (func_so_addr.IsValid()) {
642 if (!target.GetProcessSP() && is_indirect) {
643 // can't resolve indirect symbols without calling a function...
645 }
646
647 lldb::addr_t load_addr =
648 func_so_addr.GetCallableLoadAddress(&target, is_indirect);
649
650 if (load_addr != LLDB_INVALID_ADDRESS) {
651 return load_addr;
652 }
653 }
654
656}
657
659 const char *flavor,
660 bool prefer_file_cache) {
661 ModuleSP module_sp(
662 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().GetModule());
663 if (module_sp && exe_ctx.HasTargetScope()) {
665 module_sp->GetArchitecture(), nullptr, flavor, nullptr, nullptr,
666 exe_ctx.GetTargetRef(), m_addr_or_reexport.GetAddressRange(*this),
667 !prefer_file_cache);
668 }
669 return lldb::DisassemblerSP();
670}
671
672bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
673 bool prefer_file_cache, Stream &strm) {
674 lldb::DisassemblerSP disassembler_sp =
675 GetInstructions(exe_ctx, flavor, prefer_file_cache);
676 if (disassembler_sp) {
677 const bool show_address = true;
678 const bool show_bytes = false;
679 const bool show_control_flow_kind = false;
680 disassembler_sp->GetInstructionList().Dump(
681 &strm, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
682 return true;
683 }
684 return false;
685}
686
688 return m_addr_or_reexport.GetAddressRange(*this).ContainsFileAddress(
689 file_addr);
690}
691
693 if (!IsSynthetic())
694 return false;
695 if (!m_mangled)
696 return true;
697 ConstString demangled = m_mangled.GetDemangledName();
698 return demangled.GetStringRef().starts_with(GetSyntheticSymbolPrefix());
699}
700
702 if (m_is_synthetic && !m_mangled) {
703 // Synthetic symbol names don't mean anything, but they do uniquely
704 // identify individual symbols so we give them a unique name. The name
705 // starts with the synthetic symbol prefix, followed by a unique number.
706 // Typically the UserID of a real symbol is the symbol table index of the
707 // symbol in the object file's symbol table(s), so it will be the same
708 // every time you read in the object file. We want the same persistence for
709 // synthetic symbols so that users can identify them across multiple debug
710 // sessions, to understand crashes in those symbols and to reliably set
711 // breakpoints on them.
712 llvm::SmallString<256> name;
713 llvm::raw_svector_ostream os(name);
715 << llvm::format_hex_no_prefix(m_addr_or_reexport.GetAddressRange(*this)
716 .GetBaseAddress()
717 .GetFileAddress(),
718 0);
719 m_mangled.SetDemangledName(ConstString(os.str()));
720 }
721}
722
723bool Symbol::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
724 const SectionList *section_list,
725 const StringTableReader &strtab) {
726 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 8))
727 return false;
728 m_uid = data.GetU32(offset_ptr);
729 m_type_data = data.GetU16(offset_ptr);
730 const uint16_t bitfields = data.GetU16(offset_ptr);
731 m_type_data_resolved = (1u << 15 & bitfields) != 0;
732 m_is_synthetic = (1u << 14 & bitfields) != 0;
733 m_is_debug = (1u << 13 & bitfields) != 0;
734 m_is_external = (1u << 12 & bitfields) != 0;
735 m_size_is_sibling = (1u << 11 & bitfields) != 0;
736 m_size_is_synthesized = (1u << 10 & bitfields) != 0;
737 m_size_is_valid = (1u << 9 & bitfields) != 0;
738 m_demangled_is_synthesized = (1u << 8 & bitfields) != 0;
739 m_contains_linker_annotations = (1u << 7 & bitfields) != 0;
740 m_is_weak = (1u << 6 & bitfields) != 0;
741 m_type = bitfields & 0x003f;
742 if (!m_mangled.Decode(data, offset_ptr, strtab))
743 return false;
744 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 20))
745 return false;
747 const bool is_addr = data.GetU8(offset_ptr) != 0;
748 Address &base_addr =
749 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress();
750 if (is_addr) {
751 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 28))
752 return false;
753 const user_id_t sect_id = data.GetU64(offset_ptr);
754 const addr_t sect_offset = data.GetU64(offset_ptr);
755 SectionSP section_sp;
756 if (section_list)
757 section_sp = section_list->FindSectionByID(sect_id);
758 // The cache data doesn't match this binary's sections.
759 if (!section_sp)
760 return false;
761 base_addr = Address(section_sp, sect_offset);
762 } else {
763 base_addr.Clear();
764 base_addr.SetOffset(data.GetU64(offset_ptr));
765 }
766 m_addr_or_reexport.GetAddressRange(*this).SetByteSize(
767 data.GetU64(offset_ptr));
768 } else {
769 m_addr_or_reexport.GetReExportInfo(*this).name =
770 ConstString(strtab.Get(data.GetU32(offset_ptr)));
771 llvm::StringRef filename = strtab.Get(data.GetU32(offset_ptr));
772 if (!filename.empty())
773 m_addr_or_reexport.GetReExportInfo(*this).library_up =
774 std::make_unique<FileSpec>(filename);
775 }
776 m_flags = data.GetU32(offset_ptr);
777 return true;
778}
779
780// If the size of Symbol has changed, the Encode and
781// Decode methods also likely need to be updated and
782// the DataFileCache version number in Symtab::Encode
783// will need to be incremented as well.
784#if __SIZEOF_POINTER__ == 8
785static_assert(sizeof(lldb_private::Symbol) == 72,
786 "Symbol size has changed, Symbol::Encode and Decode likely need "
787 "to be updated");
788#endif
789
790/// The encoding format for the symbol is as follows:
791///
792/// uint32_t m_uid;
793/// uint16_t m_type_data;
794/// uint16_t bitfield_data;
795/// Mangled mangled;
796/// uint8_t is_addr;
797/// if (is_addr) {
798/// uint64_t section_id;
799/// uint64_t section_offset;
800/// } else {
801/// uint64_t value;
802/// }
803/// uint64_t size;
804/// uint32_t flags;
805///
806/// The only tricky thing in this encoding is encoding all of the bits in the
807/// bitfields. We use a trick to store all bitfields as a 16 bit value and we
808/// do the same thing when decoding the symbol. There are test that ensure this
809/// encoding works for each individual bit. Everything else is very easy to
810/// store.
811void Symbol::Encode(DataEncoder &file, ConstStringTable &strtab) const {
812 file.AppendU32(m_uid);
814 uint16_t bitfields = m_type;
816 bitfields |= 1u << 15;
817 if (m_is_synthetic)
818 bitfields |= 1u << 14;
819 if (m_is_debug)
820 bitfields |= 1u << 13;
821 if (m_is_external)
822 bitfields |= 1u << 12;
824 bitfields |= 1u << 11;
826 bitfields |= 1u << 10;
827 if (m_size_is_valid)
828 bitfields |= 1u << 9;
830 bitfields |= 1u << 8;
832 bitfields |= 1u << 7;
833 if (m_is_weak)
834 bitfields |= 1u << 6;
835 file.AppendU16(bitfields);
836 m_mangled.Encode(file, strtab);
838 // A symbol's value might be an address, or it might be a constant. If the
839 // symbol's base address doesn't have a section, then it is a constant
840 // value. If it does have a section, we encode the section ID and the
841 // offset within it rather than the file address, because the same binary
842 // (same UUID) can have its segments placed at different file addresses,
843 // and not all by the same amount, as happens in the Darwin shared cache.
844 const Address &base_addr =
845 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress();
846 SectionSP section_sp = base_addr.GetSection();
847 file.AppendU8(section_sp != nullptr);
848 if (section_sp) {
849 file.AppendU64(section_sp->GetID());
850 file.AppendU64(base_addr.GetOffset());
851 } else {
852 file.AppendU64(base_addr.GetFileAddress());
853 }
854 file.AppendU64(m_addr_or_reexport.GetAddressRange(*this).GetByteSize());
855 } else {
856 file.AppendU32(strtab.Add(m_addr_or_reexport.GetReExportInfo(*this).name));
857 if (m_addr_or_reexport.GetReExportInfo(*this).library_up) {
858 ConstString filepath(m_addr_or_reexport.GetReExportInfo(*this)
859 .library_up->GetPath()
860 .c_str());
861 file.AppendU32(strtab.Add(filepath));
862 } else {
863 file.AppendU32(strtab.Add(ConstString("")));
864 }
865 }
866 file.AppendU32(m_flags);
867}
868
869bool Symbol::operator==(const Symbol &rhs) const {
870 if (m_uid != rhs.m_uid)
871 return false;
872 if (m_type_data != rhs.m_type_data)
873 return false;
875 return false;
877 return false;
878 if (m_is_debug != rhs.m_is_debug)
879 return false;
880 if (m_is_external != rhs.m_is_external)
881 return false;
883 return false;
885 return false;
887 return false;
889 return false;
891 return false;
892 if (m_is_weak != rhs.m_is_weak)
893 return false;
894 if (m_type != rhs.m_type)
895 return false;
896 if (m_mangled != rhs.m_mangled)
897 return false;
898 if (m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress() !=
900 return false;
901 if (m_addr_or_reexport.GetAddressRange(*this).GetByteSize() !=
903 return false;
904 if (m_flags != rhs.m_flags)
905 return false;
906 return true;
907}
908
909#define ENUM_TO_CSTRING(x) \
910 case eSymbolType##x: \
911 return #x;
912
914 switch (symbol_type) {
916 ENUM_TO_CSTRING(Absolute);
917 ENUM_TO_CSTRING(Code);
918 ENUM_TO_CSTRING(Resolver);
919 ENUM_TO_CSTRING(Data);
920 ENUM_TO_CSTRING(Trampoline);
923 ENUM_TO_CSTRING(SourceFile);
924 ENUM_TO_CSTRING(HeaderFile);
926 ENUM_TO_CSTRING(CommonBlock);
928 ENUM_TO_CSTRING(Local);
929 ENUM_TO_CSTRING(Param);
931 ENUM_TO_CSTRING(VariableType);
933 ENUM_TO_CSTRING(LineHeader);
934 ENUM_TO_CSTRING(ScopeBegin);
935 ENUM_TO_CSTRING(ScopeEnd);
936 ENUM_TO_CSTRING(Additional);
937 ENUM_TO_CSTRING(Compiler);
938 ENUM_TO_CSTRING(Instrumentation);
939 ENUM_TO_CSTRING(Undefined);
940 ENUM_TO_CSTRING(ObjCClass);
941 ENUM_TO_CSTRING(ObjCMetaClass);
942 ENUM_TO_CSTRING(ObjCIVar);
943 ENUM_TO_CSTRING(ReExported);
944 }
945 return "<unknown SymbolType>";
946}
947
949 std::string str_lower = llvm::StringRef(str).lower();
950 return llvm::StringSwitch<lldb::SymbolType>(str_lower)
951 .Case("absolute", eSymbolTypeAbsolute)
952 .Case("code", eSymbolTypeCode)
953 .Case("resolver", eSymbolTypeResolver)
954 .Case("data", eSymbolTypeData)
955 .Case("trampoline", eSymbolTypeTrampoline)
956 .Case("runtime", eSymbolTypeRuntime)
957 .Case("exception", eSymbolTypeException)
958 .Case("sourcefile", eSymbolTypeSourceFile)
959 .Case("headerfile", eSymbolTypeHeaderFile)
960 .Case("objectfile", eSymbolTypeObjectFile)
961 .Case("commonblock", eSymbolTypeCommonBlock)
962 .Case("block", eSymbolTypeBlock)
963 .Case("local", eSymbolTypeLocal)
964 .Case("param", eSymbolTypeParam)
965 .Case("variable", eSymbolTypeVariable)
966 .Case("variableType", eSymbolTypeVariableType)
967 .Case("lineentry", eSymbolTypeLineEntry)
968 .Case("lineheader", eSymbolTypeLineHeader)
969 .Case("scopebegin", eSymbolTypeScopeBegin)
970 .Case("scopeend", eSymbolTypeScopeEnd)
971 .Case("additional,", eSymbolTypeAdditional)
972 .Case("compiler", eSymbolTypeCompiler)
973 .Case("instrumentation", eSymbolTypeInstrumentation)
974 .Case("undefined", eSymbolTypeUndefined)
975 .Case("objcclass", eSymbolTypeObjCClass)
976 .Case("objcmetaclass", eSymbolTypeObjCMetaClass)
977 .Case("objcivar", eSymbolTypeObjCIVar)
978 .Case("reexported", eSymbolTypeReExported)
979 .Default(eSymbolTypeInvalid);
980}
981
986
987const AddressRange &
989 assert(sym.GetType() != eSymbolTypeReExported);
990 return m_addr_range;
991}
992
998
1001 assert(sym.GetType() == eSymbolTypeReExported);
1002 return m_reexport_info;
1003}
1004
1006 Symbol &sym, const AddressRange addr_range) {
1007 if (sym.GetType() == eSymbolTypeReExported) {
1008 m_reexport_info.Clear();
1010 }
1011 m_addr_range = addr_range;
1012}
1013
1015 Symbol &sym, const Symbol::ReExportInfo reexport_info) {
1016 if (sym.GetType() != eSymbolTypeReExported) {
1017 m_addr_range.Clear();
1019 }
1020 m_reexport_info = reexport_info;
1021}
1022
1023namespace llvm {
1024namespace json {
1025
1026bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
1027 llvm::json::Path path) {
1028 llvm::json::ObjectMapper o(value, path);
1029 const bool mapped = o && o.map("value", symbol.value) &&
1030 o.map("address", symbol.address) &&
1031 o.map("size", symbol.size) && o.map("id", symbol.id) &&
1032 o.map("type", symbol.type) && o.map("name", symbol.name);
1033
1034 if (!mapped)
1035 return false;
1036
1037 if (!symbol.value && !symbol.address) {
1038 path.report("symbol must have either a value or an address");
1039 return false;
1040 }
1041
1042 if (symbol.value && symbol.address) {
1043 path.report("symbol cannot have both a value and an address");
1044 return false;
1045 }
1046
1047 return true;
1048}
1049
1050bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
1051 llvm::json::Path path) {
1052 if (auto str = value.getAsString()) {
1053 llvm::StringRef str_ref = str.value_or("");
1054 type = Symbol::GetTypeFromString(str_ref.data());
1055
1056 if (type == eSymbolTypeInvalid) {
1057 path.report("invalid symbol type");
1058 return false;
1059 }
1060
1061 return true;
1062 }
1063 path.report("expected string");
1064 return false;
1065}
1066} // namespace json
1067} // namespace llvm
#define ENUM_TO_CSTRING(x)
Definition Symbol.cpp:909
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition Address.cpp:303
lldb::addr_t GetCallableLoadAddress(Target *target, bool is_indirect=false) const
Get the load address as a callable code load address.
Definition Address.cpp:328
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition Address.h:426
void Clear()
Clear the object's state.
Definition Address.h:181
Function * CalculateSymbolContextFunction() const
Definition Address.cpp:860
@ DumpStyleFileAddress
Display as the file address (if any).
Definition Address.h:87
@ DumpStyleLoadAddress
Display as the load address (if resolved).
Definition Address.h:99
bool Slide(int64_t offset)
Definition Address.h:446
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition Address.cpp:275
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:283
lldb::addr_t GetOffset() const
Get the section relative offset value.
Definition Address.h:329
bool IsValid() const
Check if the object state is valid.
Definition Address.h:355
bool SetOffset(lldb::addr_t offset)
Set accessor for the offset.
Definition Address.h:435
A class that describes a single lexical block.
Definition Block.h:41
Many cache files require string tables to store data efficiently.
uint32_t Add(ConstString s)
Add a string into the string table.
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
const char * AsCString(const char *value_if_empty) const
Get the string value as a C string.
An binary data encoding class.
Definition DataEncoder.h:42
void AppendU32(uint32_t value)
void AppendU8(uint8_t value)
Append a unsigned integer to the end of the owned data.
void AppendU16(uint16_t value)
void AppendU64(uint64_t value)
An data extractor class.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const
Test the availability of length bytes of data from offset.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch, const char *plugin_name, const char *flavor, const char *cpu, const char *features, Target &target, llvm::ArrayRef< AddressRange > disasm_ranges, bool force_live_memory=false)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
Target & GetTargetRef() const
Returns a reference to the target object.
A file collection class.
const FileSpec & GetFileSpecAtIndex(size_t idx) const
Get file at index.
size_t GetSize() const
Get the number of files in the file list.
A file utility class.
Definition FileSpec.h:56
void ClearDirectory()
Clear the directory in this object.
Definition FileSpec.cpp:373
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
A class that describes a function.
Definition Function.h:386
uint32_t GetPrologueByteSize()
Get the size of the prologue instructions for this function.
Definition Function.cpp:592
A class that handles mangled names.
Definition Mangled.h:36
@ ePreferDemangledWithoutArguments
Definition Mangled.h:41
ConstString GetMangledName() const
Mangled name get accessor.
Definition Mangled.h:169
ConstString GetDemangledName() const
Demangled name get accessor.
Definition Mangled.cpp:238
ConstString GetName(NamePreference preference=ePreferDemangled) const
Best name get accessor.
Definition Mangled.cpp:297
ConstString GetDisplayDemangledName() const
Display demangled name get accessor.
Definition Mangled.cpp:282
A collection class for Module objects.
Definition ModuleList.h:127
lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const
Finds the first module whose file specification matches module_spec.
bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify=true)
Append a module to the module list, if it is not already there.
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
FileSpec & GetFileSpec()
Definition ModuleSpec.h:57
A plug-in interface definition class for object file parsers.
Definition ObjectFile.h:46
virtual llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
Definition ObjectFile.h:710
virtual bool ReExportedLibrariesShadowLocalDefinitions() const
Whether a symbol that this object file has not itself tagged as a re-export can still be shadowed by ...
Definition ObjectFile.h:382
lldb::SectionSP FindSectionByID(lldb::user_id_t sect_id) const
Definition Section.cpp:584
lldb::SectionSP FindSectionContainingFileAddress(lldb::addr_t addr, uint32_t depth=UINT32_MAX) const
Definition Section.cpp:621
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
size_t PutChar(char ch)
Definition Stream.cpp:131
void PutCStringColorHighlighted(llvm::StringRef text, std::optional< HighlightSettings > settings=std::nullopt)
Output a C string to the stream with color highlighting.
Definition Stream.cpp:73
Many cache files require string tables to store data efficiently.
llvm::StringRef Get(uint32_t offset) const
Defines a list of symbol context objects.
"lldb/Symbol/SymbolContextScope.h" Inherit from this if your object is part of a symbol context and c...
Defines a symbol context baton that can be handed other debug core functions.
lldb::ModuleSP module_sp
The Module for a given query.
Symbol * symbol
The Symbol for a given query.
LineEntry line_entry
The LineEntry for a given query.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, const SectionList *section_list, const StringTableReader &strtab)
Decode a serialized version of this object from data.
Definition Symbol.cpp:723
uint32_t GetSiblingIndex() const
Definition Symbol.cpp:242
uint16_t m_is_external
Definition Symbol.h:398
uint32_t GetID() const
Definition Symbol.h:152
lldb::addr_t GetLoadAddress(Target *target) const
Definition Symbol.cpp:608
bool ValueIsAddress() const
Definition Symbol.cpp:192
bool IsExternal() const
Definition Symbol.h:225
uint16_t m_type_data_resolved
Definition Symbol.h:391
void SetReExportedSymbolName(ConstString name)
Definition Symbol.cpp:222
void SetType(lldb::SymbolType type)
Definition Symbol.h:199
void CalculateSymbolContext(SymbolContext *sc) override
Reconstruct the object's symbol context into sc.
Definition Symbol.cpp:438
bool IsIndirect() const
Definition Symbol.cpp:250
void SynthesizeNameIfNeeded() const
Definition Symbol.cpp:701
const char * GetTypeAsString() const
Definition Symbol.cpp:434
bool IsSynthetic() const
Definition Symbol.h:211
uint16_t m_is_synthetic
Definition Symbol.h:393
uint16_t m_demangled_is_synthesized
Definition Symbol.h:405
lldb::DisassemblerSP GetInstructions(const ExecutionContext &exe_ctx, const char *flavor, bool prefer_file_cache)
Definition Symbol.cpp:658
bool ContainsLinkerAnnotations() const
Definition Symbol.h:267
lldb::addr_t GetFileAddress() const
Definition Symbol.cpp:601
void DumpSymbolContext(Stream *s) override
Dump the object's symbol context to the stream s.
Definition Symbol.cpp:455
lldb::ModuleSP CalculateSymbolContextModule() override
Definition Symbol.cpp:447
bool ContainsFileAddress(lldb::addr_t file_addr) const
Definition Symbol.cpp:687
Mangled & GetMangled()
Definition Symbol.h:162
static lldb::SymbolType GetTypeFromString(const char *str)
Definition Symbol.cpp:948
uint16_t m_contains_linker_annotations
Definition Symbol.h:408
uint16_t m_size_is_valid
Definition Symbol.h:404
bool IsTrampoline() const
Definition Symbol.cpp:248
Address & GetAddressRef()
Definition Symbol.h:78
const Symbol & operator=(const Symbol &rhs)
Definition Symbol.cpp:98
bool IsSyntheticWithAutoGeneratedName() const
Definition Symbol.cpp:692
void Encode(DataEncoder &encoder, ConstStringTable &strtab) const
Encode this object into a data encoder object.
Definition Symbol.cpp:811
ConstString GetReExportedSymbolName() const
Definition Symbol.cpp:204
bool Compare(ConstString name, lldb::SymbolType type) const
Definition Symbol.cpp:425
uint16_t m_is_debug
Definition Symbol.h:396
bool SetReExportedSymbolSharedLibrary(const FileSpec &fspec)
Definition Symbol.cpp:231
void GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target, std::optional< Stream::HighlightSettings > settings=std::nullopt) const
Definition Symbol.cpp:252
bool operator==(const Symbol &rhs) const
Definition Symbol.cpp:869
static llvm::StringRef GetSyntheticSymbolPrefix()
Definition Symbol.h:296
lldb::addr_t GetByteSize() const
Definition Symbol.cpp:470
ConstString GetName() const
Definition Symbol.cpp:615
lldb::SymbolType GetType() const
Definition Symbol.h:197
struct lldb_private::Symbol::AddrRangeOrReExport m_addr_or_reexport
Address GetAddress() const
Definition Symbol.h:98
ConstString GetNameNoArguments() const
Definition Symbol.cpp:617
uint16_t m_size_is_sibling
Definition Symbol.h:399
FileSpec GetReExportedSymbolSharedLibrary() const
Definition Symbol.cpp:211
uint16_t m_is_weak
Definition Symbol.h:411
bool IsWeak() const
Definition Symbol.h:233
Symbol * ResolveReExportedSymbolInModuleSpec(Target &target, ConstString reexport_name, lldb_private::ModuleSpec &module_spec, lldb_private::ModuleList &seen_modules) const
Definition Symbol.cpp:477
uint32_t GetPrologueByteSize()
Definition Symbol.cpp:349
Symbol * ResolveReExportedSymbol(Target &target, const lldb::ModuleSP &containing_module_sp=lldb::ModuleSP()) const
Find the symbol this re-exported symbol resolves to.
Definition Symbol.cpp:536
uint16_t m_type_data
Definition Symbol.h:390
lldb::addr_t ResolveCallableAddress(Target &target, const lldb::ModuleSP &containing_module_sp) const
Definition Symbol.cpp:621
ConstString GetDisplayName() const
Definition Symbol.cpp:200
bool GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor, bool prefer_file_cache, Stream &strm)
Definition Symbol.cpp:672
uint16_t m_size_is_synthesized
Definition Symbol.h:401
Symbol * CalculateSymbolContextSymbol() override
Definition Symbol.cpp:453
static llvm::Expected< Symbol > FromJSON(const JSONSymbol &symbol, SectionList *section_list)
Definition Symbol.cpp:128
void Dump(Stream *s, Target *target, uint32_t index, Mangled::NamePreference name_preference=Mangled::ePreferDemangled) const
Definition Symbol.cpp:300
const lldb::ProcessSP & GetProcessSP() const
Definition Target.cpp:335
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1283
#define LLDB_INVALID_ADDRESS
#define UINT32_MAX
A class that represents a running process on the host machine.
bool fromJSON(const llvm::json::Value &value, SymbolValue &data, llvm::json::Path path)
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
uint64_t offset_t
Definition lldb-types.h:86
SymbolType
Symbol types.
@ eSymbolTypeUndefined
@ eSymbolTypeVariableType
@ eSymbolTypeObjCMetaClass
@ eSymbolTypeReExported
@ eSymbolTypeObjCClass
@ eSymbolTypeObjectFile
@ eSymbolTypeTrampoline
@ eSymbolTypeResolver
@ eSymbolTypeSourceFile
@ eSymbolTypeException
@ eSymbolTypeVariable
@ eSymbolTypeAbsolute
@ eSymbolTypeAdditional
When symbols take more than one entry, the extra entries get this type.
@ eSymbolTypeInstrumentation
@ eSymbolTypeHeaderFile
@ eSymbolTypeCommonBlock
@ eSymbolTypeCompiler
@ eSymbolTypeLineHeader
@ eSymbolTypeObjCIVar
@ eSymbolTypeLineEntry
@ eSymbolTypeScopeBegin
@ eSymbolTypeScopeEnd
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::Section > SectionSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
std::optional< uint64_t > address
Definition Symbol.h:28
std::optional< uint64_t > id
Definition Symbol.h:31
std::optional< lldb::SymbolType > type
Definition Symbol.h:32
std::optional< uint64_t > value
Definition Symbol.h:29
std::optional< uint64_t > size
Definition Symbol.h:30
A line table entry class.
Definition LineEntry.h:21
AddressRange range
The section offset address range for this line entry.
Definition LineEntry.h:137
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
Definition LineEntry.h:151
void SetReExportInfo(Symbol &sym, const ReExportInfo reexport_info)
Definition Symbol.cpp:1014
void SetAddressRange(Symbol &sym, const AddressRange addr_range)
Definition Symbol.cpp:1005
ReExportInfo & GetReExportInfo(Symbol &sym)
Definition Symbol.cpp:994
AddressRange & GetAddressRange(Symbol &sym)
Definition Symbol.cpp:982
std::unique_ptr< FileSpec > library_up
Definition Symbol.h:363