--- /dev/null
+# 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
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())
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.
// 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
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));
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.
Out.emitIntValue(E.second.Contributions[i].*Field, 4);
}
-static void
-writeIndex(MCStreamer &Out, MCSection *Section,
- ArrayRef<unsigned> ContributionOffsets,
- const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
+static void writeIndex(MCStreamer &Out, MCSection *Section,
+ ArrayRef<unsigned> ContributionOffsets,
+ const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
+ uint32_t IndexVersion) {
if (IndexEntries.empty())
return;
}
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
StringRef &CurStrSection, StringRef &CurStrOffsetSection,
std::vector<StringRef> &CurTypesSection,
std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
- StringRef &CurCUIndexSection, StringRef &CurTUIndexSection) {
+ StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
+ std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
if (Section.isBSS())
return Error::success();
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) {
{"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(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<DWARFSectionKind>(0)}},
{"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
uint32_t ContributionOffsets[8] = {};
+ uint16_t Version = 0;
+ uint32_t IndexVersion = 0;
DWPStringPool Strings(Out, StrSection);
StringRef CurCUIndexSection;
StringRef CurTUIndexSection;
+ // This maps each section contained in this file to its length.
+ // This information is later on used to calculate the contributions,
+ // i.e. offset and length, of each compile/type unit to a section.
+ std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
+
for (const auto &Section : Obj.sections())
if (auto Err = handleSection(
KnownSections, StrSection, StrOffsetSection, TypesSection,
UncompressedSections, ContributionOffsets, CurEntry,
CurStrSection, CurStrOffsetSection, CurTypesSection,
CurInfoSection, AbbrevSection, CurCUIndexSection,
- CurTUIndexSection))
+ CurTUIndexSection, SectionLength))
return Err;
if (CurInfoSection.empty())
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<DWPError>("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);
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;
if (!FoundCUUnit)
return make_error<DWPError>("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;
}
DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
if (!CUIndex.parse(CUIndexData))
return make_error<DWPError>("failed to parse cu_index");
- if (CUIndex.getVersion() != 2)
- return make_error<DWPError>(
- "unsupported cu_index version: " + utostr(CUIndex.getVersion()) +
- " (only version 2 is supported)");
+ if (CUIndex.getVersion() != IndexVersion)
+ return make_error<DWPError>("incompatible cu_index versions, found " +
+ utostr(CUIndex.getVersion()) +
+ " and expecting " + utostr(IndexVersion));
Out.SwitchSection(InfoSection);
for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
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;
if (!TUIndex.parse(TUIndexData))
return make_error<DWPError>("failed to parse tu_index");
if (TUIndex.getVersion() != 2)
- return make_error<DWPError>(
- "unsupported tu_index version: " + utostr(TUIndex.getVersion()) +
- " (only version 2 is supported)");
+ return make_error<DWPError>("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();
}