Path: blob/main/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp
39587 views
//===-- SymbolContext.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Symbol/SymbolContext.h"910#include "lldb/Core/Address.h"11#include "lldb/Core/Debugger.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ModuleSpec.h"14#include "lldb/Host/Host.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/Language.h"23#include "lldb/Target/Target.h"24#include "lldb/Utility/LLDBLog.h"25#include "lldb/Utility/Log.h"26#include "lldb/Utility/Stream.h"27#include "lldb/Utility/StreamString.h"28#include "lldb/lldb-enumerations.h"2930using namespace lldb;31using namespace lldb_private;3233SymbolContext::SymbolContext() : target_sp(), module_sp(), line_entry() {}3435SymbolContext::SymbolContext(const ModuleSP &m, CompileUnit *cu, Function *f,36Block *b, LineEntry *le, Symbol *s)37: target_sp(), module_sp(m), comp_unit(cu), function(f), block(b),38line_entry(), symbol(s) {39if (le)40line_entry = *le;41}4243SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP &m,44CompileUnit *cu, Function *f, Block *b,45LineEntry *le, Symbol *s)46: target_sp(t), module_sp(m), comp_unit(cu), function(f), block(b),47line_entry(), symbol(s) {48if (le)49line_entry = *le;50}5152SymbolContext::SymbolContext(SymbolContextScope *sc_scope)53: target_sp(), module_sp(), line_entry() {54sc_scope->CalculateSymbolContext(this);55}5657SymbolContext::~SymbolContext() = default;5859void SymbolContext::Clear(bool clear_target) {60if (clear_target)61target_sp.reset();62module_sp.reset();63comp_unit = nullptr;64function = nullptr;65block = nullptr;66line_entry.Clear();67symbol = nullptr;68variable = nullptr;69}7071bool SymbolContext::DumpStopContext(72Stream *s, ExecutionContextScope *exe_scope, const Address &addr,73bool show_fullpaths, bool show_module, bool show_inlined_frames,74bool show_function_arguments, bool show_function_name,75bool show_function_display_name,76std::optional<Stream::HighlightSettings> settings) const {77bool dumped_something = false;78if (show_module && module_sp) {79if (show_fullpaths)80*s << module_sp->GetFileSpec();81else82*s << module_sp->GetFileSpec().GetFilename();83s->PutChar('`');84dumped_something = true;85}86if (function != nullptr) {87SymbolContext inline_parent_sc;88Address inline_parent_addr;89if (!show_function_name) {90s->Printf("<");91dumped_something = true;92} else {93ConstString name;94if (!show_function_arguments)95name = function->GetNameNoArguments();96if (!name && show_function_display_name)97name = function->GetDisplayName();98if (!name)99name = function->GetName();100if (name)101s->PutCStringColorHighlighted(name.GetStringRef(), settings);102}103104if (addr.IsValid()) {105const addr_t function_offset =106addr.GetOffset() -107function->GetAddressRange().GetBaseAddress().GetOffset();108if (!show_function_name) {109// Print +offset even if offset is 0110dumped_something = true;111s->Printf("+%" PRIu64 ">", function_offset);112} else if (function_offset) {113dumped_something = true;114s->Printf(" + %" PRIu64, function_offset);115}116}117118if (GetParentOfInlinedScope(addr, inline_parent_sc, inline_parent_addr)) {119dumped_something = true;120Block *inlined_block = block->GetContainingInlinedBlock();121const InlineFunctionInfo *inlined_block_info =122inlined_block->GetInlinedFunctionInfo();123s->Printf(" [inlined] %s", inlined_block_info->GetName().GetCString());124125lldb_private::AddressRange block_range;126if (inlined_block->GetRangeContainingAddress(addr, block_range)) {127const addr_t inlined_function_offset =128addr.GetOffset() - block_range.GetBaseAddress().GetOffset();129if (inlined_function_offset) {130s->Printf(" + %" PRIu64, inlined_function_offset);131}132}133// "line_entry" will always be valid as GetParentOfInlinedScope(...) will134// fill it in correctly with the calling file and line. Previous code135// was extracting the calling file and line from inlined_block_info and136// using it right away which is not correct. On the first call to this137// function "line_entry" will contain the actual line table entry. On138// susequent calls "line_entry" will contain the calling file and line139// from the previous inline info.140if (line_entry.IsValid()) {141s->PutCString(" at ");142line_entry.DumpStopContext(s, show_fullpaths);143}144145if (show_inlined_frames) {146s->EOL();147s->Indent();148const bool show_function_name = true;149return inline_parent_sc.DumpStopContext(150s, exe_scope, inline_parent_addr, show_fullpaths, show_module,151show_inlined_frames, show_function_arguments, show_function_name,152show_function_display_name);153}154} else {155if (line_entry.IsValid()) {156dumped_something = true;157s->PutCString(" at ");158if (line_entry.DumpStopContext(s, show_fullpaths))159dumped_something = true;160}161}162} else if (symbol != nullptr) {163if (!show_function_name) {164s->Printf("<");165dumped_something = true;166} else if (symbol->GetName()) {167dumped_something = true;168if (symbol->GetType() == eSymbolTypeTrampoline)169s->PutCString("symbol stub for: ");170ConstString name;171if (show_function_display_name)172name = symbol->GetDisplayName();173if (!name)174name = symbol->GetName();175s->PutCStringColorHighlighted(name.GetStringRef(), settings);176}177178if (addr.IsValid() && symbol->ValueIsAddress()) {179const addr_t symbol_offset =180addr.GetOffset() - symbol->GetAddressRef().GetOffset();181if (!show_function_name) {182// Print +offset even if offset is 0183dumped_something = true;184s->Printf("+%" PRIu64 ">", symbol_offset);185} else if (symbol_offset) {186dumped_something = true;187s->Printf(" + %" PRIu64, symbol_offset);188}189}190} else if (addr.IsValid()) {191addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);192dumped_something = true;193}194return dumped_something;195}196197void SymbolContext::GetDescription(198Stream *s, lldb::DescriptionLevel level, Target *target,199std::optional<Stream::HighlightSettings> settings) const {200if (module_sp) {201s->Indent(" Module: file = \"");202module_sp->GetFileSpec().Dump(s->AsRawOstream());203*s << '"';204if (module_sp->GetArchitecture().IsValid())205s->Printf(", arch = \"%s\"",206module_sp->GetArchitecture().GetArchitectureName());207s->EOL();208}209210if (comp_unit != nullptr) {211s->Indent("CompileUnit: ");212comp_unit->GetDescription(s, level);213s->EOL();214}215216if (function != nullptr) {217s->Indent(" Function: ");218function->GetDescription(s, level, target);219s->EOL();220221Type *func_type = function->GetType();222if (func_type) {223s->Indent(" FuncType: ");224func_type->GetDescription(s, level, false, target);225s->EOL();226}227}228229if (block != nullptr) {230std::vector<Block *> blocks;231blocks.push_back(block);232Block *parent_block = block->GetParent();233234while (parent_block) {235blocks.push_back(parent_block);236parent_block = parent_block->GetParent();237}238std::vector<Block *>::reverse_iterator pos;239std::vector<Block *>::reverse_iterator begin = blocks.rbegin();240std::vector<Block *>::reverse_iterator end = blocks.rend();241for (pos = begin; pos != end; ++pos) {242if (pos == begin)243s->Indent(" Blocks: ");244else245s->Indent(" ");246(*pos)->GetDescription(s, function, level, target);247s->EOL();248}249}250251if (line_entry.IsValid()) {252s->Indent(" LineEntry: ");253line_entry.GetDescription(s, level, comp_unit, target, false);254s->EOL();255}256257if (symbol != nullptr) {258s->Indent(" Symbol: ");259symbol->GetDescription(s, level, target, settings);260s->EOL();261}262263if (variable != nullptr) {264s->Indent(" Variable: ");265266s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID());267268switch (variable->GetScope()) {269case eValueTypeVariableGlobal:270s->PutCString("kind = global, ");271break;272273case eValueTypeVariableStatic:274s->PutCString("kind = static, ");275break;276277case eValueTypeVariableArgument:278s->PutCString("kind = argument, ");279break;280281case eValueTypeVariableLocal:282s->PutCString("kind = local, ");283break;284285case eValueTypeVariableThreadLocal:286s->PutCString("kind = thread local, ");287break;288289default:290break;291}292293s->Printf("name = \"%s\"\n", variable->GetName().GetCString());294}295}296297uint32_t SymbolContext::GetResolvedMask() const {298uint32_t resolved_mask = 0;299if (target_sp)300resolved_mask |= eSymbolContextTarget;301if (module_sp)302resolved_mask |= eSymbolContextModule;303if (comp_unit)304resolved_mask |= eSymbolContextCompUnit;305if (function)306resolved_mask |= eSymbolContextFunction;307if (block)308resolved_mask |= eSymbolContextBlock;309if (line_entry.IsValid())310resolved_mask |= eSymbolContextLineEntry;311if (symbol)312resolved_mask |= eSymbolContextSymbol;313if (variable)314resolved_mask |= eSymbolContextVariable;315return resolved_mask;316}317318void SymbolContext::Dump(Stream *s, Target *target) const {319*s << this << ": ";320s->Indent();321s->PutCString("SymbolContext");322s->IndentMore();323s->EOL();324s->IndentMore();325s->Indent();326*s << "Module = " << module_sp.get() << ' ';327if (module_sp)328module_sp->GetFileSpec().Dump(s->AsRawOstream());329s->EOL();330s->Indent();331*s << "CompileUnit = " << comp_unit;332if (comp_unit != nullptr)333s->Format(" {{{0:x-16}} {1}", comp_unit->GetID(),334comp_unit->GetPrimaryFile());335s->EOL();336s->Indent();337*s << "Function = " << function;338if (function != nullptr) {339s->Format(" {{{0:x-16}} {1}, address-range = ", function->GetID(),340function->GetType()->GetName());341function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress,342Address::DumpStyleModuleWithFileAddress);343s->EOL();344s->Indent();345Type *func_type = function->GetType();346if (func_type) {347*s << " Type = ";348func_type->Dump(s, false);349}350}351s->EOL();352s->Indent();353*s << "Block = " << block;354if (block != nullptr)355s->Format(" {{{0:x-16}}", block->GetID());356s->EOL();357s->Indent();358*s << "LineEntry = ";359line_entry.Dump(s, target, true, Address::DumpStyleLoadAddress,360Address::DumpStyleModuleWithFileAddress, true);361s->EOL();362s->Indent();363*s << "Symbol = " << symbol;364if (symbol != nullptr && symbol->GetMangled())365*s << ' ' << symbol->GetName().AsCString();366s->EOL();367*s << "Variable = " << variable;368if (variable != nullptr) {369s->Format(" {{{0:x-16}} {1}", variable->GetID(),370variable->GetType()->GetName());371s->EOL();372}373s->IndentLess();374s->IndentLess();375}376377bool lldb_private::operator==(const SymbolContext &lhs,378const SymbolContext &rhs) {379return lhs.function == rhs.function && lhs.symbol == rhs.symbol &&380lhs.module_sp.get() == rhs.module_sp.get() &&381lhs.comp_unit == rhs.comp_unit &&382lhs.target_sp.get() == rhs.target_sp.get() &&383LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 &&384lhs.variable == rhs.variable;385}386387bool lldb_private::operator!=(const SymbolContext &lhs,388const SymbolContext &rhs) {389return !(lhs == rhs);390}391392bool SymbolContext::GetAddressRange(uint32_t scope, uint32_t range_idx,393bool use_inline_block_range,394AddressRange &range) const {395if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) {396range = line_entry.range;397return true;398}399400if ((scope & eSymbolContextBlock) && (block != nullptr)) {401if (use_inline_block_range) {402Block *inline_block = block->GetContainingInlinedBlock();403if (inline_block)404return inline_block->GetRangeAtIndex(range_idx, range);405} else {406return block->GetRangeAtIndex(range_idx, range);407}408}409410if ((scope & eSymbolContextFunction) && (function != nullptr)) {411if (range_idx == 0) {412range = function->GetAddressRange();413return true;414}415}416417if ((scope & eSymbolContextSymbol) && (symbol != nullptr)) {418if (range_idx == 0) {419if (symbol->ValueIsAddress()) {420range.GetBaseAddress() = symbol->GetAddressRef();421range.SetByteSize(symbol->GetByteSize());422return true;423}424}425}426range.Clear();427return false;428}429430LanguageType SymbolContext::GetLanguage() const {431LanguageType lang;432if (function && (lang = function->GetLanguage()) != eLanguageTypeUnknown) {433return lang;434} else if (variable &&435(lang = variable->GetLanguage()) != eLanguageTypeUnknown) {436return lang;437} else if (symbol && (lang = symbol->GetLanguage()) != eLanguageTypeUnknown) {438return lang;439} else if (comp_unit &&440(lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown) {441return lang;442} else if (symbol) {443// If all else fails, try to guess the language from the name.444return symbol->GetMangled().GuessLanguage();445}446return eLanguageTypeUnknown;447}448449bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc,450SymbolContext &next_frame_sc,451Address &next_frame_pc) const {452next_frame_sc.Clear(false);453next_frame_pc.Clear();454455if (block) {456// const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();457458// In order to get the parent of an inlined function we first need to see459// if we are in an inlined block as "this->block" could be an inlined460// block, or a parent of "block" could be. So lets check if this block or461// one of this blocks parents is an inlined function.462Block *curr_inlined_block = block->GetContainingInlinedBlock();463if (curr_inlined_block) {464// "this->block" is contained in an inline function block, so to get the465// scope above the inlined block, we get the parent of the inlined block466// itself467Block *next_frame_block = curr_inlined_block->GetParent();468// Now calculate the symbol context of the containing block469next_frame_block->CalculateSymbolContext(&next_frame_sc);470471// If we get here we weren't able to find the return line entry using the472// nesting of the blocks and the line table. So just use the call site473// info from our inlined block.474475AddressRange range;476if (curr_inlined_block->GetRangeContainingAddress(curr_frame_pc, range)) {477// To see there this new frame block it, we need to look at the call478// site information from479const InlineFunctionInfo *curr_inlined_block_inlined_info =480curr_inlined_block->GetInlinedFunctionInfo();481next_frame_pc = range.GetBaseAddress();482next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;483next_frame_sc.line_entry.file_sp = std::make_shared<SupportFile>(484curr_inlined_block_inlined_info->GetCallSite().GetFile());485next_frame_sc.line_entry.original_file_sp =486std::make_shared<SupportFile>(487curr_inlined_block_inlined_info->GetCallSite().GetFile());488next_frame_sc.line_entry.line =489curr_inlined_block_inlined_info->GetCallSite().GetLine();490next_frame_sc.line_entry.column =491curr_inlined_block_inlined_info->GetCallSite().GetColumn();492return true;493} else {494Log *log = GetLog(LLDBLog::Symbols);495496if (log) {497LLDB_LOGF(498log,499"warning: inlined block 0x%8.8" PRIx64500" doesn't have a range that contains file address 0x%" PRIx64,501curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());502}503#ifdef LLDB_CONFIGURATION_DEBUG504else {505ObjectFile *objfile = nullptr;506if (module_sp) {507if (SymbolFile *symbol_file = module_sp->GetSymbolFile())508objfile = symbol_file->GetObjectFile();509}510if (objfile) {511Debugger::ReportWarning(llvm::formatv(512"inlined block {0:x} doesn't have a range that contains file "513"address {1:x} in {2}",514curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress(),515objfile->GetFileSpec().GetPath()));516} else {517Debugger::ReportWarning(llvm::formatv(518"inlined block {0:x} doesn't have a range that contains file "519"address {1:x}",520curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()));521}522}523#endif524}525}526}527528return false;529}530531Block *SymbolContext::GetFunctionBlock() {532if (function) {533if (block) {534// If this symbol context has a block, check to see if this block is535// itself, or is contained within a block with inlined function536// information. If so, then the inlined block is the block that defines537// the function.538Block *inlined_block = block->GetContainingInlinedBlock();539if (inlined_block)540return inlined_block;541542// The block in this symbol context is not inside an inlined block, so543// the block that defines the function is the function's top level block,544// which is returned below.545}546547// There is no block information in this symbol context, so we must assume548// that the block that is desired is the top level block of the function549// itself.550return &function->GetBlock(true);551}552return nullptr;553}554555llvm::StringRef SymbolContext::GetInstanceVariableName() {556LanguageType lang_type = eLanguageTypeUnknown;557558if (Block *function_block = GetFunctionBlock())559if (CompilerDeclContext decl_ctx = function_block->GetDeclContext())560lang_type = decl_ctx.GetLanguage();561562if (lang_type == eLanguageTypeUnknown)563lang_type = GetLanguage();564565if (auto *lang = Language::FindPlugin(lang_type))566return lang->GetInstanceVariableName();567568return {};569}570571void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {572Block *curr_block = block;573bool isInlinedblock = false;574if (curr_block != nullptr &&575curr_block->GetContainingInlinedBlock() != nullptr)576isInlinedblock = true;577578// Find all types that match the current block if we have one and put them579// first in the list. Keep iterating up through all blocks.580while (curr_block != nullptr && !isInlinedblock) {581type_map.ForEach(582[curr_block, &type_list](const lldb::TypeSP &type_sp) -> bool {583SymbolContextScope *scs = type_sp->GetSymbolContextScope();584if (scs && curr_block == scs->CalculateSymbolContextBlock())585type_list.Insert(type_sp);586return true; // Keep iterating587});588589// Remove any entries that are now in "type_list" from "type_map" since we590// can't remove from type_map while iterating591type_list.ForEach([&type_map](const lldb::TypeSP &type_sp) -> bool {592type_map.Remove(type_sp);593return true; // Keep iterating594});595curr_block = curr_block->GetParent();596}597// Find all types that match the current function, if we have onem, and put598// them next in the list.599if (function != nullptr && !type_map.Empty()) {600const size_t old_type_list_size = type_list.GetSize();601type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {602SymbolContextScope *scs = type_sp->GetSymbolContextScope();603if (scs && function == scs->CalculateSymbolContextFunction())604type_list.Insert(type_sp);605return true; // Keep iterating606});607608// Remove any entries that are now in "type_list" from "type_map" since we609// can't remove from type_map while iterating610const size_t new_type_list_size = type_list.GetSize();611if (new_type_list_size > old_type_list_size) {612for (size_t i = old_type_list_size; i < new_type_list_size; ++i)613type_map.Remove(type_list.GetTypeAtIndex(i));614}615}616// Find all types that match the current compile unit, if we have one, and617// put them next in the list.618if (comp_unit != nullptr && !type_map.Empty()) {619const size_t old_type_list_size = type_list.GetSize();620621type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {622SymbolContextScope *scs = type_sp->GetSymbolContextScope();623if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit())624type_list.Insert(type_sp);625return true; // Keep iterating626});627628// Remove any entries that are now in "type_list" from "type_map" since we629// can't remove from type_map while iterating630const size_t new_type_list_size = type_list.GetSize();631if (new_type_list_size > old_type_list_size) {632for (size_t i = old_type_list_size; i < new_type_list_size; ++i)633type_map.Remove(type_list.GetTypeAtIndex(i));634}635}636// Find all types that match the current module, if we have one, and put them637// next in the list.638if (module_sp && !type_map.Empty()) {639const size_t old_type_list_size = type_list.GetSize();640type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {641SymbolContextScope *scs = type_sp->GetSymbolContextScope();642if (scs && module_sp == scs->CalculateSymbolContextModule())643type_list.Insert(type_sp);644return true; // Keep iterating645});646// Remove any entries that are now in "type_list" from "type_map" since we647// can't remove from type_map while iterating648const size_t new_type_list_size = type_list.GetSize();649if (new_type_list_size > old_type_list_size) {650for (size_t i = old_type_list_size; i < new_type_list_size; ++i)651type_map.Remove(type_list.GetTypeAtIndex(i));652}653}654// Any types that are left get copied into the list an any order.655if (!type_map.Empty()) {656type_map.ForEach([&type_list](const lldb::TypeSP &type_sp) -> bool {657type_list.Insert(type_sp);658return true; // Keep iterating659});660}661}662663ConstString664SymbolContext::GetFunctionName(Mangled::NamePreference preference) const {665if (function) {666if (block) {667Block *inlined_block = block->GetContainingInlinedBlock();668669if (inlined_block) {670const InlineFunctionInfo *inline_info =671inlined_block->GetInlinedFunctionInfo();672if (inline_info)673return inline_info->GetName();674}675}676return function->GetMangled().GetName(preference);677} else if (symbol && symbol->ValueIsAddress()) {678return symbol->GetMangled().GetName(preference);679} else {680// No function, return an empty string.681return ConstString();682}683}684685LineEntry SymbolContext::GetFunctionStartLineEntry() const {686LineEntry line_entry;687Address start_addr;688if (block) {689Block *inlined_block = block->GetContainingInlinedBlock();690if (inlined_block) {691if (inlined_block->GetStartAddress(start_addr)) {692if (start_addr.CalculateSymbolContextLineEntry(line_entry))693return line_entry;694}695return LineEntry();696}697}698699if (function) {700if (function->GetAddressRange()701.GetBaseAddress()702.CalculateSymbolContextLineEntry(line_entry))703return line_entry;704}705return LineEntry();706}707708bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line,709AddressRange &range,710Status &error) {711if (!line_entry.IsValid()) {712error.SetErrorString("Symbol context has no line table.");713return false;714}715716range = line_entry.range;717if (line_entry.line > end_line) {718error.SetErrorStringWithFormat(719"end line option %d must be after the current line: %d", end_line,720line_entry.line);721return false;722}723724uint32_t line_index = 0;725bool found = false;726while (true) {727LineEntry this_line;728line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr,729false, &this_line);730if (line_index == UINT32_MAX)731break;732if (LineEntry::Compare(this_line, line_entry) == 0) {733found = true;734break;735}736}737738LineEntry end_entry;739if (!found) {740// Can't find the index of the SymbolContext's line entry in the741// SymbolContext's CompUnit.742error.SetErrorString(743"Can't find the current line entry in the CompUnit - can't process "744"the end-line option");745return false;746}747748line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false,749&end_entry);750if (line_index == UINT32_MAX) {751error.SetErrorStringWithFormat(752"could not find a line table entry corresponding "753"to end line number %d",754end_line);755return false;756}757758Block *func_block = GetFunctionBlock();759if (func_block && func_block->GetRangeIndexContainingAddress(760end_entry.range.GetBaseAddress()) == UINT32_MAX) {761error.SetErrorStringWithFormat(762"end line number %d is not contained within the current function.",763end_line);764return false;765}766767lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() -768range.GetBaseAddress().GetFileAddress();769range.SetByteSize(range_size);770return true;771}772773const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name,774Status &error) {775error.Clear();776777if (!target_sp) {778return nullptr;779}780781Target &target = *target_sp;782Module *module = module_sp.get();783784auto ProcessMatches = [this, &name, &target,785module](const SymbolContextList &sc_list,786Status &error) -> const Symbol * {787llvm::SmallVector<const Symbol *, 1> external_symbols;788llvm::SmallVector<const Symbol *, 1> internal_symbols;789for (const SymbolContext &sym_ctx : sc_list) {790if (sym_ctx.symbol) {791const Symbol *symbol = sym_ctx.symbol;792const Address sym_address = symbol->GetAddress();793794if (sym_address.IsValid()) {795switch (symbol->GetType()) {796case eSymbolTypeData:797case eSymbolTypeRuntime:798case eSymbolTypeAbsolute:799case eSymbolTypeObjCClass:800case eSymbolTypeObjCMetaClass:801case eSymbolTypeObjCIVar:802if (symbol->GetDemangledNameIsSynthesized()) {803// If the demangled name was synthesized, then don't use it for804// expressions. Only let the symbol match if the mangled named805// matches for these symbols.806if (symbol->GetMangled().GetMangledName() != name)807break;808}809if (symbol->IsExternal()) {810external_symbols.push_back(symbol);811} else {812internal_symbols.push_back(symbol);813}814break;815case eSymbolTypeReExported: {816ConstString reexport_name = symbol->GetReExportedSymbolName();817if (reexport_name) {818ModuleSP reexport_module_sp;819ModuleSpec reexport_module_spec;820reexport_module_spec.GetPlatformFileSpec() =821symbol->GetReExportedSymbolSharedLibrary();822if (reexport_module_spec.GetPlatformFileSpec()) {823reexport_module_sp =824target.GetImages().FindFirstModule(reexport_module_spec);825if (!reexport_module_sp) {826reexport_module_spec.GetPlatformFileSpec().ClearDirectory();827reexport_module_sp =828target.GetImages().FindFirstModule(reexport_module_spec);829}830}831// Don't allow us to try and resolve a re-exported symbol if it832// is the same as the current symbol833if (name == symbol->GetReExportedSymbolName() &&834module == reexport_module_sp.get())835return nullptr;836837return FindBestGlobalDataSymbol(symbol->GetReExportedSymbolName(),838error);839}840} break;841842case eSymbolTypeCode: // We already lookup functions elsewhere843case eSymbolTypeVariable:844case eSymbolTypeLocal:845case eSymbolTypeParam:846case eSymbolTypeTrampoline:847case eSymbolTypeInvalid:848case eSymbolTypeException:849case eSymbolTypeSourceFile:850case eSymbolTypeHeaderFile:851case eSymbolTypeObjectFile:852case eSymbolTypeCommonBlock:853case eSymbolTypeBlock:854case eSymbolTypeVariableType:855case eSymbolTypeLineEntry:856case eSymbolTypeLineHeader:857case eSymbolTypeScopeBegin:858case eSymbolTypeScopeEnd:859case eSymbolTypeAdditional:860case eSymbolTypeCompiler:861case eSymbolTypeInstrumentation:862case eSymbolTypeUndefined:863case eSymbolTypeResolver:864break;865}866}867}868}869870if (external_symbols.size() > 1) {871StreamString ss;872ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString());873for (const Symbol *symbol : external_symbols) {874symbol->GetDescription(&ss, eDescriptionLevelFull, &target);875}876ss.PutChar('\n');877error.SetErrorString(ss.GetData());878return nullptr;879} else if (external_symbols.size()) {880return external_symbols[0];881} else if (internal_symbols.size() > 1) {882StreamString ss;883ss.Printf("Multiple internal symbols found for '%s'\n", name.AsCString());884for (const Symbol *symbol : internal_symbols) {885symbol->GetDescription(&ss, eDescriptionLevelVerbose, &target);886ss.PutChar('\n');887}888error.SetErrorString(ss.GetData());889return nullptr;890} else if (internal_symbols.size()) {891return internal_symbols[0];892} else {893return nullptr;894}895};896897if (module) {898SymbolContextList sc_list;899module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);900const Symbol *const module_symbol = ProcessMatches(sc_list, error);901902if (!error.Success()) {903return nullptr;904} else if (module_symbol) {905return module_symbol;906}907}908909{910SymbolContextList sc_list;911target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,912sc_list);913const Symbol *const target_symbol = ProcessMatches(sc_list, error);914915if (!error.Success()) {916return nullptr;917} else if (target_symbol) {918return target_symbol;919}920}921922return nullptr; // no error; we just didn't find anything923}924925//926// SymbolContextSpecifier927//928929SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp)930: m_target_sp(target_sp), m_module_spec(), m_module_sp(), m_file_spec_up(),931m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),932m_address_range_up(), m_type(eNothingSpecified) {}933934SymbolContextSpecifier::~SymbolContextSpecifier() = default;935936bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no,937SpecificationType type) {938bool return_value = true;939switch (type) {940case eNothingSpecified:941Clear();942break;943case eLineStartSpecified:944m_start_line = line_no;945m_type |= eLineStartSpecified;946break;947case eLineEndSpecified:948m_end_line = line_no;949m_type |= eLineEndSpecified;950break;951default:952return_value = false;953break;954}955return return_value;956}957958bool SymbolContextSpecifier::AddSpecification(const char *spec_string,959SpecificationType type) {960bool return_value = true;961switch (type) {962case eNothingSpecified:963Clear();964break;965case eModuleSpecified: {966// See if we can find the Module, if so stick it in the SymbolContext.967FileSpec module_file_spec(spec_string);968ModuleSpec module_spec(module_file_spec);969lldb::ModuleSP module_sp =970m_target_sp ? m_target_sp->GetImages().FindFirstModule(module_spec)971: nullptr;972m_type |= eModuleSpecified;973if (module_sp)974m_module_sp = module_sp;975else976m_module_spec.assign(spec_string);977} break;978case eFileSpecified:979// CompUnits can't necessarily be resolved here, since an inlined function980// might show up in a number of CompUnits. Instead we just convert to a981// FileSpec and store it away.982m_file_spec_up = std::make_unique<FileSpec>(spec_string);983m_type |= eFileSpecified;984break;985case eLineStartSpecified:986if ((return_value = llvm::to_integer(spec_string, m_start_line)))987m_type |= eLineStartSpecified;988break;989case eLineEndSpecified:990if ((return_value = llvm::to_integer(spec_string, m_end_line)))991m_type |= eLineEndSpecified;992break;993case eFunctionSpecified:994m_function_spec.assign(spec_string);995m_type |= eFunctionSpecified;996break;997case eClassOrNamespaceSpecified:998Clear();999m_class_name.assign(spec_string);1000m_type = eClassOrNamespaceSpecified;1001break;1002case eAddressRangeSpecified:1003// Not specified yet...1004break;1005}10061007return return_value;1008}10091010void SymbolContextSpecifier::Clear() {1011m_module_spec.clear();1012m_file_spec_up.reset();1013m_function_spec.clear();1014m_class_name.clear();1015m_start_line = 0;1016m_end_line = 0;1017m_address_range_up.reset();10181019m_type = eNothingSpecified;1020}10211022bool SymbolContextSpecifier::SymbolContextMatches(const SymbolContext &sc) {1023if (m_type == eNothingSpecified)1024return true;10251026// Only compare targets if this specifier has one and it's not the Dummy1027// target. Otherwise if a specifier gets made in the dummy target and1028// copied over we'll artificially fail the comparision.1029if (m_target_sp && !m_target_sp->IsDummyTarget() &&1030m_target_sp != sc.target_sp)1031return false;10321033if (m_type & eModuleSpecified) {1034if (sc.module_sp) {1035if (m_module_sp.get() != nullptr) {1036if (m_module_sp.get() != sc.module_sp.get())1037return false;1038} else {1039FileSpec module_file_spec(m_module_spec);1040if (!FileSpec::Match(module_file_spec, sc.module_sp->GetFileSpec()))1041return false;1042}1043}1044}1045if (m_type & eFileSpecified) {1046if (m_file_spec_up) {1047// If we don't have a block or a comp_unit, then we aren't going to match1048// a source file.1049if (sc.block == nullptr && sc.comp_unit == nullptr)1050return false;10511052// Check if the block is present, and if so is it inlined:1053bool was_inlined = false;1054if (sc.block != nullptr) {1055const InlineFunctionInfo *inline_info =1056sc.block->GetInlinedFunctionInfo();1057if (inline_info != nullptr) {1058was_inlined = true;1059if (!FileSpec::Match(*m_file_spec_up,1060inline_info->GetDeclaration().GetFile()))1061return false;1062}1063}10641065// Next check the comp unit, but only if the SymbolContext was not1066// inlined.1067if (!was_inlined && sc.comp_unit != nullptr) {1068if (!FileSpec::Match(*m_file_spec_up, sc.comp_unit->GetPrimaryFile()))1069return false;1070}1071}1072}1073if (m_type & eLineStartSpecified || m_type & eLineEndSpecified) {1074if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)1075return false;1076}10771078if (m_type & eFunctionSpecified) {1079// First check the current block, and if it is inlined, get the inlined1080// function name:1081bool was_inlined = false;1082ConstString func_name(m_function_spec.c_str());10831084if (sc.block != nullptr) {1085const InlineFunctionInfo *inline_info =1086sc.block->GetInlinedFunctionInfo();1087if (inline_info != nullptr) {1088was_inlined = true;1089const Mangled &name = inline_info->GetMangled();1090if (!name.NameMatches(func_name))1091return false;1092}1093}1094// If it wasn't inlined, check the name in the function or symbol:1095if (!was_inlined) {1096if (sc.function != nullptr) {1097if (!sc.function->GetMangled().NameMatches(func_name))1098return false;1099} else if (sc.symbol != nullptr) {1100if (!sc.symbol->GetMangled().NameMatches(func_name))1101return false;1102}1103}1104}11051106return true;1107}11081109bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) {1110if (m_type & eAddressRangeSpecified) {11111112} else {1113Address match_address(addr, nullptr);1114SymbolContext sc;1115m_target_sp->GetImages().ResolveSymbolContextForAddress(1116match_address, eSymbolContextEverything, sc);1117return SymbolContextMatches(sc);1118}1119return true;1120}11211122void SymbolContextSpecifier::GetDescription(1123Stream *s, lldb::DescriptionLevel level) const {1124char path_str[PATH_MAX + 1];11251126if (m_type == eNothingSpecified) {1127s->Printf("Nothing specified.\n");1128}11291130if (m_type == eModuleSpecified) {1131s->Indent();1132if (m_module_sp) {1133m_module_sp->GetFileSpec().GetPath(path_str, PATH_MAX);1134s->Printf("Module: %s\n", path_str);1135} else1136s->Printf("Module: %s\n", m_module_spec.c_str());1137}11381139if (m_type == eFileSpecified && m_file_spec_up != nullptr) {1140m_file_spec_up->GetPath(path_str, PATH_MAX);1141s->Indent();1142s->Printf("File: %s", path_str);1143if (m_type == eLineStartSpecified) {1144s->Printf(" from line %" PRIu64 "", (uint64_t)m_start_line);1145if (m_type == eLineEndSpecified)1146s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);1147else1148s->Printf("to end");1149} else if (m_type == eLineEndSpecified) {1150s->Printf(" from start to line %" PRIu64 "", (uint64_t)m_end_line);1151}1152s->Printf(".\n");1153}11541155if (m_type == eLineStartSpecified) {1156s->Indent();1157s->Printf("From line %" PRIu64 "", (uint64_t)m_start_line);1158if (m_type == eLineEndSpecified)1159s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);1160else1161s->Printf("to end");1162s->Printf(".\n");1163} else if (m_type == eLineEndSpecified) {1164s->Printf("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);1165}11661167if (m_type == eFunctionSpecified) {1168s->Indent();1169s->Printf("Function: %s.\n", m_function_spec.c_str());1170}11711172if (m_type == eClassOrNamespaceSpecified) {1173s->Indent();1174s->Printf("Class name: %s.\n", m_class_name.c_str());1175}11761177if (m_type == eAddressRangeSpecified && m_address_range_up != nullptr) {1178s->Indent();1179s->PutCString("Address range: ");1180m_address_range_up->Dump(s, m_target_sp.get(),1181Address::DumpStyleLoadAddress,1182Address::DumpStyleFileAddress);1183s->PutCString("\n");1184}1185}11861187//1188// SymbolContextList1189//11901191SymbolContextList::SymbolContextList() : m_symbol_contexts() {}11921193SymbolContextList::~SymbolContextList() = default;11941195void SymbolContextList::Append(const SymbolContext &sc) {1196m_symbol_contexts.push_back(sc);1197}11981199void SymbolContextList::Append(const SymbolContextList &sc_list) {1200collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();1201for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)1202m_symbol_contexts.push_back(*pos);1203}12041205uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList &sc_list,1206bool merge_symbol_into_function) {1207uint32_t unique_sc_add_count = 0;1208collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();1209for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) {1210if (AppendIfUnique(*pos, merge_symbol_into_function))1211++unique_sc_add_count;1212}1213return unique_sc_add_count;1214}12151216bool SymbolContextList::AppendIfUnique(const SymbolContext &sc,1217bool merge_symbol_into_function) {1218collection::iterator pos, end = m_symbol_contexts.end();1219for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {1220if (*pos == sc)1221return false;1222}1223if (merge_symbol_into_function && sc.symbol != nullptr &&1224sc.comp_unit == nullptr && sc.function == nullptr &&1225sc.block == nullptr && !sc.line_entry.IsValid()) {1226if (sc.symbol->ValueIsAddress()) {1227for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {1228// Don't merge symbols into inlined function symbol contexts1229if (pos->block && pos->block->GetContainingInlinedBlock())1230continue;12311232if (pos->function) {1233if (pos->function->GetAddressRange().GetBaseAddress() ==1234sc.symbol->GetAddressRef()) {1235// Do we already have a function with this symbol?1236if (pos->symbol == sc.symbol)1237return false;1238if (pos->symbol == nullptr) {1239pos->symbol = sc.symbol;1240return false;1241}1242}1243}1244}1245}1246}1247m_symbol_contexts.push_back(sc);1248return true;1249}12501251void SymbolContextList::Clear() { m_symbol_contexts.clear(); }12521253void SymbolContextList::Dump(Stream *s, Target *target) const {12541255*s << this << ": ";1256s->Indent();1257s->PutCString("SymbolContextList");1258s->EOL();1259s->IndentMore();12601261collection::const_iterator pos, end = m_symbol_contexts.end();1262for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {1263// pos->Dump(s, target);1264pos->GetDescription(s, eDescriptionLevelVerbose, target);1265}1266s->IndentLess();1267}12681269bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const {1270if (idx < m_symbol_contexts.size()) {1271sc = m_symbol_contexts[idx];1272return true;1273}1274return false;1275}12761277bool SymbolContextList::RemoveContextAtIndex(size_t idx) {1278if (idx < m_symbol_contexts.size()) {1279m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);1280return true;1281}1282return false;1283}12841285uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); }12861287bool SymbolContextList::IsEmpty() const { return m_symbol_contexts.empty(); }12881289uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const {1290uint32_t match_count = 0;1291const size_t size = m_symbol_contexts.size();1292for (size_t idx = 0; idx < size; ++idx) {1293if (m_symbol_contexts[idx].line_entry.line == line)1294++match_count;1295}1296return match_count;1297}12981299void SymbolContextList::GetDescription(Stream *s, lldb::DescriptionLevel level,1300Target *target) const {1301const size_t size = m_symbol_contexts.size();1302for (size_t idx = 0; idx < size; ++idx)1303m_symbol_contexts[idx].GetDescription(s, level, target);1304}13051306bool lldb_private::operator==(const SymbolContextList &lhs,1307const SymbolContextList &rhs) {1308const uint32_t size = lhs.GetSize();1309if (size != rhs.GetSize())1310return false;13111312SymbolContext lhs_sc;1313SymbolContext rhs_sc;1314for (uint32_t i = 0; i < size; ++i) {1315lhs.GetContextAtIndex(i, lhs_sc);1316rhs.GetContextAtIndex(i, rhs_sc);1317if (lhs_sc != rhs_sc)1318return false;1319}1320return true;1321}13221323bool lldb_private::operator!=(const SymbolContextList &lhs,1324const SymbolContextList &rhs) {1325return !(lhs == rhs);1326}132713281329