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: 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: 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> &base_classes, std::vector &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 &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->GetAbsolutePath().GetPath(); + return ""; +} + 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( 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> bases; std::vector member_accessibilities; bool is_a_class = false; @@ -1974,7 +1974,7 @@ std::vector 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 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> &base_classes, std::vector &member_accessibilities, std::vector &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 &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 &function_param_types, std::vector &function_param_decls, unsigned &type_quals) { if (!parent_die) 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/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/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/DWARFUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -141,8 +141,9 @@ const DWARFAbbreviationDeclarationSet *GetAbbreviations() const; dw_offset_t GetAbbrevOffset() const; uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); } - dw_addr_t GetBaseAddress() const { return m_base_addr; } dw_addr_t GetAddrBase() const { return m_addr_base; } + dw_addr_t GetBaseAddress() const { return m_base_addr; } + dw_offset_t GetLineTableOffset(); dw_addr_t GetRangesBase() const { return m_ranges_base; } dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; } void SetAddrBase(dw_addr_t addr_base); @@ -196,6 +197,7 @@ bool GetIsOptimized(); const lldb_private::FileSpec &GetCompilationDirectory(); + const lldb_private::FileSpec &GetAbsolutePath(); 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,11 +280,16 @@ lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown; lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; llvm::Optional m_comp_dir; + llvm::Optional 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; + + /// Value of DW_AT_stmt_list. + dw_offset_t m_line_table_offset = DW_INVALID_OFFSET; + dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. const DIERef::Section m_section; @@ -293,6 +301,7 @@ void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); void ComputeCompDirAndGuessPathStyle(); + void ComputeAbsolutePath(); 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 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 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::GetAbsolutePath() { + if (!m_file_spec) + ComputeAbsolutePath(); + 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::ComputeAbsolutePath() { + 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/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 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 + 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(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::getEmptyKey() || + offset == llvm::DenseMapInfo::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);