diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Symbol/Block.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Symbol/Block.cpp | 631 |
1 files changed, 631 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Block.cpp b/contrib/llvm/tools/lldb/source/Symbol/Block.cpp new file mode 100644 index 0000000..4ab86e5 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Symbol/Block.cpp @@ -0,0 +1,631 @@ +//===-- 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/lldb-private-log.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/VariableList.h" + +using namespace lldb; +using namespace lldb_private; + +Block::Block(lldb::user_id_t uid) : + UserID(uid), + m_parent_scope (NULL), + m_children (), + m_ranges (), + m_inlineInfoSP (), + m_variable_list_sp (), + m_parsed_block_info (false), + m_parsed_block_variables (false), + m_parsed_child_blocks (false) +{ +} + +Block::~Block () +{ +} + +void +Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const +{ + *s << "id = " << ((const UserID&)*this); + + size_t num_ranges = m_ranges.GetSize(); + if (num_ranges > 0) + { + + addr_t base_addr = LLDB_INVALID_ADDRESS; + if (target) + base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); + + s->Printf(", range%s = ", num_ranges > 1 ? "s" : ""); + for (size_t i=0; i<num_ranges; ++i) + { + const Range &range = m_ranges.GetEntryRef(i); + s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); + } + } + + if (m_inlineInfoSP.get() != NULL) + { + bool show_fullpaths = (level == eDescriptionLevelVerbose); + m_inlineInfoSP->Dump(s, show_fullpaths); + } +} + +void +Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const +{ + if (depth < 0) + { + Block *parent = GetParent(); + if (parent) + { + // We have a depth that is less than zero, print our parent blocks + // first + parent->Dump(s, base_addr, depth + 1, show_context); + } + } + + s->Printf("%p: ", this); + s->Indent(); + *s << "Block" << ((const UserID&)*this); + const Block* parent_block = GetParent(); + if (parent_block) + { + s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID()); + } + if (m_inlineInfoSP.get() != NULL) + { + bool show_fullpaths = false; + m_inlineInfoSP->Dump(s, show_fullpaths); + } + + if (!m_ranges.IsEmpty()) + { + *s << ", ranges ="; + + size_t num_ranges = m_ranges.GetSize(); + for (size_t i=0; i<num_ranges; ++i) + { + const Range &range = m_ranges.GetEntryRef(i); + if (parent_block != NULL && parent_block->Contains(range) == false) + *s << '!'; + else + *s << ' '; + s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); + } + } + s->EOL(); + + if (depth > 0) + { + s->IndentMore(); + + if (m_variable_list_sp.get()) + { + m_variable_list_sp->Dump(s, show_context); + } + + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->Dump(s, base_addr, depth - 1, show_context); + + s->IndentLess(); + } + +} + + +Block * +Block::FindBlockByID (user_id_t block_id) +{ + if (block_id == GetID()) + return this; + + Block *matching_block = NULL; + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + { + matching_block = (*pos)->FindBlockByID (block_id); + if (matching_block) + break; + } + return matching_block; +} + +void +Block::CalculateSymbolContext (SymbolContext* sc) +{ + if (m_parent_scope) + m_parent_scope->CalculateSymbolContext(sc); + sc->block = this; +} + +lldb::ModuleSP +Block::CalculateSymbolContextModule () +{ + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextModule (); + return lldb::ModuleSP(); +} + +CompileUnit * +Block::CalculateSymbolContextCompileUnit () +{ + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextCompileUnit (); + return NULL; +} + +Function * +Block::CalculateSymbolContextFunction () +{ + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextFunction (); + return NULL; +} + +Block * +Block::CalculateSymbolContextBlock () +{ + return this; +} + +void +Block::DumpSymbolContext(Stream *s) +{ + Function *function = CalculateSymbolContextFunction(); + if (function) + function->DumpSymbolContext(s); + s->Printf(", Block{0x%8.8" PRIx64 "}", GetID()); +} + +void +Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr) +{ + if (!m_ranges.IsEmpty()) + { + size_t num_ranges = m_ranges.GetSize(); + for (size_t i=0; i<num_ranges; ++i) + { + const Range &range = m_ranges.GetEntryRef(i); + s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); + } + } +} + +bool +Block::Contains (addr_t range_offset) const +{ + return m_ranges.FindEntryThatContains(range_offset) != NULL; +} + +bool +Block::Contains (const Block *block) const +{ + if (this == block) + return false; // This block doesn't contain itself... + + // Walk the parent chain for "block" and see if any if them match this block + const Block *block_parent; + for (block_parent = block->GetParent(); + block_parent != NULL; + block_parent = block_parent->GetParent()) + { + if (this == block_parent) + return true; // One of the parents of "block" is this object! + } + return false; +} + +bool +Block::Contains (const Range& range) const +{ + return m_ranges.FindEntryThatContains (range) != NULL; +} + +Block * +Block::GetParent () const +{ + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextBlock(); + return NULL; +} + +Block * +Block::GetContainingInlinedBlock () +{ + if (GetInlinedFunctionInfo()) + return this; + return GetInlinedParent (); +} + +Block * +Block::GetInlinedParent () +{ + Block *parent_block = GetParent (); + if (parent_block) + { + if (parent_block->GetInlinedFunctionInfo()) + return parent_block; + else + return parent_block->GetInlinedParent(); + } + return NULL; +} + + +bool +Block::GetRangeContainingOffset (const addr_t offset, Range &range) +{ + const Range *range_ptr = m_ranges.FindEntryThatContains (offset); + if (range_ptr) + { + range = *range_ptr; + return true; + } + range.Clear(); + return false; +} + + +bool +Block::GetRangeContainingAddress (const Address& addr, AddressRange &range) +{ + Function *function = CalculateSymbolContextFunction(); + if (function) + { + const AddressRange &func_range = function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) + { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) + { + addr_t offset = addr_offset - func_offset; + + const Range *range_ptr = m_ranges.FindEntryThatContains (offset); + + if (range_ptr) + { + range.GetBaseAddress() = func_range.GetBaseAddress(); + range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase()); + range.SetByteSize(range_ptr->GetByteSize()); + return true; + } + } + } + } + range.Clear(); + return false; +} + +bool +Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range) +{ + Address load_address; + load_address.SetLoadAddress(load_addr, &target); + AddressRange containing_range; + return GetRangeContainingAddress(load_address, containing_range); +} + + +uint32_t +Block::GetRangeIndexContainingAddress (const Address& addr) +{ + Function *function = CalculateSymbolContextFunction(); + if (function) + { + const AddressRange &func_range = function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) + { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) + { + addr_t offset = addr_offset - func_offset; + return m_ranges.FindEntryIndexThatContains (offset); + } + } + } + return UINT32_MAX; +} + +bool +Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range) +{ + if (range_idx < m_ranges.GetSize()) + { + Function *function = CalculateSymbolContextFunction(); + if (function) + { + const Range &vm_range = m_ranges.GetEntryRef(range_idx); + range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); + range.GetBaseAddress().Slide(vm_range.GetRangeBase ()); + range.SetByteSize (vm_range.GetByteSize()); + return true; + } + } + return false; +} + +bool +Block::GetStartAddress (Address &addr) +{ + if (m_ranges.IsEmpty()) + return false; + + Function *function = CalculateSymbolContextFunction(); + if (function) + { + addr = function->GetAddressRange().GetBaseAddress(); + addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ()); + return true; + } + return false; +} + +void +Block::FinalizeRanges () +{ + m_ranges.Sort(); + m_ranges.CombineConsecutiveRanges (); +} + +void +Block::AddRange (const Range& range) +{ + Block *parent_block = GetParent (); + if (parent_block && !parent_block->Contains(range)) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); + if (log) + { + ModuleSP module_sp (m_parent_scope->CalculateSymbolContextModule()); + Function *function = m_parent_scope->CalculateSymbolContextFunction(); + const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); + const addr_t block_start_addr = function_file_addr + range.GetRangeBase (); + const addr_t block_end_addr = function_file_addr + range.GetRangeEnd (); + Type *func_type = function->GetType(); + + const Declaration &func_decl = func_type->GetDeclaration(); + if (func_decl.GetLine()) + { + log->Printf ("warning: %s:%u block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s", + func_decl.GetFile().GetPath().c_str(), + func_decl.GetLine(), + GetID(), + (uint32_t)m_ranges.GetSize(), + block_start_addr, + block_end_addr, + parent_block->GetID(), + function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); + } + else + { + log->Printf ("warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s", + GetID(), + (uint32_t)m_ranges.GetSize(), + block_start_addr, + block_end_addr, + parent_block->GetID(), + function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); + } + } + parent_block->AddRange (range); + } + m_ranges.Append(range); +} + +// 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.GetSize() * sizeof(Range); + if (m_inlineInfoSP.get()) + mem_size += m_inlineInfoSP->MemorySize(); + if (m_variable_list_sp.get()) + mem_size += m_variable_list_sp->MemorySize(); + return mem_size; + +} + +void +Block::AddChild(const BlockSP &child_block_sp) +{ + if (child_block_sp) + { + child_block_sp->SetParentScope (this); + m_children.push_back (child_block_sp); + } +} + +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)); +} + + + +VariableListSP +Block::GetBlockVariableList (bool can_create) +{ + if (m_parsed_block_variables == false) + { + if (m_variable_list_sp.get() == NULL && can_create) + { + m_parsed_block_variables = true; + SymbolContext sc; + CalculateSymbolContext(&sc); + assert(sc.module_sp); + sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); + } + } + return m_variable_list_sp; +} + +uint32_t +Block::AppendBlockVariables (bool can_create, + bool get_child_block_variables, + bool stop_if_child_block_is_inlined_function, + VariableList *variable_list) +{ + uint32_t num_variables_added = 0; + VariableList *block_var_list = GetBlockVariableList (can_create).get(); + if (block_var_list) + { + num_variables_added += block_var_list->GetSize(); + variable_list->AddVariables (block_var_list); + } + + if (get_child_block_variables) + { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + { + Block *child_block = pos->get(); + if (stop_if_child_block_is_inlined_function == false || + child_block->GetInlinedFunctionInfo() == NULL) + { + num_variables_added += child_block->AppendBlockVariables (can_create, + get_child_block_variables, + stop_if_child_block_is_inlined_function, + variable_list); + } + } + } + return num_variables_added; +} + +uint32_t +Block::AppendVariables +( + bool can_create, + bool get_parent_variables, + bool stop_if_block_is_inlined_function, + VariableList *variable_list +) +{ + uint32_t num_variables_added = 0; + VariableListSP variable_list_sp(GetBlockVariableList(can_create)); + + bool is_inlined_function = GetInlinedFunctionInfo() != NULL; + if (variable_list_sp.get()) + { + num_variables_added = variable_list_sp->GetSize(); + variable_list->AddVariables(variable_list_sp.get()); + } + + if (get_parent_variables) + { + if (stop_if_block_is_inlined_function && is_inlined_function) + return num_variables_added; + + Block* parent_block = GetParent(); + if (parent_block) + num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); + } + return num_variables_added; +} + +clang::DeclContext * +Block::GetClangDeclContext() +{ + SymbolContext sc; + + CalculateSymbolContext (&sc); + + if (!sc.module_sp) + return NULL; + + SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); + + if (!sym_vendor) + return NULL; + + SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + + if (!sym_file) + return NULL; + + return sym_file->GetClangDeclContextForTypeUID (sc, m_uid); +} + +void +Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) +{ + m_parsed_block_info = b; + if (set_children) + { + m_parsed_child_blocks = true; + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->SetBlockInfoHasBeenParsed (b, true); + } +} + +void +Block::SetDidParseVariables (bool b, bool set_children) +{ + m_parsed_block_variables = b; + if (set_children) + { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->SetDidParseVariables (b, true); + } +} + + +Block * +Block::GetSibling() const +{ + if (m_parent_scope) + { + Block *parent_block = GetParent(); + if (parent_block) + return parent_block->GetSiblingForChild (this); + } + return NULL; +} +// A parent of child blocks can be asked to find a sibling block given +// one of its child blocks +Block * +Block::GetSiblingForChild (const Block *child_block) const +{ + if (!m_children.empty()) + { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + { + if (pos->get() == child_block) + { + if (++pos != end) + return pos->get(); + break; + } + } + } + return NULL; +} + |