Search in sources :

Example 6 with TryCatchBlock

use of jadx.core.dex.trycatch.TryCatchBlock 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 7 with TryCatchBlock

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

the class RegionUtils method getExcHandlersForRegion.

public static List<IContainer> getExcHandlersForRegion(IContainer region) {
    CatchAttr cb = region.get(AType.CATCH_BLOCK);
    if (cb != null) {
        TryCatchBlock tb = cb.getTryBlock();
        List<IContainer> list = new ArrayList<IContainer>(tb.getHandlersCount());
        for (ExceptionHandler eh : tb.getHandlers()) {
            list.add(eh.getHandlerRegion());
        }
        return list;
    }
    return Collections.emptyList();
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) ArrayList(java.util.ArrayList) CatchAttr(jadx.core.dex.trycatch.CatchAttr) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) IContainer(jadx.core.dex.nodes.IContainer)

Example 8 with TryCatchBlock

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

the class BlockExceptionHandler method processExceptionHandlers.

private static void processExceptionHandlers(MethodNode mth, BlockNode block) {
    ExcHandlerAttr handlerAttr = block.get(AType.EXC_HANDLER);
    if (handlerAttr == null) {
        return;
    }
    ExceptionHandler excHandler = handlerAttr.getHandler();
    excHandler.addBlock(block);
    for (BlockNode node : BlockUtils.collectBlocksDominatedBy(block, block)) {
        excHandler.addBlock(node);
    }
    for (BlockNode excBlock : excHandler.getBlocks()) {
        // remove 'monitor-exit' from exception handler blocks
        InstructionRemover remover = new InstructionRemover(mth, excBlock);
        for (InsnNode insn : excBlock.getInstructions()) {
            if (insn.getType() == InsnType.MONITOR_ENTER) {
                break;
            }
            if (insn.getType() == InsnType.MONITOR_EXIT) {
                remover.add(insn);
            }
        }
        remover.perform();
        // if 'throw' in exception handler block have 'catch' - merge these catch blocks
        for (InsnNode insn : excBlock.getInstructions()) {
            CatchAttr catchAttr = insn.get(AType.CATCH_BLOCK);
            if (catchAttr == null) {
                continue;
            }
            if (insn.getType() == InsnType.THROW || onlyAllHandler(catchAttr.getTryBlock())) {
                TryCatchBlock handlerBlock = handlerAttr.getTryBlock();
                TryCatchBlock catchBlock = catchAttr.getTryBlock();
                handlerBlock.merge(mth, catchBlock);
            }
        }
    }
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) CatchAttr(jadx.core.dex.trycatch.CatchAttr) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) InstructionRemover(jadx.core.utils.InstructionRemover)

Aggregations

TryCatchBlock (jadx.core.dex.trycatch.TryCatchBlock)8 ExceptionHandler (jadx.core.dex.trycatch.ExceptionHandler)7 BlockNode (jadx.core.dex.nodes.BlockNode)6 HashSet (java.util.HashSet)5 ArrayList (java.util.ArrayList)4 CatchAttr (jadx.core.dex.trycatch.CatchAttr)3 IContainer (jadx.core.dex.nodes.IContainer)2 InsnNode (jadx.core.dex.nodes.InsnNode)2 ExcHandlerAttr (jadx.core.dex.trycatch.ExcHandlerAttr)2 SplitterBlockAttr (jadx.core.dex.trycatch.SplitterBlockAttr)2 BitSet (java.util.BitSet)2 CatchHandler (com.android.dex.Code.CatchHandler)1 Try (com.android.dex.Code.Try)1 ClassInfo (jadx.core.dex.info.ClassInfo)1 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)1 IBlock (jadx.core.dex.nodes.IBlock)1 IRegion (jadx.core.dex.nodes.IRegion)1 Region (jadx.core.dex.regions.Region)1 SwitchRegion (jadx.core.dex.regions.SwitchRegion)1 SynchronizedRegion (jadx.core.dex.regions.SynchronizedRegion)1