forked from pkujhd/goloader
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathinit.1.21.go
64 lines (57 loc) · 2.07 KB
/
init.1.21.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//go:build go1.21 && !go1.23
// +build go1.21,!go1.23
package goloader
import (
"cmd/objfile/objabi"
"slices"
"sort"
"strings"
"unsafe"
)
const (
_InitTaskSuffix = "..inittask"
)
func getInitFuncName(packagename string) string {
return objabi.PathToPrefix(packagename) + _InitTaskSuffix
}
// doInit1 is defined in package runtime
//
//go:linkname doInit1 runtime.doInit1
func doInit1(t unsafe.Pointer) // t should be a *runtime.initTask
type initTask struct {
state uint32 // 0 = uninitialized, 1 = in progress, 2 = done
nfns uint32
// followed by nfns pcs, uintptr sized, one per init function to run
}
func (linker *Linker) doInitialize(codeModule *CodeModule, symbolMap map[string]uintptr) error {
// Autolib order is not necessarily the same as the (*Link).inittaskSym algorithm in cmd/link/internal/ld/inittask.go,
// but it works and avoids a Kahn's graph traversal of R_INITORDER relocs...
autolibOrder := linker.Autolib()
for i := range autolibOrder {
// ..inittask symbol names will have their package escaped, so autolib list needs to as well
autolibOrder[i] = objabi.PathToPrefix(autolibOrder[i])
}
sort.Slice(linker.initFuncs, func(i, j int) bool {
return slices.Index(autolibOrder, strings.TrimSuffix(linker.initFuncs[i], _InitTaskSuffix)) < slices.Index(autolibOrder, strings.TrimSuffix(linker.initFuncs[j], _InitTaskSuffix))
})
for _, name := range linker.initFuncs {
if taskPtr, ok := symbolMap[name]; ok && taskPtr != 0 { // taskPtr may be nil if the inittask wasn't seen in the host symtab (probably a no-op and therefore eliminated)
shouldSkipDedup := false
for _, pkgPath := range linker.options.SkipTypeDeduplicationForPackages {
if strings.HasPrefix(name, pkgPath) {
shouldSkipDedup = true
}
}
x := (*initTask)(unsafe.Pointer(taskPtr))
if shouldSkipDedup {
x.state = 0 // Reset the inittask state in order to rerun the init function for the new version of the package
}
if x.nfns == 0 {
// Linker is expected to have stripped inittasks with no funcs
continue
}
doInit1(adduintptr(taskPtr, 0))
}
}
return nil
}