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