1 // run 2 3 // Copyright 2015 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 // darwin/386 seems to mangle the PC and SP before 8 // it manages to invoke the signal handler, so this test fails there. 9 // +build !darwin !386 10 // 11 // openbsd/386 and netbsd/386 don't work, not sure why. 12 // +build !openbsd !386 13 // +build !netbsd !386 14 // 15 // windows doesn't work, because Windows exception handling 16 // delivers signals based on the current PC, and that current PC 17 // doesn't go into the Go runtime. 18 // +build !windows 19 // 20 // arm64 gets "illegal instruction" (why is the data executable?) 21 // and is unable to do the traceback correctly (why?). 22 // +build !arm64 23 24 package main 25 26 import ( 27 "runtime" 28 "runtime/debug" 29 "unsafe" 30 ) 31 32 func main() { 33 debug.SetPanicOnFault(true) 34 defer func() { 35 if err := recover(); err == nil { 36 panic("not panicking") 37 } 38 pc, _, _, _ := runtime.Caller(10) 39 f := runtime.FuncForPC(pc) 40 if f == nil || f.Name() != "main.f" { 41 if f == nil { 42 println("no func for ", unsafe.Pointer(pc)) 43 } else { 44 println("found func:", f.Name()) 45 } 46 panic("cannot find main.f on stack") 47 } 48 }() 49 f(20) 50 } 51 52 func f(n int) { 53 if n > 0 { 54 f(n - 1) 55 } 56 var f struct { 57 x uintptr 58 } 59 f.x = uintptr(unsafe.Pointer(&f)) 60 fn := *(*func())(unsafe.Pointer(&f)) 61 fn() 62 } 63