[llvm] af11c55 - [DebugInfo] Fix reading DWARFv5 type units in DWP.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 7 23:15:30 PDT 2020


Author: Igor Kudrin
Date: 2020-04-08T12:50:58+07:00
New Revision: af11c556dbcee06b4511a6c5761f4cbd543d0047

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

LOG: [DebugInfo] Fix reading DWARFv5 type units in DWP.

In DWARFv5, type units are stored in .debug_info sections, along with
compilation units, and they are distinguished by the unit_type field
in the header, not by the name of the section. It is impossible to
associate the correct index section of a DWP file with the unit before
the unit's header is read. This patch fixes reading DWARFv5 type units
by parsing the header first and then applying the index entry according
to the actual unit type.

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

Added: 
    llvm/test/DebugInfo/X86/dwp-v5-tu.s

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
    llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
    llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 635c437fff10..cb9e2c32a640 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -70,10 +70,14 @@ class DWARFUnitHeader {
 
 public:
   /// Parse a unit header from \p debug_info starting at \p offset_ptr.
+  /// Note that \p SectionKind is used as a hint to guess the unit type
+  /// for DWARF formats prior to DWARFv5. In DWARFv5 the unit type is
+  /// explicitly defined in the header and the hint is ignored.
   bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
-               uint64_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO,
-               const DWARFUnitIndex *Index = nullptr,
-               const DWARFUnitIndex::Entry *Entry = nullptr);
+               uint64_t *offset_ptr, DWARFSectionKind SectionKind);
+  // For units in DWARF Package File, remember the index entry and update
+  // the abbreviation offset read by extract().
+  bool applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
   uint64_t getOffset() const { return Offset; }
   const dwarf::FormParams &getFormParams() const { return FormParams; }
   uint16_t getVersion() const { return FormParams.Version; }

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 5fb3b7616268..31c5cc8c076d 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -73,12 +73,15 @@ void DWARFUnitVector::addUnitsImpl(
       DWARFDataExtractor Data(Obj, InfoSection, LE, 0);
       if (!Data.isValidOffset(Offset))
         return nullptr;
-      const DWARFUnitIndex *Index = nullptr;
-      if (IsDWO)
-        Index = &getDWARFUnitIndex(Context, SectionKind);
       DWARFUnitHeader Header;
-      if (!Header.extract(Context, Data, &Offset, SectionKind, Index,
-                          IndexEntry))
+      if (!Header.extract(Context, Data, &Offset, SectionKind))
+        return nullptr;
+      if (!IndexEntry && IsDWO) {
+        const DWARFUnitIndex &Index = getDWARFUnitIndex(
+            Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO);
+        IndexEntry = Index.getFromOffset(Header.getOffset());
+      }
+      if (IndexEntry && !Header.applyIndexEntry(IndexEntry))
         return nullptr;
       std::unique_ptr<DWARFUnit> U;
       if (Header.isTypeUnit())
@@ -251,14 +254,10 @@ Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const {
 bool DWARFUnitHeader::extract(DWARFContext &Context,
                               const DWARFDataExtractor &debug_info,
                               uint64_t *offset_ptr,
-                              DWARFSectionKind SectionKind,
-                              const DWARFUnitIndex *Index,
-                              const DWARFUnitIndex::Entry *Entry) {
+                              DWARFSectionKind SectionKind) {
   Offset = *offset_ptr;
   Error Err = Error::success();
-  IndexEntry = Entry;
-  if (!IndexEntry && Index)
-    IndexEntry = Index->getFromOffset(*offset_ptr);
+  IndexEntry = nullptr;
   std::tie(Length, FormParams.Format) =
       debug_info.getInitialLength(offset_ptr, &Err);
   FormParams.Version = debug_info.getU16(offset_ptr, &Err);
@@ -288,19 +287,6 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
   if (errorToBool(std::move(Err)))
     return false;
 
-  if (IndexEntry) {
-    if (AbbrOffset)
-      return false;
-    auto *UnitContrib = IndexEntry->getContribution();
-    if (!UnitContrib ||
-        UnitContrib->Length != (Length + getUnitLengthFieldByteSize()))
-      return false;
-    auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
-    if (!AbbrEntry)
-      return false;
-    AbbrOffset = AbbrEntry->Offset;
-  }
-
   // Header fields all parsed, capture the size of this unit header.
   assert(*offset_ptr - Offset <= 255 && "unexpected header size");
   Size = uint8_t(*offset_ptr - Offset);
@@ -324,6 +310,23 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
   return true;
 }
 
+bool DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) {
+  assert(Entry);
+  assert(!IndexEntry);
+  IndexEntry = Entry;
+  if (AbbrOffset)
+    return false;
+  auto *UnitContrib = IndexEntry->getContribution();
+  if (!UnitContrib ||
+      UnitContrib->Length != (getLength() + getUnitLengthFieldByteSize()))
+    return false;
+  auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
+  if (!AbbrEntry)
+    return false;
+  AbbrOffset = AbbrEntry->Offset;
+  return true;
+}
+
 // Parse the rangelist table header, including the optional array of offsets
 // following it (DWARF v5 and later).
 template<typename ListTableType>

diff  --git a/llvm/test/DebugInfo/X86/dwp-v5-tu.s b/llvm/test/DebugInfo/X86/dwp-v5-tu.s
new file mode 100644
index 000000000000..91acb1d9f3b6
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/dwp-v5-tu.s
@@ -0,0 +1,76 @@
+## The test checks that we can read DWARFv5 type units in DWP files.
+
+# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o - | \
+# RUN:   llvm-dwarfdump -debug-info - | \
+# RUN:   FileCheck %s
+
+# CHECK:      .debug_info.dwo contents:
+# CHECK:      Type Unit:
+# CHECK:      DW_TAG_type_unit
+# CHECK-NEXT:   DW_AT_visibility (DW_VIS_local)
+# CHECK:      DW_TAG_structure_type
+# CHECK-NEXT:   DW_AT_name ("foo")
+
+    .section .debug_abbrev.dwo, "e", @progbits
+## Reserve some space in the section so that the abbreviation table for the type
+## unit does not start at the beginning of the section and thus the base offset
+## from the index section should be added to find the correct offset.
+    .space 16
+.LAbbrevBegin:
+    .uleb128 1                              # Abbrev code
+    .uleb128 0x41                           # DW_TAG_type_unit
+    .byte 1                                 # DW_CHILDREN_yes
+    .uleb128 0x17                           # DW_AT_visibility
+    .uleb128 0x0b                           # DW_FORM_data1
+    .byte 0                                 # EOM(1)
+    .byte 0                                 # EOM(2)
+    .uleb128 2                              # Abbrev code
+    .uleb128 0x13                           # DW_TAG_structure_type
+    .byte 0                                 # DW_CHILDREN_no
+    .uleb128 0x03                           # DW_AT_name
+    .uleb128 0x08                           # DW_FORM_string
+    .byte 0                                 # EOM(1)
+    .byte 0                                 # EOM(2)
+    .byte 0                                 # EOM(3)
+.LAbbrevEnd:
+
+    .section .debug_info.dwo, "e", @progbits
+.LTUBegin:
+    .long .LTUEnd-.LTUVersion               # Length of Unit
+.LTUVersion:
+    .short 5                                # DWARF version number
+    .byte 6                                 # DW_UT_split_type
+    .byte 8                                 # Address Size (in bytes)
+    .long 0                                 # Offset Into Abbrev. Section
+    .quad 0x1100001122222222                # Type Signature
+    .long .LTUType-.LTUBegin                # Type offset
+    .uleb128 1                              # Abbrev [1] DW_TAG_type_unit
+    .byte 1                                 # DW_AT_visibility
+.LTUType:
+    .uleb128 2                              # Abbrev [2] DW_TAG_structure_type
+    .asciz "foo"                            # DW_AT_name
+.LTUEnd:
+
+    .section .debug_tu_index, "", @progbits
+## Header:
+    .short 5                                # Version
+    .space 2                                # Padding
+    .long 2                                 # Section count
+    .long 1                                 # Unit count
+    .long 2                                 # Slot count
+## Hash Table of Signatures:
+    .quad 0x1100001122222222
+    .quad 0
+## Parallel Table of Indexes:
+    .long 1
+    .long 0
+## Table of Section Offsets:
+## Row 0:
+    .long 1                                 # DW_SECT_INFO
+    .long 3                                 # DW_SECT_ABBREV
+## Row 1:
+    .long 0                                 # Offset in .debug_info.dwo
+    .long .LAbbrevBegin-.debug_abbrev.dwo   # Offset in .debug_abbrev.dwo
+## Table of Section Sizes:
+    .long .LTUEnd-.LTUBegin                 # Size in .debug_info.dwo
+    .long .LAbbrevEnd-.LAbbrevBegin         # Size in .debug_abbrev.dwo

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index 1e7149e45bb1..c9823201f554 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -3166,7 +3166,7 @@ TEST(DWARFDebugInfo, TestDWARF64UnitLength) {
     DWARFDataExtractor Data(Obj, Sec, /* IsLittleEndian = */ true,
                             /* AddressSize = */ 4);
     uint64_t Offset = 0;
-    EXPECT_FALSE(Header.extract(*Context, Data, &Offset));
+    EXPECT_FALSE(Header.extract(*Context, Data, &Offset, DW_SECT_INFO));
     // Header.extract() returns false because there is not enough space
     // in the section for the declared length. Anyway, we can check that
     // the properties are read correctly.


        


More information about the llvm-commits mailing list