Search in sources :

Example 31 with BlockNode

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

the class BlockExceptionHandler method removeMonitorExitFromExcHandler.

private static void removeMonitorExitFromExcHandler(MethodNode mth, ExceptionHandler excHandler) {
    for (BlockNode excBlock : excHandler.getBlocks()) {
        InsnRemover remover = new InsnRemover(mth, excBlock);
        for (InsnNode insn : excBlock.getInstructions()) {
            if (insn.getType() == InsnType.MONITOR_ENTER) {
                break;
            }
            if (insn.getType() == InsnType.MONITOR_EXIT) {
                remover.addAndUnbind(insn);
            }
        }
        remover.perform();
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) InsnRemover(jadx.core.utils.InsnRemover)

Example 32 with BlockNode

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

the class BlockExceptionHandler method checkTryCatchRelation.

private static boolean checkTryCatchRelation(List<TryCatchBlockAttr> tryBlocks, TryCatchBlockAttr outerTryBlock, TryCatchBlockAttr innerTryBlock) {
    if (outerTryBlock.getBlocks().equals(innerTryBlock.getBlocks())) {
        // same try blocks -> merge handlers
        List<ExceptionHandler> handlers = Utils.concatDistinct(outerTryBlock.getHandlers(), innerTryBlock.getHandlers());
        tryBlocks.add(new TryCatchBlockAttr(tryBlocks.size(), handlers, outerTryBlock.getBlocks()));
        tryBlocks.remove(outerTryBlock);
        tryBlocks.remove(innerTryBlock);
        return true;
    }
    Set<BlockNode> handlerBlocks = innerTryBlock.getHandlers().stream().flatMap(eh -> eh.getBlocks().stream()).collect(Collectors.toSet());
    boolean catchInHandler = handlerBlocks.stream().anyMatch(isHandlersIntersects(outerTryBlock));
    boolean catchInTry = innerTryBlock.getBlocks().stream().anyMatch(isHandlersIntersects(outerTryBlock));
    boolean blocksOutsideHandler = outerTryBlock.getBlocks().stream().anyMatch(b -> !handlerBlocks.contains(b));
    boolean makeInner = catchInHandler && (catchInTry || blocksOutsideHandler);
    if (makeInner && innerTryBlock.isAllHandler()) {
        // inner try block can't have catch-all handler
        outerTryBlock.setBlocks(Utils.concatDistinct(outerTryBlock.getBlocks(), innerTryBlock.getBlocks()));
        innerTryBlock.clear();
        return false;
    }
    if (makeInner) {
        // convert to inner
        List<BlockNode> mergedBlocks = Utils.concatDistinct(outerTryBlock.getBlocks(), innerTryBlock.getBlocks());
        innerTryBlock.getHandlers().removeAll(outerTryBlock.getHandlers());
        innerTryBlock.setOuterTryBlock(outerTryBlock);
        outerTryBlock.addInnerTryBlock(innerTryBlock);
        outerTryBlock.setBlocks(mergedBlocks);
        return false;
    }
    if (innerTryBlock.getHandlers().containsAll(outerTryBlock.getHandlers())) {
        // merge
        List<BlockNode> mergedBlocks = Utils.concatDistinct(outerTryBlock.getBlocks(), innerTryBlock.getBlocks());
        List<ExceptionHandler> handlers = Utils.concatDistinct(outerTryBlock.getHandlers(), innerTryBlock.getHandlers());
        tryBlocks.add(new TryCatchBlockAttr(tryBlocks.size(), handlers, mergedBlocks));
        tryBlocks.remove(outerTryBlock);
        tryBlocks.remove(innerTryBlock);
        return true;
    }
    return false;
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) BlockNode(jadx.core.dex.nodes.BlockNode) ArgType(jadx.core.dex.instructions.args.ArgType) MethodNode(jadx.core.dex.nodes.MethodNode) Consts(jadx.core.Consts) AType(jadx.core.dex.attributes.AType) AFlag(jadx.core.dex.attributes.AFlag) TmpEdgeAttr(jadx.core.dex.attributes.nodes.TmpEdgeAttr) LoggerFactory(org.slf4j.LoggerFactory) InsnType(jadx.core.dex.instructions.InsnType) CatchAttr(jadx.core.dex.trycatch.CatchAttr) HashMap(java.util.HashMap) ClassInfo(jadx.core.dex.info.ClassInfo) Deque(java.util.Deque) BlockUtils(jadx.core.utils.BlockUtils) NamedArg(jadx.core.dex.instructions.args.NamedArg) ArrayList(java.util.ArrayList) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) Utils(jadx.api.plugins.utils.Utils) ListUtils(jadx.core.utils.ListUtils) Map(java.util.Map) InsnNode(jadx.core.dex.nodes.InsnNode) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr) InsnArg(jadx.core.dex.instructions.args.InsnArg) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) Logger(org.slf4j.Logger) Predicate(java.util.function.Predicate) Set(java.util.Set) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) TypeCompare(jadx.core.dex.visitors.typeinference.TypeCompare) ArrayDeque(java.util.ArrayDeque) Comparator(java.util.Comparator) NotNull(org.jetbrains.annotations.NotNull) InsnRemover(jadx.core.utils.InsnRemover) Collections(java.util.Collections) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr)

