brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.6 KiB · 3de3e5e Raw
519 lines · cpp
1//===-- Block.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/Block.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Core/Section.h"13#include "lldb/Symbol/Function.h"14#include "lldb/Symbol/SymbolFile.h"15#include "lldb/Symbol/VariableList.h"16#include "lldb/Utility/LLDBLog.h"17#include "lldb/Utility/Log.h"18 19#include <memory>20 21using namespace lldb;22using namespace lldb_private;23 24Block::Block(Function &function, user_id_t function_uid)25    : Block(function_uid, function) {}26 27Block::Block(lldb::user_id_t uid, SymbolContextScope &parent_scope)28    : UserID(uid), m_parent_scope(parent_scope), m_parsed_block_info(false),29      m_parsed_block_variables(false), m_parsed_child_blocks(false) {}30 31Block::~Block() = default;32 33void Block::GetDescription(Stream *s, Function *function,34                           lldb::DescriptionLevel level, Target *target) const {35  *s << "id = " << ((const UserID &)*this);36 37  size_t num_ranges = m_ranges.GetSize();38  if (num_ranges > 0) {39 40    addr_t base_addr = LLDB_INVALID_ADDRESS;41    if (target)42      base_addr = function->GetAddress().GetLoadAddress(target);43    if (base_addr == LLDB_INVALID_ADDRESS)44      base_addr = function->GetAddress().GetFileAddress();45 46    s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");47    for (size_t i = 0; i < num_ranges; ++i) {48      const Range &range = m_ranges.GetEntryRef(i);49      DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),50                       base_addr + range.GetRangeEnd(), 4);51    }52  }53 54  if (m_inlineInfoSP.get() != nullptr) {55    bool show_fullpaths = (level == eDescriptionLevelVerbose);56    m_inlineInfoSP->Dump(s, show_fullpaths);57  }58}59 60void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,61                 bool show_context) const {62  if (depth < 0) {63    Block *parent = GetParent();64    if (parent) {65      // We have a depth that is less than zero, print our parent blocks first66      parent->Dump(s, base_addr, depth + 1, show_context);67    }68  }69 70  s->Printf("%p: ", static_cast<const void *>(this));71  s->Indent();72  *s << "Block" << static_cast<const UserID &>(*this);73  const Block *parent_block = GetParent();74  if (parent_block) {75    s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());76  }77  if (m_inlineInfoSP.get() != nullptr) {78    bool show_fullpaths = false;79    m_inlineInfoSP->Dump(s, show_fullpaths);80  }81 82  if (!m_ranges.IsEmpty()) {83    *s << ", ranges =";84 85    size_t num_ranges = m_ranges.GetSize();86    for (size_t i = 0; i < num_ranges; ++i) {87      const Range &range = m_ranges.GetEntryRef(i);88      if (parent_block != nullptr && !parent_block->Contains(range))89        *s << '!';90      else91        *s << ' ';92      DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),93                       base_addr + range.GetRangeEnd(), 4);94    }95  }96  s->EOL();97 98  if (depth > 0) {99    s->IndentMore();100 101    if (m_variable_list_sp.get()) {102      m_variable_list_sp->Dump(s, show_context);103    }104 105    collection::const_iterator pos, end = m_children.end();106    for (pos = m_children.begin(); pos != end; ++pos)107      (*pos)->Dump(s, base_addr, depth - 1, show_context);108 109    s->IndentLess();110  }111}112 113Block *Block::FindBlockByID(user_id_t block_id) {114  if (block_id == GetID())115    return this;116 117  Block *matching_block = nullptr;118  collection::const_iterator pos, end = m_children.end();119  for (pos = m_children.begin(); pos != end; ++pos) {120    matching_block = (*pos)->FindBlockByID(block_id);121    if (matching_block)122      break;123  }124  return matching_block;125}126 127Block *Block::FindInnermostBlockByOffset(const lldb::addr_t offset) {128  if (!Contains(offset))129    return nullptr;130  for (const BlockSP &block_sp : m_children) {131    if (Block *block = block_sp->FindInnermostBlockByOffset(offset))132      return block;133  }134  return this;135}136 137void Block::CalculateSymbolContext(SymbolContext *sc) {138  m_parent_scope.CalculateSymbolContext(sc);139  sc->block = this;140}141 142lldb::ModuleSP Block::CalculateSymbolContextModule() {143  return m_parent_scope.CalculateSymbolContextModule();144}145 146CompileUnit *Block::CalculateSymbolContextCompileUnit() {147  return m_parent_scope.CalculateSymbolContextCompileUnit();148}149 150Function *Block::CalculateSymbolContextFunction() {151  return m_parent_scope.CalculateSymbolContextFunction();152}153 154Block *Block::CalculateSymbolContextBlock() { return this; }155 156Function &Block::GetFunction() {157  // Blocks always have an enclosing function because their parent is either a158  // function or a block (which has a parent, inductively).159  Function *function = CalculateSymbolContextFunction();160  assert(function);161  return *function;162}163 164void Block::DumpSymbolContext(Stream *s) {165  GetFunction().DumpSymbolContext(s);166  s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());167}168 169void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {170  if (!m_ranges.IsEmpty()) {171    size_t num_ranges = m_ranges.GetSize();172    for (size_t i = 0; i < num_ranges; ++i) {173      const Range &range = m_ranges.GetEntryRef(i);174      DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),175                       base_addr + range.GetRangeEnd(), 4);176    }177  }178}179 180bool Block::Contains(addr_t range_offset) const {181  return m_ranges.FindEntryThatContains(range_offset) != nullptr;182}183 184bool Block::Contains(const Block *block) const {185  if (this == block)186    return false; // This block doesn't contain itself...187 188  // Walk the parent chain for "block" and see if any if them match this block189  const Block *block_parent;190  for (block_parent = block->GetParent(); block_parent != nullptr;191       block_parent = block_parent->GetParent()) {192    if (this == block_parent)193      return true; // One of the parents of "block" is this object!194  }195  return false;196}197 198bool Block::Contains(const Range &range) const {199  return m_ranges.FindEntryThatContains(range) != nullptr;200}201 202Block *Block::GetParent() const {203  return m_parent_scope.CalculateSymbolContextBlock();204}205 206Block *Block::GetContainingInlinedBlock() {207  if (GetInlinedFunctionInfo())208    return this;209  return GetInlinedParent();210}211 212Block *Block::GetInlinedParent() {213  Block *parent_block = GetParent();214  if (parent_block) {215    if (parent_block->GetInlinedFunctionInfo())216      return parent_block;217    else218      return parent_block->GetInlinedParent();219  }220  return nullptr;221}222 223Block *Block::GetContainingInlinedBlockWithCallSite(224    const Declaration &find_call_site) {225  Block *inlined_block = GetContainingInlinedBlock();226 227  while (inlined_block) {228    const auto *function_info = inlined_block->GetInlinedFunctionInfo();229 230    if (function_info &&231        function_info->GetCallSite().FileAndLineEqual(find_call_site, true))232      return inlined_block;233    inlined_block = inlined_block->GetInlinedParent();234  }235  return nullptr;236}237 238bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {239  const Range *range_ptr = m_ranges.FindEntryThatContains(offset);240  if (range_ptr) {241    range = *range_ptr;242    return true;243  }244  range.Clear();245  return false;246}247 248bool Block::GetRangeContainingAddress(const Address &addr,249                                      AddressRange &range) {250  Function &function = GetFunction();251  if (uint32_t idx = GetRangeIndexContainingAddress(addr); idx != UINT32_MAX) {252    const Range *range_ptr = m_ranges.GetEntryAtIndex(idx);253    assert(range_ptr);254 255    Address func_addr = function.GetAddress();256    range.GetBaseAddress() =257        Address(func_addr.GetFileAddress() + range_ptr->GetRangeBase(),258                func_addr.GetModule()->GetSectionList());259    range.SetByteSize(range_ptr->GetByteSize());260    return true;261  }262  range.Clear();263  return false;264}265 266bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,267                                          Target &target, AddressRange &range) {268  Address load_address;269  load_address.SetLoadAddress(load_addr, &target);270  AddressRange containing_range;271  return GetRangeContainingAddress(load_address, containing_range);272}273 274uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {275  Function &function = GetFunction();276 277  const Address &func_addr = function.GetAddress();278  if (addr.GetModule() != func_addr.GetModule())279    return UINT32_MAX;280 281  const addr_t file_addr = addr.GetFileAddress();282  const addr_t func_file_addr = func_addr.GetFileAddress();283  return m_ranges.FindEntryIndexThatContains(file_addr - func_file_addr);284}285 286static AddressRange ToAddressRange(const Address &func_addr,287                                   const Block::Range &block_range) {288  assert(func_addr.GetModule());289  return AddressRange(func_addr.GetFileAddress() + block_range.base,290                      block_range.size,291                      func_addr.GetModule()->GetSectionList());292}293 294bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {295  if (range_idx >= m_ranges.GetSize())296    return false;297 298  Address addr = GetFunction().GetAddress();299  if (!addr.GetModule())300    return false;301 302  range = ToAddressRange(addr, m_ranges.GetEntryRef(range_idx));303  return true;304}305 306AddressRanges Block::GetRanges() {307  Address addr = GetFunction().GetAddress();308  if (!addr.GetModule())309    return {};310 311  AddressRanges ranges;312  for (size_t i = 0, e = m_ranges.GetSize(); i < e; ++i)313    ranges.push_back(ToAddressRange(addr, m_ranges.GetEntryRef(i)));314  return ranges;315}316 317bool Block::GetStartAddress(Address &addr) {318  Address func_addr = GetFunction().GetAddress();319  if (!func_addr.GetModule() || m_ranges.IsEmpty())320    return false;321 322  addr = ToAddressRange(func_addr, m_ranges.GetEntryRef(0)).GetBaseAddress();323  return true;324}325 326void Block::FinalizeRanges() {327  m_ranges.Sort();328  m_ranges.CombineConsecutiveRanges();329}330 331void Block::AddRange(const Range &range) {332  Block *parent_block = GetParent();333  if (parent_block && !parent_block->Contains(range)) {334    Log *log = GetLog(LLDBLog::Symbols);335    if (log) {336      ModuleSP module_sp(m_parent_scope.CalculateSymbolContextModule());337      Function &function = GetFunction();338      const addr_t function_file_addr = function.GetAddress().GetFileAddress();339      const addr_t block_start_addr = function_file_addr + range.GetRangeBase();340      const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();341      Type *func_type = function.GetType();342 343      const Declaration &func_decl = func_type->GetDeclaration();344      if (func_decl.GetLine()) {345        LLDB_LOGF(log,346                  "warning: %s:%u block {0x%8.8" PRIx64347                  "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64348                  ") which is not contained in parent block {0x%8.8" PRIx64349                  "} in function {0x%8.8" PRIx64 "} from %s",350                  func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),351                  GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,352                  block_end_addr, parent_block->GetID(), function.GetID(),353                  module_sp->GetFileSpec().GetPath().c_str());354      } else {355        LLDB_LOGF(log,356                  "warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64357                  " - 0x%" PRIx64358                  ") which is not contained in parent block {0x%8.8" PRIx64359                  "} in function {0x%8.8" PRIx64 "} from %s",360                  GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,361                  block_end_addr, parent_block->GetID(), function.GetID(),362                  module_sp->GetFileSpec().GetPath().c_str());363      }364    }365    parent_block->AddRange(range);366  }367  m_ranges.Append(range);368}369 370// Return the current number of bytes that this object occupies in memory371size_t Block::MemorySize() const {372  size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);373  if (m_inlineInfoSP.get())374    mem_size += m_inlineInfoSP->MemorySize();375  if (m_variable_list_sp.get())376    mem_size += m_variable_list_sp->MemorySize();377  return mem_size;378}379 380BlockSP Block::CreateChild(user_id_t uid) {381  m_children.push_back(std::shared_ptr<Block>(new Block(uid, *this)));382  return m_children.back();383}384 385void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,386                                   const Declaration *decl_ptr,387                                   const Declaration *call_decl_ptr) {388  m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,389                                                        call_decl_ptr);390}391 392VariableListSP Block::GetBlockVariableList(bool can_create) {393  if (!m_parsed_block_variables) {394    if (m_variable_list_sp.get() == nullptr && can_create) {395      m_parsed_block_variables = true;396      SymbolContext sc;397      CalculateSymbolContext(&sc);398      assert(sc.module_sp);399      sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);400    }401  }402  return m_variable_list_sp;403}404 405uint32_t406Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,407                            bool stop_if_child_block_is_inlined_function,408                            const std::function<bool(Variable *)> &filter,409                            VariableList *variable_list) {410  uint32_t num_variables_added = 0;411  VariableList *block_var_list = GetBlockVariableList(can_create).get();412  if (block_var_list) {413    for (const VariableSP &var_sp : *block_var_list) {414      if (filter(var_sp.get())) {415        num_variables_added++;416        variable_list->AddVariable(var_sp);417      }418    }419  }420 421  if (get_child_block_variables) {422    collection::const_iterator pos, end = m_children.end();423    for (pos = m_children.begin(); pos != end; ++pos) {424      Block *child_block = pos->get();425      if (!stop_if_child_block_is_inlined_function ||426          child_block->GetInlinedFunctionInfo() == nullptr) {427        num_variables_added += child_block->AppendBlockVariables(428            can_create, get_child_block_variables,429            stop_if_child_block_is_inlined_function, filter, variable_list);430      }431    }432  }433  return num_variables_added;434}435 436uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,437                                bool stop_if_block_is_inlined_function,438                                const std::function<bool(Variable *)> &filter,439                                VariableList *variable_list) {440  uint32_t num_variables_added = 0;441  VariableListSP variable_list_sp(GetBlockVariableList(can_create));442 443  bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;444  if (variable_list_sp) {445    for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {446      VariableSP variable = variable_list_sp->GetVariableAtIndex(i);447      if (filter(variable.get())) {448        num_variables_added++;449        variable_list->AddVariable(variable);450      }451    }452  }453 454  if (get_parent_variables) {455    if (stop_if_block_is_inlined_function && is_inlined_function)456      return num_variables_added;457 458    Block *parent_block = GetParent();459    if (parent_block)460      num_variables_added += parent_block->AppendVariables(461          can_create, get_parent_variables, stop_if_block_is_inlined_function,462          filter, variable_list);463  }464  return num_variables_added;465}466 467SymbolFile *Block::GetSymbolFile() {468  if (ModuleSP module_sp = CalculateSymbolContextModule())469    return module_sp->GetSymbolFile();470  return nullptr;471}472 473CompilerDeclContext Block::GetDeclContext() {474  if (SymbolFile *sym_file = GetSymbolFile())475    return sym_file->GetDeclContextForUID(GetID());476  return CompilerDeclContext();477}478 479void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {480  m_parsed_block_info = b;481  if (set_children) {482    m_parsed_child_blocks = true;483    collection::const_iterator pos, end = m_children.end();484    for (pos = m_children.begin(); pos != end; ++pos)485      (*pos)->SetBlockInfoHasBeenParsed(b, true);486  }487}488 489void Block::SetDidParseVariables(bool b, bool set_children) {490  m_parsed_block_variables = b;491  if (set_children) {492    collection::const_iterator pos, end = m_children.end();493    for (pos = m_children.begin(); pos != end; ++pos)494      (*pos)->SetDidParseVariables(b, true);495  }496}497 498Block *Block::GetSibling() const {499  if (Block *parent_block = GetParent())500    return parent_block->GetSiblingForChild(this);501  return nullptr;502}503 504// A parent of child blocks can be asked to find a sibling block given505// one of its child blocks506Block *Block::GetSiblingForChild(const Block *child_block) const {507  if (!m_children.empty()) {508    collection::const_iterator pos, end = m_children.end();509    for (pos = m_children.begin(); pos != end; ++pos) {510      if (pos->get() == child_block) {511        if (++pos != end)512          return pos->get();513        break;514      }515    }516  }517  return nullptr;518}519