Search in sources :

Example 1 with ThrowStmt

use of soot.jimple.ThrowStmt in project robovm by robovm.

the class MethodCompiler method doCompile.

protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
    function = createMethodFunction(method);
    moduleBuilder.addFunction(function);
    this.moduleBuilder = moduleBuilder;
    env = function.getParameterRef(0);
    trapsAt = new HashMap<Unit, List<Trap>>();
    Body body = method.retrieveActiveBody();
    NopStmt prependedNop = null;
    if (method.isStatic() && !body.getUnits().getFirst().getBoxesPointingToThis().isEmpty()) {
        // Fix for issue #1. This prevents an NPE in Soot's ArrayBoundsCheckerAnalysis. The NPE
        // occurs for static methods which start with a unit that is the target of some other
        // unit. We work around this by inserting a nop statement as the first unit in such 
        // methods. See http://www.sable.mcgill.ca/listarchives/soot-list/msg01397.html.
        Unit insertionPoint = body.getUnits().getFirst();
        prependedNop = Jimple.v().newNopStmt();
        body.getUnits().getNonPatchingChain().insertBefore(prependedNop, insertionPoint);
    }
    PackManager.v().getPack("jtp").apply(body);
    PackManager.v().getPack("jop").apply(body);
    PackManager.v().getPack("jap").apply(body);
    if (body.getUnits().getFirst() == prependedNop && prependedNop.getBoxesPointingToThis().isEmpty()) {
        // Remove the nop we inserted above to work around the bug in Soot's 
        // ArrayBoundsCheckerAnalysis which has now been run.
        body.getUnits().getNonPatchingChain().removeFirst();
    }
    PatchingChain<Unit> units = body.getUnits();
    Map<Unit, List<Unit>> branchTargets = getBranchTargets(body);
    Map<Unit, Integer> trapHandlers = getTrapHandlers(body);
    Map<Unit, Integer> selChanges = new HashMap<Unit, Integer>();
    int multiANewArrayMaxDims = 0;
    Set<Local> locals = new HashSet<Local>();
    boolean emitCheckStackOverflow = false;
    for (Unit unit : units) {
        if (unit instanceof DefinitionStmt) {
            DefinitionStmt stmt = (DefinitionStmt) unit;
            if (stmt.getLeftOp() instanceof Local) {
                Local local = (Local) stmt.getLeftOp();
                if (!locals.contains(local)) {
                    Type type = getLocalType(local.getType());
                    Alloca alloca = new Alloca(function.newVariable(local.getName(), type), type);
                    alloca.attach(local);
                    function.add(alloca);
                    locals.add(local);
                }
            }
            if (stmt.getRightOp() instanceof NewMultiArrayExpr) {
                NewMultiArrayExpr expr = (NewMultiArrayExpr) stmt.getRightOp();
                multiANewArrayMaxDims = Math.max(multiANewArrayMaxDims, expr.getSizeCount());
            }
            if (stmt.getRightOp() instanceof InvokeExpr) {
                emitCheckStackOverflow = true;
            }
        }
        if (unit instanceof InvokeStmt) {
            emitCheckStackOverflow = true;
        }
    }
    dims = null;
    if (multiANewArrayMaxDims > 0) {
        dims = function.newVariable("dims", new PointerType(new ArrayType(multiANewArrayMaxDims, I32)));
        function.add(new Alloca(dims, new ArrayType(multiANewArrayMaxDims, I32)));
    }
    if (emitCheckStackOverflow) {
        call(CHECK_STACK_OVERFLOW);
    }
    Value trycatchContext = null;
    if (!body.getTraps().isEmpty()) {
        List<List<Trap>> recordedTraps = new ArrayList<List<Trap>>();
        for (Unit unit : units) {
            // Calculate the predecessor units of unit 
            Set<Unit> incoming = new HashSet<Unit>();
            if (units.getFirst() != unit && units.getPredOf(unit).fallsThrough()) {
                incoming.add(units.getPredOf(unit));
            }
            if (branchTargets.keySet().contains(unit)) {
                incoming.addAll(branchTargets.get(unit));
            }
            if (unit == units.getFirst() || trapHandlers.containsKey(unit) || trapsDiffer(unit, incoming)) {
                List<Trap> traps = getTrapsAt(unit);
                if (traps.isEmpty()) {
                    selChanges.put(unit, 0);
                } else {
                    int index = recordedTraps.indexOf(traps);
                    if (index == -1) {
                        index = recordedTraps.size();
                        recordedTraps.add(traps);
                    }
                    selChanges.put(unit, index + 1);
                }
            }
        }
        StructureConstantBuilder landingPadsPtrs = new StructureConstantBuilder();
        for (List<Trap> traps : recordedTraps) {
            StructureConstantBuilder landingPads = new StructureConstantBuilder();
            for (Trap trap : traps) {
                SootClass exClass = trap.getException();
                StructureConstantBuilder landingPad = new StructureConstantBuilder();
                if ("java.lang.Throwable".equals(exClass.getName()) || exClass.isPhantom()) {
                    landingPad.add(new NullConstant(I8_PTR));
                } else {
                    catches.add(getInternalName(exClass));
                    if (exClass == sootClass) {
                        /*
                             * The class being compiled is an exception class
                             * with a catch clause which catches itself. We
                             * cannot reference the info struct directly since
                             * we don't know the type of it and it hasn't been
                             * emitted by ClassCompiler yet. Use the internal
                             * i8* alias instead which ClassCompiler will emit.
                             * See #1007.
                             */
                        landingPad.add(new AliasRef(Symbols.infoStructSymbol(getInternalName(exClass)) + "_i8ptr", I8_PTR));
                    } else {
                        Global g = new Global(Symbols.infoStructSymbol(getInternalName(exClass)), I8_PTR, true);
                        if (!moduleBuilder.hasSymbol(g.getName())) {
                            moduleBuilder.addGlobal(g);
                        }
                        landingPad.add(g.ref());
                    }
                }
                landingPad.add(new IntegerConstant(trapHandlers.get(trap.getHandlerUnit()) + 1));
                landingPads.add(landingPad.build());
            }
            landingPads.add(new StructureConstantBuilder().add(new NullConstant(I8_PTR)).add(new IntegerConstant(0)).build());
            Global g = moduleBuilder.newGlobal(landingPads.build(), true);
            landingPadsPtrs.add(new ConstantBitcast(g.ref(), I8_PTR));
        }
        Global g = moduleBuilder.newGlobal(landingPadsPtrs.build(), true);
        Variable ctx = function.newVariable(TRYCATCH_CONTEXT_PTR);
        Variable bcCtx = function.newVariable(BC_TRYCATCH_CONTEXT_PTR);
        function.add(new Alloca(bcCtx, BC_TRYCATCH_CONTEXT));
        Variable selPtr = function.newVariable(new PointerType(I32));
        function.add(new Getelementptr(selPtr, bcCtx.ref(), 0, 0, 1));
        function.add(new Store(new IntegerConstant(0), selPtr.ref()));
        Variable bcCtxLandingPadsPtr = function.newVariable(I8_PTR_PTR);
        function.add(new Getelementptr(bcCtxLandingPadsPtr, bcCtx.ref(), 0, 1));
        function.add(new Store(new ConstantBitcast(g.ref(), I8_PTR), bcCtxLandingPadsPtr.ref()));
        function.add(new Bitcast(ctx, bcCtx.ref(), TRYCATCH_CONTEXT_PTR));
        trycatchContext = ctx.ref();
        Value result = call(RVM_TRYCATCH_ENTER, env, trycatchContext);
        Map<IntegerConstant, BasicBlockRef> alt = new TreeMap<IntegerConstant, BasicBlockRef>();
        for (Entry<Unit, Integer> entry : trapHandlers.entrySet()) {
            alt.put(new IntegerConstant(entry.getValue() + 1), function.newBasicBlockRef(new Label(entry.getKey())));
        }
        function.add(new Switch(result, function.newBasicBlockRef(new Label(units.getFirst())), alt));
        if (!branchTargets.containsKey(units.getFirst())) {
            function.newBasicBlock(new Label(units.getFirst()));
        }
    }
    if ("<clinit>".equals(method.getName())) {
        initializeClassFields();
    }
    for (Unit unit : units) {
        if (branchTargets.containsKey(unit) || trapHandlers.containsKey(unit)) {
            BasicBlock oldBlock = function.getCurrentBasicBlock();
            function.newBasicBlock(new Label(unit));
            if (oldBlock != null) {
                Instruction last = oldBlock.last();
                if (last == null || !isTerminator(last)) {
                    oldBlock.add(new Br(function.newBasicBlockRef(new Label(unit))));
                }
            }
        }
        if (selChanges.containsKey(unit)) {
            int sel = selChanges.get(unit);
            // trycatchContext->sel = sel
            Variable selPtr = function.newVariable(new PointerType(I32));
            function.add(new Getelementptr(selPtr, trycatchContext, 0, 1)).attach(unit);
            function.add(new Store(new IntegerConstant(sel), selPtr.ref())).attach(unit);
        }
        if (unit instanceof DefinitionStmt) {
            assign((DefinitionStmt) unit);
        } else if (unit instanceof ReturnStmt) {
            if (!body.getTraps().isEmpty()) {
                trycatchLeave(function);
            }
            return_((ReturnStmt) unit);
        } else if (unit instanceof ReturnVoidStmt) {
            if (!body.getTraps().isEmpty()) {
                trycatchLeave(function);
            }
            returnVoid((ReturnVoidStmt) unit);
        } else if (unit instanceof IfStmt) {
            if_((IfStmt) unit);
        } else if (unit instanceof LookupSwitchStmt) {
            lookupSwitch((LookupSwitchStmt) unit);
        } else if (unit instanceof TableSwitchStmt) {
            tableSwitch((TableSwitchStmt) unit);
        } else if (unit instanceof GotoStmt) {
            goto_((GotoStmt) unit);
        } else if (unit instanceof ThrowStmt) {
            throw_((ThrowStmt) unit);
        } else if (unit instanceof InvokeStmt) {
            invoke((InvokeStmt) unit);
        } else if (unit instanceof EnterMonitorStmt) {
            enterMonitor((EnterMonitorStmt) unit);
        } else if (unit instanceof ExitMonitorStmt) {
            exitMonitor((ExitMonitorStmt) unit);
        } else if (unit instanceof NopStmt) {
            nop((NopStmt) unit);
        } else {
            throw new IllegalArgumentException("Unknown Unit type: " + unit.getClass());
        }
    }
    if (this.className.equals("java/lang/Object") && "<init>".equals(method.getName())) {
        // If it is the object will be registered for finalization.
        for (BasicBlock bb : function.getBasicBlocks()) {
            if (bb.last() instanceof Ret) {
                // Insert a call to register_finalizable() before this ret
                Call call = new Call(REGISTER_FINALIZABLE, env, function.getParameterRef(1));
                call.attach(bb.last().getAttachment(Unit.class));
                bb.insertBefore(bb.last(), call);
            }
        }
    }
    return function;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Label(org.robovm.compiler.llvm.Label) Store(org.robovm.compiler.llvm.Store) Unit(soot.Unit) Instruction(org.robovm.compiler.llvm.Instruction) Global(org.robovm.compiler.llvm.Global) ArrayType(org.robovm.compiler.llvm.ArrayType) TableSwitchStmt(soot.jimple.TableSwitchStmt) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) GotoStmt(soot.jimple.GotoStmt) ArrayList(java.util.ArrayList) List(java.util.List) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) HashSet(java.util.HashSet) BasicBlock(org.robovm.compiler.llvm.BasicBlock) Local(soot.Local) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Switch(org.robovm.compiler.llvm.Switch) Bitcast(org.robovm.compiler.llvm.Bitcast) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) Value(org.robovm.compiler.llvm.Value) DefinitionStmt(soot.jimple.DefinitionStmt) ReturnStmt(soot.jimple.ReturnStmt) ThrowStmt(soot.jimple.ThrowStmt) ExitMonitorStmt(soot.jimple.ExitMonitorStmt) Variable(org.robovm.compiler.llvm.Variable) InvokeStmt(soot.jimple.InvokeStmt) AliasRef(org.robovm.compiler.llvm.AliasRef) NewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) PointerType(org.robovm.compiler.llvm.PointerType) Getelementptr(org.robovm.compiler.llvm.Getelementptr) BasicBlockRef(org.robovm.compiler.llvm.BasicBlockRef) Body(soot.Body) Call(org.robovm.compiler.llvm.Call) Alloca(org.robovm.compiler.llvm.Alloca) NullConstant(org.robovm.compiler.llvm.NullConstant) Trap(soot.Trap) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) SootClass(soot.SootClass) TreeMap(java.util.TreeMap) Br(org.robovm.compiler.llvm.Br) FloatingPointType(org.robovm.compiler.llvm.FloatingPointType) IntegerType(org.robovm.compiler.llvm.IntegerType) PointerType(org.robovm.compiler.llvm.PointerType) NullType(soot.NullType) FunctionType(org.robovm.compiler.llvm.FunctionType) ArrayType(org.robovm.compiler.llvm.ArrayType) CharType(soot.CharType) RefLikeType(soot.RefLikeType) Type(org.robovm.compiler.llvm.Type) PrimType(soot.PrimType) IfStmt(soot.jimple.IfStmt) NopStmt(soot.jimple.NopStmt)

