Search in sources :

Example 1 with NumericConstant

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

the class ConstantFieldValueFinder method valuesForPrimTypeFields.

/*
	 * This method gives values to all the fields in all the classes if they can be determined statically
	 * We only care about fields which have primitive types
	 */
private void valuesForPrimTypeFields() {
    // go through all the classes
    Iterator classIt = appClasses.iterator();
    while (classIt.hasNext()) {
        SootClass s = (SootClass) classIt.next();
        debug("\nvaluesforPrimTypeFields", "Processing class " + s.getName());
        String declaringClass = s.getName();
        Iterator fieldIt = s.getFields().iterator();
        while (fieldIt.hasNext()) {
            SootField f = (SootField) fieldIt.next();
            String fieldName = f.getName();
            Type fieldType = f.getType();
            if (!(fieldType instanceof PrimType))
                continue;
            String combined = declaringClass + combiner + fieldName;
            classNameFieldNameToSootFieldMapping.put(combined, f);
            Object value = null;
            // check for constant value tags
            if (fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")) {
                double val = ((DoubleConstantValueTag) f.getTag("DoubleConstantValueTag")).getDoubleValue();
                value = new Double(val);
            } else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")) {
                float val = ((FloatConstantValueTag) f.getTag("FloatConstantValueTag")).getFloatValue();
                value = new Float(val);
            } else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")) {
                long val = ((LongConstantValueTag) f.getTag("LongConstantValueTag")).getLongValue();
                value = new Long(val);
            } else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")) {
                int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
                value = new Integer(val);
            } else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")) {
                int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
                if (val == 0)
                    value = new Boolean(false);
                else
                    value = new Boolean(true);
            } else if ((fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) && f.hasTag("IntegerConstantValueTag")) {
                int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
                value = new Integer(val);
            }
            // if there was a constant value tag we have its value now
            if (value != null) {
                debug("TAGGED value found for field: " + combined);
                primTypeFieldValueToUse.put(combined, value);
                // continue with next field
                continue;
            }
            // see if the field was never assigned in which case it gets default values
            Object temp = fieldToValues.get(combined);
            if (temp == null) {
                if (fieldType instanceof DoubleType)
                    value = new Double(0);
                else if (fieldType instanceof FloatType)
                    value = new Float(0);
                else if (fieldType instanceof LongType)
                    value = new Long(0);
                else if (fieldType instanceof BooleanType)
                    value = new Boolean(false);
                else if ((fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) || fieldType instanceof CharType) {
                    value = new Integer(0);
                } else
                    throw new DecompilationException("Unknown primitive type...please report to developer");
                primTypeFieldValueToUse.put(combined, value);
                debug("DEFAULT value for field: " + combined);
                // continue with next field
                continue;
            }
            // havent got a tag with value and havent use default since SOME method did define the field atleast once
            // there was some value assigned!!!!!!!!!
            debug("CHECKING USER ASSIGNED VALUES FOR: " + combined);
            ArrayList values = (ArrayList) temp;
            // check if they are all constants and that too the same constant
            Iterator it = values.iterator();
            NumericConstant tempConstant = null;
            while (it.hasNext()) {
                Value val = (Value) it.next();
                if (!(val instanceof NumericConstant)) {
                    tempConstant = null;
                    debug("Not numeric constant hence giving up");
                    break;
                }
                if (tempConstant == null) {
                    tempConstant = (NumericConstant) val;
                } else {
                    // check that this value is the same as previous
                    if (!tempConstant.equals(val)) {
                        tempConstant = null;
                        break;
                    }
                }
            }
            if (tempConstant == null) {
                // continue with next field cant do anything about this one
                continue;
            }
            if (tempConstant instanceof LongConstant) {
                Long tempVal = new Long(((LongConstant) tempConstant).value);
                if (tempVal.compareTo(new Long(0)) == 0)
                    primTypeFieldValueToUse.put(combined, tempVal);
                else
                    debug("Not assigning the agreed value since that is not the default value for " + combined);
            } else if (tempConstant instanceof DoubleConstant) {
                Double tempVal = new Double(((DoubleConstant) tempConstant).value);
                if (tempVal.compareTo(new Double(0)) == 0)
                    primTypeFieldValueToUse.put(combined, tempVal);
                else
                    debug("Not assigning the agreed value since that is not the default value for " + combined);
            } else if (tempConstant instanceof FloatConstant) {
                Float tempVal = new Float(((FloatConstant) tempConstant).value);
                if (tempVal.compareTo(new Float(0)) == 0)
                    primTypeFieldValueToUse.put(combined, tempVal);
                else
                    debug("Not assigning the agreed value since that is not the default value for " + combined);
            } else if (tempConstant instanceof IntConstant) {
                Integer tempVal = new Integer(((IntConstant) tempConstant).value);
                if (tempVal.compareTo(new Integer(0)) == 0) {
                    SootField tempField = classNameFieldNameToSootFieldMapping.get(combined);
                    if (tempField.getType() instanceof BooleanType) {
                        primTypeFieldValueToUse.put(combined, new Boolean(false));
                    // System.out.println("puttingvalue false for"+combined);
                    } else {
                        primTypeFieldValueToUse.put(combined, tempVal);
                    // System.out.println("puttingvalue 0 for"+combined);
                    }
                } else
                    debug("Not assigning the agreed value since that is not the default value for " + combined);
            } else {
                throw new DecompilationException("Un handled Numberic Constant....report to programmer");
            }
        }
    // all fields of the class
    }
