Search in sources :

Example 6 with BlocksPair

use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.

the class BlockFinallyExtract method applyRemove.

private static boolean applyRemove(MethodNode mth, BlocksRemoveInfo removeInfo) {
    BlockNode remBlock = removeInfo.getStart().getFirst();
    BlockNode startBlock = removeInfo.getStart().getSecond();
    if (remBlock.contains(AFlag.REMOVE)) {
        // already processed
        return true;
    }
    if (remBlock.getPredecessors().size() != 1) {
        LOG.warn("Finally extract failed: remBlock pred: {}, {}, method: {}", remBlock, remBlock.getPredecessors(), mth);
        return false;
    }
    BlockNode remBlockPred = remBlock.getPredecessors().get(0);
    removeInfo.setStartPredecessor(remBlockPred);
    int startSplitIndex = removeInfo.getStartSplitIndex();
    int endSplitIndex = removeInfo.getEndSplitIndex();
    if (removeInfo.getStart().equals(removeInfo.getEnd())) {
        removeInfo.setEndSplitIndex(endSplitIndex - startSplitIndex);
    }
    // split start block (remBlock)
    if (startSplitIndex > 0) {
        remBlock = splitBlock(mth, remBlock, startSplitIndex);
        // change start block in removeInfo
        removeInfo.getProcessed().remove(removeInfo.getStart());
        BlocksPair newStart = new BlocksPair(remBlock, startBlock);
        //			removeInfo.setStart(newStart);
        removeInfo.getProcessed().add(newStart);
    }
    // split end block
    if (endSplitIndex > 0) {
        BlocksPair end = removeInfo.getEnd();
        BlockNode newOut = splitBlock(mth, end.getFirst(), endSplitIndex);
        for (BlockNode s : newOut.getSuccessors()) {
            BlocksPair replaceOut = null;
            Iterator<BlocksPair> it = removeInfo.getOuts().iterator();
            while (it.hasNext()) {
                BlocksPair outPair = it.next();
                if (outPair.getFirst().equals(s)) {
                    it.remove();
                    replaceOut = new BlocksPair(newOut, outPair.getSecond());
                    break;
                }
            }
            if (replaceOut != null) {
                removeInfo.getOuts().add(replaceOut);
            }
        }
    }
    BlocksPair out = removeInfo.getOuts().iterator().next();
    BlockNode rOut = out.getFirst();
    BlockNode sOut = out.getSecond();
    // redirect out edges
    List<BlockNode> filtPreds = BlockUtils.filterPredecessors(sOut);
    if (filtPreds.size() > 1) {
        BlockNode pred = sOut.getPredecessors().get(0);
        BlockNode newPred = BlockSplitter.insertBlockBetween(mth, pred, sOut);
        for (BlockNode predBlock : new ArrayList<BlockNode>(sOut.getPredecessors())) {
            if (predBlock != newPred) {
                removeConnection(predBlock, sOut);
                connect(predBlock, newPred);
            }
        }
        rOut.getPredecessors().clear();
        addIgnoredEdge(newPred, rOut);
        connect(newPred, rOut);
    } else if (filtPreds.size() == 1) {
        BlockNode pred = filtPreds.get(0);
        BlockNode repl = removeInfo.getBySecond(pred);
        if (repl == null) {
            LOG.error("Block not found by {}, in {}, method: {}", pred, removeInfo, mth);
            return false;
        }
        removeConnection(pred, rOut);
        addIgnoredEdge(repl, rOut);
        connect(repl, rOut);
    } else {
        throw new JadxRuntimeException("Finally extract failed, unexpected preds: " + filtPreds + " for " + sOut + ", method: " + mth);
    }
    // redirect input edges
    for (BlockNode pred : new ArrayList<BlockNode>(remBlock.getPredecessors())) {
        BlockNode middle = insertBlockBetween(mth, pred, remBlock);
        removeConnection(middle, remBlock);
        connect(middle, startBlock);
        addIgnoredEdge(middle, startBlock);
        connect(middle, rOut);
    }
    // mark blocks for remove
    markForRemove(mth, remBlock);
    for (BlocksPair pair : removeInfo.getProcessed()) {
        markForRemove(mth, pair.getFirst());
        BlockNode second = pair.getSecond();
        second.updateCleanSuccessors();
    }
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ArrayList(java.util.ArrayList) BlocksPair(jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException)

Example 7 with BlocksPair

use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.

the class BlockFinallyExtract method performVariablesReMap.

private static void performVariablesReMap(MethodNode mth, List<BlocksRemoveInfo> removes, LiveVarAnalysis laBefore, LiveVarAnalysis laAfter) {
    BitSet processed = new BitSet(mth.getRegsCount());
    for (BlocksRemoveInfo removeInfo : removes) {
        processed.clear();
        BlocksPair start = removeInfo.getStart();
        BlockNode insertBlockBefore = start.getFirst();
        BlockNode insertBlock = start.getSecond();
        if (removeInfo.getRegMap().isEmpty() || insertBlock == null) {
            continue;
        }
        for (Map.Entry<RegisterArg, RegisterArg> entry : removeInfo.getRegMap().entrySet()) {
            RegisterArg fromReg = entry.getKey();
            RegisterArg toReg = entry.getValue();
            int fromRegNum = fromReg.getRegNum();
            int toRegNum = toReg.getRegNum();
            if (!processed.get(fromRegNum)) {
                boolean liveFromBefore = laBefore.isLive(insertBlockBefore, fromRegNum);
                boolean liveFromAfter = laAfter.isLive(insertBlock, fromRegNum);
                // boolean liveToBefore = laBefore.isLive(insertBlock, toRegNum);
                boolean liveToAfter = laAfter.isLive(insertBlock, toRegNum);
                if (liveToAfter && liveFromBefore) {
                    // merge 'to' and 'from' registers
                    InsnNode merge = new InsnNode(InsnType.MERGE, 2);
                    merge.setResult(toReg.duplicate());
                    merge.addArg(toReg.duplicate());
                    merge.addArg(fromReg.duplicate());
                    injectInsn(mth, insertBlock, merge);
                } else if (liveFromBefore) {
                    // remap variable
                    InsnNode move = new InsnNode(InsnType.MOVE, 1);
                    move.setResult(toReg.duplicate());
                    move.addArg(fromReg.duplicate());
                    injectInsn(mth, insertBlock, move);
                } else if (liveFromAfter) {
                    // kill variable
                    InsnNode kill = new InsnNode(InsnType.NOP, 0);
                    kill.setResult(fromReg.duplicate());
                    kill.add(AFlag.REMOVE);
                    injectInsn(mth, insertBlock, kill);
                }
                processed.set(fromRegNum);
            }
        }
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) BitSet(java.util.BitSet) BlocksPair(jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair) Map(java.util.Map) BlocksRemoveInfo(jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo)

Aggregations

BlocksPair (jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair)7 BlockNode (jadx.core.dex.nodes.BlockNode)5 InsnNode (jadx.core.dex.nodes.InsnNode)3 BlocksRemoveInfo (jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo)3 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)1 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)1 ArrayList (java.util.ArrayList)1 BitSet (java.util.BitSet)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1