Example 2 with ThrowStmt

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

the class AsmMethodSource method convertInsn.

private void convertInsn(InsnNode insn) {
    int op = insn.getOpcode();
    if (op == NOP) {
        /*
			 * We can ignore NOP instructions, but
			 * for completeness, we handle them
			 */
        if (!units.containsKey(insn))
            units.put(insn, Jimple.v().newNopStmt());
    } else if (op >= ACONST_NULL && op <= DCONST_1) {
        convertConstInsn(insn);
    } else if (op >= IALOAD && op <= SALOAD) {
        convertArrayLoadInsn(insn);
    } else if (op >= IASTORE && op <= SASTORE) {
        convertArrayStoreInsn(insn);
    } else if (op == POP) {
        popImmediate();
    } else if (op == POP2) {
        popImmediate();
        if (peek() == DWORD_DUMMY)
            pop();
        else
            popImmediate();
    } else if (op >= DUP && op <= DUP2_X2) {
        convertDupInsn((InsnNode) insn);
    } else if (op == SWAP) {
        Operand o1 = popImmediate();
        Operand o2 = popImmediate();
        push(o1);
        push(o2);
    } else if ((op >= IADD && op <= DREM) || (op >= ISHL && op <= LXOR) || (op >= LCMP && op <= DCMPG)) {
        convertBinopInsn((InsnNode) insn);
    } else if ((op >= INEG && op <= DNEG) || op == ARRAYLENGTH) {
        convertUnopInsn(insn);
    } else if (op >= I2L && op <= I2S) {
        convertPrimCastInsn(insn);
    } else if (op >= IRETURN && op <= ARETURN) {
        convertReturnInsn(insn);
    } else if (op == RETURN) {
        if (!units.containsKey(insn))
            setUnit(insn, Jimple.v().newReturnVoidStmt());
    } else if (op == ATHROW) {
        StackFrame frame = getFrame(insn);
        Operand opr;
        if (!units.containsKey(insn)) {
            opr = popImmediate();
            ThrowStmt ts = Jimple.v().newThrowStmt(opr.stackOrValue());
            opr.addBox(ts.getOpBox());
            frame.in(opr);
            frame.out(opr);
            frame.boxes(ts.getOpBox());
            setUnit(insn, ts);
        } else {
            opr = pop();
            frame.mergeIn(opr);
        }
        push(opr);
    } else if (op == MONITORENTER || op == MONITOREXIT) {
        StackFrame frame = getFrame(insn);
        if (!units.containsKey(insn)) {
            Operand opr = popStackConst();
            MonitorStmt ts = op == MONITORENTER ? Jimple.v().newEnterMonitorStmt(opr.stackOrValue()) : Jimple.v().newExitMonitorStmt(opr.stackOrValue());
            opr.addBox(ts.getOpBox());
            frame.in(opr);
            frame.boxes(ts.getOpBox());
            setUnit(insn, ts);
        } else {
            frame.mergeIn(pop());
        }
    } else {
        throw new AssertionError("Unknown insn op: " + op);
    }
}
Also used : ThrowStmt(soot.jimple.ThrowStmt) MonitorStmt(soot.jimple.MonitorStmt)

