23
23
*/
24
24
25
25
import java .util .ArrayList ;
26
+ import java .util .HashMap ;
26
27
import java .util .List ;
28
+ import java .util .Map ;
27
29
28
30
/*-
29
31
* #%L
54
56
import soot .SootClass ;
55
57
import soot .SootMethodRef ;
56
58
import soot .Type ;
59
+ import soot .Unit ;
57
60
import soot .Value ;
58
61
import soot .dotnet .members .AbstractDotnetMember ;
62
+ import soot .dotnet .members .ByReferenceWrapperGenerator ;
59
63
import soot .dotnet .members .DotnetMethod ;
60
64
import soot .dotnet .members .method .DotnetBody ;
61
65
import soot .dotnet .proto .ProtoAssemblyAllTypes ;
@@ -111,61 +115,36 @@ public void jimplify(Body jb) {
111
115
*/
112
116
@ Override
113
117
public Value jimplifyExpr (Body jb ) {
114
- clazz = Scene .v ().getSootClass (instruction .getMethod ().getDeclaringType ().getFullname ());
115
- method = new DotnetMethod (instruction .getMethod (), clazz );
116
118
119
+ SootClass clazz = Scene .v ().getSootClass (instruction .getMethod ().getDeclaringType ().getFullname ());
120
+ DotnetMethod method = new DotnetMethod (instruction .getMethod (), clazz );
117
121
// STATIC
118
122
if (method .isStatic ()) {
119
- checkMethodAvailable ();
120
- List <Value > argsVariables = new ArrayList <>(instruction .getArgumentsCount ());
121
- List <Type > argsTypes = new ArrayList <>(method .getParameterDefinitions ().size ());
122
-
123
+ checkMethodAvailable (method );
123
124
// If System.Array.Empty
124
125
Value rewriteField = AbstractDotnetMember .checkRewriteCilSpecificMember (clazz , method .getName ());
125
126
if (rewriteField != null ) {
126
127
return rewriteField ;
127
128
}
129
+ MethodParams methodParams = getMethodCallParams (method , false , jb );
128
130
129
- // method-parameters (signature)
130
- for (ProtoAssemblyAllTypes .ParameterDefinition parameterDefinition : method .getParameterDefinitions ()) {
131
- argsTypes .add (DotnetTypeFactory .toSootType (parameterDefinition .getType ()));
132
- }
133
-
134
- int i = 0 ;
135
- // arguments which are passed to this function
136
- for (ProtoIlInstructions .IlInstructionMsg a : instruction .getArgumentsList ()) {
137
- Value argValue = CilInstructionFactory .fromInstructionMsg (a , dotnetBody , cilBlock ).jimplifyExpr (jb );
138
- argValue = simplifyComplexExpression (jb , argValue );
139
- Type argDestType = argsTypes .get (i );
140
- if (argDestType instanceof RefType && argValue .getType () instanceof PrimType ) {
141
- // can happen when enums are expected
142
- argValue = createTempVar (jb , Jimple .v (), Jimple .v ().newCastExpr (argValue , argDestType ));
143
- }
144
- argsVariables .add (argValue );
145
- i ++;
146
- }
147
-
148
- String methodName = method .getUniqueName ();
149
-
150
- SootMethodRef methodRef = Scene .v ().makeMethodRef (clazz , DotnetMethod .convertCtorName (methodName ), argsTypes ,
151
- DotnetTypeFactory .toSootType (method .getReturnType ()), true );
152
- return Jimple .v ().newStaticInvokeExpr (methodRef , argsVariables );
131
+ return Jimple .v ().newStaticInvokeExpr (methodParams .methodRef , methodParams .argumentVariables );
153
132
}
154
133
// INTERFACE
155
134
else if (clazz .isInterface ()) {
156
- MethodParams methodParams = getMethodCallParams (jb );
157
- return Jimple .v ().newInterfaceInvokeExpr (methodParams .Base , methodParams .MethodRef , methodParams .ArgumentVariables );
135
+ MethodParams methodParams = getMethodCallParams (method , true , jb );
136
+ return Jimple .v ().newInterfaceInvokeExpr (methodParams .base , methodParams .methodRef , methodParams .argumentVariables );
158
137
}
159
138
// CONSTRUCTOR and PRIVATE METHOD CALLS
160
139
else if (instruction .getMethod ().getIsConstructor ()
161
140
|| instruction .getMethod ().getAccessibility ().equals (ProtoAssemblyAllTypes .Accessibility .PRIVATE )) {
162
- MethodParams methodParams = getMethodCallParams (jb );
163
- return Jimple .v ().newSpecialInvokeExpr (methodParams .Base , methodParams .MethodRef , methodParams .ArgumentVariables );
141
+ MethodParams methodParams = getMethodCallParams (method , true , jb );
142
+ return Jimple .v ().newSpecialInvokeExpr (methodParams .base , methodParams .methodRef , methodParams .argumentVariables );
164
143
}
165
144
// DYNAMIC OBJECT METHOD
166
145
else {
167
- MethodParams methodParams = getMethodCallParams (jb );
168
- return Jimple .v ().newVirtualInvokeExpr (methodParams .Base , methodParams .MethodRef , methodParams .ArgumentVariables );
146
+ MethodParams methodParams = getMethodCallParams (method , true , jb );
147
+ return Jimple .v ().newVirtualInvokeExpr (methodParams .base , methodParams .methodRef , methodParams .argumentVariables );
169
148
}
170
149
}
171
150
@@ -175,52 +154,88 @@ public List<Pair<Local, Local>> getLocalsToCastForCall() {
175
154
176
155
private final List <Pair <Local , Local >> localsToCastForCall ;
177
156
178
- private MethodParams getMethodCallParams (Body jb ) {
179
- checkMethodAvailable ();
157
+ protected MethodParams getMethodCallParams (boolean hasBase , Body jb ) {
158
+ SootClass clazz = Scene .v ().getSootClass (instruction .getMethod ().getDeclaringType ().getFullname ());
159
+ DotnetMethod method = new DotnetMethod (instruction .getMethod (), clazz );
160
+ return getMethodCallParams (method , hasBase , jb );
161
+ }
162
+
163
+ protected MethodParams getMethodCallParams (DotnetMethod method , boolean hasBase , Body jb ) {
164
+ checkMethodAvailable (method );
180
165
List <Value > argsVariables = new ArrayList <>();
181
166
List <Type > methodParamTypes = new ArrayList <>();
182
- if (instruction .getArgumentsCount () == 0 ) {
167
+ if (hasBase && instruction .getArgumentsCount () == 0 ) {
183
168
throw new RuntimeException ("Opcode: " + instruction .getOpCode () + ": Given method " + method .getName ()
184
169
+ " of declared type " + method .getDeclaringClass ().getName ()
185
170
+ " has no arguments! This means there is no base variable for the virtual invoke!" );
186
171
}
187
172
188
- Value baseValue
189
- = CilInstructionFactory .fromInstructionMsg (instruction .getArguments (0 ), dotnetBody , cilBlock ).jimplifyExpr (jb );
190
- baseValue = simplifyComplexExpression (jb , baseValue );
191
- if (baseValue instanceof Constant ) {
192
- baseValue = createTempVar (jb , Jimple .v (), baseValue );
173
+ int startIdx = 0 ;
174
+ Local base = null ;
175
+ if (hasBase ) {
176
+ Value baseValue
177
+ = CilInstructionFactory .fromInstructionMsg (instruction .getArguments (0 ), dotnetBody , cilBlock ).jimplifyExpr (jb );
178
+ baseValue = simplifyComplexExpression (jb , baseValue );
179
+ if (baseValue instanceof Constant ) {
180
+ baseValue = createTempVar (jb , Jimple .v (), baseValue );
181
+ }
182
+ base = (Local ) baseValue ;
183
+ startIdx = 1 ;
193
184
}
194
- Local base = (Local ) baseValue ;
195
185
196
- if (instruction .getArgumentsCount () > 1 ) {
197
- for (int z = 1 ; z < instruction .getArgumentsCount (); z ++) {
186
+ Map <Integer , SootClass > byRefWrappers = new HashMap <>();
187
+ if (instruction .getArgumentsCount () > startIdx ) {
188
+ for (int z = startIdx ; z < instruction .getArgumentsCount (); z ++) {
198
189
Value argValue
199
190
= CilInstructionFactory .fromInstructionMsg (instruction .getArguments (z ), dotnetBody , cilBlock ).jimplifyExpr (jb );
200
191
argValue = simplifyComplexExpression (jb , argValue );
201
192
argsVariables .add (argValue );
202
193
}
194
+ int p = 0 ;
203
195
for (ProtoAssemblyAllTypes .ParameterDefinition parameterDefinition : instruction .getMethod ().getParameterList ()) {
204
- methodParamTypes .add (DotnetTypeFactory .toSootType (parameterDefinition .getType ()));
196
+ Type t = DotnetTypeFactory .toSootType (parameterDefinition .getType ());
197
+ if (ByReferenceWrapperGenerator .needsWrapper (parameterDefinition )) {
198
+ SootClass sc = ByReferenceWrapperGenerator .getWrapperClass (t );
199
+ t = sc .getType ();
200
+ byRefWrappers .put (p , sc );
201
+ }
202
+ methodParamTypes .add (t );
203
+ p ++;
205
204
}
206
205
}
206
+ List <Unit > afterCallUnits = null ;
207
207
208
208
// Check if cast is needed for correct validation, e.g.:
209
209
// System.Object modifiers = null;
210
210
// constructor = virtualinvoke type.<System.Type: ConstructorInfo
211
211
// GetConstructor(System.Reflection.ParameterModifier[])>(modifiers);
212
212
// FastHierarchy is not available at this point, check hierarchy would be easier
213
213
for (int i = 0 ; i < argsVariables .size (); i ++) {
214
- Value arg = argsVariables .get (i );
214
+ final Value originalArg = argsVariables .get (i );
215
+ Value modifiedArg = originalArg ;
215
216
Type methodParam = methodParamTypes .get (i );
216
- if (arg instanceof Local ) {
217
- if (arg .getType ().toString ().equals (DotnetBasicTypes .SYSTEM_OBJECT )
217
+ Type argType = modifiedArg .getType ();
218
+ if (modifiedArg instanceof Local ) {
219
+ if (argType .toString ().equals (DotnetBasicTypes .SYSTEM_OBJECT )
218
220
&& !methodParam .toString ().equals (DotnetBasicTypes .SYSTEM_OBJECT )) {
219
221
Local castLocal = dotnetBody .variableManager .localGenerator .generateLocal (methodParam );
220
- localsToCastForCall .add (new Pair <>((Local ) arg , castLocal ));
221
- argsVariables .set (i , castLocal );
222
+ localsToCastForCall .add (new Pair <>((Local ) modifiedArg , castLocal ));
223
+ modifiedArg = castLocal ;
224
+ }
225
+ }
226
+ if (methodParam instanceof RefType && argType instanceof PrimType ) {
227
+ // can happen when enums are expected
228
+ modifiedArg = createTempVar (jb , Jimple .v (), Jimple .v ().newCastExpr (modifiedArg , methodParam ));
229
+ }
230
+ SootClass wrapped = byRefWrappers .get (i );
231
+ if (wrapped != null ) {
232
+ modifiedArg = ByReferenceWrapperGenerator .insertWrapperCall (jb , wrapped , modifiedArg );
233
+ if (afterCallUnits == null ) {
234
+ afterCallUnits = new ArrayList <>();
222
235
}
236
+ afterCallUnits .add (ByReferenceWrapperGenerator .getUnwrapCall (wrapped , modifiedArg , originalArg ));
223
237
}
238
+ argsVariables .set (i , modifiedArg );
224
239
}
225
240
226
241
String methodName = method .getUniqueName ();
@@ -235,28 +250,30 @@ private MethodParams getMethodCallParams(Body jb) {
235
250
return_type = DotnetTypeFactory .toSootType (method .getProtoMessage ().getReturnType ());
236
251
}
237
252
238
- SootMethodRef methodRef
239
- = Scene . v (). makeMethodRef ( clazz , DotnetMethod . convertCtorName ( methodName ), methodParamTypes , return_type , false );
253
+ SootMethodRef methodRef = Scene . v (). makeMethodRef ( method . getDeclaringClass (), DotnetMethod . convertCtorName ( methodName ),
254
+ methodParamTypes , return_type , ! hasBase );
240
255
241
- return new MethodParams (base , methodRef , argsVariables );
256
+ return new MethodParams (base , methodRef , argsVariables , afterCallUnits );
242
257
}
243
258
244
- private void checkMethodAvailable () {
259
+ private void checkMethodAvailable (DotnetMethod method ) {
245
260
if (method .getName ().trim ().isEmpty ()) {
246
261
throw new RuntimeException ("Opcode: " + instruction .getOpCode () + ": Given method " + method .getName ()
247
262
+ " of declared type " + method .getDeclaringClass ().getName () + " has no method name!" );
248
263
}
249
264
}
250
265
251
- private static class MethodParams {
252
- public MethodParams (Local base , SootMethodRef methodRef , List <Value > argsVariables ) {
253
- Base = base ;
254
- MethodRef = methodRef ;
255
- ArgumentVariables = argsVariables ;
266
+ static class MethodParams {
267
+ public MethodParams (Local base , SootMethodRef methodRef , List <Value > argsVariables , List <Unit > afterCallUnits ) {
268
+ this .base = base ;
269
+ this .methodRef = methodRef ;
270
+ this .argumentVariables = argsVariables ;
271
+ this .afterCallUnits = afterCallUnits ;
256
272
}
257
273
258
- public Local Base ;
259
- public SootMethodRef MethodRef ;
260
- public List <Value > ArgumentVariables ;
274
+ public Local base ;
275
+ public SootMethodRef methodRef ;
276
+ public List <Value > argumentVariables ;
277
+ private List <Unit > afterCallUnits ;
261
278
}
262
279
}
0 commit comments