void b(bar) {
}
-CHECK: .debug_abbrev.dwo contents:
-CHECK: Abbrev table for offset: 0x00000000
+CHECK-LABEL: .debug_abbrev.dwo contents:
+CHECK-LABEL: Abbrev table for offset:
+CHECK: 0x0000[[AAOFF:.*]]
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_variable
CHECK: DW_TAG_structure_type
-CHECK: Abbrev table for offset: 0x00000031
+CHECK-LABEL: Abbrev table for offset:
+CHECK: 0x0000[[BAOFF:.*]]
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_structure_type
CHECK: DW_TAG_subprogram
CHECK: DW_TAG_formal_parameter
CHECK: .debug_info.dwo contents:
-CHECK: 0x00000000: Compile Unit: length = 0x00000025 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000029)
+CHECK: [[AOFF:0x[0-9a-f]*]]:
+CHECK-LABEL: Compile Unit: length = 0x00000029 version = 0x0004 abbr_offset =
+CHECK: 0x[[AAOFF]] addr_size = 0x08 (next unit at [[BOFF:.*]])
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "a.cpp"
CHECK: DW_AT_GNU_dwo_id {{.*}} ([[DWOA:.*]])
CHECK: DW_TAG_variable
CHECK: DW_AT_name {{.*}} "a"
CHECK: DW_TAG_structure_type
-CHECK: DW_AT_name {{.*}} "foo"
+CHECK: DW_AT_signature {{.*}} ([[FOOSIG:.*]])
-CHECK: 0x00000029: Compile Unit: length = 0x00000031 version = 0x0004 abbr_offset = 0x0031 addr_size = 0x08 (next unit at 0x0000005e)
+CHECK: [[BOFF]]:
+CHECK-LABEL: Compile Unit: length = 0x00000035 version = 0x0004 abbr_offset =
+CHECK: 0x[[BAOFF]] addr_size = 0x08 (next unit at [[XOFF:.*]])
CHECK: DW_AT_name {{.*}} "b.cpp"
CHECK: DW_AT_GNU_dwo_id {{.*}} ([[DWOB:.*]])
CHECK: DW_TAG_structure_type
-CHECK: DW_AT_name {{.*}} "bar"
+CHECK: DW_AT_signature {{.*}} ([[BARSIG:.*]])
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "b"
CHECK: DW_TAG_formal_parameter
-CHECK: .debug_cu_index contents:
-CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS
-CHECK: 3 [[DWOA]] [0x00000000, 0x00000029) [0x00000000, 0x00000031) [0x00000000, 0x00000011) [0x00000000, 0x00000010)
-CHECK: 4 [[DWOB]] [0x00000029, 0x0000005e) [0x00000031, 0x00000075) [0x00000011, 0x00000022) [0x00000010, 0x00000024)
+CHECK-LABEL: .debug_types.dwo contents:
+CHECK: [[FOOUOFF:0x[0-9a-f]*]]:
+CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
+CHECK: 0x[[AAOFF]] addr_size = 0x08 type_signature = [[FOOSIG]] type_offset = 0x[[FOOOFF:.*]] (next unit at [[BARUOFF:.*]])
+CHECK: DW_TAG_type_unit
+CHECK: [[FOOOFF]]: DW_TAG_structure_type
+CHECK: DW_AT_name {{.*}} "foo"
+CHECK: [[BARUOFF]]:
+CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
+CHECK: 0x[[BAOFF]] addr_size = 0x08 type_signature = [[BARSIG]] type_offset = 0x001e (next unit at [[XUOFF:.*]])
+CHECK: DW_TAG_type_unit
+CHECK: 0x00000042: DW_TAG_structure_type
+CHECK: DW_AT_name {{.*}} "bar"
-CHECK: .debug_str.dwo contents:
+CHECK-LABEL: .debug_cu_index contents:
+CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS
+CHECK: 1 [[DWOA]] {{\[}}[[AOFF]], [[BOFF]]) [0x0000[[AAOFF]], 0x0000[[BAOFF]]) [0x00000000, 0x0000001a) [0x00000000, 0x00000010)
+CHECK: 3 [[DWOB]] {{\[}}[[BOFF]], [[XOFF]]) [0x0000[[BAOFF]], 0x00000099) [0x0000001a, 0x00000034) [0x00000010, 0x00000024)
+
+CHECK-LABEL: .debug_tu_index contents:
+CHECK: Index Signature TYPES ABBREV LINE STR_OFFSETS
+CHECK: 1 [[FOOSIG]] {{\[}}[[FOOUOFF]], [[BARUOFF]]) [0x0000[[AAOFF]], 0x0000[[BAOFF]]) [0x00000000, 0x0000001a) [0x00000000, 0x00000010)
+CHECK: 4 [[BARSIG]] {{\[}}[[BARUOFF]], [[XUOFF]]) [0x0000[[BAOFF]], 0x00000099) [0x0000001a, 0x00000034) [0x00000010, 0x00000024)
+
+CHECK-LABEL: .debug_str.dwo contents:
CHECK: "clang version
CHECK: 0x[[ACPP:.*]]: "a.cpp"
CHECK-NOT: "clang version
CHECK: 0x[[BCPP:.*]]: "b.cpp"
-CHECK: .debug_str_offsets.dwo contents:
+CHECK-LABEL: .debug_str_offsets.dwo contents:
CHECK: : 00000000
CHECK: : [[ACPP]]
CHECK: : 00000000
return InfoData.getU64(&Offset);
}
+struct UnitIndexEntry {
+ uint64_t Signature;
+ DWARFUnitIndex::Entry::SectionContribution Contributions[8];
+};
+
+static void addAllTypes(std::vector<UnitIndexEntry> &TypeIndexEntries,
+ uint32_t OutTypesOffset, StringRef Types,
+ const UnitIndexEntry &CUEntry) {
+ uint32_t Offset = 0;
+ DataExtractor Data(Types, true, 0);
+ while (Data.isValidOffset(Offset)) {
+ TypeIndexEntries.push_back(CUEntry);
+ auto &Entry = TypeIndexEntries.back();
+ // Zero out the debug_info contribution
+ Entry.Contributions[0] = {};
+ auto &C = Entry.Contributions[DW_SECT_TYPES - DW_SECT_INFO];
+ C.Offset = OutTypesOffset + Offset;
+ auto PrevOffset = Offset;
+ // Length of the unit, including the 4 byte length field.
+ C.Length = Data.getU32(&Offset) + 4;
+
+ Data.getU16(&Offset); // Version
+ Data.getU32(&Offset); // Abbrev offset
+ Data.getU8(&Offset); // Address size
+ Entry.Signature = Data.getU64(&Offset);
+ Offset = PrevOffset + C.Length;
+ }
+}
+
+static void
+writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
+ ArrayRef<UnitIndexEntry> IndexEntries,
+ uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
+ for (const auto &E : IndexEntries)
+ for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
+ if (ContributionOffsets[i])
+ Out.EmitIntValue(E.Contributions[i].*Field, 4);
+}
+
+static void writeIndex(MCStreamer &Out, MCSection *Section,
+ ArrayRef<unsigned> ContributionOffsets,
+ ArrayRef<UnitIndexEntry> IndexEntries) {
+ unsigned Columns = 0;
+ for (auto &C : ContributionOffsets)
+ if (C)
+ ++Columns;
+
+ std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
+ uint64_t Mask = Buckets.size() - 1;
+ for (size_t i = 0; i != IndexEntries.size(); ++i) {
+ auto S = IndexEntries[i].Signature;
+ auto H = S & Mask;
+ while (Buckets[H])
+ H += ((S >> 32) & Mask) | 1;
+ Buckets[H] = i + 1;
+ }
+
+ Out.SwitchSection(Section);
+ Out.EmitIntValue(2, 4); // Version
+ Out.EmitIntValue(Columns, 4); // Columns
+ Out.EmitIntValue(IndexEntries.size(), 4); // Num Units
+ Out.EmitIntValue(Buckets.size(), 4); // Num Buckets
+
+ // Write the signatures.
+ for (const auto &I : Buckets)
+ Out.EmitIntValue(I ? IndexEntries[I - 1].Signature : 0, 8);
+
+ // Write the indexes.
+ for (const auto &I : Buckets)
+ Out.EmitIntValue(I, 4);
+
+ // Write the column headers (which sections will appear in the table)
+ for (size_t i = 0; i != ContributionOffsets.size(); ++i)
+ if (ContributionOffsets[i])
+ Out.EmitIntValue(i + DW_SECT_INFO, 4);
+
+ // Write the offsets.
+ writeIndexTable(Out, ContributionOffsets, IndexEntries,
+ &DWARFUnitIndex::Entry::SectionContribution::Offset);
+
+ // Write the lengths.
+ writeIndexTable(Out, ContributionOffsets, IndexEntries,
+ &DWARFUnitIndex::Entry::SectionContribution::Length);
+}
static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
const auto &MCOFI = *Out.getContext().getObjectFileInfo();
MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
{"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
{"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}};
- struct UnitIndexEntry {
- uint64_t Signature;
- DWARFUnitIndex::Entry::SectionContribution Contributions[8];
- };
-
std::vector<UnitIndexEntry> IndexEntries;
+ std::vector<UnitIndexEntry> TypeIndexEntries;
StringMap<uint32_t> Strings;
uint32_t StringOffset = 0;
StringRef CurStrOffsetSection;
StringRef InfoSection;
StringRef AbbrevSection;
+ StringRef TypesSection;
+
+ auto TypesOffset = ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO];
for (const auto &Section : ErrOrObj->getBinary()->sections()) {
StringRef Name;
ContributionOffsets[Index] +=
(CurEntry.Contributions[Index].Length = Contents.size());
- if (Kind == DW_SECT_INFO) {
- assert(InfoSection.empty());
+ switch (Kind) {
+ case DW_SECT_INFO:
InfoSection = Contents;
- } else if (Kind == DW_SECT_ABBREV) {
- assert(AbbrevSection.empty());
+ break;
+ case DW_SECT_ABBREV:
AbbrevSection = Contents;
+ break;
+ case DW_SECT_TYPES:
+ TypesSection = Contents;
+ break;
+ default:
+ break;
}
}
assert(!AbbrevSection.empty());
assert(!InfoSection.empty());
CurEntry.Signature = getCUSignature(AbbrevSection, InfoSection);
+ addAllTypes(TypeIndexEntries, TypesOffset, TypesSection, CurEntry);
if (auto Err = writeStringsAndOffsets(Out, Strings, StringOffset,
StrSection, StrOffsetSection,
return Err;
}
- unsigned Columns = 0;
- for (auto &C : ContributionOffsets)
- if (C)
- ++Columns;
-
- std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
- uint64_t Mask = Buckets.size() - 1;
- for (size_t i = 0; i != IndexEntries.size(); ++i) {
- auto S = IndexEntries[i].Signature;
- auto H = S & Mask;
- while (Buckets[H])
- H += ((S >> 32) & Mask) | 1;
- Buckets[H] = i + 1;
- }
+ // Lie about there being no info contributions so the TU index only includes
+ // the type unit contribution
+ ContributionOffsets[0] = 0;
+ writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
+ TypeIndexEntries);
- Out.SwitchSection(MCOFI.getDwarfCUIndexSection());
- Out.EmitIntValue(2, 4); // Version
- Out.EmitIntValue(Columns, 4); // Columns
- Out.EmitIntValue(IndexEntries.size(), 4); // Num Units
- // FIXME: This is not the right number of buckets for a real hash.
- Out.EmitIntValue(Buckets.size(), 4); // Num Buckets
+ // Lie about the type contribution
+ ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO] = 0;
+ // Unlie about the info contribution
+ ContributionOffsets[0] = 1;
- // Write the signatures.
- for (const auto &I : Buckets)
- Out.EmitIntValue(I ? IndexEntries[I - 1].Signature : 0, 8);
-
- // Write the indexes.
- for (const auto &I : Buckets)
- Out.EmitIntValue(I, 4);
-
- // Write the column headers (which sections will appear in the table)
- for (size_t i = 0; i != array_lengthof(ContributionOffsets); ++i)
- if (ContributionOffsets[i])
- Out.EmitIntValue(i + DW_SECT_INFO, 4);
-
- // Write the offsets.
- for (const auto &E : IndexEntries)
- for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
- if (ContributionOffsets[i])
- Out.EmitIntValue(E.Contributions[i].Offset, 4);
-
- // Write the lengths.
- for (const auto &E : IndexEntries)
- for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
- if (ContributionOffsets[i])
- Out.EmitIntValue(E.Contributions[i].Length, 4);
+ writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
+ IndexEntries);
return std::error_code();
}