Example 3 with ThrowStmt

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

the class MethodNodeFactory method handleStmt.

/**
 * Adds the edges required for this statement to the graph.
 */
public final void handleStmt(Stmt s) {
    // We only consider reflective class creation when it is enabled
    if (s.containsInvokeExpr()) {
        if (!pag.getCGOpts().types_for_invoke())
            return;
        InvokeExpr iexpr = s.getInvokeExpr();
        if (iexpr instanceof VirtualInvokeExpr) {
            if (!isReflectionNewInstance(iexpr))
                return;
        } else if (!(iexpr instanceof StaticInvokeExpr))
            return;
    }
    s.apply(new AbstractStmtSwitch() {

        @Override
        public final void caseAssignStmt(AssignStmt as) {
            Value l = as.getLeftOp();
            Value r = as.getRightOp();
            if (!(l.getType() instanceof RefLikeType))
                return;
            assert r.getType() instanceof RefLikeType : "Type mismatch in assignment " + as + " in method " + method.getSignature();
            l.apply(MethodNodeFactory.this);
            Node dest = getNode();
            r.apply(MethodNodeFactory.this);
            Node src = getNode();
            if (l instanceof InstanceFieldRef) {
                ((InstanceFieldRef) l).getBase().apply(MethodNodeFactory.this);
                pag.addDereference((VarNode) getNode());
            }
            if (r instanceof InstanceFieldRef) {
                ((InstanceFieldRef) r).getBase().apply(MethodNodeFactory.this);
                pag.addDereference((VarNode) getNode());
            } else if (r instanceof StaticFieldRef) {
                StaticFieldRef sfr = (StaticFieldRef) r;
                SootFieldRef s = sfr.getFieldRef();
                if (pag.getOpts().empties_as_allocs()) {
                    if (s.declaringClass().getName().equals("java.util.Collections")) {
                        if (s.name().equals("EMPTY_SET")) {
                            src = pag.makeAllocNode(RefType.v("java.util.HashSet"), RefType.v("java.util.HashSet"), method);
                        } else if (s.name().equals("EMPTY_MAP")) {
                            src = pag.makeAllocNode(RefType.v("java.util.HashMap"), RefType.v("java.util.HashMap"), method);
                        } else if (s.name().equals("EMPTY_LIST")) {
                            src = pag.makeAllocNode(RefType.v("java.util.LinkedList"), RefType.v("java.util.LinkedList"), method);
                        }
                    } else if (s.declaringClass().getName().equals("java.util.Hashtable")) {
                        if (s.name().equals("emptyIterator")) {
                            src = pag.makeAllocNode(RefType.v("java.util.Hashtable$EmptyIterator"), RefType.v("java.util.Hashtable$EmptyIterator"), method);
                        } else if (s.name().equals("emptyEnumerator")) {
                            src = pag.makeAllocNode(RefType.v("java.util.Hashtable$EmptyEnumerator"), RefType.v("java.util.Hashtable$EmptyEnumerator"), method);
                        }
                    }
                }
            }
            mpag.addInternalEdge(src, dest);
        }

        @Override
        public final void caseReturnStmt(ReturnStmt rs) {
            if (!(rs.getOp().getType() instanceof RefLikeType))
                return;
            rs.getOp().apply(MethodNodeFactory.this);
            Node retNode = getNode();
            mpag.addInternalEdge(retNode, caseRet());
        }

        @Override
        public final void caseIdentityStmt(IdentityStmt is) {
            if (!(is.getLeftOp().getType() instanceof RefLikeType))
                return;
            Value leftOp = is.getLeftOp();
            Value rightOp = is.getRightOp();
            leftOp.apply(MethodNodeFactory.this);
            Node dest = getNode();
            rightOp.apply(MethodNodeFactory.this);
            Node src = getNode();
            mpag.addInternalEdge(src, dest);
            // in case library mode is activated add allocations to any
            // possible type of this local and
            // parameters of accessible methods
            int libOption = pag.getCGOpts().library();
            if (libOption != CGOptions.library_disabled && (accessibilityOracle.isAccessible(method))) {
                if (rightOp instanceof IdentityRef) {
                    Type rt = rightOp.getType();
                    rt.apply(new SparkLibraryHelper(pag, src, method));
                }
            }
        }

        @Override
        public final void caseThrowStmt(ThrowStmt ts) {
            ts.getOp().apply(MethodNodeFactory.this);
            mpag.addOutEdge(getNode(), pag.nodeFactory().caseThrow());
        }
    });
}
Also used : VarNode(soot.jimple.spark.pag.VarNode) AssignStmt(soot.jimple.AssignStmt) NewInstanceNode(soot.jimple.spark.pag.NewInstanceNode) Node(soot.jimple.spark.pag.Node) VarNode(soot.jimple.spark.pag.VarNode) AllocNode(soot.jimple.spark.pag.AllocNode) SootFieldRef(soot.SootFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) RefLikeType(soot.RefLikeType) RefType(soot.RefType) Type(soot.Type) RefLikeType(soot.RefLikeType) ArrayType(soot.ArrayType) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) IdentityRef(soot.jimple.IdentityRef) AbstractStmtSwitch(soot.jimple.AbstractStmtSwitch) Value(soot.Value) InstanceFieldRef(soot.jimple.InstanceFieldRef) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) ReturnStmt(soot.jimple.ReturnStmt) ThrowStmt(soot.jimple.ThrowStmt) IdentityStmt(soot.jimple.IdentityStmt) SparkLibraryHelper(soot.jimple.spark.internal.SparkLibraryHelper)

