Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/link: DWARF line tables seem to be off by 1 instruction #12942

ribrdb opened this issue Oct 14, 2015 · 3 comments

cmd/link: DWARF line tables seem to be off by 1 instruction #12942

ribrdb opened this issue Oct 14, 2015 · 3 comments


Copy link

@ribrdb ribrdb commented Oct 14, 2015

go version go1.5.1 darwin/amd64

I was noticing that values printed in the debugger often seem to be uninitialized when stepping past a line that initializes them. It appears that the DWARF line tables are advancing the line number one instruction too early. For example, with this go code

23 func main() {
24  lf, err := os.OpenFile("test", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
25  if err != nil {
26      log.Fatalf("error opening file: %v", err)
27  }
28 ....

dwarfdump shows this for the line table:

0x000063e4: DW_LNE_set_address( 0x0000000004002e90 )
0x000063ef: DW_LNS_advance_line( 22 )
0x000063f1: address += 0,  line += 0
            0x0000000004002e90      1     23      0 is_stmt

0x000063f2: DW_LNS_advance_pc( 100 )
0x000063f4: address += 0,  line += 1
            0x0000000004002ef4      1     24      0 is_stmt

0x000063f5: DW_LNS_advance_pc( 70 )
0x000063f7: address += 0,  line += 1
            0x0000000004002f3a      1     25      0 is_stmt

It shows line 25 starting at 0x4002f3a. However, from the disassembly this appears to be the last instruction of line 24. Line 25 starts at 0x4002f42:

    0x4002e90 <+0>:    movq   %gs:0x8a0, %rcx
    0x4002e99 <+9>:    leaq   -0x160(%rsp), %rax
    0x4002ea1 <+17>:   cmpq   0x10(%rcx), %rax
    0x4002ea5 <+21>:   jbe    0x4003d32                 ; <+3746> at test.go:23
    0x4002eab <+27>:   subq   $0x1e0, %rsp
    0x4002eb2 <+34>:   xorl   %eax, %eax
    0x4002eb4 <+36>:   movq   %rax, 0x1c0(%rsp)
    0x4002ebc <+44>:   movq   %rax, 0x1c8(%rsp)
    0x4002ec4 <+52>:   movq   %rax, 0x1d0(%rsp)
    0x4002ecc <+60>:   movq   %rax, 0x1d8(%rsp)
    0x4002ed4 <+68>:   movq   %rax, 0x170(%rsp)
    0x4002edc <+76>:   movq   %rax, 0x178(%rsp)
    0x4002ee4 <+84>:   movq   %rax, 0x130(%rsp)
    0x4002eec <+92>:   movq   %rax, 0x138(%rsp)
    0x4002ef4 <+100>:  leaq   0x3b6865(%rip), %rbx      ; go.string.* + 93856
    0x4002efb <+107>:  movq   %rbx, (%rsp)
    0x4002eff <+111>:  movq   $0xb, 0x8(%rsp)
    0x4002f08 <+120>:  movq   $0x20a, 0x10(%rsp)
    0x4002f11 <+129>:  movl   $0x1b6, 0x18(%rsp)
    0x4002f19 <+137>:  callq  0x40b8cb0                 ; os.OpenFile at file_unix.go:85
    0x4002f1e <+142>:  movq   0x20(%rsp), %rbx
    0x4002f23 <+147>:  movq   %rbx, 0x70(%rsp)
    0x4002f28 <+152>:  movq   0x28(%rsp), %rcx
    0x4002f2d <+157>:  movq   0x30(%rsp), %rdx
    0x4002f32 <+162>:  movq   %rdx, 0xe8(%rsp)
->  0x4002f3a <+170>:  movq   %rcx, 0xe0(%rsp)
    0x4002f42 <+178>:  cmpq   $0x0, %rcx
@ianlancetaylor ianlancetaylor changed the title DWARF line tables seem to be off by 1 instruction cmd/link: DWARF line tables seem to be off by 1 instruction Oct 14, 2015
@ianlancetaylor ianlancetaylor added this to the Go1.6 milestone Oct 14, 2015
Copy link
Contributor Author

@ribrdb ribrdb commented Oct 15, 2015

I looked at gc's assembly output, and it shows the same issue, so this isn't a problem with the dwarf generation. Also I can't seem to reproduce it if I use --gcflags "-N -l" to disable optimization, so it may not be worth digging in to.

Copy link

@rsc rsc commented Nov 5, 2015

It's not an off-by-one. The instruction you identified is the spill of a variable to memory. Spills don't really have a "correct" line number. They can be arbitrarily delayed, too, so certainly line 24 could end and parts of line 25 could continue to execute before the spill happened. In this sense the current line number reporting is probably better. Anyway, it's a very hard problem.

@rsc rsc added this to the Unplanned milestone Nov 5, 2015
@rsc rsc removed this from the Go1.6 milestone Nov 5, 2015
Copy link
Contributor Author

@ribrdb ribrdb commented Nov 5, 2015

In that case I guess that the problem is that the debug info says the variable is located in memory for the entire function, but it should instead reference the register at this instruction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

3 participants