31
31
pageSize = syscall .Getpagesize ()
32
32
)
33
33
34
+ // Patches a target func to redirect calls to "redirection" func. Both function must have same arguments and return types.
34
35
func PatchMethod (target , redirection interface {}) (* Patch , error ) {
35
36
tValue := getValueFrom (target )
36
37
rValue := getValueFrom (redirection )
@@ -43,6 +44,8 @@ func PatchMethod(target, redirection interface{}) (*Patch, error) {
43
44
}
44
45
return patch , nil
45
46
}
47
+ // Patches an instance func by using two parameters, the target struct type and the method name inside that type,
48
+ //this func will be redirected to the "redirection" func. Note: The first parameter of the redirection func must be the object instance.
46
49
func PatchInstanceMethodByName (target reflect.Type , methodName string , redirection interface {}) (* Patch , error ) {
47
50
method , ok := target .MethodByName (methodName )
48
51
if ! ok && target .Kind () == reflect .Struct {
@@ -54,6 +57,8 @@ func PatchInstanceMethodByName(target reflect.Type, methodName string, redirecti
54
57
}
55
58
return PatchMethodByReflect (method .Func , redirection )
56
59
}
60
+ // Patches a target func by passing the reflect.ValueOf of the func. The target func will be redirected to the "redirection" func.
61
+ // Both function must have same arguments and return types.
57
62
func PatchMethodByReflect (target reflect.Value , redirection interface {}) (* Patch , error ) {
58
63
tValue := & target
59
64
rValue := getValueFrom (redirection )
@@ -66,10 +71,11 @@ func PatchMethodByReflect(target reflect.Value, redirection interface{}) (*Patch
66
71
}
67
72
return patch , nil
68
73
}
74
+ // Patches a target func with a "redirection" function created at runtime by using "reflect.MakeFunc".
69
75
func PatchMethodWithMakeFunc (target reflect.Value , fn func (args []reflect.Value ) (results []reflect.Value )) (* Patch , error ) {
70
76
return PatchMethodByReflect (target , reflect .MakeFunc (target .Type (), fn ))
71
77
}
72
-
78
+ // Patch the target func with the redirection func.
73
79
func (p * Patch ) Patch () error {
74
80
if p == nil {
75
81
return errors .New ("patch is nil" )
@@ -82,6 +88,7 @@ func (p *Patch) Patch() error {
82
88
}
83
89
return nil
84
90
}
91
+ // Unpatch the target func and recover the original func.
85
92
func (p * Patch ) Unpatch () error {
86
93
if p == nil {
87
94
return errors .New ("patch is nil" )
@@ -96,7 +103,7 @@ func isPatchable(target, redirection *reflect.Value) error {
96
103
if target .Type () != redirection .Type () {
97
104
return errors .New (fmt .Sprintf ("the target and/or redirection doesn't have the same type: %s != %s" , target .Type (), redirection .Type ()))
98
105
}
99
- if _ , ok := patches [getSafeCodePointer (target )]; ok {
106
+ if _ , ok := patches [getCodePointer (target )]; ok {
100
107
return errors .New ("the target is already patched" )
101
108
}
102
109
return nil
@@ -105,7 +112,7 @@ func isPatchable(target, redirection *reflect.Value) error {
105
112
func applyPatch (patch * Patch ) error {
106
113
patchLock .Lock ()
107
114
defer patchLock .Unlock ()
108
- tPointer := getSafeCodePointer (patch .target )
115
+ tPointer := getCodePointer (patch .target )
109
116
rPointer := getInternalPtrFromValue (patch .redirection )
110
117
rPointerJumpBytes , err := getJumpFuncBytes (rPointer )
111
118
if err != nil {
@@ -114,7 +121,7 @@ func applyPatch(patch *Patch) error {
114
121
tPointerBytes := getMemorySliceFromPointer (tPointer , len (rPointerJumpBytes ))
115
122
targetBytes := make ([]byte , len (tPointerBytes ))
116
123
copy (targetBytes , tPointerBytes )
117
- if err := copyDataToPtr (tPointer , rPointerJumpBytes ); err != nil {
124
+ if err := writeDataToPointer (tPointer , rPointerJumpBytes ); err != nil {
118
125
return err
119
126
}
120
127
patch .targetBytes = targetBytes
@@ -128,12 +135,12 @@ func applyUnpatch(patch *Patch) error {
128
135
if patch .targetBytes == nil || len (patch .targetBytes ) == 0 {
129
136
return errors .New ("the target is not patched" )
130
137
}
131
- tPointer := getSafeCodePointer (patch .target )
138
+ tPointer := getCodePointer (patch .target )
132
139
if _ , ok := patches [tPointer ]; ! ok {
133
140
return errors .New ("the target is not patched" )
134
141
}
135
142
delete (patches , tPointer )
136
- err := copyDataToPtr (tPointer , patch .targetBytes )
143
+ err := writeDataToPointer (tPointer , patch .targetBytes )
137
144
if err != nil {
138
145
return err
139
146
}
@@ -148,6 +155,7 @@ func getValueFrom(data interface{}) reflect.Value {
148
155
}
149
156
}
150
157
158
+ // Extracts a memory slice from a pointer
151
159
func getMemorySliceFromPointer (p unsafe.Pointer , length int ) []byte {
152
160
return * (* []byte )(unsafe .Pointer (& sliceHeader {
153
161
Data : p ,
@@ -156,7 +164,8 @@ func getMemorySliceFromPointer(p unsafe.Pointer, length int) []byte {
156
164
}))
157
165
}
158
166
159
- func getSafeCodePointer (value * reflect.Value ) unsafe.Pointer {
167
+ // Gets the code pointer of a func
168
+ func getCodePointer (value * reflect.Value ) unsafe.Pointer {
160
169
p := getInternalPtrFromValue (value )
161
170
if p != nil {
162
171
p = * (* unsafe .Pointer )(p )
0 commit comments