1 2 /*
3 * Copyright 2021 ByteDance Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 18 package loader
19 20 import (
21 `github.com/bytedance/sonic/loader/internal/rt`
22 )
23 24 // LoadFuncs loads only one function as module, and returns the function pointer
25 // - text: machine code
26 // - funcName: function name
27 // - frameSize: stack frame size.
28 // - argSize: argument total size (in bytes)
29 // - argPtrs: indicates if a slot (8 Bytes) of arguments memory stores pointer, from low to high
30 // - localPtrs: indicates if a slot (8 Bytes) of local variants memory stores pointer, from low to high
31 //
32 // WARN:
33 // - the function MUST has fixed SP offset equaling to this, otherwise it go.gentraceback will fail
34 // - the function MUST has only one stack map for all arguments and local variants
35 func (self Loader) LoadOne(text []byte, funcName string, frameSize int, argSize int, argPtrs []bool, localPtrs []bool) Function {
36 size := uint32(len(text))
37 38 fn := Func{
39 Name: funcName,
40 TextSize: size,
41 ArgsSize: int32(argSize),
42 }
43 44 // NOTICE: suppose the function has fixed SP offset equaling to frameSize, thus make only one pcsp pair
45 fn.Pcsp = &Pcdata{
46 {PC: size, Val: int32(frameSize)},
47 }
48 49 if self.NoPreempt {
50 fn.PcUnsafePoint = &Pcdata{
51 {PC: size, Val: PCDATA_UnsafePointUnsafe},
52 }
53 } else {
54 fn.PcUnsafePoint = &Pcdata{
55 {PC: size, Val: PCDATA_UnsafePointSafe},
56 }
57 }
58 59 // NOTICE: suppose the function has only one stack map at index 0
60 fn.PcStackMapIndex = &Pcdata{
61 {PC: size, Val: 0},
62 }
63 64 if argPtrs != nil {
65 args := rt.StackMapBuilder{}
66 for _, b := range argPtrs {
67 args.AddField(b)
68 }
69 fn.ArgsPointerMaps = args.Build()
70 }
71 72 if localPtrs != nil {
73 locals := rt.StackMapBuilder{}
74 for _, b := range localPtrs {
75 locals.AddField(b)
76 }
77 fn.LocalsPointerMaps = locals.Build()
78 }
79 80 out := Load(text, []Func{fn}, self.Name + funcName, []string{self.File})
81 return out[0]
82 }
83 84 // Load loads given machine codes and corresponding function information into go moduledata
85 // and returns runnable function pointer
86 // WARN: this API is experimental, use it carefully
87 func Load(text []byte, funcs []Func, modulename string, filenames []string) (out []Function) {
88 ids := make([]string, len(funcs))
89 for i, f := range funcs {
90 ids[i] = f.Name
91 }
92 // generate module data and allocate memory address
93 mod := makeModuledata(modulename, filenames, &funcs, text)
94 95 // verify and register the new module
96 moduledataverify1(mod)
97 registerModule(mod)
98 99 //
100 // encapsulate function address
101 out = make([]Function, len(funcs))
102 for i, s := range ids {
103 for _, f := range funcs {
104 if f.Name == s {
105 m := uintptr(mod.text + uintptr(f.EntryOff))
106 out[i] = Function(&m)
107 }
108 }
109 }
110 return
111 }
112