[PATCH] Initial DWARF64 support for .debug_line

Ed Maste emaste at freebsd.org
Wed Oct 23 08:05:46 PDT 2013


  Added comments and a basic test

  (Comments are in DWARFContext.h as that seemed to be a more clear reference to the individual classes.)

Hi echristo,

http://llvm-reviews.chandlerc.com/D1988

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1988?vs=5061&id=5096#toc

Files:
  lib/DebugInfo/DWARFContext.h
  lib/DebugInfo/DWARFDebugLine.cpp
  lib/DebugInfo/DWARFDebugLine.h
  test/DebugInfo/Inputs/dwarfdump-inl-test.elf-mips64-64-bit-dwarf
  test/DebugInfo/dwarfdump-64-bit-dwarf.test

Index: lib/DebugInfo/DWARFContext.h
===================================================================
--- lib/DebugInfo/DWARFContext.h
+++ lib/DebugInfo/DWARFContext.h
@@ -27,6 +27,22 @@
 /// This data structure is the top level entity that deals with dwarf debug
 /// information parsing. The actual data is supplied through pure virtual
 /// methods that a concrete implementation provides.
+///
+/// 7.4 32-Bit and 64-Bit DWARF Formats
+/// DWARF Version 3 specifies the 64-Bit format, which uses 0xffffffff in
+/// the 32-bit initial length field to signal that the actual length and
+/// later offsets are 64-Bit.  Partial support is implemented to handle
+/// 64-Bit DWARF emitted by some toolchains, even though it is not
+/// actually necessary (the debug data is not > 4GB).
+///
+/// Class              64-bit support  Notes
+/// DataExtractor      No              Prevents handling debug data >4GB
+/// DWARFDebugAbbrev   No
+/// DWARFDebugLoc      No
+/// DWARFDebugAranges  No
+/// DWARFDebugLine     Yes
+/// DWARFDebugFrame    Yes
+///
 class DWARFContext : public DIContext {
   SmallVector<DWARFCompileUnit *, 1> CUs;
   SmallVector<DWARFTypeUnit *, 1> TUs;
Index: lib/DebugInfo/DWARFDebugLine.cpp
===================================================================
--- lib/DebugInfo/DWARFDebugLine.cpp
+++ lib/DebugInfo/DWARFDebugLine.cpp
@@ -18,9 +18,9 @@
 
 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("default_is_stmt: %u\n", DefaultIsStmt)
      << format("      line_base: %i\n", LineBase)
@@ -165,16 +165,23 @@
 bool
 DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
                               uint32_t *offset_ptr, Prologue *prologue) {
-  const uint32_t prologue_offset = *offset_ptr;
+  const uint64_t prologue_offset = *offset_ptr;
 
   prologue->clear();
   prologue->TotalLength = debug_line_data.getU32(offset_ptr);
+  if (prologue->TotalLength == UINT32_MAX) {
+    prologue->IsDWARF64 = true;
+    prologue->TotalLength = debug_line_data.getU64(offset_ptr);
+  } else if (prologue->TotalLength >= 0xffffff00) {
+    return false;
+  }
   prologue->Version = debug_line_data.getU16(offset_ptr);
   if (prologue->Version != 2)
     return false;
 
-  prologue->PrologueLength = debug_line_data.getU32(offset_ptr);
-  const uint32_t end_prologue_offset = prologue->PrologueLength + *offset_ptr;
+  prologue->PrologueLength = debug_line_data.getUnsigned(offset_ptr,
+                                              prologue->sizeofPrologueLength());
+  const uint64_t end_prologue_offset = prologue->PrologueLength + *offset_ptr;
   prologue->MinInstLength = debug_line_data.getU8(offset_ptr);
   prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr);
   prologue->LineBase = debug_line_data.getU8(offset_ptr);
@@ -209,10 +216,15 @@
     }
   }
 
-  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);
+  if (prologue->IsDWARF64 && end_prologue_offset - *offset_ptr == 12) {
+    fprintf(stderr, "warning: apparent 64-bit DWARF GNU as prologue length bug"
+                    " detected (prologue length 12 bytes too long)\n");
+    // Could correct the field: prologue->PrologueLength -= 12;
+  } else if (*offset_ptr != end_prologue_offset) {
+    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;
@@ -233,7 +245,7 @@
   }
 
   const uint32_t end_offset = debug_line_offset + prologue->TotalLength +
-                              sizeof(prologue->TotalLength);
+                              prologue->sizeofTotalLength();
 
   state.reset();
 
Index: lib/DebugInfo/DWARFDebugLine.h
===================================================================
--- lib/DebugInfo/DWARFDebugLine.h
+++ lib/DebugInfo/DWARFDebugLine.h
@@ -35,16 +35,17 @@
   struct Prologue {
     Prologue()
       : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0),
-        DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0) {}
+        DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0),
+        IsDWARF64(false) {}
 
     // 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.
@@ -61,14 +62,22 @@
     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;
@@ -80,6 +89,7 @@
       StandardOpcodeLengths.clear();
       IncludeDirectories.clear();
       FileNames.clear();
+      IsDWARF64 = false;
     }
   };
 
Index: test/DebugInfo/dwarfdump-64-bit-dwarf.test
===================================================================
--- /dev/null
+++ test/DebugInfo/dwarfdump-64-bit-dwarf.test
@@ -0,0 +1,12 @@
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump-inl-test.elf-mips64-64-bit-dwarf \
+RUN:   --debug-dump=line | FileCheck %s
+
+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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1988.2.patch
Type: text/x-patch
Size: 7242 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131023/2cdfdc27/attachment.bin>


More information about the llvm-commits mailing list