Search in sources :

Example 6 with BriefUnitGraph

use of soot.toolkits.graph.BriefUnitGraph in project soot by Sable.

the class TryCatchCombiner method internalTransform.

protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
    int weight = soot.jbco.Main.getWeight(phaseName, b.getMethod().getSignature());
    if (weight == 0)
        return;
    int trapCount = 0;
    PatchingChain<Unit> units = b.getUnits();
    ArrayList<Unit> headList = new ArrayList<Unit>();
    ArrayList<Trap> trapList = new ArrayList<Trap>();
    Iterator<Trap> traps = b.getTraps().iterator();
    // build list of heads and corresponding traps
    while (traps.hasNext()) {
        Trap t = traps.next();
        totalcount++;
        // skip runtime exceptions
        if (!isRewritable(t))
            continue;
        headList.add(t.getBeginUnit());
        trapList.add(t);
        trapCount++;
    }
    if (trapCount == 0)
        return;
    // check if any traps have same head, if so insert dumby NOP to disambiguate
    for (int i = 0; i < headList.size(); i++) {
        for (int j = 0; j < headList.size(); j++) {
            if (i == j)
                continue;
            if (headList.get(i) == headList.get(j)) {
                Trap t = trapList.get(i);
                Unit nop = Baf.v().newNopInst();
                units.insertBeforeNoRedirect(nop, headList.get(i));
                headList.set(i, nop);
                t.setBeginUnit(nop);
            }
        }
    }
    Unit first = null;
    Iterator<Unit> uit = units.iterator();
    while (uit.hasNext()) {
        Unit unit = (Unit) uit.next();
        if (!(unit instanceof IdentityInst))
            break;
        first = unit;
    }
    if (first == null) {
        first = Baf.v().newNopInst();
        units.insertBefore(first, units.getFirst());
    } else {
        first = (Unit) units.getSuccOf(first);
    }
    Collection<Local> locs = b.getLocals();
    Map<Unit, Stack<Type>> stackHeightsBefore = null;
    Map<Local, Local> bafToJLocals = soot.jbco.Main.methods2Baf2JLocals.get(b.getMethod());
    int varCount = trapCount + 1;
    traps = b.getTraps().snapshotIterator();
    while (traps.hasNext()) {
        Trap t = traps.next();
        Unit begUnit = t.getBeginUnit();
        if (!isRewritable(t) || Rand.getInt(10) > weight)
            continue;
        stackHeightsBefore = StackTypeHeightCalculator.calculateStackHeights(b, bafToJLocals);
        boolean badType = false;
        @SuppressWarnings("unchecked") Stack<Type> s = (Stack<Type>) stackHeightsBefore.get(begUnit).clone();
        if (s.size() > 0) {
            for (int i = 0; i < s.size(); i++) {
                if (s.pop() instanceof StmtAddressType) {
                    badType = true;
                    break;
                }
            }
        }
        if (badType)
            continue;
        // local to hold control flow flag (0=try, 1=catch)
        Local controlLocal = Baf.v().newLocal("controlLocal_tccomb" + trapCount, IntType.v());
        locs.add(controlLocal);
        // initialize local to 0=try
        Unit pushZero = Baf.v().newPushInst(IntConstant.v(0));
        Unit storZero = Baf.v().newStoreInst(IntType.v(), controlLocal);
        // this is necessary even though it seems like it shouldn't be
        units.insertBeforeNoRedirect((Unit) pushZero.clone(), first);
        units.insertBeforeNoRedirect((Unit) storZero.clone(), first);
        BriefUnitGraph graph = new BriefUnitGraph(b);
        List<Unit> l = graph.getPredsOf(begUnit);
        // add initializer seq for try - sets local to zero and loads null exc
        units.add(pushZero);
        units.add(storZero);
        Stack<Local> varsToLoad = new Stack<Local>();
        s = stackHeightsBefore.get(begUnit);
        if (s.size() > 0) {
            for (int i = 0; i < s.size(); i++) {
                Type type = s.pop();
                Local varLocal = Baf.v().newLocal("varLocal_tccomb" + varCount++, type);
                locs.add(varLocal);
                varsToLoad.push(varLocal);
                units.add(Baf.v().newStoreInst(type, varLocal));
                units.insertBeforeNoRedirect(FixUndefinedLocals.getPushInitializer(varLocal, type), first);
                units.insertBeforeNoRedirect(Baf.v().newStoreInst(type, varLocal), first);
            }
        }
        units.add(Baf.v().newPushInst(NullConstant.v()));
        units.add(Baf.v().newGotoInst(begUnit));
        // for each pred of the beginUnit of the try, we must insert goto initializer
        for (int i = 0; i < l.size(); i++) {
            Unit pred = l.get(i);
            if (isIf(pred)) {
                TargetArgInst ifPred = ((TargetArgInst) pred);
                if (ifPred.getTarget() == begUnit) {
                    ifPred.setTarget(pushZero);
                }
                Unit succ = units.getSuccOf(ifPred);
                if (succ == begUnit) {
                    units.insertAfter(Baf.v().newGotoInst(pushZero), ifPred);
                }
            } else if (pred instanceof GotoInst && ((GotoInst) pred).getTarget() == begUnit) {
                ((GotoInst) pred).setTarget(pushZero);
            } else {
                units.insertAfter(Baf.v().newGotoInst(pushZero), pred);
            }
        }
        Unit handlerUnit = t.getHandlerUnit();
        Unit newBeginUnit = Baf.v().newLoadInst(IntType.v(), controlLocal);
        units.insertBefore(newBeginUnit, begUnit);
        units.insertBefore(Baf.v().newIfNeInst(handlerUnit), begUnit);
        units.insertBefore(Baf.v().newPopInst(RefType.v()), begUnit);
        while (varsToLoad.size() > 0) {
            Local varLocal = (Local) varsToLoad.pop();
            units.insertBefore(Baf.v().newLoadInst(varLocal.getType(), varLocal), begUnit);
        }
        try {
            SootField[] f = FieldRenamer.getRandomOpaques();
            if (f[0] != null && f[1] != null) {
                loadBooleanValue(units, f[0], begUnit);
                loadBooleanValue(units, f[1], begUnit);
                units.insertBeforeNoRedirect(Baf.v().newIfCmpEqInst(BooleanType.v(), begUnit), begUnit);
            }
        } catch (NullPointerException npe) {
        }
        // randomize the increment - sometimes store one, sometimes just set to 1
        if (Rand.getInt() % 2 == 0) {
            units.insertBeforeNoRedirect(Baf.v().newPushInst(IntConstant.v(Rand.getInt(3) + 1)), begUnit);
            units.insertBeforeNoRedirect(Baf.v().newStoreInst(IntType.v(), controlLocal), begUnit);
        } else {
            units.insertBeforeNoRedirect(Baf.v().newIncInst(controlLocal, IntConstant.v(Rand.getInt(3) + 1)), begUnit);
        }
        trapCount--;
        t.setBeginUnit(newBeginUnit);
        t.setHandlerUnit(newBeginUnit);
        changedcount++;
        if (debug)
            StackTypeHeightCalculator.printStack(units, StackTypeHeightCalculator.calculateStackHeights(b), false);
    }
}
Also used : BriefUnitGraph(soot.toolkits.graph.BriefUnitGraph)

Aggregations

BriefUnitGraph (soot.toolkits.graph.BriefUnitGraph)6 Unit (soot.Unit)3 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 Vector (java.util.Vector)1 EquivalentValue (soot.EquivalentValue)1 Local (soot.Local)1 SideEffectTester (soot.SideEffectTester)1 Value (soot.Value)1 AssignStmt (soot.jimple.AssignStmt)1 IdentityStmt (soot.jimple.IdentityStmt)1 IfStmt (soot.jimple.IfStmt)1 LookupSwitchStmt (soot.jimple.LookupSwitchStmt)1 NaiveSideEffectTester (soot.jimple.NaiveSideEffectTester)1 Stmt (soot.jimple.Stmt)1 TableSwitchStmt (soot.jimple.TableSwitchStmt)1 PASideEffectTester (soot.jimple.toolkits.pointer.PASideEffectTester)1 LocalCreation (soot.jimple.toolkits.scalar.LocalCreation)1 BCMOptions (soot.options.BCMOptions)1