Add support for separating strings for the split debug info DWARF5
authorEric Christopher <echristo@gmail.com>
Mon, 7 Jan 2013 19:32:41 +0000 (19:32 +0000)
committerEric Christopher <echristo@gmail.com>
Mon, 7 Jan 2013 19:32:41 +0000 (19:32 +0000)
proposal. This leaves the strings in the skeleton die as strp,
but in all dwo files they're accessed now via DW_FORM_GNU_str_index.

Add support for dumping these sections and modify the fission-cu.ll
testcase to have the correct strings and form. Fix a small bug
in the fixed form sizes routine that involved out of array accesses
for the table and add a FIXME in the extractFast routine to fix
this up.

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

12 files changed:
lib/CodeGen/AsmPrinter/DIE.cpp
lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h
lib/DebugInfo/DWARFCompileUnit.h
lib/DebugInfo/DWARFContext.cpp
lib/DebugInfo/DWARFContext.h
lib/DebugInfo/DWARFDebugInfoEntry.cpp
lib/DebugInfo/DWARFFormValue.cpp
lib/DebugInfo/DWARFFormValue.h
test/DebugInfo/X86/fission-cu.ll

index 32d6cb2c45c3aedd233306033056e690537602b1..f33f0f999d77a9d9acd84eb8f8236617f3b8115c 100644 (file)
@@ -197,6 +197,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const {
   case dwarf::DW_FORM_data4: Size = 4; break;
   case dwarf::DW_FORM_ref8:  // Fall thru
   case dwarf::DW_FORM_data8: Size = 8; break;
+  case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
   case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
   case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
   case dwarf::DW_FORM_addr:
@@ -220,6 +221,7 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const {
   case dwarf::DW_FORM_data4: return sizeof(int32_t);
   case dwarf::DW_FORM_ref8:  // Fall thru
   case dwarf::DW_FORM_data8: return sizeof(int64_t);
+  case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer);
   case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer);
   case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
   case dwarf::DW_FORM_addr:  return AP->getDataLayout().getPointerSize();
index 854d82c2c58c9be264f3a288413bcb99632a9d86..60d7cd3945a76f152916c3fe93a184ea1c6aafe8 100644 (file)
@@ -128,6 +128,27 @@ void CompileUnit::addSInt(DIE *Die, unsigned Attribute,
 /// reference to the string pool instead of immediate strings so that DIEs have
 /// more predictable sizes.
 void CompileUnit::addString(DIE *Die, unsigned Attribute, StringRef String) {
+  if (!DD->useSplitDwarf()) {
+    MCSymbol *Symb = DU->getStringPoolEntry(String);
+    DIEValue *Value;
+    if (Asm->needsRelocationsForDwarfStringPool())
+      Value = new (DIEValueAllocator) DIELabel(Symb);
+    else {
+      MCSymbol *StringPool = DU->getStringPoolSym();
+      Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool);
+    }
+    Die->addValue(Attribute, dwarf::DW_FORM_strp, Value);
+  } else {
+    unsigned idx = DU->getStringPoolIndex(String);
+    DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx);
+    Die->addValue(Attribute, dwarf::DW_FORM_GNU_str_index, Value);
+  }
+}
+
+/// addLocalString - Add a string attribute data and value. This is guaranteed
+/// to be in the local string pool instead of indirected.
+void CompileUnit::addLocalString(DIE *Die, unsigned Attribute,
+                                 StringRef String) {
   MCSymbol *Symb = DU->getStringPoolEntry(String);
   DIEValue *Value;
   if (Asm->needsRelocationsForDwarfStringPool())
index 368234ba86278c88be0624c6fc414437fa6ab3b2..f210dcc03b533c71abed83ad829d76fae1f693e8 100644 (file)
@@ -198,6 +198,10 @@ public:
   ///
   void addString(DIE *Die, unsigned Attribute, const StringRef Str);
 
+  /// addLocalString - Add a string attribute data and value.
+  ///
+  void addLocalString(DIE *Die, unsigned Attribute, const StringRef Str);
+
   /// addLabel - Add a Dwarf label attribute data and value.
   ///
   void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
index 321256a613c85bba005babef5c7a80bed42e2296..11b853f17bab7790560d41896387d24ddca9a4ca 100644 (file)
@@ -228,6 +228,16 @@ MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) {
   return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
 }
 
