podman

Форк
0
245 строк · 7.0 Кб
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
    `encoding`
21
    `encoding/binary`
22
    `fmt`
23
    `reflect`
24
    `strings`
25
    `sync`
26
    `unsafe`
27
)
28

29
const (
30
    _MinLC uint8 = 1
31
    _PtrSize uint8 = 8
32
)
33

34
const (
35
    _N_FUNCDATA = 8
36
    _INVALID_FUNCDATA_OFFSET = ^uint32(0)
37
    _FUNC_SIZE = unsafe.Sizeof(_func{})
38
    
39
    _MINFUNC = 16 // minimum size for a function
40
    _BUCKETSIZE    = 256 * _MINFUNC
41
    _SUBBUCKETS    = 16
42
    _SUB_BUCKETSIZE = _BUCKETSIZE / _SUBBUCKETS
43
)
44

45
// Note: This list must match the list in runtime/symtab.go.
46
const (
47
	FuncFlag_TOPFRAME = 1 << iota
48
	FuncFlag_SPWRITE
49
	FuncFlag_ASM
50
)
51

52
// PCDATA and FUNCDATA table indexes.
53
//
54
// See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go.
55
const (
56
    _FUNCDATA_ArgsPointerMaps    = 0
57
    _FUNCDATA_LocalsPointerMaps  = 1
58
    _FUNCDATA_StackObjects       = 2
59
    _FUNCDATA_InlTree            = 3
60
    _FUNCDATA_OpenCodedDeferInfo = 4
61
    _FUNCDATA_ArgInfo            = 5
62
    _FUNCDATA_ArgLiveInfo        = 6
63
    _FUNCDATA_WrapInfo           = 7
64

65
    // ArgsSizeUnknown is set in Func.argsize to mark all functions
66
    // whose argument size is unknown (C vararg functions, and
67
    // assembly code without an explicit specification).
68
    // This value is generated by the compiler, assembler, or linker.
69
    ArgsSizeUnknown = -0x80000000
70
)
71

72
// moduledata used to cache the funcdata and findfuncbucket of one module
73
var moduleCache = struct {
74
    m map[*moduledata][]byte
75
    sync.Mutex
76
}{
77
    m: make(map[*moduledata][]byte),
78
}
79

80
// Func contains information about a function.
81
type Func struct {
82
    ID          uint8  // see runtime/symtab.go
83
    Flag        uint8  // see runtime/symtab.go
84
    ArgsSize    int32  // args byte size
85
    EntryOff    uint32 // start pc, offset to moduledata.text
86
    TextSize    uint32 // size of func text
87
    DeferReturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
88
    FileIndex   uint32 // index into filetab 
89
    Name        string // name of function
90

91
    // PC data
92
    Pcsp            *Pcdata // PC -> SP delta
93
    Pcfile          *Pcdata // PC -> file index
94
    Pcline          *Pcdata // PC -> line number
95
    PcUnsafePoint   *Pcdata // PC -> unsafe point, must be PCDATA_UnsafePointSafe or PCDATA_UnsafePointUnsafe
96
    PcStackMapIndex *Pcdata // PC -> stack map index, relative to ArgsPointerMaps and LocalsPointerMaps
97
    PcInlTreeIndex  *Pcdata // PC -> inlining tree index, relative to InlTree
98
    PcArgLiveIndex  *Pcdata // PC -> arg live index, relative to ArgLiveInfo
99
    
100
    // Func data, must implement encoding.BinaryMarshaler
101
    ArgsPointerMaps    encoding.BinaryMarshaler // concrete type: *StackMap
102
    LocalsPointerMaps  encoding.BinaryMarshaler // concrete type: *StackMap
103
    StackObjects       encoding.BinaryMarshaler
104
    InlTree            encoding.BinaryMarshaler
105
    OpenCodedDeferInfo encoding.BinaryMarshaler
106
    ArgInfo            encoding.BinaryMarshaler
107
    ArgLiveInfo        encoding.BinaryMarshaler
108
    WrapInfo           encoding.BinaryMarshaler
109
}
110

111
func getOffsetOf(data interface{}, field string) uintptr {
112
    t := reflect.TypeOf(data)
113
    fv, ok := t.FieldByName(field)
114
    if !ok {
115
        panic(fmt.Sprintf("field %s not found in struct %s", field, t.Name()))
116
    }
117
    return fv.Offset
118
}
119

