Search in sources :

Example 11 with Value

use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.

the class SSATransformer method prepare.

private boolean prepare(final IrMethod method) {
    int index = Cfg.reIndexLocal(method);
    final int[] readCounts = new int[index];
    final int[] writeCounts = new int[index];
    Cfg.travel(method.stmts, new TravelCallBack() {

        @Override
        public Value onAssign(Local v, AssignStmt as) {
            writeCounts[v._ls_index]++;
            return v;
        }

        @Override
        public Value onUse(Local v) {
            readCounts[v._ls_index]++;
            return v;
        }
    }, true);
    boolean needTravel = false;
    boolean needSSAAnalyze = false;
    index = 0;
    List<Local> oldLocals = method.locals;
    List<Local> locals = new ArrayList<>(oldLocals);
    oldLocals.clear();
    for (Local local : locals) {
        int idx = local._ls_index;
        int read = readCounts[idx];
        int write = writeCounts[idx];
        if (read > 0 && write == 0) {
        // TODO if we need throw exception ?
        // or the code is dead?
        }
        if (read == 0 && write == 0) {
        // ignore the local
        } else {
            if (write <= 1) {
                // no phi require
                local._ls_index = -1;
                oldLocals.add(local);
            } else if (read == 0) {
                local._ls_index = -2;
                needTravel = true;
            // we are going to duplicate each usage of the local and add to method.locals,
            // so not add the original local to method.locals
            } else {
                needSSAAnalyze = true;
                local._ls_index = index++;
                oldLocals.add(local);
            }
        }
    }
    if (needSSAAnalyze || needTravel) {
        Cfg.travelMod(method.stmts, new TravelCallBack() {

            @Override
            public Value onAssign(Local v, AssignStmt as) {
                if (v._ls_index == -1) {
                    return v;
                } else if (v._ls_index == -2) {
                    Local n = (Local) v.clone();
                    method.locals.add(n);
                    return n;
                }
                // others
                return v.clone();
            }

            @Override
            public Value onUse(Local v) {
                if (v._ls_index == -1) {
                    return v;
                }
                return v.clone();
            }
        }, true);
    }
    return needSSAAnalyze;
}
Also used : TravelCallBack(com.googlecode.dex2jar.ir.ts.Cfg.TravelCallBack) Value(com.googlecode.dex2jar.ir.expr.Value) AnalyzeValue(com.googlecode.dex2jar.ir.ts.an.AnalyzeValue) Local(com.googlecode.dex2jar.ir.expr.Local)

Example 12 with Value

use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.

the class TypeTransformer method transform.

@Override
public void transform(IrMethod irMethod) {
    TypeAnalyze ta = new TypeAnalyze(irMethod);
    List<TypeRef> refs = ta.analyze();
    for (TypeRef ref : refs) {
        String type = ref.getType();
        if (type == null) {
            System.err.println(ref);
            continue;
        }
        if (ref.value.vt == VT.CONSTANT) {
            Constant cst = (Constant) ref.value;
            switch(type.charAt(0)) {
                case '[':
                case 'L':
                    if (Integer.valueOf(0).equals(cst.value)) {
                        cst.value = Constant.Null;
                    }
                    if (type.equals("[F") && cst.value instanceof int[]) {
                        int[] x = (int[]) cst.value;
                        float[] f = new float[x.length];
                        for (int i = 0; i < x.length; i++) {
                            f[i] = Float.intBitsToFloat(x[i]);
                        }
                        cst.value = f;
                    }
                    if (type.equals("[D") && cst.value instanceof long[]) {
                        long[] x = (long[]) cst.value;
                        double[] f = new double[x.length];
                        for (int i = 0; i < x.length; i++) {
                            f[i] = Double.longBitsToDouble(x[i]);
                        }
                        cst.value = f;
                    }
                    break;
                case 'F':
                    if (!(cst.value instanceof Float)) {
                        cst.value = Float.intBitsToFloat(((Number) cst.value).intValue());
                    }
                    break;
                case 'D':
                    if (!(cst.value instanceof Double)) {
                        cst.value = Double.longBitsToDouble(((Number) cst.value).longValue());
                    }
                    break;
                default:
            }
        }
        Value value = ref.value;
        value.valueType = type;
        value.tag = null;
        ref.clear();
    }
}
Also used : Value(com.googlecode.dex2jar.ir.expr.Value)

