Search in sources :

Example 1 with SplitterBlockAttr

use of jadx.core.dex.trycatch.SplitterBlockAttr in project jadx by skylot.

the class ProcessTryCatchRegions method searchTryCatchDominators.

private static void searchTryCatchDominators(MethodNode mth, Map<BlockNode, TryCatchBlock> tryBlocksMap) {
    Set<TryCatchBlock> tryBlocks = new HashSet<TryCatchBlock>();
    // collect all try/catch blocks
    for (BlockNode block : mth.getBasicBlocks()) {
        CatchAttr c = block.get(AType.CATCH_BLOCK);
        if (c != null) {
            tryBlocks.add(c.getTryBlock());
        }
    }
    // for each try block search nearest dominator block
    for (TryCatchBlock tb : tryBlocks) {
        if (tb.getHandlersCount() == 0) {
            LOG.warn("No exception handlers in catch block, method: {}", mth);
            continue;
        }
        BitSet bs = new BitSet(mth.getBasicBlocks().size());
        for (ExceptionHandler excHandler : tb.getHandlers()) {
            SplitterBlockAttr splitter = excHandler.getHandlerBlock().get(AType.SPLITTER_BLOCK);
            if (splitter != null) {
                BlockNode block = splitter.getBlock();
                bs.set(block.getId());
            }
        }
        List<BlockNode> domBlocks = BlockUtils.bitSetToBlocks(mth, bs);
        BlockNode domBlock;
        if (domBlocks.size() != 1) {
            domBlock = BlockUtils.getTopBlock(domBlocks);
            if (domBlock == null) {
                throw new JadxRuntimeException("Exception block dominator not found, method:" + mth + ". bs: " + domBlocks);
            }
        } else {
            domBlock = domBlocks.get(0);
        }
        TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb);
        if (prevTB != null) {
            ErrorsCounter.methodError(mth, "Failed to process nested try/catch");
        }
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) SplitterBlockAttr(jadx.core.dex.trycatch.SplitterBlockAttr) BitSet(java.util.BitSet) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) CatchAttr(jadx.core.dex.trycatch.CatchAttr) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) HashSet(java.util.HashSet)

Example 2 with SplitterBlockAttr

use of jadx.core.dex.trycatch.SplitterBlockAttr in project jadx by skylot.

the class RegionMaker method processExcHandler.

