Search in sources :

Example 66 with Unit

use of soot.Unit 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 67 with Unit

use of soot.Unit in project soot by Sable.

the class DexReturnValuePropagator method isRedefined.

/**
 * Checks whether the given local has been redefined between the original
 * definition unitDef and the use unitUse.
 * @param l The local for which to check for redefinitions
 * @param unitUse The unit that uses the local
 * @param unitDef The unit that defines the local
 * @param graph The unit graph to use for the check
 * @return True if there is at least one path between unitDef and unitUse on
 * which local l gets redefined, otherwise false
 */
private boolean isRedefined(Local l, Unit unitUse, AssignStmt unitDef, UnitGraph graph) {
    List<Unit> workList = new ArrayList<Unit>();
    workList.add(unitUse);
    Set<Unit> doneSet = new HashSet<Unit>();
    // Check for redefinitions of the local between definition and use
    while (!workList.isEmpty()) {
        Unit curStmt = workList.remove(0);
        if (!doneSet.add(curStmt))
            continue;
        for (Unit u : graph.getPredsOf(curStmt)) {
            if (u != unitDef) {
                if (u instanceof DefinitionStmt) {
                    DefinitionStmt defStmt = (DefinitionStmt) u;
                    if (defStmt.getLeftOp() == l)
                        return true;
                }
                workList.add(u);
            }
        }
    }
    return false;
}
Also used : ArrayList(java.util.ArrayList) Unit(soot.Unit) DefinitionStmt(soot.jimple.DefinitionStmt) HashSet(java.util.HashSet)

Example 68 with Unit

use of soot.Unit in project soot by Sable.

the class DexArrayInitReducer method internalTransform.

@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
    // Make sure that we only have linear control flow
    if (!b.getTraps().isEmpty())
        return;
    // Look for a chain of two constant assignments followed by an array put
    Unit u1 = null, u2 = null;
    for (Iterator<Unit> uIt = b.getUnits().snapshotIterator(); uIt.hasNext(); ) {
        Unit u = uIt.next();
        // If this is not an assignment, it does not matter.
        if (!(u instanceof AssignStmt) || !((Stmt) u).getBoxesPointingToThis().isEmpty()) {
            u1 = null;
            u2 = null;
            continue;
        }
        // If this is an assignment to an array, we must already have two
        // preceding constant assignments
        AssignStmt assignStmt = (AssignStmt) u;
        if (assignStmt.getLeftOp() instanceof ArrayRef) {
            if (u1 != null && u2 != null && u2.getBoxesPointingToThis().isEmpty() && assignStmt.getBoxesPointingToThis().isEmpty()) {
                ArrayRef arrayRef = (ArrayRef) assignStmt.getLeftOp();
                Value u1val = u1.getDefBoxes().get(0).getValue();
                Value u2val = u2.getDefBoxes().get(0).getValue();
                // index
                if (arrayRef.getIndex() == u1val)
                    arrayRef.setIndex(((AssignStmt) u1).getRightOp());
                else if (arrayRef.getIndex() == u2val)
                    arrayRef.setIndex(((AssignStmt) u2).getRightOp());
                // value
                if (assignStmt.getRightOp() == u1val)
                    assignStmt.setRightOp(((AssignStmt) u1).getRightOp());
                else if (assignStmt.getRightOp() == u2val)
                    assignStmt.setRightOp(((AssignStmt) u2).getRightOp());
                // Remove the unnecessary assignments
                Unit checkU = u;
                boolean foundU1 = false, foundU2 = false, doneU1 = false, doneU2 = false;
                while (!(doneU1 && doneU2) && !(foundU1 && foundU2) && checkU != null) {
                    // Does the current statement use the value?
                    for (ValueBox vb : checkU.getUseBoxes()) {
                        if (!doneU1 && vb.getValue() == u1val)
                            foundU1 = true;
                        if (!doneU2 && vb.getValue() == u2val)
                            foundU2 = true;
                    }
                    // Does the current statement overwrite the value?
                    for (ValueBox vb : checkU.getDefBoxes()) {
                        if (vb.getValue() == u1val)
                            doneU1 = true;
                        else if (vb.getValue() == u2val)
                            doneU2 = true;
                    }
                    // If this statement branches, we abort
                    if (checkU.branches()) {
                        foundU1 = true;
                        foundU2 = true;
                        break;
                    }
                    // Get the next statement
                    checkU = b.getUnits().getSuccOf(checkU);
                }
                if (!foundU1) {
                    // only remove constant assignment if the left value is Local
                    if (u1val instanceof Local) {
                        b.getUnits().remove(u1);
                        if (Options.v().verbose()) {
                            logger.debug("[" + b.getMethod().getName() + "]    remove 1 " + u1);
                        }
                    }
                }
                if (!foundU2) {
                    // only remove constant assignment if the left value is Local
                    if (u2val instanceof Local) {
                        b.getUnits().remove(u2);
                        if (Options.v().verbose()) {
                            logger.debug("[" + b.getMethod().getName() + "]    remove 2 " + u2);
                        }
                    }
                }
                u1 = null;
                u2 = null;
            } else {
                // No proper initialization before
                u1 = null;
                u2 = null;
                continue;
            }
        }
        // value.
        if (!(assignStmt.getRightOp() instanceof Constant)) {
            u1 = null;
            u2 = null;
            continue;
        }
        if (u1 == null) {
            u1 = assignStmt;
        } else if (u2 == null) {
            u2 = assignStmt;
            // If the last value is overwritten again, we start again at the beginning
            if (u1 != null) {
                Value op1 = ((AssignStmt) u1).getLeftOp();
                if (op1 == ((AssignStmt) u2).getLeftOp()) {
                    u1 = u2;
                    u2 = null;
                }
            }
        } else {
            u1 = u2;
            u2 = assignStmt;
        }
    }
    // Remove all locals that are no longer necessary
    UnusedLocalEliminator.v().transform(b);
}
Also used : ArrayRef(soot.jimple.ArrayRef) AssignStmt(soot.jimple.AssignStmt) ValueBox(soot.ValueBox) Constant(soot.jimple.Constant) Value(soot.Value) Local(soot.Local) Unit(soot.Unit)