// all classes
}
Also used : DoubleConstant(soot.jimple.DoubleConstant) LongType(soot.LongType) FloatConstant(soot.jimple.FloatConstant) ArrayList(java.util.ArrayList) DecompilationException(soot.dava.DecompilationException) ByteType(soot.ByteType) FloatType(soot.FloatType) IntType(soot.IntType) Iterator(java.util.Iterator) PrimType(soot.PrimType) LongConstantValueTag(soot.tagkit.LongConstantValueTag) IntConstant(soot.jimple.IntConstant) LongConstant(soot.jimple.LongConstant) ShortType(soot.ShortType) BooleanType(soot.BooleanType) IntegerConstantValueTag(soot.tagkit.IntegerConstantValueTag) DoubleConstantValueTag(soot.tagkit.DoubleConstantValueTag) SootClass(soot.SootClass) DoubleType(soot.DoubleType) FloatType(soot.FloatType) IntType(soot.IntType) ShortType(soot.ShortType) CharType(soot.CharType) LongType(soot.LongType) BooleanType(soot.BooleanType) ByteType(soot.ByteType) Type(soot.Type) PrimType(soot.PrimType) DoubleType(soot.DoubleType) NumericConstant(soot.jimple.NumericConstant) Value(soot.Value) SootField(soot.SootField) CharType(soot.CharType)

Example 2 with NumericConstant

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

the class SimplifyExpressions method outExprOrRefValueBox.

/*	public void inASTBinaryCondition(ASTBinaryCondition cond){
		ConditionExpr condExpr = cond.getConditionExpr();
		
		ValueBox op1Box = condExpr.getOp1Box();
	
		ValueBox op2Box = condExpr.getOp2Box();
	}
	*/
public void outExprOrRefValueBox(ValueBox vb) {
    // System.out.println("here"+vb);
    Value v = vb.getValue();
    if (!(v instanceof BinopExpr)) {
        return;
    }
    BinopExpr binop = (BinopExpr) v;
    if (DEBUG)
        System.out.println("calling getResult");
    NumericConstant constant = getResult(binop);
    if (constant == null)
        return;
    if (DEBUG)
        System.out.println("Changin" + vb + " to...." + constant);
    vb.setValue(constant);
}
Also used : NumericConstant(soot.jimple.NumericConstant) Value(soot.Value) BinopExpr(soot.jimple.BinopExpr)

Example 3 with NumericConstant

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

the class SimplifyExpressions method getResult.

