Search in sources :

Example 41 with InsnNode

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

the class BlockFinallyExtract method countInstructions.

private static int countInstructions(ExceptionHandler excHandler) {
    int totalSize = 0;
    for (BlockNode excBlock : excHandler.getBlocks()) {
        List<InsnNode> list = excBlock.getInstructions();
        if (!list.isEmpty() && list.get(0).getType() == InsnType.MOVE_EXCEPTION) {
            // don't count 'move-exception' it will be removed later
            totalSize--;
        }
        totalSize += list.size();
    }
    return totalSize;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode)

Example 42 with InsnNode

use of jadx.core.dex.nodes.InsnNode 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 43 with InsnNode

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

the class BlockFinallyExtract method isStartBlock.

/**
	 * 'Finally' instructions can start in the middle of the first block.
	 */
private static BlocksRemoveInfo isStartBlock(BlockNode remBlock, BlockNode startBlock) {
    List<InsnNode> remInsns = remBlock.getInstructions();
    List<InsnNode> startInsns = startBlock.getInstructions();
    if (remInsns.size() < startInsns.size()) {
        return null;
    }
    // first - fast check
    int startPos = remInsns.size() - startInsns.size();
    int endPos = 0;
    if (!checkInsns(remInsns, startInsns, startPos, null)) {
        if (checkInsns(remInsns, startInsns, 0, null)) {
            startPos = 0;
            endPos = startInsns.size();
        } else {
            boolean found = false;
            for (int i = 1; i < startPos; i++) {
                if (checkInsns(remInsns, startInsns, i, null)) {
                    startPos = i;
                    endPos = startInsns.size() + i;
                    found = true;
                    break;
                }
            }
            if (!found) {
                return null;
            }
        }
    }
    BlocksPair startPair = new BlocksPair(remBlock, startBlock);
    BlocksRemoveInfo removeInfo = new BlocksRemoveInfo(startPair);
    removeInfo.setStartSplitIndex(startPos);
    removeInfo.setEndSplitIndex(endPos);
    if (endPos != 0) {
        removeInfo.setEnd(startPair);
    }
    // second - run checks again for collect registers mapping
    if (!checkInsns(remInsns, startInsns, startPos, removeInfo)) {
        return null;
    }
    return removeInfo;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) BlocksPair(jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair) BlocksRemoveInfo(jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo)

Example 44 with InsnNode

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

the class BlockFinallyExtract method splitBlock.

/**
	 * Split one block into connected 2 blocks with same connections.
	 *
	 * @return new successor block
	 */
private static BlockNode splitBlock(MethodNode mth, BlockNode block, int splitIndex) {
    BlockNode newBlock = BlockSplitter.startNewBlock(mth, -1);
    newBlock.getSuccessors().addAll(block.getSuccessors());
    for (BlockNode s : new ArrayList<BlockNode>(block.getSuccessors())) {
        removeConnection(block, s);
        connect(newBlock, s);
    }
    block.getSuccessors().clear();
    connect(block, newBlock);
    block.updateCleanSuccessors();
    newBlock.updateCleanSuccessors();
    List<InsnNode> insns = block.getInstructions();
    int size = insns.size();
    for (int i = splitIndex; i < size; i++) {
        InsnNode insnNode = insns.get(i);
        insnNode.add(AFlag.SKIP);
        newBlock.getInstructions().add(insnNode);
    }
    Iterator<InsnNode> it = insns.iterator();
    while (it.hasNext()) {
        InsnNode insnNode = it.next();
        if (insnNode.contains(AFlag.SKIP)) {
            it.remove();
        }
    }
    for (InsnNode insnNode : newBlock.getInstructions()) {
        insnNode.remove(AFlag.SKIP);
    }
    return newBlock;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) ArrayList(java.util.ArrayList)

Example 45 with InsnNode

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

the class BlockFinallyExtract method checkInsns.

private static boolean checkInsns(List<InsnNode> remInsns, List<InsnNode> startInsns, int delta, @Nullable BlocksRemoveInfo removeInfo) {
    for (int i = startInsns.size() - 1; i >= 0; i--) {
        InsnNode startInsn = startInsns.get(i);
        InsnNode remInsn = remInsns.get(delta + i);
        if (!sameInsns(remInsn, startInsn, removeInfo)) {
            return false;
        }
    }
    return true;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode)

Aggregations

InsnNode (jadx.core.dex.nodes.InsnNode)123 BlockNode (jadx.core.dex.nodes.BlockNode)41 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)39 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)35 InsnArg (jadx.core.dex.instructions.args.InsnArg)32 InsnWrapArg (jadx.core.dex.instructions.args.InsnWrapArg)19 SSAVar (jadx.core.dex.instructions.args.SSAVar)16 ArrayList (java.util.ArrayList)14 ArgType (jadx.core.dex.instructions.args.ArgType)11 PhiInsn (jadx.core.dex.instructions.PhiInsn)10 FieldNode (jadx.core.dex.nodes.FieldNode)10 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)8 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)7 ClassNode (jadx.core.dex.nodes.ClassNode)7 MethodNode (jadx.core.dex.nodes.MethodNode)7 FieldInfo (jadx.core.dex.info.FieldInfo)6 ArithNode (jadx.core.dex.instructions.ArithNode)6 ConstructorInsn (jadx.core.dex.instructions.mods.ConstructorInsn)6 InsnType (jadx.core.dex.instructions.InsnType)5 IContainer (jadx.core.dex.nodes.IContainer)5