Search in sources :

Example 36 with Body

use of soot.Body in project soot by Sable.

the class AccessManager method createAccessorMethod.

/**
 * Turns a field access or method call into a call to an accessor method.
 * Reuses existing accessors based on name mangling (see createAccessorName)
 *
 * @param container
 * @param stmt
 */
public static void createAccessorMethod(SootMethod container, Stmt stmt) {
    // System.out.println("Creating accessor method: \n" +
    // " method: " + container + " \n" +
    // " stmt: " + stmt);
    Body containerBody = container.getActiveBody();
    soot.util.Chain containerStmts = containerBody.getUnits();
    if (!containerStmts.contains(stmt))
        throw new RuntimeException();
    if (stmt.containsInvokeExpr()) {
        createInvokeAccessor(container, stmt);
    } else if (stmt instanceof AssignStmt) {
        AssignStmt as = (AssignStmt) stmt;
        FieldRef ref;
        if (as.getLeftOp() instanceof FieldRef) {
            // set
            ref = (FieldRef) as.getLeftOp();
            createSetAccessor(container, as, ref);
        } else if (as.getRightOp() instanceof FieldRef) {
            // get
            ref = (FieldRef) as.getRightOp();
            createGetAccessor(container, as, ref);
        } else {
            throw new RuntimeException("Expected class member access");
        }
    } else
        throw new RuntimeException("Expected class member access");
}
Also used : FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) AssignStmt(soot.jimple.AssignStmt) Body(soot.Body)

Example 37 with Body

use of soot.Body in project soot by Sable.

the class AccessManager method createInvokeAccessor.

private static void createInvokeAccessor(SootMethod container, Stmt stmt) {
    java.util.List parameterTypes = new LinkedList();
    java.util.List<SootClass> thrownExceptions = new LinkedList<SootClass>();
    Type returnType;
    Body accessorBody = Jimple.v().newBody();
    soot.util.Chain accStmts = accessorBody.getUnits();
    LocalGenerator lg = new LocalGenerator(accessorBody);
    Body containerBody = container.getActiveBody();
    soot.util.Chain containerStmts = containerBody.getUnits();
    InvokeExpr expr = stmt.getInvokeExpr();
    SootMethod method = expr.getMethod();
    // System.out.println("method: " + method);
    SootClass target = method.getDeclaringClass();
    // System.out.println("target: " + target);
    // System.out.println("method ref: " + expr.getMethodRef());
    SootMethod accessor;
    String name = createAccessorName(method, true);
    accessor = target.getMethodByNameUnsafe(name);
    if (accessor == null) {
        java.util.List arguments = new LinkedList();
        if (expr instanceof InstanceInvokeExpr) {
            parameterTypes.add(target.getType());
        }
        parameterTypes.addAll(method.getParameterTypes());
        returnType = method.getReturnType();
        thrownExceptions.addAll(method.getExceptions());
        int paramID = 0;
        for (java.util.Iterator it = parameterTypes.iterator(); it.hasNext(); ) {
            Type type = (Type) it.next();
            Local l = lg.generateLocal(type);
            // System.out.println("local type: " + type);
            accStmts.add(Jimple.v().newIdentityStmt(l, Jimple.v().newParameterRef(type, paramID)));
            arguments.add(l);
            paramID++;
        }
        InvokeExpr accExpr;
        if (expr instanceof StaticInvokeExpr) {
            accExpr = Jimple.v().newStaticInvokeExpr(method.makeRef(), arguments);
        } else if (expr instanceof VirtualInvokeExpr) {
            Local thisLocal = (Local) arguments.get(0);
            arguments.remove(0);
            accExpr = Jimple.v().newVirtualInvokeExpr(thisLocal, method.makeRef(), arguments);
        } else if (expr instanceof SpecialInvokeExpr) {
            Local thisLocal = (Local) arguments.get(0);
            arguments.remove(0);
            accExpr = Jimple.v().newSpecialInvokeExpr(thisLocal, method.makeRef(), arguments);
        } else
            throw new RuntimeException("");
        Stmt s;
        if (returnType instanceof VoidType) {
            s = Jimple.v().newInvokeStmt(accExpr);
            accStmts.add(s);
            accStmts.add(Jimple.v().newReturnVoidStmt());
        } else {
            Local resultLocal = lg.generateLocal(returnType);
            s = Jimple.v().newAssignStmt(resultLocal, accExpr);
            accStmts.add(s);
            accStmts.add(Jimple.v().newReturnStmt(resultLocal));
        }
        accessor = Scene.v().makeSootMethod(name, parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC, thrownExceptions);
        accessorBody.setMethod(accessor);
        accessor.setActiveBody(accessorBody);
        target.addMethod(accessor);
    }
    java.util.List args = new LinkedList();
    if (expr instanceof InstanceInvokeExpr) {
        args.add(((InstanceInvokeExpr) expr).getBase());
    }
    args.addAll(expr.getArgs());
    InvokeExpr newExpr = Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
    stmt.getInvokeExprBox().setValue(newExpr);
}
Also used : VoidType(soot.VoidType) LocalGenerator(soot.javaToJimple.LocalGenerator) Iterator(java.util.Iterator) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) Type(soot.Type) VoidType(soot.VoidType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) SootMethod(soot.SootMethod) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) Body(soot.Body)

