[llvm] r197674 - Teach the llvm-readobj COFF dumper to dump debug line tables from object files

Timur Iskhodzhanov timurrrr at google.com
Thu Dec 19 03:37:15 PST 2013


Author: timurrrr
Date: Thu Dec 19 05:37:14 2013
New Revision: 197674

URL: http://llvm.org/viewvc/llvm-project?rev=197674&view=rev
Log:
Teach the llvm-readobj COFF dumper to dump debug line tables from object files

Reviewed at http://llvm-reviews.chandlerc.com/D2425

Added:
    llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-i368   (with props)
    llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-x86_64   (with props)
    llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-i368   (with props)
    llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-x86_64   (with props)
    llvm/trunk/test/tools/llvm-readobj/codeview-linetables.test
Modified:
    llvm/trunk/include/llvm/Support/COFF.h
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
    llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
    llvm/trunk/tools/llvm-readobj/llvm-readobj.h

Modified: llvm/trunk/include/llvm/Support/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/COFF.h?rev=197674&r1=197673&r2=197674&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/COFF.h (original)
+++ llvm/trunk/include/llvm/Support/COFF.h Thu Dec 19 05:37:14 2013
@@ -611,6 +611,13 @@ namespace COFF {
     }
   };
 
+  enum CodeViewLineTableIdentifiers {
+    DEBUG_SECTION_MAGIC           = 0x4,
+    DEBUG_LINE_TABLE_SUBSECTION   = 0xF2,
+    DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
+    DEBUG_INDEX_SUBSECTION        = 0xF4
+  };
+
 } // End namespace COFF.
 } // End namespace llvm.
 

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-i368
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-i368?rev=197674&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-i368
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-x86_64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-x86_64?rev=197674&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2012-x86_64
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-i368
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-i368?rev=197674&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-i368
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-x86_64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-x86_64?rev=197674&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2012-x86_64
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-readobj/codeview-linetables.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/codeview-linetables.test?rev=197674&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/codeview-linetables.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/codeview-linetables.test Thu Dec 19 05:37:14 2013
@@ -0,0 +1,282 @@
+RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifunction-linetables.obj.coff-2012-i368 \
+RUN:   | FileCheck %s -check-prefix MFUN32
+RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifunction-linetables.obj.coff-2012-x86_64 \
+RUN:   | FileCheck %s -check-prefix MFUN64
+RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifile-linetables.obj.coff-2012-i368 \
+RUN:   | FileCheck %s -check-prefix MFILE32
+RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifile-linetables.obj.coff-2012-x86_64 \
+RUN:   | FileCheck %s -check-prefix MFILE64
+
+MFUN32:      CodeViewLineTables [
+MFUN32-NEXT:   Magic: 0x4
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF1
+MFUN32-NEXT:     PayloadSize: 0x52
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF5
+MFUN32-NEXT:     PayloadSize: 0x24
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF1
+MFUN32-NEXT:     PayloadSize: 0x4B
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF2
+MFUN32-NEXT:     PayloadSize: 0x30
+MFUN32:          FunctionName: _x
+MFUN32-NEXT:   ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF5
+MFUN32-NEXT:     PayloadSize: 0x24
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF1
+MFUN32-NEXT:     PayloadSize: 0x4B
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF2
+MFUN32-NEXT:     PayloadSize: 0x30
+MFUN32:          FunctionName: _y
+MFUN32-NEXT:   ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF5
+MFUN32-NEXT:     PayloadSize: 0x24
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF1
+MFUN32-NEXT:     PayloadSize: 0x4B
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF2
+MFUN32-NEXT:     PayloadSize: 0x40
+MFUN32:          FunctionName: _f
+MFUN32-NEXT:   ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF4
+MFUN32-NEXT:     PayloadSize: 0x18
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF3
+MFUN32-NEXT:     PayloadSize: 0x46
+MFUN32:        ]
+MFUN32-NEXT:   Subsection [
+MFUN32-NEXT:     Type: 0xF1
+MFUN32-NEXT:     PayloadSize: 0x8
+MFUN32:        ]
+MFUN32-NEXT:   FunctionLineTable [
+MFUN32-NEXT:     FunctionName: _x
+MFUN32-NEXT:     CodeSize: 0xA
+MFUN32-NEXT:     FilenameSegment [
+MFUN32-NEXT:       Filename: d:\source.c
+MFUN32-NEXT:       +0x0: 3
+MFUN32-NEXT:       +0x3: 4
+MFUN32-NEXT:       +0x8: 5
+MFUN32-NEXT:     ]
+MFUN32-NEXT:   ]
+MFUN32-NEXT:   FunctionLineTable [
+MFUN32-NEXT:     FunctionName: _y
+MFUN32-NEXT:     CodeSize: 0xA
+MFUN32-NEXT:     FilenameSegment [
+MFUN32-NEXT:       Filename: d:\source.c
+MFUN32-NEXT:       +0x0: 7
+MFUN32-NEXT:       +0x3: 8
+MFUN32-NEXT:       +0x8: 9
+MFUN32-NEXT:     ]
+MFUN32-NEXT:   ]
+MFUN32-NEXT:   FunctionLineTable [
+MFUN32-NEXT:     FunctionName: _f
+MFUN32-NEXT:     CodeSize: 0x14
+MFUN32-NEXT:     FilenameSegment [
+MFUN32-NEXT:       Filename: d:\source.c
+MFUN32-NEXT:       +0x0: 11
+MFUN32-NEXT:       +0x3: 12
+MFUN32-NEXT:       +0x8: 13
+MFUN32-NEXT:       +0xD: 14
+MFUN32-NEXT:       +0x12: 15
+MFUN32-NEXT:     ]
+MFUN32-NEXT:   ]
+MFUN32-NEXT: ]
+
+MFUN64:      CodeViewLineTables [
+MFUN64-NEXT:   Magic: 0x4
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF1
+MFUN64-NEXT:     PayloadSize: 0x52
+MFUN64:        ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF1
+MFUN64-NEXT:     PayloadSize: 0x4B
+MFUN64:        ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF2
+MFUN64-NEXT:     PayloadSize: 0x30
+MFUN64:          FunctionName: x
+MFUN64-NEXT:   ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF1
+MFUN64-NEXT:     PayloadSize: 0x4B
+MFUN64:        ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF2
+MFUN64-NEXT:     PayloadSize: 0x30
+MFUN64:          FunctionName: y
+MFUN64-NEXT:   ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF1
+MFUN64-NEXT:     PayloadSize: 0x4B
+MFUN64:        ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF2
+MFUN64-NEXT:     PayloadSize: 0x40
+MFUN64:          FunctionName: f
+MFUN64-NEXT:   ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF4
+MFUN64-NEXT:     PayloadSize: 0x18
+MFUN64:        ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF3
+MFUN64-NEXT:     PayloadSize: 0xD
+MFUN64:        ]
+MFUN64-NEXT:   Subsection [
+MFUN64-NEXT:     Type: 0xF1
+MFUN64-NEXT:     PayloadSize: 0x8
+MFUN64:        ]
+MFUN64-NEXT:   FunctionLineTable [
+MFUN64-NEXT:     FunctionName: x
+MFUN64-NEXT:     CodeSize: 0xE
+MFUN64-NEXT:     FilenameSegment [
+MFUN64-NEXT:       Filename: d:\source.c
+MFUN64-NEXT:       +0x0: 3
+MFUN64-NEXT:       +0x4: 4
+MFUN64-NEXT:       +0x9: 5
+MFUN64-NEXT:     ]
+MFUN64-NEXT:   ]
+MFUN64-NEXT:   FunctionLineTable [
+MFUN64-NEXT:     FunctionName: y
+MFUN64-NEXT:     CodeSize: 0xE
+MFUN64-NEXT:     FilenameSegment [
+MFUN64-NEXT:       Filename: d:\source.c
+MFUN64-NEXT:       +0x0: 7
+MFUN64-NEXT:       +0x4: 8
+MFUN64-NEXT:       +0x9: 9
+MFUN64-NEXT:     ]
+MFUN64-NEXT:   ]
+MFUN64-NEXT:   FunctionLineTable [
+MFUN64-NEXT:     FunctionName: f
+MFUN64-NEXT:     CodeSize: 0x18
+MFUN64-NEXT:     FilenameSegment [
+MFUN64-NEXT:       Filename: d:\source.c
+MFUN64-NEXT:       +0x0: 11
+MFUN64-NEXT:       +0x4: 12
+MFUN64-NEXT:       +0x9: 13
+MFUN64-NEXT:       +0xE: 14
+MFUN64-NEXT:       +0x13: 15
+MFUN64-NEXT:     ]
+MFUN64-NEXT:   ]
+MFUN64-NEXT: ]
+
+MFILE32:      CodeViewLineTables [
+MFILE32-NEXT:   Magic: 0x4
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF1
+MFILE32-NEXT:     PayloadSize: 0x51
+MFILE32:        ]
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF5
+MFILE32-NEXT:     PayloadSize: 0x24
+MFILE32:        ]
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF1
+MFILE32-NEXT:     PayloadSize: 0x4B
+MFILE32:        ]
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF2
+MFILE32-NEXT:     PayloadSize: 0x64
+MFILE32:          FunctionName: _f
+MFILE32-NEXT:   ]
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF4
+MFILE32-NEXT:     PayloadSize: 0x28
+MFILE32:        ]
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF3
+MFILE32-NEXT:     PayloadSize: 0x57
+MFILE32:        ]
+MFILE32-NEXT:   Subsection [
+MFILE32-NEXT:     Type: 0xF1
+MFILE32-NEXT:     PayloadSize: 0x8
+MFILE32:        ]
+MFILE32-NEXT:   FunctionLineTable [
+MFILE32-NEXT:     FunctionName: _f
+MFILE32-NEXT:     CodeSize: 0x14
+MFILE32-NEXT:     FilenameSegment [
+MFILE32-NEXT:       Filename: d:\input.c
+MFILE32-NEXT:       +0x0: 3
+MFILE32-NEXT:     ]
+MFILE32-NEXT:     FilenameSegment [
+MFILE32-NEXT:       Filename: d:\one.c
+MFILE32-NEXT:       +0x3: 1
+MFILE32-NEXT:     ]
+MFILE32-NEXT:     FilenameSegment [
+MFILE32-NEXT:       Filename: d:\two.c
+MFILE32-NEXT:       +0x8: 2
+MFILE32-NEXT:     ]
+MFILE32-NEXT:     FilenameSegment [
+MFILE32-NEXT:       Filename: d:\one.c
+MFILE32-NEXT:       +0xD: 7
+MFILE32-NEXT:       +0x12: 8
+MFILE32-NEXT:     ]
+MFILE32-NEXT:   ]
+MFILE32-NEXT: ]
+
+MFILE64:      CodeViewLineTables [
+MFILE64-NEXT:   Magic: 0x4
+MFILE64-NEXT:   Subsection [
+MFILE64-NEXT:     Type: 0xF1
+MFILE64-NEXT:     PayloadSize: 0x51
+MFILE64:        ]
+MFILE64-NEXT:   Subsection [
+MFILE64-NEXT:     Type: 0xF1
+MFILE64-NEXT:     PayloadSize: 0x4B
+MFILE64:        ]
+MFILE64-NEXT:   Subsection [
+MFILE64-NEXT:     Type: 0xF2
+MFILE64-NEXT:     PayloadSize: 0x64
+MFILE64:          FunctionName: f
+MFILE64-NEXT:   ]
+MFILE64-NEXT:   Subsection [
+MFILE64-NEXT:     Type: 0xF4
+MFILE64-NEXT:     PayloadSize: 0x28
+MFILE64:        ]
+MFILE64-NEXT:   Subsection [
+MFILE64-NEXT:     Type: 0xF3
+MFILE64-NEXT:     PayloadSize: 0x1E
+MFILE64:        ]
+MFILE64-NEXT:   Subsection [
+MFILE64-NEXT:     Type: 0xF1
+MFILE64-NEXT:     PayloadSize: 0x8
+MFILE64:        ]
+MFILE64-NEXT:   FunctionLineTable [
+MFILE64-NEXT:     FunctionName: f
+MFILE64-NEXT:     CodeSize: 0x18
+MFILE64-NEXT:     FilenameSegment [
+MFILE64-NEXT:       Filename: d:\input.c
+MFILE64-NEXT:       +0x0: 3
+MFILE64-NEXT:     ]
+MFILE64-NEXT:     FilenameSegment [
+MFILE64-NEXT:       Filename: d:\one.c
+MFILE64-NEXT:       +0x4: 1
+MFILE64-NEXT:     ]
+MFILE64-NEXT:     FilenameSegment [
+MFILE64-NEXT:       Filename: d:\two.c
+MFILE64-NEXT:       +0x9: 2
+MFILE64-NEXT:     ]
+MFILE64-NEXT:     FilenameSegment [
+MFILE64-NEXT:       Filename: d:\one.c
+MFILE64-NEXT:       +0xE: 7
+MFILE64-NEXT:       +0x13: 8
+MFILE64-NEXT:     ]
+MFILE64-NEXT:   ]
+MFILE64-NEXT: ]

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=197674&r1=197673&r2=197674&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Thu Dec 19 05:37:14 2013
@@ -24,6 +24,8 @@
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/Win64EH.h"
@@ -76,6 +78,8 @@ private:
 
   void printUnwindCode(const Win64EH::UnwindInfo& UI, ArrayRef<UnwindCode> UCs);
 
