1// Copyright 2015 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package main 6 7import ( 8 "encoding/binary" 9 "runtime" 10 "runtime/debug" 11 "unsafe" 12) 13 14func main() { 15 debug.SetPanicOnFault(true) 16 defer func() { 17 if err := recover(); err == nil { 18 panic("not panicking") 19 } 20 pc, _, _, _ := runtime.Caller(10) 21 f := runtime.FuncForPC(pc) 22 if f == nil || f.Name() != "main.f" { 23 if f == nil { 24 println("no func for ", unsafe.Pointer(pc)) 25 } else { 26 println("found func:", f.Name()) 27 } 28 panic("cannot find main.f on stack") 29 } 30 }() 31 f(20) 32} 33 34func f(n int) { 35 if n > 0 { 36 f(n - 1) 37 } 38 var f struct { 39 x uintptr 40 } 41 42 // We want to force a seg fault, to get a crash at a PC value != 0. 43 // Not all systems make the data section non-executable. 44 ill := make([]byte, 64) 45 switch runtime.GOARCH { 46 case "386", "amd64": 47 ill = append(ill[:0], 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0 48 case "arm": 49 binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000) // MOVW $0, R0 50 binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000) // MOVW R0, (R0) 51 case "arm64": 52 binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR) 53 case "ppc64": 54 binary.BigEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0) 55 case "ppc64le": 56 binary.LittleEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0) 57 case "mips", "mips64": 58 binary.BigEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0) 59 case "mipsle", "mips64le": 60 binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0) 61 case "s390x": 62 ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0 63 ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0) 64 case "riscv64": 65 binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0) 66 default: 67 // Just leave it as 0 and hope for the best. 68 } 69 70 f.x = uintptr(unsafe.Pointer(&ill[0])) 71 p := &f 72 fn := *(*func())(unsafe.Pointer(&p)) 73 syncIcache(f.x) 74 fn() 75} 76