Path: blob/main/contrib/llvm-project/lldb/source/Symbol/Block.cpp
39587 views
//===-- Block.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/Block.h"910#include "lldb/Core/Module.h"11#include "lldb/Core/Section.h"12#include "lldb/Symbol/Function.h"13#include "lldb/Symbol/SymbolFile.h"14#include "lldb/Symbol/VariableList.h"15#include "lldb/Utility/LLDBLog.h"16#include "lldb/Utility/Log.h"1718#include <memory>1920using namespace lldb;21using namespace lldb_private;2223Block::Block(lldb::user_id_t uid)24: UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),25m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),26m_parsed_block_variables(false), m_parsed_child_blocks(false) {}2728Block::~Block() = default;2930void Block::GetDescription(Stream *s, Function *function,31lldb::DescriptionLevel level, Target *target) const {32*s << "id = " << ((const UserID &)*this);3334size_t num_ranges = m_ranges.GetSize();35if (num_ranges > 0) {3637addr_t base_addr = LLDB_INVALID_ADDRESS;38if (target)39base_addr =40function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);41if (base_addr == LLDB_INVALID_ADDRESS)42base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();4344s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");45for (size_t i = 0; i < num_ranges; ++i) {46const Range &range = m_ranges.GetEntryRef(i);47DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),48base_addr + range.GetRangeEnd(), 4);49}50}5152if (m_inlineInfoSP.get() != nullptr) {53bool show_fullpaths = (level == eDescriptionLevelVerbose);54m_inlineInfoSP->Dump(s, show_fullpaths);55}56}5758void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,59bool show_context) const {60if (depth < 0) {61Block *parent = GetParent();62if (parent) {63// We have a depth that is less than zero, print our parent blocks first64parent->Dump(s, base_addr, depth + 1, show_context);65}66}6768s->Printf("%p: ", static_cast<const void *>(this));69s->Indent();70*s << "Block" << static_cast<const UserID &>(*this);71const Block *parent_block = GetParent();72if (parent_block) {73s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());74}75if (m_inlineInfoSP.get() != nullptr) {76bool show_fullpaths = false;77m_inlineInfoSP->Dump(s, show_fullpaths);78}7980if (!m_ranges.IsEmpty()) {81*s << ", ranges =";8283size_t num_ranges = m_ranges.GetSize();84for (size_t i = 0; i < num_ranges; ++i) {85const Range &range = m_ranges.GetEntryRef(i);86if (parent_block != nullptr && !parent_block->Contains(range))87*s << '!';88else89*s << ' ';90DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),91base_addr + range.GetRangeEnd(), 4);92}93}94s->EOL();9596if (depth > 0) {97s->IndentMore();9899if (m_variable_list_sp.get()) {100m_variable_list_sp->Dump(s, show_context);101}102103collection::const_iterator pos, end = m_children.end();104for (pos = m_children.begin(); pos != end; ++pos)105(*pos)->Dump(s, base_addr, depth - 1, show_context);106107s->IndentLess();108}109}110111Block *Block::FindBlockByID(user_id_t block_id) {112if (block_id == GetID())113return this;114115Block *matching_block = nullptr;116collection::const_iterator pos, end = m_children.end();117for (pos = m_children.begin(); pos != end; ++pos) {118matching_block = (*pos)->FindBlockByID(block_id);119if (matching_block)120break;121}122return matching_block;123}124125Block *Block::FindInnermostBlockByOffset(const lldb::addr_t offset) {126if (!Contains(offset))127return nullptr;128for (const BlockSP &block_sp : m_children) {129if (Block *block = block_sp->FindInnermostBlockByOffset(offset))130return block;131}132return this;133}134135void Block::CalculateSymbolContext(SymbolContext *sc) {136if (m_parent_scope)137m_parent_scope->CalculateSymbolContext(sc);138sc->block = this;139}140141lldb::ModuleSP Block::CalculateSymbolContextModule() {142if (m_parent_scope)143return m_parent_scope->CalculateSymbolContextModule();144return lldb::ModuleSP();145}146147CompileUnit *Block::CalculateSymbolContextCompileUnit() {148if (m_parent_scope)149return m_parent_scope->CalculateSymbolContextCompileUnit();150return nullptr;151}152153Function *Block::CalculateSymbolContextFunction() {154if (m_parent_scope)155return m_parent_scope->CalculateSymbolContextFunction();156return nullptr;157}158159Block *Block::CalculateSymbolContextBlock() { return this; }160161void Block::DumpSymbolContext(Stream *s) {162Function *function = CalculateSymbolContextFunction();163if (function)164function->DumpSymbolContext(s);165s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());166}167168void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {169if (!m_ranges.IsEmpty()) {170size_t num_ranges = m_ranges.GetSize();171for (size_t i = 0; i < num_ranges; ++i) {172const Range &range = m_ranges.GetEntryRef(i);173DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),174base_addr + range.GetRangeEnd(), 4);175}176}177}178179bool Block::Contains(addr_t range_offset) const {180return m_ranges.FindEntryThatContains(range_offset) != nullptr;181}182183bool Block::Contains(const Block *block) const {184if (this == block)185return false; // This block doesn't contain itself...186187// Walk the parent chain for "block" and see if any if them match this block188const Block *block_parent;189for (block_parent = block->GetParent(); block_parent != nullptr;190block_parent = block_parent->GetParent()) {191if (this == block_parent)192return true; // One of the parents of "block" is this object!193}194return false;195}196197bool Block::Contains(const Range &range) const {198return m_ranges.FindEntryThatContains(range) != nullptr;199}200201Block *Block::GetParent() const {202if (m_parent_scope)203return m_parent_scope->CalculateSymbolContextBlock();204return nullptr;205}206207Block *Block::GetContainingInlinedBlock() {208if (GetInlinedFunctionInfo())209return this;210return GetInlinedParent();211}212213Block *Block::GetInlinedParent() {214Block *parent_block = GetParent();215if (parent_block) {216if (parent_block->GetInlinedFunctionInfo())217return parent_block;218else219return parent_block->GetInlinedParent();220}221return nullptr;222}223224Block *Block::GetContainingInlinedBlockWithCallSite(225const Declaration &find_call_site) {226Block *inlined_block = GetContainingInlinedBlock();227228while (inlined_block) {229const auto *function_info = inlined_block->GetInlinedFunctionInfo();230231if (function_info &&232function_info->GetCallSite().FileAndLineEqual(find_call_site))233return inlined_block;234inlined_block = inlined_block->GetInlinedParent();235}236return nullptr;237}238239bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {240const Range *range_ptr = m_ranges.FindEntryThatContains(offset);241if (range_ptr) {242range = *range_ptr;243return true;244}245range.Clear();246return false;247}248249bool Block::GetRangeContainingAddress(const Address &addr,250AddressRange &range) {251Function *function = CalculateSymbolContextFunction();252if (function) {253const AddressRange &func_range = function->GetAddressRange();254if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {255const addr_t addr_offset = addr.GetOffset();256const addr_t func_offset = func_range.GetBaseAddress().GetOffset();257if (addr_offset >= func_offset &&258addr_offset < func_offset + func_range.GetByteSize()) {259addr_t offset = addr_offset - func_offset;260261const Range *range_ptr = m_ranges.FindEntryThatContains(offset);262263if (range_ptr) {264range.GetBaseAddress() = func_range.GetBaseAddress();265range.GetBaseAddress().SetOffset(func_offset +266range_ptr->GetRangeBase());267range.SetByteSize(range_ptr->GetByteSize());268return true;269}270}271}272}273range.Clear();274return false;275}276277bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,278Target &target, AddressRange &range) {279Address load_address;280load_address.SetLoadAddress(load_addr, &target);281AddressRange containing_range;282return GetRangeContainingAddress(load_address, containing_range);283}284285uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {286Function *function = CalculateSymbolContextFunction();287if (function) {288const AddressRange &func_range = function->GetAddressRange();289if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {290const addr_t addr_offset = addr.GetOffset();291const addr_t func_offset = func_range.GetBaseAddress().GetOffset();292if (addr_offset >= func_offset &&293addr_offset < func_offset + func_range.GetByteSize()) {294addr_t offset = addr_offset - func_offset;295return m_ranges.FindEntryIndexThatContains(offset);296}297}298}299return UINT32_MAX;300}301302bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {303if (range_idx < m_ranges.GetSize()) {304Function *function = CalculateSymbolContextFunction();305if (function) {306const Range &vm_range = m_ranges.GetEntryRef(range_idx);307range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();308range.GetBaseAddress().Slide(vm_range.GetRangeBase());309range.SetByteSize(vm_range.GetByteSize());310return true;311}312}313return false;314}315316AddressRanges Block::GetRanges() {317AddressRanges ranges;318Function *function = CalculateSymbolContextFunction();319if (!function)320return ranges;321for (size_t i = 0, e = m_ranges.GetSize(); i < e; ++i) {322ranges.emplace_back();323auto &range = ranges.back();324const Range &vm_range = m_ranges.GetEntryRef(i);325range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();326range.GetBaseAddress().Slide(vm_range.GetRangeBase());327range.SetByteSize(vm_range.GetByteSize());328}329return ranges;330}331332bool Block::GetStartAddress(Address &addr) {333if (m_ranges.IsEmpty())334return false;335336Function *function = CalculateSymbolContextFunction();337if (function) {338addr = function->GetAddressRange().GetBaseAddress();339addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());340return true;341}342return false;343}344345void Block::FinalizeRanges() {346m_ranges.Sort();347m_ranges.CombineConsecutiveRanges();348}349350void Block::AddRange(const Range &range) {351Block *parent_block = GetParent();352if (parent_block && !parent_block->Contains(range)) {353Log *log = GetLog(LLDBLog::Symbols);354if (log) {355ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());356Function *function = m_parent_scope->CalculateSymbolContextFunction();357const addr_t function_file_addr =358function->GetAddressRange().GetBaseAddress().GetFileAddress();359const addr_t block_start_addr = function_file_addr + range.GetRangeBase();360const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();361Type *func_type = function->GetType();362363const Declaration &func_decl = func_type->GetDeclaration();364if (func_decl.GetLine()) {365LLDB_LOGF(log,366"warning: %s:%u block {0x%8.8" PRIx64367"} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64368") which is not contained in parent block {0x%8.8" PRIx64369"} in function {0x%8.8" PRIx64 "} from %s",370func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),371GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,372block_end_addr, parent_block->GetID(), function->GetID(),373module_sp->GetFileSpec().GetPath().c_str());374} else {375LLDB_LOGF(log,376"warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64377" - 0x%" PRIx64378") which is not contained in parent block {0x%8.8" PRIx64379"} in function {0x%8.8" PRIx64 "} from %s",380GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,381block_end_addr, parent_block->GetID(), function->GetID(),382module_sp->GetFileSpec().GetPath().c_str());383}384}385parent_block->AddRange(range);386}387m_ranges.Append(range);388}389390// Return the current number of bytes that this object occupies in memory391size_t Block::MemorySize() const {392size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);393if (m_inlineInfoSP.get())394mem_size += m_inlineInfoSP->MemorySize();395if (m_variable_list_sp.get())396mem_size += m_variable_list_sp->MemorySize();397return mem_size;398}399400void Block::AddChild(const BlockSP &child_block_sp) {401if (child_block_sp) {402child_block_sp->SetParentScope(this);403m_children.push_back(child_block_sp);404}405}406407void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,408const Declaration *decl_ptr,409const Declaration *call_decl_ptr) {410m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,411call_decl_ptr);412}413414VariableListSP Block::GetBlockVariableList(bool can_create) {415if (!m_parsed_block_variables) {416if (m_variable_list_sp.get() == nullptr && can_create) {417m_parsed_block_variables = true;418SymbolContext sc;419CalculateSymbolContext(&sc);420assert(sc.module_sp);421sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);422}423}424return m_variable_list_sp;425}426427uint32_t428Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,429bool stop_if_child_block_is_inlined_function,430const std::function<bool(Variable *)> &filter,431VariableList *variable_list) {432uint32_t num_variables_added = 0;433VariableList *block_var_list = GetBlockVariableList(can_create).get();434if (block_var_list) {435for (const VariableSP &var_sp : *block_var_list) {436if (filter(var_sp.get())) {437num_variables_added++;438variable_list->AddVariable(var_sp);439}440}441}442443if (get_child_block_variables) {444collection::const_iterator pos, end = m_children.end();445for (pos = m_children.begin(); pos != end; ++pos) {446Block *child_block = pos->get();447if (!stop_if_child_block_is_inlined_function ||448child_block->GetInlinedFunctionInfo() == nullptr) {449num_variables_added += child_block->AppendBlockVariables(450can_create, get_child_block_variables,451stop_if_child_block_is_inlined_function, filter, variable_list);452}453}454}455return num_variables_added;456}457458uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,459bool stop_if_block_is_inlined_function,460const std::function<bool(Variable *)> &filter,461VariableList *variable_list) {462uint32_t num_variables_added = 0;463VariableListSP variable_list_sp(GetBlockVariableList(can_create));464465bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;466if (variable_list_sp) {467for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {468VariableSP variable = variable_list_sp->GetVariableAtIndex(i);469if (filter(variable.get())) {470num_variables_added++;471variable_list->AddVariable(variable);472}473}474}475476if (get_parent_variables) {477if (stop_if_block_is_inlined_function && is_inlined_function)478return num_variables_added;479480Block *parent_block = GetParent();481if (parent_block)482num_variables_added += parent_block->AppendVariables(483can_create, get_parent_variables, stop_if_block_is_inlined_function,484filter, variable_list);485}486return num_variables_added;487}488489SymbolFile *Block::GetSymbolFile() {490if (ModuleSP module_sp = CalculateSymbolContextModule())491return module_sp->GetSymbolFile();492return nullptr;493}494495CompilerDeclContext Block::GetDeclContext() {496if (SymbolFile *sym_file = GetSymbolFile())497return sym_file->GetDeclContextForUID(GetID());498return CompilerDeclContext();499}500501void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {502m_parsed_block_info = b;503if (set_children) {504m_parsed_child_blocks = true;505collection::const_iterator pos, end = m_children.end();506for (pos = m_children.begin(); pos != end; ++pos)507(*pos)->SetBlockInfoHasBeenParsed(b, true);508}509}510511void Block::SetDidParseVariables(bool b, bool set_children) {512m_parsed_block_variables = b;513if (set_children) {514collection::const_iterator pos, end = m_children.end();515for (pos = m_children.begin(); pos != end; ++pos)516(*pos)->SetDidParseVariables(b, true);517}518}519520Block *Block::GetSibling() const {521if (m_parent_scope) {522Block *parent_block = GetParent();523if (parent_block)524return parent_block->GetSiblingForChild(this);525}526return nullptr;527}528// A parent of child blocks can be asked to find a sibling block given529// one of its child blocks530Block *Block::GetSiblingForChild(const Block *child_block) const {531if (!m_children.empty()) {532collection::const_iterator pos, end = m_children.end();533for (pos = m_children.begin(); pos != end; ++pos) {534if (pos->get() == child_block) {535if (++pos != end)536return pos->get();537break;538}539}540}541return nullptr;542}543544545