Index: lld/ELF/DWARF.h =================================================================== --- lld/ELF/DWARF.h +++ lld/ELF/DWARF.h @@ -11,6 +11,7 @@ #define LLD_ELF_DWARF_H #include "InputFiles.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Object/ELF.h" @@ -27,8 +28,9 @@ public: explicit LLDDwarfObj(ObjFile *Obj); - const llvm::DWARFSection &getInfoSection() const override { - return InfoSection; + void forEachInfoSections( + llvm::function_ref F) const override { + F(InfoSection); } const llvm::DWARFSection &getRangeSection() const override { Index: llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -33,7 +33,8 @@ virtual ArrayRef getSectionNames() const { return {}; } virtual bool isLittleEndian() const = 0; virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); } - virtual const DWARFSection &getInfoSection() const { return Dummy; } + virtual void + forEachInfoSections(function_ref F) const {} virtual void forEachTypesSections(function_ref F) const {} virtual StringRef getAbbrevSection() const { return ""; } @@ -53,7 +54,8 @@ virtual StringRef getGnuPubNamesSection() const { return ""; } virtual StringRef getGnuPubTypesSection() const { return ""; } virtual const DWARFSection &getStringOffsetSection() const { return Dummy; } - virtual const DWARFSection &getInfoDWOSection() const { return Dummy; } + virtual void + forEachInfoDWOSections(function_ref F) const {} virtual void forEachTypesDWOSections(function_ref F) const {} virtual StringRef getAbbrevDWOSection() const { return ""; } Index: llvm/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -355,20 +355,22 @@ DObj->getAbbrevDWOSection())) getDebugAbbrevDWO()->dump(OS); - auto dumpDebugInfo = [&](unit_iterator_range Units) { - if (DumpOffset) - getDIEForOffset(DumpOffset.getValue()) - .dump(OS, 0, DumpOpts.noImplicitRecursion()); + auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) { + OS << '\n' << Name << " contents:\n"; + if (DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) + for (const auto &U : Units) + U->getDIEForOffset(DumpOffset.getValue()) + .dump(OS, 0, DumpOpts.noImplicitRecursion()); else for (const auto &U : Units) U->dump(OS, DumpOpts); }; - if (shouldDump(Explicit, ".debug_info", DIDT_ID_DebugInfo, - DObj->getInfoSection().Data)) - dumpDebugInfo(info_section_units()); - if (shouldDump(ExplicitDWO, ".debug_info.dwo", DIDT_ID_DebugInfo, - DObj->getInfoDWOSection().Data)) - dumpDebugInfo(dwo_info_section_units()); + if ((DumpType & DIDT_DebugInfo)) { + if (Explicit || getNumCompileUnits()) + dumpDebugInfo(".debug_info", info_section_units()); + if (ExplicitDWO || getNumDWOCompileUnits()) + dumpDebugInfo(".debug_info.dwo", dwo_info_section_units()); + } auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) { OS << '\n' << Name << " contents:\n"; @@ -874,7 +876,9 @@ void DWARFContext::parseNormalUnits() { if (!NormalUnits.empty()) return; - NormalUnits.addUnitsForSection(*this, DObj->getInfoSection(), DW_SECT_INFO); + DObj->forEachInfoSections([&](const DWARFSection &S) { + NormalUnits.addUnitsForSection(*this, S, DW_SECT_INFO); + }); NormalUnits.finishedInfoUnits(); DObj->forEachTypesSections([&](const DWARFSection &S) { NormalUnits.addUnitsForSection(*this, S, DW_SECT_TYPES); @@ -884,8 +888,9 @@ void DWARFContext::parseDWOUnits(bool Lazy) { if (!DWOUnits.empty()) return; - DWOUnits.addUnitsForDWOSection(*this, DObj->getInfoDWOSection(), DW_SECT_INFO, - Lazy); + DObj->forEachInfoDWOSections([&](const DWARFSection &S) { + DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_INFO, Lazy); + }); DWOUnits.finishedInfoUnits(); DObj->forEachTypesDWOSections([&](const DWARFSection &S) { DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_TYPES, Lazy); @@ -1237,20 +1242,20 @@ const object::ObjectFile *Obj = nullptr; std::vector SectionNames; - using TypeSectionMap = MapVector>; - TypeSectionMap TypesSections; - TypeSectionMap TypesDWOSections; + InfoSectionMap InfoSections; + InfoSectionMap TypesSections; + InfoSectionMap InfoDWOSections; + InfoSectionMap TypesDWOSections; - DWARFSectionMap InfoSection; DWARFSectionMap LocSection; DWARFSectionMap LocListsSection; DWARFSectionMap LineSection; DWARFSectionMap RangeSection; DWARFSectionMap RnglistsSection; DWARFSectionMap StringOffsetSection; - DWARFSectionMap InfoDWOSection; DWARFSectionMap LineDWOSection; DWARFSectionMap LocDWOSection; DWARFSectionMap StringOffsetDWOSection; @@ -1265,14 +1270,12 @@ DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { return StringSwitch(Name) - .Case("debug_info", &InfoSection) .Case("debug_loc", &LocSection) .Case("debug_loclists", &LocListsSection) .Case("debug_line", &LineSection) .Case("debug_str_offsets", &StringOffsetSection) .Case("debug_ranges", &RangeSection) .Case("debug_rnglists", &RnglistsSection) - .Case("debug_info.dwo", &InfoDWOSection) .Case("debug_loc.dwo", &LocDWOSection) .Case("debug_line.dwo", &LineDWOSection) .Case("debug_names", &DebugNamesSection) @@ -1361,6 +1364,16 @@ for (const auto &SecIt : Sections) { if (StringRef *SectionData = mapSectionToMember(SecIt.first())) *SectionData = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_info") + // Find debug_info and debug_types data by section rather than name as + // there are multiple, comdat grouped, of these sections. + InfoSections[SectionRef()].Data = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_info.dwo") + InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_types") + TypesSections[SectionRef()].Data = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_types.dwo") + TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer(); } } DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L, @@ -1415,9 +1428,13 @@ // FIXME: Use the other dwo range section when we emit it. RangeDWOSection.Data = Data; } + } else if (Name == "debug_info") { + // Find debug_info and debug_types data by section rather than name as + // there are multiple, comdat grouped, of these sections. + InfoSections[Section].Data = Data; + } else if (Name == "debug_info.dwo") { + InfoDWOSections[Section].Data = Data; } else if (Name == "debug_types") { - // Find debug_types data by section rather than name as there are - // multiple, comdat grouped, debug_types sections. TypesSections[Section].Data = Data; } else if (Name == "debug_types.dwo") { TypesDWOSections[Section].Data = Data; @@ -1452,9 +1469,16 @@ DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName); RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; if (!Map) { - // Find debug_types relocs by section rather than name as there are - // multiple, comdat grouped, debug_types sections. - if (RelSecName == "debug_types") + // Find debug_info and debug_types relocs by section rather than name + // as there are multiple, comdat grouped, of these sections. + if (RelSecName == "debug_info") + Map = &static_cast(InfoSections[*RelocatedSection]) + .Relocs; + else if (RelSecName == "debug_info.dwo") + Map = &static_cast( + InfoDWOSections[*RelocatedSection]) + .Relocs; + else if (RelSecName == "debug_types") Map = &static_cast(TypesSections[*RelocatedSection]) .Relocs; @@ -1552,8 +1576,10 @@ StringRef getLineStringSection() const override { return LineStringSection; } // Sections for DWARF5 split dwarf proposal. - const DWARFSection &getInfoDWOSection() const override { - return InfoDWOSection; + void forEachInfoDWOSections( + function_ref F) const override { + for (auto &P : InfoDWOSections) + F(P.second); } void forEachTypesDWOSections( function_ref F) const override { @@ -1600,7 +1626,11 @@ StringRef getFileName() const override { return FileName; } uint8_t getAddressSize() const override { return AddressSize; } - const DWARFSection &getInfoSection() const override { return InfoSection; } + void forEachInfoSections( + function_ref F) const override { + for (auto &P : InfoSections) + F(P.second); + } void forEachTypesSections( function_ref F) const override { for (auto &P : TypesSections) Index: llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -364,15 +364,18 @@ bool DWARFVerifier::handleDebugInfo() { const DWARFObject &DObj = DCtx.getDWARFObj(); + unsigned NumErrors = 0; OS << "Verifying .debug_info Unit Header Chain...\n"; - unsigned result = verifyUnitSection(DObj.getInfoSection(), DW_SECT_INFO); + DObj.forEachInfoSections([&](const DWARFSection &S) { + NumErrors += verifyUnitSection(S, DW_SECT_INFO); + }); OS << "Verifying .debug_types Unit Header Chain...\n"; DObj.forEachTypesSections([&](const DWARFSection &S) { - result += verifyUnitSection(S, DW_SECT_TYPES); + NumErrors += verifyUnitSection(S, DW_SECT_TYPES); }); - return result == 0; + return NumErrors == 0; } unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, @@ -551,6 +554,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue) { const DWARFObject &DObj = DCtx.getDWARFObj(); + auto DieCU = Die.getDwarfUnit(); unsigned NumErrors = 0; const auto Form = AttrValue.Value.getForm(); switch (Form) { @@ -563,7 +567,6 @@ Optional RefVal = AttrValue.Value.getAsReference(); assert(RefVal); if (RefVal) { - auto DieCU = Die.getDwarfUnit(); auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset(); auto CUOffset = AttrValue.Value.getRawUValue(); if (CUOffset >= CUSize) { @@ -588,7 +591,7 @@ Optional RefVal = AttrValue.Value.getAsReference(); assert(RefVal); if (RefVal) { - if (*RefVal >= DObj.getInfoSection().Data.size()) { + if (*RefVal >= DieCU->getInfoSection().Data.size()) { ++NumErrors; error() << "DW_FORM_ref_addr offset beyond .debug_info " "bounds:\n"; Index: llvm/test/DebugInfo/X86/dwarfdump-header.s =================================================================== --- llvm/test/DebugInfo/X86/dwarfdump-header.s +++ llvm/test/DebugInfo/X86/dwarfdump-header.s @@ -152,35 +152,13 @@ # CHECK-NEXT: DW_AT_producer {{.*}} "Handmade DWO producer" # CHECK-NEXT: DW_AT_name {{.*}} "V5_dwo_compile_unit" - .section .debug_types,"",@progbits -# CHECK-LABEL: .debug_types contents: - -# DWARF v4 Type unit header. Normal/split are identical so we do only one. -TU_4_start: - .long TU_4_end-TU_4_version # Length of Unit -TU_4_version: - .short 4 # DWARF version number - .long .debug_abbrev # Offset Into Abbrev. Section - .byte 8 # Address Size (in bytes) - .quad 0x0011223344556677 # Type Signature - .long TU_4_type-TU_4_start # Type offset -# The type-unit DIE, which has a name. - .byte 2 - .long str_TU_4 -# The type DIE, which has a name. -TU_4_type: - .byte 3 - .long str_TU_4 - .byte 0 # NULL - .byte 0 # NULL -TU_4_end: - -# CHECK: 0x00000000: Type Unit: length = 0x0000001f version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 name = 'V4_type_unit' type_signature = 0x0011223344556677 type_offset = 0x001c (next unit at 0x00000023) -# CHECK: 0x00000017: DW_TAG_type_unit +# Now a DWARF v5 type unit, which goes in a .debug_info.dwo comdat. +# Note there will not be another ".debug_info.dwo contents:" line, even though +# there is a separate ELF section header; it's dumped along with the previous +# unit as if they were in a single section. - .section .debug_types.dwo,"",@progbits -# FIXME: DWARF v5 wants type units in .debug_info[.dwo] not .debug_types[.dwo]. -# CHECK: .debug_types.dwo contents: + .section .debug_info.dwo,"G",@progbits,5555,comdat +# CHECK-NOT: .debug_info.dwo # DWARF v5 split type unit header. TU_split_5_start: @@ -206,6 +184,32 @@ # CHECK: 0x00000000: Type Unit: length = 0x00000020 version = 0x0005 unit_type = DW_UT_split_type abbr_offset = 0x0000 addr_size = 0x08 name = 'V5_split_type_unit' type_signature = 0x8899aabbccddeeff type_offset = 0x001d (next unit at 0x00000024) # CHECK: 0x00000018: DW_TAG_type_unit + .section .debug_types,"",@progbits +# CHECK-LABEL: .debug_types contents: + +# DWARF v4 Type unit header. Normal/split are identical so we do only one. +TU_4_start: + .long TU_4_end-TU_4_version # Length of Unit +TU_4_version: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 0x0011223344556677 # Type Signature + .long TU_4_type-TU_4_start # Type offset +# The type-unit DIE, which has a name. + .byte 2 + .long str_TU_4 +# The type DIE, which has a name. +TU_4_type: + .byte 3 + .long str_TU_4 + .byte 0 # NULL + .byte 0 # NULL +TU_4_end: + +# CHECK: 0x00000000: Type Unit: length = 0x0000001f version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 name = 'V4_type_unit' type_signature = 0x0011223344556677 type_offset = 0x001c (next unit at 0x00000023) +# CHECK: 0x00000017: DW_TAG_type_unit + .section .debug_line,"",@progbits # CHECK-LABEL: .debug_line contents: