forked from pkujhd/goloader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtype.go
147 lines (123 loc) · 3.35 KB
/
type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package goloader
import (
"reflect"
"runtime"
"strings"
"unsafe"
)
type tflag uint8
// Method on non-interface type
type method struct {
name nameOff // name of method
mtyp typeOff // method type (without receiver)
ifn textOff // fn used in interface call (one-word receiver)
tfn textOff // fn used for normal method call
}
type imethod struct {
name nameOff
ityp typeOff
}
type interfacetype struct {
typ _type
pkgpath name
mhdr []imethod
}
type name struct {
bytes *byte
}
//go:linkname (*_type).uncommon runtime.(*_type).uncommon
func (t *_type) uncommon() *uncommonType
//go:linkname (*_type).nameOff runtime.(*_type).nameOff
func (t *_type) nameOff(off nameOff) name
//go:linkname (*_type).typeOff runtime.(*_type).typeOff
func (t *_type) typeOff(off typeOff) *_type
//go:linkname name.name runtime.name.name
func (n name) name() (s string)
//go:linkname getitab runtime.getitab
func getitab(inter *interfacetype, typ *_type, canfail bool) int
func (t *_type) PkgPath() string {
ut := t.uncommon()
if ut == nil {
return ""
}
return t.nameOff(ut.pkgPath).name()
}
func (t *_type) Name() string {
return t.nameOff(t.str).name()
}
func (t *_type) Type() reflect.Type {
var obj interface{} = reflect.TypeOf(0)
(*interfaceHeader)(unsafe.Pointer(&obj)).word = unsafe.Pointer(t)
typ := obj.(reflect.Type)
return typ
}
func GetFunctionName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
func RegTypes(symPtr map[string]uintptr, interfaces ...interface{}) {
for _, ins := range interfaces {
v := reflect.ValueOf(ins)
regTypeInfo(symPtr, v)
if v.Kind() == reflect.Ptr {
v = v.Elem()
regTypeInfo(symPtr, v)
}
}
}
func regTypeInfo(symPtr map[string]uintptr, v reflect.Value) {
ins := v.Interface()
header := (*interfaceHeader)(unsafe.Pointer(&ins))
var ptr uintptr
var typePrefix string
var symName string
pptr := (uintptr)(header.word)
if v.Kind() == reflect.Func && pptr != 0 {
ptr = *(*uintptr)(header.word)
symName = GetFunctionName(ins)
} else {
ptr = uintptr(header.typ)
typePrefix = "type."
symName = v.Type().String()
}
if symName[0] == '*' {
typePrefix += "*"
symName = symName[1:]
}
pkgPath := (*_type)(header.typ).PkgPath()
var symFullName string
lastSlash := strings.LastIndexByte(pkgPath, '/')
if lastSlash > -1 {
symFullName = typePrefix + pkgPath[:lastSlash] + "/" + symName
} else {
symFullName = typePrefix + symName
}
symPtr[symFullName] = ptr
}
func addIFaceSubFuncType(funcTypeMap map[string]*int, typemap map[typeOff]uintptr,
inter *interfacetype, typ *_type, dataBase int) {
pkgPath := inter.typ.PkgPath()
lastSlash := strings.LastIndexByte(pkgPath, '/')
var head = pkgPath
if lastSlash > -1 {
head = pkgPath[lastSlash+1:]
}
ni := len(inter.mhdr)
x := typ.uncommon()
xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:ni]
for k := 0; k < ni; k++ {
i := &inter.mhdr[k]
itype := inter.typ.typeOff(i.ityp)
name := itype.Name()
if name[0] == '*' {
name = name[1:]
}
name = strings.Replace(name, head+".", pkgPath+".", -1)
name = "type." + name
if symAddrPtr, ok := funcTypeMap[name]; ok {
itypePtr := int(uintptr(unsafe.Pointer(itype)))
*symAddrPtr = itypePtr
typemap[typeOff(itypePtr-dataBase)] = uintptr(itypePtr)
}
xmhdr[k].mtyp = typeOff((uintptr)((unsafe.Pointer)(itype)) - (uintptr)(dataBase))
}
}