| //===-- 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(); |
| } |
| |
| |