diff --git a/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s b/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s @@ -0,0 +1,55 @@ +# This test checks the support for writing macro sections and their index (v5). + +# RUN: llvm-mc -triple x86_64-unknown-linux --filetype=obj --split-dwarf-file=%t.dwo -dwarf-version=5 %s -o %t.o +# RUN: llvm-dwp %t.dwo -o %t.dwp 2>&1 +# RUN: llvm-dwarfdump -debug-macro -debug-cu-index %t.dwp | FileCheck %s + +# CHECK-DAG: .debug_macro.dwo contents: +# CHECK: macro header: version = 0x0005, flags = 0x00, format = DWARF32 +# CHECK-NEXT: DW_MACRO_start_file - lineno: 0 filenum: 0 +# CHECK-NEXT: DW_MACRO_define_strx - lineno: 1 macro: x 5 +# CHECK-NEXT: DW_MACRO_end_file + +# CHECK-DAG: .debug_cu_index contents: +# CHECK-NEXT: version = 5, units = 1, slots = 2 +# CHECK: Index Signature INFO ABBREV STR_OFFSETS MACRO +# CHECK: 1 0x0000000000000000 [0x00000000, 0x00000019) [0x00000000, 0x00000008) [0x00000000, 0x0000000c) [0x00000000, 0x0000000b) + + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type (DW_UT_split_compile) + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 0 + .byte 1 # Abbrev [1] 0x14:0x5 DW_TAG_compile_unit + .long 0 # DW_AT_macros +.Ldebug_info_dwo_end0: + .section .debug_macro.dwo,"e",@progbits + .short 5 # Macro information version + .byte 0 # Flags: 32 bit + .byte 3 # DW_MACRO_start_file + .byte 0 # Line Number + .byte 0 # File Number + .byte 11 # DW_MACRO_define_strx + .byte 1 # Line Number + .byte 0 # Macro String + .byte 4 # DW_MACRO_end_file + .byte 0 # End Of Macro List Mark + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 121 # DW_AT_macros + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_str.dwo,"eMS",@progbits,1 + .asciz "x 5" # string offset=0 + .section .debug_str_offsets.dwo,"e",@progbits + .long 8 # Length of String Offsets Set + .short 5 + .short 0 + .long 0 diff --git a/llvm/test/tools/llvm-dwp/X86/unsupported_cu_index_version.s b/llvm/test/tools/llvm-dwp/X86/incompatible_cu_index_versions.s rename from llvm/test/tools/llvm-dwp/X86/unsupported_cu_index_version.s rename to llvm/test/tools/llvm-dwp/X86/incompatible_cu_index_versions.s --- a/llvm/test/tools/llvm-dwp/X86/unsupported_cu_index_version.s +++ b/llvm/test/tools/llvm-dwp/X86/incompatible_cu_index_versions.s @@ -1,19 +1,20 @@ # RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.dwp # RUN: not llvm-dwp %t.dwp -o %t 2>&1 | FileCheck %s -# CHECK: error: unsupported cu_index version: 5 (only version 2 is supported) +# CHECK: error: incompatible cu_index versions, found 2 and expecting 5 .section .debug_info.dwo, "e", @progbits .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit .Ldebug_info_dwo_start0: .short 5 # DWARF version number - .byte 5 # DWARF Unit type + .byte 5 # DWARF Unit type (DW_UT_split_compile) .byte 8 # Address Size (in bytes) .long 0 # Offset Into Abbrev. Section .quad -346972125991005518 + .byte 0 # Abbrev [9] 0xb:0x37 DW_TAG_compile_unit .Ldebug_info_dwo_end0: .section .debug_cu_index, "", @progbits ## Header: - .short 5 # Version + .short 2 # Version .space 2 # Padding .long 2 # Section count .long 1 # Unit count diff --git a/llvm/test/tools/llvm-dwp/X86/info-v5.s b/llvm/test/tools/llvm-dwp/X86/info-v5.s --- a/llvm/test/tools/llvm-dwp/X86/info-v5.s +++ b/llvm/test/tools/llvm-dwp/X86/info-v5.s @@ -9,7 +9,7 @@ #CHECK: 0x00000000: Compile Unit: length = 0x00000050, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = [[DWOID:.*]] (next unit at 0x00000054) # CHECK-DAG: .debug_cu_index contents: -# CHECK: version = 2, units = 1, slots = 2 +# CHECK: version = 5, units = 1, slots = 2 # CHECK: Index Signature INFO ABBREV # CHECK: 1 [[DWOID]] [0x00000000, 0x00000054) [0x00000000, 0x0000002a) diff --git a/llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s b/llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s --- a/llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s +++ b/llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s @@ -5,7 +5,7 @@ ## of version 2 and a TU index of version 5. A valid TU is not required, but ## the .debug_types.dwo section should not be empty. -# CHECK: error: unsupported tu_index version: 5 (only version 2 is supported) +# CHECK: error: expected index version 2, but got: 5 .section .debug_abbrev.dwo, "e", @progbits .LAbbrevBegin: diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -174,7 +174,7 @@ MCSection *StrOffsetSection, StringRef CurStrSection, StringRef CurStrOffsetSection, - const InfoSectionUnitHeader &Header) { + uint16_t Version) { // Could possibly produce an error or warning if one of these was non-null but // the other was null. if (CurStrSection.empty() || CurStrOffsetSection.empty()) @@ -195,7 +195,7 @@ Out.SwitchSection(StrOffsetSection); - uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Header.Version); + uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version); uint64_t Offset = 0; uint64_t Size = CurStrOffsetSection.size(); // FIXME: This can be caused by bad input and should be handled as such. @@ -340,10 +340,10 @@ // Convert an internal section identifier into the index to use with // UnitIndexEntry::Contributions. -static unsigned getContributionIndex(DWARFSectionKind Kind) { - // Assuming the pre-standard DWP format. - assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO); - return serializeSectionKind(Kind, 2) - DW_SECT_INFO; +static unsigned getContributionIndex(DWARFSectionKind Kind, + uint32_t IndexVersion) { + assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO); + return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO; } // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk @@ -379,12 +379,14 @@ for (auto Kind : TUIndex.getColumnKinds()) { if (!isSupportedSectionKind(Kind)) continue; - auto &C = Entry.Contributions[getContributionIndex(Kind)]; + auto &C = + Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())]; C.Offset += I->Offset; C.Length = I->Length; ++I; } - unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES); + unsigned TypesIndex = + getContributionIndex(DW_SECT_EXT_TYPES, TUIndex.getVersion()); auto &C = Entry.Contributions[TypesIndex]; Out.emitBytes(Types.substr( C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length)); @@ -406,7 +408,7 @@ UnitIndexEntry Entry = CUEntry; // Zero out the debug_info contribution Entry.Contributions[0] = {}; - auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES)]; + auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)]; C.Offset = TypesOffset; auto PrevOffset = Offset; // Length of the unit, including the 4 byte length field. @@ -438,10 +440,10 @@ Out.emitIntValue(E.second.Contributions[i].*Field, 4); } -static void -writeIndex(MCStreamer &Out, MCSection *Section, - ArrayRef ContributionOffsets, - const MapVector &IndexEntries) { +static void writeIndex(MCStreamer &Out, MCSection *Section, + ArrayRef ContributionOffsets, + const MapVector &IndexEntries, + uint32_t IndexVersion) { if (IndexEntries.empty()) return; @@ -467,7 +469,7 @@ } Out.SwitchSection(Section); - Out.emitIntValue(2, 4); // Version + Out.emitIntValue(IndexVersion, 4); // Version Out.emitIntValue(Columns, 4); // Columns Out.emitIntValue(IndexEntries.size(), 4); // Num Units Out.emitIntValue(Buckets.size(), 4); // Num Buckets @@ -551,7 +553,8 @@ StringRef &CurStrSection, StringRef &CurStrOffsetSection, std::vector &CurTypesSection, std::vector &CurInfoSection, StringRef &AbbrevSection, - StringRef &CurCUIndexSection, StringRef &CurTUIndexSection) { + StringRef &CurCUIndexSection, StringRef &CurTUIndexSection, + std::vector> &SectionLength) { if (Section.isBSS()) return Error::success(); @@ -578,11 +581,8 @@ return Error::success(); if (DWARFSectionKind Kind = SectionPair->second.second) { - auto Index = getContributionIndex(Kind); if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) { - CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; - ContributionOffsets[Index] += - (CurEntry.Contributions[Index].Length = Contents.size()); + SectionLength.push_back(std::make_pair(Kind, Contents.size())); } if (Kind == DW_SECT_ABBREV) { @@ -664,6 +664,7 @@ {"debug_str.dwo", {StrSection, static_cast(0)}}, {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, + {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}}, {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, {"debug_cu_index", {CUIndexSection, static_cast(0)}}, {"debug_tu_index", {TUIndexSection, static_cast(0)}}}; @@ -672,6 +673,8 @@ MapVector TypeIndexEntries; uint32_t ContributionOffsets[8] = {}; + uint16_t Version = 0; + uint32_t IndexVersion = 0; DWPStringPool Strings(Out, StrSection); @@ -698,6 +701,8 @@ StringRef CurCUIndexSection; StringRef CurTUIndexSection; + std::vector> SectionLength; + for (const auto &Section : Obj.sections()) if (auto Err = handleSection( KnownSections, StrSection, StrOffsetSection, TypesSection, @@ -705,7 +710,7 @@ UncompressedSections, ContributionOffsets, CurEntry, CurStrSection, CurStrOffsetSection, CurTypesSection, CurInfoSection, AbbrevSection, CurCUIndexSection, - CurTUIndexSection)) + CurTUIndexSection, SectionLength)) return Err; if (CurInfoSection.empty()) @@ -717,11 +722,25 @@ return HeaderOrErr.takeError(); InfoSectionUnitHeader &Header = *HeaderOrErr; + if (Version == 0) { + Version = Header.Version; + IndexVersion = Version < 5 ? 2 : 5; + } else if (Version != Header.Version) { + return make_error("incompatible DWARF compile unit versions."); + } + writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection, - CurStrOffsetSection, Header); + CurStrOffsetSection, Header.Version); + + for (auto Pair : SectionLength) { + auto Index = getContributionIndex(Pair.first, IndexVersion); + CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; + ContributionOffsets[Index] += + (CurEntry.Contributions[Index].Length = Pair.second); + } uint32_t &InfoSectionOffset = - ContributionOffsets[getContributionIndex(DW_SECT_INFO)]; + ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)]; if (CurCUIndexSection.empty()) { bool FoundCUUnit = false; Out.SwitchSection(InfoSection); @@ -737,7 +756,8 @@ InfoSectionUnitHeader &Header = *HeaderOrError; UnitIndexEntry Entry = CurEntry; - auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO)]; + auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO, + IndexVersion)]; C.Offset = InfoSectionOffset; C.Length = Header.Length + 4; @@ -768,11 +788,12 @@ if (!FoundCUUnit) return make_error("no compile unit found in file: " + Input); - // Add types from the .debug_types section from DWARF < 5. - addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection, - CurEntry, - ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); - + if (IndexVersion == 2) { + // Add types from the .debug_types section from DWARF < 5. + addAllTypes( + Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry, + ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]); + } continue; } @@ -785,10 +806,10 @@ DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0); if (!CUIndex.parse(CUIndexData)) return make_error("failed to parse cu_index"); - if (CUIndex.getVersion() != 2) - return make_error( - "unsupported cu_index version: " + utostr(CUIndex.getVersion()) + - " (only version 2 is supported)"); + if (CUIndex.getVersion() != IndexVersion) + return make_error("incompatible cu_index versions, found " + + utostr(CUIndex.getVersion()) + + " and expecting " + utostr(IndexVersion)); Out.SwitchSection(InfoSection); for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) { @@ -821,12 +842,13 @@ for (auto Kind : CUIndex.getColumnKinds()) { if (!isSupportedSectionKind(Kind)) continue; - auto &C = NewEntry.Contributions[getContributionIndex(Kind)]; + auto &C = + NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)]; C.Offset += I->Offset; C.Length = I->Length; ++I; } - unsigned Index = getContributionIndex(DW_SECT_INFO); + unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion); auto &C = NewEntry.Contributions[Index]; Out.emitBytes(CUInfoSection); C.Offset = InfoSectionOffset; @@ -841,30 +863,35 @@ if (!TUIndex.parse(TUIndexData)) return make_error("failed to parse tu_index"); if (TUIndex.getVersion() != 2) - return make_error( - "unsupported tu_index version: " + utostr(TUIndex.getVersion()) + - " (only version 2 is supported)"); + return make_error("expected index version 2, but got: " + + utostr(TUIndex.getVersion())); addAllTypesFromDWP( Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(), CurEntry, - ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); + ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]); } } - // Lie about there being no info contributions so the TU index only includes - // the type unit contribution - ContributionOffsets[0] = 0; + if (Version < 5) { + // Lie about there being no info contributions so the TU index only includes + // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a + // contribution to the info section, so we do not want to lie about it. + ContributionOffsets[0] = 0; + } writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets, - TypeIndexEntries); - - // Lie about the type contribution - ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0; - // Unlie about the info contribution - ContributionOffsets[0] = 1; + TypeIndexEntries, IndexVersion); + + if (Version < 5) { + // Lie about the type contribution for DWARF < 5. In DWARFv5 the type + // section does not exist, so no need to do anything about this. + ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0; + // Unlie about the info contribution + ContributionOffsets[0] = 1; + } writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets, - IndexEntries); + IndexEntries, IndexVersion); return Error::success(); }