Search in sources :

Example 1 with Compare

use of jadx.core.dex.regions.conditions.Compare 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 Compare

use of jadx.core.dex.regions.conditions.Compare in project jadx by skylot.

the class LoopRegionVisitor method checkArrayForEach.

private static LoopType checkArrayForEach(MethodNode mth, LoopRegion loopRegion, 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) {
        return null;
    }
    condArg = InsnUtils.getRegFromInsn(args, InsnType.IF);
    if (condArg == null) {
        return null;
    }
    RegisterArg arrIndex = InsnUtils.getRegFromInsn(args, InsnType.AGET);
    if (arrIndex == null) {
        return null;
    }
    InsnNode arrGetInsn = arrIndex.getParentInsn();
    if (arrGetInsn == null || arrGetInsn.containsWrappedInsn()) {
        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;
    }
    if (!usedOnlyInLoop(mth, loopRegion, iterVar)) {
        return null;
    }
    // array for each loop confirmed
    incrInsn.getResult().add(AFlag.DONT_GENERATE);
    condArg.add(AFlag.DONT_GENERATE);
    bCondArg.add(AFlag.DONT_GENERATE);
    arrGetInsn.add(AFlag.DONT_GENERATE);
    compare.getInsn().add(AFlag.DONT_GENERATE);
    if (arrGetInsn.contains(AFlag.WRAPPED)) {
        InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, arrGetInsn);
        if (wrapArg != null && wrapArg.getParentInsn() != null) {
            InsnNode parentInsn = wrapArg.getParentInsn();
            parentInsn.replaceArg(wrapArg, iterVar.duplicate());
            parentInsn.rebindArgs();
        } else {
            LOG.debug(" checkArrayForEach: Wrapped insn not found: {}, mth: {}", arrGetInsn, mth);
        }
    }
    ForEachLoop forEachLoop = new ForEachLoop(iterVar, len.getArg(0));
    forEachLoop.injectFakeInsns(loopRegion);
    if (InsnUtils.dontGenerateIfNotUsed(len)) {
        InsnRemover.remove(mth, len);
    }
    CodeShrinkVisitor.shrinkMethod(mth);
    return forEachLoop;
}
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 3 with Compare

use of jadx.core.dex.regions.conditions.Compare in project jadx by skylot.

the class TestIfCondition method testNormalize.

@Test
public void testNormalize() {
    // 'a != false' => 'a == true'
    InsnArg a = mockArg();
    IfCondition c = makeCondition(IfOp.NE, a, LiteralArg.litFalse());
    IfCondition simp = simplify(c);
    assertThat(simp.getMode(), is(COMPARE));
    Compare compare = simp.getCompare();
    assertThat(compare.getA(), is(a));
    assertThat(compare.getB(), is(LiteralArg.litTrue()));
}
Also used : InsnArg(jadx.core.dex.instructions.args.InsnArg) Compare(jadx.core.dex.regions.conditions.Compare) IfCondition(jadx.core.dex.regions.conditions.IfCondition) Test(org.junit.jupiter.api.Test)

Aggregations

InsnArg (jadx.core.dex.instructions.args.InsnArg)3 Compare (jadx.core.dex.regions.conditions.Compare)3 ArithNode (jadx.core.dex.instructions.ArithNode)2 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)2 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)2 SSAVar (jadx.core.dex.instructions.args.SSAVar)2 InsnNode (jadx.core.dex.nodes.InsnNode)2 ForEachLoop (jadx.core.dex.regions.loops.ForEachLoop)2 IfCondition (jadx.core.dex.regions.conditions.IfCondition)1 Test (org.junit.jupiter.api.Test)1