From 5d9224aa17e5127141047e2dc81b0fceea3edf2d Mon Sep 17 00:00:00 2001 From: Veit Weidinger Date: Thu, 29 Jun 2023 17:15:48 +0200 Subject: [PATCH] Added support for ILSpy8 instructions Removed checkVariabelIsLocal method removed TODO Removed unnecessary comment --- src/main/java/soot/Scene.java | 7 +- .../CilBinaryNumericInstruction.java | 4 +- .../instructions/CilCallVirtInstruction.java | 68 ++++++------------- .../CilCastClassUnBoxInstruction.java | 3 +- .../instructions/CilConvInstruction.java | 3 +- .../instructions/CilLdElemaInstruction.java | 2 +- .../instructions/CilNewArrInstruction.java | 1 + .../instructions/CilStLocInstruction.java | 13 ++-- .../instructions/CilStObjInstruction.java | 40 ++++++----- .../java/soot/dotnet/members/DotnetField.java | 4 +- .../method/DotnetBodyVariableManager.java | 33 +++++++++ 11 files changed, 94 insertions(+), 84 deletions(-) diff --git a/src/main/java/soot/Scene.java b/src/main/java/soot/Scene.java index 3b5b67596f2..0086695aaae 100755 --- a/src/main/java/soot/Scene.java +++ b/src/main/java/soot/Scene.java @@ -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; @@ -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); diff --git a/src/main/java/soot/dotnet/instructions/CilBinaryNumericInstruction.java b/src/main/java/soot/dotnet/instructions/CilBinaryNumericInstruction.java index 1051375d58e..6de2da3a334 100644 --- a/src/main/java/soot/dotnet/instructions/CilBinaryNumericInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilBinaryNumericInstruction.java @@ -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); diff --git a/src/main/java/soot/dotnet/instructions/CilCallVirtInstruction.java b/src/main/java/soot/dotnet/instructions/CilCallVirtInstruction.java index cd61a60e0c4..dd685dfc5a6 100644 --- a/src/main/java/soot/dotnet/instructions/CilCallVirtInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilCallVirtInstruction.java @@ -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 @@ -88,13 +87,10 @@ public void jimplify(Body jb) { // cast for validation if (cilExpr instanceof CilCallVirtInstruction) { - List> locals = ((CilCallVirtInstruction) cilExpr).getLocalsToCastForCall(); - if (locals.size() != 0) { - for (Pair 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 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); } } @@ -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 argsVariables = new ArrayList<>(); + List argsVariables = new ArrayList<>(); List argsTypes = new ArrayList<>(); // If System.Array.Empty @@ -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()) { @@ -161,15 +156,15 @@ else if (instruction.getMethod().getIsConstructor() } } - public List> getLocalsToCastForCall() { - return localsToCastForCall; + public List> getPrimitivesToCastForCall() { + return primitivesToCastForCall; } - private final List> localsToCastForCall; + private final List> primitivesToCastForCall; private MethodParams getMethodCallParams(Body jb) { checkMethodAvailable(); - List argsVariables = new ArrayList<>(); + List argsVariables = new ArrayList<>(); List methodParamTypes = new ArrayList<>(); if (instruction.getArgumentsCount() == 0) { throw new RuntimeException("Opcode: " + instruction.getOpCode() + ": Given method " + method.getName() @@ -177,18 +172,13 @@ private MethodParams getMethodCallParams(Body jb) { + " 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())); @@ -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); } } @@ -236,24 +226,8 @@ 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 argumentVariables) { + public MethodParams(Local base, SootMethodRef methodRef, List argumentVariables) { Base = base; MethodRef = methodRef; ArgumentVariables = argumentVariables; @@ -261,6 +235,6 @@ public MethodParams(Local base, SootMethodRef methodRef, List argumentVar public Local Base; public SootMethodRef MethodRef; - public List ArgumentVariables; + public List ArgumentVariables; } } diff --git a/src/main/java/soot/dotnet/instructions/CilCastClassUnBoxInstruction.java b/src/main/java/soot/dotnet/instructions/CilCastClassUnBoxInstruction.java index e74715d62c1..4e193274f62 100644 --- a/src/main/java/soot/dotnet/instructions/CilCastClassUnBoxInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilCastClassUnBoxInstruction.java @@ -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); } } diff --git a/src/main/java/soot/dotnet/instructions/CilConvInstruction.java b/src/main/java/soot/dotnet/instructions/CilConvInstruction.java index 1b7fac6cae5..962590e945a 100644 --- a/src/main/java/soot/dotnet/instructions/CilConvInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilConvInstruction.java @@ -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); } } diff --git a/src/main/java/soot/dotnet/instructions/CilLdElemaInstruction.java b/src/main/java/soot/dotnet/instructions/CilLdElemaInstruction.java index eb621d0cdd6..57734bbc0ad 100644 --- a/src/main/java/soot/dotnet/instructions/CilLdElemaInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilLdElemaInstruction.java @@ -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); diff --git a/src/main/java/soot/dotnet/instructions/CilNewArrInstruction.java b/src/main/java/soot/dotnet/instructions/CilNewArrInstruction.java index 3fcf1aca63a..da62fd3547c 100644 --- a/src/main/java/soot/dotnet/instructions/CilNewArrInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilNewArrInstruction.java @@ -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); } diff --git a/src/main/java/soot/dotnet/instructions/CilStLocInstruction.java b/src/main/java/soot/dotnet/instructions/CilStLocInstruction.java index 28eb46d565e..9eb74af53b4 100644 --- a/src/main/java/soot/dotnet/instructions/CilStLocInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilStLocInstruction.java @@ -1,7 +1,5 @@ package soot.dotnet.instructions; -import java.util.List; - /*- * #%L * Soot - a J*va Optimization Framework @@ -68,13 +66,10 @@ public void jimplify(Body jb) { // cast for validation if (cilExpr instanceof CilCallVirtInstruction) { - List> locals = ((CilCallVirtInstruction) cilExpr).getLocalsToCastForCall(); - if (locals.size() != 0) { - for (Pair 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 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 diff --git a/src/main/java/soot/dotnet/instructions/CilStObjInstruction.java b/src/main/java/soot/dotnet/instructions/CilStObjInstruction.java index a6d2d91afc5..ed3f6e375cb 100644 --- a/src/main/java/soot/dotnet/instructions/CilStObjInstruction.java +++ b/src/main/java/soot/dotnet/instructions/CilStObjInstruction.java @@ -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 @@ -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 diff --git a/src/main/java/soot/dotnet/members/DotnetField.java b/src/main/java/soot/dotnet/members/DotnetField.java index a4568c41261..1b92000b8c3 100644 --- a/src/main/java/soot/dotnet/members/DotnetField.java +++ b/src/main/java/soot/dotnet/members/DotnetField.java @@ -2,6 +2,8 @@ import static soot.dotnet.specifications.DotnetModifier.toSootModifier; +import soot.Scene; + /*- * #%L * Soot - a J*va Optimization Framework @@ -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); } } diff --git a/src/main/java/soot/dotnet/members/method/DotnetBodyVariableManager.java b/src/main/java/soot/dotnet/members/method/DotnetBodyVariableManager.java index 7dc075cd832..72e138049b3 100644 --- a/src/main/java/soot/dotnet/members/method/DotnetBodyVariableManager.java +++ b/src/main/java/soot/dotnet/members/method/DotnetBodyVariableManager.java @@ -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; @@ -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; + } }