Example 4 with ThrowStmt

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

the class DalvikTyper method assignType.

@Override
public void assignType(final Body b) {
    // Debug.printDbg("assignTypes: before: \n", b);
    constraints.clear();
    localObjList.clear();
    final Set<Unit> todoUnits = new HashSet<Unit>();
    // put constraints:
    for (Unit u : b.getUnits()) {
        StmtSwitch ss = new StmtSwitch() {

            @Override
            public void caseBreakpointStmt(BreakpointStmt stmt) {
            // nothing
            }

            @Override
            public void caseInvokeStmt(InvokeStmt stmt) {
                // add constraint
                DalvikTyper.v().setInvokeType(stmt.getInvokeExpr());
            }

            @Override
            public void caseAssignStmt(AssignStmt stmt) {
                // add constraint
                Value l = stmt.getLeftOp();
                Value r = stmt.getRightOp();
                // size in new array expression is of tye integer
                if (r instanceof NewArrayExpr) {
                    NewArrayExpr nae = (NewArrayExpr) r;
                    ValueBox sb = nae.getSizeBox();
                    if (sb.getValue() instanceof Local) {
                        DalvikTyper.v().setType(sb, IntType.v(), true);
                    }
                }
                // array index is of type integer
                if (stmt.containsArrayRef()) {
                    ArrayRef ar = stmt.getArrayRef();
                    ValueBox sb = ar.getIndexBox();
                    if (sb.getValue() instanceof Local) {
                        DalvikTyper.v().setType(sb, IntType.v(), true);
                    }
                }
                if (l instanceof Local && r instanceof Local) {
                    DalvikTyper.v().addConstraint(stmt.getLeftOpBox(), stmt.getRightOpBox());
                    return;
                }
                if (stmt.containsInvokeExpr()) {
                    DalvikTyper.v().setInvokeType(stmt.getInvokeExpr());
                }
                if (r instanceof Local) {
                    // l NOT local
                    Type leftType = stmt.getLeftOp().getType();
                    if (l instanceof ArrayRef && leftType instanceof UnknownType) {
                        // find type later
                        todoUnits.add(stmt);
                        return;
                    }
                    DalvikTyper.v().setType(stmt.getRightOpBox(), leftType, true);
                    return;
                }
                if (l instanceof Local) {
                    if (r instanceof UntypedConstant)
                        return;
                    for (Tag t : stmt.getTags()) {
                        if (r instanceof CastExpr) {
                            // do not check tag, since the tag is for the operand of the cast
                            break;
                        }
                        // Debug.printDbg("assign stmt tag: ", stmt, t);
                        if (t instanceof IntOpTag) {
                            checkExpr(r, IntType.v());
                            DalvikTyper.v().setType(stmt.getLeftOpBox(), IntType.v(), false);
                            return;
                        } else if (t instanceof FloatOpTag) {
                            checkExpr(r, FloatType.v());
                            DalvikTyper.v().setType(stmt.getLeftOpBox(), FloatType.v(), false);
                            return;
                        } else if (t instanceof DoubleOpTag) {
                            checkExpr(r, DoubleType.v());
                            DalvikTyper.v().setType(stmt.getLeftOpBox(), DoubleType.v(), false);
                            return;
                        } else if (t instanceof LongOpTag) {
                            checkExpr(r, LongType.v());
                            DalvikTyper.v().setType(stmt.getLeftOpBox(), LongType.v(), false);
                            return;
                        }
                    }
                    Type rightType = stmt.getRightOp().getType();
                    if (r instanceof ArrayRef && rightType instanceof UnknownType) {
                        // find type later
                        todoUnits.add(stmt);
                        return;
                    } else if (r instanceof CastExpr) {
                        CastExpr ce = (CastExpr) r;
                        Type castType = ce.getCastType();
                        if (castType instanceof PrimType) {
                            // check incoming primitive type
                            for (Tag t : stmt.getTags()) {
                                // Debug.printDbg("assign primitive type from stmt tag: ", stmt, t);
                                if (t instanceof IntOpTag) {
                                    DalvikTyper.v().setType(ce.getOpBox(), IntType.v(), false);
                                    return;
                                } else if (t instanceof FloatOpTag) {
                                    DalvikTyper.v().setType(ce.getOpBox(), FloatType.v(), false);
                                    return;
                                } else if (t instanceof DoubleOpTag) {
                                    DalvikTyper.v().setType(ce.getOpBox(), DoubleType.v(), false);
                                    return;
                                } else if (t instanceof LongOpTag) {
                                    DalvikTyper.v().setType(ce.getOpBox(), LongType.v(), false);
                                    return;
                                }
                            }
                        } else {
                            // incoming type is object
                            DalvikTyper.v().setType(ce.getOpBox(), RefType.v("java.lang.Object"), false);
                        }
                    }
                    DalvikTyper.v().setType(stmt.getLeftOpBox(), rightType, false);
                    return;
                }
            }

            @Override
            public void caseIdentityStmt(IdentityStmt stmt) {
                DalvikTyper.v().setType(stmt.getLeftOpBox(), stmt.getRightOp().getType(), false);
            }

            @Override
            public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
                // add constraint
                DalvikTyper.v().setType(stmt.getOpBox(), RefType.v("java.lang.Object"), true);
            }

            @Override
            public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
                // add constraint
                DalvikTyper.v().setType(stmt.getOpBox(), RefType.v("java.lang.Object"), true);
            }

            @Override
            public void caseGotoStmt(GotoStmt stmt) {
            // nothing
            }

            @Override
            public void caseIfStmt(IfStmt stmt) {
                // add constraint
                Value c = stmt.getCondition();
                if (c instanceof BinopExpr) {
                    BinopExpr bo = (BinopExpr) c;
                    Value op1 = bo.getOp1();
                    Value op2 = bo.getOp2();
                    if (op1 instanceof Local && op2 instanceof Local) {
                        DalvikTyper.v().addConstraint(bo.getOp1Box(), bo.getOp2Box());
                    }
                }
            }

            @Override
            public void caseLookupSwitchStmt(LookupSwitchStmt stmt) {
                // add constraint
                DalvikTyper.v().setType(stmt.getKeyBox(), IntType.v(), true);
            }

            @Override
            public void caseNopStmt(NopStmt stmt) {
            // nothing
            }

            @Override
            public void caseRetStmt(RetStmt stmt) {
            // nothing
            }

            @Override
            public void caseReturnStmt(ReturnStmt stmt) {
                // add constraint
                DalvikTyper.v().setType(stmt.getOpBox(), b.getMethod().getReturnType(), true);
            }

            @Override
            public void caseReturnVoidStmt(ReturnVoidStmt stmt) {
            // nothing
            }

            @Override
            public void caseTableSwitchStmt(TableSwitchStmt stmt) {
                // add constraint
                DalvikTyper.v().setType(stmt.getKeyBox(), IntType.v(), true);
            }

            @Override
            public void caseThrowStmt(ThrowStmt stmt) {
                // add constraint
                DalvikTyper.v().setType(stmt.getOpBox(), RefType.v("java.lang.Object"), true);
            }

            @Override
            public void defaultCase(Object obj) {
                throw new RuntimeException("error: unknown statement: " + obj);
            }
        };
        u.apply(ss);
    }
    // <com.admob.android.ads.q: void a(android.os.Bundle,java.lang.String,java.lang.Object)>
    if (!todoUnits.isEmpty()) {
        // propagate array types
        UnitGraph ug = new ExceptionalUnitGraph(b);
        SimpleLocalDefs sld = new SimpleLocalDefs(ug);
        SimpleLocalUses slu = new SimpleLocalUses(b, sld);
        for (Unit u : b.getUnits()) {
            if (u instanceof DefinitionStmt) {
                // Debug.printDbg("U: ", u);
                DefinitionStmt ass = (DefinitionStmt) u;
                Value r = ass.getRightOp();
                if (r instanceof UntypedConstant)
                    continue;
                Type rType = r.getType();
                if (rType instanceof ArrayType && ass.getLeftOp() instanceof Local) {
                    // Debug.printDbg("propagate-array: checking ", u);
                    // propagate array type through aliases
                    Set<Unit> done = new HashSet<Unit>();
                    Set<DefinitionStmt> toDo = new HashSet<DefinitionStmt>();
                    toDo.add(ass);
                    while (!toDo.isEmpty()) {
                        DefinitionStmt currentUnit = toDo.iterator().next();
                        if (done.contains(currentUnit)) {
                            toDo.remove(currentUnit);
                            continue;
                        }
                        done.add(currentUnit);
                        for (UnitValueBoxPair uvbp : slu.getUsesOf(currentUnit)) {
                            Unit use = uvbp.unit;
                            Value l2 = null;
                            Value r2 = null;
                            if (use instanceof AssignStmt) {
                                AssignStmt ass2 = (AssignStmt) use;
                                l2 = ass2.getLeftOp();
                                r2 = ass2.getRightOp();
                                if (!(l2 instanceof Local) || !(r2 instanceof Local || r2 instanceof ArrayRef)) {
                                    // Debug.printDbg("propagate-array: skipping ", use);
                                    continue;
                                }
                                Type newType = null;
                                if (r2 instanceof Local) {
                                    List<LocalObj> lobjs = local2Obj.get(r2);
                                    newType = lobjs.get(0).t;
                                } else if (r2 instanceof ArrayRef) {
                                    ArrayRef ar = (ArrayRef) r2;
                                    // skip if use is in index
                                    if (ar.getIndex() == currentUnit.getLeftOp()) {
                                        // Debug.printDbg("skipping since local is used as index...");
                                        continue;
                                    }
                                    Local arBase = (Local) ar.getBase();
                                    List<LocalObj> lobjs = local2Obj.get(arBase);
                                    Type baseT = lobjs.get(0).t;
                                    if (baseT.toString().equals(("java.lang.Object"))) {
                                        // look for an array type, because an TTT[] is also an Object...
                                        ArrayType aTypeOtherThanObject = null;
                                        for (LocalObj lo : local2Obj.get(arBase)) {
                                            if (lo.t instanceof ArrayType) {
                                                aTypeOtherThanObject = (ArrayType) lo.t;
                                            }
                                        }
                                        if (aTypeOtherThanObject == null) {
                                            throw new RuntimeException("error: did not found array type for base " + arBase + " " + local2Obj.get(arBase) + " \n " + b);
                                        }
                                        baseT = aTypeOtherThanObject;
                                    }
                                    ArrayType at = (ArrayType) baseT;
                                    newType = at.getElementType();
                                } else {
                                    throw new RuntimeException("error: expected Local or ArrayRef. Got " + r2);
                                }
                                toDo.add((DefinitionStmt) use);
                                DalvikTyper.v().setType(ass2.getLeftOpBox(), newType, true);
                            }
                        }
                    }
                }
            }
        }
        for (Unit u : todoUnits) {
        // Debug.printDbg("todo unit: ", u);
        }
        while (!todoUnits.isEmpty()) {
            Unit u = todoUnits.iterator().next();
            if (!(u instanceof AssignStmt)) {
                throw new RuntimeException("error: expecting assign stmt. Got " + u);
            }
            AssignStmt ass = (AssignStmt) u;
            Value l = ass.getLeftOp();
            Value r = ass.getRightOp();
            ArrayRef ar = null;
            Local loc = null;
            if (l instanceof ArrayRef) {
                ar = (ArrayRef) l;
                loc = (Local) r;
            } else if (r instanceof ArrayRef) {
                ar = (ArrayRef) r;
                loc = (Local) l;
            } else {
                throw new RuntimeException("error: expecting an array ref. Got " + u);
            }
            Local baselocal = (Local) ar.getBase();
            if (!local2Obj.containsKey(baselocal)) {
                // Debug.printDbg("b: ", b.getMethod(), " \n", b);
                throw new RuntimeException("oups");
            }
            Type baseT = local2Obj.get(baselocal).get(0).t;
            if (baseT.toString().equals(("java.lang.Object"))) {
                // look for an array type, because an TTT[] is also an Object...
                ArrayType aTypeOtherThanObject = null;
                for (LocalObj lo : local2Obj.get(baselocal)) {
                    if (lo.t instanceof ArrayType) {
                        aTypeOtherThanObject = (ArrayType) lo.t;
                    }
                }
                if (aTypeOtherThanObject == null) {
                    throw new RuntimeException("did not found array type for base " + baselocal + " " + local2Obj.get(baselocal) + " \n " + b);
                }
                baseT = aTypeOtherThanObject;
            }
            ArrayType basetype = (ArrayType) baseT;
            // Debug.printDbg("v: ", ar, " base:", ar.getBase(), " base type: ", basetype, " type: ", ar.getType());
            Type t = basetype.getElementType();
            if (t instanceof UnknownType) {
                todoUnits.add(u);
                continue;
            } else {
                DalvikTyper.v().setType(ar == l ? ass.getRightOpBox() : ass.getLeftOpBox(), t, true);
                todoUnits.remove(u);
            }
        }
    // throw new RuntimeException("ouppppp");
    }
    // Debug.printDbg(IDalvikTyper.DEBUG, "list of constraints:");
    List<ValueBox> vbList = b.getUseAndDefBoxes();
    // clear constraints after local splitting and dead code eliminator
    List<Constraint> toRemove = new ArrayList<Constraint>();
    for (Constraint c : constraints) {
        if (!vbList.contains(c.l)) {
            // Debug.printDbg(IDalvikTyper.DEBUG, "warning: ", c.l, " not in locals! removing...");
            toRemove.add(c);
            continue;
        }
        if (!vbList.contains(c.r)) {
            // Debug.printDbg(IDalvikTyper.DEBUG, "warning: ", c.r, " not in locals! removing...");
            toRemove.add(c);
            continue;
        }
    }
    for (Constraint c : toRemove) constraints.remove(c);
    // keep only valid locals
    for (LocalObj lo : localObjList) {
        if (!vbList.contains(lo.vb)) {
            // Debug.printDbg(IDalvikTyper.DEBUG, "  -- removing vb: ", lo.vb, " with type ", lo.t);
            continue;
        }
        Local l = lo.getLocal();
        Type t = lo.t;
        if (localTemp.contains(l) && lo.isUse) {
        // Debug.printDbg(IDalvikTyper.DEBUG, "  /!\\ def already added for local ", l, "! for vb: ", lo.vb);
        } else {
            // Debug.printDbg(IDalvikTyper.DEBUG, "  * add type ", t, " to local ", l, " for vb: ", lo.vb);
            localTemp.add(l);
            typed.put(lo.vb, t);
        }
    }
    for (ValueBox vb : typed.keySet()) {
        if (vb.getValue() instanceof Local) {
            Local l = (Local) vb.getValue();
            localTyped.put(l, typed.get(vb));
        }
    }
    for (Constraint c : constraints) // Debug.printDbg(IDalvikTyper.DEBUG, "  -> constraint: ", c);
    for (ValueBox vb : typed.keySet()) {
    // Debug.printDbg(IDalvikTyper.DEBUG, "    typed: ", vb, " -> ", typed.get(vb));
    }
    for (Local l : localTyped.keySet()) {
    // Debug.printDbg(IDalvikTyper.DEBUG, "    localTyped: ", l, " -> ", localTyped.get(l));
    }
    while (!constraints.isEmpty()) {
        boolean update = false;
        for (Constraint c : constraints) {
            // Debug.printDbg(IDalvikTyper.DEBUG, "current constraint: ", c);
            Value l = c.l.getValue();
            Value r = c.r.getValue();
            if (l instanceof Local && r instanceof Constant) {
                Constant cst = (Constant) r;
                if (!localTyped.containsKey(l))
                    continue;
                Type lt = localTyped.get(l);
                // Debug.printDbg(IDalvikTyper.DEBUG, "would like to set type ", lt, " to constant: ", c);
                Value newValue = null;
                if (lt instanceof IntType || lt instanceof BooleanType || lt instanceof ShortType || lt instanceof CharType || lt instanceof ByteType) {
                    UntypedIntOrFloatConstant uf = (UntypedIntOrFloatConstant) cst;
                    newValue = uf.toIntConstant();
                } else if (lt instanceof FloatType) {
                    UntypedIntOrFloatConstant uf = (UntypedIntOrFloatConstant) cst;
                    newValue = uf.toFloatConstant();
                } else if (lt instanceof DoubleType) {
                    UntypedLongOrDoubleConstant ud = (UntypedLongOrDoubleConstant) cst;
                    newValue = ud.toDoubleConstant();
                } else if (lt instanceof LongType) {
                    UntypedLongOrDoubleConstant ud = (UntypedLongOrDoubleConstant) cst;
                    newValue = ud.toLongConstant();
                } else {
                    if (cst instanceof UntypedIntOrFloatConstant && ((UntypedIntOrFloatConstant) cst).value == 0) {
                        newValue = NullConstant.v();
                    // Debug.printDbg("new null constant for constraint ", c, " with l type: ", localTyped.get(l));
                    } else {
                        throw new RuntimeException("unknow type for constance: " + lt);
                    }
                }
                c.r.setValue(newValue);
                // Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
                constraints.remove(c);
                update = true;
                break;
            } else if (l instanceof Local && r instanceof Local) {
                Local leftLocal = (Local) l;
                Local rightLocal = (Local) r;
                if (localTyped.containsKey(leftLocal)) {
                    Type leftLocalType = localTyped.get(leftLocal);
                    if (!localTyped.containsKey(rightLocal)) {
                        // Debug.printDbg(IDalvikTyper.DEBUG, "set type ", leftLocalType, " to local ", rightLocal);
                        rightLocal.setType(leftLocalType);
                        setLocalTyped(rightLocal, leftLocalType);
                    }
                    // Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
                    constraints.remove(c);
                    update = true;
                    break;
                } else if (localTyped.containsKey(rightLocal)) {
                    Type rightLocalType = localTyped.get(rightLocal);
                    if (!localTyped.containsKey(leftLocal)) {
                        // Debug.printDbg(IDalvikTyper.DEBUG, "set type ", rightLocalType, " to local ", leftLocal);
                        leftLocal.setType(rightLocalType);
                        setLocalTyped(leftLocal, rightLocalType);
                    }
                    // Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
                    constraints.remove(c);
                    update = true;
                    break;
                }
            } else if (l instanceof ArrayRef && r instanceof Local) {
                Local rightLocal = (Local) r;
                ArrayRef ar = (ArrayRef) l;
                Local base = (Local) ar.getBase();
                // Debug.printDbg(IDalvikTyper.DEBUG, "index: ", ar.getIndex());
                if (localTyped.containsKey(base)) {
                    Type t = localTyped.get(base);
                    // Debug.printDbg(IDalvikTyper.DEBUG, "type of local1: ", t, " ", t.getClass());
                    Type elementType = null;
                    if (t instanceof ArrayType) {
                        ArrayType at = (ArrayType) t;
                        elementType = at.getArrayElementType();
                    } else {
                        continue;
                    }
                    if (!localTyped.containsKey(rightLocal)) {
                        // Debug.printDbg(IDalvikTyper.DEBUG, "set type ", elementType, " to local ", r);
                        rightLocal.setType(elementType);
                        setLocalTyped(rightLocal, elementType);
                    }
                    // Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
                    constraints.remove(c);
                    update = true;
                    break;
                }
            } else if (l instanceof Local && r instanceof ArrayRef) {
                Local leftLocal = (Local) l;
                ArrayRef ar = (ArrayRef) r;
                Local base = (Local) ar.getBase();
                if (localTyped.containsKey(base)) {
                    Type t = localTyped.get(base);
                    // Debug.printDbg(IDalvikTyper.DEBUG, "type of local2: ", t, " ", t.getClass());
                    Type elementType = null;
                    if (t instanceof ArrayType) {
                        ArrayType at = (ArrayType) t;
                        elementType = at.getArrayElementType();
                    } else {
                        continue;
                    }
                    if (!localTyped.containsKey(leftLocal)) {
                        // Debug.printDbg(IDalvikTyper.DEBUG, "set type ", elementType, " to local ", l);
                        leftLocal.setType(elementType);
                        setLocalTyped(leftLocal, elementType);
                    }
                    // Debug.printDbg(IDalvikTyper.DEBUG, "remove constraint: ", c);
                    constraints.remove(c);
                    update = true;
                    break;
                }
            } else {
                throw new RuntimeException("error: do not handling this kind of constraint: " + c);
            }
        }
        if (!update)
            break;
    }
    for (Unit u : b.getUnits()) {
        if (!(u instanceof AssignStmt))
            continue;
        AssignStmt ass = (AssignStmt) u;
        if (!(ass.getLeftOp() instanceof Local))
            continue;
        if (!(ass.getRightOp() instanceof UntypedConstant))
            continue;
        UntypedConstant uc = (UntypedConstant) ass.getRightOp();
        ass.setRightOp(uc.defineType(localTyped.get(ass.getLeftOp())));
    }
    // 
    for (Constraint c : constraints) {
        // Debug.printDbg(IDalvikTyper.DEBUG, "current constraint: ", c);
        Value l = c.l.getValue();
        Value r = c.r.getValue();
        if (l instanceof Local && r instanceof Constant) {
            if (r instanceof UntypedIntOrFloatConstant) {
                UntypedIntOrFloatConstant cst = (UntypedIntOrFloatConstant) r;
                Value newValue = null;
                if (cst.value != 0) {
                    // Debug.printDbg(IDalvikTyper.DEBUG, "[untyped constaints] set type int to non zero constant: ", c, " = ", cst.value);
                    newValue = cst.toIntConstant();
                } else {
                    // check if used in cast, just in case...
                    for (Unit u : b.getUnits()) {
                        for (ValueBox vb1 : u.getUseBoxes()) {
                            Value v1 = vb1.getValue();
                            if (v1 == l) {
                                // Debug.printDbg("local used in ", u);
                                if (u instanceof AssignStmt) {
                                    AssignStmt a = (AssignStmt) u;
                                    Value right = a.getRightOp();
                                    if (right instanceof CastExpr) {
                                        newValue = NullConstant.v();
                                    } else {
                                        newValue = cst.toIntConstant();
                                    }
                                } else if (u instanceof IfStmt) {
                                    // TODO check this better
                                    newValue = cst.toIntConstant();
                                }
                            }
                        }
                    }
                }
                if (newValue == null) {
                    throw new RuntimeException("error: no type found for local: " + l);
                }
                c.r.setValue(newValue);
            } else if (r instanceof UntypedLongOrDoubleConstant) {
                // Debug.printDbg(IDalvikTyper.DEBUG, "[untyped constaints] set type long to constant: ", c);
                Value newValue = ((UntypedLongOrDoubleConstant) r).toLongConstant();
                c.r.setValue(newValue);
            }
        }
    }
    // fix untypedconstants which have flown to an array index
    for (Unit u : b.getUnits()) {
        StmtSwitch sw = new StmtSwitch() {

            @Override
            public void caseBreakpointStmt(BreakpointStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseInvokeStmt(InvokeStmt stmt) {
                changeUntypedConstantsInInvoke(stmt.getInvokeExpr());
            }

            @Override
            public void caseAssignStmt(AssignStmt stmt) {
                if (stmt.getRightOp() instanceof NewArrayExpr) {
                    NewArrayExpr nae = (NewArrayExpr) stmt.getRightOp();
                    if (nae.getSize() instanceof UntypedConstant) {
                        UntypedIntOrFloatConstant uc = (UntypedIntOrFloatConstant) nae.getSize();
                        nae.setSize(uc.defineType(IntType.v()));
                    }
                } else if (stmt.getRightOp() instanceof UntypedConstant) {
                    UntypedConstant uc = (UntypedConstant) stmt.getRightOp();
                    Value l = stmt.getLeftOp();
                    Type lType = null;
                    if (l instanceof ArrayRef) {
                        ArrayRef ar = (ArrayRef) l;
                        Local baseLocal = (Local) ar.getBase();
                        ArrayType arrayType = (ArrayType) localTyped.get(baseLocal);
                        lType = arrayType.getElementType();
                    } else {
                        lType = l.getType();
                    }
                    stmt.setRightOp(uc.defineType(lType));
                } else if (stmt.getRightOp() instanceof InvokeExpr) {
                    changeUntypedConstantsInInvoke((InvokeExpr) stmt.getRightOp());
                }
                if (!stmt.containsArrayRef()) {
                    return;
                }
                ArrayRef ar = stmt.getArrayRef();
                if ((ar.getIndex() instanceof UntypedConstant)) {
                    UntypedIntOrFloatConstant uc = (UntypedIntOrFloatConstant) ar.getIndex();
                    ar.setIndex(uc.toIntConstant());
                }
                if (stmt.getLeftOp() instanceof ArrayRef && stmt.getRightOp() instanceof UntypedConstant) {
                    UntypedConstant uc = (UntypedConstant) stmt.getRightOp();
                    Local baseLocal = (Local) stmt.getArrayRef().getBase();
                    ArrayType lType = (ArrayType) localTyped.get(baseLocal);
                    Type elemType = lType.getElementType();
                    stmt.setRightOp(uc.defineType(elemType));
                }
            }

            @Override
            public void caseIdentityStmt(IdentityStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseGotoStmt(GotoStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseIfStmt(IfStmt stmt) {
                Value c = stmt.getCondition();
                if (c instanceof BinopExpr) {
                    BinopExpr be = (BinopExpr) c;
                    Value op1 = be.getOp1();
                    Value op2 = be.getOp2();
                    if (op1 instanceof UntypedConstant || op2 instanceof UntypedConstant) {
                        if (op1 instanceof Local) {
                            Type t = localTyped.get(op1);
                            // Debug.printDbg("if op1 type: ", t);
                            UntypedConstant uc = (UntypedConstant) op2;
                            be.setOp2(uc.defineType(t));
                        } else if (op2 instanceof Local) {
                            Type t = localTyped.get(op2);
                            // Debug.printDbg("if op2 type: ", t);
                            UntypedConstant uc = (UntypedConstant) op1;
                            be.setOp1(uc.defineType(t));
                        } else if (op1 instanceof UntypedConstant && op2 instanceof UntypedConstant) {
                            if (op1 instanceof UntypedIntOrFloatConstant && op2 instanceof UntypedIntOrFloatConstant) {
                                UntypedIntOrFloatConstant uc1 = (UntypedIntOrFloatConstant) op1;
                                UntypedIntOrFloatConstant uc2 = (UntypedIntOrFloatConstant) op2;
                                // to int or float, it does not matter
                                be.setOp1(uc1.toIntConstant());
                                be.setOp2(uc2.toIntConstant());
                            } else if (op1 instanceof UntypedLongOrDoubleConstant && op2 instanceof UntypedLongOrDoubleConstant) {
                                UntypedLongOrDoubleConstant uc1 = (UntypedLongOrDoubleConstant) op1;
                                UntypedLongOrDoubleConstant uc2 = (UntypedLongOrDoubleConstant) op2;
                                // to long or double, it does not matter
                                be.setOp1(uc1.toLongConstant());
                                be.setOp2(uc2.toLongConstant());
                            } else {
                                throw new RuntimeException("error: expected same type of untyped constants. Got " + stmt);
                            }
                        } else if (op1 instanceof UntypedConstant || op2 instanceof UntypedConstant) {
                            if (op1 instanceof UntypedConstant) {
                                UntypedConstant uc = (UntypedConstant) op1;
                                be.setOp1(uc.defineType(op2.getType()));
                            } else if (op2 instanceof UntypedConstant) {
                                UntypedConstant uc = (UntypedConstant) op2;
                                be.setOp2(uc.defineType(op1.getType()));
                            }
                        } else {
                            throw new RuntimeException("error: expected local/untyped untyped/local or untyped/untyped. Got " + stmt);
                        }
                    }
                } else if (c instanceof UnopExpr) {
                } else {
                    throw new RuntimeException("error: expected binop or unop. Got " + stmt);
                }
            }

            @Override
            public void caseLookupSwitchStmt(LookupSwitchStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseNopStmt(NopStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseRetStmt(RetStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseReturnStmt(ReturnStmt stmt) {
                if (stmt.getOp() instanceof UntypedConstant) {
                    UntypedConstant uc = (UntypedConstant) stmt.getOp();
                    Type type = b.getMethod().getReturnType();
                    stmt.setOp(uc.defineType(type));
                }
            }

            @Override
            public void caseReturnVoidStmt(ReturnVoidStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseTableSwitchStmt(TableSwitchStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void caseThrowStmt(ThrowStmt stmt) {
            // TODO Auto-generated method stub
            }

            @Override
            public void defaultCase(Object obj) {
            // TODO Auto-generated method stub
            }
        };
        u.apply(sw);
    }
// fix untyped constants remaining
// Debug.printDbg("assignTypes: after: \n", b);
}
Also used : AssignStmt(soot.jimple.AssignStmt) ArrayList(java.util.ArrayList) UnopExpr(soot.jimple.UnopExpr) SimpleLocalUses(soot.toolkits.scalar.SimpleLocalUses) ByteType(soot.ByteType) Unit(soot.Unit) LongOpTag(soot.dexpler.tags.LongOpTag) FloatType(soot.FloatType) ArrayType(soot.ArrayType) DoubleOpTag(soot.dexpler.tags.DoubleOpTag) TableSwitchStmt(soot.jimple.TableSwitchStmt) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) DynamicInvokeExpr(soot.jimple.DynamicInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) GotoStmt(soot.jimple.GotoStmt) CastExpr(soot.jimple.CastExpr) PrimType(soot.PrimType) List(java.util.List) ArrayList(java.util.ArrayList) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) HashSet(java.util.HashSet) ShortType(soot.ShortType) Local(soot.Local) NewArrayExpr(soot.jimple.NewArrayExpr) Value(soot.Value) CharType(soot.CharType) ReturnStmt(soot.jimple.ReturnStmt) ThrowStmt(soot.jimple.ThrowStmt) DefinitionStmt(soot.jimple.DefinitionStmt) BinopExpr(soot.jimple.BinopExpr) SimpleLocalDefs(soot.toolkits.scalar.SimpleLocalDefs) ExitMonitorStmt(soot.jimple.ExitMonitorStmt) LongType(soot.LongType) InvokeStmt(soot.jimple.InvokeStmt) NullConstant(soot.jimple.NullConstant) Constant(soot.jimple.Constant) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) IntOpTag(soot.dexpler.tags.IntOpTag) RetStmt(soot.jimple.RetStmt) BreakpointStmt(soot.jimple.BreakpointStmt) FloatOpTag(soot.dexpler.tags.FloatOpTag) IntType(soot.IntType) ArrayRef(soot.jimple.ArrayRef) ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) StmtSwitch(soot.jimple.StmtSwitch) UnitValueBoxPair(soot.toolkits.scalar.UnitValueBoxPair) IdentityStmt(soot.jimple.IdentityStmt) BooleanType(soot.BooleanType) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) UnknownType(soot.UnknownType) RefType(soot.RefType) ShortType(soot.ShortType) BooleanType(soot.BooleanType) ByteType(soot.ByteType) Type(soot.Type) UnknownType(soot.UnknownType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) IntType(soot.IntType) CharType(soot.CharType) LongType(soot.LongType) ArrayType(soot.ArrayType) PrimType(soot.PrimType) ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) UnitGraph(soot.toolkits.graph.UnitGraph) IfStmt(soot.jimple.IfStmt) ValueBox(soot.ValueBox) NopStmt(soot.jimple.NopStmt) DoubleType(soot.DoubleType) LongOpTag(soot.dexpler.tags.LongOpTag) Tag(soot.tagkit.Tag) DoubleOpTag(soot.dexpler.tags.DoubleOpTag) IntOpTag(soot.dexpler.tags.IntOpTag) FloatOpTag(soot.dexpler.tags.FloatOpTag)

Example 5 with ThrowStmt

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

the class DavaBody method copy_Body.

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

Aggregations

ThrowStmt (soot.jimple.ThrowStmt)14 Local (soot.Local)8 Unit (soot.Unit)8 InvokeExpr (soot.jimple.InvokeExpr)8 ReturnStmt (soot.jimple.ReturnStmt)8 Value (soot.Value)7 InvokeStmt (soot.jimple.InvokeStmt)7 Type (soot.Type)6 AssignStmt (soot.jimple.AssignStmt)6 IdentityStmt (soot.jimple.IdentityStmt)6 IfStmt (soot.jimple.IfStmt)6 RefType (soot.RefType)5 DefinitionStmt (soot.jimple.DefinitionStmt)5 EnterMonitorStmt (soot.jimple.EnterMonitorStmt)5 ExitMonitorStmt (soot.jimple.ExitMonitorStmt)5 ArrayList (java.util.ArrayList)4 ArrayType (soot.ArrayType)4 UnknownType (soot.UnknownType)4 ValueBox (soot.ValueBox)4 ArrayRef (soot.jimple.ArrayRef)4