Search in sources :

Example 1 with FillArrayInsn

use of jadx.core.dex.instructions.FillArrayInsn in project jadx by skylot.

the class InsnGen method makeInsnBody.

private void makeInsnBody(ICodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException {
    switch(insn.getType()) {
        case CONST_STR:
            String str = ((ConstStringNode) insn).getString();
            code.add(mth.root().getStringUtils().unescapeString(str));
            break;
        case CONST_CLASS:
            ArgType clsType = ((ConstClassNode) insn).getClsType();
            useType(code, clsType);
            code.add(".class");
            break;
        case CONST:
            LiteralArg arg = (LiteralArg) insn.getArg(0);
            code.add(lit(arg));
            break;
        case MOVE:
            addArg(code, insn.getArg(0), false);
            break;
        case CHECK_CAST:
        case CAST:
            {
                boolean wrap = state.contains(Flags.BODY_ONLY);
                if (wrap) {
                    code.add('(');
                }
                code.add('(');
                useType(code, (ArgType) ((IndexInsnNode) insn).getIndex());
                code.add(") ");
                addArg(code, insn.getArg(0), true);
                if (wrap) {
                    code.add(')');
                }
                break;
            }
        case ARITH:
            makeArith((ArithNode) insn, code, state);
            break;
        case NEG:
            oneArgInsn(code, insn, state, '-');
            break;
        case NOT:
            char op = insn.getArg(0).getType() == ArgType.BOOLEAN ? '!' : '~';
            oneArgInsn(code, insn, state, op);
            break;
        case RETURN:
            if (insn.getArgsCount() != 0) {
                code.add("return ");
                addArg(code, insn.getArg(0), false);
            } else {
                code.add("return");
            }
            break;
        case BREAK:
            code.add("break");
            LoopLabelAttr labelAttr = insn.get(AType.LOOP_LABEL);
            if (labelAttr != null) {
                code.add(' ').add(mgen.getNameGen().getLoopLabel(labelAttr));
            }
            break;
        case CONTINUE:
            code.add("continue");
            break;
        case THROW:
            code.add("throw ");
            addArg(code, insn.getArg(0), true);
            break;
        case CMP_L:
        case CMP_G:
            code.add('(');
            addArg(code, insn.getArg(0));
            code.add(" > ");
            addArg(code, insn.getArg(1));
            code.add(" ? 1 : (");
            addArg(code, insn.getArg(0));
            code.add(" == ");
            addArg(code, insn.getArg(1));
            code.add(" ? 0 : -1))");
            break;
        case INSTANCE_OF:
            {
                boolean wrap = state.contains(Flags.BODY_ONLY);
                if (wrap) {
                    code.add('(');
                }
                addArg(code, insn.getArg(0));
                code.add(" instanceof ");
                useType(code, (ArgType) ((IndexInsnNode) insn).getIndex());
                if (wrap) {
                    code.add(')');
                }
                break;
            }
        case CONSTRUCTOR:
            makeConstructor((ConstructorInsn) insn, code);
            break;
        case INVOKE:
            makeInvoke((InvokeNode) insn, code);
            break;
        case NEW_ARRAY:
            {
                ArgType arrayType = ((NewArrayNode) insn).getArrayType();
                code.add("new ");
                useType(code, arrayType.getArrayRootElement());
                int k = 0;
                int argsCount = insn.getArgsCount();
                for (; k < argsCount; k++) {
                    code.add('[');
                    addArg(code, insn.getArg(k), false);
                    code.add(']');
                }
                int dim = arrayType.getArrayDimension();
                for (; k < dim - 1; k++) {
                    code.add("[]");
                }
                break;
            }
        case ARRAY_LENGTH:
            addArg(code, insn.getArg(0));
            code.add(".length");
            break;
        case FILLED_NEW_ARRAY:
            filledNewArray((FilledNewArrayNode) insn, code);
            break;
        case FILL_ARRAY:
            FillArrayInsn arrayNode = (FillArrayInsn) insn;
            if (fallback) {
                String arrStr = arrayNode.dataToString();
                addArg(code, insn.getArg(0));
                code.add(" = {").add(arrStr.substring(1, arrStr.length() - 1)).add("} // fill-array");
            } else {
                fillArray(code, arrayNode);
            }
            break;
        case AGET:
            addArg(code, insn.getArg(0));
            code.add('[');
            addArg(code, insn.getArg(1), false);
            code.add(']');
            break;
        case APUT:
            addArg(code, insn.getArg(0));
            code.add('[');
            addArg(code, insn.getArg(1), false);
            code.add("] = ");
            addArg(code, insn.getArg(2), false);
            break;
        case IGET:
            {
                FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
                instanceField(code, fieldInfo, insn.getArg(0));
                break;
            }
        case IPUT:
            {
                FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
                instanceField(code, fieldInfo, insn.getArg(1));
                code.add(" = ");
                addArg(code, insn.getArg(0), false);
                break;
            }
        case SGET:
            staticField(code, (FieldInfo) ((IndexInsnNode) insn).getIndex());
            break;
        case SPUT:
            FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex();
            staticField(code, field);
            code.add(" = ");
            addArg(code, insn.getArg(0), false);
            break;
        case STR_CONCAT:
            boolean wrap = state.contains(Flags.BODY_ONLY);
            if (wrap) {
                code.add('(');
            }
            for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) {
                addArg(code, it.next());
                if (it.hasNext()) {
                    code.add(" + ");
                }
            }
            if (wrap) {
                code.add(')');
            }
            break;
        case MONITOR_ENTER:
            if (isFallback()) {
                code.add("monitor-enter(");
                addArg(code, insn.getArg(0));
                code.add(')');
            }
            break;
        case MONITOR_EXIT:
            if (isFallback()) {
                code.add("monitor-exit(");
                if (insn.getArgsCount() == 1) {
                    addArg(code, insn.getArg(0));
                }
                code.add(')');
            }
            break;
        case TERNARY:
            makeTernary((TernaryInsn) insn, code, state);
            break;
        case ONE_ARG:
            addArg(code, insn.getArg(0), state);
            break;
        /* fallback mode instructions */
        case IF:
            fallbackOnlyInsn(insn);
            IfNode ifInsn = (IfNode) insn;
            code.add("if (");
            addArg(code, insn.getArg(0));
            code.add(' ');
            code.add(ifInsn.getOp().getSymbol()).add(' ');
            addArg(code, insn.getArg(1));
            code.add(") goto ").add(MethodGen.getLabelName(ifInsn.getTarget()));
            break;
        case GOTO:
            fallbackOnlyInsn(insn);
            code.add("goto ").add(MethodGen.getLabelName(((GotoNode) insn).getTarget()));
            break;
        case MOVE_EXCEPTION:
            fallbackOnlyInsn(insn);
            code.add("move-exception");
            break;
        case SWITCH:
            fallbackOnlyInsn(insn);
            SwitchInsn sw = (SwitchInsn) insn;
            code.add("switch(");
            addArg(code, insn.getArg(0));
            code.add(") {");
            code.incIndent();
            int[] keys = sw.getKeys();
            int[] targets = sw.getTargets();
            for (int i = 0; i < keys.length; i++) {
                code.startLine("case ").add(Integer.toString(keys[i])).add(": goto ");
                code.add(MethodGen.getLabelName(targets[i])).add(';');
            }
            code.startLine("default: goto ");
            code.add(MethodGen.getLabelName(sw.getDefaultCaseOffset())).add(';');
            code.decIndent();
            code.startLine('}');
            break;
        case NEW_INSTANCE:
            // only fallback - make new instance in constructor invoke
            fallbackOnlyInsn(insn);
            code.add("new ").add(insn.getResult().getInitType().toString());
            break;
        case PHI:
            fallbackOnlyInsn(insn);
            code.add(insn.getType().toString()).add('(');
            for (InsnArg insnArg : insn.getArguments()) {
                addArg(code, insnArg);
                code.add(' ');
            }
            code.add(')');
            break;
        case MOVE_RESULT:
            fallbackOnlyInsn(insn);
            code.add("move-result");
            break;
        case FILL_ARRAY_DATA:
            fallbackOnlyInsn(insn);
            code.add("fill-array " + insn);
            break;
        case SWITCH_DATA:
            fallbackOnlyInsn(insn);
            code.add(insn.toString());
            break;
        case MOVE_MULTI:
            fallbackOnlyInsn(insn);
            int len = insn.getArgsCount();
            for (int i = 0; i < len - 1; i += 2) {
                addArg(code, insn.getArg(i));
                code.add(" = ");
                addArg(code, insn.getArg(i + 1));
                code.add("; ");
            }
            break;
        default:
            throw new CodegenException(mth, "Unknown instruction: " + insn.getType());
    }
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) CodegenException(jadx.core.utils.exceptions.CodegenException) LoopLabelAttr(jadx.core.dex.attributes.nodes.LoopLabelAttr) ConstStringNode(jadx.core.dex.instructions.ConstStringNode) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) IfNode(jadx.core.dex.instructions.IfNode) SwitchInsn(jadx.core.dex.instructions.SwitchInsn) FillArrayInsn(jadx.core.dex.instructions.FillArrayInsn) InsnArg(jadx.core.dex.instructions.args.InsnArg) ConstClassNode(jadx.core.dex.instructions.ConstClassNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) FieldInfo(jadx.core.dex.info.FieldInfo) GotoNode(jadx.core.dex.instructions.GotoNode)

Example 2 with FillArrayInsn

use of jadx.core.dex.instructions.FillArrayInsn in project jadx by skylot.

the class ModVisitor method replaceStep.

private static void replaceStep(MethodNode mth, InsnRemover remover) {
    ClassNode parentClass = mth.getParentClass();
    for (BlockNode block : mth.getBasicBlocks()) {
        remover.setBlock(block);
        List<InsnNode> insnsList = block.getInstructions();
        int size = insnsList.size();
        for (int i = 0; i < size; i++) {
            InsnNode insn = insnsList.get(i);
            switch(insn.getType()) {
                case CONSTRUCTOR:
                    processAnonymousConstructor(mth, ((ConstructorInsn) insn));
                    break;
                case CONST:
                case CONST_STR:
                case CONST_CLASS:
                    replaceConst(mth, parentClass, block, i, insn);
                    break;
                case SWITCH:
                    replaceConstKeys(mth, parentClass, (SwitchInsn) insn);
                    break;
                case NEW_ARRAY:
                    // replace with filled array if 'fill-array' is next instruction
                    NewArrayNode newArrInsn = (NewArrayNode) insn;
                    InsnNode nextInsn = getFirstUseSkipMove(insn.getResult());
                    if (nextInsn != null && nextInsn.getType() == InsnType.FILL_ARRAY) {
                        FillArrayInsn fillArrInsn = (FillArrayInsn) nextInsn;
                        if (checkArrSizes(mth, newArrInsn, fillArrInsn)) {
                            InsnNode filledArr = makeFilledArrayInsn(mth, newArrInsn, fillArrInsn);
                            replaceInsn(mth, block, i, filledArr);
                            remover.addAndUnbind(nextInsn);
                        }
                    }
                    break;
                case MOVE_EXCEPTION:
                    processMoveException(mth, block, insn, remover);
                    break;
                case ARITH:
                    processArith(mth, parentClass, (ArithNode) insn);
                    break;
                case CHECK_CAST:
                    removeCheckCast(mth, block, i, (IndexInsnNode) insn);
                    break;
                case CAST:
                    fixPrimitiveCast(mth, block, i, insn);
                    break;
                case IPUT:
                case IGET:
                    fixFieldUsage(mth, (IndexInsnNode) insn);
                    break;
                default:
                    break;
            }
        }
        remover.perform();
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) FillArrayInsn(jadx.core.dex.instructions.FillArrayInsn) ClassNode(jadx.core.dex.nodes.ClassNode) ConstClassNode(jadx.core.dex.instructions.ConstClassNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) NewArrayNode(jadx.core.dex.instructions.NewArrayNode) FilledNewArrayNode(jadx.core.dex.instructions.FilledNewArrayNode) ConstructorInsn(jadx.core.dex.instructions.mods.ConstructorInsn)

Example 3 with FillArrayInsn

use of jadx.core.dex.instructions.FillArrayInsn in project jadx by skylot.

the class ProcessInstructionsVisitor method initJumps.

private static void initJumps(MethodNode mth, InsnNode[] insnByOffset) {
    for (int offset = 0; offset < insnByOffset.length; offset++) {
        InsnNode insn = insnByOffset[offset];
        if (insn == null) {
            continue;
        }
        switch(insn.getType()) {
            case SWITCH:
                SwitchInsn sw = (SwitchInsn) insn;
                if (sw.needData()) {
                    attachSwitchData(insnByOffset, offset, sw);
                }
                int defCaseOffset = sw.getDefaultCaseOffset();
                if (defCaseOffset != -1) {
                    addJump(mth, insnByOffset, offset, defCaseOffset);
                }
                for (int target : sw.getTargets()) {
                    addJump(mth, insnByOffset, offset, target);
                }
                break;
            case IF:
                int next = getNextInsnOffset(insnByOffset, offset);
                if (next != -1) {
                    addJump(mth, insnByOffset, offset, next);
                }
                addJump(mth, insnByOffset, offset, ((IfNode) insn).getTarget());
                break;
            case GOTO:
                addJump(mth, insnByOffset, offset, ((GotoNode) insn).getTarget());
                break;
            case INVOKE:
                if (insn.getResult() == null) {
                    ArgType retType = ((BaseInvokeNode) insn).getCallMth().getReturnType();
                    mergeMoveResult(insnByOffset, offset, insn, retType);
                }
                break;
            case STR_CONCAT:
                // invoke-custom with string concatenation translated directly to STR_CONCAT, merge next move-result
                if (insn.getResult() == null) {
                    mergeMoveResult(insnByOffset, offset, insn, ArgType.STRING);
                }
                break;
            case FILLED_NEW_ARRAY:
                ArgType arrType = ((FilledNewArrayNode) insn).getArrayType();
                mergeMoveResult(insnByOffset, offset, insn, arrType);
                break;
            case FILL_ARRAY:
                FillArrayInsn fillArrayInsn = (FillArrayInsn) insn;
                int target = fillArrayInsn.getTarget();
                InsnNode arrDataInsn = getInsnAtOffset(insnByOffset, target);
                if (arrDataInsn != null && arrDataInsn.getType() == InsnType.FILL_ARRAY_DATA) {
                    fillArrayInsn.setArrayData((FillArrayData) arrDataInsn);
                    removeInsn(insnByOffset, arrDataInsn);
                } else {
                    throw new JadxRuntimeException("Payload for fill-array not found at " + InsnUtils.formatOffset(target));
                }
                break;
            default:
                break;
        }
    }
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) FillArrayInsn(jadx.core.dex.instructions.FillArrayInsn) InsnNode(jadx.core.dex.nodes.InsnNode) FilledNewArrayNode(jadx.core.dex.instructions.FilledNewArrayNode) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) SwitchInsn(jadx.core.dex.instructions.SwitchInsn)

Aggregations

FillArrayInsn (jadx.core.dex.instructions.FillArrayInsn)3 ConstClassNode (jadx.core.dex.instructions.ConstClassNode)2 FilledNewArrayNode (jadx.core.dex.instructions.FilledNewArrayNode)2 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)2 SwitchInsn (jadx.core.dex.instructions.SwitchInsn)2 ArgType (jadx.core.dex.instructions.args.ArgType)2 InsnNode (jadx.core.dex.nodes.InsnNode)2 LoopLabelAttr (jadx.core.dex.attributes.nodes.LoopLabelAttr)1 FieldInfo (jadx.core.dex.info.FieldInfo)1 ConstStringNode (jadx.core.dex.instructions.ConstStringNode)1 GotoNode (jadx.core.dex.instructions.GotoNode)1 IfNode (jadx.core.dex.instructions.IfNode)1 NewArrayNode (jadx.core.dex.instructions.NewArrayNode)1 InsnArg (jadx.core.dex.instructions.args.InsnArg)1 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)1 ConstructorInsn (jadx.core.dex.instructions.mods.ConstructorInsn)1 BlockNode (jadx.core.dex.nodes.BlockNode)1 ClassNode (jadx.core.dex.nodes.ClassNode)1 CodegenException (jadx.core.utils.exceptions.CodegenException)1 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)1