DebugInfo: .debug_line DWARF64 support
authorEd Maste <emaste@freebsd.org>
Thu, 28 May 2015 15:38:17 +0000 (15:38 +0000)
committerEd Maste <emaste@freebsd.org>
Thu, 28 May 2015 15:38:17 +0000 (15:38 +0000)
This adds support for the 64-bit DWARF format, but is still limited to
less than 4GB of debug data by the DataExtractor class.  Some versions
of the GNU MIPS toolchain generate 64-Bit DWARF even though it isn't
actually necessary.

Differential Revision: http://reviews.llvm.org/D1988

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

include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
lib/DebugInfo/DWARF/DWARFDebugLine.cpp
test/DebugInfo/Inputs/dwarfdump.elf-mips64-64-bit-dwarf [new file with mode: 0755]
test/DebugInfo/dwarfdump-64-bit-dwarf.test [new file with mode: 0644]

index 37b22c2e82f62393d04b3b918a443839f4e09df8..5f223d4dc4e681a864927a2fd72e8f2fc394bd3e 100644 (file)
@@ -38,12 +38,12 @@ public:
 
     // The size in bytes of the statement information for this compilation unit
     // (not including the total_length field itself).
-    uint32_t TotalLength;
+    uint64_t TotalLength;
     // Version identifier for the statement information format.
     uint16_t Version;
     // The number of bytes following the prologue_length field to the beginning
     // of the first byte of the statement program itself.
-    uint32_t PrologueLength;
+    uint64_t PrologueLength;
     // The size in bytes of the smallest target machine instruction. Statement
     // program opcodes that alter the address register first multiply their
     // operands by this value.
@@ -63,14 +63,22 @@ public:
     std::vector<const char*> IncludeDirectories;
     std::vector<FileNameEntry> FileNames;
 
+    bool IsDWARF64;
+    uint32_t sizeofTotalLength() const {
+      return IsDWARF64 ? 12 : 4;
+    }
+    uint32_t sizeofPrologueLength() const {
+      return IsDWARF64 ? 8 : 4;
+    }
+
     // Length of the prologue in bytes.
     uint32_t getLength() const {
-      return PrologueLength + sizeof(TotalLength) + sizeof(Version) +
-             sizeof(PrologueLength);
+      return PrologueLength + sizeofTotalLength() + sizeof(Version) +
+             sizeofPrologueLength();
     }
     // Length of the line table data in bytes (not including the prologue).
     uint32_t getStatementTableLength() const {
-      return TotalLength + sizeof(TotalLength) - getLength();
+      return TotalLength + sizeofTotalLength() - getLength();
     }
     int32_t getMaxLineIncrementForSpecialOpcode() const {
       return LineBase + (int8_t)LineRange - 1;
index b63af6a64ee408c3dc87db2aaac0ff7cc2568c96..2a737ef788fc63e92872fe74050ac4e07ee4d883 100644 (file)
@@ -25,6 +25,7 @@ void DWARFDebugLine::Prologue::clear() {
   TotalLength = Version = PrologueLength = 0;
   MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
   OpcodeBase = 0;
+  IsDWARF64 = false;
   StandardOpcodeLengths.clear();
   IncludeDirectories.clear();
   FileNames.clear();
@@ -32,9 +33,9 @@ void DWARFDebugLine::Prologue::clear() {
 
 void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
   OS << "Line table prologue:\n"
-     << format("    total_length: 0x%8.8x\n", TotalLength)
+     << format("    total_length: 0x%8.8" PRIx64 "\n", TotalLength)
      << format("         version: %u\n", Version)
-     << format(" prologue_length: 0x%8.8x\n", PrologueLength)
+     << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
      << format(" min_inst_length: %u\n", MinInstLength)
      << format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
      << format(" default_is_stmt: %u\n", DefaultIsStmt)
@@ -67,16 +68,23 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
 
 bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data,
                                      uint32_t *offset_ptr) {
-  const uint32_t prologue_offset = *offset_ptr;
+  const uint64_t prologue_offset = *offset_ptr;
 
   clear();
   TotalLength = debug_line_data.getU32(offset_ptr);
+  if (TotalLength == UINT32_MAX) {
+    IsDWARF64 = true;
+    TotalLength = debug_line_data.getU64(offset_ptr);
+  } else if (TotalLength > 0xffffff00) {
+    return false;
+  }
   Version = debug_line_data.getU16(offset_ptr);
   if (Version < 2)
     return false;
 
-  PrologueLength = debug_line_data.getU32(offset_ptr);
-  const uint32_t end_prologue_offset = PrologueLength + *offset_ptr;
+  PrologueLength = debug_line_data.getUnsigned(offset_ptr,
+                                               sizeofPrologueLength());
+  const uint64_t end_prologue_offset = PrologueLength + *offset_ptr;
   MinInstLength = debug_line_data.getU8(offset_ptr);
   if (Version >= 4)
     MaxOpsPerInst = debug_line_data.getU8(offset_ptr);
@@ -114,9 +122,10 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data,
   }
 
   if (*offset_ptr != end_prologue_offset) {
-    fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should"
-                    " have ended at 0x%8.8x but it ended at 0x%8.8x\n",
-            prologue_offset, end_prologue_offset, *offset_ptr);
+    fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64
+                    " should have ended at 0x%8.8" PRIx64
+                    " but it ended at 0x%8.8" PRIx64 "\n",
+            prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr);
     return false;
   }
   return true;
@@ -258,7 +267,7 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
   }
 
   const uint32_t end_offset = debug_line_offset + Prologue.TotalLength +
-                              sizeof(Prologue.TotalLength);
+                              Prologue.sizeofTotalLength();
 
   ParsingState State(this);
 
diff --git a/test/DebugInfo/Inputs/dwarfdump.elf-mips64-64-bit-dwarf b/test/DebugInfo/Inputs/dwarfdump.elf-mips64-64-bit-dwarf
new file mode 100755 (executable)
index 0000000..5dbfea5
Binary files /dev/null and b/test/DebugInfo/Inputs/dwarfdump.elf-mips64-64-bit-dwarf differ
diff --git a/test/DebugInfo/dwarfdump-64-bit-dwarf.test b/test/DebugInfo/dwarfdump-64-bit-dwarf.test
new file mode 100644 (file)
index 0000000..0a24414
--- /dev/null
@@ -0,0 +1,15 @@
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump.elf-mips64-64-bit-dwarf \
+RUN:   --debug-dump=line | FileCheck %s
+
+# FIXME: llvm-dwarfdump's support for 64-bit dwarf is currently limited to
+# .debug_line.
+
+CHECK:   total_length: 0x00000212
+CHECK:        version: 2
+CHECK:prologue_length: 0x000001ab
+CHECK:min_inst_length: 1
+CHECK:default_is_stmt: 1
+CHECK:      line_base: -5
+CHECK:     line_range: 14
+CHECK:    opcode_base: 13
+CHECK: is_stmt end_sequence