use of jadx.core.dex.attributes.nodes.LoopInfo in project jadx by skylot.
the class RegionUtils method isInsnExitContainer.
private static boolean isInsnExitContainer(IContainer rootContainer, IBlock block) {
InsnNode lastInsn = BlockUtils.getLastInsn(block);
if (lastInsn == null) {
return false;
}
InsnType insnType = lastInsn.getType();
if (insnType == InsnType.RETURN) {
return true;
}
if (insnType == InsnType.THROW) {
// check if after throw execution can continue in current container
CatchAttr catchAttr = lastInsn.get(AType.EXC_CATCH);
if (catchAttr != null) {
for (ExceptionHandler handler : catchAttr.getHandlers()) {
if (RegionUtils.isRegionContainsBlock(rootContainer, handler.getHandlerBlock())) {
return false;
}
}
}
return true;
}
if (insnType == InsnType.BREAK) {
AttrList<LoopInfo> loopInfoAttrList = lastInsn.get(AType.LOOP);
if (loopInfoAttrList != null) {
for (LoopInfo loopInfo : loopInfoAttrList.getList()) {
if (!RegionUtils.isRegionContainsBlock(rootContainer, loopInfo.getStart())) {
return true;
}
}
}
LoopLabelAttr loopLabelAttr = lastInsn.get(AType.LOOP_LABEL);
if (loopLabelAttr != null && !RegionUtils.isRegionContainsBlock(rootContainer, loopLabelAttr.getLoop().getStart())) {
return true;
}
}
return false;
}
use of jadx.core.dex.attributes.nodes.LoopInfo in project jadx by skylot.
the class BlockProcessor method checkLoops.
private static boolean checkLoops(MethodNode mth, BlockNode block) {
if (!block.contains(AFlag.LOOP_START)) {
return false;
}
List<LoopInfo> loops = block.getAll(AType.LOOP);
int loopsCount = loops.size();
if (loopsCount == 0) {
return false;
}
for (LoopInfo loop : loops) {
if (insertBlocksForBreak(mth, loop)) {
return true;
}
}
if (loopsCount > 1 && splitLoops(mth, block, loops)) {
return true;
}
if (loopsCount == 1) {
LoopInfo loop = loops.get(0);
return insertBlocksForContinue(mth, loop) || insertBlockForPredecessors(mth, loop) || insertPreHeader(mth, loop);
}
return false;
}
use of jadx.core.dex.attributes.nodes.LoopInfo in project jadx by skylot.
the class IfMakerHelper method isBadBranchBlock.
private static boolean isBadBranchBlock(IfInfo info, BlockNode block) {
// check if block at end of loop edge
if (block.contains(AFlag.LOOP_START) && block.getPredecessors().size() == 1) {
BlockNode pred = block.getPredecessors().get(0);
if (pred.contains(AFlag.LOOP_END)) {
List<LoopInfo> startLoops = block.getAll(AType.LOOP);
List<LoopInfo> endLoops = pred.getAll(AType.LOOP);
// search for same loop
for (LoopInfo startLoop : startLoops) {
for (LoopInfo endLoop : endLoops) {
if (startLoop == endLoop) {
return true;
}
}
}
}
}
return !allPathsFromIf(block, info);
}
use of jadx.core.dex.attributes.nodes.LoopInfo in project jadx by skylot.
the class RegionMaker method traverse.
/**
* Recursively traverse all blocks from 'block' until block from 'exits'
*/
private BlockNode traverse(IRegion r, BlockNode block, RegionStack stack) {
if (block.contains(AFlag.MTH_EXIT_BLOCK)) {
return null;
}
BlockNode next = null;
boolean processed = false;
List<LoopInfo> loops = block.getAll(AType.LOOP);
int loopCount = loops.size();
if (loopCount != 0 && block.contains(AFlag.LOOP_START)) {
if (loopCount == 1) {
next = processLoop(r, loops.get(0), stack);
processed = true;
} else {
for (LoopInfo loop : loops) {
if (loop.getStart() == block) {
next = processLoop(r, loop, stack);
processed = true;
break;
}
}
}
}
InsnNode insn = BlockUtils.getLastInsn(block);
if (!processed && insn != null) {
switch(insn.getType()) {
case IF:
next = processIf(r, block, (IfNode) insn, stack);
processed = true;
break;
case SWITCH:
next = processSwitch(r, block, (SwitchInsn) insn, stack);
processed = true;
break;
case MONITOR_ENTER:
next = processMonitorEnter(r, block, insn, stack);
processed = true;
break;
default:
break;
}
}
if (!processed) {
r.getSubBlocks().add(block);
next = getNextBlock(block);
}
if (next != null && !stack.containsExit(block) && !stack.containsExit(next)) {
return next;
}
return null;
}
use of jadx.core.dex.attributes.nodes.LoopInfo in project jadx by skylot.
the class RegionMaker method checkLoopExits.
private boolean checkLoopExits(LoopInfo loop, BlockNode mainExitBlock) {
List<Edge> exitEdges = loop.getExitEdges();
if (exitEdges.size() < 2) {
return true;
}
Optional<Edge> mainEdgeOpt = exitEdges.stream().filter(edge -> edge.getSource() == mainExitBlock).findFirst();
if (!mainEdgeOpt.isPresent()) {
throw new JadxRuntimeException("Not found exit edge by exit block: " + mainExitBlock);
}
Edge mainExitEdge = mainEdgeOpt.get();
BlockNode mainOutBlock = mainExitEdge.getTarget();
for (Edge exitEdge : exitEdges) {
if (exitEdge != mainExitEdge) {
// all exit paths must be same or don't cross (will be inside loop)
BlockNode exitBlock = exitEdge.getTarget();
if (!isEqualPaths(mainOutBlock, exitBlock)) {
BlockNode crossBlock = BlockUtils.getPathCross(mth, mainOutBlock, exitBlock);
if (crossBlock != null) {
return false;
}
}
}
}
return true;
}
Aggregations