Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for ILSpy8 instructions #1983

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/main/java/soot/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -1726,9 +1727,9 @@ private void addSootBasicClasses() {
}

private void addSootBasicDotnetClasses() {
basicclasses[SootClass.HIERARCHY] = new HashSet<>();
basicclasses[SootClass.SIGNATURES] = new HashSet<>();
basicclasses[SootClass.BODIES] = new HashSet<>();
basicclasses[SootClass.HIERARCHY] = new LinkedHashSet<>();
basicclasses[SootClass.SIGNATURES] = new LinkedHashSet<>();
basicclasses[SootClass.BODIES] = new LinkedHashSet<>();

addBasicClass(DotnetBasicTypes.SYSTEM_OBJECT, SootClass.SIGNATURES);
addBasicClass(DotnetBasicTypes.SYSTEM_VOID, SootClass.SIGNATURES);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ public void jimplify(Body jb) {
@Override
public Value jimplifyExpr(Body jb) {
Value left = CilInstructionFactory.fromInstructionMsg(instruction.getLeft(), dotnetBody, cilBlock).jimplifyExpr(jb);
left = inlineCastExpr(left);
left = dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal((inlineCastExpr(left)));
Value right = CilInstructionFactory.fromInstructionMsg(instruction.getRight(), dotnetBody, cilBlock).jimplifyExpr(jb);
right = inlineCastExpr(right);
right = dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal((inlineCastExpr(right)));
switch (instruction.getOperator()) {
case Add:
return Jimple.v().newAddExpr(left, right);
Expand Down
68 changes: 21 additions & 47 deletions src/main/java/soot/dotnet/instructions/CilCallVirtInstruction.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ public class CilCallVirtInstruction extends AbstractCilnstruction {
private SootClass clazz;
private DotnetMethod method;

public CilCallVirtInstruction(ProtoIlInstructions.IlInstructionMsg instruction, DotnetBody dotnetBody,
CilBlock cilBlock) {
public CilCallVirtInstruction(ProtoIlInstructions.IlInstructionMsg instruction, DotnetBody dotnetBody, CilBlock cilBlock) {
super(instruction, dotnetBody, cilBlock);
localsToCastForCall = new ArrayList<>();
primitivesToCastForCall = new ArrayList<>();
}

@Override
Expand All @@ -88,13 +87,10 @@ public void jimplify(Body jb) {

// cast for validation
if (cilExpr instanceof CilCallVirtInstruction) {
List<Pair<Local, Local>> locals = ((CilCallVirtInstruction) cilExpr).getLocalsToCastForCall();
if (locals.size() != 0) {
for (Pair<Local, Local> pair : locals) {
CastExpr castExpr = Jimple.v().newCastExpr(pair.getO1(), pair.getO2().getType());
AssignStmt assignStmt = Jimple.v().newAssignStmt(pair.getO2(), castExpr);
jb.getUnits().add(assignStmt);
}
for (Pair<Value, Value> pair : ((CilCallVirtInstruction) cilExpr).getPrimitivesToCastForCall()) {
CastExpr castExpr = Jimple.v().newCastExpr(pair.getO1(), pair.getO2().getType());
AssignStmt assignStmt = Jimple.v().newAssignStmt(pair.getO2(), castExpr);
jb.getUnits().add(assignStmt);
}
}

Expand All @@ -109,13 +105,14 @@ public void jimplify(Body jb) {
*/
@Override
public Value jimplifyExpr(Body jb) {
clazz = Scene.v().getSootClass(instruction.getMethod().getDeclaringType().getFullname());

clazz = Scene.v().forceResolve(instruction.getMethod().getDeclaringType().getFullname(), SootClass.SIGNATURES);
method = new DotnetMethod(instruction.getMethod(), clazz);

// STATIC
if (method.isStatic()) {
checkMethodAvailable();
List<Local> argsVariables = new ArrayList<>();
List<Value> argsVariables = new ArrayList<>();
List<Type> argsTypes = new ArrayList<>();

// If System.Array.Empty
Expand All @@ -128,9 +125,7 @@ public Value jimplifyExpr(Body jb) {
for (int z = 0; z < instruction.getArgumentsCount(); z++) {
Value variableValue
= CilInstructionFactory.fromInstructionMsg(instruction.getArguments(z), dotnetBody, cilBlock).jimplifyExpr(jb);
checkVariabelIsLocal(variableValue, z, false);
Local variable = (Local) variableValue;
argsVariables.add(variable);
argsVariables.add(dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal(variableValue));
}
// method-parameters (signature)
for (ProtoAssemblyAllTypes.ParameterDefinition parameterDefinition : method.getParameterDefinitions()) {
Expand Down Expand Up @@ -161,34 +156,29 @@ else if (instruction.getMethod().getIsConstructor()
}
}

public List<Pair<Local, Local>> getLocalsToCastForCall() {
return localsToCastForCall;
public List<Pair<Value, Value>> getPrimitivesToCastForCall() {
return primitivesToCastForCall;
}

private final List<Pair<Local, Local>> localsToCastForCall;
private final List<Pair<Value, Value>> primitivesToCastForCall;

private MethodParams getMethodCallParams(Body jb) {
checkMethodAvailable();
List<Local> argsVariables = new ArrayList<>();
List<Value> argsVariables = new ArrayList<>();
List<Type> methodParamTypes = new ArrayList<>();
if (instruction.getArgumentsCount() == 0) {
throw new RuntimeException("Opcode: " + instruction.getOpCode() + ": Given method " + method.getName()
+ " of declared type " + method.getDeclaringClass().getName()
+ " has no arguments! This means there is no base variable for the virtual invoke!");
}

Value baseValue
= CilInstructionFactory.fromInstructionMsg(instruction.getArguments(0), dotnetBody, cilBlock).jimplifyExpr(jb);
checkVariabelIsLocal(baseValue, 0, true);
Local base = (Local) baseValue;
Local base = dotnetBody.variableManager.simplifyWithLocal(CilInstructionFactory.fromInstructionMsg(instruction.getArguments(0), dotnetBody, cilBlock).jimplifyExpr(jb));

if (instruction.getArgumentsCount() > 1) {
for (int z = 1; z < instruction.getArgumentsCount(); z++) {
Value variableValue
= CilInstructionFactory.fromInstructionMsg(instruction.getArguments(z), dotnetBody, cilBlock).jimplifyExpr(jb);
checkVariabelIsLocal(variableValue, z, false);
Local variable = (Local) variableValue;
argsVariables.add(variable);
argsVariables.add(dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal(variableValue));
}
for (ProtoAssemblyAllTypes.ParameterDefinition parameterDefinition : instruction.getMethod().getParameterList()) {
methodParamTypes.add(DotnetTypeFactory.toSootType(parameterDefinition.getType()));
Expand All @@ -201,12 +191,12 @@ private MethodParams getMethodCallParams(Body jb) {
// GetConstructor(System.Reflection.ParameterModifier[])>(modifiers);
// FastHierarchy is not available at this point, check hierarchy would be easier
for (int i = 0; i < argsVariables.size(); i++) {
Local arg = argsVariables.get(i);
Value arg = argsVariables.get(i);
Type methodParam = methodParamTypes.get(i);
if (arg.getType().toString().equals(DotnetBasicTypes.SYSTEM_OBJECT)
&& !methodParam.toString().equals(DotnetBasicTypes.SYSTEM_OBJECT)) {
Local castLocal = dotnetBody.variableManager.localGenerator.generateLocal(methodParam);
localsToCastForCall.add(new Pair<>(arg, castLocal));
Value castLocal = dotnetBody.variableManager.localGenerator.generateLocal(methodParam);
primitivesToCastForCall.add(new Pair<>(arg, castLocal));
argsVariables.set(i, castLocal);
}
}
Expand Down Expand Up @@ -236,31 +226,15 @@ private void checkMethodAvailable() {
}
}

private void checkVariabelIsLocal(Value var, int argPos, boolean isBase) {
String err = "CALL: The given argument ";
err += argPos;
err += " ";
if (isBase) {
err += "(base variable)";
}
err += " of invoked method " + method.getName() + " declared in " + clazz.getName() + " is not a local! "
+ "The value is: " + var.toString() + " of type " + var.getType() + "! " + "The resolving method body is: "
+ dotnetBody.getDotnetMethodSig().getSootMethodSignature().getSignature();

if (!(var instanceof Local)) {
throw new RuntimeException(err);
}
}

private static class MethodParams {
public MethodParams(Local base, SootMethodRef methodRef, List<Local> argumentVariables) {
public MethodParams(Local base, SootMethodRef methodRef, List<? extends Value> argumentVariables) {
Base = base;
MethodRef = methodRef;
ArgumentVariables = argumentVariables;
}

public Local Base;
public SootMethodRef MethodRef;
public List<Local> ArgumentVariables;
public List<? extends Value> ArgumentVariables;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public Value jimplifyExpr(Body jb) {
Type type = DotnetTypeFactory.toSootType(instruction.getType());
CilInstruction cilExpr = CilInstructionFactory.fromInstructionMsg(instruction.getArgument(), dotnetBody, cilBlock);
Value argument = cilExpr.jimplifyExpr(jb);
return Jimple.v().newCastExpr(argument, type);

return Jimple.v().newCastExpr(dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal(argument), type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ public Value jimplifyExpr(Body jb) {
convType = UnknownType.v();
break;
}

return Jimple.v().newCastExpr(argument, convType);
return Jimple.v().newCastExpr(dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal(argument), convType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void jimplify(Body jb) {
public Value jimplifyExpr(Body jb) {
CilInstruction cilExpr = CilInstructionFactory.fromInstructionMsg(instruction.getArray(), dotnetBody, cilBlock);
baseArrayLocal = cilExpr.jimplifyExpr(jb);

baseArrayLocal = dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal(baseArrayLocal);
if (instruction.getIndicesCount() == 1) {
Value ind
= CilInstructionFactory.fromInstructionMsg(instruction.getIndices(0), dotnetBody, cilBlock).jimplifyExpr(jb);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public Value jimplifyExpr(Body jb) {
for (ProtoIlInstructions.IlInstructionMsg index : instruction.getIndicesList()) {
CilInstruction cilExpr = CilInstructionFactory.fromInstructionMsg(index, dotnetBody, cilBlock);
Value value = cilExpr.jimplifyExpr(jb);
value = dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal((value));
Value val = value instanceof Immediate ? value : DotnetBodyVariableManager.inlineLocals(value, jb);
sizesOfArr.add(val);
}
Expand Down
13 changes: 4 additions & 9 deletions src/main/java/soot/dotnet/instructions/CilStLocInstruction.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package soot.dotnet.instructions;

import java.util.List;

/*-
* #%L
* Soot - a J*va Optimization Framework
Expand Down Expand Up @@ -68,13 +66,10 @@ public void jimplify(Body jb) {

// cast for validation
if (cilExpr instanceof CilCallVirtInstruction) {
List<Pair<Local, Local>> locals = ((CilCallVirtInstruction) cilExpr).getLocalsToCastForCall();
if (locals.size() != 0) {
for (Pair<Local, Local> pair : locals) {
CastExpr castExpr = Jimple.v().newCastExpr(pair.getO1(), pair.getO2().getType());
AssignStmt assignStmt = Jimple.v().newAssignStmt(pair.getO2(), castExpr);
jb.getUnits().add(assignStmt);
}
for (Pair<Value, Value> pair : ((CilCallVirtInstruction) cilExpr).getPrimitivesToCastForCall()) {
CastExpr castExpr = Jimple.v().newCastExpr(pair.getO1(), pair.getO2().getType());
AssignStmt assignStmt = Jimple.v().newAssignStmt(pair.getO2(), castExpr);
jb.getUnits().add(assignStmt);
}
}
// create this cast, to validate successfully
Expand Down
40 changes: 22 additions & 18 deletions src/main/java/soot/dotnet/instructions/CilStObjInstruction.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
import soot.dotnet.types.DotnetBasicTypes;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.Constant;
import soot.jimple.Expr;
import soot.jimple.Jimple;
import soot.jimple.internal.JStaticInvokeExpr;

/**
* AssignStmt - Store ValueTypes to a local
Expand All @@ -57,27 +60,28 @@ public void jimplify(Body jb) {
}
}

// if rvalue is not single value and lvalue is static-ref, rewrite with a local variable to meet three address
// requirement
if (value instanceof CastExpr && !(target instanceof Local)) {
Local generatedLocal = dotnetBody.variableManager.localGenerator.generateLocal(target.getType());
AssignStmt assignStmt = Jimple.v().newAssignStmt(generatedLocal, value);
jb.getUnits().add(assignStmt);
value = generatedLocal;
// if new Obj also add call of constructor - relevant for structs (System.ValueType)
if (cilExpr instanceof AbstractNewObjInstanceInstruction) {
if (target instanceof Local) {
jb.getUnits().add(Jimple.v().newAssignStmt(target, value));
((AbstractNewObjInstanceInstruction) cilExpr).resolveCallConstructorBody(jb, (Local) target);
} else {
Local local = dotnetBody.variableManager.localGenerator.generateLocal(target.getType());
jb.getUnits().add(Jimple.v().newAssignStmt(local, value));
((AbstractNewObjInstanceInstruction) cilExpr).resolveCallConstructorBody(jb, local);
jb.getUnits().add(Jimple.v().newAssignStmt(target, local));
}
return;
}

// if rvalue is not single value and lvalue is also no local you need made a temp war
if (!(target instanceof Local)) {
value = dotnetBody.variableManager.simplifyIfNotPrimitiveWithLocal(value);
}

AssignStmt astm = Jimple.v().newAssignStmt(target, value);
jb.getUnits().add(astm);
jb.getUnits().add(Jimple.v().newAssignStmt(target, value));

// if new Obj also add call of constructor - relevant for structs (System.ValueType)
if (cilExpr instanceof AbstractNewObjInstanceInstruction) {
if (!(target instanceof Local)) {
throw new RuntimeException("STOBJ: The given target is not a local! " + "The value is: " + target.toString()
+ " of type " + target.getType() + "! " + "The resolving method body is: "
+ dotnetBody.getDotnetMethodSig().getSootMethodSignature().getSignature());
}
((AbstractNewObjInstanceInstruction) cilExpr).resolveCallConstructorBody(jb, (Local) target);
}

}

@Override
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/soot/dotnet/members/DotnetField.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static soot.dotnet.specifications.DotnetModifier.toSootModifier;

import soot.Scene;

/*-
* #%L
* Soot - a J*va Optimization Framework
Expand Down Expand Up @@ -44,6 +46,6 @@ public SootField makeSootField() {
int modifier = toSootModifier(protoField);
Type type = DotnetTypeFactory.toSootType(protoField.getType());
String name = protoField.getName();
return new SootField(name, type, modifier);
return Scene.v().makeSootField(name, type, modifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import soot.javaToJimple.DefaultLocalGenerator;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.Constant;
import soot.jimple.Jimple;
import soot.jimple.NullConstant;
import soot.jimple.internal.JAssignStmt;
Expand Down Expand Up @@ -232,4 +233,36 @@ public void addLocalsToCast(String local) {
public boolean localsToCastContains(String local) {
return localsToCast.contains(local);
}
/**
* Assign expression only to new local variable to use the value in complex operations, when val is not a local or constant
*
* @param val : assign to local
*/
public Value simplifyIfNotPrimitiveWithLocal(Value val) {
if(!(val instanceof Local || val instanceof Constant))
return (Value) generateLocalAndAssign(val);
return val;
}

/**
* Assign expression only to new local variable to use the value in complex operations, when val is not a local
*
* @param val : assign to local
*/

public Local simplifyWithLocal(Value val) {
if(!(val instanceof Local))
return generateLocalAndAssign(val);
return (Local) val;
}
/**
* Assign expression to new local variable to use the value in complex operations
*
* @param val : assign to local
*/
private Local generateLocalAndAssign(Value val) {
Local local = localGenerator.generateLocal(val.getType());
mainJb.getUnits().add(Jimple.v().newAssignStmt(local, val));
return local;
}
}