Search in sources :

Example 81 with BlockNode

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

the class RegionMaker method calcPostDomOut.

@Nullable
private static BlockNode calcPostDomOut(MethodNode mth, BlockNode block, List<BlockNode> exits) {
    if (exits.size() == 1 && mth.getExitBlock().equals(exits.get(0))) {
        // simple case: for only one exit which is equal to method exit block
        return BlockUtils.calcImmediatePostDominator(mth, block);
    }
    // fast search: union of blocks dominance frontier
    // work if no fallthrough cases and no returns inside switch
    BitSet outs = BlockUtils.copyBlocksBitSet(mth, block.getDomFrontier());
    for (BlockNode s : block.getCleanSuccessors()) {
        outs.or(s.getDomFrontier());
    }
    outs.clear(block.getId());
    if (outs.cardinality() != 1) {
        // slow search: calculate partial post-dominance for every exit node
        BitSet ipdoms = BlockUtils.newBlocksBitSet(mth);
        for (BlockNode exitBlock : exits) {
            if (BlockUtils.isAnyPathExists(block, exitBlock)) {
                Set<BlockNode> pathBlocks = BlockUtils.getAllPathsBlocks(block, exitBlock);
                BlockNode ipdom = BlockUtils.calcPartialImmediatePostDominator(mth, block, pathBlocks, exitBlock);
                if (ipdom != null) {
                    ipdoms.set(ipdom.getId());
                }
            }
        }
        outs.and(ipdoms);
    }
    return BlockUtils.bitSetToOneBlock(mth, outs);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) BitSet(java.util.BitSet) Nullable(org.jetbrains.annotations.Nullable)

Example 82 with BlockNode

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

the class RegionMaker method processTryCatchBlocks.

public IRegion processTryCatchBlocks(MethodNode mth) {
    List<TryCatchBlockAttr> tcs = mth.getAll(AType.TRY_BLOCKS_LIST);
    for (TryCatchBlockAttr tc : tcs) {
        List<BlockNode> blocks = new ArrayList<>(tc.getHandlersCount());
        Set<BlockNode> splitters = new HashSet<>();
        for (ExceptionHandler handler : tc.getHandlers()) {
            BlockNode handlerBlock = handler.getHandlerBlock();
            if (handlerBlock != null) {
                blocks.add(handlerBlock);
                splitters.add(BlockUtils.getTopSplitterForHandler(handlerBlock));
            } else {
                mth.addDebugComment("No exception handler block: " + handler);
            }
        }
        Set<BlockNode> exits = new HashSet<>();
        for (BlockNode splitter : splitters) {
            for (BlockNode handler : blocks) {
                if (handler.contains(AFlag.REMOVE)) {
                    continue;
                }
                List<BlockNode> s = splitter.getSuccessors();
                if (s.isEmpty()) {
                    mth.addDebugComment("No successors for splitter: " + splitter);
                    continue;
                }
                BlockNode ss = s.get(0);
                BlockNode cross = BlockUtils.getPathCross(mth, ss, handler);
                if (cross != null && cross != ss && cross != handler) {
                    exits.add(cross);
                }
            }
        }
        for (ExceptionHandler handler : tc.getHandlers()) {
            processExcHandler(mth, handler, exits);
        }
    }
    return processHandlersOutBlocks(mth, tcs);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) TryCatchBlockAttr(jadx.core.dex.trycatch.TryCatchBlockAttr) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 83 with BlockNode

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

the class RegionMaker method isEmptySyntheticPath.

private static boolean isEmptySyntheticPath(BlockNode b1, BlockNode b2) {
    BlockNode n1 = followEmptyPath(b1);
    BlockNode n2 = followEmptyPath(b2);
    return n1 == n2 || isEqualReturnBlocks(n1, n2);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode)

Example 84 with BlockNode

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

the class RegionMaker method processLoop.

