diff --git a/lld/test/COFF/symbolizer-inline.s b/lld/test/COFF/symbolizer-inline.s --- a/lld/test/COFF/symbolizer-inline.s +++ b/lld/test/COFF/symbolizer-inline.s @@ -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 # @@ -50,6 +50,11 @@ .cv_inline_site_id 1 within 0 inlined_at 1 10 11 .cv_loc 1 1 6 20 # test.cpp:6:20 +# CHECK: inlinee_1 +# 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 @@ -59,6 +64,11 @@ # Add a line change here. .cv_loc 1 1 7 7 +# CHECK: inlinee_1 +# 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 @@ -68,6 +78,13 @@ .cv_inline_site_id 2 within 1 inlined_at 1 6 10 .cv_loc 2 1 2 10 # test.cpp:2:10 +# 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 + # CHECK: inlinee_2 # CHECK-NEXT: C:\src\test.cpp:2:0 # CHECK-NEXT: inlinee_1 diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp @@ -104,29 +104,78 @@ LineOffset = 0; FileOffset = 0; uint32_t CodeOffset = 0; + Optional CodeOffsetBase; + Optional CodeOffsetEnd; + Optional CurLineOffset; + Optional NextLineOffset; + Optional 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; } }