[llvm-symbolizer] Fix line offset for inline site.
authorZequan Wu <zequanwu@google.com>
Tue, 5 Apr 2022 19:12:48 +0000 (12:12 -0700)
committerZequan Wu <zequanwu@google.com>
Thu, 7 Apr 2022 22:17:59 +0000 (15:17 -0700)
This fixes the issue when the current line offset is actually for next range.

Maintain a current code range with current line offset and cache next file/line
offset. Update file/line offset after finishing current range.

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

lld/test/COFF/symbolizer-inline.s
llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp

index f581789..3189241 100644 (file)
@@ -2,10 +2,10 @@
 # RUN: llvm-mc -filetype=obj %s -o %t.obj -triple x86_64-windows-msvc
 # RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -pdb:%t.pdb -debug
 # RUN: llvm-symbolizer --obj=%t.exe --relative-address \
-# RUN:   0x1014 0x1018 0x101c 0x1023 0x1024 \
+# RUN:   0x1014 0x1015 0x1018 0x1019 0x101c 0x101d 0x1023 0x1024 \
 # RUN:   0x1037 0x103A 0x104B 0x104E | FileCheck %s
 
-# Compiled from this cpp code, with modifications to add extra inline line and 
+# Compiled from this cpp code, with modifications to add extra inline line and
 # file changes:
 # clang -cc1 -triple x86_64-windows-msvc -gcodeview -S test.cpp
 #
@@ -54,6 +54,11 @@ main:                                   # @main
 # CHECK-NEXT: C:\src\test.cpp:6:0
 # CHECK-NEXT: main
 # CHECK-NEXT: C:\src\test.cpp:10:11
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:6:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:10:11
        movl    16(%rsp), %eax
 
 # Add a line change here.
@@ -63,6 +68,11 @@ main:                                   # @main
 # CHECK-NEXT: C:\src\test.cpp:7:0
 # CHECK-NEXT: main
 # CHECK-NEXT: C:\src\test.cpp:10:11
+
+# CHECK: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:7:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:10:11
        movl    %eax, 20(%rsp)
 .Ltmp1:
        .cv_inline_site_id 2 within 1 inlined_at 1 6 10
@@ -74,6 +84,13 @@ main:                                   # @main
 # CHECK-NEXT: C:\src\test.cpp:6:0
 # CHECK-NEXT: main
 # CHECK-NEXT: C:\src\test.cpp:10:11
+
+# CHECK: inlinee_2
+# CHECK-NEXT: C:\src\test.cpp:2:0
+# CHECK-NEXT: inlinee_1
+# CHECK-NEXT: C:\src\test.cpp:6:0
+# CHECK-NEXT: main
+# CHECK-NEXT: C:\src\test.cpp:10:11
        movl    20(%rsp), %eax
        .cv_loc 2 1 2 12                        # test.cpp:2:12
        addl    $1, %eax
index 231838b..211c2f7 100644 (file)
@@ -104,29 +104,78 @@ void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc,
   LineOffset = 0;
   FileOffset = 0;
   uint32_t CodeOffset = 0;
+  Optional<uint32_t> CodeOffsetBase;
+  Optional<uint32_t> CodeOffsetEnd;
+  Optional<uint32_t> CurLineOffset;
+  Optional<uint32_t> NextLineOffset;
+  Optional<uint32_t> NextFileOffset;
+  auto UpdateCodeOffset = [&](uint32_t Delta) {
+    if (!CodeOffsetBase)
+      CodeOffsetBase = CodeOffset;
+    else if (!CodeOffsetEnd)
+      CodeOffsetEnd = *CodeOffsetBase + Delta;
+  };
+  auto UpdateLineOffset = [&](int32_t Delta) {
+    LineOffset += Delta;
+    if (!CodeOffsetBase || !CurLineOffset)
+      CurLineOffset = LineOffset;
+    else
+      NextLineOffset = LineOffset;
+  };
+  auto UpdateFileOffset = [&](uint32_t Offset) {
+    if (!CodeOffsetBase)
+      FileOffset = Offset;
+    else
+      NextFileOffset = Offset;
+  };
+  auto ValidateAndReset = [&]() {
+    // Current range is finished. Check if OffsetInFunc is in the range.
+    if (CodeOffsetBase && CodeOffsetEnd && CurLineOffset) {
+      if (CodeOffsetBase <= OffsetInFunc && OffsetInFunc < CodeOffsetEnd) {
+        LineOffset = *CurLineOffset;
+        return true;
+      }
+      // Set base, end, file offset and line offset for next range.
+      if (NextFileOffset)
+        FileOffset = *NextFileOffset;
+      CurLineOffset = NextLineOffset ? NextLineOffset : None;
+      CodeOffsetBase = CodeOffsetEnd;
+      CodeOffsetEnd = NextLineOffset = NextFileOffset = None;
+    }
+    return false;
+  };
   for (const auto &Annot : Sym.annotations()) {
     switch (Annot.OpCode) {
     case BinaryAnnotationsOpCode::CodeOffset:
     case BinaryAnnotationsOpCode::ChangeCodeOffset:
-    case BinaryAnnotationsOpCode::ChangeCodeLength:
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
       CodeOffset += Annot.U1;
+      UpdateCodeOffset(Annot.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLength:
+      UpdateCodeOffset(Annot.U1);
       break;
     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
       CodeOffset += Annot.U2;
+      UpdateCodeOffset(Annot.U2);
+      UpdateCodeOffset(Annot.U1);
       break;
     case BinaryAnnotationsOpCode::ChangeLineOffset:
+      UpdateLineOffset(Annot.S1);
+      break;
     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
       CodeOffset += Annot.U1;
-      LineOffset += Annot.S1;
+      UpdateCodeOffset(Annot.U1);
+      UpdateLineOffset(Annot.S1);
       break;
     case BinaryAnnotationsOpCode::ChangeFile:
-      FileOffset = Annot.U1;
+      UpdateFileOffset(Annot.U1);
       break;
     default:
       break;
     }
 
-    if (CodeOffset >= OffsetInFunc)
+    if (ValidateAndReset())
       return;
   }
 }