[llvm-dwp] Emit a rather fictional debug_cu_index
authorDavid Blaikie <dblaikie@gmail.com>
Wed, 2 Dec 2015 06:21:34 +0000 (06:21 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Wed, 2 Dec 2015 06:21:34 +0000 (06:21 +0000)
This is very rudimentary support for debug_cu_index, but it is enough to
allow llvm-dwarfdump to find the offsets for  contributions and
correctly dump debug_info.

It will need to actually find the real signature of the unit and build
the real hash table with the right number of buckets, as per the DWP
specification.

It will also need to be expanded to cover the tu_index as well.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254489 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
include/llvm/MC/MCObjectFileInfo.h
lib/DebugInfo/DWARF/DWARFContext.cpp
lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
lib/MC/MCObjectFileInfo.cpp
test/tools/llvm-dwp/X86/simple.test
tools/llvm-dwp/llvm-dwp.cpp

index 83da6fef4411257c024adde0b0c684664152925d..a85c2f9f0a23bbe818c4b519b3c553f93728a218 100644 (file)
@@ -41,12 +41,15 @@ class DWARFUnitIndex {
 
 public:
   class Entry {
-    const DWARFUnitIndex *Index;
-    uint64_t Signature;
+  public:
     struct SectionContribution {
       uint32_t Offset;
       uint32_t Length;
     };
+
+  private:
+    const DWARFUnitIndex *Index;
+    uint64_t Signature;
     std::unique_ptr<SectionContribution[]> Contributions;
     friend class DWARFUnitIndex;
 
@@ -58,14 +61,18 @@ public:
 private:
   struct Header Header;
 
+  DWARFSectionKind InfoColumnKind;
   int InfoColumn = -1;
   std::unique_ptr<DWARFSectionKind[]> ColumnKinds;
   std::unique_ptr<Entry[]> Rows;
 
   static StringRef getColumnHeader(DWARFSectionKind DS);
+  bool parseImpl(DataExtractor IndexData);
 
 public:
   bool parse(DataExtractor IndexData);
+  DWARFUnitIndex(DWARFSectionKind InfoColumnKind)
+      : InfoColumnKind(InfoColumnKind) {}
   void dump(raw_ostream &OS) const;
   const Entry *getFromOffset(uint32_t Offset) const;
 };
index eaca3833dc8914ded4f8b8e21218f48166adcbca..388a208fb4a04348ec8673a72d39a13f345d4041 100644 (file)
@@ -116,6 +116,9 @@ protected:
   MCSection *DwarfStrOffDWOSection;
   MCSection *DwarfAddrSection;
 
+  // These are for Fission DWP files.
+  MCSection *DwarfCUIndexSection;
+
   /// Section for newer gnu pubnames.
   MCSection *DwarfGnuPubNamesSection;
   /// Section for newer gnu pubtypes.
@@ -262,6 +265,7 @@ public:
   MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; }
   MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; }
   MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
+  MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; }
 
   MCSection *getCOFFDebugSymbolsSection() const {
     return COFFDebugSymbolsSection;
index 2165d353ba0968b348b3ced9b956679a90046dcd..a4195b75c47d9e9d3eea44b0cf3f90a670f4fdb6 100644 (file)
@@ -163,20 +163,12 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
 
   if (DumpType == DIDT_All || DumpType == DIDT_CUIndex) {
     OS << "\n.debug_cu_index contents:\n";
-    DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(),
-                              savedAddressByteSize);
-    DWARFUnitIndex CUIndex;
-    if (CUIndex.parse(CUIndexData))
-      CUIndex.dump(OS);
+    getCUIndex().dump(OS);
   }
 
   if (DumpType == DIDT_All || DumpType == DIDT_TUIndex) {
     OS << "\n.debug_tu_index contents:\n";
-    DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(),
-                              savedAddressByteSize);
-    DWARFUnitIndex TUIndex;
-    if (TUIndex.parse(TUIndexData))
-      TUIndex.dump(OS);
+    getTUIndex().dump(OS);
   }
 
   if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) {
@@ -280,7 +272,7 @@ const DWARFUnitIndex &DWARFContext::getCUIndex() {
 
   DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0);
 
-  CUIndex = llvm::make_unique<DWARFUnitIndex>();
+  CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
   CUIndex->parse(CUIndexData);
   return *CUIndex;
 }
@@ -291,7 +283,7 @@ const DWARFUnitIndex &DWARFContext::getTUIndex() {
 
   DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0);
 