private BlockNode processLoop(IRegion curRegion, LoopInfo loop, RegionStack stack) {
    BlockNode loopStart = loop.getStart();
    Set<BlockNode> exitBlocksSet = loop.getExitNodes();
    // set exit blocks scan order priority
    // this can help if loop have several exits (after using 'break' or 'return' in loop)
    List<BlockNode> exitBlocks = new ArrayList<>(exitBlocksSet.size());
    BlockNode nextStart = getNextBlock(loopStart);
    if (nextStart != null && exitBlocksSet.remove(nextStart)) {
        exitBlocks.add(nextStart);
    }
    if (exitBlocksSet.remove(loopStart)) {
        exitBlocks.add(loopStart);
    }
    if (exitBlocksSet.remove(loop.getEnd())) {
        exitBlocks.add(loop.getEnd());
    }
    exitBlocks.addAll(exitBlocksSet);
    LoopRegion loopRegion = makeLoopRegion(curRegion, loop, exitBlocks);
    if (loopRegion == null) {
        BlockNode exit = makeEndlessLoop(curRegion, stack, loop, loopStart);
        insertContinue(loop);
        return exit;
    }
    curRegion.getSubBlocks().add(loopRegion);
    IRegion outerRegion = stack.peekRegion();
    stack.push(loopRegion);
    IfInfo condInfo = makeIfInfo(mth, loopRegion.getHeader());
    condInfo = searchNestedIf(condInfo);
    confirmMerge(condInfo);
    if (!loop.getLoopBlocks().contains(condInfo.getThenBlock())) {
        // invert loop condition if 'then' points to exit
        condInfo = IfInfo.invert(condInfo);
    }
    loopRegion.updateCondition(condInfo);
    exitBlocks.removeAll(condInfo.getMergedBlocks());
    if (!exitBlocks.isEmpty()) {
        BlockNode loopExit = condInfo.getElseBlock();
        if (loopExit != null) {
            // add 'break' instruction before path cross between main loop exit and sub-exit
            for (Edge exitEdge : loop.getExitEdges()) {
                if (exitBlocks.contains(exitEdge.getSource())) {
                    insertLoopBreak(stack, loop, loopExit, exitEdge);
                }
            }
        }
    }
    BlockNode out;
    if (loopRegion.isConditionAtEnd()) {
        BlockNode thenBlock = condInfo.getThenBlock();
        out = thenBlock == loopStart ? condInfo.getElseBlock() : thenBlock;
        loopStart.remove(AType.LOOP);
        loop.getEnd().add(AFlag.ADDED_TO_REGION);
        stack.addExit(loop.getEnd());
        processedBlocks.clear(loopStart.getId());
        Region body = makeRegion(loopStart, stack);
        loopRegion.setBody(body);
        loopStart.addAttr(AType.LOOP, loop);
        loop.getEnd().remove(AFlag.ADDED_TO_REGION);
    } else {
        out = condInfo.getElseBlock();
        if (outerRegion != null && out.contains(AFlag.LOOP_START) && !out.getAll(AType.LOOP).contains(loop) && RegionUtils.isRegionContainsBlock(outerRegion, out)) {
            // exit to already processed outer loop
            out = null;
        }
        stack.addExit(out);
        BlockNode loopBody = condInfo.getThenBlock();
        Region body;
        if (Objects.equals(loopBody, loopStart)) {
            // empty loop body
            body = new Region(loopRegion);
        } else {
            body = makeRegion(loopBody, stack);
        }
        // add blocks from loop start to first condition block
        BlockNode conditionBlock = condInfo.getFirstIfBlock();
        if (loopStart != conditionBlock) {
            Set<BlockNode> blocks = BlockUtils.getAllPathsBlocks(loopStart, conditionBlock);
            blocks.remove(conditionBlock);
            for (BlockNode block : blocks) {
                if (block.getInstructions().isEmpty() && !block.contains(AFlag.ADDED_TO_REGION) && !RegionUtils.isRegionContainsBlock(body, block)) {
                    body.add(block);
                }
            }
        }
        loopRegion.setBody(body);
    }
    stack.pop();
    insertContinue(loop);
    return out;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ArrayList(java.util.ArrayList) Region(jadx.core.dex.regions.Region) IRegion(jadx.core.dex.nodes.IRegion) SwitchRegion(jadx.core.dex.regions.SwitchRegion) SynchronizedRegion(jadx.core.dex.regions.SynchronizedRegion) LoopRegion(jadx.core.dex.regions.loops.LoopRegion) IfRegion(jadx.core.dex.regions.conditions.IfRegion) IfMakerHelper.makeIfInfo(jadx.core.dex.visitors.regions.IfMakerHelper.makeIfInfo) IfInfo(jadx.core.dex.regions.conditions.IfInfo) LoopRegion(jadx.core.dex.regions.loops.LoopRegion) Edge(jadx.core.dex.nodes.Edge) IRegion(jadx.core.dex.nodes.IRegion)

Example 85 with BlockNode

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

the class RegionMaker method makeRegion.

public Region makeRegion(BlockNode startBlock, RegionStack stack) {
    Region r = new Region(stack.peekRegion());
    if (startBlock == null) {
        return r;
    }
    if (stack.containsExit(startBlock)) {
        insertEdgeInsns(r, startBlock);
        return r;
    }
    int startBlockId = startBlock.getId();
    if (processedBlocks.get(startBlockId)) {
        mth.addWarn("Removed duplicated region for block: " + startBlock + ' ' + startBlock.getAttributesString());
        return r;
    }
    processedBlocks.set(startBlockId);
    BlockNode next = startBlock;
    while (next != null) {
        next = traverse(r, next, stack);
        regionsCount++;
        if (regionsCount > regionsLimit) {
            throw new JadxOverflowException("Regions count limit reached");
        }
    }
    return r;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) Region(jadx.core.dex.regions.Region) IRegion(jadx.core.dex.nodes.IRegion) SwitchRegion(jadx.core.dex.regions.SwitchRegion) SynchronizedRegion(jadx.core.dex.regions.SynchronizedRegion) LoopRegion(jadx.core.dex.regions.loops.LoopRegion) IfRegion(jadx.core.dex.regions.conditions.IfRegion) JadxOverflowException(jadx.core.utils.exceptions.JadxOverflowException)

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