Example 38 with Body

use of soot.Body in project soot by Sable.

the class AccessManager method createSetAccessor.

private static void createSetAccessor(SootMethod container, AssignStmt as, FieldRef ref) {
    java.util.List parameterTypes = new LinkedList();
    java.util.List<SootClass> thrownExceptions = new LinkedList<SootClass>();
    Body accessorBody = Jimple.v().newBody();
    soot.util.Chain accStmts = accessorBody.getUnits();
    LocalGenerator lg = new LocalGenerator(accessorBody);
    Body containerBody = container.getActiveBody();
    soot.util.Chain containerStmts = containerBody.getUnits();
    SootClass target = ref.getField().getDeclaringClass();
    SootMethod accessor;
    String name = createAccessorName(ref.getField(), true);
    accessor = target.getMethodByNameUnsafe(name);
    if (accessor == null) {
        Local thisLocal = lg.generateLocal(target.getType());
        int paramID = 0;
        if (ref instanceof InstanceFieldRef) {
            accStmts.add(Jimple.v().newIdentityStmt(thisLocal, Jimple.v().newParameterRef(target.getType(), paramID)));
            parameterTypes.add(target.getType());
            paramID++;
        }
        parameterTypes.add(ref.getField().getType());
        Local l = lg.generateLocal(ref.getField().getType());
        accStmts.add(Jimple.v().newIdentityStmt(l, Jimple.v().newParameterRef(ref.getField().getType(), paramID)));
        paramID++;
        if (ref instanceof InstanceFieldRef) {
            accStmts.add(Jimple.v().newAssignStmt(Jimple.v().newInstanceFieldRef(thisLocal, ref.getFieldRef()), l));
        } else {
            accStmts.add(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(ref.getFieldRef()), l));
        }
        accStmts.addLast(Jimple.v().newReturnVoidStmt());
        Type returnType = VoidType.v();
        accessor = Scene.v().makeSootMethod(name, parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC, thrownExceptions);
        accessorBody.setMethod(accessor);
        accessor.setActiveBody(accessorBody);
        target.addMethod(accessor);
    }
    java.util.List args = new LinkedList();
    if (ref instanceof InstanceFieldRef) {
        args.add(((InstanceFieldRef) ref).getBase());
    }
    args.add(as.getRightOp());
    InvokeExpr newExpr = Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
    Stmt newStmt = Jimple.v().newInvokeStmt(newExpr);
    containerStmts.insertAfter(newStmt, as);
    containerStmts.remove(as);
}
Also used : LocalGenerator(soot.javaToJimple.LocalGenerator) Local(soot.Local) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) Type(soot.Type) VoidType(soot.VoidType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) InstanceFieldRef(soot.jimple.InstanceFieldRef) SootMethod(soot.SootMethod) Body(soot.Body)

Example 39 with Body

use of soot.Body in project soot by Sable.

the class SiteInliner method inlineSite.

/**
 *        Inlines the given site.  Note that this method does
 *        not actually check if it's safe (with respect to access modifiers and special invokes)
 *        for it to be inlined.  That functionality is handled by the InlinerSafetyManager.
 */
