Search in sources :

Example 26 with PrimType

use of soot.PrimType in project soot by Sable.

the class TypeNode method array.

public TypeNode array() {
    if (array != null) {
        return array;
    }
    if (type instanceof ArrayType) {
        ArrayType atype = (ArrayType) type;
        array = hierarchy.typeNode(ArrayType.v(atype.baseType, atype.numDimensions + 1));
        return array;
    }
    if (type instanceof PrimType || type instanceof RefType) {
        array = hierarchy.typeNode(ArrayType.v(type, 1));
        return array;
    }
    throw new InternalTypingException();
}
Also used : ArrayType(soot.ArrayType) RefType(soot.RefType) PrimType(soot.PrimType)

Example 27 with PrimType

use of soot.PrimType in project soot by Sable.

the class UseChecker method caseAssignStmt.

public void caseAssignStmt(AssignStmt stmt) {
    Value lhs = stmt.getLeftOp();
    Value rhs = stmt.getRightOp();
    Type tlhs = null;
    if (lhs instanceof Local)
        tlhs = this.tg.get((Local) lhs);
    else if (lhs instanceof ArrayRef) {
        ArrayRef aref = (ArrayRef) lhs;
        Local base = (Local) aref.getBase();
        // Try to force Type integrity. The left side must agree on the
        // element type of the right side array reference.
        ArrayType at = null;
        Type tgType = this.tg.get(base);
        if (tgType instanceof ArrayType)
            at = (ArrayType) tgType;
        else {
            // is java.lang.Object
            if (tgType == Scene.v().getObjectType() && rhs instanceof Local) {
                Type rhsType = this.tg.get((Local) rhs);
                if (rhsType instanceof PrimType) {
                    if (defs == null) {
                        defs = LocalDefs.Factory.newLocalDefs(jb);
                        uses = LocalUses.Factory.newLocalUses(jb, defs);
                    }
                    // Check the original type of the array from the alloc site
                    for (Unit defU : defs.getDefsOfAt(base, stmt)) {
                        if (defU instanceof AssignStmt) {
                            AssignStmt defUas = (AssignStmt) defU;
                            if (defUas.getRightOp() instanceof NewArrayExpr) {
                                at = (ArrayType) defUas.getRightOp().getType();
                                break;
                            }
                        }
                    }
                }
            }
            if (at == null)
                at = tgType.makeArrayType();
        }
        tlhs = ((ArrayType) at).getElementType();
        this.handleArrayRef(aref, stmt);
        aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
        stmt.setLeftOp(this.uv.visit(lhs, tlhs, stmt));
    } else if (lhs instanceof FieldRef) {
        tlhs = ((FieldRef) lhs).getFieldRef().type();
        if (lhs instanceof InstanceFieldRef)
            this.handleInstanceFieldRef((InstanceFieldRef) lhs, stmt);
    }
    // They may have been changed above
    lhs = stmt.getLeftOp();
    rhs = stmt.getRightOp();
    if (rhs instanceof Local)
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    else if (rhs instanceof ArrayRef) {
        ArrayRef aref = (ArrayRef) rhs;
        Local base = (Local) aref.getBase();
        // try to force Type integrity
        ArrayType at = null;
        Type et = null;
        if (this.tg.get(base) instanceof ArrayType)
            at = (ArrayType) this.tg.get(base);
        else {
            Type bt = this.tg.get(base);
            // For some fixed type T, we assume that we can fix the array to T[].
            if (bt instanceof RefType || bt instanceof NullType) {
                RefType rt = bt instanceof NullType ? null : (RefType) bt;
                if (rt == null || rt.getSootClass().getName().equals("java.lang.Object") || rt.getSootClass().getName().equals("java.io.Serializable") || rt.getSootClass().getName().equals("java.lang.Cloneable")) {
                    if (defs == null) {
                        defs = LocalDefs.Factory.newLocalDefs(jb);
                        uses = LocalUses.Factory.newLocalUses(jb, defs);
                    }
                    outer: for (UnitValueBoxPair usePair : uses.getUsesOf(stmt)) {
                        Stmt useStmt = (Stmt) usePair.getUnit();
                        // from the callee's signature=
                        if (useStmt.containsInvokeExpr()) {
                            for (int i = 0; i < useStmt.getInvokeExpr().getArgCount(); i++) {
                                if (useStmt.getInvokeExpr().getArg(i) == usePair.getValueBox().getValue()) {
                                    et = useStmt.getInvokeExpr().getMethod().getParameterType(i);
                                    at = et.makeArrayType();
                                    break outer;
                                }
                            }
                        } else // if the other value is a primitive.
                        if (useStmt instanceof IfStmt) {
                            IfStmt ifStmt = (IfStmt) useStmt;
                            if (ifStmt.getCondition() instanceof EqExpr) {
                                EqExpr expr = (EqExpr) ifStmt.getCondition();
                                final Value other;
                                if (expr.getOp1() == usePair.getValueBox().getValue())
                                    other = expr.getOp2();
                                else
                                    other = expr.getOp1();
                                Type newEt = getTargetType(other);
                                if (newEt != null)
                                    et = newEt;
                            }
                        } else if (useStmt instanceof AssignStmt) {
                            // For binary expressions, we can look for type information in the
                            // other operands
                            AssignStmt useAssignStmt = (AssignStmt) useStmt;
                            if (useAssignStmt.getRightOp() instanceof BinopExpr) {
                                BinopExpr binOp = (BinopExpr) useAssignStmt.getRightOp();
                                final Value other;
                                if (binOp.getOp1() == usePair.getValueBox().getValue())
                                    other = binOp.getOp2();
                                else
                                    other = binOp.getOp1();
                                Type newEt = getTargetType(other);
                                if (newEt != null)
                                    et = newEt;
                            }
                        } else if (useStmt instanceof ReturnStmt) {
                            et = jb.getMethod().getReturnType();
                        }
                    }
                }
            }
            if (at == null)
                at = et.makeArrayType();
        }
        Type trhs = ((ArrayType) at).getElementType();
        this.handleArrayRef(aref, stmt);
        aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
        stmt.setRightOp(this.uv.visit(rhs, trhs, stmt));
    } else if (rhs instanceof InstanceFieldRef) {
        this.handleInstanceFieldRef((InstanceFieldRef) rhs, stmt);
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    } else if (rhs instanceof BinopExpr)
        this.handleBinopExpr((BinopExpr) rhs, stmt, tlhs);
    else if (rhs instanceof InvokeExpr) {
        this.handleInvokeExpr((InvokeExpr) rhs, stmt);
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    } else if (rhs instanceof CastExpr)
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    else if (rhs instanceof InstanceOfExpr) {
        InstanceOfExpr ioe = (InstanceOfExpr) rhs;
        ioe.setOp(this.uv.visit(ioe.getOp(), RefType.v("java.lang.Object"), stmt));
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    } else if (rhs instanceof NewArrayExpr) {
        NewArrayExpr nae = (NewArrayExpr) rhs;
        nae.setSize(this.uv.visit(nae.getSize(), IntType.v(), stmt));
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    } else if (rhs instanceof NewMultiArrayExpr) {
        NewMultiArrayExpr nmae = (NewMultiArrayExpr) rhs;
        for (int i = 0; i < nmae.getSizeCount(); i++) nmae.setSize(i, this.uv.visit(nmae.getSize(i), IntType.v(), stmt));
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    } else if (rhs instanceof LengthExpr) {
        stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
    } else if (rhs instanceof NegExpr) {
        ((NegExpr) rhs).setOp(this.uv.visit(((NegExpr) rhs).getOp(), tlhs, stmt));
    } else if (rhs instanceof Constant)
        if (!(rhs instanceof NullConstant))
            stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
}
Also used : AssignStmt(soot.jimple.AssignStmt) NewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) NullConstant(soot.jimple.NullConstant) Constant(soot.jimple.Constant) NegExpr(soot.jimple.NegExpr) Unit(soot.Unit) BreakpointStmt(soot.jimple.BreakpointStmt) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) InvokeStmt(soot.jimple.InvokeStmt) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) AssignStmt(soot.jimple.AssignStmt) ThrowStmt(soot.jimple.ThrowStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) TableSwitchStmt(soot.jimple.TableSwitchStmt) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) ReturnStmt(soot.jimple.ReturnStmt) ExitMonitorStmt(soot.jimple.ExitMonitorStmt) Stmt(soot.jimple.Stmt) ArrayRef(soot.jimple.ArrayRef) ArrayType(soot.ArrayType) RefType(soot.RefType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) InstanceFieldRef(soot.jimple.InstanceFieldRef) CastExpr(soot.jimple.CastExpr) PrimType(soot.PrimType) UnitValueBoxPair(soot.toolkits.scalar.UnitValueBoxPair) FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) LengthExpr(soot.jimple.LengthExpr) Local(soot.Local) NullConstant(soot.jimple.NullConstant) InstanceOfExpr(soot.jimple.InstanceOfExpr) RefType(soot.RefType) BooleanType(soot.BooleanType) Type(soot.Type) IntType(soot.IntType) NullType(soot.NullType) ArrayType(soot.ArrayType) IntegerType(soot.IntegerType) PrimType(soot.PrimType) IfStmt(soot.jimple.IfStmt) NewArrayExpr(soot.jimple.NewArrayExpr) EqExpr(soot.jimple.EqExpr) Value(soot.Value) NullType(soot.NullType) ReturnStmt(soot.jimple.ReturnStmt) BinopExpr(soot.jimple.BinopExpr)

