[llvm] r362037 - [llvm-pdbutil] Dump inline call site line table annotations

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed May 29 14:26:26 PDT 2019


Author: rnk
Date: Wed May 29 14:26:25 2019
New Revision: 362037

URL: http://llvm.org/viewvc/llvm-project?rev=362037&view=rev
Log:
[llvm-pdbutil] Dump inline call site line table annotations

This ports and improves on some existing llvm-readobj -codeview dumping
functionality that llvm-pdbutil lacked.

Helpful for comparing inline line tables between MSVC and clang.

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
    llvm/trunk/test/MC/COFF/cv-inline-linetable.s
    llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h?rev=362037&r1=362036&r2=362037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h Wed May 29 14:26:25 2019
@@ -13,6 +13,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
@@ -155,15 +156,19 @@ public:
   uint32_t RecordOffset;
 };
 
-struct BinaryAnnotationIterator {
-  struct AnnotationData {
-    BinaryAnnotationsOpCode OpCode;
-    StringRef Name;
-    uint32_t U1;
-    uint32_t U2;
-    int32_t S1;
-  };
+struct DecodedAnnotation {
+  StringRef Name;
+  ArrayRef<uint8_t> Bytes;
+  BinaryAnnotationsOpCode OpCode;
+  uint32_t U1 = 0;
+  uint32_t U2 = 0;
+  int32_t S1 = 0;
+};
 
+struct BinaryAnnotationIterator
+    : public iterator_facade_base<BinaryAnnotationIterator,
+                                  std::forward_iterator_tag,
+                                  DecodedAnnotation> {
   BinaryAnnotationIterator() = default;
   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
   BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
@@ -173,10 +178,6 @@ struct BinaryAnnotationIterator {
     return Data == Other.Data;
   }
 
-  bool operator!=(const BinaryAnnotationIterator &Other) const {
-    return !(*this == Other);
-  }
-
   BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
     Data = Other.Data;
     return *this;
@@ -193,13 +194,7 @@ struct BinaryAnnotationIterator {
     return *this;
   }
 
-  BinaryAnnotationIterator operator++(int) {
-    BinaryAnnotationIterator Orig(*this);
-    ++(*this);
-    return Orig;
-  }
-
-  const AnnotationData &operator*() {
+  const DecodedAnnotation &operator*() {
     ParseCurrentAnnotation();
     return Current.getValue();
   }
@@ -241,17 +236,17 @@ private:
              (ThirdByte << 8) | FourthByte;
 
     return -1;
-  };
+  }
 
   static int32_t DecodeSignedOperand(uint32_t Operand) {
     if (Operand & 1)
       return -(Operand >> 1);
     return Operand >> 1;
-  };
+  }
 
   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
-  };
+  }
 
   bool ParseCurrentAnnotation() {
     if (Current.hasValue())
@@ -259,7 +254,7 @@ private:
 
     Next = Data;
     uint32_t Op = GetCompressedAnnotation(Next);
-    AnnotationData Result;
+    DecodedAnnotation Result;
     Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
     switch (Result.OpCode) {
     case BinaryAnnotationsOpCode::Invalid:
@@ -324,11 +319,12 @@ private:
       break;
     }
     }
+    Result.Bytes = Data.take_front(Data.size() - Next.size());
     Current = Result;
     return true;
   }
 
-  Optional<AnnotationData> Current;
+  Optional<DecodedAnnotation> Current;
   ArrayRef<uint8_t> Data;
   ArrayRef<uint8_t> Next;
 };

Modified: llvm/trunk/test/MC/COFF/cv-inline-linetable.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-inline-linetable.s?rev=362037&r1=362036&r2=362037&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-inline-linetable.s (original)
+++ llvm/trunk/test/MC/COFF/cv-inline-linetable.s Wed May 29 14:26:25 2019
@@ -1,4 +1,7 @@
-# RUN: llvm-mc -triple=i686-pc-win32 -filetype=obj < %s | llvm-readobj --codeview | FileCheck %s
+# RUN: llvm-mc -triple=i686-pc-win32 -filetype=obj %s -o %t.o
+# RUN: llvm-readobj --codeview %t.o | FileCheck %s
+# RUN: llvm-objdump -d %t.o | FileCheck %s --check-prefix=ASM
+# RUN: llvm-pdbutil dump -symbols %t.o | FileCheck %s --check-prefix=PDB
 	.text
 	.def	 @feat.00;
 	.scl	3;
@@ -43,6 +46,40 @@ Lfunc_begin0:
 	retl
 Lfunc_end0:
 
