Search in sources :

Example 1 with ISwitchPayload

use of jadx.api.plugins.input.insns.custom.ISwitchPayload in project jadx by skylot.

the class Smali method fmtPayloadInsn.

private boolean fmtPayloadInsn(InsnData insn, LineInfo line) {
    Opcode opcode = insn.getOpcode();
    if (opcode == PACKED_SWITCH_PAYLOAD) {
        line.getLineWriter().append("packed-switch-payload");
        line.addInsnLine(insn.getOffset(), line.getLineWriter().toString());
        ISwitchPayload payload = (ISwitchPayload) insn.getPayload();
        if (payload != null) {
            fmtSwitchPayload(insn, FMT_P_SWITCH_CASE, FMT_P_SWITCH_CASE_TAG, line, payload, insn.getOffset());
        }
        return true;
    }
    if (opcode == SPARSE_SWITCH_PAYLOAD) {
        line.getLineWriter().append("sparse-switch-payload");
        line.addInsnLine(insn.getOffset(), line.getLineWriter().toString());
        ISwitchPayload payload = (ISwitchPayload) insn.getPayload();
        if (payload != null) {
            fmtSwitchPayload(insn, FMT_S_SWITCH_CASE, FMT_S_SWITCH_CASE_TAG, line, payload, insn.getOffset());
        }
        return true;
    }
    if (opcode == FILL_ARRAY_DATA_PAYLOAD) {
        line.getLineWriter().append("fill-array-data-payload");
        line.addInsnLine(insn.getOffset(), line.getLineWriter().toString());
        return true;
    }
    return false;
}
Also used : ISwitchPayload(jadx.api.plugins.input.insns.custom.ISwitchPayload) Opcode(jadx.api.plugins.input.insns.Opcode)

Example 2 with ISwitchPayload

use of jadx.api.plugins.input.insns.custom.ISwitchPayload in project jadx by skylot.

the class InsnDecoder method decode.

