brintos

brintos / llvm-project-archived public Read only

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