+unsigned DwarfUnits::getStringPoolIndex(StringRef Str) {
+  std::pair<MCSymbol*, unsigned> &Entry =
+    StringPool->GetOrCreateValue(Str).getValue();
+  if (Entry.first) return Entry.second;
+
+  Entry.second = NextStringPoolNumber++;
+  Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
+  return Entry.second;
+}
+
 // Define a unique number for the abbreviation.
 //
 void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) {
@@ -2116,12 +2126,14 @@ void DwarfDebug::emitDebugPubTypes() {
 }
 
 // Emit strings into a string section.
-void DwarfUnits::emitStrings(const MCSection *Section) {
+void DwarfUnits::emitStrings(const MCSection *StrSection,
+                             const MCSection *OffsetSection = NULL,
+                             const MCSymbol *StrSecSym = NULL) {
 
   if (StringPool->empty()) return;
 
   // Start the dwarf str section.
-  Asm->OutStreamer.SwitchSection(Section);
+  Asm->OutStreamer.SwitchSection(StrSection);
 
   // Get all of the string pool entries and put them in an array by their ID so
   // we can sort them.
@@ -2144,6 +2156,17 @@ void DwarfUnits::emitStrings(const MCSection *Section) {
                                          Entries[i].second->getKeyLength()+1),
                                0/*addrspace*/);
   }
+
+  // If we've got an offset section go ahead and emit that now as well.
+  if (OffsetSection) {
+    Asm->OutStreamer.SwitchSection(OffsetSection);
+    unsigned offset = 0;
+    unsigned size = 4;
+    for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
+      Asm->OutStreamer.EmitIntValue(offset, size, 0);
+      offset += Entries[i].second->getKeyLength() + 1;
+    }
+  }
 }
 
 // Emit visible names into a debug str section.
@@ -2377,7 +2400,7 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
                                        DIUnit.getLanguage(), Die, Asm,
                                        this, &SkeletonHolder);
   // FIXME: This should be the .dwo file.
-  NewCU->addString(Die, dwarf::DW_AT_GNU_dwo_name, FN);
+  NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, FN);
 
   // FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id.
 
@@ -2393,7 +2416,7 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
     NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
 
   if (!CompilationDir.empty())
-    NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+    NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
 
   SkeletonHolder.addUnit(NewCU);
 
@@ -2458,5 +2481,8 @@ void DwarfDebug::emitDebugAbbrevDWO() {
 // sections.
 void DwarfDebug::emitDebugStrDWO() {
   assert(useSplitDwarf() && "No split dwarf?");
-  InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection());
+  const MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection();
+  const MCSymbol *StrSym = DwarfStrSectionSym;
+  InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
+                         OffSec, StrSym);
 }
index 59e4890dec4bfebf4b883b51f9c21ff472f6510e..cc6c0f7e6380e5438d55117a840d582ea5d63940 100644 (file)
@@ -240,7 +240,7 @@ public:
                  const MCSymbol *);
 
   /// \brief Emit all of the strings to the section given.
-  void emitStrings(const MCSection *);
+  void emitStrings(const MCSection *, const MCSection *, const MCSymbol *);
 
   /// \brief Returns the entry into the start of the pool.
   MCSymbol *getStringPoolSym();
@@ -249,6 +249,10 @@ public:
   /// string text.
   MCSymbol *getStringPoolEntry(StringRef Str);
 
+  /// \brief Returns the index into the string pool with the given
+  /// string text.
+  unsigned getStringPoolIndex(StringRef Str);
+
   /// \brief Returns the string pool.
   StrPool *getStringPool() { return StringPool; }
 };
index ba638dff212d899afd9648281282a9f7f3e35a05..c58664f22342153f57e746493f3bc978c34d3c2c 100644 (file)
@@ -28,6 +28,7 @@ class DWARFCompileUnit {
   StringRef AbbrevSection;
   StringRef RangeSection;
   StringRef StringSection;
+  StringRef StringOffsetSection;
   const RelocAddrMap *RelocMap;
   bool isLittleEndian;
 
@@ -42,13 +43,16 @@ class DWARFCompileUnit {
 public:
 
   DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
-                   StringRef RS, StringRef SS, const RelocAddrMap *M, bool LE) :
+                   StringRef RS, StringRef SS, StringRef SOS,
+                   const RelocAddrMap *M, bool LE) :
     Abbrev(DA), InfoSection(IS), AbbrevSection(AS),
