podman

Форк
0
185 строк · 4.8 Кб
1
/**
2
* Copyright 2023 ByteDance Inc.
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
*     http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
16

17
package loader
18

19
import (
20
	`reflect`
21
	`unsafe`
22

23
	`github.com/bytedance/sonic/internal/abi`
24
	`github.com/bytedance/sonic/internal/rt`
25
)
26

27
var _C_Redzone = []bool{false, false, false, false}
28

29
// CFunc is a function information for C func
30
type CFunc struct {
31
	// C function name
32
	Name     string
33

34
	// entry pc relative to entire text segment
35
	EntryOff uint32
36

37
	// function text size in bytes
38
	TextSize uint32
39

40
	// maximum stack depth of the function
41
	MaxStack uintptr
42

43
	// PC->SP delta lists of the function
44
	Pcsp     [][2]uint32
45
}
46

47
// GoC is the wrapper for Go calls to C
48
type GoC struct {
49
	// CName is the name of corresponding C function
50
	CName     string
51

52
	// CEntry points out where to store the entry address of corresponding C function.
53
	// It won't be set if nil
54
	CEntry   *uintptr
55

56
	// GoFunc is the POINTER of corresponding go stub function. 
57
	// It is used to generate Go-C ABI conversion wrapper and receive the wrapper's address 
58
	//   eg. &func(a int, b int) int 
59
	//     FOR 
60
	//     int add(int a, int b)
61
	// It won't be set if nil
62
	GoFunc   interface{} 
63
}
64

65
// WrapGoC wraps C functions and loader it into Go stubs
66
func WrapGoC(text []byte, natives []CFunc, stubs []GoC, modulename string, filename string) {
67
	funcs := make([]Func, len(natives))
68
	
69
	// register C funcs
70
	for i, f := range natives {
71
		fn := Func{
72
			Flag: FuncFlag_ASM,
73
			EntryOff: f.EntryOff,
74
			TextSize: f.TextSize,
75
			Name: f.Name,
76
		}
77
		if len(f.Pcsp) != 0 {
78
			fn.Pcsp = (*Pcdata)(unsafe.Pointer(&natives[i].Pcsp))
79
		}
80
		// NOTICE: always forbid async preempt
81
		fn.PcUnsafePoint = &Pcdata{
82
			{PC: f.TextSize, Val: PCDATA_UnsafePointUnsafe},
83
		}
84
		// NOTICE: always refer to first file
85
		fn.Pcfile = &Pcdata{
86
			{PC: f.TextSize, Val: 0},
87
		}
88
		// NOTICE: always refer to first line
89
		fn.Pcline = &Pcdata{
90
			{PC: f.TextSize, Val: 1},
91
		}
92
		// NOTICE: copystack need locals stackmap
93
		fn.PcStackMapIndex = &Pcdata{
94
			{PC: f.TextSize, Val: 0},
95
		}
96
		sm := rt.StackMapBuilder{}
97
		sm.AddField(false)
98
		fn.ArgsPointerMaps = sm.Build()
99
		fn.LocalsPointerMaps = sm.Build()
100
		funcs[i] = fn
101
	}
102
	rets := Load(text, funcs, modulename, []string{filename})
103

104
	// got absolute entry address
105
	native_entry := **(**uintptr)(unsafe.Pointer(&rets[0]))
106
	// println("native_entry: ", native_entry)
107

108
	wraps := make([]Func, 0, len(stubs))
109
	wrapIds := make([]int, 0, len(stubs))
110
	code := make([]byte, 0, len(wraps))
111
	entryOff := uint32(0)
112

113
	// register go wrappers
114
	for i := range stubs {
115
		for j := range natives {
116
			if stubs[i].CName != natives[j].Name {
117
				continue
118
			}
119
			
120
			// calculate corresponding C entry
121
			pc := uintptr(native_entry + uintptr(natives[j].EntryOff))
122
			if stubs[i].CEntry != nil {
123
				*stubs[i].CEntry = pc
124
			}
125

126
			// no need to generate wrapper, continue next
127
			if stubs[i].GoFunc == nil {
128
				continue
129
			}
130

131
			// assemble wrapper codes
132
			layout := abi.NewFunctionLayout(reflect.TypeOf(stubs[i].GoFunc).Elem())
133
			frame := abi.NewFrame(&layout, _C_Redzone, true) 
134
			tcode := abi.CallC(pc, frame, natives[j].MaxStack)
135
			code = append(code, tcode...)
136
			size := uint32(len(tcode))
137
		
138
			fn := Func{
139
				Flag: FuncFlag_ASM,
140
				ArgsSize: int32(layout.ArgSize()),
141
				EntryOff: entryOff,
142
				TextSize: size,
143
				Name: stubs[i].CName + "_go",
144
			}
145

146
			// add check-stack and grow-stack texts' pcsp
147
			fn.Pcsp = &Pcdata{
148
				{PC: uint32(frame.StackCheckTextSize()), Val: 0},
149
				{PC: size - uint32(frame.GrowStackTextSize()), Val: int32(frame.Size())},
150
				{PC: size, Val: 0},
151
			}
152
			// NOTICE: always refer to first file
153
			fn.Pcfile = &Pcdata{
154
				{PC: size, Val: 0},
155
			}
156
			// NOTICE: always refer to first line
157
			fn.Pcline = &Pcdata{
158
				{PC: size, Val: 1},
159
			}
160
			// NOTICE: always forbid async preempt
161
			fn.PcUnsafePoint = &Pcdata{
162
				{PC: size, Val: PCDATA_UnsafePointUnsafe},
163
			}
164

165
			// register pointer stackmaps
166
			fn.PcStackMapIndex = &Pcdata{
167
				{PC: size, Val: 0},
168
			}
169
			fn.ArgsPointerMaps = frame.ArgPtrs()
170
			fn.LocalsPointerMaps = frame.LocalPtrs()
171

172
			entryOff += size
173
			wraps = append(wraps, fn)
174
			wrapIds = append(wrapIds, i)
175
		}
176
	}
177
	gofuncs := Load(code, wraps, modulename+"/go", []string{filename+".go"})
178

179
	// set go func value 
180
	for i := range gofuncs {
181
		idx := wrapIds[i]
182
		w := rt.UnpackEface(stubs[idx].GoFunc)
183
		*(*Function)(w.Value) = gofuncs[i]
184
	}
185
}
186

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.