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  }