+  void printCodeViewLineTables(section_iterator SecI);
+
   void cacheRelocations();
 
   error_code getSectionContents(
@@ -648,6 +652,164 @@ void COFFDumper::printFileHeaders() {
   }
 }
 
+void COFFDumper::printCodeViewLineTables(section_iterator SecI) {
+  StringRef Data;
+  if (error(SecI->getContents(Data))) return;
+
+  SmallVector<StringRef, 10> FunctionNames;
+  StringMap<StringRef> FunctionLineTables;
+  StringRef FileIndexToStringOffsetTable;
+  StringRef StringTable;
+
+  ListScope D(W, "CodeViewLineTables");
+  {
+    DataExtractor DE(Data, true, 4);
+    uint32_t Offset = 0,
+             Magic = DE.getU32(&Offset);
+    W.printHex("Magic", Magic);
+    if (Magic != COFF::DEBUG_SECTION_MAGIC) {
+      error(object_error::parse_failed);
+      return;
+    }
+
+    bool Finished = false;
+    while (DE.isValidOffset(Offset) && !Finished) {
+      // The section consists of a number of subsection in the following format:
+      // |Type|PayloadSize|Payload...|
+      uint32_t SubSectionType = DE.getU32(&Offset),
+               PayloadSize = DE.getU32(&Offset);
+      ListScope S(W, "Subsection");
+      W.printHex("Type", SubSectionType);
+      W.printHex("PayloadSize", PayloadSize);
+      if (PayloadSize > Data.size() - Offset) {
+        error(object_error::parse_failed);
+        return;
+      }
+
+      // Print the raw contents to simplify debugging if anything goes wrong
+      // afterwards.
+      StringRef Contents = Data.substr(Offset, PayloadSize);
+      W.printBinaryBlock("Contents", Contents);
+
+      switch (SubSectionType) {
+      case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
+        // Holds a PC to file:line table.  Some data to parse this subsection is
+        // stored in the other subsections, so just check sanity and store the
+        // pointers for deferred processing.
+
+        if (PayloadSize < 12) {
+          // There should be at least three words to store two function
+          // relocations and size of the code.
+          error(object_error::parse_failed);
+          return;
+        }
+
+        StringRef FunctionName;
+        if (error(resolveSymbolName(RelocMap[Obj->getCOFFSection(SecI)], Offset,
+                                    FunctionName)))
+          return;
+        W.printString("FunctionName", FunctionName);
+        if (FunctionLineTables.count(FunctionName) != 0) {
+          // Saw debug info for this function already?
+          error(object_error::parse_failed);
+          return;
+        }
+
+        FunctionLineTables[FunctionName] = Contents;
+        FunctionNames.push_back(FunctionName);
+        break;
+      }
+      case COFF::DEBUG_STRING_TABLE_SUBSECTION:
+        if (PayloadSize == 0 || StringTable.data() != 0 ||
+            Contents.back() != '\0') {
+          // Empty or duplicate or non-null-terminated subsection.
+          error(object_error::parse_failed);
+          return;
+        }
+        StringTable = Contents;
+        break;
+      case COFF::DEBUG_INDEX_SUBSECTION:
+        // Holds the translation table from file indices
+        // to offsets in the string table.
+
+        if (PayloadSize == 0 || FileIndexToStringOffsetTable.data() != 0) {
+          // Empty or duplicate subsection.
+          error(object_error::parse_failed);
+          return;
+        }
+        FileIndexToStringOffsetTable = Contents;
+        break;
+      }
+      Offset += PayloadSize;
+
+      // Align the reading pointer by 4.
+      Offset += (-Offset) % 4;
+    }
+  }
+
+  // Dump the line tables now that we've read all the subsections and know all
+  // the required information.
+  for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
+    StringRef Name = FunctionNames[I];
+    ListScope S(W, "FunctionLineTable");
+    W.printString("FunctionName", Name);
+
+    DataExtractor DE(FunctionLineTables[Name], true, 4);
+    uint32_t Offset = 8;  // Skip relocations.
+    uint32_t FunctionSize = DE.getU32(&Offset);
+    W.printHex("CodeSize", FunctionSize);
+    while (DE.isValidOffset(Offset)) {
+      // For each range of lines with the same filename, we have a segment
+      // in the line table.  The filename string is accessed using double
+      // indirection to the string table subsection using the index subsection.
+      uint32_t OffsetInIndex = DE.getU32(&Offset),
+               SegmentLength   = DE.getU32(&Offset),
+               FullSegmentSize = DE.getU32(&Offset);
+      if (FullSegmentSize != 12 + 8 * SegmentLength) {
+        error(object_error::parse_failed);
+        return;
+      }
+
+      uint32_t FilenameOffset;
+      {
+        DataExtractor SDE(FileIndexToStringOffsetTable, true, 4);
+        uint32_t OffsetInSDE = OffsetInIndex;
+        if (!SDE.isValidOffset(OffsetInSDE)) {
+          error(object_error::parse_failed);
+          return;
+        }
+        FilenameOffset = SDE.getU32(&OffsetInSDE);
+      }
+
+      if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() ||
+          StringTable.data()[FilenameOffset - 1] != '\0') {
+        // Each string in an F3 subsection should be preceded by a null
+        // character.
+        error(object_error::parse_failed);
+        return;
+      }
+
+      StringRef Filename(StringTable.data() + FilenameOffset);
+      ListScope S(W, "FilenameSegment");
+      W.printString("Filename", Filename);
+      for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
+           ++J) {
+        // Then go the (PC, LineNumber) pairs.  The line number is stored in the
+        // least significant 31 bits of the respective word in the table.
+        uint32_t PC = DE.getU32(&Offset),
+                 LineNumber = DE.getU32(&Offset) & 0x7fffffff;
+        if (PC >= FunctionSize) {
+          error(object_error::parse_failed);
+          return;
+        }
+        char Buffer[32];
+        format("+0x%X", PC).snprint(Buffer, 32);
+        W.printNumber(Buffer, LineNumber);
+      }
+    }
+  }
+}
+
 void COFFDumper::printSections() {
   error_code EC;
 
@@ -707,6 +869,9 @@ void COFFDumper::printSections() {
       }
     }
 
