github.com/pkujhd/goloader@v0.0.0-20240411034752-1a28096bd7bd/type.go (about) 1 package goloader 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 "unsafe" 8 9 "github.com/pkujhd/goloader/obj" 10 ) 11 12 type tflag uint8 13 14 const ( 15 tflagUncommon tflag = 1 << 0 16 tflagExtraStar tflag = 1 << 1 17 tflagNamed tflag = 1 << 2 18 tflagRegularMemory tflag = 1 << 3 // equal and hash can treat values of this type as a single region of t.size bytes 19 ) 20 21 // See reflect/value.go emptyInterface 22 type emptyInterface struct { 23 typ *_type 24 word unsafe.Pointer 25 } 26 27 // See reflect/value.go sliceHeader 28 type sliceHeader struct { 29 Data uintptr 30 Len int 31 Cap int 32 } 33 34 // See reflect/value.go stringHeader 35 type stringHeader struct { 36 Data uintptr 37 Len int 38 } 39 40 // Method on non-interface type 41 type method struct { 42 name nameOff // name of method 43 mtyp typeOff // method type (without receiver) 44 ifn textOff // fn used in interface call (one-word receiver) 45 tfn textOff // fn used for normal method call 46 } 47 48 type imethod struct { 49 name nameOff 50 ityp typeOff 51 } 52 53 type interfacetype struct { 54 typ _type 55 pkgpath name 56 mhdr []imethod 57 } 58 59 type name struct { 60 bytes *byte 61 } 62 63 type funcType struct { 64 _type 65 inCount uint16 66 outCount uint16 // top bit is set if last input parameter is ... 67 } 68 69 type uncommonType struct { 70 pkgPath nameOff // import path; empty for built-in types like int, string 71 mcount uint16 // number of methods 72 xcount uint16 // number of exported methods 73 moff uint32 // offset from this uncommontype to [mcount]method 74 _ uint32 // unused 75 } 76 77 //go:linkname _Kind reflect.(*rtype).Kind 78 func _Kind(t *_type) reflect.Kind 79 80 //go:linkname _NumField reflect.(*rtype).NumField 81 func _NumField(t *_type) int 82 83 //go:linkname _Field reflect.(*rtype).Field 84 func _Field(t *_type, i int) reflect.StructField 85 86 //go:linkname _NumIn reflect.(*rtype).NumIn 87 func _NumIn(t *_type) int 88 89 //go:linkname _In reflect.(*rtype).In 90 func _In(t *_type, i int) reflect.Type 91 92 //go:linkname _NumOut reflect.(*rtype).NumOut 93 func _NumOut(t *_type) int 94 95 //go:linkname _Out reflect.(*rtype).Out 96 func _Out(t *_type, i int) reflect.Type 97 98 //go:linkname _Key reflect.(*rtype).Key 99 func _Key(t *_type) reflect.Type 100 101 //go:linkname _Elem reflect.(*rtype).Elem 102 func _Elem(t *_type) reflect.Type 103 104 //go:linkname _NumMethod reflect.(*rtype).NumMethod 105 func _NumMethod(t *_type) int 106 107 //go:linkname _Method reflect.(*rtype).Method 108 func _Method(t *_type, i int) reflect.Method 109 110 //go:linkname _ChanDir reflect.(*rtype).ChanDir 111 func _ChanDir(t *_type) reflect.ChanDir 112 113 //go:linkname _Len reflect.(*rtype).Len 114 func _Len(t *_type) int 115 116 //go:linkname _IsVariadic reflect.(*rtype).IsVariadic 117 func _IsVariadic(t *_type) bool 118 119 //go:linkname _Name reflect.(*rtype).Name 120 func _Name(t *_type) string 121 122 //go:linkname _String reflect.(*rtype).String 123 func _String(t *_type) string 124 125 //go:linkname _PkgPath reflect.(*rtype).PkgPath 126 func _PkgPath(t *_type) string 127 128 //go:linkname typelinksinit runtime.typelinksinit 129 func typelinksinit() 130 131 func (t *_type) Kind() reflect.Kind { return _Kind(t) } 132 func (t *_type) NumField() int { return _NumField(t) } 133 func (t *_type) Field(i int) reflect.StructField { return _Field(t, i) } 134 func (t *_type) NumIn() int { return _NumIn(t) } 135 func (t *_type) In(i int) reflect.Type { return _In(t, i) } 136 func (t *_type) NumOut() int { return _NumOut(t) } 137 func (t *_type) Out(i int) reflect.Type { return _Out(t, i) } 138 func (t *_type) Key() reflect.Type { return _Key(t) } 139 func (t *_type) Elem() reflect.Type { return _Elem(t) } 140 func (t *_type) NumMethod() int { return _NumMethod(t) } 141 func (t *_type) Method(i int) reflect.Method { return _Method(t, i) } 142 func (t *_type) ChanDir() reflect.ChanDir { return _ChanDir(t) } 143 func (t *_type) Len() int { return _Len(t) } 144 func (t *_type) IsVariadic() bool { return _IsVariadic(t) } 145 func (t *_type) Name() string { return _Name(t) } 146 func (t *_type) String() string { return _String(t) } 147 func (t *_type) PkgPath() string { return _PkgPath(t) } 148 149 func rtypeOf(i reflect.Type) *_type { 150 eface := (*emptyInterface)(unsafe.Pointer(&i)) 151 return (*_type)(eface.word) 152 } 153 154 func resolveTypeName(typ *_type) string { 155 pkgPath := obj.PathToPrefix(typ.PkgPath()) 156 name := typ.Name() 157 if pkgPath != EmptyString && name != EmptyString { 158 return pkgPath + "." + name 159 } 160 if name != EmptyString && typ.Kind() != reflect.UnsafePointer { 161 return name 162 } 163 //golang <= 1.16 map.bucket has a self-contained struct field 164 if strings.HasPrefix(typ.String(), "map.bucket[") { 165 return typ.String() 166 } 167 switch typ.Kind() { 168 case reflect.Ptr: 169 name := "*" + resolveTypeName(rtypeOf(typ.Elem())) 170 return name 171 case reflect.Struct: 172 if typ.NumField() == 0 { 173 return typ.String() 174 } 175 fields := make([]string, typ.NumField()) 176 for i := 0; i < typ.NumField(); i++ { 177 fieldName := EmptyString 178 if !typ.Field(i).Anonymous { 179 if typ.Field(i).PkgPath != EmptyString { 180 fieldName = obj.PathToPrefix(typ.Field(i).PkgPath) + "." 181 } 182 fieldName = fieldName + typ.Field(i).Name + " " 183 } 184 fields[i] = fieldName + resolveTypeName(rtypeOf(typ.Field(i).Type)) 185 if typ.Field(i).Tag != EmptyString { 186 fields[i] = fields[i] + fmt.Sprintf(" %q", string(typ.Field(i).Tag)) 187 } 188 } 189 return fmt.Sprintf("struct { %s }", strings.Join(fields, "; ")) 190 case reflect.Map: 191 return fmt.Sprintf("map[%s]%s", resolveTypeName(rtypeOf(typ.Key())), resolveTypeName(rtypeOf(typ.Elem()))) 192 case reflect.Chan: 193 return fmt.Sprintf("%s %s", typ.ChanDir().String(), resolveTypeName(rtypeOf(typ.Elem()))) 194 case reflect.Slice: 195 return fmt.Sprintf("[]%s", resolveTypeName(rtypeOf(typ.Elem()))) 196 case reflect.Array: 197 return fmt.Sprintf("[%d]%s", typ.Len(), resolveTypeName(rtypeOf(typ.Elem()))) 198 case reflect.Func: 199 ins := make([]string, typ.NumIn()) 200 outs := make([]string, typ.NumOut()) 201 for i := 0; i < typ.NumIn(); i++ { 202 if i == typ.NumIn()-1 && typ.IsVariadic() { 203 ins[i] = "..." + resolveTypeName(rtypeOf(typ.In(i).Elem())) 204 } else { 205 ins[i] = resolveTypeName(rtypeOf(typ.In(i))) 206 } 207 } 208 for i := 0; i < typ.NumOut(); i++ { 209 outs[i] = resolveTypeName(rtypeOf(typ.Out(i))) 210 } 211 name := "func(" + strings.Join(ins, ", ") + ")" 212 if len(outs) > 0 { 213 name += " " 214 } 215 outName := strings.Join(outs, ", ") 216 if len(outs) > 1 { 217 outName = "(" + outName + ")" 218 } 219 return name + outName 220 case reflect.Interface: 221 if typ.NumMethod() == 0 { 222 return typ.String() 223 } 224 methods := make([]string, typ.NumMethod()) 225 for i := 0; i < typ.NumMethod(); i++ { 226 method := typ.Method(i) 227 methods[i] = method.Name + strings.TrimPrefix(resolveTypeName(rtypeOf(method.Type)), "func") 228 } 229 return fmt.Sprintf("interface { %s }", strings.Join(methods, "; ")) 230 case reflect.Bool, 231 reflect.Int, reflect.Uint, 232 reflect.Int64, reflect.Uint64, 233 reflect.Int32, reflect.Uint32, 234 reflect.Int16, reflect.Uint16, 235 reflect.Int8, reflect.Uint8, 236 reflect.Float64, reflect.Float32, 237 reflect.Complex64, reflect.Complex128, 238 reflect.String, reflect.UnsafePointer, 239 reflect.Uintptr: 240 return typ.String() 241 default: 242 panic("unexpected builtin type: " + typ.String()) 243 } 244 } 245 246 func RegTypes(symPtr map[string]uintptr, interfaces ...interface{}) { 247 for _, inter := range interfaces { 248 header := (*emptyInterface)(unsafe.Pointer(&inter)) 249 registerType(header.typ, symPtr) 250 } 251 }