1
2
3
4
5 package main
6
7 import (
8 "encoding/binary"
9 "runtime"
10 "runtime/debug"
11 "unsafe"
12 )
13
14 func 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
34 func f(n int) {
35 if n > 0 {
36 f(n - 1)
37 }
38 var f struct {
39 x uintptr
40 }
41
42
43
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)
48 case "arm":
49 binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000)
50 binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000)
51 case "arm64":
52 binary.LittleEndian.PutUint32(ill, 0xf90003ff)
53 case "ppc64":
54 binary.BigEndian.PutUint32(ill, 0xf8000000)
55 case "ppc64le":
56 binary.LittleEndian.PutUint32(ill, 0xf8000000)
57 case "mips", "mips64":
58 binary.BigEndian.PutUint32(ill, 0xfc000000)
59 case "mipsle", "mips64le":
60 binary.LittleEndian.PutUint32(ill, 0xfc000000)
61 case "s390x":
62 ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00)
63 ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24)
64 case "riscv64":
65 binary.LittleEndian.PutUint32(ill, 0x00003023)
66 default:
67
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
View as plain text