1 //===-- SymbolContext.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/SymbolContext.h" 10 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/ModuleSpec.h" 13 #include "lldb/Host/Host.h" 14 #include "lldb/Host/StringConvert.h" 15 #include "lldb/Symbol/Block.h" 16 #include "lldb/Symbol/CompileUnit.h" 17 #include "lldb/Symbol/ObjectFile.h" 18 #include "lldb/Symbol/Symbol.h" 19 #include "lldb/Symbol/SymbolFile.h" 20 #include "lldb/Symbol/SymbolVendor.h" 21 #include "lldb/Symbol/Variable.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Utility/Log.h" 24 #include "lldb/Utility/StreamString.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 SymbolContext::SymbolContext() 30 : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr), 31 block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) {} 32 33 SymbolContext::SymbolContext(const ModuleSP &m, CompileUnit *cu, Function *f, 34 Block *b, LineEntry *le, Symbol *s) 35 : target_sp(), module_sp(m), comp_unit(cu), function(f), block(b), 36 line_entry(), symbol(s), variable(nullptr) { 37 if (le) 38 line_entry = *le; 39 } 40 41 SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP &m, 42 CompileUnit *cu, Function *f, Block *b, 43 LineEntry *le, Symbol *s) 44 : target_sp(t), module_sp(m), comp_unit(cu), function(f), block(b), 45 line_entry(), symbol(s), variable(nullptr) { 46 if (le) 47 line_entry = *le; 48 } 49 50 SymbolContext::SymbolContext(SymbolContextScope *sc_scope) 51 : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr), 52 block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) { 53 sc_scope->CalculateSymbolContext(this); 54 } 55 56 SymbolContext::~SymbolContext() {} 57 58 void SymbolContext::Clear(bool clear_target) { 59 if (clear_target) 60 target_sp.reset(); 61 module_sp.reset(); 62 comp_unit = nullptr; 63 function = nullptr; 64 block = nullptr; 65 line_entry.Clear(); 66 symbol = nullptr; 67 variable = nullptr; 68 } 69 70 bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, 71 const Address &addr, bool show_fullpaths, 72 bool show_module, bool show_inlined_frames, 73 bool show_function_arguments, 74 bool show_function_name) const { 75 bool dumped_something = false; 76 if (show_module && module_sp) { 77 if (show_fullpaths) 78 *s << module_sp->GetFileSpec(); 79 else 80 *s << module_sp->GetFileSpec().GetFilename(); 81 s->PutChar('`'); 82 dumped_something = true; 83 } 84 85 if (function != nullptr) { 86 SymbolContext inline_parent_sc; 87 Address inline_parent_addr; 88 if (!show_function_name) { 89 s->Printf("<"); 90 dumped_something = true; 91 } else { 92 ConstString name; 93 if (!show_function_arguments) 94 name = function->GetNameNoArguments(); 95 if (!name) 96 name = function->GetName(); 97 if (name) 98 name.Dump(s); 99 } 100 101 if (addr.IsValid()) { 102 const addr_t function_offset = 103 addr.GetOffset() - 104 function->GetAddressRange().GetBaseAddress().GetOffset(); 105 if (!show_function_name) { 106 // Print +offset even if offset is 0 107 dumped_something = true; 108 s->Printf("+%" PRIu64 ">", function_offset); 109 } else if (function_offset) { 110 dumped_something = true; 111 s->Printf(" + %" PRIu64, function_offset); 112 } 113 } 114 115 if (GetParentOfInlinedScope(addr, inline_parent_sc, inline_parent_addr)) { 116 dumped_something = true; 117 Block *inlined_block = block->GetContainingInlinedBlock(); 118 const InlineFunctionInfo *inlined_block_info = 119 inlined_block->GetInlinedFunctionInfo(); 120 s->Printf(" [inlined] %s", inlined_block_info->GetName().GetCString()); 121 122 lldb_private::AddressRange block_range; 123 if (inlined_block->GetRangeContainingAddress(addr, block_range)) { 124 const addr_t inlined_function_offset = 125 addr.GetOffset() - block_range.GetBaseAddress().GetOffset(); 126 if (inlined_function_offset) { 127 s->Printf(" + %" PRIu64, inlined_function_offset); 128 } 129 } 130 const Declaration &call_site = inlined_block_info->GetCallSite(); 131 if (call_site.IsValid()) { 132 s->PutCString(" at "); 133 call_site.DumpStopContext(s, show_fullpaths); 134 } 135 if (show_inlined_frames) { 136 s->EOL(); 137 s->Indent(); 138 const bool show_function_name = true; 139 return inline_parent_sc.DumpStopContext( 140 s, exe_scope, inline_parent_addr, show_fullpaths, show_module, 141 show_inlined_frames, show_function_arguments, show_function_name); 142 } 143 } else { 144 if (line_entry.IsValid()) { 145 dumped_something = true; 146 s->PutCString(" at "); 147 if (line_entry.DumpStopContext(s, show_fullpaths)) 148 dumped_something = true; 149 } 150 } 151 } else if (symbol != nullptr) { 152 if (!show_function_name) { 153 s->Printf("<"); 154 dumped_something = true; 155 } else if (symbol->GetName()) { 156 dumped_something = true; 157 if (symbol->GetType() == eSymbolTypeTrampoline) 158 s->PutCString("symbol stub for: "); 159 symbol->GetName().Dump(s); 160 } 161 162 if (addr.IsValid() && symbol->ValueIsAddress()) { 163 const addr_t symbol_offset = 164 addr.GetOffset() - symbol->GetAddressRef().GetOffset(); 165 if (!show_function_name) { 166 // Print +offset even if offset is 0 167 dumped_something = true; 168 s->Printf("+%" PRIu64 ">", symbol_offset); 169 } else if (symbol_offset) { 170 dumped_something = true; 171 s->Printf(" + %" PRIu64, symbol_offset); 172 } 173 } 174 } else if (addr.IsValid()) { 175 addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress); 176 dumped_something = true; 177 } 178 return dumped_something; 179 } 180 181 void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, 182 Target *target) const { 183 if (module_sp) { 184 s->Indent(" Module: file = \""); 185 module_sp->GetFileSpec().Dump(s->AsRawOstream()); 186 *s << '"'; 187 if (module_sp->GetArchitecture().IsValid()) 188 s->Printf(", arch = \"%s\"", 189 module_sp->GetArchitecture().GetArchitectureName()); 190 s->EOL(); 191 } 192 193 if (comp_unit != nullptr) { 194 s->Indent("CompileUnit: "); 195 comp_unit->GetDescription(s, level); 196 s->EOL(); 197 } 198 199 if (function != nullptr) { 200 s->Indent(" Function: "); 201 function->GetDescription(s, level, target); 202 s->EOL(); 203 204 Type *func_type = function->GetType(); 205 if (func_type) { 206 s->Indent(" FuncType: "); 207 func_type->GetDescription(s, level, false); 208 s->EOL(); 209 } 210 } 211 212 if (block != nullptr) { 213 std::vector<Block *> blocks; 214 blocks.push_back(block); 215 Block *parent_block = block->GetParent(); 216 217 while (parent_block) { 218 blocks.push_back(parent_block); 219 parent_block = parent_block->GetParent(); 220 } 221 std::vector<Block *>::reverse_iterator pos; 222 std::vector<Block *>::reverse_iterator begin = blocks.rbegin(); 223 std::vector<Block *>::reverse_iterator end = blocks.rend(); 224 for (pos = begin; pos != end; ++pos) { 225 if (pos == begin) 226 s->Indent(" Blocks: "); 227 else 228 s->Indent(" "); 229 (*pos)->GetDescription(s, function, level, target); 230 s->EOL(); 231 } 232 } 233 234 if (line_entry.IsValid()) { 235 s->Indent(" LineEntry: "); 236 line_entry.GetDescription(s, level, comp_unit, target, false); 237 s->EOL(); 238 } 239 240 if (symbol != nullptr) { 241 s->Indent(" Symbol: "); 242 symbol->GetDescription(s, level, target); 243 s->EOL(); 244 } 245 246 if (variable != nullptr) { 247 s->Indent(" Variable: "); 248 249 s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID()); 250 251 switch (variable->GetScope()) { 252 case eValueTypeVariableGlobal: 253 s->PutCString("kind = global, "); 254 break; 255 256 case eValueTypeVariableStatic: 257 s->PutCString("kind = static, "); 258 break; 259 260 case eValueTypeVariableArgument: 261 s->PutCString("kind = argument, "); 262 break; 263 264 case eValueTypeVariableLocal: 265 s->PutCString("kind = local, "); 266 break; 267 268 case eValueTypeVariableThreadLocal: 269 s->PutCString("kind = thread local, "); 270 break; 271 272 default: 273 break; 274 } 275 276 s->Printf("name = \"%s\"\n", variable->GetName().GetCString()); 277 } 278 } 279 280 uint32_t SymbolContext::GetResolvedMask() const { 281 uint32_t resolved_mask = 0; 282 if (target_sp) 283 resolved_mask |= eSymbolContextTarget; 284 if (module_sp) 285 resolved_mask |= eSymbolContextModule; 286 if (comp_unit) 287 resolved_mask |= eSymbolContextCompUnit; 288 if (function) 289 resolved_mask |= eSymbolContextFunction; 290 if (block) 291 resolved_mask |= eSymbolContextBlock; 292 if (line_entry.IsValid()) 293 resolved_mask |= eSymbolContextLineEntry; 294 if (symbol) 295 resolved_mask |= eSymbolContextSymbol; 296 if (variable) 297 resolved_mask |= eSymbolContextVariable; 298 return resolved_mask; 299 } 300 301 void SymbolContext::Dump(Stream *s, Target *target) const { 302 *s << this << ": "; 303 s->Indent(); 304 s->PutCString("SymbolContext"); 305 s->IndentMore(); 306 s->EOL(); 307 s->IndentMore(); 308 s->Indent(); 309 *s << "Module = " << module_sp.get() << ' '; 310 if (module_sp) 311 module_sp->GetFileSpec().Dump(s->AsRawOstream()); 312 s->EOL(); 313 s->Indent(); 314 *s << "CompileUnit = " << comp_unit; 315 if (comp_unit != nullptr) 316 s->Format(" {{{0:x-16}} {1}", comp_unit->GetID(), 317 comp_unit->GetPrimaryFile()); 318 s->EOL(); 319 s->Indent(); 320 *s << "Function = " << function; 321 if (function != nullptr) { 322 s->Format(" {{{0:x-16}} {1}, address-range = ", function->GetID(), 323 function->GetType()->GetName()); 324 function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, 325 Address::DumpStyleModuleWithFileAddress); 326 s->EOL(); 327 s->Indent(); 328 Type *func_type = function->GetType(); 329 if (func_type) { 330 *s << " Type = "; 331 func_type->Dump(s, false); 332 } 333 } 334 s->EOL(); 335 s->Indent(); 336 *s << "Block = " << block; 337 if (block != nullptr) 338 s->Format(" {{{0:x-16}}", block->GetID()); 339 s->EOL(); 340 s->Indent(); 341 *s << "LineEntry = "; 342 line_entry.Dump(s, target, true, Address::DumpStyleLoadAddress, 343 Address::DumpStyleModuleWithFileAddress, true); 344 s->EOL(); 345 s->Indent(); 346 *s << "Symbol = " << symbol; 347 if (symbol != nullptr && symbol->GetMangled()) 348 *s << ' ' << symbol->GetName().AsCString(); 349 s->EOL(); 350 *s << "Variable = " << variable; 351 if (variable != nullptr) { 352 s->Format(" {{{0:x-16}} {1}", variable->GetID(), 353 variable->GetType()->GetName()); 354 s->EOL(); 355 } 356 s->IndentLess(); 357 s->IndentLess(); 358 } 359 360 bool lldb_private::operator==(const SymbolContext &lhs, 361 const SymbolContext &rhs) { 362 return lhs.function == rhs.function && lhs.symbol == rhs.symbol && 363 lhs.module_sp.get() == rhs.module_sp.get() && 364 lhs.comp_unit == rhs.comp_unit && 365 lhs.target_sp.get() == rhs.target_sp.get() && 366 LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 && 367 lhs.variable == rhs.variable; 368 } 369 370 bool lldb_private::operator!=(const SymbolContext &lhs, 371 const SymbolContext &rhs) { 372 return !(lhs == rhs); 373 } 374 375 bool SymbolContext::GetAddressRange(uint32_t scope, uint32_t range_idx, 376 bool use_inline_block_range, 377 AddressRange &range) const { 378 if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) { 379 range = line_entry.range; 380 return true; 381 } 382 383 if ((scope & eSymbolContextBlock) && (block != nullptr)) { 384 if (use_inline_block_range) { 385 Block *inline_block = block->GetContainingInlinedBlock(); 386 if (inline_block) 387 return inline_block->GetRangeAtIndex(range_idx, range); 388 } else { 389 return block->GetRangeAtIndex(range_idx, range); 390 } 391 } 392 393 if ((scope & eSymbolContextFunction) && (function != nullptr)) { 394 if (range_idx == 0) { 395 range = function->GetAddressRange(); 396 return true; 397 } 398 } 399 400 if ((scope & eSymbolContextSymbol) && (symbol != nullptr)) { 401 if (range_idx == 0) { 402 if (symbol->ValueIsAddress()) { 403 range.GetBaseAddress() = symbol->GetAddressRef(); 404 range.SetByteSize(symbol->GetByteSize()); 405 return true; 406 } 407 } 408 } 409 range.Clear(); 410 return false; 411 } 412 413 LanguageType SymbolContext::GetLanguage() const { 414 LanguageType lang; 415 if (function && (lang = function->GetLanguage()) != eLanguageTypeUnknown) { 416 return lang; 417 } else if (variable && 418 (lang = variable->GetLanguage()) != eLanguageTypeUnknown) { 419 return lang; 420 } else if (symbol && (lang = symbol->GetLanguage()) != eLanguageTypeUnknown) { 421 return lang; 422 } else if (comp_unit && 423 (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown) { 424 return lang; 425 } else if (symbol) { 426 // If all else fails, try to guess the language from the name. 427 return symbol->GetMangled().GuessLanguage(); 428 } 429 return eLanguageTypeUnknown; 430 } 431 432 bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc, 433 SymbolContext &next_frame_sc, 434 Address &next_frame_pc) const { 435 next_frame_sc.Clear(false); 436 next_frame_pc.Clear(); 437 438 if (block) { 439 // const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress(); 440 441 // In order to get the parent of an inlined function we first need to see 442 // if we are in an inlined block as "this->block" could be an inlined 443 // block, or a parent of "block" could be. So lets check if this block or 444 // one of this blocks parents is an inlined function. 445 Block *curr_inlined_block = block->GetContainingInlinedBlock(); 446 if (curr_inlined_block) { 447 // "this->block" is contained in an inline function block, so to get the 448 // scope above the inlined block, we get the parent of the inlined block 449 // itself 450 Block *next_frame_block = curr_inlined_block->GetParent(); 451 // Now calculate the symbol context of the containing block 452 next_frame_block->CalculateSymbolContext(&next_frame_sc); 453 454 // If we get here we weren't able to find the return line entry using the 455 // nesting of the blocks and the line table. So just use the call site 456 // info from our inlined block. 457 458 AddressRange range; 459 if (curr_inlined_block->GetRangeContainingAddress(curr_frame_pc, range)) { 460 // To see there this new frame block it, we need to look at the call 461 // site information from 462 const InlineFunctionInfo *curr_inlined_block_inlined_info = 463 curr_inlined_block->GetInlinedFunctionInfo(); 464 next_frame_pc = range.GetBaseAddress(); 465 next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc; 466 next_frame_sc.line_entry.file = 467 curr_inlined_block_inlined_info->GetCallSite().GetFile(); 468 next_frame_sc.line_entry.original_file = 469 curr_inlined_block_inlined_info->GetCallSite().GetFile(); 470 next_frame_sc.line_entry.line = 471 curr_inlined_block_inlined_info->GetCallSite().GetLine(); 472 next_frame_sc.line_entry.column = 473 curr_inlined_block_inlined_info->GetCallSite().GetColumn(); 474 return true; 475 } else { 476 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); 477 478 if (log) { 479 LLDB_LOGF( 480 log, 481 "warning: inlined block 0x%8.8" PRIx64 482 " doesn't have a range that contains file address 0x%" PRIx64, 483 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); 484 } 485 #ifdef LLDB_CONFIGURATION_DEBUG 486 else { 487 ObjectFile *objfile = nullptr; 488 if (module_sp) { 489 if (SymbolFile *symbol_file = module_sp->GetSymbolFile()) 490 objfile = symbol_file->GetObjectFile(); 491 } 492 if (objfile) { 493 Host::SystemLog( 494 Host::eSystemLogWarning, 495 "warning: inlined block 0x%8.8" PRIx64 496 " doesn't have a range that contains file address 0x%" PRIx64 497 " in %s\n", 498 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress(), 499 objfile->GetFileSpec().GetPath().c_str()); 500 } else { 501 Host::SystemLog( 502 Host::eSystemLogWarning, 503 "warning: inlined block 0x%8.8" PRIx64 504 " doesn't have a range that contains file address 0x%" PRIx64 505 "\n", 506 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); 507 } 508 } 509 #endif 510 } 511 } 512 } 513 514 return false; 515 } 516 517 Block *SymbolContext::GetFunctionBlock() { 518 if (function) { 519 if (block) { 520 // If this symbol context has a block, check to see if this block is 521 // itself, or is contained within a block with inlined function 522 // information. If so, then the inlined block is the block that defines 523 // the function. 524 Block *inlined_block = block->GetContainingInlinedBlock(); 525 if (inlined_block) 526 return inlined_block; 527 528 // The block in this symbol context is not inside an inlined block, so 529 // the block that defines the function is the function's top level block, 530 // which is returned below. 531 } 532 533 // There is no block information in this symbol context, so we must assume 534 // that the block that is desired is the top level block of the function 535 // itself. 536 return &function->GetBlock(true); 537 } 538 return nullptr; 539 } 540 541 bool SymbolContext::GetFunctionMethodInfo(lldb::LanguageType &language, 542 bool &is_instance_method, 543 ConstString &language_object_name) 544 545 { 546 Block *function_block = GetFunctionBlock(); 547 if (function_block) { 548 CompilerDeclContext decl_ctx = function_block->GetDeclContext(); 549 if (decl_ctx) 550 return decl_ctx.IsClassMethod(&language, &is_instance_method, 551 &language_object_name); 552 } 553 return false; 554 } 555 556 void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const { 557 Block *curr_block = block; 558 bool isInlinedblock = false; 559 if (curr_block != nullptr && 560 curr_block->GetContainingInlinedBlock() != nullptr) 561 isInlinedblock = true; 562 563 // Find all types that match the current block if we have one and put them 564 // first in the list. Keep iterating up through all blocks. 565 while (curr_block != nullptr && !isInlinedblock) { 566 type_map.ForEach( 567 [curr_block, &type_list](const lldb::TypeSP &type_sp) -> bool { 568 SymbolContextScope *scs = type_sp->GetSymbolContextScope(); 569 if (scs && curr_block == scs->CalculateSymbolContextBlock()) 570 type_list.Insert(type_sp); 571 return true; // Keep iterating 572 }); 573 574 // Remove any entries that are now in "type_list" from "type_map" since we 575 // can't remove from type_map while iterating 576 type_list.ForEach([&type_map](const lldb::TypeSP &type_sp) -> bool { 577 type_map.Remove(type_sp); 578 return true; // Keep iterating 579 }); 580 curr_block = curr_block->GetParent(); 581 } 582 // Find all types that match the current function, if we have onem, and put 583 // them next in the list. 584 if (function != nullptr && !type_map.Empty()) { 585 const size_t old_type_list_size = type_list.GetSize(); 586 type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool { 587 SymbolContextScope *scs = type_sp->GetSymbolContextScope(); 588 if (scs && function == scs->CalculateSymbolContextFunction()) 589 type_list.Insert(type_sp); 590 return true; // Keep iterating 591 }); 592 593 // Remove any entries that are now in "type_list" from "type_map" since we 594 // can't remove from type_map while iterating 595 const size_t new_type_list_size = type_list.GetSize(); 596 if (new_type_list_size > old_type_list_size) { 597 for (size_t i = old_type_list_size; i < new_type_list_size; ++i) 598 type_map.Remove(type_list.GetTypeAtIndex(i)); 599 } 600 } 601 // Find all types that match the current compile unit, if we have one, and 602 // put them next in the list. 603 if (comp_unit != nullptr && !type_map.Empty()) { 604 const size_t old_type_list_size = type_list.GetSize(); 605 606 type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool { 607 SymbolContextScope *scs = type_sp->GetSymbolContextScope(); 608 if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit()) 609 type_list.Insert(type_sp); 610 return true; // Keep iterating 611 }); 612 613 // Remove any entries that are now in "type_list" from "type_map" since we 614 // can't remove from type_map while iterating 615 const size_t new_type_list_size = type_list.GetSize(); 616 if (new_type_list_size > old_type_list_size) { 617 for (size_t i = old_type_list_size; i < new_type_list_size; ++i) 618 type_map.Remove(type_list.GetTypeAtIndex(i)); 619 } 620 } 621 // Find all types that match the current module, if we have one, and put them 622 // next in the list. 623 if (module_sp && !type_map.Empty()) { 624 const size_t old_type_list_size = type_list.GetSize(); 625 type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool { 626 SymbolContextScope *scs = type_sp->GetSymbolContextScope(); 627 if (scs && module_sp == scs->CalculateSymbolContextModule()) 628 type_list.Insert(type_sp); 629 return true; // Keep iterating 630 }); 631 // Remove any entries that are now in "type_list" from "type_map" since we 632 // can't remove from type_map while iterating 633 const size_t new_type_list_size = type_list.GetSize(); 634 if (new_type_list_size > old_type_list_size) { 635 for (size_t i = old_type_list_size; i < new_type_list_size; ++i) 636 type_map.Remove(type_list.GetTypeAtIndex(i)); 637 } 638 } 639 // Any types that are left get copied into the list an any order. 640 if (!type_map.Empty()) { 641 type_map.ForEach([&type_list](const lldb::TypeSP &type_sp) -> bool { 642 type_list.Insert(type_sp); 643 return true; // Keep iterating 644 }); 645 } 646 } 647 648 ConstString 649 SymbolContext::GetFunctionName(Mangled::NamePreference preference) const { 650 if (function) { 651 if (block) { 652 Block *inlined_block = block->GetContainingInlinedBlock(); 653 654 if (inlined_block) { 655 const InlineFunctionInfo *inline_info = 656 inlined_block->GetInlinedFunctionInfo(); 657 if (inline_info) 658 return inline_info->GetName(); 659 } 660 } 661 return function->GetMangled().GetName(preference); 662 } else if (symbol && symbol->ValueIsAddress()) { 663 return symbol->GetMangled().GetName(preference); 664 } else { 665 // No function, return an empty string. 666 return ConstString(); 667 } 668 } 669 670 LineEntry SymbolContext::GetFunctionStartLineEntry() const { 671 LineEntry line_entry; 672 Address start_addr; 673 if (block) { 674 Block *inlined_block = block->GetContainingInlinedBlock(); 675 if (inlined_block) { 676 if (inlined_block->GetStartAddress(start_addr)) { 677 if (start_addr.CalculateSymbolContextLineEntry(line_entry)) 678 return line_entry; 679 } 680 return LineEntry(); 681 } 682 } 683 684 if (function) { 685 if (function->GetAddressRange() 686 .GetBaseAddress() 687 .CalculateSymbolContextLineEntry(line_entry)) 688 return line_entry; 689 } 690 return LineEntry(); 691 } 692 693 bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, 694 AddressRange &range, 695 Status &error) { 696 if (!line_entry.IsValid()) { 697 error.SetErrorString("Symbol context has no line table."); 698 return false; 699 } 700 701 range = line_entry.range; 702 if (line_entry.line > end_line) { 703 error.SetErrorStringWithFormat( 704 "end line option %d must be after the current line: %d", end_line, 705 line_entry.line); 706 return false; 707 } 708 709 uint32_t line_index = 0; 710 bool found = false; 711 while (true) { 712 LineEntry this_line; 713 line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr, 714 false, &this_line); 715 if (line_index == UINT32_MAX) 716 break; 717 if (LineEntry::Compare(this_line, line_entry) == 0) { 718 found = true; 719 break; 720 } 721 } 722 723 LineEntry end_entry; 724 if (!found) { 725 // Can't find the index of the SymbolContext's line entry in the 726 // SymbolContext's CompUnit. 727 error.SetErrorString( 728 "Can't find the current line entry in the CompUnit - can't process " 729 "the end-line option"); 730 return false; 731 } 732 733 line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false, 734 &end_entry); 735 if (line_index == UINT32_MAX) { 736 error.SetErrorStringWithFormat( 737 "could not find a line table entry corresponding " 738 "to end line number %d", 739 end_line); 740 return false; 741 } 742 743 Block *func_block = GetFunctionBlock(); 744 if (func_block && func_block->GetRangeIndexContainingAddress( 745 end_entry.range.GetBaseAddress()) == UINT32_MAX) { 746 error.SetErrorStringWithFormat( 747 "end line number %d is not contained within the current function.", 748 end_line); 749 return false; 750 } 751 752 lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() - 753 range.GetBaseAddress().GetFileAddress(); 754 range.SetByteSize(range_size); 755 return true; 756 } 757 758 const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name, 759 Status &error) { 760 error.Clear(); 761 762 if (!target_sp) { 763 return nullptr; 764 } 765 766 Target &target = *target_sp; 767 Module *module = module_sp.get(); 768 769 auto ProcessMatches = [this, &name, &target, 770 module](SymbolContextList &sc_list, 771 Status &error) -> const Symbol * { 772 llvm::SmallVector<const Symbol *, 1> external_symbols; 773 llvm::SmallVector<const Symbol *, 1> internal_symbols; 774 const uint32_t matches = sc_list.GetSize(); 775 for (uint32_t i = 0; i < matches; ++i) { 776 SymbolContext sym_ctx; 777 sc_list.GetContextAtIndex(i, sym_ctx); 778 if (sym_ctx.symbol) { 779 const Symbol *symbol = sym_ctx.symbol; 780 const Address sym_address = symbol->GetAddress(); 781 782 if (sym_address.IsValid()) { 783 switch (symbol->GetType()) { 784 case eSymbolTypeData: 785 case eSymbolTypeRuntime: 786 case eSymbolTypeAbsolute: 787 case eSymbolTypeObjCClass: 788 case eSymbolTypeObjCMetaClass: 789 case eSymbolTypeObjCIVar: 790 if (symbol->GetDemangledNameIsSynthesized()) { 791 // If the demangled name was synthesized, then don't use it for 792 // expressions. Only let the symbol match if the mangled named 793 // matches for these symbols. 794 if (symbol->GetMangled().GetMangledName() != name) 795 break; 796 } 797 if (symbol->IsExternal()) { 798 external_symbols.push_back(symbol); 799 } else { 800 internal_symbols.push_back(symbol); 801 } 802 break; 803 case eSymbolTypeReExported: { 804 ConstString reexport_name = symbol->GetReExportedSymbolName(); 805 if (reexport_name) { 806 ModuleSP reexport_module_sp; 807 ModuleSpec reexport_module_spec; 808 reexport_module_spec.GetPlatformFileSpec() = 809 symbol->GetReExportedSymbolSharedLibrary(); 810 if (reexport_module_spec.GetPlatformFileSpec()) { 811 reexport_module_sp = 812 target.GetImages().FindFirstModule(reexport_module_spec); 813 if (!reexport_module_sp) { 814 reexport_module_spec.GetPlatformFileSpec() 815 .GetDirectory() 816 .Clear(); 817 reexport_module_sp = 818 target.GetImages().FindFirstModule(reexport_module_spec); 819 } 820 } 821 // Don't allow us to try and resolve a re-exported symbol if it 822 // is the same as the current symbol 823 if (name == symbol->GetReExportedSymbolName() && 824 module == reexport_module_sp.get()) 825 return nullptr; 826 827 return FindBestGlobalDataSymbol(symbol->GetReExportedSymbolName(), 828 error); 829 } 830 } break; 831 832 case eSymbolTypeCode: // We already lookup functions elsewhere 833 case eSymbolTypeVariable: 834 case eSymbolTypeLocal: 835 case eSymbolTypeParam: 836 case eSymbolTypeTrampoline: 837 case eSymbolTypeInvalid: 838 case eSymbolTypeException: 839 case eSymbolTypeSourceFile: 840 case eSymbolTypeHeaderFile: 841 case eSymbolTypeObjectFile: 842 case eSymbolTypeCommonBlock: 843 case eSymbolTypeBlock: 844 case eSymbolTypeVariableType: 845 case eSymbolTypeLineEntry: 846 case eSymbolTypeLineHeader: 847 case eSymbolTypeScopeBegin: 848 case eSymbolTypeScopeEnd: 849 case eSymbolTypeAdditional: 850 case eSymbolTypeCompiler: 851 case eSymbolTypeInstrumentation: 852 case eSymbolTypeUndefined: 853 case eSymbolTypeResolver: 854 break; 855 } 856 } 857 } 858 } 859 860 if (external_symbols.size() > 1) { 861 StreamString ss; 862 ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString()); 863 for (const Symbol *symbol : external_symbols) { 864 symbol->GetDescription(&ss, eDescriptionLevelFull, &target); 865 } 866 ss.PutChar('\n'); 867 error.SetErrorString(ss.GetData()); 868 return nullptr; 869 } else if (external_symbols.size()) { 870 return external_symbols[0]; 871 } else if (internal_symbols.size() > 1) { 872 StreamString ss; 873 ss.Printf("Multiple internal symbols found for '%s'\n", name.AsCString()); 874 for (const Symbol *symbol : internal_symbols) { 875 symbol->GetDescription(&ss, eDescriptionLevelVerbose, &target); 876 ss.PutChar('\n'); 877 } 878 error.SetErrorString(ss.GetData()); 879 return nullptr; 880 } else if (internal_symbols.size()) { 881 return internal_symbols[0]; 882 } else { 883 return nullptr; 884 } 885 }; 886 887 if (module) { 888 SymbolContextList sc_list; 889 module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); 890 const Symbol *const module_symbol = ProcessMatches(sc_list, error); 891 892 if (!error.Success()) { 893 return nullptr; 894 } else if (module_symbol) { 895 return module_symbol; 896 } 897 } 898 899 { 900 SymbolContextList sc_list; 901 target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, 902 sc_list); 903 const Symbol *const target_symbol = ProcessMatches(sc_list, error); 904 905 if (!error.Success()) { 906 return nullptr; 907 } else if (target_symbol) { 908 return target_symbol; 909 } 910 } 911 912 return nullptr; // no error; we just didn't find anything 913 } 914 915 // 916 // SymbolContextSpecifier 917 // 918 919 SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp) 920 : m_target_sp(target_sp), m_module_spec(), m_module_sp(), m_file_spec_up(), 921 m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(), 922 m_address_range_up(), m_type(eNothingSpecified) {} 923 924 SymbolContextSpecifier::~SymbolContextSpecifier() {} 925 926 bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no, 927 SpecificationType type) { 928 bool return_value = true; 929 switch (type) { 930 case eNothingSpecified: 931 Clear(); 932 break; 933 case eLineStartSpecified: 934 m_start_line = line_no; 935 m_type |= eLineStartSpecified; 936 break; 937 case eLineEndSpecified: 938 m_end_line = line_no; 939 m_type |= eLineEndSpecified; 940 break; 941 default: 942 return_value = false; 943 break; 944 } 945 return return_value; 946 } 947 948 bool SymbolContextSpecifier::AddSpecification(const char *spec_string, 949 SpecificationType type) { 950 bool return_value = true; 951 switch (type) { 952 case eNothingSpecified: 953 Clear(); 954 break; 955 case eModuleSpecified: { 956 // See if we can find the Module, if so stick it in the SymbolContext. 957 FileSpec module_file_spec(spec_string); 958 ModuleSpec module_spec(module_file_spec); 959 lldb::ModuleSP module_sp( 960 m_target_sp->GetImages().FindFirstModule(module_spec)); 961 m_type |= eModuleSpecified; 962 if (module_sp) 963 m_module_sp = module_sp; 964 else 965 m_module_spec.assign(spec_string); 966 } break; 967 case eFileSpecified: 968 // CompUnits can't necessarily be resolved here, since an inlined function 969 // might show up in a number of CompUnits. Instead we just convert to a 970 // FileSpec and store it away. 971 m_file_spec_up = std::make_unique<FileSpec>(spec_string); 972 m_type |= eFileSpecified; 973 break; 974 case eLineStartSpecified: 975 m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); 976 if (return_value) 977 m_type |= eLineStartSpecified; 978 break; 979 case eLineEndSpecified: 980 m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); 981 if (return_value) 982 m_type |= eLineEndSpecified; 983 break; 984 case eFunctionSpecified: 985 m_function_spec.assign(spec_string); 986 m_type |= eFunctionSpecified; 987 break; 988 case eClassOrNamespaceSpecified: 989 Clear(); 990 m_class_name.assign(spec_string); 991 m_type = eClassOrNamespaceSpecified; 992 break; 993 case eAddressRangeSpecified: 994 // Not specified yet... 995 break; 996 } 997 998 return return_value; 999 } 1000 1001 void SymbolContextSpecifier::Clear() { 1002 m_module_spec.clear(); 1003 m_file_spec_up.reset(); 1004 m_function_spec.clear(); 1005 m_class_name.clear(); 1006 m_start_line = 0; 1007 m_end_line = 0; 1008 m_address_range_up.reset(); 1009 1010 m_type = eNothingSpecified; 1011 } 1012 1013 bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) { 1014 if (m_type == eNothingSpecified) 1015 return true; 1016 1017 if (m_target_sp.get() != sc.target_sp.get()) 1018 return false; 1019 1020 if (m_type & eModuleSpecified) { 1021 if (sc.module_sp) { 1022 if (m_module_sp.get() != nullptr) { 1023 if (m_module_sp.get() != sc.module_sp.get()) 1024 return false; 1025 } else { 1026 FileSpec module_file_spec(m_module_spec); 1027 if (!FileSpec::Match(module_file_spec, sc.module_sp->GetFileSpec())) 1028 return false; 1029 } 1030 } 1031 } 1032 if (m_type & eFileSpecified) { 1033 if (m_file_spec_up) { 1034 // If we don't have a block or a comp_unit, then we aren't going to match 1035 // a source file. 1036 if (sc.block == nullptr && sc.comp_unit == nullptr) 1037 return false; 1038 1039 // Check if the block is present, and if so is it inlined: 1040 bool was_inlined = false; 1041 if (sc.block != nullptr) { 1042 const InlineFunctionInfo *inline_info = 1043 sc.block->GetInlinedFunctionInfo(); 1044 if (inline_info != nullptr) { 1045 was_inlined = true; 1046 if (!FileSpec::Match(*m_file_spec_up, 1047 inline_info->GetDeclaration().GetFile())) 1048 return false; 1049 } 1050 } 1051 1052 // Next check the comp unit, but only if the SymbolContext was not 1053 // inlined. 1054 if (!was_inlined && sc.comp_unit != nullptr) { 1055 if (!FileSpec::Match(*m_file_spec_up, sc.comp_unit->GetPrimaryFile())) 1056 return false; 1057 } 1058 } 1059 } 1060 if (m_type & eLineStartSpecified || m_type & eLineEndSpecified) { 1061 if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line) 1062 return false; 1063 } 1064 1065 if (m_type & eFunctionSpecified) { 1066 // First check the current block, and if it is inlined, get the inlined 1067 // function name: 1068 bool was_inlined = false; 1069 ConstString func_name(m_function_spec.c_str()); 1070 1071 if (sc.block != nullptr) { 1072 const InlineFunctionInfo *inline_info = 1073 sc.block->GetInlinedFunctionInfo(); 1074 if (inline_info != nullptr) { 1075 was_inlined = true; 1076 const Mangled &name = inline_info->GetMangled(); 1077 if (!name.NameMatches(func_name)) 1078 return false; 1079 } 1080 } 1081 // If it wasn't inlined, check the name in the function or symbol: 1082 if (!was_inlined) { 1083 if (sc.function != nullptr) { 1084 if (!sc.function->GetMangled().NameMatches(func_name)) 1085 return false; 1086 } else if (sc.symbol != nullptr) { 1087 if (!sc.symbol->GetMangled().NameMatches(func_name)) 1088 return false; 1089 } 1090 } 1091 } 1092 1093 return true; 1094 } 1095 1096 bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) { 1097 if (m_type & eAddressRangeSpecified) { 1098 1099 } else { 1100 Address match_address(addr, nullptr); 1101 SymbolContext sc; 1102 m_target_sp->GetImages().ResolveSymbolContextForAddress( 1103 match_address, eSymbolContextEverything, sc); 1104 return SymbolContextMatches(sc); 1105 } 1106 return true; 1107 } 1108 1109 void SymbolContextSpecifier::GetDescription( 1110 Stream *s, lldb::DescriptionLevel level) const { 1111 char path_str[PATH_MAX + 1]; 1112 1113 if (m_type == eNothingSpecified) { 1114 s->Printf("Nothing specified.\n"); 1115 } 1116 1117 if (m_type == eModuleSpecified) { 1118 s->Indent(); 1119 if (m_module_sp) { 1120 m_module_sp->GetFileSpec().GetPath(path_str, PATH_MAX); 1121 s->Printf("Module: %s\n", path_str); 1122 } else 1123 s->Printf("Module: %s\n", m_module_spec.c_str()); 1124 } 1125 1126 if (m_type == eFileSpecified && m_file_spec_up != nullptr) { 1127 m_file_spec_up->GetPath(path_str, PATH_MAX); 1128 s->Indent(); 1129 s->Printf("File: %s", path_str); 1130 if (m_type == eLineStartSpecified) { 1131 s->Printf(" from line %" PRIu64 "", (uint64_t)m_start_line); 1132 if (m_type == eLineEndSpecified) 1133 s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line); 1134 else 1135 s->Printf("to end"); 1136 } else if (m_type == eLineEndSpecified) { 1137 s->Printf(" from start to line %" PRIu64 "", (uint64_t)m_end_line); 1138 } 1139 s->Printf(".\n"); 1140 } 1141 1142 if (m_type == eLineStartSpecified) { 1143 s->Indent(); 1144 s->Printf("From line %" PRIu64 "", (uint64_t)m_start_line); 1145 if (m_type == eLineEndSpecified) 1146 s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line); 1147 else 1148 s->Printf("to end"); 1149 s->Printf(".\n"); 1150 } else if (m_type == eLineEndSpecified) { 1151 s->Printf("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line); 1152 } 1153 1154 if (m_type == eFunctionSpecified) { 1155 s->Indent(); 1156 s->Printf("Function: %s.\n", m_function_spec.c_str()); 1157 } 1158 1159 if (m_type == eClassOrNamespaceSpecified) { 1160 s->Indent(); 1161 s->Printf("Class name: %s.\n", m_class_name.c_str()); 1162 } 1163 1164 if (m_type == eAddressRangeSpecified && m_address_range_up != nullptr) { 1165 s->Indent(); 1166 s->PutCString("Address range: "); 1167 m_address_range_up->Dump(s, m_target_sp.get(), 1168 Address::DumpStyleLoadAddress, 1169 Address::DumpStyleFileAddress); 1170 s->PutCString("\n"); 1171 } 1172 } 1173 1174 // 1175 // SymbolContextList 1176 // 1177 1178 SymbolContextList::SymbolContextList() : m_symbol_contexts() {} 1179 1180 SymbolContextList::~SymbolContextList() {} 1181 1182 void SymbolContextList::Append(const SymbolContext &sc) { 1183 m_symbol_contexts.push_back(sc); 1184 } 1185 1186 void SymbolContextList::Append(const SymbolContextList &sc_list) { 1187 collection::const_iterator pos, end = sc_list.m_symbol_contexts.end(); 1188 for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) 1189 m_symbol_contexts.push_back(*pos); 1190 } 1191 1192 uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList &sc_list, 1193 bool merge_symbol_into_function) { 1194 uint32_t unique_sc_add_count = 0; 1195 collection::const_iterator pos, end = sc_list.m_symbol_contexts.end(); 1196 for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) { 1197 if (AppendIfUnique(*pos, merge_symbol_into_function)) 1198 ++unique_sc_add_count; 1199 } 1200 return unique_sc_add_count; 1201 } 1202 1203 bool SymbolContextList::AppendIfUnique(const SymbolContext &sc, 1204 bool merge_symbol_into_function) { 1205 collection::iterator pos, end = m_symbol_contexts.end(); 1206 for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { 1207 if (*pos == sc) 1208 return false; 1209 } 1210 if (merge_symbol_into_function && sc.symbol != nullptr && 1211 sc.comp_unit == nullptr && sc.function == nullptr && 1212 sc.block == nullptr && !sc.line_entry.IsValid()) { 1213 if (sc.symbol->ValueIsAddress()) { 1214 for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { 1215 // Don't merge symbols into inlined function symbol contexts 1216 if (pos->block && pos->block->GetContainingInlinedBlock()) 1217 continue; 1218 1219 if (pos->function) { 1220 if (pos->function->GetAddressRange().GetBaseAddress() == 1221 sc.symbol->GetAddressRef()) { 1222 // Do we already have a function with this symbol? 1223 if (pos->symbol == sc.symbol) 1224 return false; 1225 if (pos->symbol == nullptr) { 1226 pos->symbol = sc.symbol; 1227 return false; 1228 } 1229 } 1230 } 1231 } 1232 } 1233 } 1234 m_symbol_contexts.push_back(sc); 1235 return true; 1236 } 1237 1238 void SymbolContextList::Clear() { m_symbol_contexts.clear(); } 1239 1240 void SymbolContextList::Dump(Stream *s, Target *target) const { 1241 1242 *s << this << ": "; 1243 s->Indent(); 1244 s->PutCString("SymbolContextList"); 1245 s->EOL(); 1246 s->IndentMore(); 1247 1248 collection::const_iterator pos, end = m_symbol_contexts.end(); 1249 for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { 1250 // pos->Dump(s, target); 1251 pos->GetDescription(s, eDescriptionLevelVerbose, target); 1252 } 1253 s->IndentLess(); 1254 } 1255 1256 bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const { 1257 if (idx < m_symbol_contexts.size()) { 1258 sc = m_symbol_contexts[idx]; 1259 return true; 1260 } 1261 return false; 1262 } 1263 1264 bool SymbolContextList::RemoveContextAtIndex(size_t idx) { 1265 if (idx < m_symbol_contexts.size()) { 1266 m_symbol_contexts.erase(m_symbol_contexts.begin() + idx); 1267 return true; 1268 } 1269 return false; 1270 } 1271 1272 uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); } 1273 1274 bool SymbolContextList::IsEmpty() const { return m_symbol_contexts.empty(); } 1275 1276 uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const { 1277 uint32_t match_count = 0; 1278 const size_t size = m_symbol_contexts.size(); 1279 for (size_t idx = 0; idx < size; ++idx) { 1280 if (m_symbol_contexts[idx].line_entry.line == line) 1281 ++match_count; 1282 } 1283 return match_count; 1284 } 1285 1286 void SymbolContextList::GetDescription(Stream *s, lldb::DescriptionLevel level, 1287 Target *target) const { 1288 const size_t size = m_symbol_contexts.size(); 1289 for (size_t idx = 0; idx < size; ++idx) 1290 m_symbol_contexts[idx].GetDescription(s, level, target); 1291 } 1292 1293 bool lldb_private::operator==(const SymbolContextList &lhs, 1294 const SymbolContextList &rhs) { 1295 const uint32_t size = lhs.GetSize(); 1296 if (size != rhs.GetSize()) 1297 return false; 1298 1299 SymbolContext lhs_sc; 1300 SymbolContext rhs_sc; 1301 for (uint32_t i = 0; i < size; ++i) { 1302 lhs.GetContextAtIndex(i, lhs_sc); 1303 rhs.GetContextAtIndex(i, rhs_sc); 1304 if (lhs_sc != rhs_sc) 1305 return false; 1306 } 1307 return true; 1308 } 1309 1310 bool lldb_private::operator!=(const SymbolContextList &lhs, 1311 const SymbolContextList &rhs) { 1312 return !(lhs == rhs); 1313 } 1314