Search in sources :

Example 51 with BlockNode

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

the class MarkFinallyVisitor method checkBlocksTree.

private static boolean checkBlocksTree(BlockNode dupBlock, BlockNode finallyBlock, InsnsSlice dupSlice, FinallyExtractInfo extractInfo) {
    InsnsSlice finallySlice = extractInfo.getFinallyInsnsSlice();
    List<BlockNode> finallyCS = getSuccessorsWithoutLoop(finallyBlock);
    List<BlockNode> dupCS = getSuccessorsWithoutLoop(dupBlock);
    if (finallyCS.size() == dupCS.size()) {
        for (int i = 0; i < finallyCS.size(); i++) {
            BlockNode finSBlock = finallyCS.get(i);
            BlockNode dupSBlock = dupCS.get(i);
            if (extractInfo.getAllHandlerBlocks().contains(finSBlock)) {
                if (!compareBlocks(dupSBlock, finSBlock, dupSlice, extractInfo)) {
                    return false;
                }
                if (!checkBlocksTree(dupSBlock, finSBlock, dupSlice, extractInfo)) {
                    return false;
                }
                dupSlice.addBlock(dupSBlock);
                finallySlice.addBlock(finSBlock);
            }
        }
    }
    dupSlice.setComplete(true);
    finallySlice.setComplete(true);
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode)

Example 52 with BlockNode

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

the class ModVisitor method iterativeRemoveStep.

private static void iterativeRemoveStep(MethodNode mth) {
    boolean changed;
    do {
        changed = false;
        for (BlockNode block : mth.getBasicBlocks()) {
            for (InsnNode insn : block.getInstructions()) {
                if (insn.getType() == InsnType.MOVE && insn.isAttrStorageEmpty() && isResultArgNotUsed(insn)) {
                    InsnRemover.remove(mth, block, insn);
                    changed = true;
                    break;
                }
            }
        }
    } while (changed);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode)

Example 53 with BlockNode

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

the class ModVisitor method removeStep.

/**
 * Remove unnecessary instructions
 */
