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