Search in sources :

Example 11 with JimpleBody

use of soot.jimple.JimpleBody in project soot by Sable.

the class TypeDecl method jimplify2clinit.

/**
 * @ast method
 * @aspect EmitJimple
 * @declaredat /Users/eric/Documents/workspaces/clara-soot/JastAddExtensions/JimpleBackend/EmitJimple.jrag:903
 */
public void jimplify2clinit() {
    SootMethod m = clinit;
    JimpleBody body = Jimple.v().newBody(m);
    m.setActiveBody(body);
    Body b = new Body(this, body, this);
    for (int i = 0; i < getNumBodyDecl(); i++) {
        BodyDecl bodyDecl = getBodyDecl(i);
        if (bodyDecl instanceof FieldDeclaration && bodyDecl.generate()) {
            FieldDeclaration f = (FieldDeclaration) bodyDecl;
            if (f.isStatic() && f.hasInit()) {
                Local l = asLocal(// AssignConversion
                b, // AssignConversion
                f.getInit().type().emitCastTo(b, f.getInit(), f.type()), f.type().getSootType());
                b.setLine(f);
                b.add(b.newAssignStmt(b.newStaticFieldRef(f.sootRef(), f), l, f));
            }
        } else if (bodyDecl instanceof StaticInitializer && bodyDecl.generate()) {
            bodyDecl.jimplify2(b);
        }
    }
    b.add(b.newReturnVoidStmt(null));
}
Also used : SootMethod(soot.SootMethod) Local(soot.Local) JimpleBody(soot.jimple.JimpleBody) JimpleBody(soot.jimple.JimpleBody)

Example 12 with JimpleBody

use of soot.jimple.JimpleBody in project soot by Sable.

the class SynchronizerManager method createClassFetcherFor.

/**
 * Creates a method which calls java.lang.Class.forName(String).
 *
 * The method should look like the following:
 *
 * <pre>
 *	         .static java.lang.Class class$(java.lang.String)
 *	         {
 *	             java.lang.String r0, $r5;
 *	             java.lang.ClassNotFoundException r1, $r3;
 *	             java.lang.Class $r2;
 *	             java.lang.NoClassDefFoundError $r4;
 *
 *	             r0 := @parameter0: java.lang.String;
 *
 *	         label0:
 *	             $r2 = .staticinvoke <java.lang.Class: java.lang.Class forName(java.lang.String)>(r0);
 *	             .return $r2;
 *
 *	         label1:
 *	             $r3 := @caughtexception;
 *	             r1 = $r3;
 *	             $r4 = .new java.lang.NoClassDefFoundError;
 *	             $r5 = .virtualinvoke r1.<java.lang.Throwable: java.lang.String getMessage()>();
 *	             .specialinvoke $r4.<java.lang.NoClassDefFoundError: .void <init>(java.lang.String)>($r5);
 *	             .throw $r4;
 *
 *	             .catch java.lang.ClassNotFoundException .from label0 .to label1 .with label1;
 *	         }
 * </pre>
 */