public NumericConstant getResult(BinopExpr binop) {
    if (DEBUG)
        System.out.println("Binop expr" + binop);
    Value leftOp = binop.getOp1();
    Value rightOp = binop.getOp2();
    int op = 0;
    if (binop instanceof AddExpr) {
        op = 1;
    } else if (binop instanceof SubExpr || binop instanceof DCmpExpr || binop instanceof DCmpgExpr || binop instanceof DCmplExpr) {
        op = 2;
    } else if (binop instanceof MulExpr) {
        op = 3;
    }
    if (op == 0) {
        if (DEBUG) {
            System.out.println("not add sub or mult");
            System.out.println(binop.getClass().getName());
        }
        return null;
    }
    NumericConstant constant = null;
    if (leftOp instanceof LongConstant && rightOp instanceof LongConstant) {
        if (DEBUG)
            System.out.println("long constants!!");
        if (op == 1)
            constant = ((LongConstant) leftOp).add((LongConstant) rightOp);
        else if (op == 2)
            constant = ((LongConstant) leftOp).subtract((LongConstant) rightOp);
        else if (op == 3)
            constant = ((LongConstant) leftOp).multiply((LongConstant) rightOp);
    } else if (leftOp instanceof DoubleConstant && rightOp instanceof DoubleConstant) {
        if (DEBUG)
            System.out.println("double constants!!");
        if (op == 1)
            constant = ((DoubleConstant) leftOp).add((DoubleConstant) rightOp);
        else if (op == 2)
            constant = ((DoubleConstant) leftOp).subtract((DoubleConstant) rightOp);
        else if (op == 3)
            constant = ((DoubleConstant) leftOp).multiply((DoubleConstant) rightOp);
    } else if (leftOp instanceof FloatConstant && rightOp instanceof FloatConstant) {
        if (DEBUG)
            System.out.println("Float constants!!");
        if (op == 1)
            constant = ((FloatConstant) leftOp).add((FloatConstant) rightOp);
        else if (op == 2)
            constant = ((FloatConstant) leftOp).subtract((FloatConstant) rightOp);
        else if (op == 3)
            constant = ((FloatConstant) leftOp).multiply((FloatConstant) rightOp);
    } else if (leftOp instanceof IntConstant && rightOp instanceof IntConstant) {
        if (DEBUG)
            System.out.println("Integer constants!!");
        if (op == 1)
            constant = ((IntConstant) leftOp).add((IntConstant) rightOp);
        else if (op == 2)
            constant = ((IntConstant) leftOp).subtract((IntConstant) rightOp);
        else if (op == 3)
            constant = ((IntConstant) leftOp).multiply((IntConstant) rightOp);
    }
    return constant;
}
Also used : MulExpr(soot.jimple.MulExpr) LongConstant(soot.jimple.LongConstant) DoubleConstant(soot.jimple.DoubleConstant) SubExpr(soot.jimple.SubExpr) FloatConstant(soot.jimple.FloatConstant) AddExpr(soot.jimple.AddExpr) DCmpExpr(soot.dava.internal.javaRep.DCmpExpr) DCmplExpr(soot.dava.internal.javaRep.DCmplExpr) DCmpgExpr(soot.dava.internal.javaRep.DCmpgExpr) NumericConstant(soot.jimple.NumericConstant) Value(soot.Value) IntConstant(soot.jimple.IntConstant)

Example 4 with NumericConstant

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

the class ArithmeticTransformer method internalTransform.

protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
    int weight = soot.jbco.Main.getWeight(phaseName, b.getMethod().getSignature());
    if (weight == 0) {
        return;
    }
    PatchingChain<Unit> units = b.getUnits();
    int localCount = 0;
    Chain<Local> locals = b.getLocals();
    if (output) {
        out.println("*** Performing Arithmetic Transformation on " + b.getMethod().getSignature());
    }
    Iterator<Unit> it = units.snapshotIterator();
    while (it.hasNext()) {
        Unit u = it.next();
        if (u instanceof AssignStmt) {
            AssignStmt as = (AssignStmt) u;
            Value v = as.getRightOp();
            if (v instanceof MulExpr) {
                total++;
                MulExpr me = (MulExpr) v;
                Value op1 = me.getOp1();
                Value op = null, op2 = me.getOp2();
                NumericConstant nc = null;
                if (op1 instanceof NumericConstant) {
                    nc = (NumericConstant) op1;
                    op = op2;
                } else if (op2 instanceof NumericConstant) {
                    nc = (NumericConstant) op2;
                    op = op1;
                }
                if (nc != null) {
                    if (output) {
                        out.println("Considering: " + as + "\r");
                    }
                    Type opType = op.getType();
                    int max = opType instanceof IntType ? 32 : opType instanceof LongType ? 64 : 0;
                    if (max != 0) {
                        Object[] shft_rem = checkNumericValue(nc);
                        if (shft_rem[0] != null && (Integer) shft_rem[0] < max && Rand.getInt(10) <= weight) {
                            List<Unit> unitsBuilt = new ArrayList<>();
                            int rand = Rand.getInt(16);
                            int shift = (Integer) shft_rem[0];
                            boolean neg = (Boolean) shft_rem[2];
                            if (rand % 2 == 0) {
                                shift += rand * max;
                            } else {
                                shift -= rand * max;
                            }
                            Expr e;
                            if (shft_rem[1] != null) {
                                // if there is an additive floating component
                                Local tmp2 = null, tmp1 = Jimple.v().newLocal("__tmp_shft_lcl" + localCount++, opType);
                                locals.add(tmp1);
                                // shift the integral portion
                                Unit newU = Jimple.v().newAssignStmt(tmp1, Jimple.v().newShlExpr(op, IntConstant.v(shift)));
                                unitsBuilt.add(newU);
                                units.insertBefore(newU, u);
                                // grab remainder (that not part of the 2^x)
                                double rem = (Double) shft_rem[1];
                                if (rem != 1) {
                                    if (rem == ((int) rem) && opType instanceof IntType) {
                                        nc = IntConstant.v((int) rem);
                                    } else if (rem == ((long) rem) && opType instanceof LongType) {
                                        nc = LongConstant.v((long) rem);
                                    } else {
                                        nc = DoubleConstant.v(rem);
                                    }
                                    if (nc instanceof DoubleConstant) {
                                        tmp2 = Jimple.v().newLocal("__tmp_shft_lcl" + localCount++, DoubleType.v());
                                        locals.add(tmp2);
                                        newU = Jimple.v().newAssignStmt(tmp2, Jimple.v().newCastExpr(op, DoubleType.v()));
                                        unitsBuilt.add(newU);
                                        units.insertBefore(newU, u);
                                        newU = Jimple.v().newAssignStmt(tmp2, Jimple.v().newMulExpr(tmp2, nc));
                                    } else {
                                        tmp2 = Jimple.v().newLocal("__tmp_shft_lcl" + localCount++, nc.getType());
                                        locals.add(tmp2);
                                        newU = Jimple.v().newAssignStmt(tmp2, Jimple.v().newMulExpr(op, nc));
                                    }
                                    unitsBuilt.add(newU);
                                    units.insertBefore(newU, u);
                                }
                                if (tmp2 == null) {
                                    e = Jimple.v().newAddExpr(tmp1, op);
                                } else if (tmp2.getType().getClass() != tmp1.getType().getClass()) {
                                    Local tmp3 = Jimple.v().newLocal("__tmp_shft_lcl" + localCount++, tmp2.getType());
                                    locals.add(tmp3);
                                    newU = Jimple.v().newAssignStmt(tmp3, Jimple.v().newCastExpr(tmp1, tmp2.getType()));
                                    unitsBuilt.add(newU);
                                    units.insertBefore(newU, u);
                                    e = Jimple.v().newAddExpr(tmp3, tmp2);
                                } else {
                                    e = Jimple.v().newAddExpr(tmp1, tmp2);
                                }
                            } else {
                                e = Jimple.v().newShlExpr(op, IntConstant.v(shift));
                            }
                            if (e.getType().getClass() != as.getLeftOp().getType().getClass()) {
                                Local tmp = Jimple.v().newLocal("__tmp_shft_lcl" + localCount++, e.getType());
                                locals.add(tmp);
                                Unit newU = Jimple.v().newAssignStmt(tmp, e);
                                unitsBuilt.add(newU);
                                units.insertAfter(newU, u);
                                e = Jimple.v().newCastExpr(tmp, as.getLeftOp().getType());
                            }
                            as.setRightOp(e);
                            unitsBuilt.add(as);
                            if (neg) {
                                Unit newU = Jimple.v().newAssignStmt(as.getLeftOp(), Jimple.v().newNegExpr(as.getLeftOp()));
                                unitsBuilt.add(newU);
                                units.insertAfter(newU, u);
                            }
                            mulPerformed++;
                            printOutput(unitsBuilt);
                        }
                    }
                }
            } else if (v instanceof DivExpr) {
                total++;
                DivExpr de = (DivExpr) v;
                Value op2 = de.getOp2();
                NumericConstant nc;
                if (op2 instanceof NumericConstant) {
                    nc = (NumericConstant) op2;
                    Type opType = de.getOp1().getType();
                    int max = opType instanceof IntType ? 32 : opType instanceof LongType ? 64 : 0;
                    if (max != 0) {
                        Object[] shft_rem = checkNumericValue(nc);
                        if (shft_rem[0] != null && (shft_rem[1] == null || (Double) shft_rem[1] == 0) && (Integer) shft_rem[0] < max && Rand.getInt(10) <= weight) {
                            List<Unit> unitsBuilt = new ArrayList<>();
                            int rand = Rand.getInt(16);
                            int shift = (Integer) shft_rem[0];
                            boolean neg = (Boolean) shft_rem[2];
                            if (Rand.getInt() % 2 == 0) {
                                shift += rand * max;
                            } else {
                                shift -= rand * max;
                            }
                            Expr e = Jimple.v().newShrExpr(de.getOp1(), IntConstant.v(shift));
                            if (e.getType().getClass() != as.getLeftOp().getType().getClass()) {
                                Local tmp = Jimple.v().newLocal("__tmp_shft_lcl" + localCount++, e.getType());
                                locals.add(tmp);
                                Unit newU = Jimple.v().newAssignStmt(tmp, e);
                                unitsBuilt.add(newU);
                                units.insertAfter(newU, u);
                                e = Jimple.v().newCastExpr(tmp, as.getLeftOp().getType());
                            }
                            as.setRightOp(e);
                            unitsBuilt.add(as);
                            if (neg) {
                                Unit newU = Jimple.v().newAssignStmt(as.getLeftOp(), Jimple.v().newNegExpr(as.getLeftOp()));
                                unitsBuilt.add(newU);
                                units.insertAfter(newU, u);
                            }
                            divPerformed++;
                            printOutput(unitsBuilt);
                        }
                    }
                }
            }
        }
    }
}
Also used : MulExpr(soot.jimple.MulExpr) DoubleConstant(soot.jimple.DoubleConstant) LongType(soot.LongType) AssignStmt(soot.jimple.AssignStmt) ArrayList(java.util.ArrayList) Unit(soot.Unit) IntType(soot.IntType) ArrayList(java.util.ArrayList) List(java.util.List) Local(soot.Local) DoubleType(soot.DoubleType) IntType(soot.IntType) LongType(soot.LongType) Type(soot.Type) DivExpr(soot.jimple.DivExpr) MulExpr(soot.jimple.MulExpr) Expr(soot.jimple.Expr) DivExpr(soot.jimple.DivExpr) NumericConstant(soot.jimple.NumericConstant) Value(soot.Value)