Example 33 with BlockNode

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

the class BlockExceptionHandler method prepareTryBlocks.

private static List<TryCatchBlockAttr> prepareTryBlocks(MethodNode mth) {
    Map<ExceptionHandler, List<BlockNode>> blocksByHandler = new HashMap<>();
    for (BlockNode block : mth.getBasicBlocks()) {
        CatchAttr catchAttr = block.get(AType.EXC_CATCH);
        if (catchAttr != null) {
            for (ExceptionHandler eh : catchAttr.getHandlers()) {
                blocksByHandler.computeIfAbsent(eh, c -> new ArrayList<>()).add(block);
            }
        }
    }
    if (Consts.DEBUG_EXC_HANDLERS) {
        LOG.debug("Input exception handlers:");
        blocksByHandler.forEach((eh, blocks) -> LOG.debug(" {}, throw blocks: {}, handler blocks: {}", eh, blocks, eh.getBlocks()));
    }
    if (blocksByHandler.isEmpty()) {
        // no catch blocks -> remove all handlers
        mth.getExceptionHandlers().forEach(eh -> removeExcHandler(mth, eh));
    } else {
        // remove handlers without blocks in catch attribute
        blocksByHandler.forEach((eh, blocks) -> {
            if (blocks.isEmpty()) {
                removeExcHandler(mth, eh);
            }
        });
    }
    BlockSplitter.detachMarkedBlocks(mth);
    mth.clearExceptionHandlers();
    if (mth.isNoExceptionHandlers()) {
        return Collections.emptyList();
    }
    blocksByHandler.forEach((eh, blocks) -> {
        // remove catches from same handler
        blocks.removeAll(eh.getBlocks());
    });
    List<TryCatchBlockAttr> tryBlocks = new ArrayList<>();
    blocksByHandler.forEach((eh, blocks) -> {
        List<ExceptionHandler> handlers = new ArrayList<>(1);
        handlers.add(eh);
        tryBlocks.add(new TryCatchBlockAttr(tryBlocks.size(), handlers, blocks));
    });
    if (tryBlocks.size() > 1) {
        // merge or mark as outer/inner
        while (true) {
            boolean restart = combineTryCatchBlocks(tryBlocks);
            if (!restart) {
                break;
            }
        }
    }
    checkForMultiCatch(mth, tryBlocks);
    clearTryBlocks(mth, tryBlocks);
    sortHandlers(mth, tryBlocks);
    if (Consts.DEBUG_EXC_HANDLERS) {
        LOG.debug("Result try-catch blocks:");
        tryBlocks.forEach(tryBlock -> LOG.debug(" {}", tryBlock));
    }
    return tryBlocks;
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) BlockNode(jadx.core.dex.nodes.BlockNode) ArgType(jadx.core.dex.instructions.args.ArgType) MethodNode(jadx.core.dex.nodes.MethodNode) Consts(jadx.core.Consts) AType(jadx.core.dex.attributes.AType) AFlag(jadx.core.dex.attributes.AFlag) TmpEdgeAttr(jadx.core.dex.attributes.nodes.TmpEdgeAttr) LoggerFactory(org.slf4j.LoggerFactory) InsnType(jadx.core.dex.instructions.InsnType) CatchAttr(jadx.core.dex.trycatch.CatchAttr) HashMap(java.util.HashMap) ClassInfo(jadx.core.dex.info.ClassInfo) Deque(java.util.Deque) BlockUtils(jadx.core.utils.BlockUtils) NamedArg(jadx.core.dex.instructions.args.NamedArg) ArrayList(java.util.ArrayList) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) Utils(jadx.api.plugins.utils.Utils) ListUtils(jadx.core.utils.ListUtils) Map(java.util.Map) InsnNode(jadx.core.dex.nodes.InsnNode) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr) InsnArg(jadx.core.dex.instructions.args.InsnArg) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) Logger(org.slf4j.Logger) Predicate(java.util.function.Predicate) Set(java.util.Set) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) TypeCompare(jadx.core.dex.visitors.typeinference.TypeCompare) ArrayDeque(java.util.ArrayDeque) Comparator(java.util.Comparator) NotNull(org.jetbrains.annotations.NotNull) InsnRemover(jadx.core.utils.InsnRemover) Collections(java.util.Collections) HashMap(java.util.HashMap) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) CatchAttr(jadx.core.dex.trycatch.CatchAttr)

