Search in sources :

Example 1 with LiteralArg

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

the class LoopRegionVisitor method checkArrayForEach.

private static LoopType checkArrayForEach(MethodNode mth, InsnNode initInsn, InsnNode incrInsn, IfCondition condition) {
    if (!(incrInsn instanceof ArithNode)) {
        return null;
    }
    ArithNode arithNode = (ArithNode) incrInsn;
    if (arithNode.getOp() != ArithOp.ADD) {
        return null;
    }
    InsnArg lit = incrInsn.getArg(1);
    if (!lit.isLiteral() || ((LiteralArg) lit).getLiteral() != 1) {
        return null;
    }
    if (initInsn.getType() != InsnType.CONST || !initInsn.getArg(0).isLiteral() || ((LiteralArg) initInsn.getArg(0)).getLiteral() != 0) {
        return null;
    }
    InsnArg condArg = incrInsn.getArg(0);
    if (!condArg.isRegister()) {
        return null;
    }
    SSAVar sVar = ((RegisterArg) condArg).getSVar();
    List<RegisterArg> args = sVar.getUseList();
    if (args.size() != 3 || args.get(2) != condArg) {
        return null;
    }
    condArg = args.get(0);
    RegisterArg arrIndex = args.get(1);
    InsnNode arrGetInsn = arrIndex.getParentInsn();
    if (arrGetInsn == null || arrGetInsn.getType() != InsnType.AGET) {
        return null;
    }
    if (!condition.isCompare()) {
        return null;
    }
    Compare compare = condition.getCompare();
    if (compare.getOp() != IfOp.LT || compare.getA() != condArg) {
        return null;
    }
    InsnNode len;
    InsnArg bCondArg = compare.getB();
    if (bCondArg.isInsnWrap()) {
        len = ((InsnWrapArg) bCondArg).getWrapInsn();
    } else if (bCondArg.isRegister()) {
        len = ((RegisterArg) bCondArg).getAssignInsn();
    } else {
        return null;
    }
    if (len == null || len.getType() != InsnType.ARRAY_LENGTH) {
        return null;
    }
    InsnArg arrayArg = len.getArg(0);
    if (!arrayArg.equals(arrGetInsn.getArg(0))) {
        return null;
    }
    RegisterArg iterVar = arrGetInsn.getResult();
    if (iterVar == null) {
        return null;
    }
    // array for each loop confirmed
    len.add(AFlag.SKIP);
    arrGetInsn.add(AFlag.SKIP);
    InstructionRemover.unbindInsn(mth, len);
    // inline array variable
    CodeShrinker.shrinkMethod(mth);
    if (arrGetInsn.contains(AFlag.WRAPPED)) {
        InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, arrGetInsn);
        if (wrapArg != null && wrapArg.getParentInsn() != null) {
            wrapArg.getParentInsn().replaceArg(wrapArg, iterVar);
        } else {
            LOG.debug(" checkArrayForEach: Wrapped insn not found: {}, mth: {}", arrGetInsn, mth);
        }
    }
    return new ForEachLoop(iterVar, len.getArg(0));
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SSAVar(jadx.core.dex.instructions.args.SSAVar) InsnArg(jadx.core.dex.instructions.args.InsnArg) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) Compare(jadx.core.dex.regions.conditions.Compare) ArithNode(jadx.core.dex.instructions.ArithNode) ForEachLoop(jadx.core.dex.regions.loops.ForEachLoop)

Example 2 with LiteralArg

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

the class SimplifyVisitor method simplifyArith.

private static InsnNode simplifyArith(InsnNode insn) {
    ArithNode arith = (ArithNode) insn;
    if (arith.getArgsCount() != 2) {
        return null;
    }
    InsnArg litArg = null;
    InsnArg secondArg = arith.getArg(1);
    if (secondArg.isInsnWrap()) {
        InsnNode wr = ((InsnWrapArg) secondArg).getWrapInsn();
        if (wr.getType() == InsnType.CONST) {
            litArg = wr.getArg(0);
        }
    } else if (secondArg.isLiteral()) {
        litArg = secondArg;
    }
    if (litArg != null) {
        long lit = ((LiteralArg) litArg).getLiteral();
        // fix 'c + (-1)' => 'c - (1)'
        if (arith.getOp() == ArithOp.ADD && lit < 0) {
            return new ArithNode(ArithOp.SUB, arith.getResult(), insn.getArg(0), InsnArg.lit(-lit, litArg.getType()));
        }
    }
    return null;
}
Also used : IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) InsnArg(jadx.core.dex.instructions.args.InsnArg) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) InsnWrapArg(jadx.core.dex.instructions.args.InsnWrapArg) ArithNode(jadx.core.dex.instructions.ArithNode)

Example 3 with LiteralArg

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

the class ModVisitor method replaceStep.

