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