[llvm-dwp] Support debug_tu_index
authorDavid Blaikie <dblaikie@gmail.com>
Sat, 5 Dec 2015 03:05:45 +0000 (03:05 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Sat, 5 Dec 2015 03:05:45 +0000 (03:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254827 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCObjectFileInfo.h
lib/MC/MCObjectFileInfo.cpp
test/tools/llvm-dwp/Inputs/simple/a.dwo
test/tools/llvm-dwp/Inputs/simple/b.dwo
test/tools/llvm-dwp/X86/simple.test
tools/llvm-dwp/llvm-dwp.cpp

index 388a208..cf2c3f1 100644 (file)
@@ -118,6 +118,7 @@ protected:
 
   // These are for Fission DWP files.
   MCSection *DwarfCUIndexSection;
+  MCSection *DwarfTUIndexSection;
 
   /// Section for newer gnu pubnames.
   MCSection *DwarfGnuPubNamesSection;
@@ -266,6 +267,7 @@ public:
   MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; }
   MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
   MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; }
+  MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; }
 
   MCSection *getCOFFDebugSymbolsSection() const {
     return COFFDebugSymbolsSection;
index 41e2869..dbedd73 100644 (file)
@@ -262,6 +262,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) {
   DwarfCUIndexSection =
       Ctx->getMachOSection("__DWARF", "__debug_cu_index", MachO::S_ATTR_DEBUG,
                            SectionKind::getMetadata());
+  DwarfTUIndexSection =
+      Ctx->getMachOSection("__DWARF", "__debug_tu_index", MachO::S_ATTR_DEBUG,
+                           SectionKind::getMetadata());
   StackMapSection = Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps",
                                          0, SectionKind::getMetadata());
 
@@ -537,6 +540,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) {
   // DWP Sections
   DwarfCUIndexSection =
       Ctx->getELFSection(".debug_cu_index", ELF::SHT_PROGBITS, 0);
+  DwarfTUIndexSection =
+      Ctx->getELFSection(".debug_tu_index", ELF::SHT_PROGBITS, 0);
 
   StackMapSection =
       Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
@@ -725,6 +730,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) {
       COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
           COFF::IMAGE_SCN_MEM_READ,
       SectionKind::getMetadata());
+  DwarfTUIndexSection = Ctx->getCOFFSection(
+      ".debug_tu_index",
+      COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+          COFF::IMAGE_SCN_MEM_READ,
+      SectionKind::getMetadata());
   DwarfAccelNamesSection = Ctx->getCOFFSection(
       ".apple_names",
       COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
index 7bdb2a7..1fc71ca 100644 (file)
Binary files a/test/tools/llvm-dwp/Inputs/simple/a.dwo and b/test/tools/llvm-dwp/Inputs/simple/a.dwo differ
index f41243d..a69cd69 100644 (file)
Binary files a/test/tools/llvm-dwp/Inputs/simple/b.dwo and b/test/tools/llvm-dwp/Inputs/simple/b.dwo differ
index 5cc6263..5502ef2 100644 (file)
@@ -13,48 +13,73 @@ b.cpp:
   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
index b4aaea3..608eca1 100644 (file)
@@ -130,6 +130,90 @@ static uint64_t getCUSignature(StringRef Abbrev, StringRef Info) {
   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();
@@ -143,12 +227,8 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
       {"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;
@@ -167,6 +247,9 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
     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;
@@ -188,12 +271,18 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
         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;
         }
       }
 
@@ -211,6 +300,7 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
     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,
@@ -218,52 +308,19 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
       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();
 }