Search in sources :

Example 1 with ExceptionHandler

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

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

the class RegionMaker method processTryCatchBlocks.

public IRegion processTryCatchBlocks(MethodNode mth) {
    Set<TryCatchBlock> tcs = new HashSet<TryCatchBlock>();
    for (ExceptionHandler handler : mth.getExceptionHandlers()) {
        tcs.add(handler.getTryBlock());
    }
    for (TryCatchBlock tc : tcs) {
        List<BlockNode> blocks = new ArrayList<BlockNode>(tc.getHandlersCount());
        Set<BlockNode> splitters = new HashSet<BlockNode>();
        for (ExceptionHandler handler : tc.getHandlers()) {
            BlockNode handlerBlock = handler.getHandlerBlock();
            if (handlerBlock != null) {
                blocks.add(handlerBlock);
                splitters.addAll(handlerBlock.getPredecessors());
            } else {
                LOG.debug(ErrorsCounter.formatErrorMsg(mth, "No exception handler block: " + handler));
            }
        }
        Set<BlockNode> exits = new HashSet<BlockNode>();
        for (BlockNode splitter : splitters) {
            for (BlockNode handler : blocks) {
                List<BlockNode> s = splitter.getSuccessors();
                if (s.isEmpty()) {
                    LOG.debug(ErrorsCounter.formatErrorMsg(mth, "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(handler, exits);
        }
    }
    return processHandlersOutBlocks(mth, tcs);
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) BlockNode(jadx.core.dex.nodes.BlockNode) ArrayList(java.util.ArrayList) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) HashSet(java.util.HashSet)

Example 3 with ExceptionHandler

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

the class BlockExceptionHandler method markExceptionHandlers.

/**
	 * Set exception handler attribute for whole block
	 */
private static void markExceptionHandlers(BlockNode block) {
    if (block.getInstructions().isEmpty()) {
        return;
    }
    InsnNode me = block.getInstructions().get(0);
    ExcHandlerAttr handlerAttr = me.get(AType.EXC_HANDLER);
    if (handlerAttr == null || me.getType() != InsnType.MOVE_EXCEPTION) {
        return;
    }
    ExceptionHandler excHandler = handlerAttr.getHandler();
    block.addAttr(handlerAttr);
    // set correct type for 'move-exception' operation
    ArgType type = excHandler.isCatchAll() ? ArgType.THROWABLE : excHandler.getCatchType().getType();
    RegisterArg resArg = me.getResult();
    resArg = InsnArg.reg(resArg.getRegNum(), type);
    me.setResult(resArg);
    me.add(AFlag.DONT_INLINE);
    excHandler.setArg(resArg);
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) ArgType(jadx.core.dex.instructions.args.ArgType) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr)

Example 4 with ExceptionHandler

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

the class ModVisitor method processMoveException.

private static void processMoveException(MethodNode mth, BlockNode block, InsnNode insn, InstructionRemover remover) {
    ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
    if (excHandlerAttr == null) {
        return;
    }
    ExceptionHandler excHandler = excHandlerAttr.getHandler();
    // result arg used both in this insn and exception handler,
    RegisterArg resArg = insn.getResult();
    ArgType type = excHandler.isCatchAll() ? ArgType.THROWABLE : excHandler.getCatchType().getType();
    String name = excHandler.isCatchAll() ? "th" : "e";
    if (resArg.getName() == null) {
        resArg.setName(name);
    }
    SSAVar sVar = insn.getResult().getSVar();
    if (sVar.getUseCount() == 0) {
        excHandler.setArg(new NamedArg(name, type));
        remover.add(insn);
    } else if (sVar.isUsedInPhi()) {
        // exception var moved to external variable => replace with 'move' insn
        InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
        moveInsn.setResult(insn.getResult());
        NamedArg namedArg = new NamedArg(name, type);
        moveInsn.addArg(namedArg);
        excHandler.setArg(namedArg);
        replaceInsn(block, 0, moveInsn);
    }
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) ArgType(jadx.core.dex.instructions.args.ArgType) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) SSAVar(jadx.core.dex.instructions.args.SSAVar) NamedArg(jadx.core.dex.instructions.args.NamedArg)

Example 5 with ExceptionHandler

use of jadx.core.dex.trycatch.ExceptionHandler 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)

Aggregations

ExceptionHandler (jadx.core.dex.trycatch.ExceptionHandler)14 TryCatchBlock (jadx.core.dex.trycatch.TryCatchBlock)7 BlockNode (jadx.core.dex.nodes.BlockNode)6 HashSet (java.util.HashSet)5 IContainer (jadx.core.dex.nodes.IContainer)4 InsnNode (jadx.core.dex.nodes.InsnNode)4 CatchAttr (jadx.core.dex.trycatch.CatchAttr)4 ExcHandlerAttr (jadx.core.dex.trycatch.ExcHandlerAttr)4 ArrayList (java.util.ArrayList)4 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)3 SplitterBlockAttr (jadx.core.dex.trycatch.SplitterBlockAttr)3 ArgType (jadx.core.dex.instructions.args.ArgType)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 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)1 NamedArg (jadx.core.dex.instructions.args.NamedArg)1 SSAVar (jadx.core.dex.instructions.args.SSAVar)1 IBlock (jadx.core.dex.nodes.IBlock)1