Example 5 with NumericConstant

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

the class DexBody method jimplify.

/**
 * Return the jimple equivalent of this body.
 *
 * @param m
 *            the SootMethod that contains this body
 */
public Body jimplify(Body b, SootMethod m) {
    final Jimple jimple = Jimple.v();
    final UnknownType unknownType = UnknownType.v();
    final NullConstant nullConstant = NullConstant.v();
    final Options options = Options.v();
    /*
		 * Timer t_whole_jimplification = new Timer(); Timer t_num = new
		 * Timer(); Timer t_null = new Timer();
		 * 
		 * t_whole_jimplification.start();
		 */
    jBody = (JimpleBody) b;
    deferredInstructions = new ArrayList<DeferableInstruction>();
    instructionsToRetype = new HashSet<RetypeableInstruction>();
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        DalvikTyper.v().clear();
    }
    // process method parameters and generate Jimple locals from Dalvik
    // registers
    List<Local> paramLocals = new LinkedList<Local>();
    if (!isStatic) {
        int thisRegister = numRegisters - numParameterRegisters - 1;
        // generateLocal(UnknownType.v());
        Local thisLocal = jimple.newLocal("$u" + thisRegister, unknownType);
        jBody.getLocals().add(thisLocal);
        registerLocals[thisRegister] = thisLocal;
        JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(thisLocal, jimple.newThisRef(declaringClassType));
        add(idStmt);
        paramLocals.add(thisLocal);
        if (IDalvikTyper.ENABLE_DVKTYPER) {
            DalvikTyper.v().setType(idStmt.leftBox, jBody.getMethod().getDeclaringClass().getType(), false);
        }
    }
    {
        // index of parameter type
        int i = 0;
        // index
        int parameterRegister = numRegisters - numParameterRegisters;
        // register
        for (Type t : parameterTypes) {
            // may
            Local gen = jimple.newLocal("$u" + parameterRegister, unknownType);
            // only
            // use
            // UnknownType
            // here
            // because
            // the
            // local
            // may
            // be
            // reused
            // with
            // a
            // different
            // type
            // later
            // (before
            // splitting)
            jBody.getLocals().add(gen);
            registerLocals[parameterRegister] = gen;
            JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(gen, jimple.newParameterRef(t, i++));
            add(idStmt);
            paramLocals.add(gen);
            if (IDalvikTyper.ENABLE_DVKTYPER) {
                DalvikTyper.v().setType(idStmt.leftBox, t, false);
            }
            // used later in the Dalvik bytecode
            if (t instanceof LongType || t instanceof DoubleType) {
                parameterRegister++;
                // may
                Local g = jimple.newLocal("$u" + parameterRegister, unknownType);
                // only
                // use
                // UnknownType
                // here
                // because
                // the
                // local
                // may
                // be
                // reused
                // with
                // a
                // different
                // type
                // later
                // (before
                // splitting)
                jBody.getLocals().add(g);
                registerLocals[parameterRegister] = g;
            }
            parameterRegister++;
        }
    }
    for (int i = 0; i < (numRegisters - numParameterRegisters - (isStatic ? 0 : 1)); i++) {
        registerLocals[i] = jimple.newLocal("$u" + i, unknownType);
        jBody.getLocals().add(registerLocals[i]);
    }
    // add local to store intermediate results
    storeResultLocal = jimple.newLocal("$u-1", unknownType);
    jBody.getLocals().add(storeResultLocal);
    // process bytecode instructions
    final boolean isOdex = dexFile instanceof DexBackedDexFile ? ((DexBackedDexFile) dexFile).isOdexFile() : false;
    ClassPath cp = null;
    if (isOdex) {
        String[] sootClasspath = options.soot_classpath().split(File.pathSeparator);
        List<String> classpathList = new ArrayList<String>();
        for (String str : sootClasspath) classpathList.add(str);
        try {
            ClassPathResolver resolver = new ClassPathResolver(classpathList, classpathList, classpathList, dexFile);
            cp = new ClassPath(resolver.getResolvedClassProviders().toArray(new ClassProvider[0]));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    int prevLineNumber = -1;
    for (DexlibAbstractInstruction instruction : instructions) {
        if (isOdex && instruction instanceof OdexInstruction)
            ((OdexInstruction) instruction).deOdex(dexFile, method, cp);
        if (dangling != null) {
            dangling.finalize(this, instruction);
            dangling = null;
        }
        instruction.jimplify(this);
        if (instruction.getLineNumber() > 0)
            prevLineNumber = instruction.getLineNumber();
        else {
            instruction.setLineNumber(prevLineNumber);
        }
    }
    for (DeferableInstruction instruction : deferredInstructions) {
        instruction.deferredJimplify(this);
    }
    if (tries != null)
        addTraps();
    int prevLn = -1;
    final boolean keepLineNumber = options.keep_line_number();
    for (DexlibAbstractInstruction instruction : instructions) {
        Unit unit = instruction.getUnit();
        int lineNumber = unit.getJavaSourceStartLineNumber();
        if (keepLineNumber && lineNumber < 0) {
            if (prevLn >= 0) {
                unit.addTag(new LineNumberTag(prevLn));
                unit.addTag(new SourceLineNumberTag(prevLn));
            }
        } else {
            prevLn = lineNumber;
        }
    }
    // At this point Jimple code is generated
    // Cleaning...
    instructions = null;
    // registerLocals = null;
    // storeResultLocal = null;
    instructionAtAddress.clear();
    // localGenerator = null;
    deferredInstructions = null;
    // instructionsToRetype = null;
    dangling = null;
    tries = null;
    /*
		 * We eliminate dead code. Dead code has been shown to occur under the
		 * following circumstances.
		 *
		 * 0006ec: 0d00 |00a2: move-exception v0 ... 0006f2: 0d00 |00a5:
		 * move-exception v0 ... 0x0041 - 0x008a Ljava/lang/Throwable; -> 0x00a5
		 * <any> -> 0x00a2
		 * 
		 * Here there are two traps both over the same region. But the same
		 * always fires, hence rendering the code at a2 unreachable. Dead code
		 * yields problems during local splitting because locals within dead
		 * code will not be split. Hence we remove all dead code here.
		 */
    // Fix traps that do not catch exceptions
    DexTrapStackFixer.v().transform(jBody);
    // Sort out jump chains
    DexJumpChainShortener.v().transform(jBody);
    // Make sure that we don't have any overlapping uses due to returns
    DexReturnInliner.v().transform(jBody);
    // Shortcut: Reduce array initializations
    DexArrayInitReducer.v().transform(jBody);
    // split first to find undefined uses
    getLocalSplitter().transform(jBody);
    // Remove dead code and the corresponding locals before assigning types
    getUnreachableCodeEliminator().transform(jBody);
    DeadAssignmentEliminator.v().transform(jBody);
    UnusedLocalEliminator.v().transform(jBody);
    for (RetypeableInstruction i : instructionsToRetype) i.retype(jBody);
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        DexReturnValuePropagator.v().transform(jBody);
        getCopyPopagator().transform(jBody);
        DexNullThrowTransformer.v().transform(jBody);
        DalvikTyper.v().typeUntypedConstrantInDiv(jBody);
        DeadAssignmentEliminator.v().transform(jBody);
        UnusedLocalEliminator.v().transform(jBody);
        DalvikTyper.v().assignType(jBody);
        // jBody.validate();
        jBody.validateUses();
        jBody.validateValueBoxes();
    // jBody.checkInit();
    // Validate.validateArrays(jBody);
    // jBody.checkTypes();
    // jBody.checkLocals();
    } else {
        // t_num.start();
        DexNumTransformer.v().transform(jBody);
        // t_num.end();
        DexReturnValuePropagator.v().transform(jBody);
        getCopyPopagator().transform(jBody);
        DexNullThrowTransformer.v().transform(jBody);
        // t_null.start();
        DexNullTransformer.v().transform(jBody);
        // t_null.end();
        DexIfTransformer.v().transform(jBody);
        DeadAssignmentEliminator.v().transform(jBody);
        UnusedLocalEliminator.v().transform(jBody);
        // DexRefsChecker.v().transform(jBody);
        DexNullArrayRefTransformer.v().transform(jBody);
    }
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        for (Local l : jBody.getLocals()) {
            l.setType(unknownType);
        }
    }
    // Remove "instanceof" checks on the null constant
    DexNullInstanceofTransformer.v().transform(jBody);
    TypeAssigner.v().transform(jBody);
    final RefType objectType = RefType.v("java.lang.Object");
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        for (Unit u : jBody.getUnits()) {
            if (u instanceof IfStmt) {
                ConditionExpr expr = (ConditionExpr) ((IfStmt) u).getCondition();
                if (((expr instanceof EqExpr) || (expr instanceof NeExpr))) {
                    Value op1 = expr.getOp1();
                    Value op2 = expr.getOp2();
                    if (op1 instanceof Constant && op2 instanceof Local) {
                        Local l = (Local) op2;
                        Type ltype = l.getType();
                        if (ltype instanceof PrimType)
                            continue;
                        if (// by default
                        !(op1 instanceof IntConstant))
                            // in Dalvik
                            continue;
                        IntConstant icst = (IntConstant) op1;
                        int val = icst.value;
                        if (val != 0)
                            continue;
                        expr.setOp1(nullConstant);
                    } else if (op1 instanceof Local && op2 instanceof Constant) {
                        Local l = (Local) op1;
                        Type ltype = l.getType();
                        if (ltype instanceof PrimType)
                            continue;
                        if (// by default
                        !(op2 instanceof IntConstant))
                            // in Dalvik
                            continue;
                        IntConstant icst = (IntConstant) op2;
                        int val = icst.value;
                        if (val != 0)
                            continue;
                        expr.setOp2(nullConstant);
                    } else if (op1 instanceof Local && op2 instanceof Local) {
                    // nothing to do
                    } else if (op1 instanceof Constant && op2 instanceof Constant) {
                        if (op1 instanceof NullConstant && op2 instanceof NumericConstant) {
                            IntConstant nc = (IntConstant) op2;
                            if (nc.value != 0)
                                throw new RuntimeException("expected value 0 for int constant. Got " + expr);
                            expr.setOp2(NullConstant.v());
                        } else if (op2 instanceof NullConstant && op1 instanceof NumericConstant) {
                            IntConstant nc = (IntConstant) op1;
                            if (nc.value != 0)
                                throw new RuntimeException("expected value 0 for int constant. Got " + expr);
                            expr.setOp1(nullConstant);
                        }
                    } else {
                        throw new RuntimeException("error: do not handle if: " + u);
                    }
                }
            }
        }
        // For null_type locals: replace their use by NullConstant()
        List<ValueBox> uses = jBody.getUseBoxes();
        // List<ValueBox> defs = jBody.getDefBoxes();
        List<ValueBox> toNullConstantify = new ArrayList<ValueBox>();
        List<Local> toRemove = new ArrayList<Local>();
        for (Local l : jBody.getLocals()) {
            if (l.getType() instanceof NullType) {
                toRemove.add(l);
                for (ValueBox vb : uses) {
                    Value v = vb.getValue();
                    if (v == l)
                        toNullConstantify.add(vb);
                }
            }
        }
        for (ValueBox vb : toNullConstantify) {
            System.out.println("replace valuebox '" + vb + " with null constant");
            vb.setValue(nullConstant);
        }
        for (Local l : toRemove) {
            System.out.println("removing null_type local " + l);
            l.setType(objectType);
        }
    }
    // We pack locals that are not used in overlapping regions. This may
    // again lead to unused locals which we have to remove.
    LocalPacker.v().transform(jBody);
    UnusedLocalEliminator.v().transform(jBody);
    LocalNameStandardizer.v().transform(jBody);
    // on the fly.
    if (options.wrong_staticness() == Options.wrong_staticness_fix) {
        FieldStaticnessCorrector.v().transform(jBody);
        MethodStaticnessCorrector.v().transform(jBody);
    }
    // Inline PackManager.v().getPack("jb").apply(jBody);
    // Keep only transformations that have not been done
    // at this point.
    TrapTightener.v().transform(jBody);
    TrapMinimizer.v().transform(jBody);
    // LocalSplitter.v().transform(jBody);
    Aggregator.v().transform(jBody);
    // UnusedLocalEliminator.v().transform(jBody);
    // TypeAssigner.v().transform(jBody);
    // LocalPacker.v().transform(jBody);
    // LocalNameStandardizer.v().transform(jBody);
    // Remove if (null == null) goto x else <madness>. We can only do this
    // after we have run the constant propagation as we might not be able
    // to statically decide the conditions earlier.
    ConditionalBranchFolder.v().transform(jBody);
    // Remove unnecessary typecasts
    ConstantCastEliminator.v().transform(jBody);
    IdentityCastEliminator.v().transform(jBody);
    // Remove unnecessary logic operations
    IdentityOperationEliminator.v().transform(jBody);
    // We need to run this transformer since the conditional branch folder
    // might have rendered some code unreachable (well, it was unreachable
    // before as well, but we didn't know).
    UnreachableCodeEliminator.v().transform(jBody);
    // Not sure whether we need this even though we do it earlier on as
    // the earlier pass does not have type information
    // CopyPropagator.v().transform(jBody);
    // we might have gotten new dead assignments and unused locals through
    // copy propagation and unreachable code elimination, so we have to do
    // this again
    DeadAssignmentEliminator.v().transform(jBody);
    UnusedLocalEliminator.v().transform(jBody);
    NopEliminator.v().transform(jBody);
    // Remove unnecessary chains of return statements
    DexReturnPacker.v().transform(jBody);
    for (Unit u : jBody.getUnits()) {
        if (u instanceof AssignStmt) {
            AssignStmt ass = (AssignStmt) u;
            if (ass.getRightOp() instanceof CastExpr) {
                CastExpr c = (CastExpr) ass.getRightOp();
                if (c.getType() instanceof NullType) {
                    ass.setRightOp(nullConstant);
                }
            }
        }
        if (u instanceof DefinitionStmt) {
            DefinitionStmt def = (DefinitionStmt) u;
            // we must manually fix the hierarchy
            if (def.getLeftOp() instanceof Local && def.getRightOp() instanceof CaughtExceptionRef) {
                Type t = def.getLeftOp().getType();
                if (t instanceof RefType) {
                    RefType rt = (RefType) t;
                    if (rt.getSootClass().isPhantom() && !rt.getSootClass().hasSuperclass() && !rt.getSootClass().getName().equals("java.lang.Throwable"))
                        rt.getSootClass().setSuperclass(Scene.v().getSootClass("java.lang.Throwable"));
                }
            }
        }
    }
    // 
    for (Local l : jBody.getLocals()) {
        Type t = l.getType();
        if (t instanceof NullType) {
            l.setType(objectType);
        }
    }
    return jBody;
}
Also used : Options(soot.options.Options) ClassPath(org.jf.dexlib2.analysis.ClassPath) LongType(soot.LongType) CaughtExceptionRef(soot.jimple.CaughtExceptionRef) NullConstant(soot.jimple.NullConstant) Constant(soot.jimple.Constant) IntConstant(soot.jimple.IntConstant) NumericConstant(soot.jimple.NumericConstant) AssignStmt(soot.jimple.AssignStmt) ArrayList(java.util.ArrayList) Unit(soot.Unit) RetypeableInstruction(soot.dexpler.instructions.RetypeableInstruction) RefType(soot.RefType) LineNumberTag(soot.tagkit.LineNumberTag) SourceLineNumberTag(soot.tagkit.SourceLineNumberTag) CastExpr(soot.jimple.CastExpr) PrimType(soot.PrimType) IntConstant(soot.jimple.IntConstant) DeferableInstruction(soot.dexpler.instructions.DeferableInstruction) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) ClassPathResolver(org.jf.dexlib2.analysis.ClassPathResolver) DexlibAbstractInstruction(soot.dexpler.instructions.DexlibAbstractInstruction) NeExpr(soot.jimple.NeExpr) JIdentityStmt(soot.jimple.internal.JIdentityStmt) NullConstant(soot.jimple.NullConstant) Local(soot.Local) IOException(java.io.IOException) LinkedList(java.util.LinkedList) UnknownType(soot.UnknownType) RefType(soot.RefType) Type(soot.Type) UnknownType(soot.UnknownType) DoubleType(soot.DoubleType) LongType(soot.LongType) NullType(soot.NullType) PrimType(soot.PrimType) IfStmt(soot.jimple.IfStmt) OdexInstruction(soot.dexpler.instructions.OdexInstruction) DoubleType(soot.DoubleType) EqExpr(soot.jimple.EqExpr) NumericConstant(soot.jimple.NumericConstant) ValueBox(soot.ValueBox) ConditionExpr(soot.jimple.ConditionExpr) Value(soot.Value) SourceLineNumberTag(soot.tagkit.SourceLineNumberTag) Jimple(soot.jimple.Jimple) NullType(soot.NullType) DefinitionStmt(soot.jimple.DefinitionStmt)

Aggregations

NumericConstant (soot.jimple.NumericConstant)7 Value (soot.Value)5 DoubleType (soot.DoubleType)4 LongType (soot.LongType)4 Type (soot.Type)4 IntConstant (soot.jimple.IntConstant)4 ArrayList (java.util.ArrayList)3 IntType (soot.IntType)3 Local (soot.Local)3 AssignStmt (soot.jimple.AssignStmt)3 DoubleConstant (soot.jimple.DoubleConstant)3 BooleanType (soot.BooleanType)2 ByteType (soot.ByteType)2 CharType (soot.CharType)2 FloatType (soot.FloatType)2 PrimType (soot.PrimType)2 ShortType (soot.ShortType)2 Unit (soot.Unit)2 FloatConstant (soot.jimple.FloatConstant)2 LongConstant (soot.jimple.LongConstant)2