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