Example 69 with Unit

use of soot.Unit in project soot by Sable.

the class DexPrinter method toMethodImplementation.

private MethodImplementation toMethodImplementation(SootMethod m) {
    if (m.isAbstract() || m.isNative()) {
        return null;
    }
    Body activeBody = m.retrieveActiveBody();
    // when installing the app
    if (m.getName().contains("<") || m.getName().equals(">"))
        if (!m.getName().equals("<init>") && !m.getName().equals("<clinit>"))
            throw new RuntimeException("Invalid method name: " + m.getName());
    // Switch statements may not be empty in dex, so we have to fix this
    // first
    EmptySwitchEliminator.v().transform(activeBody);
    // Dalvik requires synchronized methods to have explicit monitor calls,
    // so we insert them here. See
    // http://milk.com/kodebase/dalvik-docs-mirror/docs/debugger.html
    // We cannot place this upon the developer since it is only required
    // for Dalvik, but not for other targets.
    SynchronizedMethodTransformer.v().transform(activeBody);
    // Tries may not start or end at units which have no corresponding
    // Dalvik
    // instructions such as IdentityStmts. We reduce the traps to start at
    // the
    // first "real" instruction. We could also use a TrapTigthener, but that
    // would be too expensive for what we need here.
    FastDexTrapTightener.v().transform(activeBody);
    // Look for sequences of array element assignments that we can collapse
    // into bulk initializations
    DexArrayInitDetector initDetector = new DexArrayInitDetector();
    initDetector.constructArrayInitializations(activeBody);
    initDetector.fixTraps(activeBody);
    // Split the tries since Dalvik does not supported nested try/catch
    // blocks
    TrapSplitter.v().transform(activeBody);
    // word count of incoming parameters
    int inWords = SootToDexUtils.getDexWords(m.getParameterTypes());
    if (!m.isStatic()) {
        // extra word for "this"
        inWords++;
    }
    // word count of max outgoing parameters
    Collection<Unit> units = activeBody.getUnits();
    // register count = parameters + additional registers, depending on the
    // dex instructions generated (e.g. locals used and constants loaded)
    StmtVisitor stmtV = new StmtVisitor(m, initDetector);
    Chain<Trap> traps = activeBody.getTraps();
    Set<Unit> trapReferences = new HashSet<Unit>(traps.size() * 3);
    for (Trap t : activeBody.getTraps()) {
        trapReferences.add(t.getBeginUnit());
        trapReferences.add(t.getEndUnit());
        trapReferences.add(t.getHandlerUnit());
    }
    toInstructions(units, stmtV, trapReferences);
    int registerCount = stmtV.getRegisterCount();
    if (inWords > registerCount) {
        /*
			 * as the Dalvik VM moves the parameters into the last registers, the "in" word
			 * count must be at least equal to the register count. a smaller register count
			 * could occur if soot generated the method body, see e.g. the handling of
			 * phantom refs in SootMethodRefImpl.resolve(StringBuffer): the body has no
			 * locals for the ParameterRefs, it just throws an error.
			 *
			 * we satisfy the verifier by just increasing the register count, since calling
			 * phantom refs will lead to an error anyway.
			 */
        registerCount = inWords;
    }
    MethodImplementationBuilder builder = new MethodImplementationBuilder(registerCount);
    LabelAssigner labelAssinger = new LabelAssigner(builder);
    List<BuilderInstruction> instructions = stmtV.getRealInsns(labelAssinger);
    fixLongJumps(instructions, labelAssinger, stmtV);
    Map<Local, Integer> seenRegisters = new HashMap<Local, Integer>();
    Map<Instruction, LocalRegisterAssignmentInformation> instructionRegisterMap = stmtV.getInstructionRegisterMap();
    if (Options.v().write_local_annotations()) {
        for (LocalRegisterAssignmentInformation assignment : stmtV.getParameterInstructionsList()) {
            // (at least not if it exists with exactly this name)
            if (assignment.getLocal().getName().equals("this"))
                continue;
            addRegisterAssignmentDebugInfo(assignment, seenRegisters, builder);
        }
    }
    for (BuilderInstruction ins : instructions) {
        Stmt origStmt = stmtV.getStmtForInstruction(ins);
        // If this is a switch payload, we need to place the label
        if (stmtV.getInstructionPayloadMap().containsKey(ins))
            builder.addLabel(labelAssinger.getLabelName(stmtV.getInstructionPayloadMap().get(ins)));
        if (origStmt != null) {
            // Do we need a label here because this a trap handler?
            if (trapReferences.contains(origStmt))
                labelAssinger.getOrCreateLabel(origStmt);
            // Add the label if the statement has one
            String labelName = labelAssinger.getLabelName(origStmt);
            if (labelName != null && !builder.getLabel(labelName).isPlaced())
                builder.addLabel(labelName);
            // Add the tags
            if (stmtV.getStmtForInstruction(ins) != null) {
                List<Tag> tags = origStmt.getTags();
                for (Tag t : tags) {
                    if (t instanceof LineNumberTag) {
                        LineNumberTag lnt = (LineNumberTag) t;
                        builder.addLineNumber(lnt.getLineNumber());
                    } else if (t instanceof SourceFileTag) {
                        SourceFileTag sft = (SourceFileTag) t;
                        builder.addSetSourceFile(new ImmutableStringReference(sft.getSourceFile()));
                    }
                }
            }
        }
        builder.addInstruction(ins);
        LocalRegisterAssignmentInformation registerAssignmentTag = instructionRegisterMap.get(ins);
        if (registerAssignmentTag != null) {
            // Add start local debugging information: Register -> Local
            // assignment
            addRegisterAssignmentDebugInfo(registerAssignmentTag, seenRegisters, builder);
        }
    }
    for (int registersLeft : seenRegisters.values()) builder.addEndLocal(registersLeft);
    toTries(activeBody.getTraps(), stmtV, builder, labelAssinger);
    // Make sure that all labels have been placed by now
    for (Label lbl : labelAssinger.getAllLabels()) if (!lbl.isPlaced())
        throw new RuntimeException("Label not placed: " + lbl);
    return builder.getMethodImplementation();
}
Also used : LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) SourceFileTag(soot.tagkit.SourceFileTag) Label(org.jf.dexlib2.builder.Label) Unit(soot.Unit) BuilderOffsetInstruction(org.jf.dexlib2.builder.BuilderOffsetInstruction) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) NopStmt(soot.jimple.NopStmt) Stmt(soot.jimple.Stmt) IdentityStmt(soot.jimple.IdentityStmt) MonitorStmt(soot.jimple.MonitorStmt) LineNumberTag(soot.tagkit.LineNumberTag) Body(soot.Body) MethodImplementationBuilder(org.jf.dexlib2.builder.MethodImplementationBuilder) HashSet(java.util.HashSet) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) Local(soot.Local) Trap(soot.Trap) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) ConstantValueTag(soot.tagkit.ConstantValueTag) SourceFileTag(soot.tagkit.SourceFileTag) AnnotationDefaultTag(soot.tagkit.AnnotationDefaultTag) VisibilityAnnotationTag(soot.tagkit.VisibilityAnnotationTag) InnerClassTag(soot.tagkit.InnerClassTag) FloatConstantValueTag(soot.tagkit.FloatConstantValueTag) AnnotationTag(soot.tagkit.AnnotationTag) IntegerConstantValueTag(soot.tagkit.IntegerConstantValueTag) EnclosingMethodTag(soot.tagkit.EnclosingMethodTag) VisibilityParameterAnnotationTag(soot.tagkit.VisibilityParameterAnnotationTag) Tag(soot.tagkit.Tag) LineNumberTag(soot.tagkit.LineNumberTag) ParamNamesTag(soot.tagkit.ParamNamesTag) DoubleConstantValueTag(soot.tagkit.DoubleConstantValueTag) LongConstantValueTag(soot.tagkit.LongConstantValueTag) SignatureTag(soot.tagkit.SignatureTag) StringConstantValueTag(soot.tagkit.StringConstantValueTag)

