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