[Go to site: main page, start]

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())
503 return sc.symbol;
504 }
505 // If we didn't find the symbol in this module, it may be because this
506 // module re-exports some whole other library. We have to search those as
507 // well:
508 seen_modules.Append(module_sp);
509
510 FileSpecList reexported_libraries =
511 module_sp->GetObjectFile()->GetReExportedLibraries();
512 size_t num_reexported_libraries = reexported_libraries.GetSize();
513 for (size_t idx = 0; idx < num_reexported_libraries; idx++) {
514 ModuleSpec reexported_module_spec;
515 reexported_module_spec.GetFileSpec() =
516 reexported_libraries.GetFileSpecAtIndex(idx);
518 target, reexport_name, reexported_module_spec, seen_modules);
519 if (result_symbol)
520 return result_symbol;
521 }
522 }
523 return nullptr;
524}
525
527 ConstString reexport_name(GetReExportedSymbolName());
528 if (reexport_name) {
529 ModuleSpec module_spec;
530 ModuleList seen_modules;
532 if (module_spec.GetFileSpec()) {
533 return ResolveReExportedSymbolInModuleSpec(target, reexport_name,
534 module_spec, seen_modules);
535 }
536 }
537 return nullptr;
538}
539
541 if (ValueIsAddress())
542 return GetAddressRef().GetFileAddress();
543 else
545}
546
548 if (ValueIsAddress())
549 return GetAddressRef().GetLoadAddress(target);
550 else
552}
553
555
559
563
564 Address func_so_addr;
565
566 bool is_indirect = IsIndirect();
568 Symbol *reexported_symbol = ResolveReExportedSymbol(target);
569 if (reexported_symbol) {
570 func_so_addr = reexported_symbol->GetAddress();
571 is_indirect = reexported_symbol->IsIndirect();
572 }
573 } else {
574 func_so_addr = GetAddress();
575 is_indirect = IsIndirect();
576 }
577
578 if (func_so_addr.IsValid()) {
579 if (!target.GetProcessSP() && is_indirect) {
580 // can't resolve indirect symbols without calling a function...
582 }
583
584 lldb::addr_t load_addr =
585 func_so_addr.GetCallableLoadAddress(&target, is_indirect);
586
587 if (load_addr != LLDB_INVALID_ADDRESS) {
588 return load_addr;
589 }
590 }
591
593}
594
596 const char *flavor,
597 bool prefer_file_cache) {
598 ModuleSP module_sp(
599 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().GetModule());
600 if (module_sp && exe_ctx.HasTargetScope()) {
602 module_sp->GetArchitecture(), nullptr, flavor, nullptr, nullptr,
603 exe_ctx.GetTargetRef(), m_addr_or_reexport.GetAddressRange(*this),
604 !prefer_file_cache);
605 }
606 return lldb::DisassemblerSP();
607}
608
609bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
610 bool prefer_file_cache, Stream &strm) {
611 lldb::DisassemblerSP disassembler_sp =
612 GetInstructions(exe_ctx, flavor, prefer_file_cache);
613 if (disassembler_sp) {
614 const bool show_address = true;
615 const bool show_bytes = false;
616 const bool show_control_flow_kind = false;
617 disassembler_sp->GetInstructionList().Dump(
618 &strm, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
619 return true;
620 }
621 return false;
622}
623
625 return m_addr_or_reexport.GetAddressRange(*this).ContainsFileAddress(
626 file_addr);
627}
628
630 if (!IsSynthetic())
631 return false;
632 if (!m_mangled)
633 return true;
634 ConstString demangled = m_mangled.GetDemangledName();
635 return demangled.GetStringRef().starts_with(GetSyntheticSymbolPrefix());
636}
637
639 if (m_is_synthetic && !m_mangled) {
640 // Synthetic symbol names don't mean anything, but they do uniquely
641 // identify individual symbols so we give them a unique name. The name
642 // starts with the synthetic symbol prefix, followed by a unique number.
643 // Typically the UserID of a real symbol is the symbol table index of the
644 // symbol in the object file's symbol table(s), so it will be the same
645 // every time you read in the object file. We want the same persistence for
646 // synthetic symbols so that users can identify them across multiple debug
647 // sessions, to understand crashes in those symbols and to reliably set
648 // breakpoints on them.
649 llvm::SmallString<256> name;
650 llvm::raw_svector_ostream os(name);
652 << llvm::format_hex_no_prefix(m_addr_or_reexport.GetAddressRange(*this)
653 .GetBaseAddress()
654 .GetFileAddress(),
655 0);
656 m_mangled.SetDemangledName(ConstString(os.str()));
657 }
658}
659
660bool Symbol::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
661 const SectionList *section_list,
662 const StringTableReader &strtab) {
663 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 8))
664 return false;
665 m_uid = data.GetU32(offset_ptr);
666 m_type_data = data.GetU16(offset_ptr);
667 const uint16_t bitfields = data.GetU16(offset_ptr);
668 m_type_data_resolved = (1u << 15 & bitfields) != 0;
669 m_is_synthetic = (1u << 14 & bitfields) != 0;
670 m_is_debug = (1u << 13 & bitfields) != 0;
671 m_is_external = (1u << 12 & bitfields) != 0;
672 m_size_is_sibling = (1u << 11 & bitfields) != 0;
673 m_size_is_synthesized = (1u << 10 & bitfields) != 0;
674 m_size_is_valid = (1u << 9 & bitfields) != 0;
675 m_demangled_is_synthesized = (1u << 8 & bitfields) != 0;
676 m_contains_linker_annotations = (1u << 7 & bitfields) != 0;
677 m_is_weak = (1u << 6 & bitfields) != 0;
678 m_type = bitfields & 0x003f;
679 if (!m_mangled.Decode(data, offset_ptr, strtab))
680 return false;
681 if (!data.ValidOffsetForDataOfSize(*offset_ptr, 20))
682 return false;
684 const bool is_addr = data.GetU8(offset_ptr) != 0;
685 const uint64_t value = data.GetU64(offset_ptr);
686 if (is_addr) {
687 m_addr_or_reexport.GetAddressRange(*this)
688 .GetBaseAddress()
689 .ResolveAddressUsingFileSections(value, section_list);
690 } else {
691 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().Clear();
692 m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress().SetOffset(
693 value);
694 }
695 m_addr_or_reexport.GetAddressRange(*this).SetByteSize(
696 data.GetU64(offset_ptr));
697 } else {
698 m_addr_or_reexport.GetReExportInfo(*this).name =
699 ConstString(strtab.Get(data.GetU32(offset_ptr)));
700 // m_reexport_info.library is calculated based on the
701 // binaries loaded in the target, lazily. It is not
702 // saved in the serialized Symbol format as it could vary
703 // depending on the Target libraries.
704 m_addr_or_reexport.GetReExportInfo(*this).library_up.reset();
705 }
706 m_flags = data.GetU32(offset_ptr);
707 return true;
708}
709
710// If the size of Symbol has changed, the Encode and
711// Decode methods also likely need to be updated and
712// the DataFileCache version number in Symtab::Encode
713// will need to be incremented as well.
714#if __SIZEOF_POINTER__ == 8
715static_assert(sizeof(lldb_private::Symbol) == 80,
716 "Symbol size has changed, Symbol::Encode and Decode likely need "
717 "to be updated");
718#endif
719
720/// The encoding format for the symbol is as follows:
721///
722/// uint32_t m_uid;
723/// uint16_t m_type_data;
724/// uint16_t bitfield_data;
725/// Mangled mangled;
726/// uint8_t is_addr;
727/// uint64_t file_addr_or_value;
728/// uint64_t size;
729/// uint32_t flags;
730///
731/// The only tricky thing in this encoding is encoding all of the bits in the
732/// bitfields. We use a trick to store all bitfields as a 16 bit value and we
733/// do the same thing when decoding the symbol. There are test that ensure this
734/// encoding works for each individual bit. Everything else is very easy to
735/// store.
736void Symbol::Encode(DataEncoder &file, ConstStringTable &strtab) const {
737 file.AppendU32(m_uid);
739 uint16_t bitfields = m_type;
741 bitfields |= 1u << 15;
742 if (m_is_synthetic)
743 bitfields |= 1u << 14;
744 if (m_is_debug)
745 bitfields |= 1u << 13;
746 if (m_is_external)
747 bitfields |= 1u << 12;
749 bitfields |= 1u << 11;
751 bitfields |= 1u << 10;
752 if (m_size_is_valid)
753 bitfields |= 1u << 9;
755 bitfields |= 1u << 8;
757 bitfields |= 1u << 7;
758 if (m_is_weak)
759 bitfields |= 1u << 6;
760 file.AppendU16(bitfields);
761 m_mangled.Encode(file, strtab);
763 // A symbol's value might be an address, or it might be a constant. If the
764 // symbol's base address doesn't have a section, then it is a constant
765 // value. If it does have a section, we will encode the file address and
766 // re-resolve the address when we decode it.
767 bool is_addr = m_addr_or_reexport.GetAddressRange(*this)
768 .GetBaseAddress()
769 .GetSection()
770 .get() != nullptr;
771 file.AppendU8(is_addr);
772 file.AppendU64(m_addr_or_reexport.GetAddressRange(*this)
773 .GetBaseAddress()
774 .GetFileAddress());
775 file.AppendU64(m_addr_or_reexport.GetAddressRange(*this).GetByteSize());
776 } else {
777 file.AppendU32(strtab.Add(m_addr_or_reexport.GetReExportInfo(*this).name));
778 // m_reexport_info.library_up is calculated based on the
779 // binaries loaded in the target, lazily. It is not
780 // saved in the serialized Symbol format as it could vary
781 // depending on the Target libraries.
782 }
783 file.AppendU32(m_flags);
784}
785
786bool Symbol::operator==(const Symbol &rhs) const {
787 if (m_uid != rhs.m_uid)
788 return false;
789 if (m_type_data != rhs.m_type_data)
790 return false;
792 return false;
794 return false;
795 if (m_is_debug != rhs.m_is_debug)
796 return false;
797 if (m_is_external != rhs.m_is_external)
798 return false;
800 return false;
802 return false;
804 return false;
806 return false;
808 return false;
809 if (m_is_weak != rhs.m_is_weak)
810 return false;
811 if (m_type != rhs.m_type)
812 return false;
813 if (m_mangled != rhs.m_mangled)
814 return false;
815 if (m_addr_or_reexport.GetAddressRange(*this).GetBaseAddress() !=
817 return false;
818 if (m_addr_or_reexport.GetAddressRange(*this).GetByteSize() !=
820 return false;
821 if (m_flags != rhs.m_flags)
822 return false;
823 return true;
824}
825
826#define ENUM_TO_CSTRING(x) \
827 case eSymbolType##x: \
828 return #x;
829
831 switch (symbol_type) {
833 ENUM_TO_CSTRING(Absolute);
834 ENUM_TO_CSTRING(Code);
835 ENUM_TO_CSTRING(Resolver);
836 ENUM_TO_CSTRING(Data);
837 ENUM_TO_CSTRING(Trampoline);
840 ENUM_TO_CSTRING(SourceFile);
841 ENUM_TO_CSTRING(HeaderFile);
843 ENUM_TO_CSTRING(CommonBlock);
845 ENUM_TO_CSTRING(Local);
846 ENUM_TO_CSTRING(Param);
848 ENUM_TO_CSTRING(VariableType);
850 ENUM_TO_CSTRING(LineHeader);
851 ENUM_TO_CSTRING(ScopeBegin);
852 ENUM_TO_CSTRING(ScopeEnd);
853 ENUM_TO_CSTRING(Additional);
854 ENUM_TO_CSTRING(Compiler);
855 ENUM_TO_CSTRING(Instrumentation);
856 ENUM_TO_CSTRING(Undefined);
857 ENUM_TO_CSTRING(ObjCClass);
858 ENUM_TO_CSTRING(ObjCMetaClass);
859 ENUM_TO_CSTRING(ObjCIVar);
860 ENUM_TO_CSTRING(ReExported);
861 }
862 return "<unknown SymbolType>";
863}
864
866 std::string str_lower = llvm::StringRef(str).lower();
867 return llvm::StringSwitch<lldb::SymbolType>(str_lower)
868 .Case("absolute", eSymbolTypeAbsolute)
869 .Case("code", eSymbolTypeCode)
870 .Case("resolver", eSymbolTypeResolver)
871 .Case("data", eSymbolTypeData)
872 .Case("trampoline", eSymbolTypeTrampoline)
873 .Case("runtime", eSymbolTypeRuntime)
874 .Case("exception", eSymbolTypeException)
875 .Case("sourcefile", eSymbolTypeSourceFile)
876 .Case("headerfile", eSymbolTypeHeaderFile)
877 .Case("objectfile", eSymbolTypeObjectFile)
878 .Case("commonblock", eSymbolTypeCommonBlock)
879 .Case("block", eSymbolTypeBlock)
880 .Case("local", eSymbolTypeLocal)
881 .Case("param", eSymbolTypeParam)
882 .Case("variable", eSymbolTypeVariable)
883 .Case("variableType", eSymbolTypeVariableType)
884 .Case("lineentry", eSymbolTypeLineEntry)
885 .Case("lineheader", eSymbolTypeLineHeader)
886 .Case("scopebegin", eSymbolTypeScopeBegin)
887 .Case("scopeend", eSymbolTypeScopeEnd)
888 .Case("additional,", eSymbolTypeAdditional)
889 .Case("compiler", eSymbolTypeCompiler)
890 .Case("instrumentation", eSymbolTypeInstrumentation)
891 .Case("undefined", eSymbolTypeUndefined)
892 .Case("objcclass", eSymbolTypeObjCClass)
893 .Case("objcmetaclass", eSymbolTypeObjCMetaClass)
894 .Case("objcivar", eSymbolTypeObjCIVar)
895 .Case("reexported", eSymbolTypeReExported)
896 .Default(eSymbolTypeInvalid);
897}
898
903
904const AddressRange &
906 assert(sym.GetType() != eSymbolTypeReExported);
907 return m_addr_range;
908}
909
915
921
923 Symbol &sym, const AddressRange addr_range) {
924 if (sym.GetType() == eSymbolTypeReExported) {
925 m_reexport_info.Clear();
927 }
928 m_addr_range = addr_range;
929}
930
932 Symbol &sym, const Symbol::ReExportInfo reexport_info) {
933 if (sym.GetType() != eSymbolTypeReExported) {
934 m_addr_range.Clear();
936 }
937 m_reexport_info = reexport_info;
938}
939
940namespace llvm {
941namespace json {
942
943bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
944 llvm::json::Path path) {
945 llvm::json::ObjectMapper o(value, path);
946 const bool mapped = o && o.map("value", symbol.value) &&
947 o.map("address", symbol.address) &&
948 o.map("size", symbol.size) && o.map("id", symbol.id) &&
949 o.map("type", symbol.type) && o.map("name", symbol.name);
950
951 if (!mapped)
952 return false;
953
954 if (!symbol.value && !symbol.address) {
955 path.report("symbol must have either a value or an address");
956 return false;
957 }
958
959 if (symbol.value && symbol.address) {
960 path.report("symbol cannot have both a value and an address");
961 return false;
962 }
963
964 return true;
965}
966
967bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
968 llvm::json::Path path) {
969 if (auto str = value.getAsString()) {
970 llvm::StringRef str_ref = str.value_or("");
971 type = Symbol::GetTypeFromString(str_ref.data());
972
973 if (type == eSymbolTypeInvalid) {
974 path.report("invalid symbol type");
975 return false;
976 }
977
978 return true;
979 }
980 path.report("expected string");
981 return false;
982}
983} // namespace json
984} // namespace llvm
#define ENUM_TO_CSTRING(x)
Definition Symbol.cpp:826
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:301
lldb::addr_t GetCallableLoadAddress(Target *target, bool is_indirect=false) const
Get the load address as a callable code load address.
Definition Address.cpp:326
Function * CalculateSymbolContextFunction() const
Definition Address.cpp:859
@ 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:273
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:281
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
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:660
uint32_t GetSiblingIndex() const
Definition Symbol.cpp:241
uint16_t m_is_external
Definition Symbol.h:386
uint32_t GetID() const
Definition Symbol.h:154
lldb::addr_t GetLoadAddress(Target *target) const
Definition Symbol.cpp:547
bool ValueIsAddress() const
Definition Symbol.cpp:191
uint16_t m_type_data_resolved
Definition Symbol.h:379
void SetReExportedSymbolName(ConstString name)
Definition Symbol.cpp:221
void SetType(lldb::SymbolType type)
Definition Symbol.h:188
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:638
const char * GetTypeAsString() const
Definition Symbol.cpp:433
bool IsSynthetic() const
Definition Symbol.h:200
uint16_t m_is_synthetic
Definition Symbol.h:381
uint16_t m_demangled_is_synthesized
Definition Symbol.h:393
lldb::DisassemblerSP GetInstructions(const ExecutionContext &exe_ctx, const char *flavor, bool prefer_file_cache)
Definition Symbol.cpp:595
lldb::addr_t GetFileAddress() const
Definition Symbol.cpp:540
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:624
Mangled & GetMangled()
Definition Symbol.h:164
static lldb::SymbolType GetTypeFromString(const char *str)
Definition Symbol.cpp:865
uint16_t m_contains_linker_annotations
Definition Symbol.h:396
uint16_t m_size_is_valid
Definition Symbol.h:392
bool IsTrampoline() const
Definition Symbol.cpp:247
Address & GetAddressRef()
Definition Symbol.h:82
const Symbol & operator=(const Symbol &rhs)
Definition Symbol.cpp:97
bool IsSyntheticWithAutoGeneratedName() const
Definition Symbol.cpp:629
void Encode(DataEncoder &encoder, ConstStringTable &strtab) const
Encode this object into a data encoder object.
Definition Symbol.cpp:736
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:384
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:786
static llvm::StringRef GetSyntheticSymbolPrefix()
Definition Symbol.h:285
lldb::addr_t GetByteSize() const
Definition Symbol.cpp:469
ConstString GetName() const
Definition Symbol.cpp:554
lldb::SymbolType GetType() const
Definition Symbol.h:186
struct lldb_private::Symbol::AddrRangeOrReExport m_addr_or_reexport
Address GetAddress() const
Definition Symbol.h:102
ConstString GetNameNoArguments() const
Definition Symbol.cpp:556
uint16_t m_size_is_sibling
Definition Symbol.h:387
Symbol * ResolveReExportedSymbol(Target &target) const
Definition Symbol.cpp:526
FileSpec GetReExportedSymbolSharedLibrary() const
Definition Symbol.cpp:210
uint16_t m_is_weak
Definition Symbol.h:399
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
uint16_t m_type_data
Definition Symbol.h:378
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:609
lldb::addr_t ResolveCallableAddress(Target &target) const
Definition Symbol.cpp:560
uint16_t m_size_is_synthesized
Definition Symbol.h:389
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:328
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1247
#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:931
void SetAddressRange(Symbol &sym, const AddressRange addr_range)
Definition Symbol.cpp:922
ReExportInfo & GetReExportInfo(Symbol &sym)
Definition Symbol.cpp:911
AddressRange & GetAddressRange(Symbol &sym)
Definition Symbol.cpp:899
std::unique_ptr< FileSpec > library_up
Definition Symbol.h:351