[llvm] 16a0313 - [DWARF] Add support for 64-bit DWARF in .debug_names.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 31 01:14:10 PST 2020


Author: Igor Kudrin
Date: 2020-01-31T16:12:35+07:00
New Revision: 16a0313ee328f093682d5924eef6313cd4a8fcbe

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

LOG: [DWARF] Add support for 64-bit DWARF in .debug_names.

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

Added: 
    llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
    llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
    llvm/unittests/DebugInfo/DWARF/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index f1e02aae5564..961a8d82fe9e 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -229,7 +229,8 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
 
   /// DWARF v5 Name Index header.
   struct Header {
-    uint32_t UnitLength;
+    uint64_t UnitLength;
+    dwarf::DwarfFormat Format;
     uint16_t Version;
     uint32_t CompUnitCount;
     uint32_t LocalTypeUnitCount;
@@ -456,7 +457,10 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
 
     Error extract();
     uint64_t getUnitOffset() const { return Base; }
-    uint64_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
+    uint64_t getNextUnitOffset() const {
+      return Base + dwarf::getUnitLengthFieldByteSize(Hdr.Format) +
+             Hdr.UnitLength;
+    }
     void dump(ScopedPrinter &W) const;
 
     friend class DWARFDebugNames;

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index a5f257fe9cce..bfcd0960faec 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -377,6 +377,19 @@ void DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
 
 Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
                                              uint64_t *Offset) {
+  uint64_t StartingOffset = *Offset;
+  // Check that we can read the unit length field.
+  if (!AS.isValidOffsetForDataOfSize(StartingOffset, 4))
+    return createStringError(errc::illegal_byte_sequence,
+                             "Section too small: cannot read header.");
+  UnitLength = AS.getU32(Offset);
+  if (UnitLength >= dwarf::DW_LENGTH_lo_reserved &&
+      UnitLength != dwarf::DW_LENGTH_DWARF64)
+    return createStringError(errc::illegal_byte_sequence,
+                             "Unsupported reserved unit length value");
+  Format = (UnitLength == dwarf::DW_LENGTH_DWARF64) ? dwarf::DWARF64
+                                                    : dwarf::DWARF32;
+
   // These fields are the same for 32-bit and 64-bit DWARF formats.
   constexpr unsigned CommonHeaderSize = 2 + // Version
                                         2 + // Padding
@@ -387,14 +400,14 @@ Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
                                         4 + // Name count
                                         4 + // Abbreviations table size
                                         4;  // Augmentation string size
-  static const unsigned DWARF32HeaderFixedPartSize =
-      dwarf::getUnitLengthFieldByteSize(dwarf::DWARF32) + CommonHeaderSize;
   // Check that we can read the fixed-size part.
-  if (!AS.isValidOffsetForDataOfSize(*Offset, DWARF32HeaderFixedPartSize))
+  if (!AS.isValidOffsetForDataOfSize(
+          StartingOffset,
+          CommonHeaderSize + dwarf::getUnitLengthFieldByteSize(Format)))
     return createStringError(errc::illegal_byte_sequence,
                              "Section too small: cannot read header.");
-
-  UnitLength = AS.getU32(Offset);
+  if (Format == dwarf::DWARF64)
+    UnitLength = AS.getU64(Offset);
   Version = AS.getU16(Offset);
   // Skip padding
   *Offset += 2;
@@ -498,9 +511,10 @@ Error DWARFDebugNames::NameIndex::extract() {
   if (Error E = Hdr.extract(AS, &Offset))
     return E;
 
+  const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
   CUsBase = Offset;
-  Offset += Hdr.CompUnitCount * 4;
-  Offset += Hdr.LocalTypeUnitCount * 4;
+  Offset += Hdr.CompUnitCount * SectionOffsetSize;
+  Offset += Hdr.LocalTypeUnitCount * SectionOffsetSize;
   Offset += Hdr.ForeignTypeUnitCount * 8;
   BucketsBase = Offset;
   Offset += Hdr.BucketCount * 4;
@@ -508,9 +522,9 @@ Error DWARFDebugNames::NameIndex::extract() {
   if (Hdr.BucketCount > 0)
     Offset += Hdr.NameCount * 4;
   StringOffsetsBase = Offset;
-  Offset += Hdr.NameCount * 4;
+  Offset += Hdr.NameCount * SectionOffsetSize;
   EntryOffsetsBase = Offset;
-  Offset += Hdr.NameCount * 4;
+  Offset += Hdr.NameCount * SectionOffsetSize;
 
   if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
     return createStringError(errc::illegal_byte_sequence,
@@ -591,20 +605,24 @@ std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const {
 
 uint64_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const {
   assert(CU < Hdr.CompUnitCount);
-  uint64_t Offset = CUsBase + 4 * CU;
-  return Section.AccelSection.getRelocatedValue(4, &Offset);
+  const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
+  uint64_t Offset = CUsBase + SectionOffsetSize * CU;
+  return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
 }
 
 uint64_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const {
   assert(TU < Hdr.LocalTypeUnitCount);
-  uint64_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + TU);
-  return Section.AccelSection.getRelocatedValue(4, &Offset);
+  const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
+  uint64_t Offset = CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
+  return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
 }
 
 uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const {
   assert(TU < Hdr.ForeignTypeUnitCount);
+  const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
   uint64_t Offset =
-      CUsBase + 4 * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
+      CUsBase +
+      SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
   return Section.AccelSection.getU64(&Offset);
 }
 
@@ -625,7 +643,7 @@ DWARFDebugNames::NameIndex::getEntry(uint64_t *Offset) const {
 
   Entry E(*this, *AbbrevIt);
 
-  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
+  dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
   for (auto &Value : E.Values) {
     if (!Value.extractValue(AS, Offset, FormParams))
       return createStringError(errc::io_error,
@@ -637,12 +655,16 @@ DWARFDebugNames::NameIndex::getEntry(uint64_t *Offset) const {
 DWARFDebugNames::NameTableEntry
 DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const {
   assert(0 < Index && Index <= Hdr.NameCount);
-  uint64_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1);
-  uint64_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1);
+  const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
+  uint64_t StringOffsetOffset =
+      StringOffsetsBase + SectionOffsetSize * (Index - 1);
+  uint64_t EntryOffsetOffset =
+      EntryOffsetsBase + SectionOffsetSize * (Index - 1);
   const DWARFDataExtractor &AS = Section.AccelSection;
 
-  uint64_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset);
-  uint64_t EntryOffset = AS.getU32(&EntryOffsetOffset);
+  uint64_t StringOffset =
+      AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
+  uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
   EntryOffset += EntriesBase;
   return {Section.StringSection, Index, StringOffset, EntryOffset};
 }

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s b/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
index ccfb6fc538f7..cc3de5dcc967 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-names.s
@@ -93,6 +93,46 @@
 	.long	0                       # End of list: bar
 	.p2align	2
 .Lnames_end1:
+
+	.long	0xffffffff                  # DWARF64 mark
+	.quad	.Lnames_end2-.Lnames_start2 # Length
+.Lnames_start2:
+	.short	5                           # Version
+	.space	2                           # Padding
+	.long	1                           # CU count
+	.long	1                           # Local TU count
+	.long	1                           # Foreign TU count
+	.long	1                           # Bucket count
+	.long	1                           # Name count
+	.long	.Lnames_abbrev_end2-.Lnames_abbrev_start2   # Abbreviations table size
+	.long	0                           # Augmentation string size
+	.quad	0xcc00cccccccc              # CU0 offset
+	.quad	0xaa00aaaaaaaa              # Local TU0 offset
+	.quad	0xffffff00ffffffff          # Foreign TU2 signature
+	.long	1                           # Bucket 0
+	.long	0xb887389                   # Hash in Bucket 0
+	.quad	.Linfo_string0              # String in Bucket 0: foo
+	.quad	.Lnames3-.Lnames_entries2   # Offset in Bucket 0
+.Lnames_abbrev_start2:
+	.byte	0x01                        # Abbrev code
+	.byte	0x24                        # DW_TAG_base_type
+	.byte	0x02                        # DW_IDX_type_unit
+	.byte	0x06                        # DW_FORM_data4
+	.byte	0x05                        # DW_IDX_type_hash
+	.byte	0x07                        # DW_FORM_data8
+	.byte	0x00                        # End of abbrev
+	.byte	0x00                        # End of abbrev
+	.byte	0x00                        # End of abbrev list
+.Lnames_abbrev_end2:
+.Lnames_entries2:
+.Lnames3:
+	.byte	0x01                        # Abbrev code
+	.long	1                           # DW_IDX_type_unit
+	.quad	0xff03ffffffff              # DW_IDX_type_hash
+	.byte   0x00                        # End of list: foo
+	.p2align	2
+.Lnames_end2:
+
 # CHECK: .debug_names contents:
 # CHECK-NEXT: Name Index @ 0x0 {
 # CHECK-NEXT:   Header {
@@ -172,3 +212,44 @@
 # CHECK-NEXT:     }
 # CHECK-NEXT:   ]
 # CHECK-NEXT: }
+# CHECK-NEXT: Name Index @ 0xac {
+# CHECK-NEXT:   Header {
+# CHECK-NEXT:     Length: 0x68
+# CHECK-NEXT:     Version: 5
+# CHECK-NEXT:     CU count: 1
+# CHECK-NEXT:     Local TU count: 1
+# CHECK-NEXT:     Foreign TU count: 1
+# CHECK-NEXT:     Bucket count: 1
+# CHECK-NEXT:     Name count: 1
+# CHECK-NEXT:     Abbreviations table size: 0x9
+# CHECK-NEXT:     Augmentation: ''
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Compilation Unit offsets [
+# CHECK-NEXT:     CU[0]: 0xcc00cccccccc
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Local Type Unit offsets [
+# CHECK-NEXT:     LocalTU[0]: 0xaa00aaaaaaaa
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Foreign Type Unit signatures [
+# CHECK-NEXT:     ForeignTU[0]: 0xffffff00ffffffff
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Abbreviations [
+# CHECK-NEXT:     Abbreviation 0x1 {
+# CHECK-NEXT:       Tag: DW_TAG_base_type
+# CHECK-NEXT:       DW_IDX_type_unit: DW_FORM_data4
+# CHECK-NEXT:       DW_IDX_type_hash: DW_FORM_data8
+# CHECK-NEXT:     }
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Bucket 0 [
+# CHECK-NEXT:     Name 1 {
+# CHECK-NEXT:       Hash: 0xB887389
+# CHECK-NEXT:       String: 0x00000000 "foo"
+# CHECK-NEXT:       Entry @ 0x111 {
+# CHECK-NEXT:         Abbrev: 0x1
+# CHECK-NEXT:         Tag: DW_TAG_base_type
+# CHECK-NEXT:         DW_IDX_type_unit: 0x00000001
+# CHECK-NEXT:         DW_IDX_type_hash: 0x0000ff03ffffffff
+# CHECK-NEXT:       }
+# CHECK-NEXT:     }
+# CHECK-NEXT:   ]
+# CHECK-NEXT: }

diff  --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
index 611621dbd379..68d7840b6e6d 100644
--- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
@@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_unittest(DebugInfoDWARFTests
   DwarfGenerator.cpp
   DwarfUtils.cpp
+  DWARFAcceleratorTableTest.cpp
   DWARFDebugArangeSetTest.cpp
   DWARFDebugInfoTest.cpp
   DWARFDebugLineTest.cpp

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
new file mode 100644
index 000000000000..17a4b7474bfb
--- /dev/null
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp
@@ -0,0 +1,52 @@
+//===- DWARFAcceleratorTableTest.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+void ExpectDebugNamesExtractError(StringRef NamesSecData, StringRef StrSecData,
+                                  const char *ErrorMessage) {
+  DWARFSection NamesDWARFSection;
+  NamesDWARFSection.Data = NamesSecData;
+  StringMap<std::unique_ptr<MemoryBuffer>> Sections;
+  auto Context = DWARFContext::create(Sections, /* AddrSize = */ 4,
+                                      /* isLittleEndian = */ true);
+  DWARFDataExtractor NamesExtractor(Context->getDWARFObj(), NamesDWARFSection,
+                                    /* isLittleEndian = */ true,
+                                    /* AddrSize = */ 4);
+  DataExtractor StrExtractor(StrSecData,
+                             /* isLittleEndian = */ true,
+                             /* AddrSize = */ 4);
+  DWARFDebugNames Table(NamesExtractor, StrExtractor);
+  Error E = Table.extract();
+  ASSERT_TRUE(E.operator bool());
+  EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str());
+}
+
+TEST(DWARFDebugNames, ReservedUnitLength) {
+  static const char NamesSecData[64] =
+      "\xf0\xff\xff\xff"; // Reserved unit length value
+  ExpectDebugNamesExtractError(StringRef(NamesSecData, sizeof(NamesSecData)),
+                               StringRef(),
+                               "Unsupported reserved unit length value");
+}
+
+TEST(DWARFDebugNames, TooSmallForDWARF64) {
+  // DWARF64 header takes at least 44 bytes.
+  static const char NamesSecData[43] = "\xff\xff\xff\xff"; // DWARF64 mark
+  ExpectDebugNamesExtractError(
+      StringRef(NamesSecData, sizeof(NamesSecData)), StringRef(),
+      "Section too small: cannot read header.");
+}
+
+} // end anonymous namespace


        


More information about the llvm-commits mailing list