github.com/pkujhd/goloader@v0.0.0-20240411034752-1a28096bd7bd/module.go (about)

     1  package goloader
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  //go:linkname firstmoduledata runtime.firstmoduledata
     8  var firstmoduledata moduledata
     9  
    10  // findfunctab is an array of these structures.
    11  // Each bucket represents 4096 bytes of the text segment.
    12  // Each subbucket represents 256 bytes of the text segment.
    13  // To find a function given a pc, locate the bucket and subbucket for
    14  // that pc. Add together the idx and subbucket value to obtain a
    15  // function index. Then scan the functab array starting at that
    16  // index to find the target function.
    17  // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead.
    18  type findfuncbucket struct {
    19  	idx        uint32
    20  	subbuckets [16]byte
    21  }
    22  
    23  // Mapping information for secondary text sections
    24  type textsect struct {
    25  	vaddr    uintptr // prelinked section vaddr
    26  	length   uintptr // section length
    27  	baseaddr uintptr // relocated section address
    28  }
    29  
    30  type nameOff int32
    31  type typeOff int32
    32  type textOff int32
    33  
    34  // A ptabEntry is generated by the compiler for each exported function
    35  // and global variable in the main package of a plugin. It is used to
    36  // initialize the plugin module's symbol map.
    37  type ptabEntry struct {
    38  	name nameOff
    39  	typ  typeOff
    40  }
    41  
    42  type modulehash struct {
    43  	modulename   string
    44  	linktimehash string
    45  	runtimehash  *string
    46  }
    47  
    48  type bitvector struct {
    49  	n        int32 // # of bits
    50  	bytedata *uint8
    51  }
    52  
    53  type stackmap struct {
    54  	n        int32   // number of bitmaps
    55  	nbit     int32   // number of bits in each bitmap
    56  	bytedata [1]byte // bitmaps, each starting on a byte boundary
    57  }
    58  
    59  type funcInfo struct {
    60  	*_func
    61  	datap *moduledata
    62  }
    63  
    64  const minfunc = 16                 // minimum function size
    65  const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table
    66  const nsub = len(findfuncbucket{}.subbuckets)
    67  
    68  //go:linkname step runtime.step
    69  func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool)
    70  
    71  //go:linkname findfunc runtime.findfunc
    72  func findfunc(pc uintptr) funcInfo
    73  
    74  //go:linkname funcdata runtime.funcdata
    75  func funcdata(f funcInfo, i int32) unsafe.Pointer
    76  
    77  //go:linkname funcname runtime.funcname
    78  func funcname(f funcInfo) string
    79  
    80  //go:linkname gostringnocopy runtime.gostringnocopy
    81  func gostringnocopy(str *byte) string
    82  
    83  //go:linkname moduledataverify1 runtime.moduledataverify1
    84  func moduledataverify1(datap *moduledata)
    85  
    86  //go:linkname modulesinit runtime.modulesinit
    87  func modulesinit()
    88  
    89  //go:linkname progToPointerMask runtime.progToPointerMask
    90  func progToPointerMask(prog *byte, size uintptr) bitvector
    91  
    92  func addModule(module *moduledata) {
    93  	modules[module] = true
    94  	for datap := &firstmoduledata; ; {
    95  		if datap.next == nil {
    96  			datap.next = module
    97  			break
    98  		}
    99  		datap = datap.next
   100  	}
   101  }
   102  func removeModule(module interface{}) {
   103  	prevp := &firstmoduledata
   104  	for datap := &firstmoduledata; datap != nil; {
   105  		if datap == module {
   106  			prevp.next = datap.next
   107  			break
   108  		}
   109  		prevp = datap
   110  		datap = datap.next
   111  	}
   112  	delete(modules, module)
   113  }