Skip to content

cmd/compile: misleading PC <> line number with "for {}" #30167

@pwaller

Description

@pwaller

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

$ go version
go1.12beta2

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/pwaller/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/pwaller/.local"
GOPROXY=""
GORACE=""
GOROOT="/home/pwaller/.local/src/go"
GOTMPDIR=""
GOTOOLDIR="/home/pwaller/.local/src/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build478432202=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Compiled the following program:

package main

func main() {
	go func() {}()

	for {}
}

What did you expect to see?

I expected the infinite for loop in the binary to be correctly mapped to the source.

What did you see instead?

The for loop is on line 6 in the source, but in the binary at 0x44f0d5, where there is a "jmp-to-self", it is shown by go tool objdump at main.go:4.

$ go1.12beta2 build && go tool objdump -s main.main misleading-debuginfo

TEXT main.main(SB) .../misleading-debuginfo/main.go
  main.go:3		0x44f0a0		64488b0c25f8ffffff	MOVQ FS:0xfffffff8, CX			
  main.go:3		0x44f0a9		483b6110		CMPQ 0x10(CX), SP			
  main.go:3		0x44f0ad		7628			JBE 0x44f0d7				
  main.go:3		0x44f0af		4883ec18		SUBQ $0x18, SP				
  main.go:3		0x44f0b3		48896c2410		MOVQ BP, 0x10(SP)			
  main.go:3		0x44f0b8		488d6c2410		LEAQ 0x10(SP), BP			
  main.go:4		0x44f0bd		c7042400000000		MOVL $0x0, 0(SP)			
  main.go:4		0x44f0c4		488d05fd420200		LEAQ 0x242fd(IP), AX			
  main.go:4		0x44f0cb		4889442408		MOVQ AX, 0x8(SP)			
  main.go:4		0x44f0d0		e82bd1fdff		CALL runtime.newproc(SB)		
  main.go:4		0x44f0d5		ebfe			JMP 0x44f0d5				
  main.go:3		0x44f0d7		e8d47effff		CALL runtime.morestack_noctxt(SB)	
  main.go:3		0x44f0dc		ebc2			JMP main.main(SB)			

Additional thinking

I encountered this while diagnosing golang/tools#74 - an issue causing 100% CPU usage unnecessarily. Because the mapping was incorrect, I did not immediately discover the for {} (I wasn't expecting it).

In the example above, the "infinite for" is not far away from its correct location, but it is easy to imagine them being quite distant (for example if the goroutine had a substantial chunk of code in it).

I realize that a precise PC <> line number in general might be too much to ask for. But it seems worth asking, and if it is too much, at least this issue serves to document some discussion.

@gopherbot please add label Debugging.

/cc @ianlancetaylor who likely knows about these things.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DebuggingFrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions