Skip to content

cmd/link: debug_line can contain multiple entries for the same PC address in Go 1.15.4 #42484

@aarzilli

Description

@aarzilli

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions