Search in sources :

Example 6 with IdentityStmt

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

the class DavaBody method copy_Body.

/*
	 *  Copy and patch a GrimpBody so that it can be used to output Java.
	 */
private void copy_Body(Body body) {
    if (!(body instanceof GrimpBody))
        throw new RuntimeException("You can only create a DavaBody from a GrimpBody!");
    GrimpBody grimpBody = (GrimpBody) body;
    /*
		 *  Import body contents from Grimp.
		 */
    {
        HashMap<Switchable, Switchable> bindings = new HashMap<Switchable, Switchable>();
        HashMap<Unit, Unit> reverse_binding = new HashMap<Unit, Unit>();
        // Clone units in body's statement list
        for (Unit original : grimpBody.getUnits()) {
            Unit copy = (Unit) original.clone();
            // Add cloned unit to our unitChain.
            getUnits().addLast(copy);
            // Build old <-> new map to be able to patch up references to other units
            // within the cloned units. (these are still refering to the original
            // unit objects).
            bindings.put(original, copy);
            reverse_binding.put(copy, original);
        }
        // patch up the switch statments
        for (Unit u : getUnits()) {
            Stmt s = (Stmt) u;
            if (s instanceof TableSwitchStmt) {
                TableSwitchStmt ts = (TableSwitchStmt) s;
                TableSwitchStmt original_switch = (TableSwitchStmt) reverse_binding.get(u);
                ts.setDefaultTarget((Unit) bindings.get(original_switch.getDefaultTarget()));
                LinkedList<Unit> new_target_list = new LinkedList<Unit>();
                int target_count = ts.getHighIndex() - ts.getLowIndex() + 1;
                for (int i = 0; i < target_count; i++) new_target_list.add((Unit) bindings.get(original_switch.getTarget(i)));
                ts.setTargets(new_target_list);
            }
            if (s instanceof LookupSwitchStmt) {
                LookupSwitchStmt ls = (LookupSwitchStmt) s;
                LookupSwitchStmt original_switch = (LookupSwitchStmt) reverse_binding.get(u);
                ls.setDefaultTarget((Unit) bindings.get(original_switch.getDefaultTarget()));
                Unit[] new_target_list = new Unit[original_switch.getTargetCount()];
                for (int i = 0; i < original_switch.getTargetCount(); i++) new_target_list[i] = (Unit) (bindings.get(original_switch.getTarget(i)));
                ls.setTargets(new_target_list);
                ls.setLookupValues(original_switch.getLookupValues());
            }
        }
        // Clone locals.
        for (Local original : grimpBody.getLocals()) {
            Local copy = Dava.v().newLocal(original.getName(), original.getType());
            getLocals().add(copy);
            // Build old <-> new mapping.
            bindings.put(original, copy);
        }
        // Patch up references within units using our (old <-> new) map.
        for (UnitBox box : getAllUnitBoxes()) {
            Unit newObject, oldObject = box.getUnit();
            // it's clone.
            if ((newObject = (Unit) bindings.get(oldObject)) != null)
                box.setUnit(newObject);
        }
        // backpatch all local variables.
        for (ValueBox vb : getUseAndDefBoxes()) {
            if (vb.getValue() instanceof Local)
                vb.setValue((Value) bindings.get(vb.getValue()));
        }
        // clone the traps
        for (Trap originalTrap : grimpBody.getTraps()) {
            Trap cloneTrap = (Trap) originalTrap.clone();
            Unit handlerUnit = (Unit) bindings.get(originalTrap.getHandlerUnit());
            cloneTrap.setHandlerUnit(handlerUnit);
            cloneTrap.setBeginUnit((Unit) bindings.get(originalTrap.getBeginUnit()));
            cloneTrap.setEndUnit((Unit) bindings.get(originalTrap.getEndUnit()));
            getTraps().add(cloneTrap);
        }
    }
    /*
		 *  Add one level of indirection to "if", "switch", and exceptional control flow.
		 *  This allows for easy handling of breaks, continues and exceptional loops.
		 */
    {
        PatchingChain<Unit> units = getUnits();
        Iterator<Unit> it = units.snapshotIterator();
        while (it.hasNext()) {
            Unit u = it.next();
            Stmt s = (Stmt) u;
            if (s instanceof IfStmt) {
                IfStmt ifs = (IfStmt) s;
                JGotoStmt jgs = new JGotoStmt((Unit) units.getSuccOf(u));
                units.insertAfter(jgs, u);
                JGotoStmt jumper = new JGotoStmt((Unit) ifs.getTarget());
                units.insertAfter(jumper, jgs);
                ifs.setTarget((Unit) jumper);
            } else if (s instanceof TableSwitchStmt) {
                TableSwitchStmt tss = (TableSwitchStmt) s;
                int targetCount = tss.getHighIndex() - tss.getLowIndex() + 1;
                for (int i = 0; i < targetCount; i++) {
                    JGotoStmt jgs = new JGotoStmt((Unit) tss.getTarget(i));
                    units.insertAfter(jgs, tss);
                    tss.setTarget(i, (Unit) jgs);
                }
                JGotoStmt jgs = new JGotoStmt((Unit) tss.getDefaultTarget());
                units.insertAfter(jgs, tss);
                tss.setDefaultTarget((Unit) jgs);
            } else if (s instanceof LookupSwitchStmt) {
                LookupSwitchStmt lss = (LookupSwitchStmt) s;
                for (int i = 0; i < lss.getTargetCount(); i++) {
                    JGotoStmt jgs = new JGotoStmt((Unit) lss.getTarget(i));
                    units.insertAfter(jgs, lss);
                    lss.setTarget(i, (Unit) jgs);
                }
                JGotoStmt jgs = new JGotoStmt((Unit) lss.getDefaultTarget());
                units.insertAfter(jgs, lss);
                lss.setDefaultTarget((Unit) jgs);
            }
        }
        for (Trap t : getTraps()) {
            JGotoStmt jgs = new JGotoStmt((Unit) t.getHandlerUnit());
            units.addLast(jgs);
            t.setHandlerUnit((Unit) jgs);
        }
    }
    /*
		 *  Fix up the grimp representations of statements so they can be compiled as java.
		 */
    {
        for (Local l : getLocals()) {
            Type t = l.getType();
            if (t instanceof RefType) {
                RefType rt = (RefType) t;
                String className = rt.getSootClass().toString();
                String packageName = rt.getSootClass().getJavaPackageName();
                String classPackageName = packageName;
                if (className.lastIndexOf('.') > 0) {
                    // 0 doesnt make sense
                    classPackageName = className.substring(0, className.lastIndexOf('.'));
                }
                if (!packageName.equals(classPackageName))
                    throw new DecompilationException("Unable to retrieve package name for identifier. Please report to developer.");
                addToImportList(className);
            // addPackage(rt.getSootClass().getJavaPackageName());
            }
        }
        for (Unit u : getUnits()) {
            Stmt s = (Stmt) u;
            if (s instanceof IfStmt)
                javafy(((IfStmt) s).getConditionBox());
            else if (s instanceof ThrowStmt)
                javafy(((ThrowStmt) s).getOpBox());
            else if (s instanceof TableSwitchStmt)
                javafy(((TableSwitchStmt) s).getKeyBox());
            else if (s instanceof LookupSwitchStmt)
                javafy(((LookupSwitchStmt) s).getKeyBox());
            else if (s instanceof MonitorStmt)
                javafy(((MonitorStmt) s).getOpBox());
            else if (s instanceof DefinitionStmt) {
                DefinitionStmt ds = (DefinitionStmt) s;
                javafy(ds.getRightOpBox());
                javafy(ds.getLeftOpBox());
                if (ds.getRightOp() instanceof IntConstant)
                    ds.getRightOpBox().setValue(DIntConstant.v(((IntConstant) ds.getRightOp()).value, ds.getLeftOp().getType()));
            } else if (s instanceof ReturnStmt) {
                ReturnStmt rs = (ReturnStmt) s;
                if (rs.getOp() instanceof IntConstant)
                    rs.getOpBox().setValue(DIntConstant.v(((IntConstant) rs.getOp()).value, body.getMethod().getReturnType()));
                else
                    javafy(rs.getOpBox());
            } else if (s instanceof InvokeStmt)
                javafy(((InvokeStmt) s).getInvokeExprBox());
        }
    }
    /*
		 *  Convert references to "this" and parameters.
		 */
    {
        for (Unit u : getUnits()) {
            Stmt s = (Stmt) u;
            if (s instanceof IdentityStmt) {
                IdentityStmt ids = (IdentityStmt) s;
                Value ids_rightOp = ids.getRightOp();
                Value ids_leftOp = ids.getLeftOp();
                if ((ids_leftOp instanceof Local) && (ids_rightOp instanceof ThisRef)) {
                    Local thisLocal = (Local) ids_leftOp;
                    thisLocals.add(thisLocal);
                    thisLocal.setName("this");
                }
            }
            if (s instanceof DefinitionStmt) {
                DefinitionStmt ds = (DefinitionStmt) s;
                Value rightOp = ds.getRightOp();
                if (rightOp instanceof ParameterRef)
                    pMap.put(((ParameterRef) rightOp).getIndex(), ds.getLeftOp());
                if (rightOp instanceof CaughtExceptionRef)
                    caughtrefs.add((CaughtExceptionRef) rightOp);
            }
        }
    }
    /*
		 *  Fix up the calls to other constructors.  Note, this is seriously underbuilt.
		 */
    {
        for (Unit u : getUnits()) {
            Stmt s = (Stmt) u;
            if (s instanceof InvokeStmt) {
                InvokeStmt ivs = (InvokeStmt) s;
                Value ie = ivs.getInvokeExpr();
                if (ie instanceof InstanceInvokeExpr) {
                    InstanceInvokeExpr iie = (InstanceInvokeExpr) ie;
                    Value base = iie.getBase();
                    if ((base instanceof Local) && (((Local) base).getName().equals("this"))) {
                        SootMethodRef m = iie.getMethodRef();
                        String name = m.name();
                        if ((name.equals(SootMethod.constructorName)) || (name.equals(SootMethod.staticInitializerName))) {
                            if (constructorUnit != null)
                                throw new RuntimeException("More than one candidate for constructor found.");
                            constructorExpr = iie;
                            constructorUnit = (Unit) s;
                        }
                    }
                }
            }
        }
    }
}
Also used : InvokeStmt(soot.jimple.InvokeStmt) CaughtExceptionRef(soot.jimple.CaughtExceptionRef) HashMap(java.util.HashMap) Switchable(soot.util.Switchable) Unit(soot.Unit) AugmentedStmt(soot.dava.internal.asg.AugmentedStmt) JGotoStmt(soot.jimple.internal.JGotoStmt) IfStmt(soot.jimple.IfStmt) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) Stmt(soot.jimple.Stmt) DefinitionStmt(soot.jimple.DefinitionStmt) InvokeStmt(soot.jimple.InvokeStmt) ThrowStmt(soot.jimple.ThrowStmt) IdentityStmt(soot.jimple.IdentityStmt) TableSwitchStmt(soot.jimple.TableSwitchStmt) MonitorStmt(soot.jimple.MonitorStmt) ReturnStmt(soot.jimple.ReturnStmt) RefType(soot.RefType) TableSwitchStmt(soot.jimple.TableSwitchStmt) Iterator(java.util.Iterator) IntConstant(soot.jimple.IntConstant) DIntConstant(soot.dava.internal.javaRep.DIntConstant) GrimpBody(soot.grimp.GrimpBody) IdentityStmt(soot.jimple.IdentityStmt) UnitBox(soot.UnitBox) PatchingChain(soot.PatchingChain) SootMethodRef(soot.SootMethodRef) JimpleLocal(soot.jimple.internal.JimpleLocal) Local(soot.Local) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) Trap(soot.Trap) MonitorStmt(soot.jimple.MonitorStmt) LinkedList(java.util.LinkedList) JGotoStmt(soot.jimple.internal.JGotoStmt) Type(soot.Type) RefType(soot.RefType) IntType(soot.IntType) IfStmt(soot.jimple.IfStmt) ParameterRef(soot.jimple.ParameterRef) DThisRef(soot.dava.internal.javaRep.DThisRef) ThisRef(soot.jimple.ThisRef) ValueBox(soot.ValueBox) Value(soot.Value) ThrowStmt(soot.jimple.ThrowStmt) DefinitionStmt(soot.jimple.DefinitionStmt) ReturnStmt(soot.jimple.ReturnStmt)