public SootMethod createClassFetcherFor(SootClass c, String methodName) {
    // Create the method
    SootMethod method = Scene.v().makeSootMethod(methodName, Arrays.asList(new Type[] { RefType.v("java.lang.String") }), RefType.v("java.lang.Class"), Modifier.STATIC);
    c.addMethod(method);
    // Create the method body
    {
        JimpleBody body = Jimple.v().newBody(method);
        method.setActiveBody(body);
        Chain units = body.getUnits();
        Local l_r0, l_r1, l_r2, l_r3, l_r4, l_r5;
        // Add some locals
        l_r0 = Jimple.v().newLocal("r0", RefType.v("java.lang.String"));
        l_r1 = Jimple.v().newLocal("r1", RefType.v("java.lang.ClassNotFoundException"));
        l_r2 = Jimple.v().newLocal("$r2", RefType.v("java.lang.Class"));
        l_r3 = Jimple.v().newLocal("$r3", RefType.v("java.lang.ClassNotFoundException"));
        l_r4 = Jimple.v().newLocal("$r4", RefType.v("java.lang.NoClassDefFoundError"));
        l_r5 = Jimple.v().newLocal("$r5", RefType.v("java.lang.String"));
        body.getLocals().add(l_r0);
        body.getLocals().add(l_r1);
        body.getLocals().add(l_r2);
        body.getLocals().add(l_r3);
        body.getLocals().add(l_r4);
        body.getLocals().add(l_r5);
        // add "r0 := @parameter0: java.lang.String"
        units.add(Jimple.v().newIdentityStmt(l_r0, Jimple.v().newParameterRef(RefType.v("java.lang.String"), 0)));
        // add "$r2 = .staticinvoke <java.lang.Class: java.lang.Class
        // forName(java.lang.String)>(r0);
        AssignStmt asi;
        units.add(asi = Jimple.v().newAssignStmt(l_r2, Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<java.lang.Class: java.lang.Class" + " forName(java.lang.String)>").makeRef(), Arrays.asList(new Value[] { l_r0 }))));
        // insert "return $r2;"
        units.add(Jimple.v().newReturnStmt(l_r2));
        // add "r3 := @caughtexception;"
        Stmt handlerStart;
        units.add(handlerStart = Jimple.v().newIdentityStmt(l_r3, Jimple.v().newCaughtExceptionRef()));
        // add "r1 = r3;"
        units.add(Jimple.v().newAssignStmt(l_r1, l_r3));
        // add "$r4 = .new java.lang.NoClassDefFoundError;"
        units.add(Jimple.v().newAssignStmt(l_r4, Jimple.v().newNewExpr(RefType.v("java.lang.NoClassDefFoundError"))));
        // add "$r5 = virtualinvoke r1.<java.lang.Throwable:
        // java.lang.String getMessage()>();"
        units.add(Jimple.v().newAssignStmt(l_r5, Jimple.v().newVirtualInvokeExpr(l_r1, Scene.v().getMethod("<java.lang.Throwable: java.lang.String getMessage()>").makeRef(), new LinkedList())));
        // add .specialinvoke $r4.<java.lang.NoClassDefFoundError: .void
        // <init>(java.lang.String)>($r5);
        units.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(l_r4, Scene.v().getMethod("<java.lang.NoClassDefFoundError: void" + " <init>(java.lang.String)>").makeRef(), Arrays.asList(new Value[] { l_r5 }))));
        // add .throw $r4;
        units.add(Jimple.v().newThrowStmt(l_r4));
        body.getTraps().add(Jimple.v().newTrap(Scene.v().getSootClass("java.lang.ClassNotFoundException"), asi, handlerStart, handlerStart));
    }
    return method;
}
Also used : Chain(soot.util.Chain) RefType(soot.RefType) Type(soot.Type) AssignStmt(soot.jimple.AssignStmt) Value(soot.Value) SootMethod(soot.SootMethod) Local(soot.Local) JimpleBody(soot.jimple.JimpleBody) LinkedList(java.util.LinkedList) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt)

Example 13 with JimpleBody

use of soot.jimple.JimpleBody 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 14 with JimpleBody

use of soot.jimple.JimpleBody in project soot by Sable.

the class LockAllocationBodyTransformer method internalTransform.

