Search in sources :

Example 1 with TryCatchBlock

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

the class ProcessTryCatchRegions method checkAndWrap.

private static boolean checkAndWrap(MethodNode mth, Map<BlockNode, TryCatchBlock> tryBlocksMap, IRegion region) {
    // search dominator blocks in this region (don't need to go deeper)
    for (Map.Entry<BlockNode, TryCatchBlock> entry : tryBlocksMap.entrySet()) {
        BlockNode dominator = entry.getKey();
        if (region.getSubBlocks().contains(dominator)) {
            TryCatchBlock tb = tryBlocksMap.get(dominator);
            if (!wrapBlocks(region, tb, dominator)) {
                ErrorsCounter.methodError(mth, "Can't wrap try/catch for " + region);
            }
            tryBlocksMap.remove(dominator);
            return true;
        }
    }
    return false;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with TryCatchBlock

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

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

the class RegionMaker method processHandlersOutBlocks.

/**
	 * Search handlers successor blocks not included in any region.
	 */
protected IRegion processHandlersOutBlocks(MethodNode mth, Set<TryCatchBlock> tcs) {
    Set<IBlock> allRegionBlocks = new HashSet<IBlock>();
    RegionUtils.getAllRegionBlocks(mth.getRegion(), allRegionBlocks);
    Set<IBlock> succBlocks = new HashSet<IBlock>();
    for (TryCatchBlock tc : tcs) {
        for (ExceptionHandler handler : tc.getHandlers()) {
            IContainer region = handler.getHandlerRegion();
            if (region != null) {
                IBlock lastBlock = RegionUtils.getLastBlock(region);
                if (lastBlock instanceof BlockNode) {
                    succBlocks.addAll(((BlockNode) lastBlock).getSuccessors());
                }
                RegionUtils.getAllRegionBlocks(region, allRegionBlocks);
            }
        }
    }
    succBlocks.removeAll(allRegionBlocks);
    if (succBlocks.isEmpty()) {
        return null;
    }
    Region excOutRegion = new Region(mth.getRegion());
    for (IBlock block : succBlocks) {
        if (block instanceof BlockNode) {
            excOutRegion.add(makeRegion((BlockNode) block, new RegionStack(mth)));
        }
    }
    return excOutRegion;
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) BlockNode(jadx.core.dex.nodes.BlockNode) IBlock(jadx.core.dex.nodes.IBlock) 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) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) IContainer(jadx.core.dex.nodes.IContainer) HashSet(java.util.HashSet)

Example 5 with TryCatchBlock

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

the class MethodNode method initTryCatches.

private void initTryCatches(Code mthCode) {
    InsnNode[] insnByOffset = instructions;
    CatchHandler[] catchBlocks = mthCode.getCatchHandlers();
    Try[] tries = mthCode.getTries();
    if (catchBlocks.length == 0 && tries.length == 0) {
        return;
    }
    int hc = 0;
    Set<Integer> addrs = new HashSet<Integer>();
    List<TryCatchBlock> catches = new ArrayList<TryCatchBlock>(catchBlocks.length);
    for (CatchHandler handler : catchBlocks) {
        TryCatchBlock tcBlock = new TryCatchBlock();
        catches.add(tcBlock);
        for (int i = 0; i < handler.getAddresses().length; i++) {
            int addr = handler.getAddresses()[i];
            ClassInfo type = ClassInfo.fromDex(parentClass.dex(), handler.getTypeIndexes()[i]);
            tcBlock.addHandler(this, addr, type);
            addrs.add(addr);
            hc++;
        }
        int addr = handler.getCatchAllAddress();
        if (addr >= 0) {
            tcBlock.addHandler(this, addr, null);
            addrs.add(addr);
            hc++;
        }
    }
    if (hc > 0 && hc != addrs.size()) {
        // each handler must be only in one try/catch block
        for (TryCatchBlock ct1 : catches) {
            for (TryCatchBlock ct2 : catches) {
                if (ct1 != ct2 && ct2.containsAllHandlers(ct1)) {
                    for (ExceptionHandler h : ct1.getHandlers()) {
                        ct2.removeHandler(this, h);
                        h.setTryBlock(ct1);
                    }
                }
            }
        }
    }
    // attach EXC_HANDLER attributes to instructions
    addrs.clear();
    for (TryCatchBlock ct : catches) {
        for (ExceptionHandler eh : ct.getHandlers()) {
            int addr = eh.getHandleOffset();
            ExcHandlerAttr ehAttr = new ExcHandlerAttr(ct, eh);
            insnByOffset[addr].addAttr(ehAttr);
        }
    }
    // attach TRY_ENTER, TRY_LEAVE attributes to instructions
    for (Try aTry : tries) {
        int catchNum = aTry.getCatchHandlerIndex();
        TryCatchBlock catchBlock = catches.get(catchNum);
        int offset = aTry.getStartAddress();
        int end = offset + aTry.getInstructionCount() - 1;
        InsnNode insn = insnByOffset[offset];
        insn.add(AFlag.TRY_ENTER);
        while (offset <= end && offset >= 0) {
            insn = insnByOffset[offset];
            catchBlock.addInsn(insn);
            offset = InsnDecoder.getNextInsnOffset(insnByOffset, offset);
        }
        if (insnByOffset[end] != null) {
            insnByOffset[end].add(AFlag.TRY_LEAVE);
        } else {
            insn.add(AFlag.TRY_LEAVE);
        }
    }
}
Also used : ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) ArrayList(java.util.ArrayList) CatchHandler(com.android.dex.Code.CatchHandler) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) Try(com.android.dex.Code.Try) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) HashSet(java.util.HashSet) ClassInfo(jadx.core.dex.info.ClassInfo)

Aggregations

TryCatchBlock (jadx.core.dex.trycatch.TryCatchBlock)7 ExceptionHandler (jadx.core.dex.trycatch.ExceptionHandler)6 BlockNode (jadx.core.dex.nodes.BlockNode)5 HashSet (java.util.HashSet)4 CatchAttr (jadx.core.dex.trycatch.CatchAttr)3 ArrayList (java.util.ArrayList)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