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 §ion_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