+    if (Name == ".debug$S" && opts::CodeViewLineTables)
+      printCodeViewLineTables(SecI);
+
     if (opts::SectionData) {
       StringRef Data;
       if (error(SecI->getContents(Data))) break;

Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=197674&r1=197673&r2=197674&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Thu Dec 19 05:37:14 2013
@@ -128,6 +128,10 @@ namespace opts {
   // -expand-relocs
   cl::opt<bool> ExpandRelocs("expand-relocs",
     cl::desc("Expand each shown relocation to multiple lines"));
+
+  // -codeview-linetables
+  cl::opt<bool> CodeViewLineTables("codeview-linetables",
+    cl::desc("Display CodeView line table information"));
 } // namespace opts
 
 static int ReturnValue = EXIT_SUCCESS;

Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.h?rev=197674&r1=197673&r2=197674&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.h (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.h Thu Dec 19 05:37:14 2013
@@ -38,6 +38,7 @@ namespace opts {
   extern llvm::cl::opt<bool> DynamicSymbols;
   extern llvm::cl::opt<bool> UnwindInfo;
   extern llvm::cl::opt<bool> ExpandRelocs;
+  extern llvm::cl::opt<bool> CodeViewLineTables;
 } // namespace opts
 
 #define LLVM_READOBJ_ENUM_ENT(ns, enum) \





More information about the llvm-commits mailing list