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

runtime: runtime.FuncForPC().FileLine() returns an incorrect line #50397

Open
e-nikolov opened this issue Dec 30, 2021 · 1 comment
Open

runtime: runtime.FuncForPC().FileLine() returns an incorrect line #50397

e-nikolov opened this issue Dec 30, 2021 · 1 comment

Comments

@e-nikolov
Copy link

@e-nikolov e-nikolov commented Dec 30, 2021

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

$ go version 1.18beta1

Does this issue reproduce with the latest release?

reproduces for all go versions including and after go 1.7

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/enikolov/.cache/go-build"
GOENV="/home/enikolov/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/enikolov/.asdf/installs/golang/1.18beta1/packages/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/enikolov/.asdf/installs/golang/1.18beta1/packages"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/enikolov/.asdf/installs/golang/1.18beta1/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/enikolov/.asdf/installs/golang/1.18beta1/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18beta1"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/enikolov/dev/go-chai/chai/go.mod"
GOWORK=""
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-build212376993=/tmp/go-build -gno-record-gcc-switches"

What did you do?

https://go.dev/play/p/XxgAqT0Ds1j

package main

import (
	"fmt"
	"reflect"
	"runtime"
)

//go:noinline
func HelloGood() string {

	//

	//

	//

	_ = HelloBad() + HelloBad()

	return "hello"
}

//go:noinline
func HelloBad() string {

	//

	//

	//

	return "hello"
}

func main() {
	printFuncInfo(HelloGood) // Prints the line where HelloGood() is defined
	printFuncInfo(HelloBad)  // Prints the line where HelloBad() returns instead (due to some compiler optimizations(?))
}

func printFuncInfo(fn func() string) {
	pc := reflect.ValueOf(fn).Pointer()

	f := runtime.FuncForPC(pc)
	file, line := f.FileLine(pc)

	fmt.Printf("%+v %+v %+v\n", f.Name(), f.Entry(), pc)
	fmt.Printf("file: %+v\n", file)
	fmt.Printf("line: %+v\n", line)
	fmt.Printf("-----------\n")
}

What did you expect to see?

I expected the entry for HelloBad() to print the line where it is defined but instead it prints the line where it returns

The functions should not be inlined due to the //go:noinline directives.
Disabling go compiler optimizations via go run -gcflags -N is a workaround.

@cherrymui
Copy link
Contributor

@cherrymui cherrymui commented Dec 30, 2021

HelloGood has a function prologue which is treated at the line of the function definition. HelloBad is simple enough that it doesn't have a prologue and all its instructions are for that return statement, so the return statement's line number is printed. There is no instruction at the line of function definition.

I don't think that is incorrect. FileLine prints the "line number of the source code corresponding to the program counter pc", and the given pc is actually corresponding to the return statement.

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

Successfully merging a pull request may close this issue.

None yet
3 participants