diff options
Diffstat (limited to 'lldb/source/Symbol/Block.cpp')
-rw-r--r-- | lldb/source/Symbol/Block.cpp | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp new file mode 100644 index 00000000000..321411940f4 --- /dev/null +++ b/lldb/source/Symbol/Block.cpp @@ -0,0 +1,641 @@ +//===-- Block.cpp -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/VariableList.h" + +using namespace lldb; +using namespace lldb_private; + +Block::Block(user_id_t uid, uint32_t depth, BlockList* blocks) : + UserID(uid), + m_block_list(blocks), + m_depth(depth), + m_ranges(), + m_inlineInfoSP(), + m_variables() +{ +} + +Block::Block(const Block& rhs) : + UserID(rhs), + m_block_list(rhs.m_block_list), + m_depth(rhs.m_depth), + m_ranges(rhs.m_ranges), + m_inlineInfoSP(rhs.m_inlineInfoSP), + m_variables(rhs.m_variables) +{ +} + +const Block& +Block::operator= (const Block& rhs) +{ + if (this != &rhs) + { + UserID::operator= (rhs); + m_block_list = rhs.m_block_list; + m_depth = rhs.m_depth; + m_ranges = rhs.m_ranges; + m_inlineInfoSP = rhs.m_inlineInfoSP; + m_variables = rhs.m_variables; + } + return *this; +} + +Block::~Block () +{ +} + +void +Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const +{ + if (depth < 0) + { + // We have a depth that is less than zero, print our parent blocks + // first + m_block_list->Dump(s, GetParentUID(), depth + 1, show_context); + } + + s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + s->Indent(); + *s << "Block" << ((const UserID&)*this); + user_id_t parentID = GetParentUID(); + const Block* parent_block = NULL; + if (parentID != Block::InvalidID) + { + parent_block = m_block_list->GetBlockByID(parentID); + s->Printf(", parent = {0x%8.8x}", parentID); + } + if (m_inlineInfoSP.get() != NULL) + m_inlineInfoSP->Dump(s); + + if (!m_ranges.empty()) + { + *s << ", ranges ="; + std::vector<VMRange>::const_iterator pos; + std::vector<VMRange>::const_iterator end = m_ranges.end(); + for (pos = m_ranges.begin(); pos != end; ++pos) + { + if (parent_block != NULL && parent_block->Contains(*pos) == false) + *s << '!'; + else + *s << ' '; + pos->Dump(s, base_addr); + } + } + s->EOL(); + + if (depth > 0) + { + s->IndentMore(); + + if (m_variables.get()) + { + m_variables->Dump(s, show_context); + } + + uint32_t blockID = m_block_list->GetFirstChild(GetID()); + while (blockID != Block::InvalidID) + { + m_block_list->Dump(s, blockID, depth - 1, show_context); + + blockID = m_block_list->GetSibling(blockID); + } + + s->IndentLess(); + } + +} + + +void +Block::CalculateSymbolContext(SymbolContext* sc) +{ + sc->block = this; + m_block_list->GetFunction()->CalculateSymbolContext(sc); +} + +void +Block::DumpStopContext (Stream *s, const SymbolContext *sc) +{ + user_id_t parentID = GetParentUID(); + Block* parent_block = NULL; + if (parentID != Block::InvalidID) + parent_block = m_block_list->GetBlockByID(parentID); + + InlineFunctionInfo* inline_info = InlinedFunctionInfo (); + if (inline_info) + { + const Declaration &call_site = inline_info->GetCallSite(); + if (sc) + { + // First frame, dump the first inline call site +// if (call_site.IsValid()) +// { +// s->PutCString(" at "); +// call_site.DumpStopContext (s); +// } + s->PutCString (" [inlined]"); + } + s->EOL(); + inline_info->DumpStopContext (s); + if (sc == NULL) + { + if (call_site.IsValid()) + { + s->PutCString(" at "); + call_site.DumpStopContext (s); + } + } + } + + if (sc) + { + // If we have any inlined functions, this will be the deepest most + // inlined location + if (sc->line_entry.IsValid()) + { + s->PutCString(" at "); + sc->line_entry.DumpStopContext (s); + } + } + if (parent_block) + parent_block->Block::DumpStopContext (s, NULL); +} + + +void +Block::DumpSymbolContext(Stream *s) +{ + m_block_list->GetFunction()->DumpSymbolContext(s); + s->Printf(", Block{0x%8.8x}", GetID()); +} + +bool +Block::Contains (addr_t range_offset) const +{ + return VMRange::ContainsValue(m_ranges, range_offset); +} + +bool +Block::Contains (const VMRange& range) const +{ + return VMRange::ContainsRange(m_ranges, range); +} + + + +bool +BlockList::BlockContainsBlockWithID (const user_id_t block_id, const user_id_t find_block_id) const +{ + if (block_id == Block::InvalidID) + return false; + + if (block_id == find_block_id) + return true; + else + { + user_id_t child_block_id = GetFirstChild(block_id); + while (child_block_id != Block::InvalidID) + { + if (BlockContainsBlockWithID (child_block_id, find_block_id)) + return true; + child_block_id = GetSibling(child_block_id); + } + } + + return false; +} + +bool +Block::ContainsBlockWithID (user_id_t block_id) const +{ + return m_block_list->BlockContainsBlockWithID (GetID(), block_id); +} + + +void +Block::AddRange(addr_t start_offset, addr_t end_offset) +{ + m_ranges.resize(m_ranges.size()+1); + m_ranges.back().Reset(start_offset, end_offset); +} + +InlineFunctionInfo* +Block::InlinedFunctionInfo () +{ + return m_inlineInfoSP.get(); +} + +const InlineFunctionInfo* +Block::InlinedFunctionInfo () const +{ + return m_inlineInfoSP.get(); +} + +// Return the current number of bytes that this object occupies in memory +size_t +Block::MemorySize() const +{ + size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange); + if (m_inlineInfoSP.get()) + mem_size += m_inlineInfoSP->MemorySize(); + if (m_variables.get()) + mem_size += m_variables->MemorySize(); + return mem_size; + +} + +user_id_t +Block::GetParentUID() const +{ + return m_block_list->GetParent(GetID()); +} + +user_id_t +Block::GetSiblingUID() const +{ + return m_block_list->GetSibling(GetID()); +} + +user_id_t +Block::GetFirstChildUID() const +{ + return m_block_list->GetFirstChild(GetID()); +} + +user_id_t +Block::AddChild(user_id_t userID) +{ + return m_block_list->AddChild(GetID(), userID); +} + +void +Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) +{ + m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); +} + +BlockList::BlockList(Function *function, const AddressRange& range) : + m_function(function), + m_range(range), + m_blocks() +{ +} + +BlockList::~BlockList() +{ +} + +AddressRange & +BlockList::GetAddressRange() +{ + return m_range; +} + +const AddressRange & +BlockList::GetAddressRange() const +{ + return m_range; +} + +void +BlockList::Dump(Stream *s, user_id_t blockID, uint32_t depth, bool show_context) const +{ + const Block* block = GetBlockByID(blockID); + if (block) + block->Dump(s, m_range.GetBaseAddress().GetFileAddress(), depth, show_context); +} + +Function * +BlockList::GetFunction() +{ + return m_function; +} + + +const Function * +BlockList::GetFunction() const +{ + return m_function; +} + +user_id_t +BlockList::GetParent(user_id_t blockID) const +{ + collection::const_iterator end = m_blocks.end(); + collection::const_iterator begin = m_blocks.begin(); + collection::const_iterator pos = std::find_if(begin, end, UserID::IDMatches(blockID)); + + if (pos != end && pos != begin && pos->Depth() > 0) + { + const uint32_t parent_depth = pos->Depth() - 1; + + while (--pos >= begin) + { + if (pos->Depth() == parent_depth) + return pos->GetID(); + } + } + return Block::InvalidID; +} + +user_id_t +BlockList::GetSibling(user_id_t blockID) const +{ + collection::const_iterator end = m_blocks.end(); + collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); + + if (pos != end) + { + const uint32_t sibling_depth = pos->Depth(); + while (++pos != end) + { + uint32_t depth = pos->Depth(); + if (depth == sibling_depth) + return pos->GetID(); + if (depth < sibling_depth) + break; + } + } + return Block::InvalidID; +} + +user_id_t +BlockList::GetFirstChild(user_id_t blockID) const +{ + if (!m_blocks.empty()) + { + if (blockID == Block::RootID) + { + return m_blocks.front().GetID(); + } + else + { + collection::const_iterator end = m_blocks.end(); + collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); + + if (pos != end) + { + collection::const_iterator child_pos = pos + 1; + if (child_pos != end) + { + if (child_pos->Depth() == pos->Depth() + 1) + return child_pos->GetID(); + } + } + } + } + return Block::InvalidID; +} + + +// Return the current number of bytes that this object occupies in memory +size_t +BlockList::MemorySize() const +{ + size_t mem_size = sizeof(BlockList); + + collection::const_iterator pos, end = m_blocks.end(); + for (pos = m_blocks.begin(); pos != end; ++pos) + mem_size += pos->MemorySize(); // Each block can vary in size + + return mem_size; + +} + +user_id_t +BlockList::AddChild (user_id_t parentID, user_id_t childID) +{ + bool added = false; + if (parentID == Block::RootID) + { + assert(m_blocks.empty()); + Block block(childID, 0, this); + m_blocks.push_back(block); + added = true; + } + else + { + collection::iterator end = m_blocks.end(); + collection::iterator parent_pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(parentID)); + assert(parent_pos != end); + if (parent_pos != end) + { + const uint32_t parent_sibling_depth = parent_pos->Depth(); + + collection::iterator insert_pos = parent_pos; + collection::iterator prev_sibling = end; + while (++insert_pos != end) + { + if (insert_pos->Depth() <= parent_sibling_depth) + break; + } + + Block child_block(childID, parent_pos->Depth() + 1, this); + collection::iterator child_pos = m_blocks.insert(insert_pos, child_block); + added = true; + } + } + if (added) + return childID; + return Block::InvalidID; +} + +const Block * +BlockList::GetBlockByID(user_id_t blockID) const +{ + if (m_blocks.empty()) + return NULL; + + if (blockID == Block::RootID) + blockID = m_blocks.front().GetID(); + + collection::const_iterator end = m_blocks.end(); + collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); + if (pos != end) + return &(*pos); + return NULL; +} + +Block * +BlockList::GetBlockByID(user_id_t blockID) +{ + if (m_blocks.empty()) + return NULL; + + if (blockID == Block::RootID) + blockID = m_blocks.front().GetID(); + + collection::iterator end = m_blocks.end(); + collection::iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); + if (pos != end) + return &(*pos); + return NULL; +} + +bool +BlockList::AddRange(user_id_t blockID, addr_t start_offset, addr_t end_offset) +{ + Block *block = GetBlockByID(blockID); + + if (block) + { + block->AddRange(start_offset, end_offset); + return true; + } + return false; +} +// +//const Block * +//BlockList::FindDeepestBlockForAddress (const Address &addr) +//{ +// if (m_range.Contains(addr)) +// { +// addr_t block_offset = addr.GetFileAddress() - m_range.GetBaseAddress().GetFileAddress(); +// collection::const_iterator pos, end = m_blocks.end(); +// collection::const_iterator deepest_match_pos = end; +// for (pos = m_blocks.begin(); pos != end; ++pos) +// { +// if (pos->Contains (block_offset)) +// { +// if (deepest_match_pos == end || deepest_match_pos->Depth() < pos->Depth()) +// deepest_match_pos = pos; +// } +// } +// if (deepest_match_pos != end) +// return &(*deepest_match_pos); +// } +// return NULL; +//} +// +bool +BlockList::SetInlinedFunctionInfo(user_id_t blockID, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) +{ + Block *block = GetBlockByID(blockID); + + if (block) + { + block->SetInlinedFunctionInfo(name, mangled, decl_ptr, call_decl_ptr); + return true; + } + return false; +} + +VariableListSP +BlockList::GetVariableList(user_id_t blockID, bool get_child_variables, bool can_create) +{ + VariableListSP variable_list_sp; + Block *block = GetBlockByID(blockID); + if (block) + variable_list_sp = block->GetVariableList(get_child_variables, can_create); + return variable_list_sp; +} + +bool +BlockList::IsEmpty() const +{ + return m_blocks.empty(); +} + + + +bool +BlockList::SetVariableList(user_id_t blockID, VariableListSP& variables) +{ + Block *block = GetBlockByID(blockID); + if (block) + { + block->SetVariableList(variables); + return true; + } + return false; + +} + + +VariableListSP +Block::GetVariableList (bool get_child_variables, bool can_create) +{ + VariableListSP variable_list_sp; + if (m_variables.get() == NULL && can_create) + { + SymbolContext sc; + CalculateSymbolContext(&sc); + assert(sc.module_sp); + sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); + } + + if (m_variables.get()) + { + variable_list_sp.reset(new VariableList()); + if (variable_list_sp.get()) + variable_list_sp->AddVariables(m_variables.get()); + + if (get_child_variables) + { + user_id_t block_id = GetFirstChildUID(); + while (block_id != Block::InvalidID) + { + Block *child_block = m_block_list->GetBlockByID(block_id); + assert(child_block); + VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create)); + if (child_block_variable_list.get()) + variable_list_sp->AddVariables(child_block_variable_list.get()); + + block_id = child_block->GetSiblingUID(); + } + } + } + + return variable_list_sp; +} + +uint32_t +Block::AppendVariables (bool can_create, bool get_parent_variables, VariableList *variable_list) +{ + uint32_t num_variables_added = 0; + VariableListSP variable_list_sp(GetVariableList(false, can_create)); + + if (variable_list_sp.get()) + { + num_variables_added = variable_list_sp->GetSize(); + variable_list->AddVariables(variable_list_sp.get()); + } + + if (get_parent_variables) + { + user_id_t parentID = GetParentUID(); + if (parentID != Block::InvalidID) + { + Block* parent_block = m_block_list->GetBlockByID(parentID); + if (parent_block) + num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, variable_list); + } + } + return num_variables_added; +} + + +void +Block::SetVariableList(VariableListSP& variables) +{ + m_variables = variables; +} + +uint32_t +Block::Depth () const +{ + return m_depth; +} + |