-    RangeSection(RS), StringSection(SS), RelocMap(M), isLittleEndian(LE) {
+    RangeSection(RS), StringSection(SS), StringOffsetSection(SOS),
+    RelocMap(M), isLittleEndian(LE) {
     clear();
   }
 
   StringRef getStringSection() const { return StringSection; }
+  StringRef getStringOffsetSection() const { return StringOffsetSection; }
   const RelocAddrMap *getRelocMap() const { return RelocMap; }
   DataExtractor getDebugInfoExtractor() const;
 
index 1270e6ec72ae5951b3595ac515cabc85d70bfedc..d6d9fcf3ea88ba2f7f94f00c10de91c560337e46 100644 (file)
@@ -152,7 +152,8 @@ void DWARFContext::parseCompileUnits() {
   while (DIData.isValidOffset(offset)) {
     CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
                                    getAbbrevSection(), getRangeSection(),
-                                   getStringSection(), &infoRelocMap(),
+                                   getStringSection(), "",
+                                   &infoRelocMap(),
                                    isLittleEndian()));
     if (!CUs.back().extract(DIData, &offset)) {
       CUs.pop_back();
@@ -172,6 +173,7 @@ void DWARFContext::parseDWOCompileUnits() {
                                       getAbbrevDWOSection(),
                                       getRangeDWOSection(),
                                       getStringDWOSection(),
+                                      getStringOffsetDWOSection(),
                                       &infoDWORelocMap(),
                                       isLittleEndian()));
     if (!DWOCUs.back().extract(DIData, &offset)) {
@@ -382,6 +384,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
       AbbrevDWOSection = data;
     else if (name == "debug_str.dwo")
       StringDWOSection = data;
+    else if (name == "debug_str_offsets.dwo")
+      StringOffsetDWOSection = data;
     // Any more debug info sections go here.
     else
       continue;
index 0c3eb30a64cae209e64f8cd7fbcb94246d62db95..c6d6283f53afbff9e1da940ec010a175b1e7590c 100644 (file)
@@ -106,6 +106,7 @@ public:
   virtual StringRef getInfoDWOSection() = 0;
   virtual StringRef getAbbrevDWOSection() = 0;
   virtual StringRef getStringDWOSection() = 0;
+  virtual StringRef getStringOffsetDWOSection() = 0;
   virtual StringRef getRangeDWOSection() = 0;
   virtual const RelocAddrMap &infoDWORelocMap() const = 0;
 
@@ -140,6 +141,7 @@ class DWARFContextInMemory : public DWARFContext {
   StringRef InfoDWOSection;
   StringRef AbbrevDWOSection;
   StringRef StringDWOSection;
+  StringRef StringOffsetDWOSection;
   StringRef RangeDWOSection;
 
 public:
@@ -157,6 +159,9 @@ public:
   virtual StringRef getInfoDWOSection() { return InfoDWOSection; }
   virtual StringRef getAbbrevDWOSection() { return AbbrevDWOSection; }
   virtual StringRef getStringDWOSection() { return StringDWOSection; }
+  virtual StringRef getStringOffsetDWOSection() {
+    return StringOffsetDWOSection;
+  }
   virtual StringRef getRangeDWOSection() { return RangeDWOSection; }
   virtual const RelocAddrMap &infoDWORelocMap() const { return InfoDWORelocMap; }
 };
index c083b8c61bc3c2446560f5b87163416aca1e986a..bb118501c11ab793ac74260acd8fe5aa774bdfda 100644 (file)
@@ -12,6 +12,7 @@
 #include "DWARFContext.h"
 #include "DWARFDebugAbbrev.h"
 #include "DWARFFormValue.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
@@ -113,9 +114,14 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
     uint32_t i;
     uint16_t form;
     for (i=0; i<numAttributes; ++i) {
+
       form = AbbrevDecl->getFormByIndex(i);
 
-      const uint8_t fixed_skip_size = fixed_form_sizes[form];
+      // FIXME: Currently we're checking if this is less than the last
+      // entry in the fixed_form_sizes table, but this should be changed
+      // to use dynamic dispatch.
+      const uint8_t fixed_skip_size = (form < DW_FORM_ref_sig8) ?
+                                       fixed_form_sizes[form] : 0;
       if (fixed_skip_size)
         offset += fixed_skip_size;
       else {
@@ -187,6 +193,8 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
           case DW_FORM_sdata:
           case DW_FORM_udata:
           case DW_FORM_ref_udata:
+          case DW_FORM_GNU_str_index:
+          case DW_FORM_GNU_addr_index:
             debug_info_data.getULEB128(&offset);
             break;
 
@@ -207,7 +215,6 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
             return false;
           }
           offset += form_size;
-
         } while (form_is_indirect);
       }
     }
@@ -327,6 +334,8 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
               case DW_FORM_sdata:
               case DW_FORM_udata:
               case DW_FORM_ref_udata:
+              case DW_FORM_GNU_str_index:
+              case DW_FORM_GNU_addr_index:
                 debug_info_data.getULEB128(&offset);
                 break;
 
