diff options
Diffstat (limited to 'test/fixedbugs/issue17381.go')
-rw-r--r-- | test/fixedbugs/issue17381.go | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/test/fixedbugs/issue17381.go b/test/fixedbugs/issue17381.go new file mode 100644 index 0000000..be63633 --- /dev/null +++ b/test/fixedbugs/issue17381.go @@ -0,0 +1,54 @@ +// run + +// Copyright 2016 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. + +// issue 17381: make sure leave function with non-empty frame +// saves link register, so that traceback will work. + +package main + +import ( + "runtime" + "unsafe" +) + +func main() { + defer func() { + if recover() == nil { + panic("did not panic") + } + pcs := make([]uintptr, 20) + n := runtime.Callers(1, pcs) + for _, pc := range pcs[:n] { + if runtime.FuncForPC(pc).Name() == "main.main" { + return + } + } + panic("cannot find main.main in backtrace") + }() + + prep() + f() // should panic +} + +func funcPC(f interface{}) uintptr { + var ptr uintptr + return **(**uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&f)) + unsafe.Sizeof(ptr))) +} + +//go:noinline +func f() { + var t [1]int // non-empty frame + *(*int)(nil) = t[0] +} + +var p = funcPC(runtime.GC) + 8 + +//go:noinline +func prep() { + // put some garbage on stack + var x = [20]uintptr{p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p} + _ = x +} |