Files
clang-p2996/lldb/source/Symbol/SymbolContext.cpp
Sean Callanan 5666b674f3 Added support for accessing members of C++ objects,
including superclass members.  This involved ensuring
that access control was ignored, and ensuring that
the operands of BitCasts were properly scanned for
variables that needed importing.

Also laid the groundwork for declaring objects of
custom types; however, this functionality is disabled
for now because of a potential loop in ASTImporter.

llvm-svn: 110174
2010-08-04 01:02:13 +00:00

494 lines
13 KiB
C++

//===-- SymbolContext.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/SymbolContext.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
SymbolContext::SymbolContext() :
target_sp (),
module_sp (),
comp_unit (NULL),
function (NULL),
block (NULL),
line_entry (),
symbol (NULL)
{
}
SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
target_sp (),
module_sp (m),
comp_unit (cu),
function (f),
block (b),
line_entry (),
symbol (s)
{
if (le)
line_entry = *le;
}
SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
target_sp (t),
module_sp (m),
comp_unit (cu),
function (f),
block (b),
line_entry (),
symbol (s)
{
if (le)
line_entry = *le;
}
SymbolContext::SymbolContext(const SymbolContext& rhs) :
target_sp (rhs.target_sp),
module_sp (rhs.module_sp),
comp_unit (rhs.comp_unit),
function (rhs.function),
block (rhs.block),
line_entry (rhs.line_entry),
symbol (rhs.symbol)
{
}
SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
target_sp (),
module_sp (),
comp_unit (NULL),
function (NULL),
block (NULL),
line_entry (),
symbol (NULL)
{
sc_scope->CalculateSymbolContext (this);
}
const SymbolContext&
SymbolContext::operator= (const SymbolContext& rhs)
{
if (this != &rhs)
{
target_sp = rhs.target_sp;
module_sp = rhs.module_sp;
comp_unit = rhs.comp_unit;
function = rhs.function;
block = rhs.block;
line_entry = rhs.line_entry;
symbol = rhs.symbol;
}
return *this;
}
void
SymbolContext::Clear()
{
target_sp.reset();
module_sp.reset();
comp_unit = NULL;
function = NULL;
block = NULL;
line_entry.Clear();
symbol = NULL;
}
void
SymbolContext::DumpStopContext
(
Stream *s,
ExecutionContextScope *exe_scope,
const Address &addr,
bool show_module
) const
{
if (show_module && module_sp)
{
*s << module_sp->GetFileSpec().GetFilename() << '`';
}
if (function != NULL)
{
if (function->GetMangled().GetName())
function->GetMangled().GetName().Dump(s);
const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset();
if (function_offset)
s->Printf(" + %llu", function_offset);
if (block != NULL)
{
s->IndentMore();
block->DumpStopContext(s, this);
s->IndentLess();
}
else
{
if (line_entry.IsValid())
{
s->PutCString(" at ");
if (line_entry.DumpStopContext(s))
return;
}
}
}
else if (symbol != NULL)
{
symbol->GetMangled().GetName().Dump(s);
if (symbol->GetAddressRangePtr())
{
const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset();
if (symbol_offset)
s->Printf(" + %llu", symbol_offset);
}
}
else
{
addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
}
}
void
SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) const
{
if (module_sp)
{
s->Indent(" Module: \"");
module_sp->GetFileSpec().Dump(s);
s->PutChar('"');
s->EOL();
}
if (comp_unit != NULL)
{
s->Indent("CompileUnit: ");
comp_unit->GetDescription (s, level);
s->EOL();
}
if (function != NULL)
{
s->Indent(" Function: ");
function->GetDescription (s, level, process);
s->EOL();
Type *func_type = function->GetType();
if (func_type)
{
s->Indent(" FuncType: ");
func_type->GetDescription (s, level, false);
s->EOL();
}
}
if (block != NULL)
{
std::vector<Block *> blocks;
blocks.push_back (block);
Block *parent_block = block->GetParent();
while (parent_block)
{
blocks.push_back (parent_block);
parent_block = parent_block->GetParent();
}
std::vector<Block *>::reverse_iterator pos;
std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
std::vector<Block *>::reverse_iterator end = blocks.rend();
for (pos = begin; pos != end; ++pos)
{
if (pos == begin)
s->Indent(" Blocks: ");
else
s->Indent(" ");
(*pos)->GetDescription(s, level, process);
s->EOL();
}
}
if (line_entry.IsValid())
{
s->Indent(" LineEntry: ");
line_entry.GetDescription (s, level, comp_unit, process, false);
s->EOL();
}
if (symbol != NULL)
{
s->Indent(" Symbol: ");
symbol->GetDescription(s, level, process);
s->EOL();
}
}
void
SymbolContext::Dump(Stream *s, Process *process) const
{
*s << (void *)this << ": ";
s->Indent();
s->PutCString("SymbolContext");
s->IndentMore();
s->EOL();
s->IndentMore();
s->Indent();
*s << "Module = " << (void *)module_sp.get() << ' ';
if (module_sp)
module_sp->GetFileSpec().Dump(s);
s->EOL();
s->Indent();
*s << "CompileUnit = " << (void *)comp_unit;
if (comp_unit != NULL)
*s << " {0x" << comp_unit->GetID() << "} " << *(dynamic_cast<FileSpec*> (comp_unit));
s->EOL();
s->Indent();
*s << "Function = " << (void *)function;
if (function != NULL)
{
*s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
function->GetAddressRange().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
s->EOL();
s->Indent();
Type* func_type = function->GetType();
if (func_type)
{
*s << " Type = ";
func_type->Dump (s, false);
}
}
s->EOL();
s->Indent();
*s << "Block = " << (void *)block;
if (block != NULL)
*s << " {0x" << block->GetID() << '}';
// Dump the block and pass it a negative depth to we print all the parent blocks
//if (block != NULL)
// block->Dump(s, function->GetFileAddress(), INT_MIN);
s->EOL();
s->Indent();
*s << "LineEntry = ";
line_entry.Dump (s, process, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
s->EOL();
s->Indent();
*s << "Symbol = " << (void *)symbol;
if (symbol != NULL && symbol->GetMangled())
*s << ' ' << symbol->GetMangled().GetName().AsCString();
s->EOL();
s->IndentLess();
s->IndentLess();
}
bool
lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
{
return lhs.target_sp.get() == rhs.target_sp.get() &&
lhs.module_sp.get() == rhs.module_sp.get() &&
lhs.comp_unit == rhs.comp_unit &&
lhs.function == rhs.function &&
LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 &&
lhs.symbol == rhs.symbol;
}
bool
lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
{
return lhs.target_sp.get() != rhs.target_sp.get() ||
lhs.module_sp.get() != rhs.module_sp.get() ||
lhs.comp_unit != rhs.comp_unit ||
lhs.function != rhs.function ||
LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 ||
lhs.symbol != rhs.symbol;
}
bool
SymbolContext::GetAddressRange (uint32_t scope, AddressRange &range) const
{
if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
{
range = line_entry.range;
return true;
}
else if ((scope & eSymbolContextFunction) && function != NULL)
{
range = function->GetAddressRange();
return true;
}
else if ((scope & eSymbolContextSymbol) && symbol != NULL && symbol->GetAddressRangePtr())
{
range = *symbol->GetAddressRangePtr();
if (range.GetByteSize() == 0)
{
if (module_sp)
{
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
{
Symtab *symtab = objfile->GetSymtab();
if (symtab)
range.SetByteSize(symtab->CalculateSymbolSize (symbol));
}
}
}
return true;
}
range.Clear();
return false;
}
size_t
SymbolContext::FindFunctionsByName (const ConstString &name, bool append, SymbolContextList &sc_list) const
{
if (!append)
sc_list.Clear();
if (function != NULL)
{
// FIXME: Look in the class of the current function, if it exists,
// for methods matching name.
}
if (comp_unit != NULL)
{
// Make sure we've read in all the functions. We should be able to check and see
// if there's one by this name present before we do this...
module_sp->GetSymbolVendor()->ParseCompileUnitFunctions(*this);
uint32_t func_idx;
lldb::FunctionSP func_sp;
for (func_idx = 0; (func_sp = comp_unit->GetFunctionAtIndex(func_idx)) != NULL; ++func_idx)
{
if (func_sp->GetMangled().GetName() == name)
{
SymbolContext sym_ctx(target_sp,
module_sp,
comp_unit,
func_sp.get());
sc_list.Append(sym_ctx);
}
}
}
if (module_sp != NULL)
module_sp->FindFunctions (name, eFunctionNameTypeBase | eFunctionNameTypeFull, true, sc_list);
if (target_sp)
target_sp->GetImages().FindFunctions (name, eFunctionNameTypeBase | eFunctionNameTypeFull, true, sc_list);
return sc_list.GetSize();
}
lldb::VariableSP
SymbolContext::FindVariableByName (const char *name) const
{
lldb::VariableSP return_value;
return return_value;
}
lldb::TypeSP
SymbolContext::FindTypeByName (const ConstString &name) const
{
lldb::TypeSP return_value;
TypeList types;
if (module_sp && module_sp->FindTypes (*this, name, false, 1, types))
return types.GetTypeAtIndex(0);
if (!return_value.get() && target_sp && target_sp->GetImages().FindTypes (*this, name, false, 1, types))
return types.GetTypeAtIndex(0);
return return_value;
}
//----------------------------------------------------------------------
//
// SymbolContextList
//
//----------------------------------------------------------------------
SymbolContextList::SymbolContextList() :
m_symbol_contexts()
{
}
SymbolContextList::~SymbolContextList()
{
}
void
SymbolContextList::Append(const SymbolContext& sc)
{
m_symbol_contexts.push_back(sc);
}
void
SymbolContextList::Clear()
{
m_symbol_contexts.clear();
}
void
SymbolContextList::Dump(Stream *s, Process *process) const
{
*s << (void *)this << ": ";
s->Indent();
s->PutCString("SymbolContextList");
s->EOL();
s->IndentMore();
collection::const_iterator pos, end = m_symbol_contexts.end();
for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
{
pos->Dump(s, process);
}
s->IndentLess();
}
bool
SymbolContextList::GetContextAtIndex(uint32_t idx, SymbolContext& sc) const
{
if (idx < m_symbol_contexts.size())
{
sc = m_symbol_contexts[idx];
return true;
}
return false;
}
bool
SymbolContextList::RemoveContextAtIndex (uint32_t idx)
{
if (idx < m_symbol_contexts.size())
{
m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
return true;
}
return false;
}
uint32_t
SymbolContextList::GetSize() const
{
return m_symbol_contexts.size();
}