Example 34 with BlockNode

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

the class BlockExceptionHandler method initExcHandlers.

@SuppressWarnings("ForLoopReplaceableByForEach")
private static void initExcHandlers(MethodNode mth) {
    List<BlockNode> blocks = mth.getBasicBlocks();
    int blocksCount = blocks.size();
    for (int i = 0; i < blocksCount; i++) {
        // will add new blocks to list end
        BlockNode block = blocks.get(i);
        InsnNode firstInsn = BlockUtils.getFirstInsn(block);
        if (firstInsn == null) {
            continue;
        }
        ExcHandlerAttr excHandlerAttr = firstInsn.get(AType.EXC_HANDLER);
        if (excHandlerAttr == null) {
            continue;
        }
        firstInsn.remove(AType.EXC_HANDLER);
        TmpEdgeAttr tmpEdgeAttr = block.get(AType.TMP_EDGE);
        if (tmpEdgeAttr != null) {
            // remove temp connection
            BlockSplitter.removeConnection(tmpEdgeAttr.getBlock(), block);
            block.remove(AType.TMP_EDGE);
        }
        ExceptionHandler excHandler = excHandlerAttr.getHandler();
        if (block.getPredecessors().isEmpty()) {
            excHandler.setHandlerBlock(block);
            block.addAttr(excHandlerAttr);
            excHandler.addBlock(block);
            BlockUtils.collectBlocksDominatedByWithExcHandlers(mth, block, block).forEach(excHandler::addBlock);
        } else {
            // ignore already connected handlers -> make catch empty
            BlockNode emptyHandlerBlock = BlockSplitter.startNewBlock(mth, block.getStartOffset());
            emptyHandlerBlock.add(AFlag.SYNTHETIC);
            emptyHandlerBlock.addAttr(excHandlerAttr);
            BlockSplitter.connect(emptyHandlerBlock, block);
            excHandler.setHandlerBlock(emptyHandlerBlock);
            excHandler.addBlock(emptyHandlerBlock);
        }
        fixMoveExceptionInsn(block, excHandlerAttr);
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) InsnNode(jadx.core.dex.nodes.InsnNode) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) TmpEdgeAttr(jadx.core.dex.attributes.nodes.TmpEdgeAttr)

Example 35 with BlockNode

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

the class BlockExceptionHandler method wrapBlocksWithTryCatch.

