use of soot.jimple.GotoStmt in project soot by Sable.
the class DexReturnInliner method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
Set<Unit> duplicateIfTargets = getFallThroughReturns(body);
Iterator<Unit> it = body.getUnits().snapshotIterator();
boolean mayBeMore = false;
Unit last = null;
do {
mayBeMore = false;
while (it.hasNext()) {
Unit u = it.next();
if (u instanceof GotoStmt) {
GotoStmt gtStmt = (GotoStmt) u;
if (isInstanceofReturn(gtStmt.getTarget())) {
Stmt stmt = (Stmt) gtStmt.getTarget().clone();
for (Trap t : body.getTraps()) for (UnitBox ubox : t.getUnitBoxes()) if (ubox.getUnit() == u)
ubox.setUnit(stmt);
while (!u.getBoxesPointingToThis().isEmpty()) u.getBoxesPointingToThis().get(0).setUnit(stmt);
// the cloned return stmt gets the tags of u
stmt.addAllTagsOf(u);
body.getUnits().swapWith(u, stmt);
mayBeMore = true;
}
} else if (u instanceof IfStmt) {
IfStmt ifstmt = (IfStmt) u;
Unit t = ifstmt.getTarget();
if (isInstanceofReturn(t)) {
// once, otherwise we will end up with unused copies
if (duplicateIfTargets == null)
duplicateIfTargets = new HashSet<Unit>();
if (!duplicateIfTargets.add(t)) {
Unit newTarget = (Unit) t.clone();
body.getUnits().addLast(newTarget);
ifstmt.setTarget(newTarget);
}
}
} else if (isInstanceofReturn(u)) {
// the original return stmt gets the tags of its predecessor
if (last != null) {
u.removeAllTags();
u.addAllTagsOf(last);
}
}
last = u;
}
} while (mayBeMore);
}
use of soot.jimple.GotoStmt in project soot by Sable.
the class ThisInliner method internalTransform.
public void internalTransform(Body b, String phaseName, Map options) {
// assure body is a constructor
if (!b.getMethod().getName().equals("<init>"))
return;
// if the first invoke is a this() and not a super() inline the this()
InvokeStmt invokeStmt = getFirstSpecialInvoke(b);
if (invokeStmt == null)
return;
SpecialInvokeExpr specInvokeExpr = (SpecialInvokeExpr) invokeStmt.getInvokeExpr();
if (specInvokeExpr.getMethod().getDeclaringClass().equals(b.getMethod().getDeclaringClass())) {
// put locals from inlinee into container
if (!specInvokeExpr.getMethod().hasActiveBody()) {
specInvokeExpr.getMethod().retrieveActiveBody();
}
HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
for (Local l : specInvokeExpr.getMethod().getActiveBody().getLocals()) {
Local newLocal = (Local) l.clone();
b.getLocals().add(newLocal);
oldLocalsToNew.put(l, newLocal);
}
// find identity stmt of original method
IdentityStmt origIdStmt = findIdentityStmt(b);
HashMap<Stmt, Stmt> oldStmtsToNew = new HashMap<Stmt, Stmt>();
// System.out.println("locals: "+b.getLocals());
Chain<Unit> containerUnits = b.getUnits();
for (Unit u : specInvokeExpr.getMethod().getActiveBody().getUnits()) {
Stmt inlineeStmt = (Stmt) u;
// handle identity stmts
if (inlineeStmt instanceof IdentityStmt) {
IdentityStmt idStmt = (IdentityStmt) inlineeStmt;
if (idStmt.getRightOp() instanceof ThisRef) {
Stmt newThis = Jimple.v().newAssignStmt((Local) oldLocalsToNew.get(idStmt.getLeftOp()), origIdStmt.getLeftOp());
containerUnits.insertBefore(newThis, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newThis);
} else if (idStmt.getRightOp() instanceof CaughtExceptionRef) {
Stmt newInlinee = (Stmt) inlineeStmt.clone();
for (ValueBox next : newInlinee.getUseAndDefBoxes()) {
if (next.getValue() instanceof Local) {
next.setValue((Local) oldLocalsToNew.get(next.getValue()));
}
}
containerUnits.insertBefore(newInlinee, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newInlinee);
} else if (idStmt.getRightOp() instanceof ParameterRef) {
Stmt newParam = Jimple.v().newAssignStmt((Local) oldLocalsToNew.get(idStmt.getLeftOp()), specInvokeExpr.getArg(((ParameterRef) idStmt.getRightOp()).getIndex()));
containerUnits.insertBefore(newParam, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newParam);
}
} else // from a constructor)
if (inlineeStmt instanceof ReturnVoidStmt) {
Stmt newRet = Jimple.v().newGotoStmt((Stmt) containerUnits.getSuccOf(invokeStmt));
containerUnits.insertBefore(newRet, invokeStmt);
System.out.println("adding to stmt map: " + inlineeStmt + " and " + newRet);
oldStmtsToNew.put(inlineeStmt, newRet);
} else {
Stmt newInlinee = (Stmt) inlineeStmt.clone();
for (ValueBox next : newInlinee.getUseAndDefBoxes()) {
if (next.getValue() instanceof Local) {
next.setValue((Local) oldLocalsToNew.get(next.getValue()));
}
}
containerUnits.insertBefore(newInlinee, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newInlinee);
}
}
// handleTraps
for (Trap t : specInvokeExpr.getMethod().getActiveBody().getTraps()) {
System.out.println("begin: " + t.getBeginUnit());
Stmt newBegin = oldStmtsToNew.get(t.getBeginUnit());
System.out.println("end: " + t.getEndUnit());
Stmt newEnd = oldStmtsToNew.get(t.getEndUnit());
System.out.println("handler: " + t.getHandlerUnit());
Stmt newHandler = oldStmtsToNew.get(t.getHandlerUnit());
if (newBegin == null || newEnd == null || newHandler == null)
throw new RuntimeException("couldn't map trap!");
b.getTraps().add(Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler));
}
// patch gotos
for (Unit u : specInvokeExpr.getMethod().getActiveBody().getUnits()) {
Stmt inlineeStmt = (Stmt) u;
if (inlineeStmt instanceof GotoStmt) {
System.out.println("inlinee goto target: " + ((GotoStmt) inlineeStmt).getTarget());
((GotoStmt) oldStmtsToNew.get(inlineeStmt)).setTarget(oldStmtsToNew.get(((GotoStmt) inlineeStmt).getTarget()));
}
}
// remove original invoke
containerUnits.remove(invokeStmt);
// resolve name collisions
LocalNameStandardizer.v().transform(b, "ji.lns");
}
// System.out.println("locals: "+b.getLocals());
// System.out.println("units: "+b.getUnits());
}
use of soot.jimple.GotoStmt 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++;
}
use of soot.jimple.GotoStmt in project soot by Sable.
the class StmtVisitor method caseGotoStmt.
@Override
public void caseGotoStmt(GotoStmt stmt) {
Stmt target = (Stmt) stmt.getTarget();
addInsn(buildGotoInsn(target), stmt);
}
use of soot.jimple.GotoStmt in project soot by Sable.
the class CastAndReturnInliner method internalTransform.
@Override
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
Iterator<Unit> it = body.getUnits().snapshotIterator();
while (it.hasNext()) {
Unit u = it.next();
if (u instanceof GotoStmt) {
GotoStmt gtStmt = (GotoStmt) u;
if (gtStmt.getTarget() instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) gtStmt.getTarget();
if (assign.getRightOp() instanceof CastExpr) {
CastExpr ce = (CastExpr) assign.getRightOp();
// We have goto that ends up at a cast statement
Unit nextStmt = body.getUnits().getSuccOf(assign);
if (nextStmt instanceof ReturnStmt) {
ReturnStmt retStmt = (ReturnStmt) nextStmt;
if (retStmt.getOp() == assign.getLeftOp()) {
// We need to replace the GOTO with the return
ReturnStmt newStmt = (ReturnStmt) retStmt.clone();
newStmt.setOp(ce.getOp());
for (Trap t : body.getTraps()) for (UnitBox ubox : t.getUnitBoxes()) if (ubox.getUnit() == gtStmt)
ubox.setUnit(newStmt);
while (!gtStmt.getBoxesPointingToThis().isEmpty()) gtStmt.getBoxesPointingToThis().get(0).setUnit(newStmt);
body.getUnits().swapWith(gtStmt, newStmt);
}
}
}
}
}
}
}
Aggregations