private static void replaceStep(MethodNode mth, InstructionRemover remover) {
    ClassNode parentClass = mth.getParentClass();
    for (BlockNode block : mth.getBasicBlocks()) {
        remover.setBlock(block);
        int size = block.getInstructions().size();
        for (int i = 0; i < size; i++) {
            InsnNode insn = block.getInstructions().get(i);
            switch(insn.getType()) {
                case INVOKE:
                    processInvoke(mth, block, i, remover);
                    break;
                case CONST:
                case CONST_STR:
                case CONST_CLASS:
                    {
                        FieldNode f;
                        if (insn.getType() == InsnType.CONST_STR) {
                            String s = ((ConstStringNode) insn).getString();
                            f = parentClass.getConstField(s);
                        } else if (insn.getType() == InsnType.CONST_CLASS) {
                            ArgType t = ((ConstClassNode) insn).getClsType();
                            f = parentClass.getConstField(t);
                        } else {
                            f = parentClass.getConstFieldByLiteralArg((LiteralArg) insn.getArg(0));
                        }
                        if (f != null) {
                            InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
                            inode.setResult(insn.getResult());
                            replaceInsn(block, i, inode);
                        }
                        break;
                    }
                case SWITCH:
                    SwitchNode sn = (SwitchNode) insn;
                    for (int k = 0; k < sn.getCasesCount(); k++) {
                        FieldNode f = parentClass.getConstField(sn.getKeys()[k]);
                        if (f != null) {
                            sn.getKeys()[k] = f;
                        }
                    }
                    break;
                case NEW_ARRAY:
                    // create array in 'fill-array' instruction
                    int next = i + 1;
                    if (next < size) {
                        InsnNode ni = block.getInstructions().get(next);
                        if (ni.getType() == InsnType.FILL_ARRAY) {
                            ni.getResult().merge(mth.dex(), insn.getResult());
                            ArgType arrType = ((NewArrayNode) insn).getArrayType();
                            ((FillArrayNode) ni).mergeElementType(mth.dex(), arrType.getArrayElement());
                            remover.add(insn);
                        }
                    }
                    break;
                case FILL_ARRAY:
                    InsnNode filledArr = makeFilledArrayInsn(mth, (FillArrayNode) insn);
                    replaceInsn(block, i, filledArr);
                    break;
                case MOVE_EXCEPTION:
                    processMoveException(mth, block, insn, remover);
                    break;
                case ARITH:
                    ArithNode arithNode = (ArithNode) insn;
                    if (arithNode.getArgsCount() == 2) {
                        InsnArg litArg = arithNode.getArg(1);
                        if (litArg.isLiteral()) {
                            FieldNode f = parentClass.getConstFieldByLiteralArg((LiteralArg) litArg);
                            if (f != null) {
                                InsnNode fGet = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
                                insn.replaceArg(litArg, InsnArg.wrapArg(fGet));
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
        }
        remover.perform();
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ArgType(jadx.core.dex.instructions.args.ArgType) ClassNode(jadx.core.dex.nodes.ClassNode) ConstClassNode(jadx.core.dex.instructions.ConstClassNode) FieldNode(jadx.core.dex.nodes.FieldNode) NewArrayNode(jadx.core.dex.instructions.NewArrayNode) FilledNewArrayNode(jadx.core.dex.instructions.FilledNewArrayNode) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) ArithNode(jadx.core.dex.instructions.ArithNode) SwitchNode(jadx.core.dex.instructions.SwitchNode) FillArrayNode(jadx.core.dex.instructions.FillArrayNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) InsnArg(jadx.core.dex.instructions.args.InsnArg) ConstClassNode(jadx.core.dex.instructions.ConstClassNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode)

Example 4 with LiteralArg

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

the class ConstInlineVisitor method checkInsn.

private static boolean checkInsn(MethodNode mth, InsnNode insn) {
    if (insn.getType() != InsnType.CONST || insn.contains(AFlag.DONT_INLINE)) {
        return false;
    }
    InsnArg arg = insn.getArg(0);
    if (!arg.isLiteral()) {
        return false;
    }
    long lit = ((LiteralArg) arg).getLiteral();
    SSAVar sVar = insn.getResult().getSVar();
    if (lit == 0 && checkObjectInline(sVar)) {
        if (sVar.getUseCount() == 1) {
            InsnNode assignInsn = insn.getResult().getAssignInsn();
            if (assignInsn != null) {
                assignInsn.add(AFlag.DONT_INLINE);
            }
        }
        return false;
    }
    ArgType resType = insn.getResult().getType();
    // make sure arg has correct type
    if (!arg.getType().isTypeKnown()) {
        arg.merge(mth.dex(), resType);
    }
    return replaceConst(mth, insn, lit);
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) SSAVar(jadx.core.dex.instructions.args.SSAVar) InsnArg(jadx.core.dex.instructions.args.InsnArg) LiteralArg(jadx.core.dex.instructions.args.LiteralArg)

Example 5 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)

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