Example 13 with Value

use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.

the class ZeroTransformer method transformReportChanged.

@Override
public boolean transformReportChanged(IrMethod method) {
    boolean changed = false;
    List<AssignStmt> assignStmtList = new ArrayList<>();
    for (Stmt p = method.stmts.getFirst(); p != null; p = p.getNext()) {
        if (p.st == Stmt.ST.ASSIGN) {
            AssignStmt as = (AssignStmt) p;
            if (as.getOp1().vt == Value.VT.LOCAL && as.getOp2().vt == Value.VT.CONSTANT) {
                Constant cst = (Constant) as.getOp2();
                Object value = cst.value;
                if (value instanceof Number && !((value instanceof Long) || (value instanceof Double))) {
                    int v = ((Number) value).intValue();
                    if (v == 0 || v == 1) {
                        assignStmtList.add(as);
                    }
                }
            }
        }
    }
    if (assignStmtList.size() == 0) {
        return false;
    }
    List<LabelStmt> phiLabels = method.phiLabels;
    if (phiLabels != null) {
        for (AssignStmt as : assignStmtList) {
            Local local = (Local) as.getOp1();
            boolean first = true;
            for (LabelStmt labelStmt : phiLabels) {
                for (AssignStmt phi : labelStmt.phis) {
                    Value[] vs = phi.getOp2().getOps();
                    for (int i = 0; i < vs.length; i++) {
                        Value v = vs[i];
                        if (v == local) {
                            if (first) {
                                first = false;
                            } else {
                                Local nLocal = Exprs.nLocal(-1);
                                method.locals.add(nLocal);
                                changed = true;
                                method.stmts.insertBefore(as, Stmts.nAssign(nLocal, as.getOp2().clone()));
                                vs[i] = nLocal;
                            }
                        }
                    }
                }
            }
        }
    }
    return changed;
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Constant(com.googlecode.dex2jar.ir.expr.Constant) ArrayList(java.util.ArrayList) Local(com.googlecode.dex2jar.ir.expr.Local) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt) Value(com.googlecode.dex2jar.ir.expr.Value)

Example 14 with Value

use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.

the class ArrayNullPointerTransformer method tryAdd.

private boolean tryAdd(Value value, List<Value> values) {
    if (!arrayNPE(value)) {
        values.add(value);
        return true;
    } else {
        switch(value.et) {
            case E0:
                values.add(value);
                break;
            case E1:
                E1Expr e1 = (E1Expr) value;
                if (e1.op == null || e1.op.trim() == null) {
                    return false;
                }
                tryAdd(e1.op.trim(), values);
                break;
            case E2:
                E2Expr e2 = (E2Expr) value;
                if (e2.vt == VT.ARRAY && e2.op1.trim().vt == VT.CONSTANT) {
                    Constant cst = (Constant) e2.op1.trim();
                    if (cst.value.equals(Integer.valueOf(0))) {
                        tryAdd(e2.op2.trim(), values);
                        return false;
                    }
                }
                if (tryAdd(e2.op1.trim(), values)) {
                    tryAdd(e2.op2.trim(), values);
                }
            case En:
                for (Value vb : ((EnExpr) value).ops) {
                    if (!tryAdd(vb.trim(), values)) {
                        break;
                    }
                }
        }
    }
    return false;
}
Also used : E2Expr(com.googlecode.dex2jar.ir.expr.Value.E2Expr) E1Expr(com.googlecode.dex2jar.ir.expr.Value.E1Expr) EnExpr(com.googlecode.dex2jar.ir.expr.Value.EnExpr) Constant(com.googlecode.dex2jar.ir.expr.Constant) Value(com.googlecode.dex2jar.ir.expr.Value)

Example 15 with Value

use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.

the class Dex2IRConverter method buildInterpreter.