@NotNull
protected InsnNode decode(InsnData insn) throws DecodeException {
    switch(insn.getOpcode()) {
        case NOP:
            return new InsnNode(InsnType.NOP, 0);
        // move-result will be process in invoke and filled-new-array instructions
        case MOVE_RESULT:
            return insn(InsnType.MOVE_RESULT, InsnArg.reg(insn, 0, ArgType.UNKNOWN));
        case CONST:
            LiteralArg narrowLitArg = InsnArg.lit(insn, ArgType.NARROW);
            return insn(InsnType.CONST, InsnArg.reg(insn, 0, narrowLitArg.getType()), narrowLitArg);
        case CONST_WIDE:
            LiteralArg wideLitArg = InsnArg.lit(insn, ArgType.WIDE);
            return insn(InsnType.CONST, InsnArg.reg(insn, 0, wideLitArg.getType()), wideLitArg);
        case CONST_STRING:
            InsnNode constStrInsn = new ConstStringNode(insn.getIndexAsString());
            constStrInsn.setResult(InsnArg.reg(insn, 0, ArgType.STRING));
            return constStrInsn;
        case CONST_CLASS:
            {
                ArgType clsType = ArgType.parse(insn.getIndexAsType());
                InsnNode constClsInsn = new ConstClassNode(clsType);
                constClsInsn.setResult(InsnArg.reg(insn, 0, ArgType.generic(Consts.CLASS_CLASS, clsType)));
                return constClsInsn;
            }
        case MOVE:
            return insn(InsnType.MOVE, InsnArg.reg(insn, 0, ArgType.NARROW), InsnArg.reg(insn, 1, ArgType.NARROW));
        case MOVE_MULTI:
            int len = insn.getRegsCount();
            InsnNode mmv = new InsnNode(InsnType.MOVE_MULTI, len);
            for (int i = 0; i < len; i++) {
                mmv.addArg(InsnArg.reg(insn, i, ArgType.UNKNOWN));
            }
            return mmv;
        case MOVE_WIDE:
            return insn(InsnType.MOVE, InsnArg.reg(insn, 0, ArgType.WIDE), InsnArg.reg(insn, 1, ArgType.WIDE));
        case MOVE_OBJECT:
            return insn(InsnType.MOVE, InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT), InsnArg.reg(insn, 1, ArgType.UNKNOWN_OBJECT));
        case ADD_INT:
            return arith(insn, ArithOp.ADD, ArgType.INT);
        case ADD_DOUBLE:
            return arith(insn, ArithOp.ADD, ArgType.DOUBLE);
        case ADD_FLOAT:
            return arith(insn, ArithOp.ADD, ArgType.FLOAT);
        case ADD_LONG:
            return arith(insn, ArithOp.ADD, ArgType.LONG);
        case ADD_INT_LIT:
            return arithLit(insn, ArithOp.ADD, ArgType.INT);
        case SUB_INT:
            return arith(insn, ArithOp.SUB, ArgType.INT);
        case RSUB_INT:
            return new ArithNode(ArithOp.SUB, InsnArg.reg(insn, 0, ArgType.INT), InsnArg.lit(insn, ArgType.INT), InsnArg.reg(insn, 1, ArgType.INT));
        case SUB_LONG:
            return arith(insn, ArithOp.SUB, ArgType.LONG);
        case SUB_FLOAT:
            return arith(insn, ArithOp.SUB, ArgType.FLOAT);
        case SUB_DOUBLE:
            return arith(insn, ArithOp.SUB, ArgType.DOUBLE);
        case MUL_INT:
            return arith(insn, ArithOp.MUL, ArgType.INT);
        case MUL_DOUBLE:
            return arith(insn, ArithOp.MUL, ArgType.DOUBLE);
        case MUL_FLOAT:
            return arith(insn, ArithOp.MUL, ArgType.FLOAT);
        case MUL_LONG:
            return arith(insn, ArithOp.MUL, ArgType.LONG);
        case MUL_INT_LIT:
            return arithLit(insn, ArithOp.MUL, ArgType.INT);
        case DIV_INT:
            return arith(insn, ArithOp.DIV, ArgType.INT);
        case REM_INT:
            return arith(insn, ArithOp.REM, ArgType.INT);
        case REM_LONG:
            return arith(insn, ArithOp.REM, ArgType.LONG);
        case REM_FLOAT:
            return arith(insn, ArithOp.REM, ArgType.FLOAT);
        case REM_DOUBLE:
            return arith(insn, ArithOp.REM, ArgType.DOUBLE);
        case DIV_DOUBLE:
            return arith(insn, ArithOp.DIV, ArgType.DOUBLE);
        case DIV_FLOAT:
            return arith(insn, ArithOp.DIV, ArgType.FLOAT);
        case DIV_LONG:
            return arith(insn, ArithOp.DIV, ArgType.LONG);
        case DIV_INT_LIT:
            return arithLit(insn, ArithOp.DIV, ArgType.INT);
        case REM_INT_LIT:
            return arithLit(insn, ArithOp.REM, ArgType.INT);
        case AND_INT:
            return arith(insn, ArithOp.AND, ArgType.INT);
        case AND_INT_LIT:
            return arithLit(insn, ArithOp.AND, ArgType.INT);
        case XOR_INT_LIT:
            return arithLit(insn, ArithOp.XOR, ArgType.INT);
        case AND_LONG:
            return arith(insn, ArithOp.AND, ArgType.LONG);
        case OR_INT:
            return arith(insn, ArithOp.OR, ArgType.INT);
        case OR_INT_LIT:
            return arithLit(insn, ArithOp.OR, ArgType.INT);
        case XOR_INT:
            return arith(insn, ArithOp.XOR, ArgType.INT);
        case OR_LONG:
            return arith(insn, ArithOp.OR, ArgType.LONG);
        case XOR_LONG:
            return arith(insn, ArithOp.XOR, ArgType.LONG);
        case USHR_INT:
            return arith(insn, ArithOp.USHR, ArgType.INT);
        case USHR_LONG:
            return arith(insn, ArithOp.USHR, ArgType.LONG);
        case SHL_INT:
            return arith(insn, ArithOp.SHL, ArgType.INT);
        case SHL_LONG:
            return arith(insn, ArithOp.SHL, ArgType.LONG);
        case SHR_INT:
            return arith(insn, ArithOp.SHR, ArgType.INT);
        case SHR_LONG:
            return arith(insn, ArithOp.SHR, ArgType.LONG);
        case SHL_INT_LIT:
            return arithLit(insn, ArithOp.SHL, ArgType.INT);
        case SHR_INT_LIT:
            return arithLit(insn, ArithOp.SHR, ArgType.INT);
        case USHR_INT_LIT:
            return arithLit(insn, ArithOp.USHR, ArgType.INT);
        case NEG_INT:
            return neg(insn, ArgType.INT);
        case NEG_LONG:
            return neg(insn, ArgType.LONG);
        case NEG_FLOAT:
            return neg(insn, ArgType.FLOAT);
        case NEG_DOUBLE:
            return neg(insn, ArgType.DOUBLE);
        case NOT_INT:
            return not(insn, ArgType.INT);
        case NOT_LONG:
            return not(insn, ArgType.LONG);
        case INT_TO_BYTE:
            return cast(insn, ArgType.INT, ArgType.BYTE);
        case INT_TO_CHAR:
            return cast(insn, ArgType.INT, ArgType.CHAR);
        case INT_TO_SHORT:
            return cast(insn, ArgType.INT, ArgType.SHORT);
        case INT_TO_FLOAT:
            return cast(insn, ArgType.INT, ArgType.FLOAT);
        case INT_TO_DOUBLE:
            return cast(insn, ArgType.INT, ArgType.DOUBLE);
        case INT_TO_LONG:
            return cast(insn, ArgType.INT, ArgType.LONG);
        case FLOAT_TO_INT:
            return cast(insn, ArgType.FLOAT, ArgType.INT);
        case FLOAT_TO_DOUBLE:
            return cast(insn, ArgType.FLOAT, ArgType.DOUBLE);
        case FLOAT_TO_LONG:
            return cast(insn, ArgType.FLOAT, ArgType.LONG);
        case DOUBLE_TO_INT:
            return cast(insn, ArgType.DOUBLE, ArgType.INT);
        case DOUBLE_TO_FLOAT:
            return cast(insn, ArgType.DOUBLE, ArgType.FLOAT);
        case DOUBLE_TO_LONG:
            return cast(insn, ArgType.DOUBLE, ArgType.LONG);
        case LONG_TO_INT:
            return cast(insn, ArgType.LONG, ArgType.INT);
        case LONG_TO_FLOAT:
            return cast(insn, ArgType.LONG, ArgType.FLOAT);
        case LONG_TO_DOUBLE:
            return cast(insn, ArgType.LONG, ArgType.DOUBLE);
        case IF_EQ:
        case IF_EQZ:
            return new IfNode(insn, IfOp.EQ);
        case IF_NE:
        case IF_NEZ:
            return new IfNode(insn, IfOp.NE);
        case IF_GT:
        case IF_GTZ:
            return new IfNode(insn, IfOp.GT);
        case IF_GE:
        case IF_GEZ:
            return new IfNode(insn, IfOp.GE);
        case IF_LT:
        case IF_LTZ:
            return new IfNode(insn, IfOp.LT);
        case IF_LE:
        case IF_LEZ:
            return new IfNode(insn, IfOp.LE);
        case CMP_LONG:
            return cmp(insn, InsnType.CMP_L, ArgType.LONG);
        case CMPL_FLOAT:
            return cmp(insn, InsnType.CMP_L, ArgType.FLOAT);
        case CMPL_DOUBLE:
            return cmp(insn, InsnType.CMP_L, ArgType.DOUBLE);
        case CMPG_FLOAT:
            return cmp(insn, InsnType.CMP_G, ArgType.FLOAT);
        case CMPG_DOUBLE:
            return cmp(insn, InsnType.CMP_G, ArgType.DOUBLE);
        case GOTO:
            return new GotoNode(insn.getTarget());
        case THROW:
            return insn(InsnType.THROW, null, InsnArg.reg(insn, 0, ArgType.THROWABLE));
        case MOVE_EXCEPTION:
            return insn(InsnType.MOVE_EXCEPTION, InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT_NO_ARRAY));
        case RETURN_VOID:
            return new InsnNode(InsnType.RETURN, 0);
        case RETURN:
            return insn(InsnType.RETURN, null, InsnArg.reg(insn, 0, method.getReturnType()));
        case INSTANCE_OF:
            InsnNode instInsn = new IndexInsnNode(InsnType.INSTANCE_OF, ArgType.parse(insn.getIndexAsType()), 1);
            instInsn.setResult(InsnArg.reg(insn, 0, ArgType.BOOLEAN));
            instInsn.addArg(InsnArg.reg(insn, 1, ArgType.UNKNOWN_OBJECT));
            return instInsn;
        case CHECK_CAST:
            ArgType castType = ArgType.parse(insn.getIndexAsType());
            InsnNode checkCastInsn = new IndexInsnNode(InsnType.CHECK_CAST, castType, 1);
            checkCastInsn.setResult(InsnArg.reg(insn, 0, castType));
            checkCastInsn.addArg(InsnArg.reg(insn, insn.getRegsCount() == 2 ? 1 : 0, ArgType.UNKNOWN_OBJECT));
            return checkCastInsn;
        case IGET:
            FieldInfo igetFld = FieldInfo.fromRef(root, insn.getIndexAsField());
            InsnNode igetInsn = new IndexInsnNode(InsnType.IGET, igetFld, 1);
            igetInsn.setResult(InsnArg.reg(insn, 0, tryResolveFieldType(igetFld)));
            igetInsn.addArg(InsnArg.reg(insn, 1, igetFld.getDeclClass().getType()));
            return igetInsn;
        case IPUT:
            FieldInfo iputFld = FieldInfo.fromRef(root, insn.getIndexAsField());
            InsnNode iputInsn = new IndexInsnNode(InsnType.IPUT, iputFld, 2);
            iputInsn.addArg(InsnArg.reg(insn, 0, tryResolveFieldType(iputFld)));
            iputInsn.addArg(InsnArg.reg(insn, 1, iputFld.getDeclClass().getType()));
            return iputInsn;
        case SGET:
            FieldInfo sgetFld = FieldInfo.fromRef(root, insn.getIndexAsField());
            InsnNode sgetInsn = new IndexInsnNode(InsnType.SGET, sgetFld, 0);
            sgetInsn.setResult(InsnArg.reg(insn, 0, tryResolveFieldType(sgetFld)));
            return sgetInsn;
        case SPUT:
            FieldInfo sputFld = FieldInfo.fromRef(root, insn.getIndexAsField());
            InsnNode sputInsn = new IndexInsnNode(InsnType.SPUT, sputFld, 1);
            sputInsn.addArg(InsnArg.reg(insn, 0, tryResolveFieldType(sputFld)));
            return sputInsn;
        case ARRAY_LENGTH:
            InsnNode arrLenInsn = new InsnNode(InsnType.ARRAY_LENGTH, 1);
            arrLenInsn.setResult(InsnArg.reg(insn, 0, ArgType.INT));
            arrLenInsn.addArg(InsnArg.reg(insn, 1, ArgType.array(ArgType.UNKNOWN)));
            return arrLenInsn;
        case AGET:
            return arrayGet(insn, ArgType.INT_FLOAT);
        case AGET_BOOLEAN:
            return arrayGet(insn, ArgType.BOOLEAN);
        case AGET_BYTE:
            return arrayGet(insn, ArgType.BYTE);
        case AGET_BYTE_BOOLEAN:
            return arrayGet(insn, ArgType.BYTE_BOOLEAN);
        case AGET_CHAR:
            return arrayGet(insn, ArgType.CHAR);
        case AGET_SHORT:
            return arrayGet(insn, ArgType.SHORT);
        case AGET_WIDE:
            return arrayGet(insn, ArgType.WIDE);
        case AGET_OBJECT:
            return arrayGet(insn, ArgType.UNKNOWN_OBJECT);
        case APUT:
            return arrayPut(insn, ArgType.INT_FLOAT);
        case APUT_BOOLEAN:
            return arrayPut(insn, ArgType.BOOLEAN);
        case APUT_BYTE:
            return arrayPut(insn, ArgType.BYTE);
        case APUT_BYTE_BOOLEAN:
            return arrayPut(insn, ArgType.BYTE_BOOLEAN);
        case APUT_CHAR:
            return arrayPut(insn, ArgType.CHAR);
        case APUT_SHORT:
            return arrayPut(insn, ArgType.SHORT);
        case APUT_WIDE:
            return arrayPut(insn, ArgType.WIDE);
        case APUT_OBJECT:
            return arrayPut(insn, ArgType.UNKNOWN_OBJECT);
        case INVOKE_STATIC:
            return invoke(insn, InvokeType.STATIC, false);
        case INVOKE_STATIC_RANGE:
            return invoke(insn, InvokeType.STATIC, true);
        case INVOKE_DIRECT:
            return invoke(insn, InvokeType.DIRECT, false);
        case INVOKE_INTERFACE:
            return invoke(insn, InvokeType.INTERFACE, false);
        case INVOKE_SUPER:
            return invoke(insn, InvokeType.SUPER, false);
        case INVOKE_VIRTUAL:
            return invoke(insn, InvokeType.VIRTUAL, false);
        case INVOKE_CUSTOM:
            return invokeCustom(insn, false);
        case INVOKE_SPECIAL:
            return invokeSpecial(insn);
        case INVOKE_DIRECT_RANGE:
            return invoke(insn, InvokeType.DIRECT, true);
        case INVOKE_INTERFACE_RANGE:
            return invoke(insn, InvokeType.INTERFACE, true);
        case INVOKE_SUPER_RANGE:
            return invoke(insn, InvokeType.SUPER, true);
        case INVOKE_VIRTUAL_RANGE:
            return invoke(insn, InvokeType.VIRTUAL, true);
        case INVOKE_CUSTOM_RANGE:
            return invokeCustom(insn, true);
        case NEW_INSTANCE:
            ArgType clsType = ArgType.parse(insn.getIndexAsType());
            IndexInsnNode newInstInsn = new IndexInsnNode(InsnType.NEW_INSTANCE, clsType, 0);
            newInstInsn.setResult(InsnArg.reg(insn, 0, clsType));
            return newInstInsn;
        case NEW_ARRAY:
            return makeNewArray(insn);
        case FILL_ARRAY_DATA:
            return new FillArrayInsn(InsnArg.reg(insn, 0, ArgType.UNKNOWN_ARRAY), insn.getTarget());
        case FILL_ARRAY_DATA_PAYLOAD:
            return new FillArrayData(((IArrayPayload) Objects.requireNonNull(insn.getPayload())));
        case FILLED_NEW_ARRAY:
            return filledNewArray(insn, false);
        case FILLED_NEW_ARRAY_RANGE:
            return filledNewArray(insn, true);
        case PACKED_SWITCH:
            return makeSwitch(insn, true);
        case SPARSE_SWITCH:
            return makeSwitch(insn, false);
        case PACKED_SWITCH_PAYLOAD:
        case SPARSE_SWITCH_PAYLOAD:
            return new SwitchData(((ISwitchPayload) insn.getPayload()));
        case MONITOR_ENTER:
            return insn(InsnType.MONITOR_ENTER, null, InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT));
        case MONITOR_EXIT:
            return insn(InsnType.MONITOR_EXIT, null, InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT));
        default:
            throw new DecodeException("Unknown instruction: '" + insn + '\'');
    }
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) IArrayPayload(jadx.api.plugins.input.insns.custom.IArrayPayload) DecodeException(jadx.core.utils.exceptions.DecodeException) InsnNode(jadx.core.dex.nodes.InsnNode) ISwitchPayload(jadx.api.plugins.input.insns.custom.ISwitchPayload) FieldInfo(jadx.core.dex.info.FieldInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with ISwitchPayload

use of jadx.api.plugins.input.insns.custom.ISwitchPayload in project jadx by skylot.

the class InsnDecoder method makeSwitch.

@NotNull
private SwitchInsn makeSwitch(InsnData insn, boolean packed) {
    SwitchInsn swInsn = new SwitchInsn(InsnArg.reg(insn, 0, ArgType.UNKNOWN), insn.getTarget(), packed);
    ICustomPayload payload = insn.getPayload();
    if (payload != null) {
        swInsn.attachSwitchData(new SwitchData((ISwitchPayload) payload), insn.getTarget());
    }
    return swInsn;
}
Also used : ISwitchPayload(jadx.api.plugins.input.insns.custom.ISwitchPayload) ICustomPayload(jadx.api.plugins.input.insns.custom.ICustomPayload) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

ISwitchPayload (jadx.api.plugins.input.insns.custom.ISwitchPayload)3 NotNull (org.jetbrains.annotations.NotNull)2 Opcode (jadx.api.plugins.input.insns.Opcode)1 IArrayPayload (jadx.api.plugins.input.insns.custom.IArrayPayload)1 ICustomPayload (jadx.api.plugins.input.insns.custom.ICustomPayload)1 FieldInfo (jadx.core.dex.info.FieldInfo)1 ArgType (jadx.core.dex.instructions.args.ArgType)1 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)1 InsnNode (jadx.core.dex.nodes.InsnNode)1 DecodeException (jadx.core.utils.exceptions.DecodeException)1