Skip to content

cmd/compile: pcstmt marker applied to the wrong instruction #29443

@aarzilli

Description

@aarzilli

What version of Go are you using (go version)?

$ go version
go version go1.11.4 linux/amd64

but also devel at c043fc4 (newest as of today)

What did you do?

Take this program:

package main

import "fmt"

var aflag = false
var bflag = false

func testfn() {
	if bflag {
		if aflag {
			g()
		}
	}

	h()
}

func g() {
}

func h() {
	fmt.Printf("breakpoint skipped\n")
}

func main() {
	testfn()
}

compile with go build -gcflags='-N -l' onajmp.go, then:

$ gdb ./onajmp
...
Reading symbols from ./onajmp...done.
Loading Go Runtime support.
(gdb) b /home/a/temp/onajmp.go:15
Breakpoint 1 at 0x487748: file /home/a/temp/onajmp.go, line 15.
(gdb) r
Starting program: /home/a/temp/onajmp 
[New LWP 1180]
[New LWP 1181]
[New LWP 1182]
breakpoint skipped
[LWP 1175 exited]
[LWP 1180 exited]
[LWP 1182 exited]
[Inferior 1 (process 1175) exited normally]

(or use delve+break+continue, exact same thing).

The breakpoint on line 15 (the call to main.h) gets skipped entirely.

Why

onajmp.go:8 | S | 0x487710 | 64488b0c25f8ffffff | MOVQ FS:0xfffffff8, CX
onajmp.go:8 |   | 0x487719 | 483b6110 | CMPQ 0x10(CX), SP
onajmp.go:8 |   | 0x48771d | 763d | JBE 0x48775c
onajmp.go:8 | SP | 0x48771f | 4883ec08 | SUBQ $0x8, SP
onajmp.go:8 |   | 0x487723 | 48892c24 | MOVQ BP, 0(SP)
onajmp.go:8 |   | 0x487727 | 488d2c24 | LEAQ 0(SP), BP
onajmp.go:9 | S | 0x48772b | 803db6770e0000 | CMPB $0x0, 0xe77b6(IP)
onajmp.go:9 |   | 0x487732 | 7502 | JNE 0x487736
onajmp.go:9 |   | 0x487734 | eb24 | JMP 0x48775a
onajmp.go:10 | S | 0x487736 | 803daa770e0000 | CMPB $0x0, 0xe77aa(IP)
onajmp.go:10 |   | 0x48773d | 7502 | JNE 0x487741
onajmp.go:10 |   | 0x48773f | eb17 | JMP 0x487758
onajmp.go:11 | S | 0x487741 | e82a000000 | CALL main.g(SB)
onajmp.go:11 |   | 0x487746 | eb00 | JMP 0x487748
onajmp.go:15 | S | 0x487748 | eb00 | JMP 0x48774a
onajmp.go:15 |   | 0x48774a | e831000000 | CALL main.h(SB)
onajmp.go:16 | S | 0x48774f | 488b2c24 | MOVQ 0(SP), BP
onajmp.go:16 |   | 0x487753 | 4883c408 | ADDQ $0x8, SP
onajmp.go:16 |   | 0x487757 | c3 | RET
onajmp.go:10 |   | 0x487758 | ebee | JMP 0x487748
onajmp.go:9 |   | 0x48775a | ebee | JMP 0x48774a
onajmp.go:8 | S | 0x48775c | e82f71fcff | CALL runtime.morestack_noctxt(SB)
onajmp.go:8 |   | 0x487761 | ebad | JMP main.testfn(SB)

The statement marker for line 15 ends up on instruction 0x487748, a JMP, instead of 0x48774a. But the program reaches that line from another path that jumps directly to 0x48774a. Specifically through: 0x487734 → 0x48775a → 0x48774a.

@gopherbot, please add label Debugging
cc @heschik @dr2chase

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions