Search in sources :

Example 6 with LiteralArg

use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.

the class FillArrayNode method getLiteralArgs.

public List<LiteralArg> getLiteralArgs() {
    List<LiteralArg> list = new ArrayList<LiteralArg>(size);
    Object array = data;
    if (array instanceof int[]) {
        for (int b : (int[]) array) {
            list.add(InsnArg.lit(b, elemType));
        }
    } else if (array instanceof byte[]) {
        for (byte b : (byte[]) array) {
            list.add(InsnArg.lit(b, elemType));
        }
    } else if (array instanceof short[]) {
        for (short b : (short[]) array) {
            list.add(InsnArg.lit(b, elemType));
        }
    } else if (array instanceof long[]) {
        for (long b : (long[]) array) {
            list.add(InsnArg.lit(b, elemType));
        }
    } else {
        throw new JadxRuntimeException("Unknown type: " + data.getClass() + ", expected: " + elemType);
    }
    return list;
}
Also used : ArrayList(java.util.ArrayList) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException)

Example 7 with LiteralArg

use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.

the class PostTypeInference method process.

public static boolean process(MethodNode mth, InsnNode insn) {
    DexNode dex = mth.dex();
    switch(insn.getType()) {
        case CONST:
            RegisterArg res = insn.getResult();
            LiteralArg litArg = (LiteralArg) insn.getArg(0);
            if (res.getType().isObject()) {
                long lit = litArg.getLiteral();
                if (lit != 0) {
                    // incorrect literal value for object
                    ArgType type = lit == 1 ? ArgType.BOOLEAN : ArgType.INT;
                    // can't merge with object -> force it
                    litArg.setType(type);
                    res.getSVar().setType(type);
                    return true;
                }
            }
            return litArg.merge(dex, res);
        case MOVE:
            {
                boolean change = false;
                if (insn.getResult().merge(dex, insn.getArg(0))) {
                    change = true;
                }
                if (insn.getArg(0).merge(dex, insn.getResult())) {
                    change = true;
                }
                return change;
            }
        case AGET:
            return fixArrayTypes(dex, insn.getArg(0), insn.getResult());
        case APUT:
            return fixArrayTypes(dex, insn.getArg(0), insn.getArg(2));
        case IF:
            {
                boolean change = false;
                if (insn.getArg(1).merge(dex, insn.getArg(0))) {
                    change = true;
                }
                if (insn.getArg(0).merge(dex, insn.getArg(1))) {
                    change = true;
                }
                return change;
            }
        // check argument types for overloaded methods
        case INVOKE:
            {
                boolean change = false;
                InvokeNode inv = (InvokeNode) insn;
                MethodInfo callMth = inv.getCallMth();
                MethodNode node = mth.dex().resolveMethod(callMth);
                if (node != null && node.isArgsOverload()) {
                    List<ArgType> args = callMth.getArgumentsTypes();
                    int j = inv.getArgsCount() - 1;
                    for (int i = args.size() - 1; i >= 0; i--) {
                        ArgType argType = args.get(i);
                        InsnArg insnArg = inv.getArg(j--);
                        if (insnArg.isRegister() && !argType.equals(insnArg.getType())) {
                            insnArg.setType(argType);
                            change = true;
                        }
                    }
                }
                return change;
            }
        case CHECK_CAST:
            {
                ArgType castType = (ArgType) ((IndexInsnNode) insn).getIndex();
                RegisterArg result = insn.getResult();
                ArgType resultType = result.getType();
                // don't override generic types of same base class
                boolean skip = castType.isObject() && resultType.isObject() && castType.getObject().equals(resultType.getObject());
                if (!skip) {
                    // workaround for compiler bug (see TestDuplicateCast)
                    result.getSVar().setType(castType);
                }
                return true;
            }
        case PHI:
        case MERGE:
            {
                ArgType type = insn.getResult().getType();
                if (!type.isTypeKnown()) {
                    for (InsnArg arg : insn.getArguments()) {
                        if (arg.getType().isTypeKnown()) {
                            type = arg.getType();
                            break;
                        }
                    }
                }
                boolean changed = false;
                if (updateType(insn.getResult(), type)) {
                    changed = true;
                }
                for (int i = 0; i < insn.getArgsCount(); i++) {
                    RegisterArg arg = (RegisterArg) insn.getArg(i);
                    if (updateType(arg, type)) {
                        changed = true;
                    }
                }
                return changed;
            }
        default:
            break;
    }
    return false;
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) MethodNode(jadx.core.dex.nodes.MethodNode) InsnArg(jadx.core.dex.instructions.args.InsnArg) DexNode(jadx.core.dex.nodes.DexNode) InvokeNode(jadx.core.dex.instructions.InvokeNode) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) MethodInfo(jadx.core.dex.info.MethodInfo) List(java.util.List) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode)

Example 8 with LiteralArg

use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.

the class InsnGen method makeArithOneArg.

private void makeArithOneArg(ArithNode insn, CodeWriter code) throws CodegenException {
    ArithOp op = insn.getOp();
    InsnArg arg = insn.getArg(1);
    // "++" or "--"
    if (arg.isLiteral() && (op == ArithOp.ADD || op == ArithOp.SUB)) {
        LiteralArg lit = (LiteralArg) arg;
        if (lit.isInteger() && lit.getLiteral() == 1) {
            assignVar(code, insn);
            String opSymbol = op.getSymbol();
            code.add(opSymbol).add(opSymbol);
            return;
        }
    }
    // +=, -= ...
    assignVar(code, insn);
    code.add(' ').add(op.getSymbol()).add("= ");
    addArg(code, arg, false);
}
Also used : InsnArg(jadx.core.dex.instructions.args.InsnArg) ArithOp(jadx.core.dex.instructions.ArithOp) LiteralArg(jadx.core.dex.instructions.args.LiteralArg)

Example 9 with LiteralArg

use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.

the class InsnGen method makeInsnBody.

private void makeInsnBody(CodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException {
    switch(insn.getType()) {
        case CONST_STR:
            String str = ((ConstStringNode) insn).getString();
            code.add(mth.dex().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:
            {
                boolean wrap = state.contains(Flags.BODY_ONLY);
                if (wrap) {
                    code.add('(');
                }
                code.add('-');
                addArg(code, insn.getArg(0));
                if (wrap) {
                    code.add(')');
                }
                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());
                code.add('[');
                addArg(code, insn.getArg(0));
                code.add(']');
                int dim = arrayType.getArrayDimension();
                for (int i = 0; i < dim - 1; i++) {
                    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 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(");
                addArg(code, insn.getArg(0));
                code.add(')');
            }
            break;
        case TERNARY:
            makeTernary((TernaryInsn) insn, code, state);
            break;
        case ONE_ARG:
            addArg(code, insn.getArg(0));
            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);
            SwitchNode sw = (SwitchNode) insn;
            code.add("switch(");
            addArg(code, insn.getArg(0));
            code.add(") {");
            code.incIndent();
            for (int i = 0; i < sw.getCasesCount(); i++) {
                String key = sw.getKeys()[i].toString();
                code.startLine("case ").add(key).add(": goto ");
                code.add(MethodGen.getLabelName(sw.getTargets()[i])).add(';');
            }
            code.startLine("default: goto ");
            code.add(MethodGen.getLabelName(sw.getDefaultCaseOffset())).add(';');
            code.decIndent();
            code.startLine('}');
            break;
        case FILL_ARRAY:
            fallbackOnlyInsn(insn);
            FillArrayNode arrayNode = (FillArrayNode) insn;
            Object data = arrayNode.getData();
            String arrStr;
            if (data instanceof int[]) {
                arrStr = Arrays.toString((int[]) data);
            } else if (data instanceof short[]) {
                arrStr = Arrays.toString((short[]) data);
            } else if (data instanceof byte[]) {
                arrStr = Arrays.toString((byte[]) data);
            } else if (data instanceof long[]) {
                arrStr = Arrays.toString((long[]) data);
            } else {
                arrStr = "?";
            }
            code.add('{').add(arrStr.substring(1, arrStr.length() - 1)).add('}');
            break;
        case NEW_INSTANCE:
            // only fallback - make new instance in constructor invoke
            fallbackOnlyInsn(insn);
            code.add("new ").add(insn.getResult().getType().toString());
            break;
        case PHI:
        case MERGE:
            fallbackOnlyInsn(insn);
            code.add(insn.getType().toString()).add("(");
            for (InsnArg insnArg : insn.getArguments()) {
                addArg(code, insnArg);
                code.add(' ');
            }
            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) SwitchNode(jadx.core.dex.instructions.SwitchNode) FillArrayNode(jadx.core.dex.instructions.FillArrayNode) 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 10 with LiteralArg

use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.

the class ConditionGen method addCompare.

private void addCompare(CodeWriter code, CondStack stack, Compare compare) throws CodegenException {
    IfOp op = compare.getOp();
    InsnArg firstArg = compare.getA();
    InsnArg secondArg = compare.getB();
    if (firstArg.getType().equals(ArgType.BOOLEAN) && secondArg.isLiteral() && secondArg.getType().equals(ArgType.BOOLEAN)) {
        LiteralArg lit = (LiteralArg) secondArg;
        if (lit.getLiteral() == 0) {
            op = op.invert();
        }
        if (op == IfOp.EQ) {
            // == true
            if (stack.getStack().size() == 1) {
                addArg(code, firstArg, false);
            } else {
                wrap(code, firstArg);
            }
            return;
        } else if (op == IfOp.NE) {
            // != true
            code.add('!');
            wrap(code, firstArg);
            return;
        }
        LOG.warn(ErrorsCounter.formatErrorMsg(mth, "Unsupported boolean condition " + op.getSymbol()));
    }
    addArg(code, firstArg, isArgWrapNeeded(firstArg));
    code.add(' ').add(op.getSymbol()).add(' ');
    addArg(code, secondArg, isArgWrapNeeded(secondArg));
}
Also used : InsnArg(jadx.core.dex.instructions.args.InsnArg) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) IfOp(jadx.core.dex.instructions.IfOp)

Aggregations

LiteralArg (jadx.core.dex.instructions.args.LiteralArg)12 InsnArg (jadx.core.dex.instructions.args.InsnArg)8 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)7 InsnNode (jadx.core.dex.nodes.InsnNode)7 ArgType (jadx.core.dex.instructions.args.ArgType)6 ArithNode (jadx.core.dex.instructions.ArithNode)3 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)3 SSAVar (jadx.core.dex.instructions.args.SSAVar)3 FieldNode (jadx.core.dex.nodes.FieldNode)3 ConstClassNode (jadx.core.dex.instructions.ConstClassNode)2 FillArrayNode (jadx.core.dex.instructions.FillArrayNode)2 FilledNewArrayNode (jadx.core.dex.instructions.FilledNewArrayNode)2 IfNode (jadx.core.dex.instructions.IfNode)2 SwitchNode (jadx.core.dex.instructions.SwitchNode)2 InsnWrapArg (jadx.core.dex.instructions.args.InsnWrapArg)2 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)2 ArrayList (java.util.ArrayList)2 LoopLabelAttr (jadx.core.dex.attributes.nodes.LoopLabelAttr)1 FieldInfo (jadx.core.dex.info.FieldInfo)1 MethodInfo (jadx.core.dex.info.MethodInfo)1