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