labath updated this revision to Diff 203790. labath marked 13 inline comments as done. labath added a comment.
- Implement code review suggestions (except the Die::GetName, and return {}) - Add a test for the error message which is printed when we encounter an incomplete class (this is motivated by the bug in the printing of the name of the compile unit) CHANGES SINCE LAST ACTION https://reviews.llvm.org/D62894/new/ https://reviews.llvm.org/D62894 Files: lit/SymbolFile/DWARF/debug-types-line-tables.s lit/SymbolFile/DWARF/forward-declarations.s source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp source/Plugins/SymbolFile/DWARF/DWARFUnit.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -49,6 +49,7 @@ class DWARFDebugRangesBase; class DWARFDeclContext; class DWARFFormValue; +class DWARFTypeUnit; class SymbolFileDWARFDebugMap; class SymbolFileDWARFDwo; class SymbolFileDWARFDwp; @@ -299,6 +300,8 @@ lldb_private::DWARFContext &GetDWARFContext() { return m_context; } + lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx); + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; @@ -438,6 +441,8 @@ SymbolFileDWARFDwp *GetDwpSymbolFile(); + const lldb_private::FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; @@ -476,6 +481,8 @@ DIEToVariableSP m_die_to_variable_sp; DIEToClangType m_forward_decl_die_to_clang_type; ClangTypeToDIE m_forward_decl_clang_type_to_die; + llvm::DenseMap<dw_offset_t, lldb_private::FileSpecList> + m_type_unit_support_files; }; #endif // SymbolFileDWARF_SymbolFileDWARF_h_ Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -54,6 +54,7 @@ #include "AppleDWARFIndex.h" #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" @@ -62,6 +63,7 @@ #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" #include "DWARFFormValue.h" +#include "DWARFTypeUnit.h" #include "DWARFUnit.h" #include "DebugNamesDWARFIndex.h" #include "LogChannelDWARF.h" @@ -775,26 +777,55 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { ASSERT_MODULE_LOCK(this); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); - if (dwarf_cu) { - const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly(); - - if (cu_die) { - const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned( - DW_AT_stmt_list, DW_INVALID_OFFSET); - if (stmt_list != DW_INVALID_OFFSET) { - // All file indexes in DWARF are one based and a file of index zero is - // supposed to be the compile unit itself. - support_files.Append(comp_unit); - return DWARFDebugLine::ParseSupportFiles( - comp_unit.GetModule(), m_context.getOrLoadLineData(), stmt_list, - support_files, dwarf_cu); - } + DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit); + if (auto *tu = llvm::dyn_cast_or_null<DWARFTypeUnit>(unit)) { + support_files = GetTypeUnitSupportFiles(*tu); + return true; + } + + if (unit) { + const dw_offset_t stmt_list = unit->GetLineTableOffset(); + if (stmt_list != DW_INVALID_OFFSET) { + // All file indexes in DWARF are one based and a file of index zero is + // supposed to be the compile unit itself. + support_files.Append(comp_unit); + return DWARFDebugLine::ParseSupportFiles(comp_unit.GetModule(), + m_context.getOrLoadLineData(), + stmt_list, support_files, unit); } } return false; } +FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { + if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(&unit)) + return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx); + return FileSpec(); +} + +const FileSpecList & +SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { + static FileSpecList empty_list; + + dw_offset_t offset = tu.GetLineTableOffset(); + if (offset == DW_INVALID_OFFSET || + offset == llvm::DenseMapInfo<dw_offset_t>::getEmptyKey() || + offset == llvm::DenseMapInfo<dw_offset_t>::getTombstoneKey()) + return empty_list; + + // Many type units can share a line table, so parse the support file list + // once, and cache it based on the offset field. + auto iter_bool = m_type_unit_support_files.try_emplace(offset); + FileSpecList &list = iter_bool.first->second; + if (iter_bool.second) { + list.Append(FileSpec()); + DWARFDebugLine::ParseSupportFiles(GetObjectFile()->GetModule(), + m_context.getOrLoadLineData(), offset, + list, &tu); + } + return list; +} + bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { ASSERT_MODULE_LOCK(this); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -145,6 +145,7 @@ dw_addr_t GetAddrBase() const { return m_addr_base; } dw_addr_t GetRangesBase() const { return m_ranges_base; } dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; } + dw_offset_t GetLineTableOffset(); void SetAddrBase(dw_addr_t addr_base); void SetRangesBase(dw_addr_t ranges_base); void SetBaseObjOffset(dw_offset_t base_obj_offset); @@ -196,6 +197,7 @@ bool GetIsOptimized(); const lldb_private::FileSpec &GetCompilationDirectory(); + const lldb_private::FileSpec &GetFileSpec(); lldb_private::FileSpec::Style GetPathStyle(); SymbolFileDWARFDwo *GetDwoSymbolFile() const; @@ -210,6 +212,7 @@ DIERef::Section GetDebugSection() const { return m_section; } uint8_t GetUnitType() const { return m_header.GetUnitType(); } + bool IsTypeUnit() const { return m_header.IsTypeUnit(); } /// Return a list of address ranges resulting from a (possibly encoded) /// range list starting at a given offset in the appropriate ranges section. @@ -277,12 +280,15 @@ lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown; lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; llvm::Optional<lldb_private::FileSpec> m_comp_dir; + llvm::Optional<lldb_private::FileSpec> m_file_spec; dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base // If this is a dwo compile unit this is the offset of the base compile unit // in the main object file dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. + dw_offset_t m_line_table_offset = + DW_INVALID_OFFSET; // Value of DW_AT_stmt_list. const DIERef::Section m_section; private: @@ -293,6 +299,7 @@ void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); void ComputeCompDirAndGuessPathStyle(); + void ComputeFileSpec(); DISALLOW_COPY_AND_ASSIGN(DWARFUnit); }; Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -283,24 +283,47 @@ // m_die_array_mutex must be already held as read/write. void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { - dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned( - this, DW_AT_addr_base, LLDB_INVALID_ADDRESS); - if (addr_base != LLDB_INVALID_ADDRESS) - SetAddrBase(addr_base); - - dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( - this, DW_AT_rnglists_base, LLDB_INVALID_ADDRESS); - if (ranges_base != LLDB_INVALID_ADDRESS) - SetRangesBase(ranges_base); - - SetStrOffsetsBase( - cu_die.GetAttributeValueAsUnsigned(this, DW_AT_str_offsets_base, 0)); - - uint64_t base_addr = cu_die.GetAttributeValueAsAddress(this, DW_AT_low_pc, - LLDB_INVALID_ADDRESS); - if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = cu_die.GetAttributeValueAsAddress(this, DW_AT_entry_pc, 0); - SetBaseAddress(base_addr); + llvm::Optional<uint64_t> addr_base, gnu_addr_base, ranges_base, + gnu_ranges_base; + + DWARFAttributes attributes; + size_t num_attributes = cu_die.GetAttributes(this, attributes); + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(i, form_value)) + continue; + switch (attr) { + case DW_AT_addr_base: + addr_base = form_value.Unsigned(); + SetAddrBase(*addr_base); + break; + case DW_AT_rnglists_base: + ranges_base = form_value.Unsigned(); + SetRangesBase(*ranges_base); + break; + case DW_AT_str_offsets_base: + SetStrOffsetsBase(form_value.Unsigned()); + break; + case DW_AT_low_pc: + SetBaseAddress(form_value.Address()); + break; + case DW_AT_entry_pc: + // If the value was already set by DW_AT_low_pc, don't update it. + if (m_base_addr == LLDB_INVALID_ADDRESS) + SetBaseAddress(form_value.Address()); + break; + case DW_AT_stmt_list: + m_line_table_offset = form_value.Unsigned(); + break; + case DW_AT_GNU_addr_base: + gnu_addr_base = form_value.Unsigned(); + break; + case DW_AT_GNU_ranges_base: + gnu_ranges_base = form_value.Unsigned(); + break; + } + } std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); @@ -331,18 +354,17 @@ // attributes which were applicable to the DWO units. The corresponding // DW_AT_* attributes standardized in DWARF v5 are also applicable to the main // unit in contrast. - if (addr_base == LLDB_INVALID_ADDRESS) - addr_base = - cu_die.GetAttributeValueAsUnsigned(this, DW_AT_GNU_addr_base, 0); - dwo_cu->SetAddrBase(addr_base); + if (addr_base) + dwo_cu->SetAddrBase(*addr_base); + else if (gnu_addr_base) + dwo_cu->SetAddrBase(*gnu_addr_base); - if (ranges_base == LLDB_INVALID_ADDRESS) - ranges_base = - cu_die.GetAttributeValueAsUnsigned(this, DW_AT_GNU_ranges_base, 0); - dwo_cu->SetRangesBase(ranges_base); + if (ranges_base) + dwo_cu->SetRangesBase(*ranges_base); + else if (gnu_ranges_base) + dwo_cu->SetRangesBase(*gnu_ranges_base); dwo_cu->SetBaseObjOffset(GetOffset()); - SetDwoStrOffsetsBase(dwo_cu); } @@ -387,6 +409,11 @@ return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; } +dw_offset_t DWARFUnit::GetLineTableOffset() { + ExtractUnitDIEIfNeeded(); + return m_line_table_offset; +} + void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { @@ -611,6 +638,12 @@ return *m_comp_dir; } +const FileSpec &DWARFUnit::GetFileSpec() { + if (!m_file_spec) + ComputeFileSpec(); + return *m_file_spec; +} + // DWARF2/3 suggests the form hostname:pathname for compilation directory. // Remove the host part if present. static llvm::StringRef @@ -670,6 +703,20 @@ } } +void DWARFUnit::ComputeFileSpec() { + m_file_spec = FileSpec(); + const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); + if (!die) + return; + + m_file_spec = + FileSpec(die->GetAttributeValueAsString(this, DW_AT_name, nullptr), + GetPathStyle()); + + if (m_file_spec->IsRelative()) + m_file_spec->MakeAbsolute(GetCompilationDirectory()); +} + SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { return m_dwo_symbol_file.get(); } Index: source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h @@ -22,9 +22,7 @@ dw_offset_t GetTypeOffset() { return GetOffset() + m_header.GetTypeOffset(); } - static bool classof(const DWARFUnit *unit) { - return unit->GetUnitType() == DW_UT_type; - } + static bool classof(const DWARFUnit *unit) { return unit->IsTypeUnit(); } private: DWARFTypeUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -18,6 +18,8 @@ void Dump(lldb_private::Stream *s) const override; + static bool classof(const DWARFUnit *unit) { return !unit->IsTypeUnit(); } + private: DWARFCompileUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, Index: source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -101,8 +101,6 @@ lldb::ModuleSP GetModule() const; - lldb_private::CompileUnit *GetLLDBCompileUnit() const; - // Getting attribute values from the DIE. // // GetAttributeValueAsXXX() functions should only be used if you are Index: source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -90,13 +90,6 @@ return lldb::ModuleSP(); } -lldb_private::CompileUnit *DWARFBaseDIE::GetLLDBCompileUnit() const { - if (IsValid()) - return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU()); - else - return nullptr; -} - dw_offset_t DWARFBaseDIE::GetOffset() const { if (IsValid()) return m_die->GetOffset(); Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -81,8 +81,7 @@ &template_param_infos); bool ParseChildMembers( - const lldb_private::SymbolContext &sc, const DWARFDIE &die, - lldb_private::CompilerType &class_compiler_type, + const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, const lldb::LanguageType class_language, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, std::vector<int> &member_accessibilities, @@ -92,8 +91,7 @@ lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t - ParseChildParameters(lldb_private::CompileUnit &comp_unit, - clang::DeclContext *containing_decl_ctx, + ParseChildParameters(clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die, bool skip_artificial, bool &is_static, bool &is_variadic, bool &has_template_params, @@ -101,8 +99,7 @@ std::vector<clang::ParmVarDecl *> &function_param_decls, unsigned &type_quals); - size_t ParseChildEnumerators(const lldb_private::SymbolContext &sc, - lldb_private::CompilerType &compiler_type, + size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type, bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die); Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -233,7 +233,7 @@ /// Some attributes are relevant for all kinds of types (declaration), while /// others are only meaningful to a specific type (is_virtual) struct ParsedTypeAttributes { - ParsedTypeAttributes(const DWARFDIE &die, CompileUnit &comp_unit); + explicit ParsedTypeAttributes(const DWARFDIE &die); AccessType accessibility = eAccessNone; bool is_artificial = false; @@ -263,8 +263,7 @@ }; } // namespace -ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die, - CompileUnit &comp_unit) { +ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) { DWARFAttributes attributes; size_t num_attributes = die.GetAttributes(attributes); for (size_t i = 0; i < num_attributes; ++i) { @@ -306,8 +305,8 @@ break; case DW_AT_decl_file: - decl.SetFile(comp_unit.GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); + decl.SetFile( + die.GetDWARF()->GetFile(*die.GetCU(), form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); @@ -385,6 +384,12 @@ } } +static std::string GetUnitName(const DWARFDIE &die) { + if (DWARFUnit *unit = die.GetCU()) + return unit->GetFileSpec().GetPath(); + return "<missing DWARF unit path>"; +} + TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, const DWARFDIE &die, Log *log, bool *type_is_new_ptr) { @@ -416,7 +421,7 @@ // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - ParsedTypeAttributes attrs(die, *sc.comp_unit); + ParsedTypeAttributes attrs(die); if (DWARFDIE signature_die = attrs.signature.Reference()) { if (TypeSP type_sp = @@ -1107,10 +1112,9 @@ if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { if (die.HasChildren()) { - SymbolContext cu_sc(die.GetLLDBCompileUnit()); bool is_signed = false; enumerator_clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(cu_sc, clang_type, is_signed, + ParseChildEnumerators(clang_type, is_signed, type_sp->GetByteSize().getValueOr(0), die); } ClangASTContext::CompleteTagDeclarationDefinition(clang_type); @@ -1174,10 +1178,10 @@ if (die.HasChildren()) { bool skip_artificial = true; - ParseChildParameters(*sc.comp_unit, containing_decl_ctx, die, - skip_artificial, is_static, is_variadic, - has_template_params, function_param_types, - function_param_decls, type_quals); + ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static, + is_variadic, has_template_params, + function_param_types, function_param_decls, + type_quals); } bool ignore_containing_context = false; @@ -1464,8 +1468,6 @@ if (attrs.abstract_origin.IsValid()) { DWARFDIE abs_die = attrs.abstract_origin.Reference(); - SymbolContext sc; - if (dwarf->ResolveType(abs_die)) { function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( GetCachedClangDeclContextForDIE(abs_die)); @@ -1574,9 +1576,7 @@ "file a bug against the compiler and include the " "preprocessed output for %s", die.GetOffset(), type_die_ref.die_offset, - die.GetLLDBCompileUnit() - ? die.GetLLDBCompileUnit()->GetPath().c_str() - : "the source file"); + GetUnitName(die).c_str()); } // We have no choice other than to pretend that the element class @@ -1665,7 +1665,8 @@ sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); if (symbol_context_scope == NULL) symbol_context_scope = sc.function; - } + } else + symbol_context_scope = sc.module_sp.get(); if (symbol_context_scope != NULL) { type_sp->SetSymbolContextScope(symbol_context_scope); @@ -1966,7 +1967,6 @@ default_accessibility = eAccessPrivate; } - SymbolContext sc(die.GetLLDBCompileUnit()); std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; std::vector<int> member_accessibilities; bool is_a_class = false; @@ -1974,7 +1974,7 @@ std::vector<DWARFDIE> member_function_dies; DelayedPropertyList delayed_properties; - ParseChildMembers(sc, die, clang_type, class_language, bases, + ParseChildMembers(die, clang_type, class_language, bases, member_accessibilities, member_function_dies, delayed_properties, default_accessibility, is_a_class, layout_info); @@ -2165,10 +2165,9 @@ case DW_TAG_enumeration_type: if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { if (die.HasChildren()) { - SymbolContext sc(die.GetLLDBCompileUnit()); bool is_signed = false; clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(sc, clang_type, is_signed, + ParseChildEnumerators(clang_type, is_signed, type->GetByteSize().getValueOr(0), die); } ClangASTContext::CompleteTagDeclarationDefinition(clang_type); @@ -2218,8 +2217,8 @@ } size_t DWARFASTParserClang::ParseChildEnumerators( - const SymbolContext &sc, lldb_private::CompilerType &clang_type, - bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die) { + lldb_private::CompilerType &clang_type, bool is_signed, + uint32_t enumerator_byte_size, const DWARFDIE &parent_die) { if (!parent_die) return 0; @@ -2258,8 +2257,8 @@ case DW_AT_description: default: case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); + decl.SetFile( + die.GetDWARF()->GetFile(*die.GetCU(), form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); @@ -2393,9 +2392,9 @@ clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); - ParseChildParameters(comp_unit, containing_decl_ctx, die, true, - is_static, is_variadic, has_template_params, - param_types, param_decls, type_quals); + ParseChildParameters(containing_decl_ctx, die, true, is_static, + is_variadic, has_template_params, param_types, + param_decls, type_quals); sstr << "("; for (size_t i = 0; i < param_types.size(); i++) { if (i > 0) @@ -2415,9 +2414,9 @@ FunctionSP func_sp; std::unique_ptr<Declaration> decl_up; if (decl_file != 0 || decl_line != 0 || decl_column != 0) - decl_up.reset(new Declaration( - comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file), - decl_line, decl_column)); + decl_up.reset( + new Declaration(die.GetDWARF()->GetFile(*die.GetCU(), decl_file), + decl_line, decl_column)); SymbolFileDWARF *dwarf = die.GetDWARF(); // Supply the type _only_ if it has already been parsed @@ -2446,8 +2445,8 @@ } bool DWARFASTParserClang::ParseChildMembers( - const SymbolContext &sc, const DWARFDIE &parent_die, - CompilerType &class_clang_type, const LanguageType class_language, + const DWARFDIE &parent_die, CompilerType &class_clang_type, + const LanguageType class_language, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, std::vector<int> &member_accessibilities, std::vector<DWARFDIE> &member_function_dies, @@ -2706,13 +2705,12 @@ ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); objfile->GetModule()->ReportWarning( "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid " - "bit offset (0x%8.8" PRIx64 + "bit offset (0x%8.8" PRIx64 ") member will be ignored. Please file a bug against the " "compiler and include the preprocessed output for %s\n", die.GetID(), DW_TAG_value_to_name(tag), name, this_field_info.bit_offset, - sc.comp_unit ? sc.comp_unit->GetPath().c_str() - : "the source file"); + GetUnitName(parent_die).c_str()); this_field_info.Clear(); continue; } @@ -2865,9 +2863,7 @@ "complete definition.\nPlease file a bug against the " "compiler and include the preprocessed output for %s", parent_die.GetOffset(), parent_die.GetName(), - die.GetOffset(), name, - sc.comp_unit ? sc.comp_unit->GetPath().c_str() - : "the source file"); + die.GetOffset(), name, GetUnitName(parent_die).c_str()); // We have no choice other than to pretend that the member // class is complete. If we don't do this, clang will crash // when trying to layout the class. Since we provide layout @@ -3064,10 +3060,9 @@ } size_t DWARFASTParserClang::ParseChildParameters( - CompileUnit &comp_unit, clang::DeclContext *containing_decl_ctx, - const DWARFDIE &parent_die, bool skip_artificial, bool &is_static, - bool &is_variadic, bool &has_template_params, - std::vector<CompilerType> &function_param_types, + clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die, + bool skip_artificial, bool &is_static, bool &is_variadic, + bool &has_template_params, std::vector<CompilerType> &function_param_types, std::vector<clang::ParmVarDecl *> &function_param_decls, unsigned &type_quals) { if (!parent_die) Index: lit/SymbolFile/DWARF/forward-declarations.s =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/forward-declarations.s @@ -0,0 +1,108 @@ +# Test handling of the situation (including the error message) where a structure +# has a incomplete member. +# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t +# RUN: %lldb %t -o "target var b" -b 2>&1 | FileCheck %s + +# CHECK: error: {{.*}} DWARF DIE at 0x0000002b (class B) has a member variable 0x00000030 (a) whose type is a forward declaration, not a complete definition. +# CHECK-NEXT: Please file a bug against the compiler and include the preprocessed output for /tmp/a.cc + +# CHECK: b = (a = A @ 0x0000000000000001) + + .type b,@object # @b + .comm b,1,1 + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Hand-written DWARF" +.Lcu_name: + .asciz "/tmp/a.cc" +.Lcu_compdir: + .asciz "/foo/bar" +.Lb: + .asciz "b" +.La: + .asciz "a" +.LA: + .asciz "A" +.LB: + .asciz "B" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x46 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .long .Lcu_name # DW_AT_name + .long .Lcu_compdir # DW_AT_comp_dir + .byte 2 # Abbrev [2] 0x1e:0x15 DW_TAG_variable + .long .Lb # DW_AT_name + .long .LB_die-.Lcu_begin0 # DW_AT_type + .byte 9 # DW_AT_location + .byte 3 + .quad b +.LB_die: + .byte 3 # Abbrev [3] 0x33:0x15 DW_TAG_structure_type + .long .LB # DW_AT_name + .byte 4 # Abbrev [4] 0x3b:0xc DW_TAG_member + .long .La # DW_AT_name + .long .LA_die-.Lcu_begin0 # DW_AT_type + .byte 0 # End Of Children Mark +.LA_die: + .byte 5 # Abbrev [5] 0x48:0x8 DW_TAG_structure_type + # DW_AT_declaration + .long .LA # DW_AT_name + .byte 0 # End Of Children Mark +.Ldebug_info_end0: Index: lit/SymbolFile/DWARF/debug-types-line-tables.s =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/debug-types-line-tables.s @@ -0,0 +1,183 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %s -o %t +# RUN: lldb-test symbols %t | FileCheck %s + + .file 1 "/tmp" "b.cc" + + .section .debug_types,"",@progbits + +# CHECK: Types: +# Type unit one: "struct A" defined at b.cc:1 +# CHECK-DAG: name = "A", size = 4, decl = b.cc:1 +1: + .long 4f-2f # Length of Unit +2: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5390450678491038984 # Type Signature + .long 3f-1b # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x1b DW_TAG_type_unit + .short 4 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list +3: + .byte 2 # Abbrev [2] 0x1e:0xc DW_TAG_structure_type + .long .LA # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 0 # End Of Children Mark +4: + +# Type unit two: "struct B" defined at b.cc:2 +# It shares the same line table as unit one. +# CHECK-DAG: name = "B", size = 4, decl = b.cc:2 +1: + .long 4f-2f # Length of Unit +2: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5390450678491038985 # Type Signature + .long 3f-1b # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x1b DW_TAG_type_unit + .short 4 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list +3: + .byte 2 # Abbrev [2] 0x1e:0xc DW_TAG_structure_type + .long .LB # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # End Of Children Mark +4: + +# Type unit three: "struct C". +# DW_AT_stmt_list missing +# CHECK-DAG: name = "C", size = 4, line = 3 +1: + .long 4f-2f # Length of Unit +2: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5390450678491038986 # Type Signature + .long 3f-1b # Type DIE Offset + .byte 4 # Abbrev [4] 0x17:0x1b DW_TAG_type_unit + .short 4 # DW_AT_language +3: + .byte 2 # Abbrev [2] 0x1e:0xc DW_TAG_structure_type + .long .LC # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 0 # End Of Children Mark +4: + +# Type unit four: "struct D". +# DW_AT_stmt_list invalid +# CHECK-DAG: name = "D", size = 4, line = 4 +1: + .long 4f-2f # Length of Unit +2: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5390450678491038987 # Type Signature + .long 3f-1b # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x1b DW_TAG_type_unit + .short 4 # DW_AT_language + .long .Lline_table_start0+47 # DW_AT_stmt_list +3: + .byte 2 # Abbrev [2] 0x1e:0xc DW_TAG_structure_type + .long .LD # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 0 # End Of Children Mark +4: + +# Type unit five: "struct E". +# DW_AT_decl_file invalid +# CHECK-DAG: name = "E", size = 4, line = 5 +1: + .long 4f-2f # Length of Unit +2: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5390450678491038988 # Type Signature + .long 3f-1b # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x1b DW_TAG_type_unit + .short 4 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list +3: + .byte 2 # Abbrev [2] 0x1e:0xc DW_TAG_structure_type + .long .LE # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 47 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 0 # End Of Children Mark +4: + + + .section .debug_str,"MS",@progbits,1 +.LA: + .asciz "A" +.LB: + .asciz "B" +.LC: + .asciz "C" +.LD: + .asciz "D" +.LE: + .asciz "E" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 4 # Abbrev [4] 0xb:0x32 DW_TAG_compile_unit + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + + .section .debug_line,"",@progbits +.Lline_table_start0:
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits