[llvm] d1d5f0b - [DebugInfo][DWARF64] Fix dumping pre-standard .debug_str_offsets.dwo sections.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 25 05:00:07 PDT 2020


Author: Igor Kudrin
Date: 2020-04-25T18:59:41+07:00
New Revision: d1d5f0b10341fbc26c2907241124ffc2585b8ea1

URL: https://github.com/llvm/llvm-project/commit/d1d5f0b10341fbc26c2907241124ffc2585b8ea1
DIFF: https://github.com/llvm/llvm-project/commit/d1d5f0b10341fbc26c2907241124ffc2585b8ea1.diff

LOG: [DebugInfo][DWARF64] Fix dumping pre-standard .debug_str_offsets.dwo sections.

The sizes of offsets in the `.debug_str_offsets.dwo` section depend on
the format of compilation or type units referencing them: 4 bytes for
DWARF32 units and 8 bytes for DWARF64 ones. The fix uses parsed units
to determine the actual size of offsets in the corresponding part of
the `.debug_str_offsets.dwo` section.

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

Added: 
    llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s
    llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s

Modified: 
    llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
    llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index fe00baab9093..052b693f2167 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -133,11 +133,21 @@ collectContributionData(DWARFContext::unit_iterator_range Units) {
   return Contributions;
 }
 
-static void dumpDWARFv5StringOffsetsSection(
-    raw_ostream &OS, DIDumpOptions DumpOpts, StringRef SectionName,
-    const DWARFObject &Obj, const DWARFSection &StringOffsetsSection,
-    StringRef StringSection, DWARFContext::unit_iterator_range Units,
-    bool LittleEndian) {
+// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
+// string offsets section, where each compile or type unit contributes a
+// number of entries (string offsets), with each contribution preceded by
+// a header containing size and version number. Alternatively, it may be a
+// monolithic series of string offsets, as generated by the pre-DWARF v5
+// implementation of split DWARF; however, in that case we still need to
+// collect contributions of units because the size of the offsets (4 or 8
+// bytes) depends on the format of the referencing unit (DWARF32 or DWARF64).
+static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
+                                     StringRef SectionName,
+                                     const DWARFObject &Obj,
+                                     const DWARFSection &StringOffsetsSection,
+                                     StringRef StringSection,
+                                     DWARFContext::unit_iterator_range Units,
+                                     bool LittleEndian) {
   auto Contributions = collectContributionData(Units);
   DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
   DataExtractor StrData(StringSection, LittleEndian, 0);
@@ -202,49 +212,6 @@ static void dumpDWARFv5StringOffsetsSection(
   }
 }
 
-// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
-// string offsets section, where each compile or type unit contributes a
-// number of entries (string offsets), with each contribution preceded by
-// a header containing size and version number. Alternatively, it may be a
-// monolithic series of string offsets, as generated by the pre-DWARF v5
-// implementation of split DWARF.
-static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
-                                     StringRef SectionName,
-                                     const DWARFObject &Obj,
-                                     const DWARFSection &StringOffsetsSection,
-                                     StringRef StringSection,
-                                     DWARFContext::unit_iterator_range Units,
-                                     bool LittleEndian, unsigned MaxVersion) {
-  // If we have at least one (compile or type) unit with DWARF v5 or greater,
-  // we assume that the section is formatted like a DWARF v5 string offsets
-  // section.
-  if (MaxVersion >= 5)
-    dumpDWARFv5StringOffsetsSection(OS, DumpOpts, SectionName, Obj,
-                                    StringOffsetsSection, StringSection, Units,
-                                    LittleEndian);
-  else {
-    DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
-    uint64_t offset = 0;
-    uint64_t size = StringOffsetsSection.Data.size();
-    // Ensure that size is a multiple of the size of an entry.
-    if (size & ((uint64_t)(sizeof(uint32_t) - 1))) {
-      OS << "error: size of ." << SectionName << " is not a multiple of "
-         << sizeof(uint32_t) << ".\n";
-      size &= -(uint64_t)sizeof(uint32_t);
-    }
-    DataExtractor StrData(StringSection, LittleEndian, 0);
-    while (offset < size) {
-      OS << format("0x%8.8" PRIx64 ": ", offset);
-      uint64_t StringOffset = strOffsetExt.getU32(&offset);
-      OS << format("%8.8" PRIx64 "  ", StringOffset);
-      const char *S = StrData.getCStr(&StringOffset);
-      if (S)
-        OS << format("\"%s\"", S);
-      OS << "\n";
-    }
-  }
-}
-
 // Dump the .debug_addr section.
 static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
                             DIDumpOptions DumpOpts, uint16_t Version,
@@ -660,16 +627,15 @@ void DWARFContext::dump(
 
   if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
                  DObj->getStrOffsetsSection().Data))
-    dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets", *DObj,
-                             DObj->getStrOffsetsSection(),
-                             DObj->getStrSection(), normal_units(),
-                             isLittleEndian(), getMaxVersion());
+    dumpStringOffsetsSection(
+        OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
+        DObj->getStrSection(), normal_units(), isLittleEndian());
   if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
                  DObj->getStrOffsetsDWOSection().Data))
     dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
                              DObj->getStrOffsetsDWOSection(),
                              DObj->getStrDWOSection(), dwo_units(),
-                             isLittleEndian(), getMaxDWOVersion());
+                             isLittleEndian());
 
   if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
                  DObj->getGdbIndexSection())) {

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index fb24576620f4..f90204167050 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -996,11 +996,10 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
   // index table (in a package file). In a .dwo file it is simply
   // the length of the string offsets section.
   if (!IndexEntry)
-    return {
-        Optional<StrOffsetsContributionDescriptor>(
-            {0, StringOffsetSection.Data.size(), 4, DWARF32})};
+    return {Optional<StrOffsetsContributionDescriptor>(
+        {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})};
   if (C)
     return {Optional<StrOffsetsContributionDescriptor>(
-        {C->Offset, C->Length, 4, DWARF32})};
+        {C->Offset, C->Length, 4, Header.getFormat()})};
   return None;
 }

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
index 718b0f5b672c..3eccd7731f92 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
@@ -9,6 +9,5 @@
 # A degenerate section, not enough for a single entry.
         .byte 2
 
-# INVALIDSECTIONLENGTH:      .debug_str_offsets contents:
-# INVALIDSECTIONLENGTH-NOT:  contents:
-# INVALIDSECTIONLENGTH:      error: size of .debug_str_offsets is not a multiple of 4.
+# INVALIDSECTIONLENGTH: .debug_str_offsets contents:
+# INVALIDSECTIONLENGTH: 0x00000000: Gap, length = 1

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s
new file mode 100644
index 000000000000..427a90429dc7
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s
@@ -0,0 +1,95 @@
+## This tests dumping a .debug_str_offsets.dwo section which is referenced by
+## DWARF64 pre-v5 units and dumping attributes in such units which use the
+## DW_FORM_strx form.
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o - | \
+# RUN:   llvm-dwarfdump -v - | \
+# RUN:   FileCheck %s
+
+# CHECK:      .debug_info.dwo contents:
+# CHECK:      Compile Unit:
+# CHECK:      DW_TAG_compile_unit [1]
+# CHECK-NEXT:   DW_AT_name [DW_FORM_strx] (indexed (00000000) string = "Compilation Unit")
+
+# CHECK:      .debug_types.dwo contents:
+# CHECK:      Type Unit:
+# CHECK:      DW_TAG_type_unit [2] *
+# CHECK-NEXT:   DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "Type Unit")
+# CHECK:      DW_TAG_structure_type [3]  
+# CHECK-NEXT:   DW_AT_name [DW_FORM_strx] (indexed (00000002) string = "Structure")
+
+# CHECK:      .debug_str.dwo contents:
+# CHECK-NEXT: 0x00000000: "Compilation Unit"
+# CHECK-NEXT: 0x00000011: "Type Unit"
+# CHECK-NEXT: 0x0000001b: "Structure"
+
+# CHECK:      .debug_str_offsets.dwo contents:
+# CHECK-NEXT: 0x00000000: Contribution size = 24, Format = DWARF64, Version = 4
+# CHECK-NEXT: 0x00000000: 00000000 "Compilation Unit"
+# CHECK-NEXT: 0x00000008: 00000011 "Type Unit"
+# CHECK-NEXT: 0x00000010: 0000001b "Structure"
+
+    .section .debug_str.dwo, "MSe", @progbits, 1
+.LStr0:
+    .asciz "Compilation Unit"
+.LStr1:
+    .asciz "Type Unit"
+.LStr2:
+    .asciz "Structure"
+
+    .section .debug_str_offsets.dwo, "e", @progbits
+    .quad .LStr0-.debug_str.dwo     # 0: "Compilation Unit"
+    .quad .LStr1-.debug_str.dwo     # 1: "Type Unit"
+    .quad .LStr2-.debug_str.dwo     # 2: "Structure"
+
+    .section .debug_abbrev.dwo, "e", @progbits
+    .uleb128 0x01                   # Abbrev code
+    .uleb128 0x11                   # DW_TAG_compile_unit
+    .byte 0x00                      # DW_CHILDREN_no
+    .uleb128 0x03                   # DW_AT_name
+    .uleb128 0x1a                   # DW_FORM_strx
+    .byte 0x00                      # EOM(1)
+    .byte 0x00                      # EOM(2)
+    .uleb128 0x02                   # Abbrev code
+    .uleb128 0x41                   # DW_TAG_type_unit
+    .byte 0x01                      # DW_CHILDREN_yes
+    .uleb128 0x03                   # DW_AT_name
+    .uleb128 0x1a                   # DW_FORM_strx
+    .byte 0x00                      # EOM(1)
+    .byte 0x00                      # EOM(2)
+    .uleb128 0x03                   # Abbrev code
+    .uleb128 0x13                   # DW_TAG_structure_type
+    .byte 0x00                      # DW_CHILDREN_no (no members)
+    .uleb128 0x03                   # DW_AT_name
+    .uleb128 0x1a                   # DW_FORM_strx
+    .byte 0x00                      # EOM(1)
+    .byte 0x00                      # EOM(2)
+    .byte 0x00                      # EOM(3)
+
+    .section .debug_info.dwo, "e", @progbits
+    .long 0xffffffff                # DWARF64 mark
+    .quad .LCUEnd-.LCUVer           # Length
+.LCUVer:
+    .short 4                        # Version
+    .quad 0                         # Abbrev. offset
+    .byte 8                         # Address size
+    .uleb128 1                      # Abbrev [1] DW_TAG_compile_unit
+    .uleb128 0                      # DW_AT_name ("Compilation Unit")
+.LCUEnd:
+
+    .section .debug_types.dwo, "e", @progbits
+.LTU:
+    .long 0xffffffff                # DWARF64 mark
+    .quad .LTUEnd-.LTUVer           # Length
+.LTUVer:
+    .short 4                        # Version
+    .quad 0                         # Abbrev. offset
+    .byte 8                         # Address size
+    .quad 0x11110022ffffffff        # Type Signature
+    .quad .LTUType-.LTU             # Type offset
+    .uleb128 2                      # Abbrev [2] DW_TAG_type_unit
+    .uleb128 1                      # DW_AT_name ("Type Unit")
+.LTUType:
+    .uleb128 3                      # Abbrev [3] DW_TAG_structure_type
+    .uleb128 2                      # DW_AT_name ("Structure")
+.LTUEnd:

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s
new file mode 100644
index 000000000000..ac2d0cfa1c05
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s
@@ -0,0 +1,140 @@
+## This tests dumping a .debug_str_offsets.dwo section in a DWP file when it is
+## referenced by units in 
diff erent formats: one unit is DWARF32 and another
+## is DWARF64, thus the .debug_str_offsets.dwo section has contributions with
+## 
diff erent sizes of offsets.
+## This also checks that attributes in the units which use the DW_FORM_strx form
+## are dumped correctly.
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o - | \
+# RUN:   llvm-dwarfdump -v - | \
+# RUN:   FileCheck %s
+
+# CHECK:      .debug_info.dwo contents:
+# CHECK:      Compile Unit:
+# CHECK:      DW_TAG_compile_unit [1]
+# CHECK-NEXT:   DW_AT_producer [DW_FORM_strx] (indexed (00000000) string = "CU0 Producer")
+# CHECK-NEXT:   DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "CU0 Name")
+# CHECK:      Compile Unit:
+# CHECK:      DW_TAG_compile_unit [1]
+# CHECK-NEXT:   DW_AT_producer [DW_FORM_strx] (indexed (00000000) string = "CU1 Producer")
+# CHECK-NEXT:   DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "CU1 Name")
+
+# CHECK:      .debug_str.dwo contents:
+# CHECK-NEXT: 0x00000000: "CU0 Producer"
+# CHECK-NEXT: 0x0000000d: "CU0 Name"
+# CHECK-NEXT: 0x00000016: "CU1 Producer"
+# CHECK-NEXT: 0x00000023: "CU1 Name"
+
+# CHECK:      .debug_str_offsets.dwo contents:
+# CHECK-NEXT: 0x00000000: Contribution size = 8, Format = DWARF32, Version = 4
+# CHECK-NEXT: 0x00000000: 00000000 "CU0 Producer"
+# CHECK-NEXT: 0x00000004: 0000000d "CU0 Name"
+# CHECK-NEXT: 0x00000008: Contribution size = 16, Format = DWARF64, Version = 4
+# CHECK-NEXT: 0x00000008: 00000016 "CU1 Producer"
+# CHECK-NEXT: 0x00000010: 00000023 "CU1 Name"
+
+    .section .debug_str.dwo, "MSe", @progbits, 1
+.LStr0:
+    .asciz "CU0 Producer"
+.LStr1:
+    .asciz "CU0 Name"
+.LStr2:
+    .asciz "CU1 Producer"
+.LStr3:
+    .asciz "CU1 Name"
+
+    .section .debug_str_offsets.dwo, "e", @progbits
+## The contribution of CU0 (DWARF32)
+.LSO0:
+    .long .LStr0-.debug_str.dwo     # 0: "CU0 Producer"
+    .long .LStr1-.debug_str.dwo     # 1: "CU0 Name"
+.LSO0End:
+## The contribution of CU1 (DWARF64)
+.LSO1:
+    .quad .LStr2-.debug_str.dwo     # 0: "CU1 Producer"
+    .quad .LStr3-.debug_str.dwo     # 1: "CU1 Name"
+.LSO1End:
+
+    .section .debug_abbrev.dwo, "e", @progbits
+## For simplicity and to make the test shorter, both compilation units share
+## the same abbreviations table.
+.LAbbr:
+    .uleb128 0x01                   # Abbrev code
+    .uleb128 0x11                   # DW_TAG_compile_unit
+    .byte 0x00                      # DW_CHILDREN_no
+    .uleb128 0x25                   # DW_AT_producer
+    .uleb128 0x1a                   # DW_FORM_strx
+    .uleb128 0x03                   # DW_AT_name
+    .uleb128 0x1a                   # DW_FORM_strx
+    .uleb128 0x2131                 # DW_AT_GNU_dwo_id
+    .uleb128 0x07                   # DW_FORM_data8
+    .byte 0x00                      # EOM(1)
+    .byte 0x00                      # EOM(2)
+    .byte 0x00                      # EOM(3)
+.LAbbrEnd:
+
+    .section .debug_info.dwo, "e", @progbits
+## CU0 uses the 32-bit DWARF format.
+.LCU0:
+    .long .LCU0End-.LCU0Ver         # Length
+.LCU0Ver:
+    .short 4                        # Version
+    .long 0                         # Abbrev. offset
+    .byte 8                         # Address size
+    .uleb128 1                      # Abbrev [1] DW_TAG_compile_unit
+    .uleb128 0                      # DW_AT_producer ("CU0 Producer")
+    .uleb128 1                      # DW_AT_name ("CU0 Name")
+    .quad 0x1100001122222222        # DW_AT_GNU_dwo_id
+.LCU0End:
+## CU1 uses the 64-bit DWARF format.
+.LCU1:
+    .long 0xffffffff                # DWARF64 mark
+    .quad .LCU1End-.LCU1Ver           # Length
+.LCU1Ver:
+    .short 4                        # Version
+    .quad 0                         # Abbrev. offset
+    .byte 8                         # Address size
+    .uleb128 1                      # Abbrev [1] DW_TAG_compile_unit
+    .uleb128 0                      # DW_AT_producer ("CU1 Producer")
+    .uleb128 1                      # DW_AT_name ("CU1 Name")
+    .quad 0x1100001133333333        # DW_AT_GNU_dwo_id
+.LCU1End:
+
+    .section .debug_cu_index, "", @progbits
+## Header:
+    .long 2                         # Version
+    .long 3                         # Section count
+    .long 2                         # Unit count
+    .long 4                         # Slot count
+## Hash Table of Signatures:
+    .quad 0
+    .quad 0
+    .quad 0x1100001122222222        # DWO Id of CU0
+    .quad 0x1100001133333333        # DWO Id of CU1
+## Parallel Table of Indexes:
+    .long 0
+    .long 0
+    .long 1
+    .long 2
+## Table of Section Offsets:
+## Row 0:
+    .long 1                         # DW_SECT_INFO
+    .long 3                         # DW_SECT_ABBREV
+    .long 6                         # DW_SECT_STR_OFFSETS
+## Row 1, offsets of contributions of CU0:
+    .long .LCU0-.debug_info.dwo
+    .long .LAbbr-.debug_abbrev.dwo
+    .long .LSO0-.debug_str_offsets.dwo
+## Row 2, offsets of contributions of CU1:
+    .long .LCU1-.debug_info.dwo
+    .long .LAbbr-.debug_abbrev.dwo
+    .long .LSO1-.debug_str_offsets.dwo
+## Table of Section Sizes:
+## Row 1, sizes of contributions of CU0:
+    .long .LCU0End-.LCU0
+    .long .LAbbrEnd-.LAbbr
+    .long .LSO0End-.LSO0
+## Row 2, sizes of contributions of CU1:
+    .long .LCU1End-.LCU1
+    .long .LAbbrEnd-.LAbbr
+    .long .LSO1End-.LSO1


        


More information about the llvm-commits mailing list