use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class RegionMaker method addEdgeInsn.
private void addEdgeInsn(IfInfo ifInfo, Region region, EdgeInsnAttr edgeInsnAttr) {
BlockNode start = edgeInsnAttr.getStart();
boolean fromThisIf = false;
for (BlockNode ifBlock : ifInfo.getMergedBlocks()) {
if (ifBlock.getSuccessors().contains(start)) {
fromThisIf = true;
break;
}
}
if (!fromThisIf) {
return;
}
region.add(start);
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class RegionMaker method makeEndlessLoop.
private BlockNode makeEndlessLoop(IRegion curRegion, RegionStack stack, LoopInfo loop, BlockNode loopStart) {
LoopRegion loopRegion = new LoopRegion(curRegion, loop, null, false);
curRegion.getSubBlocks().add(loopRegion);
loopStart.remove(AType.LOOP);
processedBlocks.clear(loopStart.getId());
stack.push(loopRegion);
BlockNode out = null;
// insert 'break' for exits
List<Edge> exitEdges = loop.getExitEdges();
if (exitEdges.size() == 1) {
Edge exitEdge = exitEdges.get(0);
BlockNode exit = exitEdge.getTarget();
if (insertLoopBreak(stack, loop, exit, exitEdge)) {
BlockNode nextBlock = getNextBlock(exit);
if (nextBlock != null) {
stack.addExit(nextBlock);
out = nextBlock;
}
}
} else {
for (Edge exitEdge : exitEdges) {
BlockNode exit = exitEdge.getTarget();
List<BlockNode> blocks = BlockUtils.bitSetToBlocks(mth, exit.getDomFrontier());
for (BlockNode block : blocks) {
if (BlockUtils.isPathExists(exit, block)) {
stack.addExit(block);
insertLoopBreak(stack, loop, block, exitEdge);
out = block;
} else {
insertLoopBreak(stack, loop, exit, exitEdge);
}
}
}
}
Region body = makeRegion(loopStart, stack);
BlockNode loopEnd = loop.getEnd();
if (!RegionUtils.isRegionContainsBlock(body, loopEnd) && !loopEnd.contains(AType.EXC_HANDLER) && !inExceptionHandlerBlocks(loopEnd)) {
body.getSubBlocks().add(loopEnd);
}
loopRegion.setBody(body);
if (out == null) {
BlockNode next = getNextBlock(loopEnd);
out = RegionUtils.isRegionContainsBlock(body, next) ? null : next;
}
stack.pop();
loopStart.addAttr(AType.LOOP, loop);
return out;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class RegionMaker method canInsertContinue.
private static boolean canInsertContinue(BlockNode pred, List<BlockNode> predecessors, BlockNode loopEnd, Set<BlockNode> loopExitNodes) {
if (!pred.contains(AFlag.SYNTHETIC) || BlockUtils.checkLastInsnType(pred, InsnType.CONTINUE)) {
return false;
}
List<BlockNode> preds = pred.getPredecessors();
if (preds.isEmpty()) {
return false;
}
BlockNode codePred = preds.get(0);
if (codePred.contains(AFlag.ADDED_TO_REGION)) {
return false;
}
if (loopEnd.isDominator(codePred) || loopExitNodes.contains(codePred)) {
return false;
}
if (isDominatedOnBlocks(codePred, predecessors)) {
return false;
}
boolean gotoExit = false;
for (BlockNode exit : loopExitNodes) {
if (BlockUtils.isPathExists(codePred, exit)) {
gotoExit = true;
break;
}
}
return gotoExit;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class RegionMaker method processIf.
private BlockNode processIf(IRegion currentRegion, BlockNode block, IfNode ifnode, RegionStack stack) {
if (block.contains(AFlag.ADDED_TO_REGION)) {
// block already included in other 'if' region
return ifnode.getThenBlock();
}
IfInfo currentIf = makeIfInfo(mth, block);
if (currentIf == null) {
return null;
}
IfInfo mergedIf = mergeNestedIfNodes(currentIf);
if (mergedIf != null) {
currentIf = mergedIf;
} else {
// invert simple condition (compiler often do it)
currentIf = IfInfo.invert(currentIf);
}
IfInfo modifiedIf = IfMakerHelper.restructureIf(mth, block, currentIf);
if (modifiedIf != null) {
currentIf = modifiedIf;
} else {
if (currentIf.getMergedBlocks().size() <= 1) {
return null;
}
currentIf = makeIfInfo(mth, block);
currentIf = IfMakerHelper.restructureIf(mth, block, currentIf);
if (currentIf == null) {
// all attempts failed
return null;
}
}
confirmMerge(currentIf);
IfRegion ifRegion = new IfRegion(currentRegion);
ifRegion.updateCondition(currentIf);
currentRegion.getSubBlocks().add(ifRegion);
BlockNode outBlock = currentIf.getOutBlock();
stack.push(ifRegion);
stack.addExit(outBlock);
ifRegion.setThenRegion(makeRegion(currentIf.getThenBlock(), stack));
BlockNode elseBlock = currentIf.getElseBlock();
if (elseBlock == null || stack.containsExit(elseBlock)) {
ifRegion.setElseRegion(null);
} else {
ifRegion.setElseRegion(makeRegion(elseBlock, stack));
}
// TODO: make more common algorithm
if (ifRegion.getElseRegion() == null && outBlock != null) {
List<EdgeInsnAttr> edgeInsnAttrs = outBlock.getAll(AType.EDGE_INSN);
if (!edgeInsnAttrs.isEmpty()) {
Region elseRegion = new Region(ifRegion);
for (EdgeInsnAttr edgeInsnAttr : edgeInsnAttrs) {
if (edgeInsnAttr.getEnd().equals(outBlock)) {
addEdgeInsn(currentIf, elseRegion, edgeInsnAttr);
}
}
ifRegion.setElseRegion(elseRegion);
}
}
stack.pop();
return outBlock;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class RegionMaker method processHandlersOutBlocks.
/**
* Search handlers successor blocks not included in any region.
*/
protected IRegion processHandlersOutBlocks(MethodNode mth, List<TryCatchBlockAttr> tcs) {
Set<IBlock> allRegionBlocks = new HashSet<>();
RegionUtils.getAllRegionBlocks(mth.getRegion(), allRegionBlocks);
Set<IBlock> succBlocks = new HashSet<>();
for (TryCatchBlockAttr 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;
}
Aggregations