Example 7 with IdentityStmt

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

the class DexNumTransformer method internalTransform.

@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
    final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
    for (Local loc : getNumCandidates(body)) {
        usedAsFloatingPoint = false;
        Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
        // process normally
        doBreak = false;
        for (Unit u : defs) {
            // put correct local in l
            final Local l = u instanceof DefinitionStmt ? (Local) ((DefinitionStmt) u).getLeftOp() : null;
            // check defs
            u.apply(new AbstractStmtSwitch() {

                @Override
                public void caseAssignStmt(AssignStmt stmt) {
                    Value r = stmt.getRightOp();
                    if (r instanceof BinopExpr && !(r instanceof CmpExpr)) {
                        usedAsFloatingPoint = examineBinopExpr(stmt);
                        doBreak = true;
                    } else if (r instanceof FieldRef) {
                        usedAsFloatingPoint = isFloatingPointLike(((FieldRef) r).getFieldRef().type());
                        doBreak = true;
                    } else if (r instanceof NewArrayExpr) {
                        NewArrayExpr nae = (NewArrayExpr) r;
                        Type t = nae.getType();
                        usedAsFloatingPoint = isFloatingPointLike(t);
                        doBreak = true;
                    } else if (r instanceof ArrayRef) {
                        ArrayRef ar = (ArrayRef) r;
                        Type arType = ar.getType();
                        if (arType instanceof UnknownType) {
                            Type t = findArrayType(localDefs, stmt, 0, // TODO:
                            Collections.<Unit>emptySet());
                            // check
                            // where
                            // else
                            // to
                            // update
                            // if(ArrayRef...
                            usedAsFloatingPoint = isFloatingPointLike(t);
                        } else {
                            usedAsFloatingPoint = isFloatingPointLike(ar.getType());
                        }
                        doBreak = true;
                    } else if (r instanceof CastExpr) {
                        usedAsFloatingPoint = isFloatingPointLike(((CastExpr) r).getCastType());
                        doBreak = true;
                    } else if (r instanceof InvokeExpr) {
                        usedAsFloatingPoint = isFloatingPointLike(((InvokeExpr) r).getType());
                        doBreak = true;
                    } else if (r instanceof LengthExpr) {
                        usedAsFloatingPoint = false;
                        doBreak = true;
                    }
                }

                @Override
                public void caseIdentityStmt(IdentityStmt stmt) {
                    if (stmt.getLeftOp() == l) {
                        usedAsFloatingPoint = isFloatingPointLike(stmt.getRightOp().getType());
                        doBreak = true;
                    }
                }
            });
            if (doBreak) {
                break;
            }
            // check uses
            for (Unit use : localDefs.getUsesOf(l)) {
                use.apply(new AbstractStmtSwitch() {

                    private boolean examineInvokeExpr(InvokeExpr e) {
                        List<Value> args = e.getArgs();
                        List<Type> argTypes = e.getMethodRef().parameterTypes();
                        assert args.size() == argTypes.size();
                        for (int i = 0; i < args.size(); i++) {
                            if (args.get(i) == l && isFloatingPointLike(argTypes.get(i))) {
                                return true;
                            }
                        }
                        return false;
                    }

                    @Override
                    public void caseInvokeStmt(InvokeStmt stmt) {
                        InvokeExpr e = stmt.getInvokeExpr();
                        usedAsFloatingPoint = examineInvokeExpr(e);
                    }

                    @Override
                    public void caseAssignStmt(AssignStmt stmt) {
                        // only case where 'l' could be on the left side is
                        // arrayRef with 'l' as the index
                        Value left = stmt.getLeftOp();
                        if (left instanceof ArrayRef) {
                            ArrayRef ar = (ArrayRef) left;
                            if (ar.getIndex() == l) {
                                doBreak = true;
                                return;
                            }
                        }
                        // from this point, we only check the right hand
                        // side of the assignment
                        Value r = stmt.getRightOp();
                        if (r instanceof ArrayRef) {
                            if (((ArrayRef) r).getIndex() == l) {
                                doBreak = true;
                                return;
                            }
                        } else if (r instanceof InvokeExpr) {
                            usedAsFloatingPoint = examineInvokeExpr((InvokeExpr) r);
                            doBreak = true;
                            return;
                        } else if (r instanceof BinopExpr) {
                            usedAsFloatingPoint = examineBinopExpr(stmt);
                            doBreak = true;
                            return;
                        } else if (r instanceof CastExpr) {
                            usedAsFloatingPoint = stmt.hasTag("FloatOpTag") || stmt.hasTag("DoubleOpTag");
                            doBreak = true;
                            return;
                        } else if (r instanceof Local && r == l) {
                            if (left instanceof FieldRef) {
                                FieldRef fr = (FieldRef) left;
                                if (isFloatingPointLike(fr.getType())) {
                                    usedAsFloatingPoint = true;
                                }
                                doBreak = true;
                                return;
                            } else if (left instanceof ArrayRef) {
                                ArrayRef ar = (ArrayRef) left;
                                Type arType = ar.getType();
                                if (arType instanceof UnknownType) {
                                    arType = findArrayType(localDefs, stmt, 0, Collections.<Unit>emptySet());
                                }
                                usedAsFloatingPoint = isFloatingPointLike(arType);
                                doBreak = true;
                                return;
                            }
                        }
                    }

                    @Override
                    public void caseReturnStmt(ReturnStmt stmt) {
                        usedAsFloatingPoint = stmt.getOp() == l && isFloatingPointLike(body.getMethod().getReturnType());
                        doBreak = true;
                        return;
                    }
                });
                if (doBreak)
                    break;
            }
            // for uses
            if (doBreak)
                break;
        }
        // change values
        if (usedAsFloatingPoint) {
            for (Unit u : defs) {
                replaceWithFloatingPoint(u);
            }
        }
    // end if
    }
}
Also used : FieldRef(soot.jimple.FieldRef) InvokeStmt(soot.jimple.InvokeStmt) AssignStmt(soot.jimple.AssignStmt) LengthExpr(soot.jimple.LengthExpr) Local(soot.Local) Unit(soot.Unit) ArrayRef(soot.jimple.ArrayRef) UnknownType(soot.UnknownType) UnknownType(soot.UnknownType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) Type(soot.Type) InvokeExpr(soot.jimple.InvokeExpr) NewArrayExpr(soot.jimple.NewArrayExpr) CmpExpr(soot.jimple.CmpExpr) AbstractStmtSwitch(soot.jimple.AbstractStmtSwitch) Value(soot.Value) CastExpr(soot.jimple.CastExpr) List(java.util.List) DefinitionStmt(soot.jimple.DefinitionStmt) ReturnStmt(soot.jimple.ReturnStmt) IdentityStmt(soot.jimple.IdentityStmt) BinopExpr(soot.jimple.BinopExpr)