Example 28 with PrimType

use of soot.PrimType in project soot by Sable.

the class BytecodeHierarchy method lcas_.

public static Collection<Type> lcas_(Type a, Type b) {
    if (TypeResolver.typesEqual(a, b))
        return Collections.<Type>singletonList(a);
    else if (a instanceof BottomType)
        return Collections.<Type>singletonList(b);
    else if (b instanceof BottomType)
        return Collections.<Type>singletonList(a);
    else if (a instanceof IntegerType && b instanceof IntegerType)
        return Collections.<Type>singletonList(IntType.v());
    else // Implicit type widening: Integer+Float -> Float
    if (a instanceof IntegerType && b instanceof FloatType)
        return Collections.<Type>singletonList(FloatType.v());
    else if (b instanceof IntegerType && a instanceof FloatType)
        return Collections.<Type>singletonList(FloatType.v());
    else // Disallow type sharing for primitives in general
    if (a instanceof PrimType || b instanceof PrimType)
        return Collections.<Type>emptyList();
    else // Null reference handling
    if (a instanceof NullType)
        return Collections.<Type>singletonList(b);
    else if (b instanceof NullType)
        return Collections.<Type>singletonList(a);
    else // a and b are both ArrayType or RefType
    if (a instanceof ArrayType && b instanceof ArrayType) {
        Type eta = ((ArrayType) a).getElementType(), etb = ((ArrayType) b).getElementType();
        Collection<Type> ts;
        // Primitive arrays are not covariant but all other arrays are
        if (eta instanceof PrimType || etb instanceof PrimType)
            ts = Collections.<Type>emptyList();
        else
            ts = lcas_(eta, etb);
        LinkedList<Type> r = new LinkedList<Type>();
        if (ts.isEmpty()) {
            // From Java Language Spec 2nd ed., Chapter 10, Arrays
            r.add(RefType.v("java.lang.Object"));
            r.add(RefType.v("java.io.Serializable"));
            r.add(RefType.v("java.lang.Cloneable"));
        } else
            for (Type t : ts) r.add(t.makeArrayType());
        return r;
    } else if (a instanceof ArrayType || b instanceof ArrayType) {
        Type rt;
        if (a instanceof ArrayType)
            rt = b;
        else
            rt = a;
        /* If the reference type implements Serializable or Cloneable then 
			these are the least common supertypes, otherwise the only one is 
			Object. */
        LinkedList<Type> r = new LinkedList<Type>();
        /* Do not consider Object to be a subtype of Serializable or Cloneable
			(it can appear this way if phantom-refs is enabled and rt.jar is not
			available) otherwise an infinite loop can result. */
        if (!TypeResolver.typesEqual(RefType.v("java.lang.Object"), rt)) {
            if (ancestor_(RefType.v("java.io.Serializable"), rt))
                r.add(RefType.v("java.io.Serializable"));
            if (ancestor_(RefType.v("java.lang.Cloneable"), rt))
                r.add(RefType.v("java.lang.Cloneable"));
        }
        if (r.isEmpty())
            r.add(RefType.v("java.lang.Object"));
        return r;
    } else // a and b are both RefType
    {
        Collection<AncestryTreeNode> treea = buildAncestryTree((RefType) a), treeb = buildAncestryTree((RefType) b);
        LinkedList<Type> r = new LinkedList<Type>();
        for (AncestryTreeNode nodea : treea) for (AncestryTreeNode nodeb : treeb) {
            RefType t = leastCommonNode(nodea, nodeb);
            boolean least = true;
            for (ListIterator<Type> i = r.listIterator(); i.hasNext(); ) {
                Type t_ = i.next();
                if (ancestor_(t, t_)) {
                    least = false;
                    break;
                }
                if (ancestor_(t_, t))
                    i.remove();
            }
            if (least)
                r.add(t);
        }
        // syed - 05/06/2009
        if (r.isEmpty())
            r.add(RefType.v("java.lang.Object"));
        return r;
    }
}
Also used : ListIterator(java.util.ListIterator) LinkedList(java.util.LinkedList) FloatType(soot.FloatType) IntegerType(soot.IntegerType) ArrayType(soot.ArrayType) RefType(soot.RefType) RefType(soot.RefType) ArrayType(soot.ArrayType) FloatType(soot.FloatType) IntegerType(soot.IntegerType) IntType(soot.IntType) Type(soot.Type) PrimType(soot.PrimType) NullType(soot.NullType) PrimType(soot.PrimType) Collection(java.util.Collection) NullType(soot.NullType)