public static List inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container, Map options) {
    boolean enableNullPointerCheckInsertion = PhaseOptions.getBoolean(options, "insert-null-checks");
    boolean enableRedundantCastInsertion = PhaseOptions.getBoolean(options, "insert-redundant-casts");
    Hierarchy hierarchy = Scene.v().getActiveHierarchy();
    JimpleBody containerB = (JimpleBody) container.getActiveBody();
    Chain<Unit> containerUnits = containerB.getUnits();
    if (!(inlinee.getDeclaringClass().isApplicationClass() || inlinee.getDeclaringClass().isLibraryClass()))
        return null;
    Body inlineeB = inlinee.getActiveBody();
    Chain<Unit> inlineeUnits = inlineeB.getUnits();
    InvokeExpr ie = toInline.getInvokeExpr();
    Value thisToAdd = null;
    if (ie instanceof InstanceInvokeExpr)
        thisToAdd = ((InstanceInvokeExpr) ie).getBase();
    // Insert casts to please the verifier.
    {
        boolean targetUsesThis = true;
        if (enableRedundantCastInsertion && ie instanceof InstanceInvokeExpr && targetUsesThis) {
            // The verifier will complain if targetUsesThis, and:
            // the argument passed to the method is not the same type.
            // For instance, Bottle.price_static takes a cost.
            // Cost is an interface implemented by Bottle.
            SootClass localType, parameterType;
            localType = ((RefType) ((InstanceInvokeExpr) ie).getBase().getType()).getSootClass();
            parameterType = inlinee.getDeclaringClass();
            if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
                Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
                containerB.getLocals().add(castee);
                containerB.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), toInline);
                thisToAdd = castee;
            }
        }
    }
    // (If enabled), add a null pointer check.
    {
        if (enableNullPointerCheckInsertion && ie instanceof InstanceInvokeExpr) {
            boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB);
            /* Ah ha.  Caught again! */
            if (caught) {
                /* In this case, we don't use throwPoint;
                     * instead, put the code right there. */
                Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), toInline);
                containerB.getUnits().insertBefore(insertee, toInline);
                // This sucks (but less than before).
                ((IfStmt) insertee).setTarget(toInline);
                ThrowManager.addThrowAfter(containerB, insertee);
            } else {
                Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(containerB);
                containerB.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), toInline);
            }
        }
    }
    // Add synchronizing stuff.
    {
        if (inlinee.isSynchronized()) {
            // Need to get the class object if ie is a static invoke.
            if (ie instanceof InstanceInvokeExpr)
                SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, (Local) ((InstanceInvokeExpr) ie).getBase());
            else {
                // synchronization.
                if (!container.getDeclaringClass().isInterface()) {
                    // Whew!
                    Local l = SynchronizerManager.v().addStmtsToFetchClassBefore(containerB, toInline);
                    SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, l);
                }
            }
        }
    }
    Stmt exitPoint = (Stmt) containerUnits.getSuccOf(toInline);
    // First, clone all of the inlinee's units & locals.
    HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
    HashMap<Stmt, Stmt> oldUnitsToNew = new HashMap<Stmt, Stmt>();
    {
        Stmt cursor = toInline;
        for (Iterator<Unit> currIt = inlineeUnits.iterator(); currIt.hasNext(); ) {
            final Stmt curr = (Stmt) currIt.next();
            Stmt currPrime = (Stmt) curr.clone();
            if (currPrime == null)
                throw new RuntimeException("getting null from clone!");
            currPrime.addAllTagsOf(curr);
            containerUnits.insertAfter(currPrime, cursor);
            cursor = currPrime;
            oldUnitsToNew.put(curr, currPrime);
        }
        for (Iterator<Local> lIt = inlineeB.getLocals().iterator(); lIt.hasNext(); ) {
            final Local l = lIt.next();
            Local lPrime = (Local) l.clone();
            if (lPrime == null)
                throw new RuntimeException("getting null from local clone!");
            containerB.getLocals().add(lPrime);
            oldLocalsToNew.put(l, lPrime);
        }
    }
    // Backpatch the newly-inserted units using newly-constructed maps.
    {
        Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
        while (it.hasNext()) {
            Stmt patchee = (Stmt) it.next();
            for (ValueBox box : patchee.getUseAndDefBoxes()) {
                if (!(box.getValue() instanceof Local))
                    continue;
                Local lPrime = oldLocalsToNew.get(box.getValue());
                if (lPrime != null)
                    box.setValue(lPrime);
                else
                    throw new RuntimeException("local has no clone!");
            }
            for (UnitBox box : patchee.getUnitBoxes()) {
                Unit uPrime = (oldUnitsToNew.get(box.getUnit()));
                if (uPrime != null)
                    box.setUnit(uPrime);
                else
                    throw new RuntimeException("inlined stmt has no clone!");
            }
        }
    }
    // Copy & backpatch the traps; preserve their same order.
    {
        Trap prevTrap = null;
        for (Trap t : inlineeB.getTraps()) {
            Stmt newBegin = oldUnitsToNew.get(t.getBeginUnit()), newEnd = oldUnitsToNew.get(t.getEndUnit()), newHandler = oldUnitsToNew.get(t.getHandlerUnit());
            if (newBegin == null || newEnd == null || newHandler == null)
                throw new RuntimeException("couldn't map trap!");
            Trap trap = Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler);
            if (prevTrap == null)
                containerB.getTraps().addFirst(trap);
            else
                containerB.getTraps().insertAfter(trap, prevTrap);
            prevTrap = trap;
        }
    }
    // Handle identity stmt's and returns.
    {
        Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
        ArrayList<Unit> cuCopy = new ArrayList<Unit>();
        while (it.hasNext()) {
            cuCopy.add(it.next());
        }
        for (Unit u : cuCopy) {
            Stmt s = (Stmt) u;
            if (s instanceof IdentityStmt) {
                IdentityRef rhs = (IdentityRef) ((IdentityStmt) s).getRightOp();
                if (rhs instanceof CaughtExceptionRef)
                    continue;
                else if (rhs instanceof ThisRef) {
                    if (!(ie instanceof InstanceInvokeExpr))
                        throw new RuntimeException("thisref with no receiver!");
                    containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), thisToAdd));
                } else if (rhs instanceof ParameterRef) {
                    ParameterRef pref = (ParameterRef) rhs;
                    containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), ie.getArg(pref.getIndex())));
                }
            } else if (s instanceof ReturnStmt) {
                if (toInline instanceof InvokeStmt) {
                    // munch, munch.
                    containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
                    continue;
                }
                if (!(toInline instanceof AssignStmt))
                    throw new RuntimeException("invoking stmt neither InvokeStmt nor AssignStmt!??!?!");
                Value ro = ((ReturnStmt) s).getOp();
                Value lhs = ((AssignStmt) toInline).getLeftOp();
                AssignStmt as = Jimple.v().newAssignStmt(lhs, ro);
                containerUnits.insertBefore(as, s);
                containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
            } else if (s instanceof ReturnVoidStmt)
                containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
        }
    }
    List<Unit> newStmts = new ArrayList<Unit>();
    for (Iterator<Unit> i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext(); ) {
        newStmts.add(i.next());
    }
    // Remove the original statement toInline.
    containerUnits.remove(toInline);
    // Resolve name collisions.
    LocalNameStandardizer.v().transform(containerB, "ji.lns");
    return newStmts;
}
Also used : CaughtExceptionRef(soot.jimple.CaughtExceptionRef) InvokeStmt(soot.jimple.InvokeStmt) HashMap(java.util.HashMap) AssignStmt(soot.jimple.AssignStmt) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) ArrayList(java.util.ArrayList) Unit(soot.Unit) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) InvokeStmt(soot.jimple.InvokeStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) RefType(soot.RefType) Hierarchy(soot.Hierarchy) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) IdentityRef(soot.jimple.IdentityRef) Iterator(java.util.Iterator) JimpleBody(soot.jimple.JimpleBody) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody) IdentityStmt(soot.jimple.IdentityStmt) UnitBox(soot.UnitBox) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) Trap(soot.Trap) SootClass(soot.SootClass) ParameterRef(soot.jimple.ParameterRef) ThisRef(soot.jimple.ThisRef) ValueBox(soot.ValueBox) Value(soot.Value) ReturnStmt(soot.jimple.ReturnStmt)