Example 8 with IdentityStmt

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

the class DexTransformer method findArrayType.

protected Type findArrayType(LocalDefs localDefs, Stmt arrayStmt, int depth, Set<Unit> alreadyVisitedDefs) {
    ArrayRef aRef = null;
    if (arrayStmt.containsArrayRef()) {
        aRef = arrayStmt.getArrayRef();
    }
    Local aBase = null;
    if (null == aRef) {
        if (arrayStmt instanceof AssignStmt) {
            AssignStmt stmt = (AssignStmt) arrayStmt;
            aBase = (Local) stmt.getRightOp();
        } else {
            throw new RuntimeException("ERROR: not an assign statement: " + arrayStmt);
        }
    } else {
        aBase = (Local) aRef.getBase();
    }
    List<Unit> defsOfaBaseList = localDefs.getDefsOfAt(aBase, arrayStmt);
    if (defsOfaBaseList == null || defsOfaBaseList.isEmpty()) {
        throw new RuntimeException("ERROR: no def statement found for array base local " + arrayStmt);
    }
    // We should find an answer only by processing the first item of the
    // list
    Type aType = null;
    int nullDefCount = 0;
    for (Unit baseDef : defsOfaBaseList) {
        if (alreadyVisitedDefs.contains(baseDef))
            continue;
        Set<Unit> newVisitedDefs = new HashSet<Unit>(alreadyVisitedDefs);
        newVisitedDefs.add(baseDef);
        // statement
        if (baseDef instanceof AssignStmt) {
            AssignStmt stmt = (AssignStmt) baseDef;
            Value r = stmt.getRightOp();
            if (r instanceof FieldRef) {
                Type t = ((FieldRef) r).getFieldRef().type();
                if (t instanceof ArrayType) {
                    ArrayType at = (ArrayType) t;
                    t = at.getArrayElementType();
                }
                if (depth == 0) {
                    aType = t;
                    break;
                } else {
                    return t;
                }
            } else if (r instanceof ArrayRef) {
                ArrayRef ar = (ArrayRef) r;
                if (ar.getType().toString().equals(".unknown") || ar.getType().toString().equals("unknown")) {
                    // ||
                    // ar.getType())
                    // {
                    Type t = findArrayType(localDefs, stmt, ++depth, // TODO: which type should be
                    newVisitedDefs);
                    // returned?
                    if (t instanceof ArrayType) {
                        ArrayType at = (ArrayType) t;
                        t = at.getArrayElementType();
                    }
                    if (depth == 0) {
                        aType = t;
                        break;
                    } else {
                        return t;
                    }
                } else {
                    ArrayType at = (ArrayType) stmt.getRightOp().getType();
                    Type t = at.getArrayElementType();
                    if (depth == 0) {
                        aType = t;
                        break;
                    } else {
                        return t;
                    }
                }
            } else if (r instanceof NewArrayExpr) {
                NewArrayExpr expr = (NewArrayExpr) r;
                Type t = expr.getBaseType();
                if (depth == 0) {
                    aType = t;
                    break;
                } else {
                    return t;
                }
            } else if (r instanceof CastExpr) {
                Type t = (((CastExpr) r).getCastType());
                if (t instanceof ArrayType) {
                    ArrayType at = (ArrayType) t;
                    t = at.getArrayElementType();
                }
                if (depth == 0) {
                    aType = t;
                    break;
                } else {
                    return t;
                }
            } else if (r instanceof InvokeExpr) {
                Type t = ((InvokeExpr) r).getMethodRef().returnType();
                if (t instanceof ArrayType) {
                    ArrayType at = (ArrayType) t;
                    t = at.getArrayElementType();
                }
                if (depth == 0) {
                    aType = t;
                    break;
                } else {
                    return t;
                }
            // introduces alias. We look whether there is any type
            // information associated with the alias.
            } else if (r instanceof Local) {
                Type t = findArrayType(localDefs, stmt, ++depth, newVisitedDefs);
                if (depth == 0) {
                    aType = t;
                // break;
                } else {
                    // return t;
                    aType = t;
                }
            } else if (r instanceof Constant) {
                // If the right side is a null constant, we might have a
                // case of broken code, e.g.,
                // a = null;
                // a[12] = 42;
                nullDefCount++;
            } else {
                throw new RuntimeException("ERROR: def statement not possible! " + stmt);
            }
        } else if (baseDef instanceof IdentityStmt) {
            IdentityStmt stmt = (IdentityStmt) baseDef;
            ArrayType at = (ArrayType) stmt.getRightOp().getType();
            Type t = at.getArrayElementType();
            if (depth == 0) {
                aType = t;
                break;
            } else {
                return t;
            }
        } else {
            throw new RuntimeException("ERROR: base local def must be AssignStmt or IdentityStmt! " + baseDef);
        }
        if (aType != null)
            break;
    }
    if (depth == 0 && aType == null) {
        if (nullDefCount == defsOfaBaseList.size()) {
            return NullType.v();
        } else {
            throw new RuntimeException("ERROR: could not find type of array from statement '" + arrayStmt + "'");
        }
    } else
        return aType;
}
Also used : FieldRef(soot.jimple.FieldRef) AssignStmt(soot.jimple.AssignStmt) Constant(soot.jimple.Constant) Local(soot.Local) Unit(soot.Unit) ArrayRef(soot.jimple.ArrayRef) ArrayType(soot.ArrayType) ArrayType(soot.ArrayType) Type(soot.Type) NullType(soot.NullType) InvokeExpr(soot.jimple.InvokeExpr) NewArrayExpr(soot.jimple.NewArrayExpr) Value(soot.Value) CastExpr(soot.jimple.CastExpr) IdentityStmt(soot.jimple.IdentityStmt) HashSet(java.util.HashSet)

