github.com/dearplain/goloader@v0.0.0-20190107071432-2b1e47d74273/register.go (about)

     1  package goloader
     2  
     3  import (
     4  	"cmd/objfile/objfile"
     5  	"encoding/binary"
     6  	"os"
     7  	"reflect"
     8  	"strings"
     9  	"unsafe"
    10  )
    11  
    12  const (
    13  	TLSNAME        = "(TLS)"
    14  	R_CALLIND_NAME = "R_CALLIND"
    15  )
    16  
    17  type interfaceHeader struct {
    18  	typ  uintptr
    19  	word unsafe.Pointer
    20  }
    21  
    22  type stringHeader struct {
    23  	Data uintptr
    24  	Len  int
    25  }
    26  
    27  type sliceHeader struct {
    28  	Data uintptr
    29  	Len  int
    30  	Cap  int
    31  }
    32  
    33  //go:linkname block runtime.block
    34  func block()
    35  
    36  // RegSymbol register common types for relocation
    37  func RegSymbol(symPtr map[string]uintptr) {
    38  
    39  	var int0 = int(0)
    40  	RegTypes(symPtr, int(0), int8(0), int16(0), int32(0), int64(0),
    41  		uint(0), uint8(0), uint16(0), uint32(0), uint64(0), true, &int0,
    42  		float32(0), float64(0), complex64(0), complex128(0),
    43  		"", []byte{}, []uint{}, []int{}, uintptr(0), make(chan bool, 1), unsafe.Pointer(&symPtr))
    44  	RegFunc(symPtr, "runtime.block", block)
    45  
    46  	ex, err := os.Executable()
    47  	mustOK(err)
    48  	f, err := objfile.Open(ex)
    49  	mustOK(err)
    50  	defer f.Close()
    51  
    52  	syms, err := f.Symbols()
    53  	for _, sym := range syms {
    54  		if sym.Code == 'T' && !strings.HasPrefix(sym.Name, "type..") {
    55  			symPtr[sym.Name] = uintptr(sym.Addr)
    56  		} else if strings.HasPrefix(sym.Name, "runtime.") {
    57  			symPtr[sym.Name] = uintptr(sym.Addr)
    58  		}
    59  		if strings.HasPrefix(sym.Name, "go.itab") {
    60  			RegItab(symPtr, sym.Name, uintptr(sym.Addr))
    61  		}
    62  	}
    63  }
    64  
    65  func RegItab(symPtr map[string]uintptr, name string, addr uintptr) {
    66  	symPtr[name] = uintptr(addr)
    67  	bs := strings.TrimLeft(name, "go.itab.")
    68  	bss := strings.Split(bs, ",")
    69  	ptrs := *(*[2]uintptr)(unsafe.Pointer(addr))
    70  	for i, ptr := range ptrs {
    71  		typeName := bss[len(bss)-i-1]
    72  		if typeName[0] == '*' {
    73  			var obj interface{} = reflect.TypeOf(0)
    74  			(*interfaceHeader)(unsafe.Pointer(&obj)).word = unsafe.Pointer(ptr)
    75  			typ := obj.(reflect.Type).Elem()
    76  			obj = typ
    77  			typePtr := uintptr((*interfaceHeader)(unsafe.Pointer(&obj)).word)
    78  			symPtr["type."+typeName[1:]] = typePtr
    79  		}
    80  		symPtr["type."+typeName] = ptr
    81  	}
    82  }
    83  
    84  func RegTLS(symPtr map[string]uintptr, offset int) {
    85  	var ptr interface{} = RegSymbol
    86  	var ptr2 = *(*uintptr)((*interfaceHeader)(unsafe.Pointer(&ptr)).word)
    87  	var ptr3 = (*[36]byte)(unsafe.Pointer(ptr2))
    88  	var tlsValue = uintptr(binary.LittleEndian.Uint32(ptr3[offset:]))
    89  	symPtr[TLSNAME] = tlsValue
    90  }
    91  
    92  func RegType(symPtr map[string]uintptr, name string, typ interface{}) {
    93  	aHeader := (*interfaceHeader)(unsafe.Pointer(&typ))
    94  	symPtr[name] = aHeader.typ
    95  }
    96  
    97  func RegFunc(symPtr map[string]uintptr, name string, f interface{}) {
    98  	var ptr = *(*uintptr)((*interfaceHeader)(unsafe.Pointer(&f)).word)
    99  	symPtr[name] = ptr
   100  }
   101  
   102  func getFuncPtr(f interface{}) uintptr {
   103  	return *(*uintptr)((*interfaceHeader)(unsafe.Pointer(&f)).word)
   104  }