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 
9 #include "lldb/Symbol/Symbol.h"
10 
11 #include "lldb/Core/Address.h"
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleSpec.h"
15 #include "lldb/Core/Section.h"
16 #include "lldb/Symbol/Function.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Symbol/SymbolVendor.h"
19 #include "lldb/Symbol/Symtab.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/DataEncoder.h"
23 #include "lldb/Utility/Stream.h"
24 #include "llvm/ADT/StringSwitch.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 Symbol::Symbol()
30     : SymbolContextScope(), m_type_data_resolved(false), m_is_synthetic(false),
31       m_is_debug(false), m_is_external(false), m_size_is_sibling(false),
32       m_size_is_synthesized(false), m_size_is_valid(false),
33       m_demangled_is_synthesized(false), m_contains_linker_annotations(false),
34       m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(),
35       m_addr_range() {}
36 
37 Symbol::Symbol(uint32_t symID, llvm::StringRef name, SymbolType type,
38                bool external, bool is_debug, bool is_trampoline,
39                bool is_artificial, const lldb::SectionSP &section_sp,
40                addr_t offset, addr_t size, bool size_is_valid,
41                bool contains_linker_annotations, uint32_t flags)
42     : SymbolContextScope(), m_uid(symID), m_type_data_resolved(false),
43       m_is_synthetic(is_artificial), m_is_debug(is_debug),
44       m_is_external(external), m_size_is_sibling(false),
45       m_size_is_synthesized(false), m_size_is_valid(size_is_valid || size > 0),
46       m_demangled_is_synthesized(false),
47       m_contains_linker_annotations(contains_linker_annotations),
48       m_is_weak(false), m_type(type), m_mangled(name),
49       m_addr_range(section_sp, offset, size), m_flags(flags) {}
50 
51 Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type,
52                bool external, bool is_debug, bool is_trampoline,
53                bool is_artificial, const AddressRange &range,
54                bool size_is_valid, bool contains_linker_annotations,
55                uint32_t flags)
56     : SymbolContextScope(), m_uid(symID), m_type_data_resolved(false),
57       m_is_synthetic(is_artificial), m_is_debug(is_debug),
58       m_is_external(external), m_size_is_sibling(false),
59       m_size_is_synthesized(false),
60       m_size_is_valid(size_is_valid || range.GetByteSize() > 0),
61       m_demangled_is_synthesized(false),
62       m_contains_linker_annotations(contains_linker_annotations),
63       m_is_weak(false), m_type(type), m_mangled(mangled), m_addr_range(range),
64       m_flags(flags) {}
65 
66 Symbol::Symbol(const Symbol &rhs)
67     : SymbolContextScope(rhs), m_uid(rhs.m_uid), m_type_data(rhs.m_type_data),
68       m_type_data_resolved(rhs.m_type_data_resolved),
69       m_is_synthetic(rhs.m_is_synthetic), m_is_debug(rhs.m_is_debug),
70       m_is_external(rhs.m_is_external),
71       m_size_is_sibling(rhs.m_size_is_sibling), m_size_is_synthesized(false),
72       m_size_is_valid(rhs.m_size_is_valid),
73       m_demangled_is_synthesized(rhs.m_demangled_is_synthesized),
74       m_contains_linker_annotations(rhs.m_contains_linker_annotations),
75       m_is_weak(rhs.m_is_weak), m_type(rhs.m_type), m_mangled(rhs.m_mangled),
76       m_addr_range(rhs.m_addr_range), m_flags(rhs.m_flags) {}
77 
78 const Symbol &Symbol::operator=(const Symbol &rhs) {
79   if (this != &rhs) {
80     SymbolContextScope::operator=(rhs);
81     m_uid = rhs.m_uid;
82     m_type_data = rhs.m_type_data;
83     m_type_data_resolved = rhs.m_type_data_resolved;
84     m_is_synthetic = rhs.m_is_synthetic;
85     m_is_debug = rhs.m_is_debug;
86     m_is_external = rhs.m_is_external;
87     m_size_is_sibling = rhs.m_size_is_sibling;
88     m_size_is_synthesized = rhs.m_size_is_sibling;
89     m_size_is_valid = rhs.m_size_is_valid;
90     m_demangled_is_synthesized = rhs.m_demangled_is_synthesized;
91     m_contains_linker_annotations = rhs.m_contains_linker_annotations;
92     m_is_weak = rhs.m_is_weak;
93     m_type = rhs.m_type;
94     m_mangled = rhs.m_mangled;
95     m_addr_range = rhs.m_addr_range;
96     m_flags = rhs.m_flags;
97   }
98   return *this;
99 }
100 
101 llvm::Expected<Symbol> Symbol::FromJSON(const JSONSymbol &symbol,
102                                         SectionList *section_list) {
103   if (!section_list)
104     return llvm::make_error<llvm::StringError>("no section list provided",
105                                                llvm::inconvertibleErrorCode());
106 
107   if (!symbol.value && !symbol.address)
108     return llvm::make_error<llvm::StringError>(
109         "symbol must contain either a value or an address",
110         llvm::inconvertibleErrorCode());
111 
112   if (symbol.value && symbol.address)
113     return llvm::make_error<llvm::StringError>(
114         "symbol cannot contain both a value and an address",
115         llvm::inconvertibleErrorCode());
116 
117   const uint64_t size = symbol.size.value_or(0);
118   const bool is_artificial = false;
119   const bool is_trampoline = false;
120   const bool is_debug = false;
121   const bool external = false;
122   const bool size_is_valid = symbol.size.has_value();
123   const bool contains_linker_annotations = false;
124   const uint32_t flags = 0;
125 
126   if (symbol.address) {
127     if (SectionSP section_sp =
128             section_list->FindSectionContainingFileAddress(*symbol.address)) {
129       const uint64_t offset = *symbol.address - section_sp->GetFileAddress();
130       return Symbol(symbol.id.value_or(0), Mangled(symbol.name),
131                     symbol.type.value_or(eSymbolTypeAny), external, is_debug,
132                     is_trampoline, is_artificial,
133                     AddressRange(section_sp, offset, size), size_is_valid,
134                     contains_linker_annotations, flags);
135     }
136     return llvm::make_error<llvm::StringError>(
137         llvm::formatv("no section found for address: {0:x}", *symbol.address),
138         llvm::inconvertibleErrorCode());
139   }
140 
141   // Absolute symbols encode the integer value in the m_offset of the
142   // AddressRange object and the section is set to nothing.
143   return Symbol(symbol.id.value_or(0), Mangled(symbol.name),
144                 symbol.type.value_or(eSymbolTypeAny), external, is_debug,
145                 is_trampoline, is_artificial,
146                 AddressRange(SectionSP(), *symbol.value, size), size_is_valid,
147                 contains_linker_annotations, flags);
148 }
149 
150 void Symbol::Clear() {
151   m_uid = UINT32_MAX;
152   m_mangled.Clear();
153   m_type_data = 0;
154   m_type_data_resolved = false;
155   m_is_synthetic = false;
156   m_is_debug = false;
157   m_is_external = false;
158   m_size_is_sibling = false;
159   m_size_is_synthesized = false;
160   m_size_is_valid = false;
161   m_demangled_is_synthesized = false;
162   m_contains_linker_annotations = false;
163   m_is_weak = false;
164   m_type = eSymbolTypeInvalid;
165   m_flags = 0;
166   m_addr_range.Clear();
167 }
168 
169 bool Symbol::ValueIsAddress() const {
170   return (bool)m_addr_range.GetBaseAddress().GetSection();
171 }
172 
173 ConstString Symbol::GetDisplayName() const {
174   return GetMangled().GetDisplayDemangledName();
175 }
176 
177 ConstString Symbol::GetReExportedSymbolName() const {
178   if (m_type == eSymbolTypeReExported) {
179     // For eSymbolTypeReExported, the "const char *" from a ConstString is used
180     // as the offset in the address range base address. We can then make this
181     // back into a string that is the re-exported name.
182     intptr_t str_ptr = m_addr_range.GetBaseAddress().GetOffset();
183     if (str_ptr != 0)
184       return ConstString((const char *)str_ptr);
185     else
186       return GetName();
187   }
188   return ConstString();
189 }
190 
191 FileSpec Symbol::GetReExportedSymbolSharedLibrary() const {
192   if (m_type == eSymbolTypeReExported) {
193     // For eSymbolTypeReExported, the "const char *" from a ConstString is used
194     // as the offset in the address range base address. We can then make this
195     // back into a string that is the re-exported name.
196     intptr_t str_ptr = m_addr_range.GetByteSize();
197     if (str_ptr != 0)
198       return FileSpec((const char *)str_ptr);
199   }
200   return FileSpec();
201 }
202 
203 void Symbol::SetReExportedSymbolName(ConstString name) {
204   SetType(eSymbolTypeReExported);
205   // For eSymbolTypeReExported, the "const char *" from a ConstString is used
206   // as the offset in the address range base address.
207   m_addr_range.GetBaseAddress().SetOffset((uintptr_t)name.GetCString());
208 }
209 
210 bool Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec) {
211   if (m_type == eSymbolTypeReExported) {
212     // For eSymbolTypeReExported, the "const char *" from a ConstString is used
213     // as the offset in the address range base address.
214     m_addr_range.SetByteSize(
215         (uintptr_t)ConstString(fspec.GetPath().c_str()).GetCString());
216     return true;
217   }
218   return false;
219 }
220 
221 uint32_t Symbol::GetSiblingIndex() const {
222   return m_size_is_sibling ? m_addr_range.GetByteSize() : UINT32_MAX;
223 }
224 
225 bool Symbol::IsTrampoline() const { return m_type == eSymbolTypeTrampoline; }
226 
227 bool Symbol::IsIndirect() const { return m_type == eSymbolTypeResolver; }
228 
229 void Symbol::GetDescription(
230     Stream *s, lldb::DescriptionLevel level, Target *target,
231     std::optional<Stream::HighlightSettings> settings) const {
232   s->Printf("id = {0x%8.8x}", m_uid);
233 
234   if (m_addr_range.GetBaseAddress().GetSection()) {
235     if (ValueIsAddress()) {
236       const lldb::addr_t byte_size = GetByteSize();
237       if (byte_size > 0) {
238         s->PutCString(", range = ");
239         m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress,
240                           Address::DumpStyleFileAddress);
241       } else {
242         s->PutCString(", address = ");
243         m_addr_range.GetBaseAddress().Dump(s, target,
244                                            Address::DumpStyleLoadAddress,
245                                            Address::DumpStyleFileAddress);
246       }
247     } else
248       s->Printf(", value = 0x%16.16" PRIx64,
249                 m_addr_range.GetBaseAddress().GetOffset());
250   } else {
251     if (m_size_is_sibling)
252       s->Printf(", sibling = %5" PRIu64,
253                 m_addr_range.GetBaseAddress().GetOffset());
254     else
255       s->Printf(", value = 0x%16.16" PRIx64,
256                 m_addr_range.GetBaseAddress().GetOffset());
257   }
258   if (ConstString demangled = m_mangled.GetDemangledName()) {
259     s->PutCString(", name=\"");
260     s->PutCStringColorHighlighted(demangled.GetStringRef(), settings);
261     s->PutCString("\"");
262   }
263   if (ConstString mangled_name = m_mangled.GetMangledName()) {
264     s->PutCString(", mangled=\"");
265     s->PutCStringColorHighlighted(mangled_name.GetStringRef(), settings);
266     s->PutCString("\"");
267   }
268 }
269 
270 void Symbol::Dump(Stream *s, Target *target, uint32_t index,
271                   Mangled::NamePreference name_preference) const {
272   s->Printf("[%5u] %6u %c%c%c %-15s ", index, GetID(), m_is_debug ? 'D' : ' ',
273             m_is_synthetic ? 'S' : ' ', m_is_external ? 'X' : ' ',
274             GetTypeAsString());
275 
276   // Make sure the size of the symbol is up to date before dumping
277   GetByteSize();
278 
279   ConstString name = GetMangled().GetName(name_preference);
280   if (ValueIsAddress()) {
281     if (!m_addr_range.GetBaseAddress().Dump(s, nullptr,
282                                             Address::DumpStyleFileAddress))
283       s->Printf("%*s", 18, "");
284 
285     s->PutChar(' ');
286 
287     if (!m_addr_range.GetBaseAddress().Dump(s, target,
288                                             Address::DumpStyleLoadAddress))
289       s->Printf("%*s", 18, "");
290 
291     const char *format = m_size_is_sibling ? " Sibling -> [%5llu] 0x%8.8x %s\n"
292                                            : " 0x%16.16" PRIx64 " 0x%8.8x %s\n";
293     s->Printf(format, GetByteSize(), m_flags, name.AsCString(""));
294   } else if (m_type == eSymbolTypeReExported) {
295     s->Printf(
296         "                                                         0x%8.8x %s",
297         m_flags, name.AsCString(""));
298 
299     ConstString reexport_name = GetReExportedSymbolName();
300     intptr_t shlib = m_addr_range.GetByteSize();
301     if (shlib)
302       s->Printf(" -> %s`%s\n", (const char *)shlib, reexport_name.GetCString());
303     else
304       s->Printf(" -> %s\n", reexport_name.GetCString());
305   } else {
306     const char *format =
307         m_size_is_sibling
308             ? "0x%16.16" PRIx64
309               "                    Sibling -> [%5llu] 0x%8.8x %s\n"
310             : "0x%16.16" PRIx64 "                    0x%16.16" PRIx64
311               " 0x%8.8x %s\n";
312     s->Printf(format, m_addr_range.GetBaseAddress().GetOffset(), GetByteSize(),
313               m_flags, name.AsCString(""));
314   }
315 }
316 
317 uint32_t Symbol::GetPrologueByteSize() {
318   if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver) {
319     if (!m_type_data_resolved) {
320       m_type_data_resolved = true;
321 
322       const Address &base_address = m_addr_range.GetBaseAddress();
323       Function *function = base_address.CalculateSymbolContextFunction();
324       if (function) {
325         // Functions have line entries which can also potentially have end of
326         // prologue information. So if this symbol points to a function, use
327         // the prologue information from there.
328         m_type_data = function->GetPrologueByteSize();
329       } else {
330         ModuleSP module_sp(base_address.GetModule());
331         SymbolContext sc;
332         if (module_sp) {
333           uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress(
334               base_address, eSymbolContextLineEntry, sc);
335           if (resolved_flags & eSymbolContextLineEntry) {
336             // Default to the end of the first line entry.
337             m_type_data = sc.line_entry.range.GetByteSize();
338 
339             // Set address for next line.
340             Address addr(base_address);
341             addr.Slide(m_type_data);
342 
343             // Check the first few instructions and look for one that has a
344             // line number that is different than the first entry. This is also
345             // done in Function::GetPrologueByteSize().
346             uint16_t total_offset = m_type_data;
347             for (int idx = 0; idx < 6; ++idx) {
348               SymbolContext sc_temp;
349               resolved_flags = module_sp->ResolveSymbolContextForAddress(
350                   addr, eSymbolContextLineEntry, sc_temp);
351               // Make sure we got line number information...
352               if (!(resolved_flags & eSymbolContextLineEntry))
353                 break;
354 
355               // If this line number is different than our first one, use it
356               // and we're done.
357               if (sc_temp.line_entry.line != sc.line_entry.line) {
358                 m_type_data = total_offset;
359                 break;
360               }
361 
362               // Slide addr up to the next line address.
363               addr.Slide(sc_temp.line_entry.range.GetByteSize());
364               total_offset += sc_temp.line_entry.range.GetByteSize();
365               // If we've gone too far, bail out.
366               if (total_offset >= m_addr_range.GetByteSize())
367                 break;
368             }
369 
370             // Sanity check - this may be a function in the middle of code that
371             // has debug information, but not for this symbol.  So the line
372             // entries surrounding us won't lie inside our function. In that
373             // case, the line entry will be bigger than we are, so we do that
374             // quick check and if that is true, we just return 0.
375             if (m_type_data >= m_addr_range.GetByteSize())
376               m_type_data = 0;
377           } else {
378             // TODO: expose something in Process to figure out the
379             // size of a function prologue.
380             m_type_data = 0;
381           }
382         }
383       }
384     }
385     return m_type_data;
386   }
387   return 0;
388 }
389 
390 bool Symbol::Compare(ConstString name, SymbolType type) const {
391   if (type == eSymbolTypeAny || m_type == type) {
392     const Mangled &mangled = GetMangled();
393     return mangled.GetMangledName() == name ||
394            mangled.GetDemangledName() == name;
395   }
396   return false;
397 }
398 
399 #define ENUM_TO_CSTRING(x)                                                     \
400   case eSymbolType##x:                                                         \
401     return #x;
402 
403 const char *Symbol::GetTypeAsString() const {
404   switch (m_type) {
405     ENUM_TO_CSTRING(Invalid);
406     ENUM_TO_CSTRING(Absolute);
407     ENUM_TO_CSTRING(Code);
408     ENUM_TO_CSTRING(Resolver);
409     ENUM_TO_CSTRING(Data);
410     ENUM_TO_CSTRING(Trampoline);
411     ENUM_TO_CSTRING(Runtime);
412     ENUM_TO_CSTRING(Exception);
413     ENUM_TO_CSTRING(SourceFile);
414     ENUM_TO_CSTRING(HeaderFile);
415     ENUM_TO_CSTRING(ObjectFile);
416     ENUM_TO_CSTRING(CommonBlock);
417     ENUM_TO_CSTRING(Block);
418     ENUM_TO_CSTRING(Local);
419     ENUM_TO_CSTRING(Param);
420     ENUM_TO_CSTRING(Variable);
421     ENUM_TO_CSTRING(VariableType);
422     ENUM_TO_CSTRING(LineEntry);
423     ENUM_TO_CSTRING(LineHeader);
424     ENUM_TO_CSTRING(ScopeBegin);
425     ENUM_TO_CSTRING(ScopeEnd);
426     ENUM_TO_CSTRING(Additional);
427     ENUM_TO_CSTRING(Compiler);
428     ENUM_TO_CSTRING(Instrumentation);
429     ENUM_TO_CSTRING(Undefined);
430     ENUM_TO_CSTRING(ObjCClass);
431     ENUM_TO_CSTRING(ObjCMetaClass);
432     ENUM_TO_CSTRING(ObjCIVar);
433     ENUM_TO_CSTRING(ReExported);
434   default:
435     break;
436   }
437   return "<unknown SymbolType>";
438 }
439 
440 void Symbol::CalculateSymbolContext(SymbolContext *sc) {
441   // Symbols can reconstruct the symbol and the module in the symbol context
442   sc->symbol = this;
443   if (ValueIsAddress())
444     sc->module_sp = GetAddressRef().GetModule();
445   else
446     sc->module_sp.reset();
447 }
448 
449 ModuleSP Symbol::CalculateSymbolContextModule() {
450   if (ValueIsAddress())
451     return GetAddressRef().GetModule();
452   return ModuleSP();
453 }
454 
455 Symbol *Symbol::CalculateSymbolContextSymbol() { return this; }
456 
457 void Symbol::DumpSymbolContext(Stream *s) {
458   bool dumped_module = false;
459   if (ValueIsAddress()) {
460     ModuleSP module_sp(GetAddressRef().GetModule());
461     if (module_sp) {
462       dumped_module = true;
463       module_sp->DumpSymbolContext(s);
464     }
465   }
466   if (dumped_module)
467     s->PutCString(", ");
468 
469   s->Printf("Symbol{0x%8.8x}", GetID());
470 }
471 
472 lldb::addr_t Symbol::GetByteSize() const { return m_addr_range.GetByteSize(); }
473 
474 Symbol *Symbol::ResolveReExportedSymbolInModuleSpec(
475     Target &target, ConstString &reexport_name, ModuleSpec &module_spec,
476     ModuleList &seen_modules) const {
477   ModuleSP module_sp;
478   if (module_spec.GetFileSpec()) {
479     // Try searching for the module file spec first using the full path
480     module_sp = target.GetImages().FindFirstModule(module_spec);
481     if (!module_sp) {
482       // Next try and find the module by basename in case environment variables
483       // or other runtime trickery causes shared libraries to be loaded from
484       // alternate paths
485       module_spec.GetFileSpec().ClearDirectory();
486       module_sp = target.GetImages().FindFirstModule(module_spec);
487     }
488   }
489 
490   if (module_sp) {
491     // There should not be cycles in the reexport list, but we don't want to
492     // crash if there are so make sure we haven't seen this before:
493     if (!seen_modules.AppendIfNeeded(module_sp))
494       return nullptr;
495 
496     lldb_private::SymbolContextList sc_list;
497     module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny,
498                                           sc_list);
499     for (const SymbolContext &sc : sc_list) {
500       if (sc.symbol->IsExternal())
501         return sc.symbol;
502     }
503     // If we didn't find the symbol in this module, it may be because this
504     // module re-exports some whole other library.  We have to search those as
505     // well:
506     seen_modules.Append(module_sp);
507 
508     FileSpecList reexported_libraries =
509         module_sp->GetObjectFile()->GetReExportedLibraries();
510     size_t num_reexported_libraries = reexported_libraries.GetSize();
511     for (size_t idx = 0; idx < num_reexported_libraries; idx++) {
512       ModuleSpec reexported_module_spec;
513       reexported_module_spec.GetFileSpec() =
514           reexported_libraries.GetFileSpecAtIndex(idx);
515       Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec(
516           target, reexport_name, reexported_module_spec, seen_modules);
517       if (result_symbol)
518         return result_symbol;
519     }
520   }
521   return nullptr;
522 }
523 
524 Symbol *Symbol::ResolveReExportedSymbol(Target &target) const {
525   ConstString reexport_name(GetReExportedSymbolName());
526   if (reexport_name) {
527     ModuleSpec module_spec;
528     ModuleList seen_modules;
529     module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary();
530     if (module_spec.GetFileSpec()) {
531       return ResolveReExportedSymbolInModuleSpec(target, reexport_name,
532                                                  module_spec, seen_modules);
533     }
534   }
535   return nullptr;
536 }
537 
538 lldb::addr_t Symbol::GetFileAddress() const {
539   if (ValueIsAddress())
540     return GetAddressRef().GetFileAddress();
541   else
542     return LLDB_INVALID_ADDRESS;
543 }
544 
545 lldb::addr_t Symbol::GetLoadAddress(Target *target) const {
546   if (ValueIsAddress())
547     return GetAddressRef().GetLoadAddress(target);
548   else
549     return LLDB_INVALID_ADDRESS;
550 }
551 
552 ConstString Symbol::GetName() const { return GetMangled().GetName(); }
553 
554 ConstString Symbol::GetNameNoArguments() const {
555   return GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments);
556 }
557 
558 lldb::addr_t Symbol::ResolveCallableAddress(Target &target) const {
559   if (GetType() == lldb::eSymbolTypeUndefined)
560     return LLDB_INVALID_ADDRESS;
561 
562   Address func_so_addr;
563 
564   bool is_indirect = IsIndirect();
565   if (GetType() == eSymbolTypeReExported) {
566     Symbol *reexported_symbol = ResolveReExportedSymbol(target);
567     if (reexported_symbol) {
568       func_so_addr = reexported_symbol->GetAddress();
569       is_indirect = reexported_symbol->IsIndirect();
570     }
571   } else {
572     func_so_addr = GetAddress();
573     is_indirect = IsIndirect();
574   }
575 
576   if (func_so_addr.IsValid()) {
577     if (!target.GetProcessSP() && is_indirect) {
578       // can't resolve indirect symbols without calling a function...
579       return LLDB_INVALID_ADDRESS;
580     }
581 
582     lldb::addr_t load_addr =
583         func_so_addr.GetCallableLoadAddress(&target, is_indirect);
584 
585     if (load_addr != LLDB_INVALID_ADDRESS) {
586       return load_addr;
587     }
588   }
589 
590   return LLDB_INVALID_ADDRESS;
591 }
592 
593 lldb::DisassemblerSP Symbol::GetInstructions(const ExecutionContext &exe_ctx,
594                                              const char *flavor,
595                                              bool prefer_file_cache) {
596   ModuleSP module_sp(m_addr_range.GetBaseAddress().GetModule());
597   if (module_sp && exe_ctx.HasTargetScope()) {
598     return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
599                                           flavor, exe_ctx.GetTargetRef(),
600                                           m_addr_range, !prefer_file_cache);
601   }
602   return lldb::DisassemblerSP();
603 }
604 
605 bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
606                             bool prefer_file_cache, Stream &strm) {
607   lldb::DisassemblerSP disassembler_sp =
608       GetInstructions(exe_ctx, flavor, prefer_file_cache);
609   if (disassembler_sp) {
610     const bool show_address = true;
611     const bool show_bytes = false;
612     const bool show_control_flow_kind = false;
613     disassembler_sp->GetInstructionList().Dump(
614         &strm, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
615     return true;
616   }
617   return false;
618 }
619 
620 bool Symbol::ContainsFileAddress(lldb::addr_t file_addr) const {
621   return m_addr_range.ContainsFileAddress(file_addr);
622 }
623 
624 bool Symbol::IsSyntheticWithAutoGeneratedName() const {
625   if (!IsSynthetic())
626     return false;
627   if (!m_mangled)
628     return true;
629   ConstString demangled = m_mangled.GetDemangledName();
630   return demangled.GetStringRef().starts_with(GetSyntheticSymbolPrefix());
631 }
632 
633 void Symbol::SynthesizeNameIfNeeded() const {
634   if (m_is_synthetic && !m_mangled) {
635     // Synthetic symbol names don't mean anything, but they do uniquely
636     // identify individual symbols so we give them a unique name. The name
637     // starts with the synthetic symbol prefix, followed by a unique number.
638     // Typically the UserID of a real symbol is the symbol table index of the
639     // symbol in the object file's symbol table(s), so it will be the same
640     // every time you read in the object file. We want the same persistence for
641     // synthetic symbols so that users can identify them across multiple debug
642     // sessions, to understand crashes in those symbols and to reliably set
643     // breakpoints on them.
644     llvm::SmallString<256> name;
645     llvm::raw_svector_ostream os(name);
646     os << GetSyntheticSymbolPrefix() << GetID();
647     m_mangled.SetDemangledName(ConstString(os.str()));
648   }
649 }
650 
651 bool Symbol::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
652                     const SectionList *section_list,
653                     const StringTableReader &strtab) {
654   if (!data.ValidOffsetForDataOfSize(*offset_ptr, 8))
655     return false;
656   m_uid = data.GetU32(offset_ptr);
657   m_type_data = data.GetU16(offset_ptr);
658   const uint16_t bitfields = data.GetU16(offset_ptr);
659   m_type_data_resolved = (1u << 15 & bitfields) != 0;
660   m_is_synthetic = (1u << 14 & bitfields) != 0;
661   m_is_debug = (1u << 13 & bitfields) != 0;
662   m_is_external = (1u << 12 & bitfields) != 0;
663   m_size_is_sibling = (1u << 11 & bitfields) != 0;
664   m_size_is_synthesized = (1u << 10 & bitfields) != 0;
665   m_size_is_valid = (1u << 9 & bitfields) != 0;
666   m_demangled_is_synthesized = (1u << 8 & bitfields) != 0;
667   m_contains_linker_annotations = (1u << 7 & bitfields) != 0;
668   m_is_weak = (1u << 6 & bitfields) != 0;
669   m_type = bitfields & 0x003f;
670   if (!m_mangled.Decode(data, offset_ptr, strtab))
671     return false;
672   if (!data.ValidOffsetForDataOfSize(*offset_ptr, 20))
673     return false;
674   const bool is_addr = data.GetU8(offset_ptr) != 0;
675   const uint64_t value = data.GetU64(offset_ptr);
676   if (is_addr) {
677     m_addr_range.GetBaseAddress().ResolveAddressUsingFileSections(value,
678                                                                   section_list);
679   } else {
680     m_addr_range.GetBaseAddress().Clear();
681     m_addr_range.GetBaseAddress().SetOffset(value);
682   }
683   m_addr_range.SetByteSize(data.GetU64(offset_ptr));
684   m_flags = data.GetU32(offset_ptr);
685   return true;
686 }
687 
688 /// The encoding format for the symbol is as follows:
689 ///
690 /// uint32_t m_uid;
691 /// uint16_t m_type_data;
692 /// uint16_t bitfield_data;
693 /// Mangled mangled;
694 /// uint8_t is_addr;
695 /// uint64_t file_addr_or_value;
696 /// uint64_t size;
697 /// uint32_t flags;
698 ///
699 /// The only tricky thing in this encoding is encoding all of the bits in the
700 /// bitfields. We use a trick to store all bitfields as a 16 bit value and we
701 /// do the same thing when decoding the symbol. There are test that ensure this
702 /// encoding works for each individual bit. Everything else is very easy to
703 /// store.
704 void Symbol::Encode(DataEncoder &file, ConstStringTable &strtab) const {
705   file.AppendU32(m_uid);
706   file.AppendU16(m_type_data);
707   uint16_t bitfields = m_type;
708   if (m_type_data_resolved)
709     bitfields |= 1u << 15;
710   if (m_is_synthetic)
711     bitfields |= 1u << 14;
712   if (m_is_debug)
713     bitfields |= 1u << 13;
714   if (m_is_external)
715     bitfields |= 1u << 12;
716   if (m_size_is_sibling)
717     bitfields |= 1u << 11;
718   if (m_size_is_synthesized)
719     bitfields |= 1u << 10;
720   if (m_size_is_valid)
721     bitfields |= 1u << 9;
722   if (m_demangled_is_synthesized)
723     bitfields |= 1u << 8;
724   if (m_contains_linker_annotations)
725     bitfields |= 1u << 7;
726   if (m_is_weak)
727     bitfields |= 1u << 6;
728   file.AppendU16(bitfields);
729   m_mangled.Encode(file, strtab);
730   // A symbol's value might be an address, or it might be a constant. If the
731   // symbol's base address doesn't have a section, then it is a constant value.
732   // If it does have a section, we will encode the file address and re-resolve
733   // the address when we decode it.
734   bool is_addr = m_addr_range.GetBaseAddress().GetSection().get() != nullptr;
735   file.AppendU8(is_addr);
736   file.AppendU64(m_addr_range.GetBaseAddress().GetFileAddress());
737   file.AppendU64(m_addr_range.GetByteSize());
738   file.AppendU32(m_flags);
739 }
740 
741 bool Symbol::operator==(const Symbol &rhs) const {
742   if (m_uid != rhs.m_uid)
743     return false;
744   if (m_type_data != rhs.m_type_data)
745     return false;
746   if (m_type_data_resolved != rhs.m_type_data_resolved)
747     return false;
748   if (m_is_synthetic != rhs.m_is_synthetic)
749     return false;
750   if (m_is_debug != rhs.m_is_debug)
751     return false;
752   if (m_is_external != rhs.m_is_external)
753     return false;
754   if (m_size_is_sibling != rhs.m_size_is_sibling)
755     return false;
756   if (m_size_is_synthesized != rhs.m_size_is_synthesized)
757     return false;
758   if (m_size_is_valid != rhs.m_size_is_valid)
759     return false;
760   if (m_demangled_is_synthesized != rhs.m_demangled_is_synthesized)
761     return false;
762   if (m_contains_linker_annotations != rhs.m_contains_linker_annotations)
763     return false;
764   if (m_is_weak != rhs.m_is_weak)
765     return false;
766   if (m_type != rhs.m_type)
767     return false;
768   if (m_mangled != rhs.m_mangled)
769     return false;
770   if (m_addr_range.GetBaseAddress() != rhs.m_addr_range.GetBaseAddress())
771     return false;
772   if (m_addr_range.GetByteSize() != rhs.m_addr_range.GetByteSize())
773     return false;
774   if (m_flags != rhs.m_flags)
775     return false;
776   return true;
777 }
778 
779 namespace llvm {
780 namespace json {
781 
782 bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
783               llvm::json::Path path) {
784   llvm::json::ObjectMapper o(value, path);
785   const bool mapped = o && o.map("value", symbol.value) &&
786                       o.map("address", symbol.address) &&
787                       o.map("size", symbol.size) && o.map("id", symbol.id) &&
788                       o.map("type", symbol.type) && o.map("name", symbol.name);
789 
790   if (!mapped)
791     return false;
792 
793   if (!symbol.value && !symbol.address) {
794     path.report("symbol must have either a value or an address");
795     return false;
796   }
797 
798   if (symbol.value && symbol.address) {
799     path.report("symbol cannot have both a value and an address");
800     return false;
801   }
802 
803   return true;
804 }
805 
806 bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
807               llvm::json::Path path) {
808   if (auto str = value.getAsString()) {
809     type = llvm::StringSwitch<lldb::SymbolType>(*str)
810                .Case("absolute", eSymbolTypeAbsolute)
811                .Case("code", eSymbolTypeCode)
812                .Case("resolver", eSymbolTypeResolver)
813                .Case("data", eSymbolTypeData)
814                .Case("trampoline", eSymbolTypeTrampoline)
815                .Case("runtime", eSymbolTypeRuntime)
816                .Case("exception", eSymbolTypeException)
817                .Case("sourcefile", eSymbolTypeSourceFile)
818                .Case("headerfile", eSymbolTypeHeaderFile)
819                .Case("objectfile", eSymbolTypeObjectFile)
820                .Case("commonblock", eSymbolTypeCommonBlock)
821                .Case("block", eSymbolTypeBlock)
822                .Case("local", eSymbolTypeLocal)
823                .Case("param", eSymbolTypeParam)
824                .Case("variable", eSymbolTypeVariable)
825                .Case("variableType", eSymbolTypeVariableType)
826                .Case("lineentry", eSymbolTypeLineEntry)
827                .Case("lineheader", eSymbolTypeLineHeader)
828                .Case("scopebegin", eSymbolTypeScopeBegin)
829                .Case("scopeend", eSymbolTypeScopeEnd)
830                .Case("additional,", eSymbolTypeAdditional)
831                .Case("compiler", eSymbolTypeCompiler)
832                .Case("instrumentation", eSymbolTypeInstrumentation)
833                .Case("undefined", eSymbolTypeUndefined)
834                .Case("objcclass", eSymbolTypeObjCClass)
835                .Case("objcmetaClass", eSymbolTypeObjCMetaClass)
836                .Case("objcivar", eSymbolTypeObjCIVar)
837                .Case("reexporte", eSymbolTypeReExported)
838                .Default(eSymbolTypeInvalid);
839 
840     if (type == eSymbolTypeInvalid) {
841       path.report("invalid symbol type");
842       return false;
843     }
844 
845     return true;
846   }
847   path.report("expected string");
848   return false;
849 }
850 } // namespace json
851 } // namespace llvm
852