|  | // 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 | 
|  | } |