Search in sources :

Example 6 with GotoStmt

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);
}
Also used : UnitBox(soot.UnitBox) IfStmt(soot.jimple.IfStmt) GotoStmt(soot.jimple.GotoStmt) Trap(soot.Trap) Unit(soot.Unit) GotoStmt(soot.jimple.GotoStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) IfStmt(soot.jimple.IfStmt)

Example 7 with GotoStmt

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());
}
Also used : InvokeStmt(soot.jimple.InvokeStmt) CaughtExceptionRef(soot.jimple.CaughtExceptionRef) HashMap(java.util.HashMap) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) Local(soot.Local) Trap(soot.Trap) Unit(soot.Unit) GotoStmt(soot.jimple.GotoStmt) Stmt(soot.jimple.Stmt) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) InvokeStmt(soot.jimple.InvokeStmt) IdentityStmt(soot.jimple.IdentityStmt) ParameterRef(soot.jimple.ParameterRef) ThisRef(soot.jimple.ThisRef) ValueBox(soot.ValueBox) GotoStmt(soot.jimple.GotoStmt) IdentityStmt(soot.jimple.IdentityStmt)

Example 8 with GotoStmt

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++;
}
Also used : LocalGenerator(soot.javaToJimple.LocalGenerator) HashChain(soot.util.HashChain) AssignStmt(soot.jimple.AssignStmt) Local(soot.Local) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Unit(soot.Unit) LinkedList(java.util.LinkedList) InvokeStmt(soot.jimple.InvokeStmt) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) AssignStmt(soot.jimple.AssignStmt) Stmt(soot.jimple.Stmt) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) RefType(soot.RefType) BooleanType(soot.BooleanType) Type(soot.Type) RefLikeType(soot.RefLikeType) ArrayType(soot.ArrayType) PrimType(soot.PrimType) VoidType(soot.VoidType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) Value(soot.Value) SootMethod(soot.SootMethod) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody)

Example 9 with GotoStmt

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);
}
Also used : BreakpointStmt(soot.jimple.BreakpointStmt) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) InvokeStmt(soot.jimple.InvokeStmt) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) RetStmt(soot.jimple.RetStmt) AssignStmt(soot.jimple.AssignStmt) ThrowStmt(soot.jimple.ThrowStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) TableSwitchStmt(soot.jimple.TableSwitchStmt) MonitorStmt(soot.jimple.MonitorStmt) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) ReturnStmt(soot.jimple.ReturnStmt) ExitMonitorStmt(soot.jimple.ExitMonitorStmt) Stmt(soot.jimple.Stmt)

Example 10 with GotoStmt

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);
                        }
                    }
                }
            }
        }
    }
}
Also used : UnitBox(soot.UnitBox) AssignStmt(soot.jimple.AssignStmt) GotoStmt(soot.jimple.GotoStmt) CastExpr(soot.jimple.CastExpr) Trap(soot.Trap) Unit(soot.Unit) ReturnStmt(soot.jimple.ReturnStmt)

Aggregations

GotoStmt (soot.jimple.GotoStmt)13 Unit (soot.Unit)10 IfStmt (soot.jimple.IfStmt)7 IdentityStmt (soot.jimple.IdentityStmt)6 InvokeStmt (soot.jimple.InvokeStmt)6 ReturnStmt (soot.jimple.ReturnStmt)6 ReturnVoidStmt (soot.jimple.ReturnVoidStmt)6 LookupSwitchStmt (soot.jimple.LookupSwitchStmt)5 NopStmt (soot.jimple.NopStmt)5 Stmt (soot.jimple.Stmt)5 TableSwitchStmt (soot.jimple.TableSwitchStmt)5 Local (soot.Local)4 PrimType (soot.PrimType)4 AssignStmt (soot.jimple.AssignStmt)4 EnterMonitorStmt (soot.jimple.EnterMonitorStmt)4 ExitMonitorStmt (soot.jimple.ExitMonitorStmt)4 InstanceInvokeExpr (soot.jimple.InstanceInvokeExpr)4 InvokeExpr (soot.jimple.InvokeExpr)4 StaticInvokeExpr (soot.jimple.StaticInvokeExpr)4 ThrowStmt (soot.jimple.ThrowStmt)4