use of soot.util.HashChain in project soot by Sable.
the class ReflectiveCallsInliner method initializeReflectiveCallsTable.
private void initializeReflectiveCallsTable() {
int callSiteId = 0;
SootClass reflCallsClass = Scene.v().getSootClass("soot.rtlib.tamiflex.ReflectiveCalls");
SootMethod clinit = reflCallsClass.getMethodByName(SootMethod.staticInitializerName);
Body body = clinit.retrieveActiveBody();
PatchingChain<Unit> units = body.getUnits();
LocalGenerator localGen = new LocalGenerator(body);
Chain<Unit> newUnits = new HashChain<Unit>();
SootClass setClass = Scene.v().getSootClass("java.util.Set");
SootMethodRef addMethodRef = setClass.getMethodByName("add").makeRef();
for (SootMethod m : RTI.methodsContainingReflectiveCalls()) {
{
if (!RTI.classForNameClassNames(m).isEmpty()) {
SootFieldRef fieldRef = Scene.v().makeFieldRef(reflCallsClass, "classForName", RefType.v("java.util.Set"), true);
Local setLocal = localGen.generateLocal(RefType.v("java.util.Set"));
newUnits.add(Jimple.v().newAssignStmt(setLocal, Jimple.v().newStaticFieldRef(fieldRef)));
for (String className : RTI.classForNameClassNames(m)) {
InterfaceInvokeExpr invokeExpr = Jimple.v().newInterfaceInvokeExpr(setLocal, addMethodRef, StringConstant.v(callSiteId + className));
newUnits.add(Jimple.v().newInvokeStmt(invokeExpr));
}
callSiteId++;
}
}
{
if (!RTI.classNewInstanceClassNames(m).isEmpty()) {
SootFieldRef fieldRef = Scene.v().makeFieldRef(reflCallsClass, "classNewInstance", RefType.v("java.util.Set"), true);
Local setLocal = localGen.generateLocal(RefType.v("java.util.Set"));
newUnits.add(Jimple.v().newAssignStmt(setLocal, Jimple.v().newStaticFieldRef(fieldRef)));
for (String className : RTI.classNewInstanceClassNames(m)) {
InterfaceInvokeExpr invokeExpr = Jimple.v().newInterfaceInvokeExpr(setLocal, addMethodRef, StringConstant.v(callSiteId + className));
newUnits.add(Jimple.v().newInvokeStmt(invokeExpr));
}
callSiteId++;
}
}
{
if (!RTI.constructorNewInstanceSignatures(m).isEmpty()) {
SootFieldRef fieldRef = Scene.v().makeFieldRef(reflCallsClass, "constructorNewInstance", RefType.v("java.util.Set"), true);
Local setLocal = localGen.generateLocal(RefType.v("java.util.Set"));
newUnits.add(Jimple.v().newAssignStmt(setLocal, Jimple.v().newStaticFieldRef(fieldRef)));
for (String constrSig : RTI.constructorNewInstanceSignatures(m)) {
InterfaceInvokeExpr invokeExpr = Jimple.v().newInterfaceInvokeExpr(setLocal, addMethodRef, StringConstant.v(callSiteId + constrSig));
newUnits.add(Jimple.v().newInvokeStmt(invokeExpr));
}
callSiteId++;
}
}
{
if (!RTI.methodInvokeSignatures(m).isEmpty()) {
SootFieldRef fieldRef = Scene.v().makeFieldRef(reflCallsClass, "methodInvoke", RefType.v("java.util.Set"), true);
Local setLocal = localGen.generateLocal(RefType.v("java.util.Set"));
newUnits.add(Jimple.v().newAssignStmt(setLocal, Jimple.v().newStaticFieldRef(fieldRef)));
for (String methodSig : RTI.methodInvokeSignatures(m)) {
InterfaceInvokeExpr invokeExpr = Jimple.v().newInterfaceInvokeExpr(setLocal, addMethodRef, StringConstant.v(callSiteId + methodSig));
newUnits.add(Jimple.v().newInvokeStmt(invokeExpr));
}
callSiteId++;
}
}
}
Unit secondLastStmt = units.getPredOf(units.getLast());
units.insertAfter(newUnits, secondLastStmt);
if (Options.v().validate())
body.validate();
}
use of soot.util.HashChain in project soot by Sable.
the class ReflectiveCallsInliner method addCaching.
private void addCaching(Kind kind) {
SootClass c;
String methodName;
switch(kind) {
case ClassNewInstance:
c = Scene.v().getSootClass("java.lang.Class");
methodName = "knownClassNewInstance";
break;
case ConstructorNewInstance:
c = Scene.v().getSootClass("java.lang.reflect.Constructor");
methodName = "knownConstructorNewInstance";
break;
case MethodInvoke:
c = Scene.v().getSootClass("java.lang.reflect.Method");
methodName = "knownMethodInvoke";
break;
case ClassForName:
// to the String argument
return;
default:
throw new IllegalStateException("unknown kind: " + kind);
}
SootClass reflCallsClass = Scene.v().getSootClass("soot.rtlib.tamiflex.ReflectiveCalls");
SootMethod m = reflCallsClass.getMethodByName(methodName);
JimpleBody body = (JimpleBody) m.retrieveActiveBody();
LocalGenerator localGen = new LocalGenerator(body);
Unit firstStmt = body.getFirstNonIdentityStmt();
firstStmt = body.getUnits().getPredOf(firstStmt);
Stmt jumpTarget = Jimple.v().newNopStmt();
Chain<Unit> newUnits = new HashChain<Unit>();
// alreadyCheckedLocal = m.alreadyChecked
InstanceFieldRef fieldRef = Jimple.v().newInstanceFieldRef(body.getParameterLocal(m.getParameterCount() - 1), Scene.v().makeFieldRef(c, ALREADY_CHECKED_FIELDNAME, BooleanType.v(), false));
Local alreadyCheckedLocal = localGen.generateLocal(BooleanType.v());
newUnits.add(Jimple.v().newAssignStmt(alreadyCheckedLocal, fieldRef));
// if(!alreadyChecked) goto jumpTarget
newUnits.add(Jimple.v().newIfStmt(Jimple.v().newEqExpr(alreadyCheckedLocal, IntConstant.v(0)), jumpTarget));
// return
newUnits.add(Jimple.v().newReturnVoidStmt());
// jumpTarget: nop
newUnits.add(jumpTarget);
// m.alreadyChecked = true
InstanceFieldRef fieldRef2 = Jimple.v().newInstanceFieldRef(body.getParameterLocal(m.getParameterCount() - 1), Scene.v().makeFieldRef(c, ALREADY_CHECKED_FIELDNAME, BooleanType.v(), false));
newUnits.add(Jimple.v().newAssignStmt(fieldRef2, IntConstant.v(1)));
body.getUnits().insertAfter(newUnits, firstStmt);
if (Options.v().validate())
body.validate();
}
use of soot.util.HashChain in project soot by Sable.
the class ReflectiveCallsInliner method inlineRelectiveCalls.
private void inlineRelectiveCalls(SootMethod m, Set<String> targets, Kind callKind) {
if (!m.hasActiveBody())
m.retrieveActiveBody();
Body b = m.getActiveBody();
PatchingChain<Unit> units = b.getUnits();
Iterator<Unit> iter = units.snapshotIterator();
LocalGenerator localGen = new LocalGenerator(b);
// for all units
while (iter.hasNext()) {
Chain<Unit> newUnits = new HashChain<Unit>();
Stmt s = (Stmt) iter.next();
// reflective invoke expression
if (s.containsInvokeExpr()) {
InvokeExpr ie = s.getInvokeExpr();
boolean found = false;
Type fieldSetGetType = null;
if (callKind == Kind.ClassForName && (ie.getMethodRef().getSignature().equals("<java.lang.Class: java.lang.Class forName(java.lang.String)>") || ie.getMethodRef().getSignature().equals("<java.lang.Class: java.lang.Class forName(java.lang.String,boolean,java.lang.ClassLoader)>"))) {
found = true;
Value classNameValue = ie.getArg(0);
newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownClassForName(int,java.lang.String)>").makeRef(), IntConstant.v(callSiteId), classNameValue)));
} else if (callKind == Kind.ClassNewInstance && ie.getMethodRef().getSignature().equals("<java.lang.Class: java.lang.Object newInstance()>")) {
found = true;
Local classLocal = (Local) ((InstanceInvokeExpr) ie).getBase();
newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownClassNewInstance(int,java.lang.Class)>").makeRef(), IntConstant.v(callSiteId), classLocal)));
} else if (callKind == Kind.ConstructorNewInstance && ie.getMethodRef().getSignature().equals("<java.lang.reflect.Constructor: java.lang.Object newInstance(java.lang.Object[])>")) {
found = true;
Local constrLocal = (Local) ((InstanceInvokeExpr) ie).getBase();
newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownConstructorNewInstance(int,java.lang.reflect.Constructor)>").makeRef(), IntConstant.v(callSiteId), constrLocal)));
} else if (callKind == Kind.MethodInvoke && ie.getMethodRef().getSignature().equals("<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>")) {
found = true;
Local methodLocal = (Local) ((InstanceInvokeExpr) ie).getBase();
Value recv = ie.getArg(0);
newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownMethodInvoke(int,java.lang.Object,java.lang.reflect.Method)>").makeRef(), IntConstant.v(callSiteId), recv, methodLocal)));
} else if (callKind == Kind.FieldSet) {
SootMethod sootMethod = ie.getMethodRef().resolve();
if (sootMethod.getDeclaringClass().getName().equals("java.lang.reflect.Field") && fieldSets.contains(sootMethod.getName())) {
found = true;
// assign
fieldSetGetType = sootMethod.getParameterType(1);
// type
// of
// 2nd
// parameter
// (1st
// is
// receiver
// object)
Value recv = ie.getArg(0);
Value field = ((InstanceInvokeExpr) ie).getBase();
newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownFieldSet(int,java.lang.Object,java.lang.reflect.Field)>").makeRef(), IntConstant.v(callSiteId), recv, field)));
}
} else if (callKind == Kind.FieldGet) {
SootMethod sootMethod = ie.getMethodRef().resolve();
if (sootMethod.getDeclaringClass().getName().equals("java.lang.reflect.Field") && fieldGets.contains(sootMethod.getName())) {
found = true;
// assign
fieldSetGetType = sootMethod.getReturnType();
// return
// type
// of
// get
Value recv = ie.getArg(0);
Value field = ((InstanceInvokeExpr) ie).getBase();
newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownFieldSet(int,java.lang.Object,java.lang.reflect.Field)>").makeRef(), IntConstant.v(callSiteId), recv, field)));
}
}
if (!found)
continue;
NopStmt endLabel = Jimple.v().newNopStmt();
// for all recorded targets
for (String target : targets) {
NopStmt jumpTarget = Jimple.v().newNopStmt();
// boolean predLocal = Opaque.getFalse();
Local predLocal = localGen.generateLocal(BooleanType.v());
StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(UNINTERPRETED_METHOD);
newUnits.add(Jimple.v().newAssignStmt(predLocal, staticInvokeExpr));
// if predLocal == 0 goto <original reflective call>
newUnits.add(Jimple.v().newIfStmt(Jimple.v().newEqExpr(IntConstant.v(0), predLocal), jumpTarget));
SootMethod newMethod = createNewMethod(callKind, target, fieldSetGetType);
List<Value> args = new LinkedList<Value>();
switch(callKind) {
case ClassForName:
case ClassNewInstance:
// no arguments
break;
case ConstructorNewInstance:
// add Object[] argument
args.add((Value) ie.getArgs().get(0));
break;
case MethodInvoke:
// add Object argument
args.add((Value) ie.getArgs().get(0));
// add Object[] argument
args.add((Value) ie.getArgs().get(1));
break;
case FieldSet:
// add Object argument
args.add((Value) ie.getArgs().get(0));
// add value argument
args.add((Value) ie.getArgs().get(1));
break;
case FieldGet:
// add Object argument
args.add((Value) ie.getArgs().get(0));
break;
default:
throw new IllegalStateException();
}
StaticInvokeExpr methodInvokeExpr = Jimple.v().newStaticInvokeExpr(newMethod.makeRef(), args);
Local retLocal = localGen.generateLocal(newMethod.getReturnType());
newUnits.add(Jimple.v().newAssignStmt(retLocal, methodInvokeExpr));
if (s instanceof AssignStmt) {
AssignStmt assignStmt = (AssignStmt) s;
Value leftOp = assignStmt.getLeftOp();
AssignStmt newAssignStmt = Jimple.v().newAssignStmt(leftOp, retLocal);
newUnits.add(newAssignStmt);
}
GotoStmt gotoStmt = Jimple.v().newGotoStmt(endLabel);
newUnits.add(gotoStmt);
newUnits.add(jumpTarget);
}
Unit end = newUnits.getLast();
units.insertAfter(newUnits, s);
units.remove(s);
units.insertAfter(s, end);
units.insertAfter(endLabel, s);
}
}
callSiteId++;
}
Aggregations