protected void internalTransform(Body b, FlowSet fs, List<CriticalSectionGroup> groups, boolean[] insertedGlobalLock) {
    // 
    JimpleBody j = (JimpleBody) b;
    SootMethod thisMethod = b.getMethod();
    PatchingChain<Unit> units = b.getUnits();
    Iterator<Unit> unitIt = units.iterator();
    Unit firstUnit = j.getFirstNonIdentityStmt();
    Unit lastUnit = units.getLast();
    // Objects of synchronization, plus book keeping
    Local[] lockObj = new Local[groups.size()];
    boolean[] addedLocalLockObj = new boolean[groups.size()];
    SootField[] globalLockObj = new SootField[groups.size()];
    for (int i = 1; i < groups.size(); i++) {
        lockObj[i] = Jimple.v().newLocal("lockObj" + i, RefType.v("java.lang.Object"));
        addedLocalLockObj[i] = false;
        globalLockObj[i] = null;
    }
    // Get references to them if they do already exist.
    for (int i = 1; i < groups.size(); i++) {
        CriticalSectionGroup tnGroup = groups.get(i);
        if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
            if (!insertedGlobalLock[i]) {
                // use it!
                try {
                    globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
                // field already exists
                } catch (RuntimeException re) {
                    // field does not yet exist (or, as a pre-existing
                    // error, there is more than one field by this name)
                    globalLockObj[i] = Scene.v().makeSootField("globalLockObj" + i, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
                    Scene.v().getMainClass().addField(globalLockObj[i]);
                }
                insertedGlobalLock[i] = true;
            } else {
                globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
            }
        }
    }
    // local lock object into the global lock object for use by other fns.
    if (// thisMethod.getSubSignature().equals("void
    !addedGlobalLockDefs) // <clinit>()") &&
    // thisMethod.getDeclaringClass() ==
    // Scene.v().getMainClass())
    {
        // Either get or add the <clinit> method to the main class
        SootClass mainClass = Scene.v().getMainClass();
        SootMethod clinitMethod = null;
        JimpleBody clinitBody = null;
        Stmt firstStmt = null;
        boolean addingNewClinit = !mainClass.declaresMethod("void <clinit>()");
        if (addingNewClinit) {
            clinitMethod = Scene.v().makeSootMethod("<clinit>", new ArrayList(), VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
            clinitBody = Jimple.v().newBody(clinitMethod);
            clinitMethod.setActiveBody(clinitBody);
            mainClass.addMethod(clinitMethod);
        } else {
            clinitMethod = mainClass.getMethod("void <clinit>()");
            clinitBody = (JimpleBody) clinitMethod.getActiveBody();
            firstStmt = clinitBody.getFirstNonIdentityStmt();
        }
        PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
        for (int i = 1; i < groups.size(); i++) {
            CriticalSectionGroup tnGroup = groups.get(i);
            // if( useGlobalLock[i - 1] )
            if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
                // add local lock obj
                // addedLocalLockObj[i] = true;
                // TODO: add name
                clinitBody.getLocals().add(lockObj[i]);
                // conflict
                // avoidance code
                // assign new object to lock obj
                Stmt newStmt = Jimple.v().newAssignStmt(lockObj[i], Jimple.v().newNewExpr(RefType.v("java.lang.Object")));
                if (addingNewClinit)
                    clinitUnits.add(newStmt);
                else
                    clinitUnits.insertBeforeNoRedirect(newStmt, firstStmt);
                // initialize new object
                SootClass objectClass = Scene.v().loadClassAndSupport("java.lang.Object");
                RefType type = RefType.v(objectClass);
                SootMethod initMethod = objectClass.getMethod("void <init>()");
                Stmt initStmt = Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(lockObj[i], initMethod.makeRef(), Collections.EMPTY_LIST));
                if (addingNewClinit)
                    clinitUnits.add(initStmt);
                else
                    clinitUnits.insertBeforeNoRedirect(initStmt, firstStmt);
                // copy new object to global static lock object (for use by
                // other fns)
                Stmt assignStmt = Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(globalLockObj[i].makeRef()), lockObj[i]);
                if (addingNewClinit)
                    clinitUnits.add(assignStmt);
                else
                    clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
            }
        }
        if (addingNewClinit)
            clinitUnits.add(Jimple.v().newReturnVoidStmt());
        addedGlobalLockDefs = true;
    }
    int tempNum = 1;
    // Iterate through all of the transactions in the current method
    Iterator fsIt = fs.iterator();
    Stmt newPrep = null;
    while (fsIt.hasNext()) {
        CriticalSection tn = ((SynchronizedRegionFlowPair) fsIt.next()).tn;
        if (tn.setNumber == -1)
            // this tn should be deleted... for now just skip it!
            continue;
        if (tn.wholeMethod) {
            // remove
            thisMethod.setModifiers(thisMethod.getModifiers() & ~(Modifier.SYNCHRONIZED));
        // synchronized
        // modifier
        // for
        // this
        // method
        }
        // depends on type of locking
        Local clo = null;
        // current synchronized region
        SynchronizedRegion csr = null;
        int lockNum = 0;
        boolean moreLocks = true;
        while (moreLocks) {
            // needed for this transaction, then create one.
            if (tn.group.useDynamicLock) {
                // adds
                Value lock = getLockFor((EquivalentValue) tn.lockObject);
                // needed
                if (lock instanceof Ref) {
                    if (lock instanceof InstanceFieldRef) {
                        InstanceFieldRef ifr = (InstanceFieldRef) lock;
                        if (ifr.getBase() instanceof FakeJimpleLocal)
                            lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
                    }
                    if (!b.getLocals().contains(lockObj[tn.setNumber]))
                        b.getLocals().add(lockObj[tn.setNumber]);
                    newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], lock);
                    if (tn.wholeMethod)
                        units.insertBeforeNoRedirect(newPrep, firstUnit);
                    else
                        units.insertBefore(newPrep, tn.entermonitor);
                    clo = lockObj[tn.setNumber];
                } else if (lock instanceof Local)
                    clo = (Local) lock;
                else
                    throw new RuntimeException("Unknown type of lock (" + lock + "): expected Ref or Local");
                csr = tn;
                moreLocks = false;
            } else if (tn.group.useLocksets) {
                // adds
                Value lock = getLockFor((EquivalentValue) tn.lockset.get(lockNum));
                // needed
                if (lock instanceof FieldRef) {
                    if (lock instanceof InstanceFieldRef) {
                        InstanceFieldRef ifr = (InstanceFieldRef) lock;
                        if (ifr.getBase() instanceof FakeJimpleLocal)
                            lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
                    }
                    // add a local variable for this lock
                    Local lockLocal = Jimple.v().newLocal("locksetObj" + tempNum, RefType.v("java.lang.Object"));
                    tempNum++;
                    b.getLocals().add(lockLocal);
                    // make it refer to the right lock object
                    newPrep = Jimple.v().newAssignStmt(lockLocal, lock);
                    if (tn.entermonitor != null)
                        units.insertBefore(newPrep, tn.entermonitor);
                    else
                        units.insertBeforeNoRedirect(newPrep, tn.beginning);
                    // use it as the lock
                    clo = lockLocal;
                } else if (lock instanceof Local)
                    clo = (Local) lock;
                else
                    throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef or Local");
                if (lockNum + 1 >= tn.lockset.size())
                    moreLocks = false;
                else
                    moreLocks = true;
                if (lockNum > 0) {
                    SynchronizedRegion nsr = new SynchronizedRegion();
                    nsr.beginning = csr.beginning;
                    for (Pair earlyEnd : csr.earlyEnds) {
                        Stmt earlyExitmonitor = (Stmt) earlyEnd.getO2();
                        // <early
                        nsr.earlyEnds.add(new Pair(earlyExitmonitor, null));
                    // exitmonitor,
                    // null>
                    }
                    // last stmt before exception
                    nsr.last = csr.last;
                    // handling
                    if (csr.end != null) {
                        Stmt endExitmonitor = csr.end.getO2();
                        nsr.after = endExitmonitor;
                    }
                    csr = nsr;
                } else
                    csr = tn;
            } else // global lock
            {
                if (!addedLocalLockObj[tn.setNumber])
                    b.getLocals().add(lockObj[tn.setNumber]);
                addedLocalLockObj[tn.setNumber] = true;
                newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], Jimple.v().newStaticFieldRef(globalLockObj[tn.setNumber].makeRef()));
                if (tn.wholeMethod)
                    units.insertBeforeNoRedirect(newPrep, firstUnit);
                else
                    units.insertBefore(newPrep, tn.entermonitor);
                clo = lockObj[tn.setNumber];
                csr = tn;
                moreLocks = false;
            }
            // monitorenter/monitorexit statements with new ones
            if (true) {
                // Remove old prep stmt
                if (csr.prepStmt != null) {
                // units.remove(clr.prepStmt); // seems to trigger bugs
                // in code generation?
                }
                // Reuse old entermonitor or insert new one, and insert prep
                Stmt newEntermonitor = Jimple.v().newEnterMonitorStmt(clo);
                if (csr.entermonitor != null) {
                    units.insertBefore(newEntermonitor, csr.entermonitor);
                    // redirectTraps(b, clr.entermonitor, newEntermonitor);
                    // // EXPERIMENTAL
                    units.remove(csr.entermonitor);
                    csr.entermonitor = newEntermonitor;
                // units.insertBefore(newEntermonitor, newPrep); //
                // already inserted
                // clr.prepStmt = newPrep;
                } else {
                    units.insertBeforeNoRedirect(newEntermonitor, csr.beginning);
                    csr.entermonitor = newEntermonitor;
                // units.insertBefore(newEntermonitor, newPrep); //
                // already inserted
                // clr.prepStmt = newPrep;
                }
                // For each early end, reuse or insert exitmonitor stmt
                List<Pair<Stmt, Stmt>> newEarlyEnds = new ArrayList<Pair<Stmt, Stmt>>();
                for (Pair<Stmt, Stmt> end : csr.earlyEnds) {
                    Stmt earlyEnd = end.getO1();
                    Stmt exitmonitor = end.getO2();
                    Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
                    if (exitmonitor != null) {
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            // seems
                            units.insertBefore(tmp, exitmonitor);
                        // to
                        // avoid
                        // code
                        // generation
                        // bugs?
                        }
                        units.insertBefore(newExitmonitor, exitmonitor);
                        // redirectTraps(b, exitmonitor, newExitmonitor); //
                        // EXPERIMENTAL
                        units.remove(exitmonitor);
                        newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
                    } else {
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            units.insertBefore(tmp, earlyEnd);
                        }
                        units.insertBefore(newExitmonitor, earlyEnd);
                        newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
                    }
                }
                csr.earlyEnds = newEarlyEnds;
                // If fallthrough end, reuse or insert goto and exit
                if (csr.after != null) {
                    Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
                    if (csr.end != null) {
                        Stmt exitmonitor = csr.end.getO2();
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            units.insertBefore(tmp, exitmonitor);
                        }
                        units.insertBefore(newExitmonitor, exitmonitor);
                        // redirectTraps(b, exitmonitor, newExitmonitor); //
                        // EXPERIMENTAL
                        units.remove(exitmonitor);
                        csr.end = new Pair<Stmt, Stmt>(csr.end.getO1(), newExitmonitor);
                    } else {
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            units.insertBefore(tmp, csr.after);
                        }
                        // steal
                        units.insertBefore(newExitmonitor, csr.after);
                        // jumps
                        // to
                        // end,
                        // send
                        // them
                        // to
                        // monitorexit
                        Stmt newGotoStmt = Jimple.v().newGotoStmt(csr.after);
                        units.insertBeforeNoRedirect(newGotoStmt, csr.after);
                        csr.end = new Pair<Stmt, Stmt>(newGotoStmt, newExitmonitor);
                        csr.last = newGotoStmt;
                    }
                }
                // If exceptional end, reuse it, else insert it and traps
                Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
                if (csr.exceptionalEnd != null) {
                    Stmt exitmonitor = csr.exceptionalEnd.getO2();
                    if (newPrep != null) {
                        Stmt tmp = (Stmt) newPrep.clone();
                        units.insertBefore(tmp, exitmonitor);
                    }
                    units.insertBefore(newExitmonitor, exitmonitor);
                    units.remove(exitmonitor);
                    csr.exceptionalEnd = new Pair<Stmt, Stmt>(csr.exceptionalEnd.getO1(), newExitmonitor);
                } else {
                    // insert after the last end
                    // last end stmt (not same as last
                    Stmt lastEnd = null;
                    // stmt)
                    if (csr.end != null) {
                        lastEnd = csr.end.getO1();
                    } else {
                        for (Pair earlyEnd : csr.earlyEnds) {
                            Stmt end = (Stmt) earlyEnd.getO1();
                            if (lastEnd == null || (units.contains(lastEnd) && units.contains(end) && units.follows(end, lastEnd)))
                                lastEnd = end;
                        }
                    }
                    if (// || !units.contains(clr.last))
                    csr.last == null)
                        // last stmt and last end are
                        csr.last = lastEnd;
                    // the same
                    if (lastEnd == null)
                        throw new RuntimeException("Lock Region has no ends!  Where should we put the exception handling???");
                    // Add throwable
                    Local throwableLocal = Jimple.v().newLocal("throwableLocal" + (throwableNum++), RefType.v("java.lang.Throwable"));
                    b.getLocals().add(throwableLocal);
                    // Add stmts
                    Stmt newCatch = Jimple.v().newIdentityStmt(throwableLocal, Jimple.v().newCaughtExceptionRef());
                    if (csr.last == null)
                        throw new RuntimeException("WHY IS clr.last NULL???");
                    if (newCatch == null)
                        throw new RuntimeException("WHY IS newCatch NULL???");
                    units.insertAfter(newCatch, csr.last);
                    units.insertAfter(newExitmonitor, newCatch);
                    Stmt newThrow = Jimple.v().newThrowStmt(throwableLocal);
                    units.insertAfter(newThrow, newExitmonitor);
                    // Add traps
                    SootClass throwableClass = Scene.v().loadClassAndSupport("java.lang.Throwable");
                    b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, newExitmonitor, newThrow, newCatch));
                    b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, csr.beginning, lastEnd, newCatch));
                    csr.exceptionalEnd = new Pair<Stmt, Stmt>(newThrow, newExitmonitor);
                }
            }
            lockNum++;
        }
        // deal with waits and notifys
        {
            for (Unit uNotify : tn.notifys) {
                Stmt sNotify = (Stmt) uNotify;
                Stmt newNotify = Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(clo, sNotify.getInvokeExpr().getMethodRef().declaringClass().getMethod("void notifyAll()").makeRef(), Collections.EMPTY_LIST));
                if (newPrep != null) {
                    Stmt tmp = (Stmt) newPrep.clone();
                    units.insertBefore(tmp, sNotify);
                    units.insertBefore(newNotify, tmp);
                } else
                    units.insertBefore(newNotify, sNotify);
                redirectTraps(b, sNotify, newNotify);
                units.remove(sNotify);
            }
            // Replace base object of calls to wait with appropriate lockobj
            for (Unit uWait : tn.waits) {
                Stmt sWait = (Stmt) uWait;
                // WHAT
                ((InstanceInvokeExpr) sWait.getInvokeExpr()).setBase(clo);
                // LOCKS???
                if (newPrep != null)
                    units.insertBefore((Stmt) newPrep.clone(), sWait);
            }
        }
    }
}
Also used : EquivalentValue(soot.EquivalentValue) ArrayList(java.util.ArrayList) Unit(soot.Unit) Stmt(soot.jimple.Stmt) RefType(soot.RefType) Iterator(java.util.Iterator) InstanceFieldRef(soot.jimple.InstanceFieldRef) JimpleBody(soot.jimple.JimpleBody) Pair(soot.toolkits.scalar.Pair) FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) FakeJimpleLocal(soot.jimple.toolkits.infoflow.FakeJimpleLocal) Local(soot.Local) SootClass(soot.SootClass) ArrayRef(soot.jimple.ArrayRef) Ref(soot.jimple.Ref) FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) EquivalentValue(soot.EquivalentValue) Value(soot.Value) SootMethod(soot.SootMethod) SootField(soot.SootField) FakeJimpleLocal(soot.jimple.toolkits.infoflow.FakeJimpleLocal)

