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

gccgo: incorrect call stack from runtime.CallersFrames #29619

Open
randall77 opened this issue Jan 8, 2019 · 1 comment

Comments

@randall77
Copy link
Contributor

commented Jan 8, 2019

Stack traces are not quite right for gccgo with optimizations on (mid-stack inlining, particularly).

package main

import (
	"fmt"
	"runtime"
)

func main() {
	f()
}
func f() {
	g()
}

//go:noinline
func g() {
	for i := 0; i < 4; i++ {
		var pcs [1]uintptr
		runtime.Callers(i+1, pcs[:])
		f, _ := runtime.CallersFrames(pcs[:]).Next()
		fmt.Printf("%x %s %s:%d\n", f.PC, f.Function, f.File, f.Line)
	}
}

Running under gc, I get:

48683c main.g /usr/local/google/home/khr/gowork/tmp5.go:19
48678f main.f /usr/local/google/home/khr/gowork/tmp5.go:12
48675f main.main /usr/local/google/home/khr/gowork/tmp5.go:9
428846 runtime.main /usr/local/google/home/khr/go1.11/src/runtime/proc.go:201

Running under gccgo -O3, I get:

56261c5ebc19 main.g /usr/local/google/home/khr/gowork/tmp5.go:19
56261c5ebeb3 main.f /usr/local/google/home/khr/gowork/tmp5.go:12
56261c5ebeb3 main.f /usr/local/google/home/khr/gowork/tmp5.go:12
7f9974ede51c runtime_main ../../../src/libgo/runtime/proc.c:606

Note the third line - that should be main.main, not a second copy of main.f.
gccgo works without -O3.

Mid-stack inlining is happening with -O3, main.main calls main.g directly. main.f isn't even in the binary.

It doesn't help to provide runtime.Callers a larger buffer.

Note that this code does work, calling runtime.Callers just once and using the runtime.CallersFrames iterator:

package main

import (
	"fmt"
	"runtime"
)

func main() {
	f()
}
func f() {
	g()
}

//go:noinline
func g() {
	var pcs [10]uintptr
	n := runtime.Callers(1, pcs[:])
	iter := runtime.CallersFrames(pcs[:n])
	for {
		f, more := iter.Next()
		fmt.Printf("%x %s %s:%d\n", f.PC, f.Function, f.File, f.Line)
		if !more {
			break
		}
	}
}
55bb3972acd4 main.g /usr/local/google/home/khr/gowork/tmp6.go:18
55bb3972afc3 main.f /usr/local/google/home/khr/gowork/tmp6.go:12
55bb3972afc3 main.main /usr/local/google/home/khr/gowork/tmp6.go:9
7fa2706d451c runtime_main ../../../src/libgo/runtime/proc.c:606

@ianlancetaylor

@randall77 randall77 added this to the Gccgo milestone Jan 8, 2019

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 8, 2019

This is not surprising. The only way I can see to make this work is to use magic PC values, such as the inline marker NOPs you are using in cmd/compile. Since gccgo does not change the GCC backend, it has no opportunity for such markers. I can't see any reason to write code like your first program, so I'm not inclined to put any time into trying to fix this in gccgo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.