private static boolean wrapBlocksWithTryCatch(MethodNode mth, TryCatchBlockAttr tryCatchBlock) {
    List<BlockNode> blocks = tryCatchBlock.getBlocks();
    BlockNode top = searchTopBlock(mth, blocks);
    if (top.getPredecessors().isEmpty() && top != mth.getEnterBlock()) {
        return false;
    }
    BlockNode bottom = searchBottomBlock(mth, blocks);
    if (Consts.DEBUG_EXC_HANDLERS) {
        LOG.debug("TryCatch #{} split: top {}, bottom: {}", tryCatchBlock.id(), top, bottom);
    }
    BlockNode topSplitterBlock = getTopSplitterBlock(mth, top);
    topSplitterBlock.add(AFlag.EXC_TOP_SPLITTER);
    topSplitterBlock.add(AFlag.SYNTHETIC);
    int totalHandlerBlocks = tryCatchBlock.getHandlers().stream().mapToInt(eh -> eh.getBlocks().size()).sum();
    BlockNode bottomSplitterBlock;
    if (bottom == null || totalHandlerBlocks == 0) {
        bottomSplitterBlock = null;
    } else {
        BlockNode existBottomSplitter = BlockUtils.getBlockWithFlag(bottom.getSuccessors(), AFlag.EXC_BOTTOM_SPLITTER);
        bottomSplitterBlock = existBottomSplitter != null ? existBottomSplitter : BlockSplitter.startNewBlock(mth, -1);
        bottomSplitterBlock.add(AFlag.EXC_BOTTOM_SPLITTER);
        bottomSplitterBlock.add(AFlag.SYNTHETIC);
        BlockSplitter.connect(bottom, bottomSplitterBlock);
    }
    if (Consts.DEBUG_EXC_HANDLERS) {
        LOG.debug("TryCatch #{} result splitters: top {}, bottom: {}", tryCatchBlock.id(), topSplitterBlock, bottomSplitterBlock);
    }
    connectSplittersAndHandlers(tryCatchBlock, topSplitterBlock, bottomSplitterBlock);
    for (BlockNode block : blocks) {
        TryCatchBlockAttr currentTCBAttr = block.get(AType.TRY_BLOCK);
        if (currentTCBAttr == null || currentTCBAttr.getInnerTryBlocks().contains(tryCatchBlock)) {
            block.addAttr(tryCatchBlock);
        }
    }
    tryCatchBlock.setTopSplitter(topSplitterBlock);
    topSplitterBlock.updateCleanSuccessors();
    if (bottomSplitterBlock != null) {
        bottomSplitterBlock.updateCleanSuccessors();
    }
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ArgType(jadx.core.dex.instructions.args.ArgType) MethodNode(jadx.core.dex.nodes.MethodNode) Consts(jadx.core.Consts) AType(jadx.core.dex.attributes.AType) AFlag(jadx.core.dex.attributes.AFlag) TmpEdgeAttr(jadx.core.dex.attributes.nodes.TmpEdgeAttr) LoggerFactory(org.slf4j.LoggerFactory) InsnType(jadx.core.dex.instructions.InsnType) CatchAttr(jadx.core.dex.trycatch.CatchAttr) HashMap(java.util.HashMap) ClassInfo(jadx.core.dex.info.ClassInfo) Deque(java.util.Deque) BlockUtils(jadx.core.utils.BlockUtils) NamedArg(jadx.core.dex.instructions.args.NamedArg) ArrayList(java.util.ArrayList) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) Utils(jadx.api.plugins.utils.Utils) ListUtils(jadx.core.utils.ListUtils) Map(java.util.Map) InsnNode(jadx.core.dex.nodes.InsnNode) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr) InsnArg(jadx.core.dex.instructions.args.InsnArg) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) Logger(org.slf4j.Logger) Predicate(java.util.function.Predicate) Set(java.util.Set) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) TypeCompare(jadx.core.dex.visitors.typeinference.TypeCompare) ArrayDeque(java.util.ArrayDeque) Comparator(java.util.Comparator) NotNull(org.jetbrains.annotations.NotNull) InsnRemover(jadx.core.utils.InsnRemover) Collections(java.util.Collections) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr)

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