private DvmInterpreter<DvmValue> buildInterpreter() {
    return new DvmInterpreter<DvmValue>() {

        DvmValue b(com.googlecode.dex2jar.ir.expr.Value value) {
            Local local = newLocal();
            emit(Stmts.nAssign(local, value));
            return new DvmValue(local);
        }

        @Override
        public DvmValue newOperation(DexStmtNode insn) {
            switch(insn.op) {
                case CONST:
                case CONST_16:
                case CONST_4:
                case CONST_HIGH16:
                    return b(nInt((Integer) ((ConstStmtNode) insn).value));
                case CONST_WIDE:
                case CONST_WIDE_16:
                case CONST_WIDE_32:
                case CONST_WIDE_HIGH16:
                    return b(nLong((Long) ((ConstStmtNode) insn).value));
                case CONST_CLASS:
                    return b(nType(((DexType) ((ConstStmtNode) insn).value).desc));
                case CONST_STRING:
                case CONST_STRING_JUMBO:
                    return b(nString((String) ((ConstStmtNode) insn).value));
                case SGET:
                case SGET_BOOLEAN:
                case SGET_BYTE:
                case SGET_CHAR:
                case SGET_OBJECT:
                case SGET_SHORT:
                case SGET_WIDE:
                    Field field = ((FieldStmtNode) insn).field;
                    return b(nStaticField(field.getOwner(), field.getName(), field.getType()));
                case NEW_INSTANCE:
                    return b(nNew(((TypeStmtNode) insn).type));
                default:
            }
            return null;
        }

        @Override
        public DvmValue copyOperation(DexStmtNode insn, DvmValue value) {
            if (value == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            return b(getLocal(value));
        }

        @Override
        public DvmValue unaryOperation(DexStmtNode insn, DvmValue value) {
            if (value == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            Local local = getLocal(value);
            switch(insn.op) {
                case NOT_INT:
                    return b(nNot(local, "I"));
                case NOT_LONG:
                    return b(nNot(local, "J"));
                case NEG_DOUBLE:
                    return b(nNeg(local, "D"));
                case NEG_FLOAT:
                    return b(nNeg(local, "F"));
                case NEG_INT:
                    return b(nNeg(local, "I"));
                case NEG_LONG:
                    return b(nNeg(local, "J"));
                case INT_TO_BYTE:
                    return b(nCast(local, "I", "B"));
                case INT_TO_CHAR:
                    return b(nCast(local, "I", "C"));
                case INT_TO_DOUBLE:
                    return b(nCast(local, "I", "D"));
                case INT_TO_FLOAT:
                    return b(nCast(local, "I", "F"));
                case INT_TO_LONG:
                    return b(nCast(local, "I", "J"));
                case INT_TO_SHORT:
                    return b(nCast(local, "I", "S"));
                case FLOAT_TO_DOUBLE:
                    return b(nCast(local, "F", "D"));
                case FLOAT_TO_INT:
                    return b(nCast(local, "F", "I"));
                case FLOAT_TO_LONG:
                    return b(nCast(local, "F", "J"));
                case DOUBLE_TO_FLOAT:
                    return b(nCast(local, "D", "F"));
                case DOUBLE_TO_INT:
                    return b(nCast(local, "D", "I"));
                case DOUBLE_TO_LONG:
                    return b(nCast(local, "D", "J"));
                case LONG_TO_DOUBLE:
                    return b(nCast(local, "J", "D"));
                case LONG_TO_FLOAT:
                    return b(nCast(local, "J", "F"));
                case LONG_TO_INT:
                    return b(nCast(local, "J", "I"));
                case ARRAY_LENGTH:
                    return b(nLength(local));
                case IF_EQZ:
                    emit(nIf(Exprs.nEq(local, nInt(0), TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GEZ:
                    emit(nIf(Exprs.nGe(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GTZ:
                    emit(nIf(Exprs.nGt(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LEZ:
                    emit(nIf(Exprs.nLe(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LTZ:
                    emit(nIf(Exprs.nLt(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_NEZ:
                    emit(nIf(Exprs.nNe(local, nInt(0), TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case PACKED_SWITCH:
                case SPARSE_SWITCH:
                    DexLabel[] labels = ((BaseSwitchStmtNode) insn).labels;
                    LabelStmt[] lss = new LabelStmt[labels.length];
                    for (int i = 0; i < labels.length; i++) {
                        lss[i] = getLabel(labels[i]);
                    }
                    LabelStmt d = new LabelStmt();
                    if (insn.op == Op.PACKED_SWITCH) {
                        emit(nTableSwitch(local, ((PackedSwitchStmtNode) insn).first_case, lss, d));
                    } else {
                        emit(nLookupSwitch(local, ((SparseSwitchStmtNode) insn).cases, lss, d));
                    }
                    emit(d);
                    return null;
                case SPUT:
                case SPUT_BOOLEAN:
                case SPUT_BYTE:
                case SPUT_CHAR:
                case SPUT_OBJECT:
                case SPUT_SHORT:
                case SPUT_WIDE:
                    {
                        Field field = ((FieldStmtNode) insn).field;
                        emit(nAssign(nStaticField(field.getOwner(), field.getName(), field.getType()), local));
                        return null;
                    }
                case IGET:
                case IGET_BOOLEAN:
                case IGET_BYTE:
                case IGET_CHAR:
                case IGET_OBJECT:
                case IGET_SHORT:
                case IGET_WIDE:
                    {
                        Field field = ((FieldStmtNode) insn).field;
                        return b(nField(local, field.getOwner(), field.getName(), field.getType()));
                    }
                case INSTANCE_OF:
                    return b(nInstanceOf(local, ((TypeStmtNode) insn).type));
                case NEW_ARRAY:
                    return b(nNewArray(((TypeStmtNode) insn).type.substring(1), local));
                case CHECK_CAST:
                    return b(nCheckCast(local, ((TypeStmtNode) insn).type));
                case MONITOR_ENTER:
                    emit(nLock(local));
                    return null;
                case MONITOR_EXIT:
                    emit(nUnLock(local));
                    return null;
                case THROW:
                    emit(nThrow(local));
                    return null;
                case ADD_INT_LIT16:
                case ADD_INT_LIT8:
                    return b(nAdd(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case RSUB_INT_LIT8:
                case //
                RSUB_INT:
                    return b(nSub(nInt(((Stmt2R1NNode) insn).content), local, "I"));
                case MUL_INT_LIT8:
                case MUL_INT_LIT16:
                    return b(nMul(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case DIV_INT_LIT16:
                case DIV_INT_LIT8:
                    return b(nDiv(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case REM_INT_LIT16:
                case REM_INT_LIT8:
                    return b(nRem(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case AND_INT_LIT16:
                case AND_INT_LIT8:
                    return b(nAnd(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
                case OR_INT_LIT16:
                case OR_INT_LIT8:
                    return b(nOr(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
                case XOR_INT_LIT16:
                case XOR_INT_LIT8:
                    return b(nXor(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
                case SHL_INT_LIT8:
                    return b(nShl(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case SHR_INT_LIT8:
                    return b(nShr(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case USHR_INT_LIT8:
                    return b(nUshr(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case FILL_ARRAY_DATA:
                    emit(nFillArrayData(local, nArrayValue(((FillArrayDataStmtNode) insn).array)));
                    return null;
            }
            throw new RuntimeException();
        }

        @Override
        public DvmValue binaryOperation(DexStmtNode insn, DvmValue value1, DvmValue value2) {
            if (value1 == null || value2 == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            Local local1 = getLocal(value1);
            Local local2 = getLocal(value2);
            switch(insn.op) {
                case AGET:
                    return b(nArray(local1, local2, TypeClass.IF.name));
                case AGET_BOOLEAN:
                    return b(nArray(local1, local2, "Z"));
                case AGET_BYTE:
                    return b(nArray(local1, local2, "B"));
                case AGET_CHAR:
                    return b(nArray(local1, local2, "C"));
                case AGET_OBJECT:
                    return b(nArray(local1, local2, "L"));
                case AGET_SHORT:
                    return b(nArray(local1, local2, "S"));
                case AGET_WIDE:
                    return b(nArray(local1, local2, TypeClass.JD.name));
                case CMP_LONG:
                    return b(nLCmp(local1, local2));
                case CMPG_DOUBLE:
                    return b(nDCmpg(local1, local2));
                case CMPG_FLOAT:
                    return b(nFCmpg(local1, local2));
                case CMPL_DOUBLE:
                    return b(nDCmpl(local1, local2));
                case CMPL_FLOAT:
                    return b(nFCmpl(local1, local2));
                case ADD_DOUBLE:
                    return b(nAdd(local1, local2, "D"));
                case ADD_FLOAT:
                    return b(nAdd(local1, local2, "F"));
                case ADD_INT:
                    return b(nAdd(local1, local2, "I"));
                case ADD_LONG:
                    return b(nAdd(local1, local2, "J"));
                case SUB_DOUBLE:
                    return b(nSub(local1, local2, "D"));
                case SUB_FLOAT:
                    return b(nSub(local1, local2, "F"));
                case SUB_INT:
                    return b(nSub(local1, local2, "I"));
                case SUB_LONG:
                    return b(nSub(local1, local2, "J"));
                case MUL_DOUBLE:
                    return b(nMul(local1, local2, "D"));
                case MUL_FLOAT:
                    return b(nMul(local1, local2, "F"));
                case MUL_INT:
                    return b(nMul(local1, local2, "I"));
                case MUL_LONG:
                    return b(nMul(local1, local2, "J"));
                case DIV_DOUBLE:
                    return b(nDiv(local1, local2, "D"));
                case DIV_FLOAT:
                    return b(nDiv(local1, local2, "F"));
                case DIV_INT:
                    return b(nDiv(local1, local2, "I"));
                case DIV_LONG:
                    return b(nDiv(local1, local2, "J"));
                case REM_DOUBLE:
                    return b(nRem(local1, local2, "D"));
                case REM_FLOAT:
                    return b(nRem(local1, local2, "F"));
                case REM_INT:
                    return b(nRem(local1, local2, "I"));
                case REM_LONG:
                    return b(nRem(local1, local2, "J"));
                case AND_INT:
                    return b(nAnd(local1, local2, TypeClass.ZI.name));
                case AND_LONG:
                    return b(nAnd(local1, local2, "J"));
                case OR_INT:
                    return b(nOr(local1, local2, TypeClass.ZI.name));
                case OR_LONG:
                    return b(nOr(local1, local2, "J"));
                case XOR_INT:
                    return b(nXor(local1, local2, TypeClass.ZI.name));
                case XOR_LONG:
                    return b(nXor(local1, local2, "J"));
                case SHL_INT:
                    return b(nShl(local1, local2, "I"));
                case SHL_LONG:
                    return b(nShl(local1, local2, "J"));
                case SHR_INT:
                    return b(nShr(local1, local2, "I"));
                case SHR_LONG:
                    return b(nShr(local1, local2, "J"));
                case USHR_INT:
                    return b(nUshr(local1, local2, "I"));
                case USHR_LONG:
                    return b(nUshr(local1, local2, "J"));
                case IF_EQ:
                    emit(nIf(Exprs.nEq(local1, local2, TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GE:
                    emit(nIf(Exprs.nGe(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GT:
                    emit(nIf(Exprs.nGt(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LE:
                    emit(nIf(Exprs.nLe(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LT:
                    emit(nIf(Exprs.nLt(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_NE:
                    emit(nIf(Exprs.nNe(local1, local2, TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IPUT:
                case IPUT_BOOLEAN:
                case IPUT_BYTE:
                case IPUT_CHAR:
                case IPUT_OBJECT:
                case IPUT_SHORT:
                case IPUT_WIDE:
                    Field field = ((FieldStmtNode) insn).field;
                    emit(nAssign(nField(local1, field.getOwner(), field.getName(), field.getType()), local2));
                    return null;
                case ADD_DOUBLE_2ADDR:
                    return b(nAdd(local1, local2, "D"));
                case ADD_FLOAT_2ADDR:
                    return b(nAdd(local1, local2, "F"));
                case ADD_INT_2ADDR:
                    return b(nAdd(local1, local2, "I"));
                case ADD_LONG_2ADDR:
                    return b(nAdd(local1, local2, "J"));
                case SUB_DOUBLE_2ADDR:
                    return b(nSub(local1, local2, "D"));
                case SUB_FLOAT_2ADDR:
                    return b(nSub(local1, local2, "F"));
                case SUB_INT_2ADDR:
                    return b(nSub(local1, local2, "I"));
                case SUB_LONG_2ADDR:
                    return b(nSub(local1, local2, "J"));
                case MUL_DOUBLE_2ADDR:
                    return b(nMul(local1, local2, "D"));
                case MUL_FLOAT_2ADDR:
                    return b(nMul(local1, local2, "F"));
                case MUL_INT_2ADDR:
                    return b(nMul(local1, local2, "I"));
                case MUL_LONG_2ADDR:
                    return b(nMul(local1, local2, "J"));
                case DIV_DOUBLE_2ADDR:
                    return b(nDiv(local1, local2, "D"));
                case DIV_FLOAT_2ADDR:
                    return b(nDiv(local1, local2, "F"));
                case DIV_INT_2ADDR:
                    return b(nDiv(local1, local2, "I"));
                case DIV_LONG_2ADDR:
                    return b(nDiv(local1, local2, "J"));
                case REM_DOUBLE_2ADDR:
                    return b(nRem(local1, local2, "D"));
                case REM_FLOAT_2ADDR:
                    return b(nRem(local1, local2, "F"));
                case REM_INT_2ADDR:
                    return b(nRem(local1, local2, "I"));
                case REM_LONG_2ADDR:
                    return b(nRem(local1, local2, "J"));
                case AND_INT_2ADDR:
                    return b(nAnd(local1, local2, TypeClass.ZI.name));
                case AND_LONG_2ADDR:
                    return b(nAnd(local1, local2, "J"));
                case OR_INT_2ADDR:
                    return b(nOr(local1, local2, TypeClass.ZI.name));
                case OR_LONG_2ADDR:
                    return b(nOr(local1, local2, "J"));
                case XOR_INT_2ADDR:
                    return b(nXor(local1, local2, TypeClass.ZI.name));
                case XOR_LONG_2ADDR:
                    return b(nXor(local1, local2, "J"));
                case SHL_INT_2ADDR:
                    return b(nShl(local1, local2, "I"));
                case SHL_LONG_2ADDR:
                    return b(nShl(local1, local2, "J"));
                case SHR_INT_2ADDR:
                    return b(nShr(local1, local2, "I"));
                case SHR_LONG_2ADDR:
                    return b(nShr(local1, local2, "J"));
                case USHR_INT_2ADDR:
                    return b(nUshr(local1, local2, "I"));
                case USHR_LONG_2ADDR:
                    return b(nUshr(local1, local2, "J"));
            }
            throw new RuntimeException();
        }

        @Override
        public DvmValue ternaryOperation(DexStmtNode insn, DvmValue value1, DvmValue value2, DvmValue value3) {
            if (value1 == null || value2 == null || value3 == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            Local localArray = getLocal(value1);
            Local localIndex = getLocal(value2);
            Local localValue = getLocal(value3);
            switch(insn.op) {
                case APUT:
                    emit(nAssign(nArray(localArray, localIndex, TypeClass.IF.name), localValue));
                    break;
                case APUT_BOOLEAN:
                    emit(nAssign(nArray(localArray, localIndex, "Z"), localValue));
                    break;
                case APUT_BYTE:
                    emit(nAssign(nArray(localArray, localIndex, "B"), localValue));
                    break;
                case APUT_CHAR:
                    emit(nAssign(nArray(localArray, localIndex, "C"), localValue));
                    break;
                case APUT_OBJECT:
                    emit(nAssign(nArray(localArray, localIndex, "L"), localValue));
                    break;
                case APUT_SHORT:
                    emit(nAssign(nArray(localArray, localIndex, "S"), localValue));
                    break;
                case APUT_WIDE:
                    emit(nAssign(nArray(localArray, localIndex, TypeClass.JD.name), localValue));
                    break;
            }
            return null;
        }

        @Override
        public DvmValue naryOperation(DexStmtNode insn, List<? extends DvmValue> values) {
            for (DvmValue v : values) {
                if (v == null) {
                    emitNotFindOperand(insn);
                    return b(nInt(0));
                }
            }
            switch(insn.op) {
                case FILLED_NEW_ARRAY:
                case FILLED_NEW_ARRAY_RANGE:
                    DvmValue value = new DvmValue();
                    FilledNewArrayStmtNode filledNewArrayStmtNode = (FilledNewArrayStmtNode) insn;
                    String type = filledNewArrayStmtNode.type;
                    String elem = type.substring(1);
                    emit(nAssign(getLocal(value), nNewArray(elem, nInt(values.size()))));
                    for (int i = 0; i < values.size(); i++) {
                        emit(nAssign(nArray(getLocal(value), nInt(i), elem), getLocal(values.get(i))));
                    }
                    return value;
                default:
                    Op op = insn.op;
                    Method method = ((MethodStmtNode) insn).method;
                    Value[] vs = new Value[values.size()];
                    for (int i = 0; i < vs.length; i++) {
                        vs[i] = getLocal(values.get(i));
                    }
                    Value invoke = null;
                    switch(op) {
                        case INVOKE_VIRTUAL_RANGE:
                        case INVOKE_VIRTUAL:
                            invoke = nInvokeVirtual(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        case INVOKE_SUPER_RANGE:
                        case INVOKE_DIRECT_RANGE:
                        case INVOKE_SUPER:
                        case INVOKE_DIRECT:
                            invoke = nInvokeSpecial(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        case INVOKE_STATIC_RANGE:
                        case INVOKE_STATIC:
                            invoke = nInvokeStatic(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        case INVOKE_INTERFACE_RANGE:
                        case INVOKE_INTERFACE:
                            invoke = nInvokeInterface(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        default:
                            throw new RuntimeException();
                    }
                    if ("V".equals(method.getReturnType())) {
                        emit(nVoidInvoke(invoke));
                        return null;
                    } else {
                        return b(invoke);
                    }
            }
        }

        void emitNotFindOperand(DexStmtNode insn) {
            String msg;
            switch(insn.op) {
                case MOVE_RESULT:
                case MOVE_RESULT_OBJECT:
                case MOVE_RESULT_WIDE:
                    msg = "can't get operand(s) for " + insn.op + ", wrong position ?";
                    break;
                default:
                    msg = "can't get operand(s) for " + insn.op + ", out-of-range or not initialized ?";
                    break;
            }
            System.err.println("WARN: " + msg);
            emit(nThrow(nInvokeNew(new Value[] { nString("d2j: " + msg) }, new String[] { "Ljava/lang/String;" }, "Ljava/lang/VerifyError;")));
        }

        @Override
        public void returnOperation(DexStmtNode insn, DvmValue value) {
            if (value == null) {
                emitNotFindOperand(insn);
                return;
            }
            emit(nReturn(getLocal(value)));
        }
    };
}
Also used : Op(com.googlecode.d2j.reader.Op) Field(com.googlecode.d2j.Field) DvmInterpreter(com.googlecode.d2j.node.analysis.DvmInterpreter) DexType(com.googlecode.d2j.DexType) Local(com.googlecode.dex2jar.ir.expr.Local) IrMethod(com.googlecode.dex2jar.ir.IrMethod) Method(com.googlecode.d2j.Method) Value(com.googlecode.dex2jar.ir.expr.Value) DexLabel(com.googlecode.d2j.DexLabel)

Aggregations

Value (com.googlecode.dex2jar.ir.expr.Value)32 Local (com.googlecode.dex2jar.ir.expr.Local)19 AssignStmt (com.googlecode.dex2jar.ir.stmt.AssignStmt)11 LabelStmt (com.googlecode.dex2jar.ir.stmt.LabelStmt)9 Stmt (com.googlecode.dex2jar.ir.stmt.Stmt)8 Constant (com.googlecode.dex2jar.ir.expr.Constant)5 Exprs.nArrayValue (com.googlecode.dex2jar.ir.expr.Exprs.nArrayValue)4 ArrayList (java.util.ArrayList)4 AnalyzeValue (com.googlecode.dex2jar.ir.ts.an.AnalyzeValue)3 PhiExpr (com.googlecode.dex2jar.ir.expr.PhiExpr)2 TravelCallBack (com.googlecode.dex2jar.ir.ts.Cfg.TravelCallBack)2 DexLabel (com.googlecode.d2j.DexLabel)1 DexType (com.googlecode.d2j.DexType)1 Field (com.googlecode.d2j.Field)1 Method (com.googlecode.d2j.Method)1 DvmInterpreter (com.googlecode.d2j.node.analysis.DvmInterpreter)1 Op (com.googlecode.d2j.reader.Op)1 IrMethod (com.googlecode.dex2jar.ir.IrMethod)1 LocalVar (com.googlecode.dex2jar.ir.LocalVar)1 StmtSearcher (com.googlecode.dex2jar.ir.StmtSearcher)1