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;
}
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);
}
}
}
}
Aggregations