index 1610db27d2cdaab4ce96dba211ef4e7f0f17491c..47fad8bcfbcc25baba8562b844438f2bf5e13e28 100644 (file)
@@ -46,8 +46,6 @@ static const uint8_t form_sizes_addr4[] = {
   0, // 0x18 DW_FORM_exprloc
   0, // 0x19 DW_FORM_flag_present
   8, // 0x20 DW_FORM_ref_sig8
-  4, // 0x1f01 DW_FORM_GNU_addr_index
-  4, // 0x1f02 DW_FORM_GNU_str_index
 };
 
 static const uint8_t form_sizes_addr8[] = {
@@ -78,8 +76,6 @@ static const uint8_t form_sizes_addr8[] = {
   0, // 0x18 DW_FORM_exprloc
   0, // 0x19 DW_FORM_flag_present
   8, // 0x20 DW_FORM_ref_sig8
-  8, // 0x1f01 DW_FORM_GNU_addr_index
-  8, // 0x1f01 DW_FORM_GNU_str_index
 };
 
 const uint8_t *
@@ -295,6 +291,8 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
     case DW_FORM_sdata:
     case DW_FORM_udata:
     case DW_FORM_ref_udata:
+    case DW_FORM_GNU_str_index:
+    case DW_FORM_GNU_addr_index:
       debug_info_data.getULEB128(offset_ptr);
       return true;
 
@@ -321,6 +319,7 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
 void
 DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
   DataExtractor debug_str_data(cu->getStringSection(), true, 0);
+  DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
   uint64_t uvalue = getUnsigned();
   bool cu_relative_offset = false;
 
@@ -379,6 +378,17 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
     }
     break;
   }
+  case DW_FORM_GNU_str_index: {
+    OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
+    const char *dbg_str = getIndirectCString(&debug_str_data,
+                                             &debug_str_offset_data);
+    if (dbg_str) {
+      OS << '"';
+      OS.write_escaped(dbg_str);
+      OS << '"';
+    }
+    break;
+  }
   case DW_FORM_ref_addr:
     OS << format("0x%016" PRIx64, uvalue);
     break;
@@ -436,6 +446,16 @@ DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
   return NULL;
 }
 
+const char*
+DWARFFormValue::getIndirectCString(const DataExtractor *DS,
+                                   const DataExtractor *DSO) const {
+  if (!DS || !DSO) return NULL;
+
+  uint32_t offset = Value.uval * 4;
+  uint32_t soffset = DSO->getULEB128(&offset);
+  return DS->getCStr(&soffset);
+}
+
 uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
   uint64_t die_offset = Value.uval;
   switch (Form) {
index c5b590db95f595892b70bf97ee9ae68c1d322d02..7768c1848fad52f0041d235d8e45ae05132196e7 100644 (file)
@@ -64,6 +64,8 @@ public:
   uint64_t getUnsigned() const { return Value.uval; }
   int64_t getSigned() const { return Value.sval; }
   const char *getAsCString(const DataExtractor *debug_str_data_ptr) const;
+  const char *getIndirectCString(const DataExtractor *,
+                                 const DataExtractor *) const;
   bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
                  const DWARFCompileUnit *cu) const;
   static bool skipValue(uint16_t form, DataExtractor debug_info_data,
index 22f59dd8a60bce62515bf99c309f111dc4af93b5..3ada3ef383f8b63762f639778eb138ba9a04a607 100644 (file)
 ; FIXME: Strings will ultimately be a different form.
 ; CHECK: .debug_info.dwo contents:
 ; CHECK: DW_TAG_compile_unit
-; CHECK: DW_AT_producer [DW_FORM_strp]
+; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] ( indexed (00000000) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)")
 ; CHECK: DW_AT_language [DW_FORM_data2]        (0x000c)
-; CHECK: DW_AT_name [DW_FORM_strp]             ( .debug_str[0x00000035] = "baz.c")
+; CHECK: DW_AT_name [DW_FORM_GNU_str_index]    ( indexed (00000001) string = "baz.c")
 ; CHECK: DW_TAG_base_type
-; CHECK: DW_AT_name [DW_FORM_strp]      ( .debug_str[0x00000061] = "int")
+; CHECK: DW_AT_name [DW_FORM_GNU_str_index]     ( indexed (00000004) string = "int")
 ; CHECK: DW_TAG_variable
-; CHECK: DW_AT_name [DW_FORM_strp]     ( .debug_str[0x0000005f] = "a")
+; CHECK: DW_AT_name [DW_FORM_GNU_str_index]     ( indexed (00000003) string = "a")