コード例 #1
0
ファイル: RegionMaker.java プロジェクト: qiyeboy/jadx
 private void addBreakLabel(Edge exitEdge, BlockNode exit, InsnNode breakInsn) {
   BlockNode outBlock = BlockUtils.getNextBlock(exitEdge.getTarget());
   if (outBlock == null) {
     return;
   }
   List<LoopInfo> exitLoop = mth.getAllLoopsForBlock(outBlock);
   if (!exitLoop.isEmpty()) {
     return;
   }
   List<LoopInfo> inLoops = mth.getAllLoopsForBlock(exitEdge.getSource());
   if (inLoops.size() < 2) {
     return;
   }
   // search for parent loop
   LoopInfo parentLoop = null;
   for (LoopInfo loop : inLoops) {
     if (loop.getParentLoop() == null) {
       parentLoop = loop;
       break;
     }
   }
   if (parentLoop == null) {
     return;
   }
   if (parentLoop.getEnd() != exit && !parentLoop.getExitNodes().contains(exit)) {
     LoopLabelAttr labelAttr = new LoopLabelAttr(parentLoop);
     breakInsn.addAttr(labelAttr);
     parentLoop.getStart().addAttr(labelAttr);
   }
 }
コード例 #2
0
ファイル: RegionMaker.java プロジェクト: qiyeboy/jadx
 private static void insertContinue(LoopInfo loop) {
   BlockNode loopEnd = loop.getEnd();
   List<BlockNode> predecessors = loopEnd.getPredecessors();
   if (predecessors.size() <= 1) {
     return;
   }
   Set<BlockNode> loopExitNodes = loop.getExitNodes();
   for (BlockNode pred : predecessors) {
     if (canInsertContinue(pred, predecessors, loopEnd, loopExitNodes)) {
       InsnNode cont = new InsnNode(InsnType.CONTINUE, 0);
       pred.getInstructions().add(cont);
     }
   }
 }
コード例 #3
0
ファイル: RegionMaker.java プロジェクト: qiyeboy/jadx
  private BlockNode processLoop(IRegion curRegion, LoopInfo loop, RegionStack stack) {
    BlockNode loopStart = loop.getStart();
    Set<BlockNode> exitBlocksSet = loop.getExitNodes();

    // set exit blocks scan order priority
    // this can help if loop have several exits (after using 'break' or 'return' in loop)
    List<BlockNode> exitBlocks = new ArrayList<BlockNode>(exitBlocksSet.size());
    BlockNode nextStart = getNextBlock(loopStart);
    if (nextStart != null && exitBlocksSet.remove(nextStart)) {
      exitBlocks.add(nextStart);
    }
    if (exitBlocksSet.remove(loopStart)) {
      exitBlocks.add(loopStart);
    }
    if (exitBlocksSet.remove(loop.getEnd())) {
      exitBlocks.add(loop.getEnd());
    }
    exitBlocks.addAll(exitBlocksSet);

    LoopRegion loopRegion = makeLoopRegion(curRegion, loop, exitBlocks);
    if (loopRegion == null) {
      BlockNode exit = makeEndlessLoop(curRegion, stack, loop, loopStart);
      insertContinue(loop);
      return exit;
    }
    curRegion.getSubBlocks().add(loopRegion);
    IRegion outerRegion = stack.peekRegion();
    stack.push(loopRegion);

    IfInfo condInfo = makeIfInfo(loopRegion.getHeader());
    condInfo = searchNestedIf(condInfo);
    confirmMerge(condInfo);
    if (!loop.getLoopBlocks().contains(condInfo.getThenBlock())) {
      // invert loop condition if 'then' points to exit
      condInfo = IfInfo.invert(condInfo);
    }
    loopRegion.setCondition(condInfo.getCondition());
    exitBlocks.removeAll(condInfo.getMergedBlocks());

    if (!exitBlocks.isEmpty()) {
      BlockNode loopExit = condInfo.getElseBlock();
      if (loopExit != null) {
        // add 'break' instruction before path cross between main loop exit and sub-exit
        for (Edge exitEdge : loop.getExitEdges()) {
          if (!exitBlocks.contains(exitEdge.getSource())) {
            continue;
          }
          insertBreak(stack, loopExit, exitEdge);
        }
      }
    }

    BlockNode out;
    if (loopRegion.isConditionAtEnd()) {
      BlockNode thenBlock = condInfo.getThenBlock();
      out = thenBlock == loopStart ? condInfo.getElseBlock() : thenBlock;
      loopStart.remove(AType.LOOP);
      loop.getEnd().add(AFlag.SKIP);
      stack.addExit(loop.getEnd());
      loopRegion.setBody(makeRegion(loopStart, stack));
      loopStart.addAttr(AType.LOOP, loop);
      loop.getEnd().remove(AFlag.SKIP);
    } else {
      out = condInfo.getElseBlock();
      if (outerRegion != null
          && out.contains(AFlag.LOOP_START)
          && !out.getAll(AType.LOOP).contains(loop)
          && RegionUtils.isRegionContainsBlock(outerRegion, out)) {
        // exit to already processed outer loop
        out = null;
      }
      stack.addExit(out);
      BlockNode loopBody = condInfo.getThenBlock();
      Region body = makeRegion(loopBody, stack);
      // add blocks from loop start to first condition block
      BlockNode conditionBlock = condInfo.getIfBlock();
      if (loopStart != conditionBlock) {
        Set<BlockNode> blocks = BlockUtils.getAllPathsBlocks(loopStart, conditionBlock);
        blocks.remove(conditionBlock);
        for (BlockNode block : blocks) {
          if (block.getInstructions().isEmpty()
              && !block.contains(AFlag.SKIP)
              && !RegionUtils.isRegionContainsBlock(body, block)) {
            body.add(block);
          }
        }
      }
      loopRegion.setBody(body);
    }
    stack.pop();
    insertContinue(loop);
    return out;
  }