Search in sources :

Example 96 with BlockNode

use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.

the class LoopRegionVisitor method checkForIndexedLoop.

/**
 * Check for indexed loop.
 */
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
    BlockNode loopEndBlock = loopRegion.getInfo().getEnd();
    InsnNode incrInsn = BlockUtils.getLastInsn(BlockUtils.skipSyntheticPredecessor(loopEndBlock));
    if (incrInsn == null) {
        return false;
    }
    RegisterArg incrArg = incrInsn.getResult();
    if (incrArg == null || incrArg.getSVar() == null || !incrArg.getSVar().isUsedInPhi()) {
        return false;
    }
    List<PhiInsn> phiInsnList = incrArg.getSVar().getUsedInPhi();
    if (phiInsnList.size() != 1) {
        return false;
    }
    PhiInsn phiInsn = phiInsnList.get(0);
    if (phiInsn.getArgsCount() != 2 || !phiInsn.containsVar(incrArg) || incrArg.getSVar().getUseCount() != 1) {
        return false;
    }
    RegisterArg arg = phiInsn.getResult();
    List<RegisterArg> condArgs = condition.getRegisterArgs();
    if (!condArgs.contains(arg) || arg.getSVar().isUsedInPhi()) {
        return false;
    }
    RegisterArg initArg = phiInsn.getArg(0);
    InsnNode initInsn = initArg.getAssignInsn();
    if (initInsn == null || initInsn.contains(AFlag.DONT_GENERATE) || initArg.getSVar().getUseCount() != 1) {
        return false;
    }
    if (!usedOnlyInLoop(mth, loopRegion, arg)) {
        return false;
    }
    // can't make loop if argument from increment instruction is assign in loop
    List<RegisterArg> args = new LinkedList<>();
    incrInsn.getRegisterArgs(args);
    for (RegisterArg iArg : args) {
        try {
            if (assignOnlyInLoop(mth, loopRegion, iArg)) {
                return false;
            }
        } catch (StackOverflowError error) {
            throw new JadxOverflowException("LoopRegionVisitor.assignOnlyInLoop endless recursion");
        }
    }
    // all checks passed
    initInsn.add(AFlag.DONT_GENERATE);
    incrInsn.add(AFlag.DONT_GENERATE);
    LoopType arrForEach = checkArrayForEach(mth, loopRegion, initInsn, incrInsn, condition);
    loopRegion.setType(arrForEach != null ? arrForEach : new ForLoop(initInsn, incrInsn));
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) PhiInsn(jadx.core.dex.instructions.PhiInsn) ForLoop(jadx.core.dex.regions.loops.ForLoop) LoopType(jadx.core.dex.regions.loops.LoopType) JadxOverflowException(jadx.core.utils.exceptions.JadxOverflowException) LinkedList(java.util.LinkedList)

Example 97 with BlockNode

use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.

the class BlockProcessor method computeBlockDF.

private static void computeBlockDF(MethodNode mth, BlockNode block) {
    if (block.getDomFrontier() != null) {
        return;
    }
    List<BlockNode> blocks = mth.getBasicBlocks();
    BitSet domFrontier = null;
    for (BlockNode s : block.getSuccessors()) {
        if (s.getIDom() != block) {
            if (domFrontier == null) {
                domFrontier = new BitSet(blocks.size());
            }
            domFrontier.set(s.getId());
        }
    }
    for (BlockNode c : block.getDominatesOn()) {
        BitSet frontier = c.getDomFrontier();
        if (frontier == null) {
            throw new JadxRuntimeException("Dominance frontier not calculated for dominated block: " + c + ", from: " + block);
        }
        for (int p = frontier.nextSetBit(0); p >= 0; p = frontier.nextSetBit(p + 1)) {
            if (blocks.get(p).getIDom() != block) {
                if (domFrontier == null) {
                    domFrontier = new BitSet(blocks.size());
                }
                domFrontier.set(p);
            }
        }
    }
    if (domFrontier == null || domFrontier.isEmpty()) {
        domFrontier = EMPTY;
    }
    block.setDomFrontier(domFrontier);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) BitSet(java.util.BitSet) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException)