Example 9 with IdentityStmt

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

the class DexNullTransformer method internalTransform.

@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
    final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
    AbstractStmtSwitch checkDef = new // Alex: should also end as
    AbstractStmtSwitch() {

        // soon as detected as not
        // used as an object
        @Override
        public void caseAssignStmt(AssignStmt stmt) {
            Value r = stmt.getRightOp();
            if (r instanceof FieldRef) {
                usedAsObject = isObject(((FieldRef) r).getFieldRef().type());
                doBreak = true;
                return;
            } else if (r instanceof ArrayRef) {
                ArrayRef ar = (ArrayRef) r;
                if (ar.getType() instanceof UnknownType) {
                    // isObject
                    usedAsObject = stmt.hasTag("ObjectOpTag");
                // (findArrayType
                // (g,
                // localDefs,
                // localUses,
                // stmt));
                } else {
                    usedAsObject = isObject(ar.getType());
                }
                doBreak = true;
                return;
            } else if (r instanceof StringConstant || r instanceof NewExpr || r instanceof NewArrayExpr) {
                usedAsObject = true;
                doBreak = true;
                return;
            } else if (r instanceof CastExpr) {
                usedAsObject = isObject(((CastExpr) r).getCastType());
                doBreak = true;
                return;
            } else if (r instanceof InvokeExpr) {
                usedAsObject = isObject(((InvokeExpr) r).getType());
                doBreak = true;
                return;
            } else if (r instanceof LengthExpr) {
                usedAsObject = false;
                doBreak = true;
                return;
            // introduces alias
            }
        }

        @Override
        public void caseIdentityStmt(IdentityStmt stmt) {
            if (stmt.getLeftOp() == l) {
                usedAsObject = isObject(stmt.getRightOp().getType());
                doBreak = true;
                return;
            }
        }
    };
    AbstractStmtSwitch checkUse = new AbstractStmtSwitch() {

        private boolean examineInvokeExpr(InvokeExpr e) {
            List<Value> args = e.getArgs();
            List<Type> argTypes = e.getMethodRef().parameterTypes();
            assert args.size() == argTypes.size();
            for (int i = 0; i < args.size(); i++) {
                if (args.get(i) == l && isObject(argTypes.get(i))) {
                    return true;
                }
            }
            // check for base
            SootMethodRef sm = e.getMethodRef();
            if (!sm.isStatic()) {
                if (e instanceof AbstractInvokeExpr) {
                    AbstractInstanceInvokeExpr aiiexpr = (AbstractInstanceInvokeExpr) e;
                    Value b = aiiexpr.getBase();
                    if (b == l) {
                        return true;
                    }
                }
            }
            return false;
        }

        @Override
        public void caseInvokeStmt(InvokeStmt stmt) {
            InvokeExpr e = stmt.getInvokeExpr();
            usedAsObject = examineInvokeExpr(e);
            doBreak = true;
            return;
        }

        @Override
        public void caseAssignStmt(AssignStmt stmt) {
            Value left = stmt.getLeftOp();
            Value r = stmt.getRightOp();
            if (left instanceof ArrayRef) {
                ArrayRef ar = (ArrayRef) left;
                if (ar.getIndex() == l) {
                    doBreak = true;
                    return;
                } else if (ar.getBase() == l) {
                    usedAsObject = true;
                    doBreak = true;
                    return;
                }
            }
            if (left instanceof InstanceFieldRef) {
                InstanceFieldRef ifr = (InstanceFieldRef) left;
                if (ifr.getBase() == l) {
                    usedAsObject = true;
                    doBreak = true;
                    return;
                }
            }
            // used to assign
            if (stmt.getRightOp() == l) {
                Value l = stmt.getLeftOp();
                if (l instanceof StaticFieldRef && isObject(((StaticFieldRef) l).getFieldRef().type())) {
                    usedAsObject = true;
                    doBreak = true;
                    return;
                } else if (l instanceof InstanceFieldRef && isObject(((InstanceFieldRef) l).getFieldRef().type())) {
                    usedAsObject = true;
                    doBreak = true;
                    return;
                } else if (l instanceof ArrayRef) {
                    Type aType = ((ArrayRef) l).getType();
                    if (aType instanceof UnknownType) {
                        usedAsObject = stmt.hasTag(// isObject(
                        "ObjectOpTag");
                    // findArrayType(g,
                    // localDefs,
                    // localUses,
                    // stmt));
                    } else {
                        usedAsObject = isObject(aType);
                    }
                    doBreak = true;
                    return;
                }
            }
            // is used as value (does not exclude assignment)
            if (r instanceof FieldRef) {
                // isObject(((FieldRef)
                usedAsObject = true;
                // r).getFieldRef().type());
                doBreak = true;
                return;
            } else if (r instanceof ArrayRef) {
                ArrayRef ar = (ArrayRef) r;
                if (ar.getBase() == l) {
                    usedAsObject = true;
                } else {
                    // used as index
                    usedAsObject = false;
                }
                doBreak = true;
                return;
            } else if (r instanceof StringConstant || r instanceof NewExpr) {
                throw new RuntimeException("NOT POSSIBLE StringConstant or NewExpr at " + stmt);
            } else if (r instanceof NewArrayExpr) {
                usedAsObject = false;
                doBreak = true;
                return;
            } else if (r instanceof CastExpr) {
                usedAsObject = isObject(((CastExpr) r).getCastType());
                doBreak = true;
                return;
            } else if (r instanceof InvokeExpr) {
                usedAsObject = examineInvokeExpr((InvokeExpr) stmt.getRightOp());
                doBreak = true;
                return;
            } else if (r instanceof LengthExpr) {
                usedAsObject = true;
                doBreak = true;
                return;
            } else if (r instanceof BinopExpr) {
                usedAsObject = false;
                doBreak = true;
                return;
            }
        }

        @Override
        public void caseIdentityStmt(IdentityStmt stmt) {
            if (stmt.getLeftOp() == l)
                throw new RuntimeException("IMPOSSIBLE 0");
        }

        @Override
        public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
            usedAsObject = stmt.getOp() == l;
            doBreak = true;
            return;
        }

        @Override
        public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
            usedAsObject = stmt.getOp() == l;
            doBreak = true;
            return;
        }

        @Override
        public void caseReturnStmt(ReturnStmt stmt) {
            usedAsObject = stmt.getOp() == l && isObject(body.getMethod().getReturnType());
            doBreak = true;
            return;
        }

        @Override
        public void caseThrowStmt(ThrowStmt stmt) {
            usedAsObject = stmt.getOp() == l;
            doBreak = true;
            return;
        }
    };
    for (Local loc : getNullCandidates(body)) {
        usedAsObject = false;
        Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
        // process normally
        doBreak = false;
        for (Unit u : defs) {
            // put correct local in l
            if (u instanceof DefinitionStmt) {
                l = (Local) ((DefinitionStmt) u).getLeftOp();
            } else if (u instanceof IfStmt) {
                throw new RuntimeException("ERROR: def can not be something else than Assign or Identity statement! (def: " + u + " class: " + u.getClass() + "");
            }
            // check defs
            u.apply(checkDef);
            if (doBreak)
                break;
            // check uses
            for (Unit use : localDefs.getUsesOf(l)) {
                use.apply(checkUse);
                if (doBreak)
                    break;
            }
            // for uses
            if (doBreak)
                break;
        }
        // change values
        if (usedAsObject) {
            for (Unit u : defs) {
                replaceWithNull(u);
                Set<Value> defLocals = new HashSet<Value>();
                for (ValueBox vb : u.getDefBoxes()) defLocals.add(vb.getValue());
                Local l = (Local) ((DefinitionStmt) u).getLeftOp();
                for (Unit uuse : localDefs.getUsesOf(l)) {
                    Stmt use = (Stmt) uuse;
                    // If we have a[x] = 0 and a is an object, we may not conclude 0 -> null
                    if (!use.containsArrayRef() || !defLocals.contains(use.getArrayRef().getBase()))
                        replaceWithNull(use);
                }
            }
        }
    // end if
    }
    // Check for inlined zero values
    AbstractStmtSwitch inlinedZeroValues = new AbstractStmtSwitch() {

        final NullConstant nullConstant = NullConstant.v();

        @Override
        public void caseAssignStmt(AssignStmt stmt) {
            // Case a = 0 with a being an object
            if (isObject(stmt.getLeftOp().getType()) && isConstZero(stmt.getRightOp())) {
                stmt.setRightOp(nullConstant);
                return;
            }
            // Case a = (Object) 0
            if (stmt.getRightOp() instanceof CastExpr) {
                CastExpr ce = (CastExpr) stmt.getRightOp();
                if (isObject(ce.getCastType()) && isConstZero(ce.getOp())) {
                    stmt.setRightOp(nullConstant);
                }
            }
            // Case a[0] = 0
            if (stmt.getLeftOp() instanceof ArrayRef && isConstZero(stmt.getRightOp())) {
                ArrayRef ar = (ArrayRef) stmt.getLeftOp();
                if (isObjectArray(ar.getBase(), body) || stmt.hasTag("ObjectOpTag")) {
                    stmt.setRightOp(nullConstant);
                }
            }
        }

        private boolean isConstZero(Value rightOp) {
            if (rightOp instanceof IntConstant && ((IntConstant) rightOp).value == 0)
                return true;
            if (rightOp instanceof LongConstant && ((LongConstant) rightOp).value == 0)
                return true;
            return false;
        }

        @Override
        public void caseReturnStmt(ReturnStmt stmt) {
            if (stmt.getOp() instanceof IntConstant && isObject(body.getMethod().getReturnType())) {
                IntConstant iconst = (IntConstant) stmt.getOp();
                assert iconst.value == 0;
                stmt.setOp(nullConstant);
            }
        }

        @Override
        public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
            if (stmt.getOp() instanceof IntConstant && ((IntConstant) stmt.getOp()).value == 0)
                stmt.setOp(nullConstant);
        }

        @Override
        public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
            if (stmt.getOp() instanceof IntConstant && ((IntConstant) stmt.getOp()).value == 0)
                stmt.setOp(nullConstant);
        }
    };
    final NullConstant nullConstant = NullConstant.v();
    for (Unit u : body.getUnits()) {
        u.apply(inlinedZeroValues);
        if (u instanceof Stmt) {
            Stmt stmt = (Stmt) u;
            if (stmt.containsInvokeExpr()) {
                InvokeExpr invExpr = stmt.getInvokeExpr();
                for (int i = 0; i < invExpr.getArgCount(); i++) if (isObject(invExpr.getMethodRef().parameterType(i)))
                    if (invExpr.getArg(i) instanceof IntConstant) {
                        IntConstant iconst = (IntConstant) invExpr.getArg(i);
                        assert iconst.value == 0;
                        invExpr.setArg(i, nullConstant);
                    }
            }
        }
    }
}
Also used : ExitMonitorStmt(soot.jimple.ExitMonitorStmt) InvokeStmt(soot.jimple.InvokeStmt) AssignStmt(soot.jimple.AssignStmt) Unit(soot.Unit) InvokeStmt(soot.jimple.InvokeStmt) ThrowStmt(soot.jimple.ThrowStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) ReturnStmt(soot.jimple.ReturnStmt) ExitMonitorStmt(soot.jimple.ExitMonitorStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) DefinitionStmt(soot.jimple.DefinitionStmt) ArrayRef(soot.jimple.ArrayRef) AbstractInvokeExpr(soot.jimple.internal.AbstractInvokeExpr) AbstractInstanceInvokeExpr(soot.jimple.internal.AbstractInstanceInvokeExpr) AbstractInvokeExpr(soot.jimple.internal.AbstractInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) AbstractInstanceInvokeExpr(soot.jimple.internal.AbstractInstanceInvokeExpr) AbstractStmtSwitch(soot.jimple.AbstractStmtSwitch) CastExpr(soot.jimple.CastExpr) InstanceFieldRef(soot.jimple.InstanceFieldRef) IntConstant(soot.jimple.IntConstant) IdentityStmt(soot.jimple.IdentityStmt) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) HashSet(java.util.HashSet) LongConstant(soot.jimple.LongConstant) FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) SootMethodRef(soot.SootMethodRef) LengthExpr(soot.jimple.LengthExpr) Local(soot.Local) NullConstant(soot.jimple.NullConstant) StaticFieldRef(soot.jimple.StaticFieldRef) UnknownType(soot.UnknownType) UnknownType(soot.UnknownType) ArrayType(soot.ArrayType) Type(soot.Type) IfStmt(soot.jimple.IfStmt) NewArrayExpr(soot.jimple.NewArrayExpr) ValueBox(soot.ValueBox) Value(soot.Value) NewExpr(soot.jimple.NewExpr) StringConstant(soot.jimple.StringConstant) ReturnStmt(soot.jimple.ReturnStmt) ThrowStmt(soot.jimple.ThrowStmt) DefinitionStmt(soot.jimple.DefinitionStmt) BinopExpr(soot.jimple.BinopExpr)

