Skip to content

Commit 2d6386a

Browse files
committed
Simpifications
1 parent a84f3a7 commit 2d6386a

7 files changed

+201
-139
lines changed

src/main/java/soot/dotnet/instructions/AbstractNewObjInstanceInstruction.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
import soot.jimple.Jimple;
5757
import soot.jimple.SpecialInvokeExpr;
5858

59-
public abstract class AbstractNewObjInstanceInstruction extends AbstractCilnstruction {
59+
public abstract class AbstractNewObjInstanceInstruction extends CilCallInstruction {
6060
public AbstractNewObjInstanceInstruction(ProtoIlInstructions.IlInstructionMsg instruction, DotnetBody dotnetBody,
6161
CilBlock cilBlock) {
6262
super(instruction, dotnetBody, cilBlock);

src/main/java/soot/dotnet/instructions/CilCallInstruction.java

+82-65
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
*/
2424

2525
import java.util.ArrayList;
26+
import java.util.HashMap;
2627
import java.util.List;
28+
import java.util.Map;
2729

2830
/*-
2931
* #%L
@@ -54,8 +56,10 @@
5456
import soot.SootClass;
5557
import soot.SootMethodRef;
5658
import soot.Type;
59+
import soot.Unit;
5760
import soot.Value;
5861
import soot.dotnet.members.AbstractDotnetMember;
62+
import soot.dotnet.members.ByReferenceWrapperGenerator;
5963
import soot.dotnet.members.DotnetMethod;
6064
import soot.dotnet.members.method.DotnetBody;
6165
import soot.dotnet.proto.ProtoAssemblyAllTypes;
@@ -111,61 +115,36 @@ public void jimplify(Body jb) {
111115
*/
112116
@Override
113117
public Value jimplifyExpr(Body jb) {
114-
clazz = Scene.v().getSootClass(instruction.getMethod().getDeclaringType().getFullname());
115-
method = new DotnetMethod(instruction.getMethod(), clazz);
116118

119+
SootClass clazz = Scene.v().getSootClass(instruction.getMethod().getDeclaringType().getFullname());
120+
DotnetMethod method = new DotnetMethod(instruction.getMethod(), clazz);
117121
// STATIC
118122
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);
123124
// If System.Array.Empty
124125
Value rewriteField = AbstractDotnetMember.checkRewriteCilSpecificMember(clazz, method.getName());
125126
if (rewriteField != null) {
126127
return rewriteField;
127128
}
129+
MethodParams methodParams = getMethodCallParams(method, false, jb);
128130

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);
153132
}
154133
// INTERFACE
155134
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);
158137
}
159138
// CONSTRUCTOR and PRIVATE METHOD CALLS
160139
else if (instruction.getMethod().getIsConstructor()
161140
|| 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);
164143
}
165144
// DYNAMIC OBJECT METHOD
166145
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);
169148
}
170149
}
171150

@@ -175,52 +154,88 @@ public List<Pair<Local, Local>> getLocalsToCastForCall() {
175154

176155
private final List<Pair<Local, Local>> localsToCastForCall;
177156

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);
180165
List<Value> argsVariables = new ArrayList<>();
181166
List<Type> methodParamTypes = new ArrayList<>();
182-
if (instruction.getArgumentsCount() == 0) {
167+
if (hasBase && instruction.getArgumentsCount() == 0) {
183168
throw new RuntimeException("Opcode: " + instruction.getOpCode() + ": Given method " + method.getName()
184169
+ " of declared type " + method.getDeclaringClass().getName()
185170
+ " has no arguments! This means there is no base variable for the virtual invoke!");
186171
}
187172

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;
193184
}
194-
Local base = (Local) baseValue;
195185

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++) {
198189
Value argValue
199190
= CilInstructionFactory.fromInstructionMsg(instruction.getArguments(z), dotnetBody, cilBlock).jimplifyExpr(jb);
200191
argValue = simplifyComplexExpression(jb, argValue);
201192
argsVariables.add(argValue);
202193
}
194+
int p = 0;
203195
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++;
205204
}
206205
}
206+
List<Unit> afterCallUnits = null;
207207

208208
// Check if cast is needed for correct validation, e.g.:
209209
// System.Object modifiers = null;
210210
// constructor = virtualinvoke type.<System.Type: ConstructorInfo
211211
// GetConstructor(System.Reflection.ParameterModifier[])>(modifiers);
212212
// FastHierarchy is not available at this point, check hierarchy would be easier
213213
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;
215216
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)
218220
&& !methodParam.toString().equals(DotnetBasicTypes.SYSTEM_OBJECT)) {
219221
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<>();
222235
}
236+
afterCallUnits.add(ByReferenceWrapperGenerator.getUnwrapCall(wrapped, modifiedArg, originalArg));
223237
}
238+
argsVariables.set(i, modifiedArg);
224239
}
225240

226241
String methodName = method.getUniqueName();
@@ -235,28 +250,30 @@ private MethodParams getMethodCallParams(Body jb) {
235250
return_type = DotnetTypeFactory.toSootType(method.getProtoMessage().getReturnType());
236251
}
237252

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);
240255

