[llvm] r337910 - dwarfgen: Add support for generating the debug_str_offsets section

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 25 04:55:59 PDT 2018


Author: labath
Date: Wed Jul 25 04:55:59 2018
New Revision: 337910

URL: http://llvm.org/viewvc/llvm-project?rev=337910&view=rev
Log:
dwarfgen: Add support for generating the debug_str_offsets section

Summary:
The motivation for this is D49493, where we'd like to test details of
debug_str_offsets behavior which is difficult to trigger from a
traditional test.

This adds the plubming necessary for dwarfgen to generate this section.
The more interesting changes are:
- I've moved emitStringOffsetsTableHeader function from DwarfFile to
  DwarfStringPool, so I can generate the section header more easily from
  the unit test.
- added a new addAttribute overload taking an MCExpr*. This is used to
  generate the DW_AT_str_offsets_base, which links a compile unit to the
  offset table.

I've also added a basic test for reading and writing DW_form_strx forms.

Reviewers: dblaikie, JDevlieghere, probinson

Subscribers: llvm-commits, aprantl

Differential Revision: https://reviews.llvm.org/D49670

Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h
    llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
    llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
    llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Wed Jul 25 04:55:59 2018
@@ -1506,8 +1506,9 @@ void DwarfDebug::emitAbbreviations() {
 
 void DwarfDebug::emitStringOffsetsTableHeader() {
   DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
-  Holder.emitStringOffsetsTableHeader(
-      Asm->getObjFileLowering().getDwarfStrOffSection());
+  Holder.getStringPool().emitStringOffsetsTableHeader(
+      *Asm, Asm->getObjFileLowering().getDwarfStrOffSection(),
+      Holder.getStringOffsetsStartSym());
 }
 
 template <typename AccelTableT>
@@ -2292,8 +2293,9 @@ void DwarfDebug::emitDebugLineDWO() {
 
 void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
   assert(useSplitDwarf() && "No split dwarf?");
-  InfoHolder.emitStringOffsetsTableHeader(
-      Asm->getObjFileLowering().getDwarfStrOffDWOSection());
+  InfoHolder.getStringPool().emitStringOffsetsTableHeader(
+      *Asm, Asm->getObjFileLowering().getDwarfStrOffDWOSection(),
+      InfoHolder.getStringOffsetsStartSym());
 }
 
 // Emit the .debug_str.dwo section for separated dwarf. This contains the

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp Wed Jul 25 04:55:59 2018
@@ -28,26 +28,6 @@ void DwarfFile::addUnit(std::unique_ptr<
   CUs.push_back(std::move(U));
 }
 
-void DwarfFile::emitStringOffsetsTableHeader(MCSection *Section) {
-  if (StrPool.empty())
-    return;
-  Asm->OutStreamer->SwitchSection(Section);
-  unsigned EntrySize = 4;
-  // FIXME: DWARF64
-  // We are emitting the header for a contribution to the string offsets
-  // table. The header consists of an entry with the contribution's
-  // size (not including the size of the length field), the DWARF version and
-  // 2 bytes of padding.
-  Asm->emitInt32(StrPool.size() * EntrySize + 4);
-  Asm->emitInt16(Asm->getDwarfVersion());
-  Asm->emitInt16(0);
-  // Define the symbol that marks the start of the contribution. It is
-  // referenced by most unit headers via DW_AT_str_offsets_base.
-  // Split units do not use the attribute.
-  if (StringOffsetsStartSym)
-    Asm->OutStreamer->EmitLabel(StringOffsetsStartSym);
-}
-
 // Emit the various dwarf units to the unit section USection with
 // the abbreviations going into ASection.
 void DwarfFile::emitUnits(bool UseOffsets) {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h Wed Jul 25 04:55:59 2018
@@ -91,9 +91,6 @@ public:
   /// Add a unit to the list of CUs.
   void addUnit(std::unique_ptr<DwarfCompileUnit> U);
 
-  /// Emit the string table offsets header.
-  void emitStringOffsetsTableHeader(MCSection *Section);
-
   /// Emit all of the units to the section listed with the given
   /// abbreviation section.
   void emitUnits(bool UseOffsets);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp Wed Jul 25 04:55:59 2018
@@ -39,6 +39,28 @@ DwarfStringPool::EntryRef DwarfStringPoo
   return EntryRef(*I.first);
 }
 
+void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
+                                                   MCSection *Section,
+                                                   MCSymbol *StartSym) {
+  if (empty())
+    return;
+  Asm.OutStreamer->SwitchSection(Section);
+  unsigned EntrySize = 4;
+  // FIXME: DWARF64
+  // We are emitting the header for a contribution to the string offsets
+  // table. The header consists of an entry with the contribution's
+  // size (not including the size of the length field), the DWARF version and
+  // 2 bytes of padding.
+  Asm.emitInt32(size() * EntrySize + 4);
+  Asm.emitInt16(Asm.getDwarfVersion());
+  Asm.emitInt16(0);
+  // Define the symbol that marks the start of the contribution. It is
+  // referenced by most unit headers via DW_AT_str_offsets_base.
+  // Split units do not use the attribute.
+  if (StartSym)
+    Asm.OutStreamer->EmitLabel(StartSym);
+}
+
 void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
                            MCSection *OffsetSection, bool UseRelativeOffsets) {
   if (Pool.empty())

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h Wed Jul 25 04:55:59 2018
@@ -19,6 +19,7 @@ namespace llvm {
 
 class AsmPrinter;
 class MCSection;
+class MCSymbol;
 
 // Collection of strings for this unit and assorted symbols.
 // A String->Symbol mapping of strings used by indirect
@@ -36,6 +37,9 @@ public:
 
   DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix);
 
+  void emitStringOffsetsTableHeader(AsmPrinter &Asm, MCSection *OffsetSection,
+                                    MCSymbol *StartSym);
+
   void emit(AsmPrinter &Asm, MCSection *StrSection,
             MCSection *OffsetSection = nullptr,
             bool UseRelativeOffsets = false);

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Wed Jul 25 04:55:59 2018
@@ -67,12 +67,23 @@ void TestAllForms() {
   const uint32_t Dwarf32Values[] = {1, 2, 3, 4, 5, 6, 7, 8};
   const char *StringValue = "Hello";
   const char *StrpValue = "World";
+  const char *StrxValue = "Indexed";
+  const char *Strx1Value = "Indexed1";
+  const char *Strx2Value = "Indexed2";
+  const char *Strx3Value = "Indexed3";
+  const char *Strx4Value = "Indexed4";
 
   auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
   ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
   dwarfgen::Generator *DG = ExpectedDG.get().get();
   dwarfgen::CompileUnit &CU = DG->addCompileUnit();
   dwarfgen::DIE CUDie = CU.getUnitDIE();
+
+  if (Version >= 5)
+    CUDie.addAttribute(dwarf::DW_AT_str_offsets_base, dwarf::DW_FORM_sec_offset,
+                       MCSymbolRefExpr::create(DG->getStringOffsetsStartSym(),
+                                               *DG->getMCContext()));
+
   uint16_t Attr = DW_AT_lo_user;
 
   //----------------------------------------------------------------------
@@ -122,6 +133,19 @@ void TestAllForms() {
   const auto Attr_DW_FORM_string = static_cast<dwarf::Attribute>(Attr++);
   CUDie.addAttribute(Attr_DW_FORM_string, DW_FORM_string, StringValue);
 
+  const auto Attr_DW_FORM_strx = static_cast<dwarf::Attribute>(Attr++);
+  const auto Attr_DW_FORM_strx1 = static_cast<dwarf::Attribute>(Attr++);
+  const auto Attr_DW_FORM_strx2 = static_cast<dwarf::Attribute>(Attr++);
+  const auto Attr_DW_FORM_strx3 = static_cast<dwarf::Attribute>(Attr++);
+  const auto Attr_DW_FORM_strx4 = static_cast<dwarf::Attribute>(Attr++);
+  if (Version >= 5) {
+    CUDie.addAttribute(Attr_DW_FORM_strx, DW_FORM_strx, StrxValue);
+    CUDie.addAttribute(Attr_DW_FORM_strx1, DW_FORM_strx1, Strx1Value);
+    CUDie.addAttribute(Attr_DW_FORM_strx2, DW_FORM_strx2, Strx2Value);
+    CUDie.addAttribute(Attr_DW_FORM_strx3, DW_FORM_strx3, Strx3Value);
+    CUDie.addAttribute(Attr_DW_FORM_strx4, DW_FORM_strx4, Strx4Value);
+  }
+
   const auto Attr_DW_FORM_strp = static_cast<dwarf::Attribute>(Attr++);
   CUDie.addAttribute(Attr_DW_FORM_strp, DW_FORM_strp, StrpValue);
 
@@ -281,11 +305,33 @@ void TestAllForms() {
   //----------------------------------------------------------------------
   auto ExtractedStringValue = toString(DieDG.find(Attr_DW_FORM_string));
   EXPECT_TRUE((bool)ExtractedStringValue);
-  EXPECT_TRUE(strcmp(StringValue, *ExtractedStringValue) == 0);
+  EXPECT_STREQ(StringValue, *ExtractedStringValue);
+
+  if (Version >= 5) {
+    auto ExtractedStrxValue = toString(DieDG.find(Attr_DW_FORM_strx));
+    EXPECT_TRUE((bool)ExtractedStrxValue);
+    EXPECT_STREQ(StrxValue, *ExtractedStrxValue);
+
+    auto ExtractedStrx1Value = toString(DieDG.find(Attr_DW_FORM_strx1));
+    EXPECT_TRUE((bool)ExtractedStrx1Value);
+    EXPECT_STREQ(Strx1Value, *ExtractedStrx1Value);
+
+    auto ExtractedStrx2Value = toString(DieDG.find(Attr_DW_FORM_strx2));
+    EXPECT_TRUE((bool)ExtractedStrx2Value);
+    EXPECT_STREQ(Strx2Value, *ExtractedStrx2Value);
+
+    auto ExtractedStrx3Value = toString(DieDG.find(Attr_DW_FORM_strx3));
+    EXPECT_TRUE((bool)ExtractedStrx3Value);
+    EXPECT_STREQ(Strx3Value, *ExtractedStrx3Value);
+
+    auto ExtractedStrx4Value = toString(DieDG.find(Attr_DW_FORM_strx4));
+    EXPECT_TRUE((bool)ExtractedStrx4Value);
+    EXPECT_STREQ(Strx4Value, *ExtractedStrx4Value);
+  }
 
   auto ExtractedStrpValue = toString(DieDG.find(Attr_DW_FORM_strp));
   EXPECT_TRUE((bool)ExtractedStrpValue);
-  EXPECT_TRUE(strcmp(StrpValue, *ExtractedStrpValue) == 0);
+  EXPECT_STREQ(StrpValue, *ExtractedStrpValue);
 
   //----------------------------------------------------------------------
   // Test reference forms

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp Wed Jul 25 04:55:59 2018
@@ -54,16 +54,36 @@ void dwarfgen::DIE::addAttribute(uint16_
 }
 
 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
+                                 const MCExpr *Expr) {
+  auto &DG = CU->getGenerator();
+  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+                DIEExpr(Expr));
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
                                  StringRef String) {
   auto &DG = CU->getGenerator();
-  if (Form == DW_FORM_string) {
+  switch (Form) {
+  case DW_FORM_string:
     Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
                   new (DG.getAllocator())
                       DIEInlineString(String, DG.getAllocator()));
-  } else {
+    break;
+
+  case DW_FORM_strp:
+  case DW_FORM_GNU_str_index:
+  case DW_FORM_strx:
+  case DW_FORM_strx1:
+  case DW_FORM_strx2:
+  case DW_FORM_strx3:
+  case DW_FORM_strx4:
     Die->addValue(
         DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
         DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
+    break;
+
+  default:
+    llvm_unreachable("Unhandled form!");
   }
 }
 
@@ -427,6 +447,7 @@ llvm::Error dwarfgen::Generator::init(Tr
   Asm->setDwarfVersion(Version);
 
   StringPool = llvm::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
+  StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");
 
   return Error::success();
 }
@@ -448,7 +469,12 @@ StringRef dwarfgen::Generator::generate(
     CU->setLength(CUOffset - 4);
   }
   Abbreviations.Emit(Asm.get(), MOFI->getDwarfAbbrevSection());
-  StringPool->emit(*Asm, MOFI->getDwarfStrSection());
+
+  StringPool->emitStringOffsetsTableHeader(*Asm, MOFI->getDwarfStrOffSection(),
+                                           StringOffsetsStartSym);
+  StringPool->emit(*Asm, MOFI->getDwarfStrSection(),
+                   MOFI->getDwarfStrOffSection());
+
   MS->SwitchSection(MOFI->getDwarfInfoSection());
   for (auto &CU : CompileUnits) {
     uint16_t Version = CU->getVersion();

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h?rev=337910&r1=337909&r2=337910&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h Wed Jul 25 04:55:59 2018
@@ -89,6 +89,14 @@ public:
   /// \param U the unsigned integer to encode.
   void addAttribute(uint16_t Attr, dwarf::Form Form, uint64_t U);
 
+  /// Add an attribute value to be encoded as a DIEExpr
+  ///
+  /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+  /// represents a user defined DWARF attribute.
+  /// \param Form the dwarf::Form to use when encoding the attribute.
+  /// \param Expr the MC expression used to compute the value
+  void addAttribute(uint16_t Attr, dwarf::Form Form, const MCExpr *Expr);
+
   /// Add an attribute value to be encoded as a DIEString or DIEInlinedString.
   ///
   /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
@@ -242,6 +250,8 @@ class Generator {
   std::vector<std::unique_ptr<LineTable>> LineTables;
   DIEAbbrevSet Abbreviations;
 
+  MCSymbol *StringOffsetsStartSym;
+
   SmallString<4096> FileBytes;
   /// The stream we use to generate the DWARF into as an ELF file.
   std::unique_ptr<raw_svector_ostream> Stream;
@@ -293,6 +303,7 @@ public:
   MCContext *getMCContext() const { return MC.get(); }
   DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
   DwarfStringPool &getStringPool() { return *StringPool; }
+  MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; }
 
   /// Save the generated DWARF file to disk.
   ///




More information about the llvm-commits mailing list