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 if (sc.symbol->GetType() == eSymbolTypeUndefined)
505 continue;
506 // Don't return a symbol that itself only re-exports the definition
507 // (e.g. an ELF filter library's placeholder): the real definition is
508 // found by following the module-level re-exports below, which also
509 // guards against cycles.
510 if (sc.symbol->GetType() == eSymbolTypeReExported)
511 continue;
512 return sc.symbol;
513 }
514 // If we didn't find the symbol in this module, it may be because this
515 // module re-exports some whole other library. We have to search those as
516 // well:
517 seen_modules.Append(module_sp);
518
519 FileSpecList reexported_libraries =
520 module_sp->GetObjectFile()->GetReExportedLibraries();
521 size_t num_reexported_libraries = reexported_libraries.GetSize();
522 for (size_t idx = 0; idx < num_reexported_libraries; idx++) {
523 ModuleSpec reexported_module_spec;
524 reexported_module_spec.GetFileSpec() =
525 reexported_libraries.GetFileSpecAtIndex(idx);
527 target, reexport_name, reexported_module_spec, seen_modules);
528 if (result_symbol)
529 return result_symbol;
530 }
531 }
532 return nullptr;
533}
534
536 Target &target, const lldb::ModuleSP &containing_module_sp) const {
537 ConstString reexport_name(GetReExportedSymbolName());
538 ModuleList seen_modules;
539
540 if (reexport_name) {
541 // Search the library recorded on the symbol itself first.
542 ModuleSpec module_spec;
544 if (module_spec.GetFileSpec()) {
546 target, reexport_name, module_spec, seen_modules))
547 return result;
548 }
549 } else {
550 // This symbol isn't itself marked as a re-export. Some formats (ELF's
551 // DT_FILTER / DT_AUXILIARY) have no per-symbol tagging: the dynamic
552 // linker always resolves through the filtee(s) first and only falls
553 // back to the filter object's own definition if none of them provide
554 // it, even when the filter also provides a genuine implementation of
555 // the same symbol.
556 ObjectFile *object_file =
557 containing_module_sp ? containing_module_sp->GetObjectFile() : nullptr;
558 if (!object_file ||
560 return nullptr;
561
562 // Only exported (global or weak) definitions take part in dynamic
563 // linking, so local symbols are never shadowed by a filtee.
564 if (!IsExternal() && !IsWeak())
565 return nullptr;
566
567 // Use this symbol's own (version-suffix-stripped) name so the filtees
568 // below are searched for it.
569 reexport_name = GetName();
570 if (!reexport_name)
571 return nullptr;
573 reexport_name = ConstString(object_file->StripLinkerSymbolAnnotations(
574 reexport_name.GetStringRef()));
575 }
576
577 // The recorded library is only the first candidate: the module defining
578 // this symbol may re-export several libraries which must be searched in
579 // the order they are declared (e.g. an ELF filter library with multiple
580 // DT_FILTER / DT_AUXILIARY entries). seen_modules is shared with the
581 // search above so no library is searched twice.
582 if (containing_module_sp) {
583 if (ObjectFile *object_file = containing_module_sp->GetObjectFile()) {
584 FileSpecList reexported_libraries = object_file->GetReExportedLibraries();
585 const size_t count = reexported_libraries.GetSize();
586 for (size_t idx = 0; idx < count; ++idx) {
587 ModuleSpec reexported_module_spec;
588 reexported_module_spec.GetFileSpec() =
589 reexported_libraries.GetFileSpecAtIndex(idx);
591 target, reexport_name, reexported_module_spec, seen_modules))
592 return result;
593 }
594 }
595 }
596
597 return nullptr;
598}
599
601 if (ValueIsAddress())
602 return GetAddressRef().GetFileAddress();
603 else
605}
606
608 if (ValueIsAddress())
609 return GetAddressRef().GetLoadAddress(target);
610 else
612}
613
615
619
621 Target &target, const lldb::ModuleSP &containing_module_sp) const {
624
625 Address func_so_addr;
626
627 bool is_indirect = IsIndirect();
628 // A symbol from an ELF filter/auxiliary library is resolved through its
629 // filtee(s) first, falling back to its own definition only if none of them
630 // provide it, mirroring what the dynamic linker does.
631 if (Symbol *reexported_symbol =
632 ResolveReExportedSymbol(target, containing_module_sp)) {
633 func_so_addr = reexported_symbol->GetAddress();
634 is_indirect = reexported_symbol->IsIndirect();
635 } else if (GetType() != eSymbolTypeReExported) {
636 func_so_addr = GetAddress();
637 is_indirect = IsIndirect();
638 }
639
640 if (func_so_addr.IsValid()) {
641 if (!target.GetProcessSP() && is_indirect) {
642 // can't resolve indirect symbols without calling a function...
644 }
645
646 lldb::addr_t load_addr =
647 func_so_addr.GetCallableLoadAddress(&target, is_indirect);
648
649 if (load_addr != LLDB_INVALID_ADDRESS) {
650 return load_addr;
651 }
652 }
653
655}
656
658 const char *flavor,
659 bool prefer_file_cache) {
660 ModuleSP module_sp(
661 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().GetModule());
662 if (module_sp && exe_ctx.HasTargetScope()) {
664 module_sp->GetArchitecture(), nullptr, flavor, nullptr, nullptr,
665 exe_ctx.GetTargetRef(), m_addr_or_reexport.GetAddressRange(*this),
666 !prefer_file_cache);
667 }
668 return lldb::DisassemblerSP();
669}
670
671bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
672 bool prefer_file_cache, Stream &strm) {
673 lldb::DisassemblerSP disassembler_sp =
674 GetInstructions(exe_ctx, flavor, prefer_file_cache);
675 if (disassembler_sp) {
676 const bool show_address = true;
677 const bool show_bytes = false;
678 const bool show_control_flow_kind = false;
679 disassembler_sp->GetInstructionList().Dump(
680 &strm, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
681 return true;
682 }
683 return false;
684}
685
687 return m_addr_or_reexport.GetAddressRange(*this).ContainsFileAddress(
688 file_addr);
689}
690
692 if (!IsSynthetic())
693 return false;
694 if (!m_mangled)
695 return true;
696 ConstString demangled = m_mangled.GetDemangledName();
697 return demangled.GetStringRef().starts_with(GetSyntheticSymbolPrefix());
698}
699
701 if (m_is_synthetic && !m_mangled) {
702 // Synthetic symbol names don't mean anything, but they do uniquely
703 // identify individual symbols so we give them a unique name. The name
704 // starts with the synthetic symbol prefix, followed by a unique number.
705 // Typically the UserID of a real symbol is the symbol table index of the
706 // symbol in the object file's symbol table(s), so it will be the same
707 // every time you read in the object file. We want the same persistence for
708 // synthetic symbols so that users can identify them across multiple debug
709 // sessions, to understand crashes in those symbols and to reliably set
710 // breakpoints on them.
711 llvm::SmallString<256> name;
712 llvm::raw_svector_ostream os(name);
714 << llvm::format_hex_no_prefix(m_addr_or_reexport.GetAddressRange(*this)
715 .GetBaseAddress()
716 .GetFileAddress(),
717 0);
718 m_mangled.SetDemangledName(ConstString(os.str()));
719 }
720}
721
722bool Symbol::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
723 const SectionList *section_list,
724 const StringTableReader &strtab) {
725 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 8))
726 return false;
727 m_uid = data.GetU32(offset_ptr);
728 m_type_data = data.GetU16(offset_ptr);
729 const uint16_t bitfields = data.GetU16(offset_ptr);
730 m_type_data_resolved = (1u << 15 & bitfields) != 0;
731 m_is_synthetic = (1u << 14 & bitfields) != 0;
732 m_is_debug = (1u << 13 & bitfields) != 0;
733 m_is_external = (1u << 12 & bitfields) != 0;
734 m_size_is_sibling = (1u << 11 & bitfields) != 0;
735 m_size_is_synthesized = (1u << 10 & bitfields) != 0;
736 m_size_is_valid = (1u << 9 & bitfields) != 0;
737 m_demangled_is_synthesized = (1u << 8 & bitfields) != 0;
738 m_contains_linker_annotations = (1u << 7 & bitfields) != 0;
739 m_is_weak = (1u << 6 & bitfields) != 0;
740 m_type = bitfields & 0x003f;
741 if (!m_mangled.Decode(data, offset_ptr, strtab))
742 return false;
743 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 20))
744 return false;
746 const bool is_addr = data.GetU8(offset_ptr) != 0;
747 const uint64_t value = data.GetU64(offset_ptr);
748 if (is_addr) {
749 m_addr_or_reexport.GetAddressRange(*this)
750 .GetBaseAddress()
751 .ResolveAddressUsingFileSections(value, section_list);
752 } else {
753 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().Clear();
754 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().SetOffset(
755 value);
756 }
757 m_addr_or_reexport.GetAddressRange(*this).SetByteSize(
758 data.GetU64(offset_ptr));
759 } else {
760 m_addr_or_reexport.GetReExportInfo(*this).name =
761 ConstString(strtab.Get(data.GetU32(offset_ptr)));
762 llvm::StringRef filename = strtab.Get(data.GetU32(offset_ptr));
763 if (!filename.empty())
764 m_addr_or_reexport.GetReExportInfo(*this).library_up =
765 std::make_unique<FileSpec>(filename);
766 }
767 m_flags = data.GetU32(offset_ptr);
768 return true;
769}
770
771// If the size of Symbol has changed, the Encode and
772// Decode methods also likely need to be updated and
773// the DataFileCache version number in Symtab::Encode
774// will need to be incremented as well.
775#if __SIZEOF_POINTER__ == 8
776static_assert(sizeof(lldb_private::Symbol) == 72,
777 "Symbol size has changed, Symbol::Encode and Decode likely need "
778 "to be updated");
779#endif
780
781/// The encoding format for the symbol is as follows:
782///
783/// uint32_t m_uid;
784/// uint16_t m_type_data;
785/// uint16_t bitfield_data;
786/// Mangled mangled;
787/// uint8_t is_addr;
788/// uint64_t file_addr_or_value;
789/// uint64_t size;
790/// uint32_t flags;
791///
792/// The only tricky thing in this encoding is encoding all of the bits in the
793/// bitfields. We use a trick to store all bitfields as a 16 bit value and we
794/// do the same thing when decoding the symbol. There are test that ensure this
795/// encoding works for each individual bit. Everything else is very easy to
796/// store.
797void Symbol::Encode(DataEncoder &file, ConstStringTable &strtab) const {
798 file.AppendU32(m_uid);
800 uint16_t bitfields = m_type;
802 bitfields |= 1u << 15;
803 if (m_is_synthetic)
804 bitfields |= 1u << 14;
805 if (m_is_debug)
806 bitfields |= 1u << 13;
807 if (m_is_external)
808 bitfields |= 1u << 12;
810 bitfields |= 1u << 11;
812 bitfields |= 1u << 10;
813 if (m_size_is_valid)
814 bitfields |= 1u << 9;
816 bitfields |= 1u << 8;
818 bitfields |= 1u << 7;
819 if (m_is_weak)
820 bitfields |= 1u << 6;
821 file.AppendU16(bitfields);
822 m_mangled.Encode(file, strtab);
824 // A symbol's value might be an address, or it might be a constant. If the
825 // symbol's base address doesn't have a section, then it is a constant
826 // value. If it does have a section, we will encode the file address and
827 // re-resolve the address when we decode it.
828 bool is_addr = m_addr_or_reexport.GetAddressRange(*this)
829 .GetBaseAddress()
830 .GetSection()
831 .get() != nullptr;
832 file.AppendU8(is_addr);
833 file.AppendU64(m_addr_or_reexport.GetAddressRange(*this)
834 .GetBaseAddress()
835 .GetFileAddress());
836 file.AppendU64(m_addr_or_reexport.GetAddressRange(*this).GetByteSize());
837 } else {
838 file.AppendU32(strtab.Add(m_addr_or_reexport.GetReExportInfo(*this).name));
839 if (m_addr_or_reexport.GetReExportInfo(*this).library_up) {
840 ConstString filepath(m_addr_or_reexport.GetReExportInfo(*this)
841 .library_up->GetPath()
842 .c_str());
843 file.AppendU32(strtab.Add(filepath));
844 } else {
845 file.AppendU32(strtab.Add(ConstString("")));
846 }
847 }
848 file.AppendU32(m_flags);
849}
850
851bool Symbol::operator==(const Symbol &rhs) const {
852 if (m_uid != rhs.m_uid)
853 return false;
854 if (m_type_data != rhs.m_type_data)
855 return false;
857 return false;
859 return false;
860 if (m_is_debug != rhs.m_is_debug)
861 return false;
862 if (m_is_external != rhs.m_is_external)
863 return false;
865 return false;
867 return false;
869 return false;
871 return false;
873 return false;
874 if (m_is_weak != rhs.m_is_weak)
875 return false;
876 if (m_type != rhs.m_type)
877 return false;
878 if (m_mangled != rhs.m_mangled)
879 return false;
880 if (m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress() !=
882 return false;
883 if (m_addr_or_reexport.GetAddressRange(*this).GetByteSize() !=
885 return false;
886 if (m_flags != rhs.m_flags)
887 return false;
888 return true;
889}
890
891#define ENUM_TO_CSTRING(x) \
892 case eSymbolType##x: \
893 return #x;
894
896 switch (symbol_type) {
898 ENUM_TO_CSTRING(Absolute);
899 ENUM_TO_CSTRING(Code);
900 ENUM_TO_CSTRING(Resolver);
901 ENUM_TO_CSTRING(Data);
902 ENUM_TO_CSTRING(Trampoline);
905 ENUM_TO_CSTRING(SourceFile);
906 ENUM_TO_CSTRING(HeaderFile);
908 ENUM_TO_CSTRING(CommonBlock);
910 ENUM_TO_CSTRING(Local);
911 ENUM_TO_CSTRING(Param);
913 ENUM_TO_CSTRING(VariableType);
915 ENUM_TO_CSTRING(LineHeader);
916 ENUM_TO_CSTRING(ScopeBegin);
917 ENUM_TO_CSTRING(ScopeEnd);
918 ENUM_TO_CSTRING(Additional);
919 ENUM_TO_CSTRING(Compiler);
920 ENUM_TO_CSTRING(Instrumentation);
921 ENUM_TO_CSTRING(Undefined);
922 ENUM_TO_CSTRING(ObjCClass);
923 ENUM_TO_CSTRING(ObjCMetaClass);
924 ENUM_TO_CSTRING(ObjCIVar);
925 ENUM_TO_CSTRING(ReExported);
926 }
927 return "<unknown SymbolType>";
928}
929
931 std::string str_lower = llvm::StringRef(str).lower();
932 return llvm::StringSwitch<lldb::SymbolType>(str_lower)
933 .Case("absolute", eSymbolTypeAbsolute)
934 .Case("code", eSymbolTypeCode)
935 .Case("resolver", eSymbolTypeResolver)
936 .Case("data", eSymbolTypeData)
937 .Case("trampoline", eSymbolTypeTrampoline)
938 .Case("runtime", eSymbolTypeRuntime)
939 .Case("exception", eSymbolTypeException)
940 .Case("sourcefile", eSymbolTypeSourceFile)
941 .Case("headerfile", eSymbolTypeHeaderFile)
942 .Case("objectfile", eSymbolTypeObjectFile)
943 .Case("commonblock", eSymbolTypeCommonBlock)
944 .Case("block", eSymbolTypeBlock)
945 .Case("local", eSymbolTypeLocal)
946 .Case("param", eSymbolTypeParam)
947 .Case("variable", eSymbolTypeVariable)
948 .Case("variableType", eSymbolTypeVariableType)
949 .Case("lineentry", eSymbolTypeLineEntry)
950 .Case("lineheader", eSymbolTypeLineHeader)
951 .Case("scopebegin", eSymbolTypeScopeBegin)
952 .Case("scopeend", eSymbolTypeScopeEnd)
953 .Case("additional,", eSymbolTypeAdditional)
954 .Case("compiler", eSymbolTypeCompiler)
955 .Case("instrumentation", eSymbolTypeInstrumentation)
956 .Case("undefined", eSymbolTypeUndefined)
957 .Case("objcclass", eSymbolTypeObjCClass)
958 .Case("objcmetaclass", eSymbolTypeObjCMetaClass)
959 .Case("objcivar", eSymbolTypeObjCIVar)
960 .Case("reexported", eSymbolTypeReExported)
961 .Default(eSymbolTypeInvalid);
962}
963
968
969const AddressRange &
971 assert(sym.GetType() != eSymbolTypeReExported);
972 return m_addr_range;
973}
974
980
986
988 Symbol &sym, const AddressRange addr_range) {
989 if (sym.GetType() == eSymbolTypeReExported) {
990 m_reexport_info.Clear();
992 }
993 m_addr_range = addr_range;
994}
995
997 Symbol &sym, const Symbol::ReExportInfo reexport_info) {
998 if (sym.GetType() != eSymbolTypeReExported) {
999 m_addr_range.Clear();
1001 }
1002 m_reexport_info = reexport_info;
1003}
1004
1005namespace llvm {
1006namespace json {
1007
1008bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
1009 llvm::json::Path path) {
1010 llvm::json::ObjectMapper o(value, path);
1011 const bool mapped = o && o.map("value", symbol.value) &&
1012 o.map("address", symbol.address) &&
1013 o.map("size", symbol.size) && o.map("id", symbol.id) &&
1014 o.map("type", symbol.type) && o.map("name", symbol.name);
1015
1016 if (!mapped)
1017 return false;
1018
1019 if (!symbol.value && !symbol.address) {
1020 path.report("symbol must have either a value or an address");
1021 return false;
1022 }
1023
1024 if (symbol.value && symbol.address) {
1025 path.report("symbol cannot have both a value and an address");
1026 return false;
1027 }
1028
1029 return true;
1030}
1031
1032bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
1033 llvm::json::Path path) {
1034 if (auto str = value.getAsString()) {
1035 llvm::StringRef str_ref = str.value_or("");
1036 type = Symbol::GetTypeFromString(str_ref.data());
1037
1038 if (type == eSymbolTypeInvalid) {
1039 path.report("invalid symbol type");
1040 return false;
1041 }
1042
1043 return true;
1044 }
1045 path.report("expected string");
1046 return false;
1047}
1048} // namespace json
1049} // namespace llvm
#define ENUM_TO_CSTRING(x)
Definition Symbol.cpp:891
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: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:241
ConstString GetName(NamePreference preference=ePreferDemangled) const
Best name get accessor.
Definition Mangled.cpp:300
ConstString GetDisplayDemangledName() const
Display demangled name get accessor.
Definition Mangled.cpp:285
A collection class for Module objects.
Definition ModuleList.h:128
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:699
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 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:722
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:607
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:700
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:657
bool ContainsLinkerAnnotations() const
Definition Symbol.h:267
lldb::addr_t GetFileAddress() const
Definition Symbol.cpp:600
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:686
Mangled & GetMangled()
Definition Symbol.h:162
static lldb::SymbolType GetTypeFromString(const char *str)
Definition Symbol.cpp:930
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:691
void Encode(DataEncoder &encoder, ConstStringTable &strtab) const
Encode this object into a data encoder object.
Definition Symbol.cpp:797
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:851
static llvm::StringRef GetSyntheticSymbolPrefix()
Definition Symbol.h:296
lldb::addr_t GetByteSize() const
Definition Symbol.cpp:469
ConstString GetName() const
Definition Symbol.cpp:614
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:616
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:535
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:620
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:671
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: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
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:996
void SetAddressRange(Symbol &sym, const AddressRange addr_range)
Definition Symbol.cpp:987
ReExportInfo & GetReExportInfo(Symbol &sym)
Definition Symbol.cpp:976
AddressRange & GetAddressRange(Symbol &sym)
Definition Symbol.cpp:964
std::unique_ptr< FileSpec > library_up
Definition Symbol.h:362