241-
return new MethodParams(base, methodRef, argsVariables);
256+
return new MethodParams(base, methodRef, argsVariables, afterCallUnits);
242257
}
243258

244-
private void checkMethodAvailable() {
259+
private void checkMethodAvailable(DotnetMethod method) {
245260
if (method.getName().trim().isEmpty()) {
246261
throw new RuntimeException("Opcode: " + instruction.getOpCode() + ": Given method " + method.getName()
247262
+ " of declared type " + method.getDeclaringClass().getName() + " has no method name!");
248263
}
249264
}
250265

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;
256272
}
257273

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;
261278
}
262279
}

src/main/java/soot/dotnet/instructions/CilNewObjInstruction.java

+3-64
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package soot.dotnet.instructions;
22

3-
import java.util.ArrayList;
4-
53
/*-
64
* #%L
75
* Soot - a J*va Optimization Framework
@@ -24,24 +22,14 @@
2422
* #L%
2523
*/
2624
import soot.Body;
27-
import soot.PrimType;
2825
import soot.RefType;
2926
import soot.Scene;
3027
import soot.SootClass;
31-
import soot.Type;
3228
import soot.Value;
3329
import soot.dotnet.members.method.DotnetBody;
34-
import soot.dotnet.proto.ProtoAssemblyAllTypes.IlType;
35-
import soot.dotnet.proto.ProtoAssemblyAllTypes.ParameterDefinition;
3630
import soot.dotnet.proto.ProtoIlInstructions;
37-
import soot.dotnet.types.DotnetTypeFactory;
38-
import soot.jimple.DoubleConstant;
39-
import soot.jimple.FloatConstant;
40-
import soot.jimple.IntConstant;
4131
import soot.jimple.Jimple;
42-
import soot.jimple.LongConstant;
4332
import soot.jimple.NewExpr;
44-
import soot.jimple.StringConstant;
4533

4634
/**
4735
* Combi instruction with instantiating a new object and calling the constructor (no structs often) Call
@@ -64,60 +52,11 @@ public Value jimplifyExpr(Body jb) {
6452
SootClass clazz = RefType.v(instruction.getMethod().getDeclaringType().getFullname()).getSootClass();
6553
NewExpr newExpr = Jimple.v().newNewExpr(clazz.getType());
6654

67-
ArrayList<Type> argsTypes = new ArrayList<>(instruction.getMethod().getParameterCount());
68-
for (ParameterDefinition p : instruction.getMethod().getParameterList()) {
69-
argsTypes.add(DotnetTypeFactory.toSootType(p.getType()));
70-
}
71-
ArrayList<Value> argsVariables = new ArrayList<>(instruction.getArgumentsList().size());
72-
int i = 0;
73-
for (ProtoIlInstructions.IlInstructionMsg a : instruction.getArgumentsList()) {
74-
75-
if (a.hasVariable()) {
76-
argsVariables.add(dotnetBody.variableManager.addOrGetVariable(a.getVariable(), jb));
77-
} else {
78-
IlType t = a.getConstantType();
79-
if (t == null) {
80-
throw new RuntimeException("Not a local or constant: " + a);
81-
}
82-
Value argValue;
83-
switch (t) {
84-
case type_unknown:
85-
case UNRECOGNIZED:
86-
Value v = CilInstructionFactory.fromInstructionMsg(a, dotnetBody, cilBlock).jimplifyExpr(jb);
87-
argValue = createTempVar(jb, Jimple.v(), v);
88-
break;
89-
case type_double:
90-
argValue = DoubleConstant.v(a.getValueConstantDouble());
91-
break;
92-
case type_float:
93-
argValue = FloatConstant.v(a.getValueConstantFloat());
94-
break;
95-
case type_int32:
96-
argValue = IntConstant.v((int) a.getValueConstantInt64());
97-
break;
98-
case type_int64:
99-
argValue = LongConstant.v(a.getValueConstantInt64());
100-
break;
101-
case type_string:
102-
argValue = StringConstant.v(a.getValueConstantString());
103-
break;
104-
default:
105-
throw new RuntimeException("Unsupported: " + t);
106-
107-
}
108-
Type argDestType = argsTypes.get(i);
109-
if (argDestType instanceof RefType && argValue.getType() instanceof PrimType) {
110-
// can happen when enums are expected
111-
argValue = createTempVar(jb, Jimple.v(), Jimple.v().newCastExpr(argValue, argDestType));
112-
}
113-
argsVariables.add(argValue);
114-
i++;
115-
}
116-
}
55+
MethodParams t = getMethodCallParams(false, jb);
11756

11857
// Constructor call expression
119-
methodRef = Scene.v().makeConstructorRef(clazz, argsTypes);
120-
listOfArgs = argsVariables;
58+
methodRef = Scene.v().makeConstructorRef(clazz, t.methodRef.getParameterTypes());
59+
listOfArgs = t.argumentVariables;
12160

12261
return newExpr;
12362
}

0 commit comments

Comments
 (0)