Home | History | Annotate | Download | only in fixedbugs
      1 // run
      2 
      3 // Copyright 2016 The Go Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style
      5 // license that can be found in the LICENSE file.
      6 
      7 // issue 17381: make sure leave function with non-empty frame
      8 // saves link register, so that traceback will work.
      9 
     10 package main
     11 
     12 import (
     13 	"runtime"
     14 	"unsafe"
     15 )
     16 
     17 func main() {
     18 	defer func() {
     19 		if recover() == nil {
     20 			panic("did not panic")
     21 		}
     22 		pcs := make([]uintptr, 20)
     23 		n := runtime.Callers(1, pcs)
     24 		for _, pc := range pcs[:n] {
     25 			if runtime.FuncForPC(pc).Name() == "main.main" {
     26 				return
     27 			}
     28 		}
     29 		panic("cannot find main.main in backtrace")
     30 	}()
     31 
     32 	prep()
     33 	f() // should panic
     34 }
     35 
     36 func funcPC(f interface{}) uintptr {
     37 	var ptr uintptr
     38 	return **(**uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&f)) + unsafe.Sizeof(ptr)))
     39 }
     40 
     41 //go:noinline
     42 func f() {
     43 	var t [1]int // non-empty frame
     44 	*(*int)(nil) = t[0]
     45 }
     46 
     47 var p = funcPC(runtime.GC) + 8
     48 
     49 //go:noinline
     50 func prep() {
     51 	// put some garbage on stack
     52 	var x = [20]uintptr{p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p}
     53 	_ = x
     54 }
     55