github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/loader/loader_latest.go (about) 1 //go:build go1.16 && !go1.22 2 // +build go1.16,!go1.22 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 "github.com/goshafaq/sonic/internal/rt" 24 ) 25 26 // LoadFuncs loads only one function as module, and returns the function pointer 27 // - text: machine code 28 // - funcName: function name 29 // - frameSize: stack frame size. 30 // - argSize: argument total size (in bytes) 31 // - argPtrs: indicates if a slot (8 Bytes) of arguments memory stores pointer, from low to high 32 // - localPtrs: indicates if a slot (8 Bytes) of local variants memory stores pointer, from low to high 33 // 34 // WARN: 35 // - the function MUST has fixed SP offset equaling to this, otherwise it go.gentraceback will fail 36 // - the function MUST has only one stack map for all arguments and local variants 37 func (self Loader) LoadOne(text []byte, funcName string, frameSize int, argSize int, argPtrs []bool, localPtrs []bool) Function { 38 size := uint32(len(text)) 39 40 fn := Func{ 41 Name: funcName, 42 TextSize: size, 43 ArgsSize: int32(argSize), 44 } 45 46 // NOTICE: suppose the function has fixed SP offset equaling to frameSize, thus make only one pcsp pair 47 fn.Pcsp = &Pcdata{ 48 {PC: size, Val: int32(frameSize)}, 49 } 50 51 if self.NoPreempt { 52 fn.PcUnsafePoint = &Pcdata{ 53 {PC: size, Val: PCDATA_UnsafePointUnsafe}, 54 } 55 } else { 56 fn.PcUnsafePoint = &Pcdata{ 57 {PC: size, Val: PCDATA_UnsafePointSafe}, 58 } 59 } 60 61 // NOTICE: suppose the function has only one stack map at index 0 62 fn.PcStackMapIndex = &Pcdata{ 63 {PC: size, Val: 0}, 64 } 65 66 if argPtrs != nil { 67 args := rt.StackMapBuilder{} 68 for _, b := range argPtrs { 69 args.AddField(b) 70 } 71 fn.ArgsPointerMaps = args.Build() 72 } 73 74 if localPtrs != nil { 75 locals := rt.StackMapBuilder{} 76 for _, b := range localPtrs { 77 locals.AddField(b) 78 } 79 fn.LocalsPointerMaps = locals.Build() 80 } 81 82 out := Load(text, []Func{fn}, self.Name+funcName, []string{self.File}) 83 return out[0] 84 } 85 86 // Load loads given machine codes and corresponding function information into go moduledata 87 // and returns runnable function pointer 88 // WARN: this API is experimental, use it carefully 89 func Load(text []byte, funcs []Func, modulename string, filenames []string) (out []Function) { 90 ids := make([]string, len(funcs)) 91 for i, f := range funcs { 92 ids[i] = f.Name 93 } 94 // generate module data and allocate memory address 95 mod := makeModuledata(modulename, filenames, &funcs, text) 96 97 // verify and register the new module 98 moduledataverify1(mod) 99 registerModule(mod) 100 101 // 102 // encapsulate function address 103 out = make([]Function, len(funcs)) 104 for i, s := range ids { 105 for _, f := range funcs { 106 if f.Name == s { 107 m := uintptr(mod.text + uintptr(f.EntryOff)) 108 out[i] = Function(&m) 109 } 110 } 111 } 112 return 113 }