github.com/dearplain/goloader@v0.0.0-20190107071432-2b1e47d74273/type.go (about) 1 package goloader 2 3 import ( 4 "reflect" 5 "runtime" 6 "strings" 7 "unsafe" 8 ) 9 10 type tflag uint8 11 12 type _type struct { 13 size uintptr 14 ptrdata uintptr // size of memory prefix holding all pointers 15 hash uint32 16 tflag tflag 17 align uint8 18 fieldalign uint8 19 kind uint8 20 alg *typeAlg 21 // gcdata stores the GC type data for the garbage collector. 22 // If the KindGCProg bit is set in kind, gcdata is a GC program. 23 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. 24 gcdata *byte 25 str nameOff 26 ptrToThis typeOff 27 } 28 29 type typeAlg struct { 30 // function for hashing objects of this type 31 // (ptr to object, seed) -> hash 32 hash func(unsafe.Pointer, uintptr) uintptr 33 // function for comparing objects of this type 34 // (ptr to object A, ptr to object B) -> ==? 35 equal func(unsafe.Pointer, unsafe.Pointer) bool 36 } 37 38 type imethod struct { 39 name nameOff 40 ityp typeOff 41 } 42 43 type interfacetype struct { 44 typ _type 45 pkgpath name 46 mhdr []imethod 47 } 48 49 type uncommonType struct { 50 pkgPath nameOff // import path; empty for built-in types like int, string 51 mcount uint16 // number of methods 52 _ uint16 // unused 53 moff uint32 // offset from this uncommontype to [mcount]method 54 _ uint32 // unused 55 } 56 57 type name struct { 58 bytes *byte 59 } 60 61 //go:linkname (*_type).uncommon runtime.(*_type).uncommon 62 func (t *_type) uncommon() *uncommonType 63 64 //go:linkname (*_type).nameOff runtime.(*_type).nameOff 65 func (t *_type) nameOff(off nameOff) name 66 67 //go:linkname (*_type).typeOff runtime.(*_type).typeOff 68 func (t *_type) typeOff(off typeOff) *_type 69 70 //go:linkname name.name runtime.name.name 71 func (n name) name() (s string) 72 73 func (t *_type) PkgPath() string { 74 ut := t.uncommon() 75 if ut == nil { 76 return "" 77 } 78 return t.nameOff(ut.pkgPath).name() 79 } 80 81 func (t *_type) Name() string { 82 return t.nameOff(t.str).name() 83 } 84 85 func (t *_type) Type() reflect.Type { 86 var obj interface{} = reflect.TypeOf(0) 87 (*interfaceHeader)(unsafe.Pointer(&obj)).word = unsafe.Pointer(t) 88 typ := obj.(reflect.Type) 89 return typ 90 } 91 92 func ToType(typ reflect.Type) *_type { 93 var obj interface{} = typ 94 typePtr := uintptr((*interfaceHeader)(unsafe.Pointer(&obj)).word) 95 return (*_type)(unsafe.Pointer(typePtr)) 96 } 97 98 func GetFunctionName(i interface{}) string { 99 return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() 100 } 101 102 func RegTypes(symPtr map[string]uintptr, interfaces ...interface{}) { 103 for _, ins := range interfaces { 104 v := reflect.ValueOf(ins) 105 regTypeInfo(symPtr, v) 106 if v.Kind() == reflect.Ptr { 107 v = v.Elem() 108 regTypeInfo(symPtr, v) 109 } 110 } 111 } 112 113 func regTypeInfo(symPtr map[string]uintptr, v reflect.Value) { 114 ins := v.Interface() 115 header := (*interfaceHeader)(unsafe.Pointer(&ins)) 116 117 var ptr uintptr 118 var typePrefix string 119 var symName string 120 pptr := (uintptr)(header.word) 121 if v.Kind() == reflect.Func && pptr != 0 { 122 ptr = *(*uintptr)(header.word) 123 symName = GetFunctionName(ins) 124 } else { 125 ptr = uintptr(header.typ) 126 typePrefix = "type." 127 symName = v.Type().String() 128 } 129 130 if symName[0] == '*' { 131 typePrefix += "*" 132 symName = symName[1:] 133 } 134 135 pkgPath := (*_type)(unsafe.Pointer(header.typ)).PkgPath() 136 137 var symFullName string 138 lastSlash := strings.LastIndexByte(pkgPath, '/') 139 if lastSlash > -1 { 140 symFullName = typePrefix + pkgPath[:lastSlash] + "/" + symName 141 } else { 142 symFullName = typePrefix + symName 143 } 144 symPtr[symFullName] = ptr 145 // fmt.Println(symFullName, v.Kind()) 146 } 147 148 //go:linkname getitab runtime.getitab 149 func getitab(inter int, typ int, canfail bool) int 150 151 func addIFaceSubFuncType(funcTypeMap map[string]*int, typemap map[typeOff]uintptr, 152 inter *interfacetype, dataBase int) { 153 pkgPath := inter.typ.PkgPath() 154 lastSlash := strings.LastIndexByte(pkgPath, '/') 155 var head = pkgPath 156 if lastSlash > -1 { 157 head = pkgPath[lastSlash+1:] 158 } 159 ni := len(inter.mhdr) 160 for k := 0; k < ni; k++ { 161 i := &inter.mhdr[k] 162 itype := inter.typ.typeOff(i.ityp) 163 name := itype.Name() 164 if name[0] == '*' { 165 name = name[1:] 166 } 167 name = strings.Replace(name, head+".", pkgPath+".", -1) 168 name = "type." + name 169 if symAddrPtr, ok := funcTypeMap[name]; ok { 170 itypePtr := int(uintptr(unsafe.Pointer(itype))) 171 *symAddrPtr = itypePtr 172 // fmt.Println(*symAddrPtr) 173 typemap[typeOff(itypePtr-dataBase)] = uintptr(itypePtr) 174 // fmt.Println(name, itypePtr-dataBase, itypePtr) 175 } 176 } 177 }