
Summary: When searching for methods only, we need to do extra work to make sure the functions we get from the apple tables are indeed methods. Previously we were resolving the DIE into a SymbolContext and then checked whether the enclosing CompilerDeclContext is a class (or struct, or union). This patch changes that to operate on the debug info directly. This should be: - simpler - faster - more consistent with the ManualDWARFIndex (which does the same check, only at indexing time). What we lose this ways is for the language plugin to have a say in what it considers to be a "class", but that's probably more flexibility than we need (and if we really wanted to do that in the future, we could implement a more direct way to consult the plugin about this). This also fixes the find-method-local-struct test, which was failing because we were not able to construct a CompilerDeclContext for a local struct correctly. As a drive-by, I rename the DWARFDIE's IsStructClassOrUnion method to match the name on the CompilerDeclContext class. Reviewers: clayborg, JDevlieghere Subscribers: aprantl, lldb-commits Differential Revision: https://reviews.llvm.org/D47470 llvm-svn: 333878
308 lines
8.7 KiB
C++
308 lines
8.7 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 "DWARFDIECollection.h"
|
|
#include "DWARFDebugInfo.h"
|
|
#include "DWARFDebugInfoEntry.h"
|
|
#include "DWARFDeclContext.h"
|
|
#include "DWARFUnit.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
void DWARFDIE::ElaboratingDIEIterator::Next() {
|
|
assert(!m_worklist.empty() && "Incrementing end iterator?");
|
|
|
|
// Pop the current item from the list.
|
|
DWARFDIE die = m_worklist.back();
|
|
m_worklist.pop_back();
|
|
|
|
// And add back any items that elaborate it.
|
|
for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
|
|
if (DWARFDIE d = die.GetReferencedDIE(attr))
|
|
if (m_seen.insert(die.GetID()).second)
|
|
m_worklist.push_back(d);
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
|
|
if (IsValid()) {
|
|
DWARFUnit *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();
|
|
}
|
|
|
|
DWARFDIE
|
|
DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
|
|
if (IsValid()) {
|
|
SymbolFileDWARF *dwarf = GetDWARF();
|
|
DWARFUnit *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();
|
|
}
|
|
|
|
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_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 || tag == DW_TAG_partial_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();
|
|
}
|
|
|
|
bool DWARFDIE::IsStructUnionOrClass() const {
|
|
const dw_tag_t tag = Tag();
|
|
return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
|
|
tag == DW_TAG_union_type;
|
|
}
|
|
|
|
bool DWARFDIE::IsMethod() const {
|
|
for (DWARFDIE d: elaborating_dies())
|
|
if (d.GetParent().IsStructUnionOrClass())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
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 || tag == DW_TAG_partial_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::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;
|
|
}
|
|
|
|
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();
|
|
}
|