github.com/pkujhd/goloader@v0.0.0-20240411034752-1a28096bd7bd/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  	"unsafe"
     8  
     9  	"github.com/pkujhd/goloader/obj"
    10  	"github.com/pkujhd/goloader/objabi/reloctype"
    11  )
    12  
    13  type initTask struct {
    14  	state uint32 // 0 = uninitialized, 1 = in progress, 2 = done
    15  	nfns  uint32
    16  	// followed by nfns pcs, uintptr sized, one per init function to run
    17  }
    18  
    19  const (
    20  	_InitTaskSuffix = "..inittask"
    21  )
    22  
    23  func getInitFuncName(packagename string) string {
    24  	return obj.PathToPrefix(packagename) + _InitTaskSuffix
    25  }
    26  
    27  //go:linkname doInit1 runtime.doInit1
    28  func doInit1(t unsafe.Pointer) // t should be a *runtime.initTask
    29  
    30  func (linker *Linker) doInitialize(symPtr, symbolMap map[string]uintptr) error {
    31  	for _, pkg := range linker.Packages {
    32  		name := getInitFuncName(pkg.PkgPath)
    33  		if ptr, ok := symbolMap[name]; ok {
    34  			for _, loc := range linker.SymMap[name].Reloc {
    35  				if loc.Type == reloctype.R_INITORDER {
    36  					if locPtr, ok := symPtr[loc.SymName]; ok {
    37  						doInit1(adduintptr(locPtr, 0))
    38  					} else if locPtr, ok := symbolMap[loc.SymName]; ok {
    39  						doInit1(adduintptr(locPtr, 0))
    40  					}
    41  				}
    42  			}
    43  			task := *(*initTask)(adduintptr(ptr, 0))
    44  			if task.nfns == 0 {
    45  				continue
    46  			}
    47  			doInit1(adduintptr(ptr, 0))
    48  		}
    49  	}
    50  	return nil
    51  }