Example 98 with BlockNode

use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.

the class BlockProcessor method splitReturn.

/**
 * Splice return block if several predecessors presents
 */
private static boolean splitReturn(MethodNode mth, BlockNode returnBlock) {
    if (returnBlock.contains(AFlag.SYNTHETIC) || returnBlock.contains(AFlag.ORIG_RETURN) || returnBlock.contains(AType.EXC_HANDLER)) {
        return false;
    }
    List<BlockNode> preds = returnBlock.getPredecessors();
    if (preds.size() < 2) {
        return false;
    }
    InsnNode returnInsn = BlockUtils.getLastInsn(returnBlock);
    if (returnInsn == null) {
        return false;
    }
    if (returnInsn.getArgsCount() == 1 && returnBlock.getInstructions().size() == 1 && !isReturnArgAssignInPred(preds, returnInsn)) {
        return false;
    }
    boolean first = true;
    for (BlockNode pred : new ArrayList<>(preds)) {
        if (first) {
            returnBlock.add(AFlag.ORIG_RETURN);
            first = false;
        } else {
            BlockNode newRetBlock = BlockSplitter.startNewBlock(mth, -1);
            newRetBlock.add(AFlag.SYNTHETIC);
            newRetBlock.add(AFlag.RETURN);
            for (InsnNode oldInsn : returnBlock.getInstructions()) {
                InsnNode copyInsn = oldInsn.copyWithoutSsa();
                copyInsn.add(AFlag.SYNTHETIC);
                newRetBlock.getInstructions().add(copyInsn);
            }
            BlockSplitter.replaceConnection(pred, returnBlock, newRetBlock);
        }
    }
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) ArrayList(java.util.ArrayList)

Example 99 with BlockNode

use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.

the class BlockProcessor method mergeConstAndReturnBlocks.

private static void mergeConstAndReturnBlocks(MethodNode mth, BlockNode retBlock, BlockNode pred) {
    pred.getInstructions().addAll(retBlock.getInstructions());
    pred.copyAttributesFrom(retBlock);
    BlockSplitter.removeConnection(pred, retBlock);
    retBlock.getInstructions().clear();
    retBlock.add(AFlag.REMOVE);
    BlockNode exitBlock = mth.getExitBlock();
    BlockSplitter.removeConnection(retBlock, exitBlock);
    BlockSplitter.connect(pred, exitBlock);
    pred.updateCleanSuccessors();
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode)

Example 100 with BlockNode

use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.

the class BlockProcessor method updateExitBlockConnections.

private static void updateExitBlockConnections(MethodNode mth) {
    BlockNode exitBlock = mth.getExitBlock();
    BlockSplitter.removePredecessors(exitBlock);
    for (BlockNode block : mth.getBasicBlocks()) {
        if (block != exitBlock && block.getSuccessors().isEmpty() && !block.contains(AFlag.REMOVE)) {
            BlockSplitter.connect(block, exitBlock);
        }
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode)

Aggregations

BlockNode (jadx.core.dex.nodes.BlockNode)220 InsnNode (jadx.core.dex.nodes.InsnNode)91 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)43 ArrayList (java.util.ArrayList)41 BitSet (java.util.BitSet)31 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)29 InsnArg (jadx.core.dex.instructions.args.InsnArg)25 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)21 ExceptionHandler (jadx.core.dex.trycatch.ExceptionHandler)19 PhiInsn (jadx.core.dex.instructions.PhiInsn)14 SSAVar (jadx.core.dex.instructions.args.SSAVar)14 Nullable (org.jetbrains.annotations.Nullable)14 LoopInfo (jadx.core.dex.attributes.nodes.LoopInfo)13 IRegion (jadx.core.dex.nodes.IRegion)13 HashSet (java.util.HashSet)13 MethodNode (jadx.core.dex.nodes.MethodNode)12 Region (jadx.core.dex.regions.Region)12 LoopRegion (jadx.core.dex.regions.loops.LoopRegion)12 InsnType (jadx.core.dex.instructions.InsnType)11 SynchronizedRegion (jadx.core.dex.regions.SynchronizedRegion)11