Example 70 with Unit

use of soot.Unit in project soot by Sable.

the class FastDexTrapTightener method internalTransform.

@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
    for (Iterator<Trap> trapIt = b.getTraps().snapshotIterator(); trapIt.hasNext(); ) {
        Trap t = trapIt.next();
        Unit beginUnit;
        while (!isDexInstruction(beginUnit = t.getBeginUnit()) && t.getBeginUnit() != t.getEndUnit()) t.setBeginUnit(b.getUnits().getSuccOf(beginUnit));
        // If the trap is empty, we remove it
        if (t.getBeginUnit() == t.getEndUnit())
            trapIt.remove();
    }
}
Also used : Trap(soot.Trap) Unit(soot.Unit)

Aggregations

Unit (soot.Unit)240 Local (soot.Local)77 Stmt (soot.jimple.Stmt)77 Value (soot.Value)74 ArrayList (java.util.ArrayList)65 AssignStmt (soot.jimple.AssignStmt)58 SootMethod (soot.SootMethod)47 Body (soot.Body)37 InvokeStmt (soot.jimple.InvokeStmt)35 Type (soot.Type)34 HashSet (java.util.HashSet)33 ValueBox (soot.ValueBox)33 InvokeExpr (soot.jimple.InvokeExpr)33 Trap (soot.Trap)32 RefType (soot.RefType)30 IdentityStmt (soot.jimple.IdentityStmt)28 HashMap (java.util.HashMap)27 IfStmt (soot.jimple.IfStmt)27 DefinitionStmt (soot.jimple.DefinitionStmt)25 List (java.util.List)23