-  TUIndex = llvm::make_unique<DWARFUnitIndex>();
+  TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES);
   TUIndex->parse(TUIndexData);
   return *TUIndex;
 }
index baefed30f36874b5cc7c489212f3954ac84c2f2a..e8e7441d976927c35c536d2cb99e426e3f2327b8 100644 (file)
@@ -30,6 +30,13 @@ void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
 }
 
 bool DWARFUnitIndex::parse(DataExtractor IndexData) {
+  bool b = parseImpl(IndexData);
+  if (!b)
+    *this = DWARFUnitIndex(InfoColumnKind);
+  return b;
+}
+
+bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
   uint32_t Offset = 0;
   if (!Header.parse(IndexData, &Offset))
     return false;
@@ -62,7 +69,7 @@ bool DWARFUnitIndex::parse(DataExtractor IndexData) {
   // Read the Column Headers
   for (unsigned i = 0; i != Header.NumColumns; ++i) {
     ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
-    if (ColumnKinds[i] == DW_SECT_INFO || ColumnKinds[i] == DW_SECT_TYPES) {
+    if (ColumnKinds[i] == InfoColumnKind) {
       if (InfoColumn != -1)
         return false;
       InfoColumn = i;
@@ -107,6 +114,9 @@ StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
 }
 
 void DWARFUnitIndex::dump(raw_ostream &OS) const {
+  if (!Header.NumBuckets)
+    return;
+
   Header.dump(OS);
   OS << "Index Signature         ";
   for (unsigned i = 0; i != Header.NumColumns; ++i)
index 8b75457a246024bd812eaa7c2d254b05b4372284..41e28698b1cc8007155e47b33d25fa1ae62bf4ba 100644 (file)
@@ -259,6 +259,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) {
   DwarfDebugInlineSection =
       Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG,
                            SectionKind::getMetadata());
+  DwarfCUIndexSection =
+      Ctx->getMachOSection("__DWARF", "__debug_cu_index", MachO::S_ATTR_DEBUG,
+                           SectionKind::getMetadata());
   StackMapSection = Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps",
                                          0, SectionKind::getMetadata());
 
@@ -531,6 +534,10 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) {
   DwarfAddrSection =
       Ctx->getELFSection(".debug_addr", ELF::SHT_PROGBITS, 0, "addr_sec");
 
+  // DWP Sections
+  DwarfCUIndexSection =
+      Ctx->getELFSection(".debug_cu_index", ELF::SHT_PROGBITS, 0);
+
   StackMapSection =
       Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
 
@@ -713,6 +720,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) {
       COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
           COFF::IMAGE_SCN_MEM_READ,
       SectionKind::getMetadata(), "addr_sec");
+  DwarfCUIndexSection = Ctx->getCOFFSection(
+      ".debug_cu_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 754450f13f3fb3ba36bb5db09904555aeec17a69..aa5ae40dc2b3b77e1a2f4cc04a172e5a6924fd79 100644 (file)
@@ -33,12 +33,13 @@ CHECK:     DW_AT_name {{.*}} "a"
 CHECK:   DW_TAG_structure_type
 CHECK:     DW_AT_name {{.*}} "foo"
 
-FIXME: Using cu_index, identify that abbr_offset is 0x0031, not 0x0000
-CHECK: 0x00000029: Compile Unit: length = 0x00000031 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0000005e)
-FIXME: Using cu_index, use strings based on the right str index offset
-CHECK:   DW_AT_name {{.*}} "a.cpp"
-FIXME: Using cu_index to find the right abbrevs at abbr_offset, this abbrevation should actually be structure_type
-CHECK:   DW_TAG_variable
+CHECK: 0x00000029: Compile Unit: length = 0x00000031 version = 0x0004 abbr_offset = 0x0031 addr_size = 0x08 (next unit at 0x0000005e)
+CHECK:   DW_AT_name {{.*}} "b.cpp"
+CHECK:   DW_TAG_structure_type
+CHECK:     DW_AT_name {{.*}} "bar"
+CHECK:   DW_TAG_subprogram
+CHECK:     DW_AT_name {{.*}} "b"
+CHECK:     DW_TAG_formal_parameter
 
 CHECK: .debug_cu_index contents:
 FIXME: Emit and verify the cu_index contents
index 9ce37ec2ceee4b8b9c0f334bdc7aef8edc6ee6fd..6617b0b23aebb6e43e6edcf489f12c08bca87f3f 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
 #include <memory>
 #include <list>
 #include <unordered_set>
@@ -85,48 +86,106 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
-  const StringMap<MCSection *> KnownSections = {
-      {"debug_info.dwo", MCOFI.getDwarfInfoDWOSection()},
-      {"debug_types.dwo", MCOFI.getDwarfTypesDWOSection()},
-      {"debug_str_offsets.dwo", StrOffsetSection},
-      {"debug_str.dwo", StrSection},
-      {"debug_loc.dwo", MCOFI.getDwarfLocDWOSection()},
-      {"debug_abbrev.dwo", MCOFI.getDwarfAbbrevDWOSection()}};
+  const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
+      {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
+      {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_TYPES}},
+      {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
+      {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
+      {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_LOC}},
+      {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}};
+
+  struct UnitIndexEntry {
+    uint64_t Signature;
+    DWARFUnitIndex::Entry::SectionContribution Contributions[8];
+  };
+
+  std::vector<UnitIndexEntry> IndexEntries;
 
   StringMap<uint32_t> Strings;
   uint32_t StringOffset = 0;
 
+  uint64_t UnitIndex = 0;
+  uint32_t ContributionOffsets[8] = {};
+
   for (const auto &Input : Inputs) {
     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
     if (!ErrOrObj)
       return ErrOrObj.getError();
-    const auto *Obj = ErrOrObj->getBinary();
+
+    IndexEntries.emplace_back();
+    UnitIndexEntry &CurEntry = IndexEntries.back();
+    CurEntry.Signature = UnitIndex++;
+
     StringRef CurStrSection;
     StringRef CurStrOffsetSection;
-    for (const auto &Section : Obj->sections()) {
+
+    for (const auto &Section : ErrOrObj->getBinary()->sections()) {
       StringRef Name;
       if (std::error_code Err = Section.getName(Name))
         return Err;
-      if (MCSection *OutSection =
-              KnownSections.lookup(Name.substr(Name.find_first_not_of("._")))) {
-        StringRef Contents;
-        if (auto Err = Section.getContents(Contents))
-          return Err;
-        if (OutSection == StrOffsetSection)
-          CurStrOffsetSection = Contents;
-        else if (OutSection == StrSection)
-          CurStrSection = Contents;
-        else {
-          Out.SwitchSection(OutSection);
-          Out.EmitBytes(Contents);
-        }
+
+      auto SectionPair =
+          KnownSections.find(Name.substr(Name.find_first_not_of("._")));
+      if (SectionPair == KnownSections.end())
+        continue;
+
+      StringRef Contents;
+      if (auto Err = Section.getContents(Contents))
+        return Err;
+
+      if (DWARFSectionKind Kind = SectionPair->second.second) {
+        auto Index = Kind - DW_SECT_INFO;
+        CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
+        ContributionOffsets[Index] +=
+            (CurEntry.Contributions[Index].Length = Contents.size());
+      }
+
+      MCSection *OutSection = SectionPair->second.first;
+      if (OutSection == StrOffsetSection)
+        CurStrOffsetSection = Contents;
+      else if (OutSection == StrSection)
+        CurStrSection = Contents;
+      else {
+        Out.SwitchSection(OutSection);
+        Out.EmitBytes(Contents);
       }
     }
+
     if (auto Err = writeStringsAndOffsets(Out, Strings, StringOffset,
                                           StrSection, StrOffsetSection,
                                           CurStrSection, CurStrOffsetSection))
       return Err;
   }
+
+  Out.SwitchSection(MCOFI.getDwarfCUIndexSection());
+  Out.EmitIntValue(2, 4);                   // Version
+  Out.EmitIntValue(8, 4);                   // Columns
+  Out.EmitIntValue(IndexEntries.size(), 4); // Num Units
+  // FIXME: This is not the right number of buckets for a real hash.
+  Out.EmitIntValue(IndexEntries.size(), 4); // Num Buckets
+
+  // Write the signatures.
+  for (const auto &E : IndexEntries)
+    Out.EmitIntValue(E.Signature, 8);
+
+  // Write the indexes.
+  for (size_t i = 0; i != IndexEntries.size(); ++i)
+    Out.EmitIntValue(i + 1, 4);
+
+  // Write the column headers (which sections will appear in the table)
+  for (size_t i = 1; i != 9; ++i)
+    Out.EmitIntValue(i, 4);
+
+  // Write the offsets.
+  for (const auto &E : IndexEntries)
+    for (const auto &C : E.Contributions)
+      Out.EmitIntValue(C.Offset, 4);
+
+  // Write the lengths.
+  for (const auto &E : IndexEntries)
+    for (const auto &C : E.Contributions)
+      Out.EmitIntValue(C.Length, 4);
+
   return std::error_code();
 }