private static void removeStep(MethodNode mth, InsnRemover remover) {
    for (BlockNode block : mth.getBasicBlocks()) {
        remover.setBlock(block);
        for (InsnNode insn : block.getInstructions()) {
            switch(insn.getType()) {
                case NOP:
                case GOTO:
                case NEW_INSTANCE:
                    remover.addAndUnbind(insn);
                    break;
                default:
                    if (insn.contains(AFlag.REMOVE)) {
                        remover.addAndUnbind(insn);
                    }
                    break;
            }
        }
        remover.perform();
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode)

Example 54 with BlockNode

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

the class MarkFinallyVisitor method extractFinally.

/**
 * Search and mark common code from 'try' block and 'handlers'.
 */
private static boolean extractFinally(MethodNode mth, TryCatchBlockAttr tryBlock, ExceptionHandler allHandler) {
    BlockNode handlerBlock = allHandler.getHandlerBlock();
    List<BlockNode> handlerBlocks = new ArrayList<>(BlockUtils.collectBlocksDominatedByWithExcHandlers(mth, handlerBlock, handlerBlock));
    // exclude block with 'move-exception'
    handlerBlocks.remove(handlerBlock);
    handlerBlocks.removeIf(b -> BlockUtils.checkLastInsnType(b, InsnType.THROW));
    if (handlerBlocks.isEmpty() || BlockUtils.isAllBlocksEmpty(handlerBlocks)) {
        // remove empty catch
        allHandler.getTryBlock().removeHandler(allHandler);
        return true;
    }
    BlockNode startBlock = Utils.getOne(handlerBlock.getCleanSuccessors());
    FinallyExtractInfo extractInfo = new FinallyExtractInfo(allHandler, startBlock, handlerBlocks);
    boolean hasInnerBlocks = !tryBlock.getInnerTryBlocks().isEmpty();
    List<ExceptionHandler> handlers;
    if (hasInnerBlocks) {
        // collect handlers from this and all inner blocks (intentionally not using recursive collect for
        // now)
        handlers = new ArrayList<>(tryBlock.getHandlers());
        for (TryCatchBlockAttr innerTryBlock : tryBlock.getInnerTryBlocks()) {
            handlers.addAll(innerTryBlock.getHandlers());
        }
    } else {
        handlers = tryBlock.getHandlers();
    }
    if (handlers.isEmpty()) {
        return false;
    }
    // search 'finally' instructions in other handlers
    for (ExceptionHandler otherHandler : handlers) {
        if (otherHandler == allHandler) {
            continue;
        }
        for (BlockNode checkBlock : otherHandler.getBlocks()) {
            if (searchDuplicateInsns(checkBlock, extractInfo)) {
                break;
            } else {
                extractInfo.getFinallyInsnsSlice().resetIncomplete();
            }
        }
    }
    boolean mergeInnerTryBlocks;
    int duplicatesCount = extractInfo.getDuplicateSlices().size();
    boolean fullTryBlock = duplicatesCount == (handlers.size() - 1);
    if (fullTryBlock) {
        // all collected handlers have duplicate block
        mergeInnerTryBlocks = hasInnerBlocks;
    } else {
        // some handlers don't have duplicated blocks
        if (!hasInnerBlocks || duplicatesCount != (tryBlock.getHandlers().size() - 1)) {
            // unexpected count of duplicated slices
            return false;
        }
        mergeInnerTryBlocks = false;
    }
    // remove 'finally' from 'try' blocks, check all up paths on each exit (connected with finally exit)
    List<BlockNode> tryBlocks = allHandler.getTryBlock().getBlocks();
    BlockNode bottomBlock = BlockUtils.getBottomBlock(allHandler.getBlocks());
    if (bottomBlock == null) {
        return false;
    }
    BlockNode bottomFinallyBlock = BlockUtils.followEmptyPath(bottomBlock);
    BlockNode bottom = BlockUtils.getNextBlock(bottomFinallyBlock);
    if (bottom == null) {
        return false;
    }
    boolean found = false;
    List<BlockNode> pathBlocks = getPathStarts(mth, bottom, bottomFinallyBlock);
    for (BlockNode pred : pathBlocks) {
        List<BlockNode> upPath = BlockUtils.collectPredecessors(mth, pred, tryBlocks);
        if (upPath.size() < handlerBlocks.size()) {
            continue;
        }
        for (BlockNode block : upPath) {
            if (searchDuplicateInsns(block, extractInfo)) {
                found = true;
                break;
            } else {
                extractInfo.getFinallyInsnsSlice().resetIncomplete();
            }
        }
    }
    if (!found) {
        return false;
    }
    if (!checkSlices(extractInfo)) {
        mth.addWarnComment("Finally extract failed");
        return false;
    }
    // 'finally' extract confirmed, apply
    apply(extractInfo);
    allHandler.setFinally(true);
    if (mergeInnerTryBlocks) {
        List<TryCatchBlockAttr> innerTryBlocks = tryBlock.getInnerTryBlocks();
        for (TryCatchBlockAttr innerTryBlock : innerTryBlocks) {
            tryBlock.getHandlers().addAll(innerTryBlock.getHandlers());
            tryBlock.getBlocks().addAll(innerTryBlock.getBlocks());
            innerTryBlock.setMerged(true);
        }
        tryBlock.setBlocks(ListUtils.distinctList(tryBlock.getBlocks()));
        innerTryBlocks.clear();
    }
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr) ArrayList(java.util.ArrayList)

Example 55 with BlockNode

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

the class CheckRegions method visit.

@Override
public void visit(MethodNode mth) throws JadxException {
    if (mth.isNoCode() || mth.getRegion() == null || mth.getBasicBlocks().isEmpty() || mth.contains(AType.JADX_ERROR)) {
        return;
    }
    // check if all blocks included in regions
    Set<BlockNode> blocksInRegions = new HashSet<>();
    DepthRegionTraversal.traverse(mth, new AbstractRegionVisitor() {

        @Override
        public void processBlock(MethodNode mth, IBlock container) {
            if (!(container instanceof BlockNode)) {
                return;
            }
            BlockNode block = (BlockNode) container;
            if (blocksInRegions.add(block)) {
                return;
            }
            if (LOG.isDebugEnabled() && !block.contains(AFlag.RETURN) && !block.contains(AFlag.REMOVE) && !block.contains(AFlag.SYNTHETIC) && !block.getInstructions().isEmpty()) {
                LOG.debug("Duplicated block: {} - {}", mth, block);
            }
        }
    });
    if (mth.getBasicBlocks().size() != blocksInRegions.size()) {
        for (BlockNode block : mth.getBasicBlocks()) {
            if (!blocksInRegions.contains(block) && !block.getInstructions().isEmpty() && !block.contains(AFlag.ADDED_TO_REGION) && !block.contains(AFlag.DONT_GENERATE) && !block.contains(AFlag.REMOVE)) {
                String blockCode = getBlockInsnStr(mth, block).replace("*/", "*\\/");
                mth.addWarn("Code restructure failed: missing block: " + block + ", code lost:" + blockCode);
            }
        }
    }
    DepthRegionTraversal.traverse(mth, new AbstractRegionVisitor() {

        @Override
        public boolean enterRegion(MethodNode mth, IRegion region) {
            if (region instanceof LoopRegion) {
                // check loop conditions
                BlockNode loopHeader = ((LoopRegion) region).getHeader();
                if (loopHeader != null && loopHeader.getInstructions().size() != 1) {
                    mth.addWarn("Incorrect condition in loop: " + loopHeader);
                }
            }
            return true;
        }
    });
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) IBlock(jadx.core.dex.nodes.IBlock) MethodNode(jadx.core.dex.nodes.MethodNode) LoopRegion(jadx.core.dex.regions.loops.LoopRegion) IRegion(jadx.core.dex.nodes.IRegion) HashSet(java.util.HashSet)

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