private void processExcHandler(ExceptionHandler handler, Set<BlockNode> exits) {
    BlockNode start = handler.getHandlerBlock();
    if (start == null) {
        return;
    }
    RegionStack stack = new RegionStack(mth);
    BlockNode dom;
    if (handler.isFinally()) {
        SplitterBlockAttr splitterAttr = start.get(AType.SPLITTER_BLOCK);
        if (splitterAttr == null) {
            return;
        }
        dom = splitterAttr.getBlock();
    } else {
        dom = start;
        stack.addExits(exits);
    }
    BitSet domFrontier = dom.getDomFrontier();
    List<BlockNode> handlerExits = BlockUtils.bitSetToBlocks(mth, domFrontier);
    boolean inLoop = mth.getLoopForBlock(start) != null;
    for (BlockNode exit : handlerExits) {
        if ((!inLoop || BlockUtils.isPathExists(start, exit)) && RegionUtils.isRegionContainsBlock(mth.getRegion(), exit)) {
            stack.addExit(exit);
        }
    }
    handler.setHandlerRegion(makeRegion(start, stack));
    ExcHandlerAttr excHandlerAttr = start.get(AType.EXC_HANDLER);
    if (excHandlerAttr == null) {
        LOG.warn("Missing exception handler attribute for start block");
    } else {
        handler.getHandlerRegion().addAttr(excHandlerAttr);
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) SplitterBlockAttr(jadx.core.dex.trycatch.SplitterBlockAttr) BitSet(java.util.BitSet)

Example 3 with SplitterBlockAttr

use of jadx.core.dex.trycatch.SplitterBlockAttr in project jadx by skylot.

the class BlockFinallyExtract method extractFinally.

/**
	 * Search and remove common code from 'catch' and 'handlers'.
	 */
private static boolean extractFinally(MethodNode mth, ExceptionHandler handler) {
    int count = handler.getBlocks().size();
    BitSet bs = new BitSet(count);
    List<BlockNode> blocks = new ArrayList<BlockNode>(count);
    for (BlockNode block : handler.getBlocks()) {
        List<InsnNode> insns = block.getInstructions();
        if (!insns.isEmpty()) {
            if (insns.get(0).getType() != InsnType.MOVE_EXCEPTION) {
                blocks.add(block);
            }
            bs.set(block.getId());
        }
    }
    if (blocks.isEmpty()) {
        // nothing to do
        return false;
    }
    List<BlocksRemoveInfo> removes = new LinkedList<BlocksRemoveInfo>();
    Set<BlockNode> splitters = new HashSet<BlockNode>();
    // remove 'finally' from handlers
    TryCatchBlock tryBlock = handler.getTryBlock();
    if (tryBlock.getHandlersCount() > 1) {
        for (ExceptionHandler otherHandler : tryBlock.getHandlers()) {
            if (otherHandler == handler) {
                continue;
            }
            for (BlockNode hb : otherHandler.getBlocks()) {
                BlocksRemoveInfo removeInfo = removeInsns(mth, hb, blocks, bs);
                if (removeInfo != null) {
                    removes.add(removeInfo);
                    break;
                }
            }
        }
        if (removes.size() != tryBlock.getHandlersCount() - 1) {
            return false;
        }
    }
    for (ExceptionHandler otherHandler : tryBlock.getHandlers()) {
        SplitterBlockAttr splitterAttr = otherHandler.getHandlerBlock().get(AType.SPLITTER_BLOCK);
        if (splitterAttr != null) {
            BlockNode splBlock = splitterAttr.getBlock();
            if (!splBlock.getCleanSuccessors().isEmpty()) {
                splitters.add(splBlock);
            }
        }
    }
    // remove 'finally' from 'try' blocks (dominated by splitter block)
    boolean removed = false;
    for (BlockNode splitter : splitters) {
        BlockNode start = splitter.getCleanSuccessors().get(0);
        List<BlockNode> list = BlockUtils.collectBlocksDominatedBy(splitter, start);
        for (BlockNode block : list) {
            if (bs.get(block.getId())) {
                continue;
            }
            BlocksRemoveInfo removeInfo = removeInsns(mth, block, blocks, bs);
            if (removeInfo != null) {
                removes.add(removeInfo);
                removed = true;
                break;
            }
        }
    }
    if (!removed) {
        return false;
    }
    // 'finally' extract confirmed, run remove steps
    LiveVarAnalysis laBefore = null;
    boolean runReMap = isReMapNeeded(removes);
    if (runReMap) {
        laBefore = new LiveVarAnalysis(mth);
        laBefore.runAnalysis();
    }
    for (BlocksRemoveInfo removeInfo : removes) {
        if (!applyRemove(mth, removeInfo)) {
            return false;
        }
    }
    LiveVarAnalysis laAfter = null;
    // remove 'move-exception' instruction
    BlockNode handlerBlock = handler.getHandlerBlock();
    InsnNode me = BlockUtils.getLastInsn(handlerBlock);
    if (me != null && me.getType() == InsnType.MOVE_EXCEPTION) {
        boolean replaced = false;
        List<InsnNode> insnsList = handlerBlock.getInstructions();
        if (!handlerBlock.getCleanSuccessors().isEmpty()) {
            laAfter = new LiveVarAnalysis(mth);
            laAfter.runAnalysis();
            RegisterArg resArg = me.getResult();
            BlockNode succ = handlerBlock.getCleanSuccessors().get(0);
            if (laAfter.isLive(succ, resArg.getRegNum())) {
                // kill variable
                InsnNode kill = new InsnNode(InsnType.NOP, 0);
                kill.setResult(resArg);
                kill.add(AFlag.REMOVE);
                insnsList.set(insnsList.size() - 1, kill);
                replaced = true;
            }
        }
        if (!replaced) {
            insnsList.remove(insnsList.size() - 1);
            handlerBlock.add(AFlag.SKIP);
        }
    }
    // generate 'move' instruction for mapped register pairs
    if (runReMap) {
        if (laAfter == null) {
            laAfter = new LiveVarAnalysis(mth);
            laAfter.runAnalysis();
        }
        performVariablesReMap(mth, removes, laBefore, laAfter);
    }
    handler.setFinally(true);
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SplitterBlockAttr(jadx.core.dex.trycatch.SplitterBlockAttr) LiveVarAnalysis(jadx.core.dex.visitors.ssa.LiveVarAnalysis) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) BlocksRemoveInfo(jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo) HashSet(java.util.HashSet)

Example 4 with SplitterBlockAttr

use of jadx.core.dex.trycatch.SplitterBlockAttr in project jadx by skylot.

the class BlockSplitter method connectExceptionHandlers.

private static void connectExceptionHandlers(Map<Integer, BlockNode> blocksMap, BlockNode block, InsnNode insn) {
    CatchAttr catches = insn.get(AType.CATCH_BLOCK);
    SplitterBlockAttr spl = block.get(AType.SPLITTER_BLOCK);
    if (catches == null || spl == null) {
        return;
    }
    BlockNode splitterBlock = spl.getBlock();
    boolean tryEnd = insn.contains(AFlag.TRY_LEAVE);
    for (ExceptionHandler h : catches.getTryBlock().getHandlers()) {
        BlockNode handlerBlock = getBlock(h.getHandleOffset(), blocksMap);
        // skip self loop in handler
        if (splitterBlock != handlerBlock) {
            if (!handlerBlock.contains(AType.SPLITTER_BLOCK)) {
                handlerBlock.addAttr(spl);
            }
            connect(splitterBlock, handlerBlock);
        }
        if (tryEnd) {
            connect(block, handlerBlock);
        }
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) SplitterBlockAttr(jadx.core.dex.trycatch.SplitterBlockAttr) CatchAttr(jadx.core.dex.trycatch.CatchAttr)

Example 5 with SplitterBlockAttr

use of jadx.core.dex.trycatch.SplitterBlockAttr in project jadx by skylot.

the class BlockFinish method fixSplitterBlock.

/**
	 * For evey exception handler must be only one splitter block,
	 * select correct one and remove others if necessary.
	 */
private static void fixSplitterBlock(BlockNode block) {
    ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
    if (excHandlerAttr == null) {
        return;
    }
    BlockNode handlerBlock = excHandlerAttr.getHandler().getHandlerBlock();
    if (handlerBlock.getPredecessors().size() < 2) {
        return;
    }
    Map<BlockNode, SplitterBlockAttr> splitters = new HashMap<BlockNode, SplitterBlockAttr>();
    for (BlockNode pred : handlerBlock.getPredecessors()) {
        pred = BlockUtils.skipSyntheticPredecessor(pred);
        SplitterBlockAttr splitterAttr = pred.get(AType.SPLITTER_BLOCK);
        if (splitterAttr != null && pred == splitterAttr.getBlock()) {
            splitters.put(pred, splitterAttr);
        }
    }
    if (splitters.size() < 2) {
        return;
    }
    BlockNode topSplitter = BlockUtils.getTopBlock(splitters.keySet());
    if (topSplitter == null) {
        LOG.warn("Unknown top splitter block from list: {}", splitters);
        return;
    }
    for (Map.Entry<BlockNode, SplitterBlockAttr> entry : splitters.entrySet()) {
        BlockNode pred = entry.getKey();
        SplitterBlockAttr splitterAttr = entry.getValue();
        if (pred == topSplitter) {
            block.addAttr(splitterAttr);
        } else {
            pred.remove(AType.SPLITTER_BLOCK);
            for (BlockNode s : pred.getCleanSuccessors()) {
                s.remove(AType.SPLITTER_BLOCK);
            }
        }
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) SplitterBlockAttr(jadx.core.dex.trycatch.SplitterBlockAttr) HashMap(java.util.HashMap) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

BlockNode (jadx.core.dex.nodes.BlockNode)6 SplitterBlockAttr (jadx.core.dex.trycatch.SplitterBlockAttr)6 ExceptionHandler (jadx.core.dex.trycatch.ExceptionHandler)3 BitSet (java.util.BitSet)3 InsnNode (jadx.core.dex.nodes.InsnNode)2 CatchAttr (jadx.core.dex.trycatch.CatchAttr)2 ExcHandlerAttr (jadx.core.dex.trycatch.ExcHandlerAttr)2 TryCatchBlock (jadx.core.dex.trycatch.TryCatchBlock)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 InsnType (jadx.core.dex.instructions.InsnType)1 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)1 BlocksRemoveInfo (jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo)1 LiveVarAnalysis (jadx.core.dex.visitors.ssa.LiveVarAnalysis)1 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1