+# Check the disassembly so we have accurate instruction offsets in hex.
+# ASM-LABEL: ?baz@@YAXXZ:
+# ASM-NEXT:       0: {{.*}} pushl   %eax
+# ASM-NEXT:       1: {{.*}} addl    $6, 0
+# ASM-NEXT:       8: {{.*}} addl    $4, 0
+# ASM-NEXT:       f: {{.*}} movl    $1, (%esp)
+# ASM-NEXT:      16: {{.*}} leal    (%esp), %eax
+# ASM-NEXT:      19: {{.*}} addl    %eax, 0
+# ASM-NEXT:      1f: {{.*}} addl    $2, 0
+# ASM-NEXT:      26: {{.*}} addl    $3, 0
+# ASM-NEXT:      2d: {{.*}} addl    $5, 0
+# ASM-NEXT:      34: {{.*}} addl    $7, 0
+# ASM-NEXT:      3b: {{.*}} popl    %eax
+# ASM-NEXT:      3c: {{.*}} retl
+
+# PDB: S_GPROC32_ID {{.*}} `baz`
+# PDB: S_INLINESITE
+# PDB-NEXT: inlinee = 0x1003 (bar), parent = 0, end = 0
+# PDB-NEXT:   0B08      code 0x8 (+0x8) line 0 (-0)
+# PDB-NEXT:   0B27      code 0xF (+0x7) line 1 (+1)
+# PDB-NEXT:   0602      line 2 (+1)
+# PDB-NEXT:   031E      code 0x2D (+0x1E)
+# PDB-NEXT:   0407      code end 0x34 (+0x7)
+# PDB: S_INLINESITE
+# PDB-NEXT: inlinee = 0x1004 (foo), parent = 0, end = 0
+# PDB-NEXT:    0B0F      code 0xF (+0xF) line 0 (-0)
+# PDB-NEXT:    0B2A      code 0x19 (+0xA) line 1 (+1)
+# PDB-NEXT:    0B26      code 0x1F (+0x6) line 2 (+1)
+# PDB-NEXT:    0B27      code 0x26 (+0x7) line 3 (+1)
+# PDB-NEXT:    0407      code end 0x2D (+0x7)
+# PEB: S_INLINESITE_END
+# PEB: S_INLINESITE_END
+# PEB: S_PROC_ID_END
+
 	.section	.debug$T,"dr"
 	.long	4
 	.short	6

Modified: llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp?rev=362037&r1=362036&r2=362037&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp Wed May 29 14:26:25 2019
@@ -650,13 +650,85 @@ Error MinimalSymbolDumper::visitKnownRec
 
 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, InlineSiteSym &IS) {
   AutoIndent Indent(P, 7);
-  auto Bytes = makeArrayRef(IS.AnnotationData);
-  StringRef Annotations(reinterpret_cast<const char *>(Bytes.begin()),
-                        Bytes.size());
-
   P.formatLine("inlinee = {0}, parent = {1}, end = {2}", idIndex(IS.Inlinee),
                IS.Parent, IS.End);
-  P.formatLine("annotations = {0}", toHex(Annotations));
+
+  // Break down the annotation byte code and calculate code and line offsets.
+  // FIXME: It would be helpful if we could look up the initial file and inlinee
+  // lines offset using the inlinee index above.
+  uint32_t CodeOffset = 0;
+  int32_t LineOffset = 0;
+  for (auto &Annot : IS.annotations()) {
+    P.formatLine("  {0}", fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9));
+
+    auto formatCodeOffset = [&](uint32_t Delta) {
+      CodeOffset += Delta;
+      P.format(" code 0x{0} (+0x{1})", utohexstr(CodeOffset), utohexstr(Delta));
+    };
+    auto formatCodeLength = [&](uint32_t Length) {
+      // Notably, changing the code length does not affect the code offset.
+      P.format(" code end 0x{0} (+0x{1})", utohexstr(CodeOffset + Length),
+               utohexstr(Length));
+    };
+    auto formatLineOffset = [&](int32_t Delta) {
+      LineOffset += Delta;
+      char Sign = Delta > 0 ? '+' : '-';
+      P.format(" line {0} ({1}{2})", LineOffset, Sign, std::abs(Delta));
+    };
+
+    // Use the opcode to interpret the integer values.
+    switch (Annot.OpCode) {
+    case BinaryAnnotationsOpCode::Invalid:
+      break;
+    case BinaryAnnotationsOpCode::CodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeOffset:
+      formatCodeOffset(Annot.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeLineOffset:
+      formatLineOffset(Annot.S1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLength:
+      formatCodeLength(Annot.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+      formatCodeOffset(Annot.U1);
+      formatLineOffset(Annot.S1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+      formatCodeOffset(Annot.U2);
+      formatCodeLength(Annot.U1);
+      break;
+
+    case BinaryAnnotationsOpCode::ChangeFile: {
+      uint32_t FileOffset = Annot.U1;
+      StringRef Filename = "<unknown>";
+      if (SymGroup) {
+        if (Expected<StringRef> MaybeFile =
+                SymGroup->getNameFromStringTable(FileOffset))
+          Filename = *MaybeFile;
+        else
+          return MaybeFile.takeError();
+      }
+      P.format(" setfile {0} 0x{1}", utohexstr(FileOffset));
+      break;
+    }
+
+    // The rest of these are hard to convince MSVC to emit, so they are not as
+    // well understood.
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
+      formatCodeOffset(Annot.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeLineEndDelta:
+    case BinaryAnnotationsOpCode::ChangeRangeKind:
+    case BinaryAnnotationsOpCode::ChangeColumnStart:
+    case BinaryAnnotationsOpCode::ChangeColumnEnd:
+      P.format(" {0} {1}", Annot.Name, Annot.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
+      P.format(" {0} {1}", Annot.Name, Annot.S1);
+      break;
+    }
+  }
   return Error::success();
 }
 




More information about the llvm-commits mailing list