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