Example 29 with PrimType

use of soot.PrimType in project soot by Sable.

the class CP method createConstantFieldsList.

/*
	 * Uses the results of the ConstantValueFinder to create a list of
	 * constantField CPTuple
	 */
private void createConstantFieldsList(HashMap<String, Object> constantFields, HashMap<String, SootField> classNameFieldNameToSootFieldMapping) {
    constantFieldTuples = new ArrayList<CPTuple>();
    Iterator<String> it = constantFields.keySet().iterator();
    // System.out.println("Adding constant fields to initial set: ");
    while (it.hasNext()) {
        String combined = it.next();
        int temp = combined.indexOf(ConstantFieldValueFinder.combiner, 0);
        if (temp > 0) {
            String className = combined.substring(0, temp);
            // String fieldName = combined.substring(temp+
            // ConstantFieldValueFinder.combiner.length());
            SootField field = classNameFieldNameToSootFieldMapping.get(combined);
            if (!(field.getType() instanceof PrimType)) {
                // we only care about PrimTypes
                continue;
            }
            // object type is double float long boolean or integer
            Object value = constantFields.get(combined);
            CPVariable var = new CPVariable(field);
            CPTuple newTuples = new CPTuple(className, var, value);
            constantFieldTuples.add(newTuples);
        // System.out.print("Class: "+className +
        // " Field: "+fieldName+" Value: "+value+"   ");
        } else {
            throw new DavaFlowAnalysisException("Second argument of VariableValuePair not a variable");
        }
    }
// System.out.println("");
}
Also used : DavaFlowAnalysisException(soot.dava.DavaFlowAnalysisException) PrimType(soot.PrimType) SootField(soot.SootField)

Example 30 with PrimType

use of soot.PrimType 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

PrimType (soot.PrimType)31 RefType (soot.RefType)15 ArrayList (java.util.ArrayList)12 Type (soot.Type)10 Value (soot.Value)10 DoubleType (soot.DoubleType)9 FloatType (soot.FloatType)9 IntType (soot.IntType)9 Local (soot.Local)9 LongType (soot.LongType)9 BooleanType (soot.BooleanType)8 SootClass (soot.SootClass)8 SootMethod (soot.SootMethod)8 ByteType (soot.ByteType)7 CharType (soot.CharType)7 ShortType (soot.ShortType)7 ArrayType (soot.ArrayType)6 VoidType (soot.VoidType)6 MethodVisitor (org.objectweb.asm.MethodVisitor)4 PointerType (org.robovm.compiler.llvm.PointerType)4