120
func rnd(v int64, r int64) int64 {
121
    if r <= 0 {
122
        return v
123
    }
124
    v += r - 1
125
    c := v % r
126
    if c < 0 {
127
        c += r
128
    }
129
    v -= c
130
    return v
131
}
132

133
var (
134
    byteOrder binary.ByteOrder = binary.LittleEndian
135
)
136

137
func funcNameParts(name string) (string, string, string) {
138
    i := strings.IndexByte(name, '[')
139
    if i < 0 {
140
        return name, "", ""
141
    }
142
    // TODO: use LastIndexByte once the bootstrap compiler is >= Go 1.5.
143
    j := len(name) - 1
144
    for j > i && name[j] != ']' {
145
        j--
146
    }
147
    if j <= i {
148
        return name, "", ""
149
    }
150
    return name[:i], "[...]", name[j+1:]
151
}
152

153

154
// func name table format: 
155
//   nameOff[0] -> namePartA namePartB namePartC \x00 
156
//   nameOff[1] -> namePartA namePartB namePartC \x00
157
//  ...
158
func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) {
159
    offs = make([]int32, len(funcs))
160
    offset := 1
161
    tab = []byte{0}
162

163
    for i, f := range funcs {
164
        offs[i] = int32(offset)
165

166
        a, b, c := funcNameParts(f.Name)
167
        tab = append(tab, a...)
168
        tab = append(tab, b...)
169
        tab = append(tab, c...)
170
        tab = append(tab, 0)
171
        offset += len(a) + len(b) + len(c) + 1
172
    }
173

174
    return
175
}
176

177
// CU table format:
178
//  cuOffsets[0] -> filetabOffset[0] filetabOffset[1] ... filetabOffset[len(CUs[0].fileNames)-1]
179
//  cuOffsets[1] -> filetabOffset[len(CUs[0].fileNames)] ... filetabOffset[len(CUs[0].fileNames) + len(CUs[1].fileNames)-1]
180
//  ...
181
//
182
// file name table format:
183
//  filetabOffset[0] -> CUs[0].fileNames[0] \x00
184
//  ...
185
//  filetabOffset[len(CUs[0]-1)] -> CUs[0].fileNames[len(CUs[0].fileNames)-1] \x00
186
//  ...
187
//  filetabOffset[SUM(CUs,fileNames)-1] -> CUs[len(CU)-1].fileNames[len(CUs[len(CU)-1].fileNames)-1] \x00
188
func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) {
189
    cuOffsets = make([]uint32, len(cus))
190
    cuOffset := 0
191
    fileOffset := 0
192

193
    for i, cu := range cus {
194
        cuOffsets[i] = uint32(cuOffset)
195

196
        for _, name := range cu.fileNames {
197
            cutab = append(cutab, uint32(fileOffset))
198

199
            fileOffset += len(name) + 1
200
            filetab = append(filetab, name...)
201
            filetab = append(filetab, 0)
202
        }
203

204
        cuOffset += len(cu.fileNames)
205
    }
206

207
    return
208
}
209

210
func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) {
211
    fstart = len(*out)
212
    *out = append(*out, byte(0))
213
    offs := uint32(1)
214

215
    funcdataOffs = make([][]uint32, len(funcs))
216
    for i, f := range funcs {
217

218
        var writer = func(fd encoding.BinaryMarshaler) {
219
            var ab []byte
220
            var err error
221
            if fd != nil {
222
                ab, err = fd.MarshalBinary()
223
                if err != nil {
224
                    panic(err)
225
                }
226
                funcdataOffs[i] = append(funcdataOffs[i], offs)
227
            } else {
228
                ab = []byte{0}
229
                funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET)
230
            }
231
            *out = append(*out, ab...)
232
            offs += uint32(len(ab))
233
        }
234

235
        writer(f.ArgsPointerMaps)
236
        writer(f.LocalsPointerMaps)
237
        writer(f.StackObjects)
238
        writer(f.InlTree)
239
        writer(f.OpenCodedDeferInfo)
240
        writer(f.ArgInfo)
241
        writer(f.ArgLiveInfo)
242
        writer(f.WrapInfo)
243
    }
244
    return 
245
}
246

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

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

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

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