Example 10 with IdentityStmt

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

the class OutFlow method jimplify.

/**
 * Main.v() entry point for converting list of Instructions to Jimple statements;
 * performs flow analysis, constructs Jimple statements, and fixes jumps.
 * @param constant_pool constant pool of ClassFile.
 * @param this_class constant pool index of the CONSTANT_Class_info object for
 * this' class.
 * @param clearStacks if <i>true</i> semantic stacks will be deleted after
 * the process is complete.
 * @return <i>true</i> if all ok, <i>false</i> if there was an error.
 * @see CFG#jimplify(cp_info[], int)
 * @see Stmt
 */
void jimplify(cp_info[] constant_pool, int this_class) {
    Code_attribute codeAttribute = method.locate_code_attribute();
    Set<Instruction> handlerInstructions = new ArraySet<Instruction>();
    Map<Instruction, SootClass> handlerInstructionToException = new HashMap<Instruction, SootClass>();
    Map<Instruction, TypeStack> instructionToTypeStack;
    Map<Instruction, TypeStack> instructionToPostTypeStack;
    {
        // build graph in
        buildInsnCFGfromBBCFG();
        // Put in successors due to exception handlers
        {
            for (int i = 0; i < codeAttribute.exception_table_length; i++) {
                Instruction startIns = codeAttribute.exception_table[i].start_inst;
                Instruction endIns = codeAttribute.exception_table[i].end_inst;
                Instruction handlerIns = codeAttribute.exception_table[i].handler_inst;
                handlerInstructions.add(handlerIns);
                // Determine exception to catch
                {
                    int catchType = codeAttribute.exception_table[i].catch_type;
                    SootClass exception;
                    if (catchType != 0) {
                        CONSTANT_Class_info classinfo = (CONSTANT_Class_info) constant_pool[catchType];
                        String name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index])).convert();
                        name = name.replace('/', '.');
                        exception = cm.getSootClass(name);
                    } else
                        exception = cm.getSootClass("java.lang.Throwable");
                    handlerInstructionToException.put(handlerIns, exception);
                }
                if (startIns == endIns)
                    throw new RuntimeException("Empty catch range for exception handler");
                Instruction ins = startIns;
                for (; ; ) {
                    Instruction[] succs = ins.succs;
                    Instruction[] newsuccs = new Instruction[succs.length + 1];
                    System.arraycopy(succs, 0, newsuccs, 0, succs.length);
                    newsuccs[succs.length] = handlerIns;
                    ins.succs = newsuccs;
                    ins = ins.next;
                    if (ins == endIns || ins == null)
                        break;
                }
            }
        }
    }
    Set<Instruction> reachableInstructions = new HashSet<Instruction>();
    // Mark all the reachable instructions
    {
        LinkedList<Instruction> instructionsToVisit = new LinkedList<Instruction>();
        reachableInstructions.add(firstInstruction);
        instructionsToVisit.addLast(firstInstruction);
        while (!instructionsToVisit.isEmpty()) {
            Instruction ins = instructionsToVisit.removeFirst();
            Instruction[] succs = ins.succs;
            for (Instruction succ : succs) {
                if (!reachableInstructions.contains(succ)) {
                    reachableInstructions.add(succ);
                    instructionsToVisit.addLast(succ);
                }
            }
        }
    }
    /*
        // Check to see if any instruction is unmarked.
        {
            BasicBlock b = cfg;

             while(b != null)
            {
                Instruction ins = b.head;

                 while(ins != null)
                {
                    if(!reachableInstructions.contains(ins))
                        throw new RuntimeException("Method to jimplify contains unreachable code!  (not handled for now)");

                     ins = ins.next;
                }

                 b = b.next;
            }
        }
        */
    // Perform the flow analysis, and build up instructionToTypeStack and instructionToLocalArray
    {
        instructionToTypeStack = new HashMap<Instruction, TypeStack>();
        instructionToPostTypeStack = new HashMap<Instruction, TypeStack>();
        Set<Instruction> visitedInstructions = new HashSet<Instruction>();
        List<Instruction> changedInstructions = new ArrayList<Instruction>();
        TypeStack initialTypeStack;
        // Build up initial type stack and initial local array (for the first instruction)
        {
            initialTypeStack = TypeStack.v();
        // the empty stack with nothing on it.
        }
        // Get the loop cranked up.
        {
            instructionToTypeStack.put(firstInstruction, initialTypeStack);
            visitedInstructions.add(firstInstruction);
            changedInstructions.add(firstInstruction);
        }
        {
            while (!changedInstructions.isEmpty()) {
                Instruction ins = changedInstructions.get(0);
                changedInstructions.remove(0);
                OutFlow ret = processFlow(ins, instructionToTypeStack.get(ins), constant_pool);
                instructionToPostTypeStack.put(ins, ret.typeStack);
                Instruction[] successors = ins.succs;
                for (Instruction s : successors) {
                    if (!visitedInstructions.contains(s)) {
                        if (handlerInstructions.contains(s)) {
                            TypeStack exceptionTypeStack = (TypeStack.v()).push(RefType.v(handlerInstructionToException.get(s).getName()));
                            instructionToTypeStack.put(s, exceptionTypeStack);
                        } else {
                            instructionToTypeStack.put(s, ret.typeStack);
                        }
                        visitedInstructions.add(s);
                        changedInstructions.add(s);
                    // logger.debug("adding successor: " + s);
                    } else {
                        // logger.debug("considering successor: " + s);
                        TypeStack newTypeStack, oldTypeStack = instructionToTypeStack.get(s);
                        if (handlerInstructions.contains(s)) {
                            // The type stack for an instruction handler should always be that of
                            // single object on the stack.
                            TypeStack exceptionTypeStack = (TypeStack.v()).push(RefType.v(handlerInstructionToException.get(s).getName()));
                            newTypeStack = exceptionTypeStack;
                        } else {
                            try {
                                newTypeStack = ret.typeStack.merge(oldTypeStack);
                            } catch (RuntimeException re) {
                                logger.debug("Considering " + s);
                                throw re;
                            }
                        }
                        if (!newTypeStack.equals(oldTypeStack)) {
                            changedInstructions.add(s);
                        // logger.debug("requires a revisit: " + s);
                        }
                        instructionToTypeStack.put(s, newTypeStack);
                    }
                }
            }
        }
    }
    // logger.debug("Producing Jimple code...");
    // Jimplify each statement
    {
        BasicBlock b = cfg;
        while (b != null) {
            Instruction ins = b.head;
            b.statements = new ArrayList<Stmt>();
            List<Stmt> blockStatements = b.statements;
            for (; ; ) {
                List<Stmt> statementsForIns = new ArrayList<Stmt>();
                if (reachableInstructions.contains(ins))
                    generateJimple(ins, instructionToTypeStack.get(ins), instructionToPostTypeStack.get(ins), constant_pool, statementsForIns, b);
                else
                    statementsForIns.add(Jimple.v().newNopStmt());
                if (!statementsForIns.isEmpty()) {
                    for (int i = 0; i < statementsForIns.size(); i++) {
                        units.add(statementsForIns.get(i));
                        blockStatements.add(statementsForIns.get(i));
                    }
                    instructionToFirstStmt.put(ins, statementsForIns.get(0));
                    instructionToLastStmt.put(ins, statementsForIns.get(statementsForIns.size() - 1));
                }
                if (ins == b.tail)
                    break;
                ins = ins.next;
            }
            b = b.next;
        }
    }
    // fix up jump targets
    jimpleTargetFixup();
    /*
        // Print out basic blocks
        {
            BasicBlock b = cfg;

            logger.debug("Basic blocks for: " + jmethod.getName());

            while(b != null)
            {
                Instruction ins = b.head;

                

                while(ins != null)
                {
                    logger.debug(""+ins.toString());
                    ins = ins.next;
                }

                b = b.next;
            }
        }
        */
    // Insert beginCatch/endCatch statements for exception handling
    {
        Map<Stmt, Stmt> targetToHandler = new HashMap<Stmt, Stmt>();
        for (int i = 0; i < codeAttribute.exception_table_length; i++) {
            Instruction startIns = codeAttribute.exception_table[i].start_inst;
            Instruction endIns = codeAttribute.exception_table[i].end_inst;
            Instruction targetIns = codeAttribute.exception_table[i].handler_inst;
            if (!instructionToFirstStmt.containsKey(startIns) || (endIns != null && (!instructionToLastStmt.containsKey(endIns)))) {
                throw new RuntimeException("Exception range does not coincide with jimple instructions");
            }
            if (!instructionToFirstStmt.containsKey(targetIns)) {
                throw new RuntimeException("Exception handler does not coincide with jimple instruction");
            }
            SootClass exception;
            // Determine exception to catch
            {
                int catchType = codeAttribute.exception_table[i].catch_type;
                if (catchType != 0) {
                    CONSTANT_Class_info classinfo = (CONSTANT_Class_info) constant_pool[catchType];
                    String name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index])).convert();
                    name = name.replace('/', '.');
                    exception = cm.getSootClass(name);
                } else
                    exception = cm.getSootClass("java.lang.Throwable");
            }
            Stmt newTarget;
            // Insert assignment of exception
            {
                Stmt firstTargetStmt = instructionToFirstStmt.get(targetIns);
                if (targetToHandler.containsKey(firstTargetStmt))
                    newTarget = targetToHandler.get(firstTargetStmt);
                else {
                    Local local = Util.v().getLocalCreatingIfNecessary(listBody, "$stack0", UnknownType.v());
                    newTarget = Jimple.v().newIdentityStmt(local, Jimple.v().newCaughtExceptionRef());
                    // changed to account for catch blocks which are also part of normal control flow
                    // units.insertBefore(newTarget, firstTargetStmt);
                    ((PatchingChain<Unit>) units).insertBeforeNoRedirect(newTarget, firstTargetStmt);
                    targetToHandler.put(firstTargetStmt, newTarget);
                    if (units.getFirst() != newTarget) {
                        Unit prev = (Unit) units.getPredOf(newTarget);
                        if (prev != null && prev.fallsThrough())
                            units.insertAfter(Jimple.v().newGotoStmt(firstTargetStmt), prev);
                    }
                }
            }
            // Insert trap
            {
                Stmt firstStmt = instructionToFirstStmt.get(startIns);
                Stmt afterEndStmt;
                if (endIns == null) {
                    // A kludge which isn't really correct, but
                    // gets us closer to correctness (until we
                    // clean up the rest of Soot to properly
                    // represent Traps which extend to the end
                    // of a method): if the protected code extends
                    // to the end of the method, use the last Stmt
                    // as the endUnit of the Trap, even though
                    // that will leave the last unit outside
                    // the protected area.
                    afterEndStmt = (Stmt) units.getLast();
                } else {
                    afterEndStmt = instructionToLastStmt.get(endIns);
                    IdentityStmt catchStart = (IdentityStmt) targetToHandler.get(afterEndStmt);
                    // (Cast to IdentityStmt as an assertion check.)
                    if (catchStart != null) {
                        // before the old afterEndStmt.
                        if (catchStart != units.getPredOf(afterEndStmt)) {
                            throw new IllegalStateException("Assertion failure: catchStart != pred of afterEndStmt");
                        }
                        afterEndStmt = catchStart;
                    }
                }
                Trap trap = Jimple.v().newTrap(exception, firstStmt, afterEndStmt, newTarget);
                listBody.getTraps().add(trap);
            }
        }
    }
    /* convert line number table to tags attached to statements */
    if (Options.v().keep_line_number()) {
        HashMap<Stmt, Tag> stmtstags = new HashMap<Stmt, Tag>();
        LinkedList<Stmt> startstmts = new LinkedList<Stmt>();
        attribute_info[] attrs = codeAttribute.attributes;
        for (attribute_info element : attrs) {
            if (element instanceof LineNumberTable_attribute) {
                LineNumberTable_attribute lntattr = (LineNumberTable_attribute) element;
                for (line_number_table_entry element0 : lntattr.line_number_table) {
                    Stmt start_stmt = instructionToFirstStmt.get(element0.start_inst);
                    if (start_stmt != null) {
                        LineNumberTag lntag = new LineNumberTag(element0.line_number);
                        stmtstags.put(start_stmt, lntag);
                        startstmts.add(start_stmt);
                    }
                }
            }
        }
        /* if the predecessor of a statement is a caughtexcetionref,
             * give it the tag of its successor */
        for (Iterator<Stmt> stmtIt = new ArrayList<Stmt>(stmtstags.keySet()).iterator(); stmtIt.hasNext(); ) {
            final Stmt stmt = stmtIt.next();
            Stmt pred = stmt;
            Tag tag = stmtstags.get(stmt);
            while (true) {
                pred = (Stmt) units.getPredOf(pred);
                if (pred == null)
                    break;
                if (!(pred instanceof IdentityStmt))
                    break;
                stmtstags.put(pred, tag);
                pred.addTag(tag);
            }
        }
        /* attach line number tag to each statement. */
        for (int i = 0; i < startstmts.size(); i++) {
            Stmt stmt = startstmts.get(i);
            Tag tag = stmtstags.get(stmt);
            stmt.addTag(tag);
            stmt = (Stmt) units.getSuccOf(stmt);
            while (stmt != null && !stmtstags.containsKey(stmt)) {
                stmt.addTag(tag);
                stmt = (Stmt) units.getSuccOf(stmt);
            }
        }
    }
}
Also used : ArraySet(soot.util.ArraySet) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Unit(soot.Unit) GotoStmt(soot.jimple.GotoStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) TableSwitchStmt(soot.jimple.TableSwitchStmt) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) Stmt(soot.jimple.Stmt) LineNumberTag(soot.tagkit.LineNumberTag) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) IdentityStmt(soot.jimple.IdentityStmt) HashSet(java.util.HashSet) ArraySet(soot.util.ArraySet) PatchingChain(soot.PatchingChain) Local(soot.Local) Trap(soot.Trap) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) Tag(soot.tagkit.Tag) LineNumberTag(soot.tagkit.LineNumberTag) BytecodeOffsetTag(soot.tagkit.BytecodeOffsetTag) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

IdentityStmt (soot.jimple.IdentityStmt)25 Unit (soot.Unit)20 Local (soot.Local)14 Value (soot.Value)14 AssignStmt (soot.jimple.AssignStmt)13 InvokeExpr (soot.jimple.InvokeExpr)11 Type (soot.Type)10 ParameterRef (soot.jimple.ParameterRef)10 ReturnStmt (soot.jimple.ReturnStmt)10 IfStmt (soot.jimple.IfStmt)9 Stmt (soot.jimple.Stmt)9 ArrayList (java.util.ArrayList)8 InvokeStmt (soot.jimple.InvokeStmt)8 HashSet (java.util.HashSet)7 ArrayType (soot.ArrayType)7 RefType (soot.RefType)7 ArrayRef (soot.jimple.ArrayRef)7 CastExpr (soot.jimple.CastExpr)7 DefinitionStmt (soot.jimple.DefinitionStmt)7 NewArrayExpr (soot.jimple.NewArrayExpr)7