TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &dwarf_decl_ctx); The problem was we might be looking for a type "Foo", and find one from another langauge. Then the DWARFASTParserClang would try to make an AST type using a CompilerType that might return an empty. This fix makes sure that when we create a DWARFDeclContext from a DWARFDIE that the DWARFDeclContext we set the language of the DIE. Then when we go to find matches for DWARFDeclContext, we end up with bunch of DIEs. We check each DWARFDIE that we found by asking it for its language and making sure the language is compatible with the type system that we want to use. This keeps us from using the wrong types to resolve forward declarations. <rdar://problem/25276165> llvm-svn: 265196
571 lines
14 KiB
C++
571 lines
14 KiB
C++
//===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "DWARFDIE.h"
|
|
|
|
#include "DWARFASTParser.h"
|
|
#include "DWARFCompileUnit.h"
|
|
#include "DWARFDebugAbbrev.h"
|
|
#include "DWARFDebugAranges.h"
|
|
#include "DWARFDebugInfo.h"
|
|
#include "DWARFDebugInfoEntry.h"
|
|
#include "DWARFDebugRanges.h"
|
|
#include "DWARFDeclContext.h"
|
|
#include "DWARFDIECollection.h"
|
|
#include "DWARFFormValue.h"
|
|
#include "SymbolFileDWARF.h"
|
|
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
#include "lldb/Symbol/Type.h"
|
|
#include "lldb/Symbol/TypeSystem.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
DIERef
|
|
DWARFDIE::GetDIERef() const
|
|
{
|
|
if (!IsValid())
|
|
return DIERef();
|
|
|
|
dw_offset_t cu_offset = m_cu->GetOffset();
|
|
if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
|
|
cu_offset = m_cu->GetBaseObjOffset();
|
|
return DIERef(cu_offset, m_die->GetOffset());
|
|
}
|
|
|
|
dw_tag_t
|
|
DWARFDIE::Tag() const
|
|
{
|
|
if (m_die)
|
|
return m_die->Tag();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
const char *
|
|
DWARFDIE::GetTagAsCString () const
|
|
{
|
|
return lldb_private::DW_TAG_value_to_name (Tag());
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetParent () const
|
|
{
|
|
if (IsValid())
|
|
return DWARFDIE(m_cu, m_die->GetParent());
|
|
else
|
|
return DWARFDIE();
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetFirstChild () const
|
|
{
|
|
if (IsValid())
|
|
return DWARFDIE(m_cu, m_die->GetFirstChild());
|
|
else
|
|
return DWARFDIE();
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetSibling () const
|
|
{
|
|
if (IsValid())
|
|
return DWARFDIE(m_cu, m_die->GetSibling());
|
|
else
|
|
return DWARFDIE();
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetReferencedDIE (const dw_attr_t attr) const
|
|
{
|
|
const dw_offset_t die_offset = GetAttributeValueAsReference (attr, DW_INVALID_OFFSET);
|
|
if (die_offset != DW_INVALID_OFFSET)
|
|
return GetDIE(die_offset);
|
|
else
|
|
return DWARFDIE();
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetDIE (dw_offset_t die_offset) const
|
|
{
|
|
if (IsValid())
|
|
return m_cu->GetDIE(die_offset);
|
|
else
|
|
return DWARFDIE();
|
|
}
|
|
|
|
const char *
|
|
DWARFDIE::GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, fail_value);
|
|
else
|
|
return fail_value;
|
|
}
|
|
|
|
uint64_t
|
|
DWARFDIE::GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, fail_value);
|
|
else
|
|
return fail_value;
|
|
}
|
|
|
|
int64_t
|
|
DWARFDIE::GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, fail_value);
|
|
else
|
|
return fail_value;
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetAttributeValueAsReferenceDIE (const dw_attr_t attr) const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
DWARFCompileUnit *cu = GetCU();
|
|
SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF();
|
|
const bool check_specification_or_abstract_origin = true;
|
|
DWARFFormValue form_value;
|
|
if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
|
|
return dwarf->GetDIE(DIERef(form_value));
|
|
}
|
|
return DWARFDIE();
|
|
}
|
|
|
|
uint64_t
|
|
DWARFDIE::GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, fail_value);
|
|
else
|
|
return fail_value;
|
|
}
|
|
|
|
uint64_t
|
|
DWARFDIE::GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, fail_value);
|
|
else
|
|
return fail_value;
|
|
}
|
|
|
|
|
|
DWARFDIE
|
|
DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
SymbolFileDWARF *dwarf= GetDWARF();
|
|
DWARFCompileUnit *cu = GetCU();
|
|
DWARFDebugInfoEntry* function_die = nullptr;
|
|
DWARFDebugInfoEntry* block_die = nullptr;
|
|
if (m_die->LookupAddress (file_addr,
|
|
dwarf,
|
|
cu,
|
|
&function_die,
|
|
&block_die))
|
|
{
|
|
if (block_die && block_die != function_die)
|
|
{
|
|
if (cu->ContainsDIEOffset(block_die->GetOffset()))
|
|
return DWARFDIE(cu, block_die);
|
|
else
|
|
return DWARFDIE(dwarf->DebugInfo()->GetCompileUnit(DIERef(cu->GetOffset(), block_die->GetOffset())), block_die);
|
|
}
|
|
}
|
|
}
|
|
return DWARFDIE();
|
|
}
|
|
|
|
lldb::user_id_t
|
|
DWARFDIE::GetID () const
|
|
{
|
|
return GetDIERef().GetUID(GetDWARF());
|
|
}
|
|
|
|
const char *
|
|
DWARFDIE::GetName () const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetName (GetDWARF(), m_cu);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
const char *
|
|
DWARFDIE::GetMangledName () const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetMangledName (GetDWARF(), m_cu);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
const char *
|
|
DWARFDIE::GetPubname () const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetPubname (GetDWARF(), m_cu);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
const char *
|
|
DWARFDIE::GetQualifiedName (std::string &storage) const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetQualifiedName (GetDWARF(), m_cu, storage);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
lldb::LanguageType
|
|
DWARFDIE::GetLanguage () const
|
|
{
|
|
if (IsValid())
|
|
return m_cu->GetLanguageType();
|
|
else
|
|
return lldb::eLanguageTypeUnknown;
|
|
}
|
|
|
|
|
|
lldb::ModuleSP
|
|
DWARFDIE::GetModule () const
|
|
{
|
|
SymbolFileDWARF *dwarf = GetDWARF();
|
|
if (dwarf)
|
|
return dwarf->GetObjectFile()->GetModule();
|
|
else
|
|
return lldb::ModuleSP();
|
|
}
|
|
|
|
lldb_private::CompileUnit *
|
|
DWARFDIE::GetLLDBCompileUnit () const
|
|
{
|
|
if (IsValid())
|
|
return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
lldb_private::Type *
|
|
DWARFDIE::ResolveType () const
|
|
{
|
|
if (IsValid())
|
|
return GetDWARF()->ResolveType(*this, true);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
lldb_private::Type *
|
|
DWARFDIE::ResolveTypeUID (const DIERef &die_ref) const
|
|
{
|
|
SymbolFileDWARF *dwarf = GetDWARF();
|
|
if (dwarf)
|
|
return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
DWARFDIE::GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
DWARFDIE parent_decl_ctx_die = m_die->GetParentDeclContextDIE (GetDWARF(), GetCU());
|
|
if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE())
|
|
{
|
|
decl_context_dies.Append(parent_decl_ctx_die);
|
|
parent_decl_ctx_die.GetDeclContextDIEs (decl_context_dies);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
dwarf_decl_ctx.SetLanguage(GetLanguage());
|
|
m_die->GetDWARFDeclContext (GetDWARF(), GetCU(), dwarf_decl_ctx);
|
|
}
|
|
else
|
|
{
|
|
dwarf_decl_ctx.Clear();
|
|
}
|
|
}
|
|
|
|
void
|
|
DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const
|
|
{
|
|
const dw_tag_t tag = Tag();
|
|
if (tag == DW_TAG_compile_unit)
|
|
return;
|
|
DWARFDIE parent = GetParent();
|
|
if (parent)
|
|
parent.GetDWOContext(context);
|
|
switch (tag)
|
|
{
|
|
case DW_TAG_module:
|
|
context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
|
|
break;
|
|
case DW_TAG_namespace:
|
|
context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName())));
|
|
break;
|
|
case DW_TAG_structure_type:
|
|
context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName())));
|
|
break;
|
|
case DW_TAG_union_type:
|
|
context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
|
|
break;
|
|
case DW_TAG_class_type:
|
|
context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
|
|
break;
|
|
case DW_TAG_enumeration_type:
|
|
context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName())));
|
|
break;
|
|
case DW_TAG_subprogram:
|
|
context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname())));
|
|
break;
|
|
case DW_TAG_variable:
|
|
context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname())));
|
|
break;
|
|
case DW_TAG_typedef:
|
|
context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetParentDeclContextDIE () const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
|
|
else
|
|
return DWARFDIE();
|
|
}
|
|
|
|
|
|
dw_offset_t
|
|
DWARFDIE::GetOffset () const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetOffset();
|
|
else
|
|
return DW_INVALID_OFFSET;
|
|
}
|
|
|
|
dw_offset_t
|
|
DWARFDIE::GetCompileUnitRelativeOffset () const
|
|
{
|
|
if (IsValid())
|
|
return m_die->GetOffset() - m_cu->GetOffset();
|
|
else
|
|
return DW_INVALID_OFFSET;
|
|
}
|
|
|
|
SymbolFileDWARF *
|
|
DWARFDIE::GetDWARF () const
|
|
{
|
|
if (m_cu)
|
|
return m_cu->GetSymbolFileDWARF();
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
lldb_private::TypeSystem *
|
|
DWARFDIE::GetTypeSystem () const
|
|
{
|
|
if (m_cu)
|
|
return m_cu->GetTypeSystem();
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
DWARFASTParser *
|
|
DWARFDIE::GetDWARFParser () const
|
|
{
|
|
lldb_private::TypeSystem *type_system = GetTypeSystem ();
|
|
if (type_system)
|
|
return type_system->GetDWARFParser();
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
bool
|
|
DWARFDIE::IsStructOrClass () const
|
|
{
|
|
const dw_tag_t tag = Tag();
|
|
return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
|
|
}
|
|
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetContainingDWOModuleDIE () const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
DWARFDIE top_module_die;
|
|
// Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so
|
|
for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent())
|
|
{
|
|
const dw_tag_t tag = parent.Tag();
|
|
if (tag == DW_TAG_module)
|
|
top_module_die = parent;
|
|
else if (tag == DW_TAG_compile_unit)
|
|
break;
|
|
}
|
|
|
|
return top_module_die;
|
|
}
|
|
return DWARFDIE();
|
|
}
|
|
|
|
lldb::ModuleSP
|
|
DWARFDIE::GetContainingDWOModule () const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
|
|
|
|
if (dwo_module_die)
|
|
{
|
|
const char *module_name = dwo_module_die.GetName();
|
|
if (module_name)
|
|
return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name));
|
|
}
|
|
}
|
|
return lldb::ModuleSP();
|
|
}
|
|
|
|
bool
|
|
DWARFDIE::HasChildren () const
|
|
{
|
|
if (m_die)
|
|
return m_die->HasChildren();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type () const
|
|
{
|
|
if (IsValid())
|
|
return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
size_t
|
|
DWARFDIE::GetAttributes (DWARFAttributes &attributes, uint32_t depth) const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
return m_die->GetAttributes (m_cu,
|
|
m_cu->GetFixedFormSizes(),
|
|
attributes,
|
|
depth);
|
|
}
|
|
if (depth == 0)
|
|
attributes.Clear();
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool
|
|
DWARFDIE::GetDIENamesAndRanges (const char * &name,
|
|
const char * &mangled,
|
|
DWARFRangeList& ranges,
|
|
int& decl_file,
|
|
int& decl_line,
|
|
int& decl_column,
|
|
int& call_file,
|
|
int& call_line,
|
|
int& call_column,
|
|
lldb_private::DWARFExpression *frame_base) const
|
|
{
|
|
if (IsValid())
|
|
{
|
|
return m_die->GetDIENamesAndRanges (GetDWARF(),
|
|
GetCU(),
|
|
name,
|
|
mangled,
|
|
ranges,
|
|
decl_file,
|
|
decl_line,
|
|
decl_column,
|
|
call_file,
|
|
call_line,
|
|
call_column,
|
|
frame_base);
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
void
|
|
DWARFDIE::Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const
|
|
{
|
|
if (s && IsValid())
|
|
m_die->Dump (GetDWARF(), GetCU(), *s, recurse_depth);
|
|
}
|
|
|
|
|
|
CompilerDecl
|
|
DWARFDIE::GetDecl () const
|
|
{
|
|
DWARFASTParser *dwarf_ast = GetDWARFParser();
|
|
if (dwarf_ast)
|
|
return dwarf_ast->GetDeclForUIDFromDWARF(*this);
|
|
else
|
|
return CompilerDecl();
|
|
}
|
|
|
|
CompilerDeclContext
|
|
DWARFDIE::GetDeclContext () const
|
|
{
|
|
DWARFASTParser *dwarf_ast = GetDWARFParser();
|
|
if (dwarf_ast)
|
|
return dwarf_ast->GetDeclContextForUIDFromDWARF(*this);
|
|
else
|
|
return CompilerDeclContext();
|
|
}
|
|
|
|
CompilerDeclContext
|
|
DWARFDIE::GetContainingDeclContext () const
|
|
{
|
|
DWARFASTParser *dwarf_ast = GetDWARFParser();
|
|
if (dwarf_ast)
|
|
return dwarf_ast->GetDeclContextContainingUIDFromDWARF(*this);
|
|
else
|
|
return CompilerDeclContext();
|
|
}
|
|
|
|
bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs)
|
|
{
|
|
return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
|
|
}
|
|
|
|
bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs)
|
|
{
|
|
return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU();
|
|
}
|
|
|
|
|