Example 40 with Body

use of soot.Body in project soot by Sable.

the class OnFlyCallGraphBuilder method processNewMethod.

private void processNewMethod(SootMethod m) {
    if (m.isNative() || m.isPhantom()) {
        return;
    }
    Body b = m.retrieveActiveBody();
    getImplicitTargets(m);
    findReceivers(m, b);
}
Also used : Body(soot.Body)

Aggregations

Body (soot.Body)57 Unit (soot.Unit)37 SootMethod (soot.SootMethod)32 Local (soot.Local)20 SootClass (soot.SootClass)19 Value (soot.Value)15 InvokeExpr (soot.jimple.InvokeExpr)14 StaticInvokeExpr (soot.jimple.StaticInvokeExpr)13 Type (soot.Type)12 Stmt (soot.jimple.Stmt)12 InstanceInvokeExpr (soot.jimple.InstanceInvokeExpr)11 JimpleBody (soot.jimple.JimpleBody)11 SpecialInvokeExpr (soot.jimple.SpecialInvokeExpr)11 RefType (soot.RefType)10 VoidType (soot.VoidType)10 VirtualInvokeExpr (soot.jimple.VirtualInvokeExpr)10 LinkedList (java.util.LinkedList)9 SootMethodRef (soot.SootMethodRef)9 ArrayList (java.util.ArrayList)8 PrimType (soot.PrimType)8