github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/loader/loader_go116_test.go (about) 1 //go:build go1.16 && !go1.17 2 // +build go1.16,!go1.17 3 4 /* 5 * Copyright 2021 ByteDance Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 package loader 21 22 import ( 23 "fmt" 24 "runtime" 25 "runtime/debug" 26 "strconv" 27 "testing" 28 "unsafe" 29 30 "github.com/goshafaq/sonic/internal/rt" 31 "github.com/stretchr/testify/require" 32 ) 33 34 func TestLoad(t *testing.T) { 35 // defer func() { 36 // if r := recover(); r != nil { 37 // runtime.GC() 38 // if r != "hook1" { 39 // t.Fatal("not right panic:" + r.(string)) 40 // } 41 // } else { 42 // t.Fatal("not panic") 43 // } 44 // }() 45 46 var hstr string 47 48 type TestFunc func(i *int, hook func(i *int)) int 49 var hook = func(i *int) { 50 runtime.GC() 51 debug.FreeOSMemory() 52 hstr = ("hook" + strconv.Itoa(*i)) 53 runtime.GC() 54 debug.FreeOSMemory() 55 } 56 // var f TestFunc = func(i *int, hook func(i *int)) int { 57 // var t = *i 58 // hook(i) 59 // return t + *i 60 // } 61 bc := []byte{ 62 0x48, 0x83, 0xec, 0x18, // (0x00) subq $24, %rsp 63 0x48, 0x89, 0x6c, 0x24, 0x10, // (0x04) movq %rbp, 16(%rsp) 64 0x48, 0x8d, 0x6c, 0x24, 0x10, // (0x09) leaq 16(%rsp), %rbp 65 0x48, 0x8b, 0x44, 0x24, 0x20, // (0x0e) movq 32(%rsp), %rax 66 0x48, 0x8b, 0x08, // (0x13) movq (%rax), %rcx 67 0x48, 0x89, 0x4c, 0x24, 0x08, // (0x16) movq %rcx, 8(%rsp) 68 0x48, 0x8b, 0x54, 0x24, 0x28, // (0x1b) movq 40(%rsp), %rdx 69 0x48, 0x8b, 0x1a, // (0x20) movq (%rdx), %rbx 70 0x48, 0x89, 0x04, 0x24, // (0x23) movq %rax, (%rsp) 71 0xff, 0xd3, // (0x27) callq %rbx 72 0x48, 0x8b, 0x44, 0x24, 0x08, // (0x29) movq 8(%rsp), %rax 73 0x48, 0x8b, 0x4c, 0x24, 0x20, // (0x2e) movq 32(%rsp), %rcx 74 0x48, 0x03, 0x01, // (0x33) addq (%rcx), %rax 75 0x48, 0x89, 0x44, 0x24, 0x30, // (0x36) movq %rax, 48(%rsp) 76 0x48, 0x8b, 0x6c, 0x24, 0x10, // (0x3b) movq 16(%rsp), %rbp 77 0x48, 0x83, 0xc4, 0x18, // (0x40) addq $24, %rsp 78 0xc3, // (0x44) ret 79 } 80 81 size := uint32(len(bc)) 82 fn := Func{ 83 ID: 0, 84 Flag: 0, 85 ArgsSize: 16, 86 EntryOff: 0, 87 TextSize: size, 88 DeferReturn: 0, 89 FileIndex: 0, 90 Name: "dummy", 91 } 92 93 fn.Pcsp = &Pcdata{ 94 {PC: size, Val: 24}, 95 } 96 97 fn.Pcline = &Pcdata{ 98 {PC: 0x13, Val: 0}, 99 {PC: 0x1b, Val: 1}, 100 {PC: 0x23, Val: 2}, 101 {PC: size, Val: 3}, 102 } 103 104 fn.Pcfile = &Pcdata{ 105 {PC: size, Val: 0}, 106 } 107 108 fn.PcUnsafePoint = &Pcdata{ 109 {PC: size, Val: PCDATA_UnsafePointUnsafe}, 110 } 111 112 fn.PcStackMapIndex = &Pcdata{ 113 {PC: size, Val: 0}, 114 } 115 116 args := rt.StackMapBuilder{} 117 args.AddField(true) 118 args.AddField(true) 119 fn.ArgsPointerMaps = args.Build() 120 ab, _ := fn.ArgsPointerMaps.MarshalBinary() 121 fmt.Printf("args: %+v\n", ab) 122 123 locals := rt.StackMapBuilder{} 124 locals.AddField(false) 125 locals.AddField(false) 126 fn.LocalsPointerMaps = locals.Build() 127 lb, _ := fn.LocalsPointerMaps.MarshalBinary() 128 fmt.Printf("locals: %+v\n", lb) 129 130 rets := Load(bc, []Func{fn}, "dummy_module", []string{"github.com/goshafaq/sonic/dummy.go"}) 131 println("func address ", *(*unsafe.Pointer)(rets[0])) 132 // for k, _ := range moduleCache.m { 133 // spew.Dump(k) 134 // } 135 f := *(*TestFunc)(unsafe.Pointer(&rets[0])) 136 i := 1 137 j := f(&i, hook) 138 require.Equal(t, 2, j) 139 require.Equal(t, "hook1", hstr) 140 141 fi := runtime.FuncForPC(*(*uintptr)(rets[0])) 142 require.Equal(t, "dummy", fi.Name()) 143 file, line := fi.FileLine(0) 144 require.Equal(t, "github.com/goshafaq/sonic/dummy.go", file) 145 require.Equal(t, 0, line) 146 }