1
0
mirror of https://github.com/golang/go synced 2024-11-24 09:50:17 -07:00
go/test/inline_callers.go
Keith Randall 956879dd0b runtime: make FuncForPC return the innermost inlined frame
Returning the innermost frame instead of the outermost
makes code that walks the results of runtime.Caller{,s}
still work correctly in the presence of mid-stack inlining.

Fixes #29582

Change-Id: I2392e3dd5636eb8c6f58620a61cef2194fe660a7
Reviewed-on: https://go-review.googlesource.com/c/156364
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2019-01-08 21:54:04 +00:00

96 lines
1.9 KiB
Go

// run -gcflags=-l=4
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"runtime"
)
var skip int
var npcs int
var pcs = make([]uintptr, 32)
func f() {
g()
}
func g() {
h()
}
func h() {
npcs = runtime.Callers(skip, pcs)
}
func testCallers(skp int) (frames []string) {
skip = skp
f()
for i := 0; i < npcs; i++ {
fn := runtime.FuncForPC(pcs[i] - 1)
frames = append(frames, fn.Name())
if fn.Name() == "main.main" {
break
}
}
return
}
func testCallersFrames(skp int) (frames []string) {
skip = skp
f()
callers := pcs[:npcs]
ci := runtime.CallersFrames(callers)
for {
frame, more := ci.Next()
frames = append(frames, frame.Function)
if !more || frame.Function == "main.main" {
break
}
}
return
}
var expectedFrames [][]string = [][]string{
0: {"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallers", "main.main"},
1: {"main.h", "main.g", "main.f", "main.testCallers", "main.main"},
2: {"main.g", "main.f", "main.testCallers", "main.main"},
3: {"main.f", "main.testCallers", "main.main"},
4: {"main.testCallers", "main.main"},
5: {"main.main"},
}
var allFrames = []string{"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallersFrames", "main.main"}
func same(xs, ys []string) bool {
if len(xs) != len(ys) {
return false
}
for i := range xs {
if xs[i] != ys[i] {
return false
}
}
return true
}
func main() {
for i := 0; i <= 5; i++ {
frames := testCallers(i)
expected := expectedFrames[i]
if !same(frames, expected) {
fmt.Printf("testCallers(%d):\n got %v\n want %v\n", i, frames, expected)
}
frames = testCallersFrames(i)
expected = allFrames[i:]
if !same(frames, expected) {
fmt.Printf("testCallersFrames(%d):\n got %v\n want %v\n", i, frames, expected)
}
}
}