Example 15 with JimpleBody

use of soot.jimple.JimpleBody 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();
}
Also used : LocalGenerator(soot.javaToJimple.LocalGenerator) HashChain(soot.util.HashChain) InstanceFieldRef(soot.jimple.InstanceFieldRef) SootMethod(soot.SootMethod) Local(soot.Local) SootClass(soot.SootClass) Unit(soot.Unit) JimpleBody(soot.jimple.JimpleBody) InvokeStmt(soot.jimple.InvokeStmt) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) AssignStmt(soot.jimple.AssignStmt) Stmt(soot.jimple.Stmt)

Aggregations

JimpleBody (soot.jimple.JimpleBody)23 Local (soot.Local)14 SootMethod (soot.SootMethod)13 Unit (soot.Unit)10 ArrayList (java.util.ArrayList)9 SootClass (soot.SootClass)9 Iterator (java.util.Iterator)7 Value (soot.Value)7 Stmt (soot.jimple.Stmt)7 RefType (soot.RefType)6 List (java.util.List)5 VoidType (soot.VoidType)5 HashMap (java.util.HashMap)4 LinkedList (java.util.LinkedList)4 Body (soot.Body)4 BooleanType (soot.BooleanType)4 ByteType (soot.ByteType)4 CharType (soot.CharType)4 DoubleType (soot.DoubleType)4 FloatType (soot.FloatType)4