-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
This is caused by https://go-review.googlesource.com/c/go/+/258422, commit 8f14c18.
If the body of a function immediately follows the body of another function then the PC address of the second function will have two entries in debug_line, one with the file:line of the first line of the first function and the second with the first line of the second function.
For example, compiling https://raw.githubusercontent.com/go-delve/delve/master/_fixtures/decllinetest.go on linux/arm64 (this is important) with -gcflags='-N -l'
will produce the following code for main.main
decllinetest.go:7 0x9cda0 f9400b81 MOVD 16(R28), R1
decllinetest.go:7 0x9cda4 910003e2 MOVD RSP, R2
decllinetest.go:7 0x9cda8 eb01005f CMP R1, R2
decllinetest.go:7 0x9cdac 540001e9 BLS 15(PC)
decllinetest.go:7 0x9cdb0 f81d0ffe MOVD.W R30, -48(RSP)
decllinetest.go:7 0x9cdb4 f81f83fd MOVD R29, -8(RSP)
decllinetest.go:7 0x9cdb8 d10023fd SUB $8, RSP, R29
decllinetest.go:8 0x9cdbc f90013ff MOVD ZR, 32(RSP)
decllinetest.go:9 0x9cdc0 b24003e0 ORR $1, ZR, R0
decllinetest.go:9 0x9cdc4 f90013e0 MOVD R0, 32(RSP)
decllinetest.go:10 0x9cdc8 f9000fff MOVD ZR, 24(RSP)
decllinetest.go:11 0x9cdcc f94013e0 MOVD 32(RSP), R0
decllinetest.go:11 0x9cdd0 f90007e0 MOVD R0, 8(RSP)
decllinetest.go:11 0x9cdd4 f9000bff MOVD ZR, 16(RSP)
decllinetest.go:11 0x9cdd8 9400000a CALL main.f1(SB)
decllinetest.go:12 0x9cddc f85f83fd LDUR -8(RSP), R29
decllinetest.go:12 0x9cde0 f84307fe MOVD.P 48(RSP), R30
decllinetest.go:12 0x9cde4 d65f03c0 RET
decllinetest.go:7 0x9cde8 aa1e03e3 MOVD R30, R3
decllinetest.go:7 0x9cdec 97ff321d CALL runtime.morestack_noctxt(SB)
decllinetest.go:7 0x9cdf0 17ffffec JMP main.main(SB)
decllinetest.go:7 0x9cdf4 00000000 ?
decllinetest.go:7 0x9cdf8 00000000 ?
decllinetest.go:7 0x9cdfc 00000000 ?
With main.f1 following immediately after at 0x9ce00. Debug_line contains the following for address 0x9ce00:
[0x00026ce9] Special opcode 120: advance Address by 12 to 0x9cde8 and Line by -4 to 7
[0x00026cea] Special opcode 244: advance Address by 24 to 0x9ce00 and Line by 0 to 7
[0x00026ceb] Extended opcode 1: End of Sequence
[0x00026cee] Extended opcode 2: set Address to 0x9ce00
[0x00026cf9] Set File Name to entry 2 in the File Name Table
[0x00026cfb] Advance Line by 8 to 9
[0x00026cfd] Special opcode 9: advance Address by 0 to 0x9ce00 and Line by 5 to 14
Address 0x9cee is marked both as decllinetest.go:7 (first line of main.main) at 0x00026cea and then as decllinetest.go:14 (first line of main.f1) by 0x00026cfd.
This is a problem for Delve because it will pick the first entry in debug_line which in this case sytematically leads to a mistake. I tried changing it to always select the last entry for a given PC address but that causes problems with Go 1.14 which emitted multiple entries for each address but with the first one being the right one. I could change it to first look for the start of a sequence that matches the function entry point but that wouldn't work with older versions of Go that do not emit a sequence for each function.
The linker-side fix would be to not use putpclcdelta at the end of generateDebugLinesSymbol and instead issue a DW_LNS_const_add_pc followed by a DW_LNS_advance_line manually.
cc @thanm