Search in sources :

Example 11 with AssignStmt

use of soot.jimple.AssignStmt 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 12 with AssignStmt

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

the class DexNumTransformer method replaceWithFloatingPoint.

/**
 * Replace 0 with null in the given unit.
 *
 * @param u
 *            the unit where 0 will be replaced with null.
 */
private void replaceWithFloatingPoint(Unit u) {
    if (u instanceof AssignStmt) {
        AssignStmt s = (AssignStmt) u;
        Value v = s.getRightOp();
        if ((v instanceof IntConstant)) {
            int vVal = ((IntConstant) v).value;
            s.setRightOp(FloatConstant.v(Float.intBitsToFloat(vVal)));
        } else if (v instanceof LongConstant) {
            long vVal = ((LongConstant) v).value;
            s.setRightOp(DoubleConstant.v(Double.longBitsToDouble(vVal)));
        }
    }
}
Also used : LongConstant(soot.jimple.LongConstant) AssignStmt(soot.jimple.AssignStmt) Value(soot.Value) IntConstant(soot.jimple.IntConstant)

Example 13 with AssignStmt

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

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

the class DexTransformer method collectDefinitionsWithAliases.

/**
 * Collect definitions of l in body including the definitions of aliases of
 * l.
 *
 * In this context an alias is a local that propagates its value to l.
 *
 * @param l
 *            the local whose definitions are to collect
 * @param localDefs
 *            the LocalDefs object
 * @param body
 *            the body that contains the local
 */
protected List<Unit> collectDefinitionsWithAliases(Local l, LocalDefs localDefs, LocalUses localUses, Body body) {
    Set<Local> seenLocals = new HashSet<Local>();
    List<Local> newLocals = new ArrayList<Local>();
    List<Unit> defs = new ArrayList<Unit>();
    newLocals.add(l);
    seenLocals.add(l);
    while (!newLocals.isEmpty()) {
        Local local = newLocals.remove(0);
        for (Unit u : collectDefinitions(local, localDefs)) {
            if (u instanceof AssignStmt) {
                Value r = ((AssignStmt) u).getRightOp();
                if (r instanceof Local && seenLocals.add((Local) r))
                    newLocals.add((Local) r);
            }
            defs.add(u);
            // 
            List<UnitValueBoxPair> usesOf = localUses.getUsesOf(u);
            for (UnitValueBoxPair pair : usesOf) {
                Unit unit = pair.getUnit();
                if (unit instanceof AssignStmt) {
                    AssignStmt assignStmt = ((AssignStmt) unit);
                    Value right = assignStmt.getRightOp();
                    Value left = assignStmt.getLeftOp();
                    if (right == local && left instanceof Local && seenLocals.add((Local) left))
                        newLocals.add((Local) left);
                }
            }
        // 
        }
    }
    return defs;
}
Also used : AssignStmt(soot.jimple.AssignStmt) ArrayList(java.util.ArrayList) Value(soot.Value) Local(soot.Local) UnitValueBoxPair(soot.toolkits.scalar.UnitValueBoxPair) Unit(soot.Unit) HashSet(java.util.HashSet)

Example 15 with AssignStmt

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

the class AputInstruction method jimplify.

@Override
public void jimplify(DexBody body) {
    if (!(instruction instanceof Instruction23x))
        throw new IllegalArgumentException("Expected Instruction23x but got: " + instruction.getClass());
    Instruction23x aPutInstr = (Instruction23x) instruction;
    int source = aPutInstr.getRegisterA();
    Local arrayBase = body.getRegisterLocal(aPutInstr.getRegisterB());
    Local index = body.getRegisterLocal(aPutInstr.getRegisterC());
    ArrayRef arrayRef = Jimple.v().newArrayRef(arrayBase, index);
    Local sourceValue = body.getRegisterLocal(source);
    AssignStmt assign = getAssignStmt(body, sourceValue, arrayRef);
    if (aPutInstr.getOpcode() == Opcode.APUT_OBJECT)
        assign.addTag(new ObjectOpTag());
    setUnit(assign);
    addTags(assign);
    body.add(assign);
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        DalvikTyper.v().addConstraint(assign.getLeftOpBox(), assign.getRightOpBox());
        DalvikTyper.v().setType(arrayRef.getIndexBox(), IntType.v(), true);
    }
}
Also used : ArrayRef(soot.jimple.ArrayRef) AssignStmt(soot.jimple.AssignStmt) Local(soot.Local) Instruction23x(org.jf.dexlib2.iface.instruction.formats.Instruction23x) ObjectOpTag(soot.dexpler.tags.ObjectOpTag)

Aggregations

AssignStmt (soot.jimple.AssignStmt)83 Local (soot.Local)50 Value (soot.Value)44 Unit (soot.Unit)40 Type (soot.Type)28 Stmt (soot.jimple.Stmt)24 InvokeExpr (soot.jimple.InvokeExpr)20 RefType (soot.RefType)19 ArrayRef (soot.jimple.ArrayRef)19 ArrayType (soot.ArrayType)17 CastExpr (soot.jimple.CastExpr)17 InvokeStmt (soot.jimple.InvokeStmt)17 ArrayList (java.util.ArrayList)15 IdentityStmt (soot.jimple.IdentityStmt)15 DefinitionStmt (soot.jimple.DefinitionStmt)13 FieldRef (soot.jimple.FieldRef)13 InstanceFieldRef (soot.jimple.InstanceFieldRef)13 IntConstant (soot.jimple.IntConstant)13 ReturnStmt (soot.jimple.ReturnStmt)13 HashSet (java.util.HashSet)12