Projects STRLCPY jadx Commits 5cbf71bd
🤬
  • core: remove unnecessary return instructions for void methods

  • Loading...
  • Skylot committed 1 decade ago
    5cbf71bd
    1 parent a85d382e
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
    skipped 436 lines
    437 437   return null;
    438 438   }
    439 439   
     440 + public int getLoopsCount() {
     441 + return loops.size();
     442 + }
     443 + 
    440 444   public ExceptionHandler addExceptionHandler(ExceptionHandler handler) {
    441 445   if (exceptionHandlers == null) {
    442 446   exceptionHandlers = new ArrayList<ExceptionHandler>(2);
    skipped 79 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/FinishRegions.java
    1  -package jadx.core.dex.visitors.regions;
    2  - 
    3  -import jadx.core.dex.nodes.BlockNode;
    4  -import jadx.core.dex.nodes.IBlock;
    5  -import jadx.core.dex.nodes.IRegion;
    6  -import jadx.core.dex.nodes.MethodNode;
    7  -import jadx.core.dex.regions.LoopRegion;
    8  - 
    9  -import java.util.Iterator;
    10  - 
    11  -public class FinishRegions extends TracedRegionVisitor {
    12  - @Override
    13  - public void processBlockTraced(MethodNode mth, IBlock container, IRegion currentRegion) {
    14  - if (container.getClass() != BlockNode.class)
    15  - return;
    16  - 
    17  - BlockNode block = (BlockNode) container;
    18  - 
    19  - // remove last return in void functions
    20  - /*
    21  - BlockNode block = (BlockNode) container;
    22  - if (block.getCleanSuccessors().isEmpty()
    23  - && mth.getReturnType().equals(ArgType.VOID)) {
    24  - List<InsnNode> insns = block.getInstructions();
    25  - int lastIndex = insns.size() - 1;
    26  - if (lastIndex != -1) {
    27  - InsnNode last = insns.get(lastIndex);
    28  - if (last.getType() == InsnType.RETURN
    29  - && blockNotInLoop(mth, block)) {
    30  - insns.remove(lastIndex);
    31  - }
    32  - }
    33  - }
    34  - */
    35  - }
    36  - 
    37  - private boolean blockNotInLoop(MethodNode mth, BlockNode block) {
    38  - if (mth.getLoopForBlock(block) != null)
    39  - return false;
    40  - 
    41  - for (Iterator<IRegion> it = regionStack.descendingIterator(); it.hasNext(); ) {
    42  - IRegion region = it.next();
    43  - if (region.getClass() == LoopRegion.class)
    44  - return false;
    45  - }
    46  - return true;
    47  - }
    48  - 
    49  - @Override
    50  - public void leaveRegion(MethodNode mth, IRegion region) {
    51  - if (region instanceof LoopRegion) {
    52  - LoopRegion loop = (LoopRegion) region;
    53  - loop.mergePreCondition();
    54  - }
    55  - super.leaveRegion(mth, region);
    56  - }
    57  -}
    58  - 
  • ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/PostRegionVisitor.java
    1 1  package jadx.core.dex.visitors.regions;
    2 2   
    3  -import jadx.core.dex.instructions.InsnType;
    4 3  import jadx.core.dex.instructions.args.ArgType;
    5  -import jadx.core.dex.nodes.BlockNode;
    6 4  import jadx.core.dex.nodes.IContainer;
    7  -import jadx.core.dex.nodes.InsnNode;
    8 5  import jadx.core.dex.nodes.MethodNode;
    9  -import jadx.core.dex.regions.Region;
    10 6  import jadx.core.dex.visitors.AbstractVisitor;
    11 7  import jadx.core.utils.exceptions.JadxException;
    12  - 
    13  -import java.util.List;
    14 8   
    15 9  public class PostRegionVisitor extends AbstractVisitor {
    16 10   
    17 11   @Override
    18 12   public void visit(MethodNode mth) throws JadxException {
    19  - if (mth.isNoCode() || mth.getRegion() == null)
     13 + IContainer startRegion = mth.getRegion();
     14 + if (mth.isNoCode() || startRegion == null) {
    20 15   return;
    21  - 
    22  - DepthRegionTraverser.traverse(mth, new MarkTryCatchRegions(mth), mth.getRegion());
    23  - DepthRegionTraverser.traverse(mth, new FinishRegions(), mth.getRegion());
    24  - 
    25  - removeReturn(mth);
    26  - }
    27  - 
    28  - /**
    29  - * Remove useless return at end
    30  - */
    31  - private void removeReturn(MethodNode mth) {
    32  - if (!mth.getReturnType().equals(ArgType.VOID))
    33  - return;
    34  - 
    35  - if (!(mth.getRegion() instanceof Region))
    36  - return;
    37  - 
    38  - Region rootRegion = (Region) mth.getRegion();
    39  - if (rootRegion.getSubBlocks().isEmpty())
    40  - return;
    41  - 
    42  - IContainer lastCont = rootRegion.getSubBlocks().get(rootRegion.getSubBlocks().size() - 1);
    43  - if (lastCont instanceof BlockNode) {
    44  - BlockNode lastBlock = (BlockNode) lastCont;
    45  - List<InsnNode> insns = lastBlock.getInstructions();
    46  - int last = insns.size() - 1;
    47  - if (last >= 0
    48  - && insns.get(last).getType() == InsnType.RETURN
    49  - && insns.get(last).getArgsCount() == 0) {
    50  - insns.remove(last);
    51  - }
     16 + }
     17 + DepthRegionTraverser.traverse(mth, new ProcessTryCatchRegions(mth), startRegion);
     18 + if (mth.getLoopsCount() != 0) {
     19 + DepthRegionTraverser.traverse(mth, new ProcessLoopRegions(), startRegion);
     20 + }
     21 + if (mth.getReturnType().equals(ArgType.VOID)) {
     22 + DepthRegionTraverser.traverseAll(mth, new ProcessReturnInsns());
    52 23   }
    53 24   }
    54 25  }
    skipped 1 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessLoopRegions.java
     1 +package jadx.core.dex.visitors.regions;
     2 + 
     3 +import jadx.core.dex.nodes.IRegion;
     4 +import jadx.core.dex.nodes.MethodNode;
     5 +import jadx.core.dex.regions.LoopRegion;
     6 + 
     7 +public class ProcessLoopRegions extends AbstractRegionVisitor {
     8 + 
     9 + @Override
     10 + public void enterRegion(MethodNode mth, IRegion region) {
     11 + if (region instanceof LoopRegion) {
     12 + LoopRegion loop = (LoopRegion) region;
     13 + loop.mergePreCondition();
     14 + }
     15 + }
     16 +}
     17 + 
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessReturnInsns.java
     1 +package jadx.core.dex.visitors.regions;
     2 + 
     3 +import jadx.core.dex.attributes.AttributeFlag;
     4 +import jadx.core.dex.nodes.BlockNode;
     5 +import jadx.core.dex.nodes.IBlock;
     6 +import jadx.core.dex.nodes.IContainer;
     7 +import jadx.core.dex.nodes.IRegion;
     8 +import jadx.core.dex.nodes.InsnNode;
     9 +import jadx.core.dex.nodes.MethodNode;
     10 +import jadx.core.dex.regions.LoopRegion;
     11 +import jadx.core.utils.RegionUtils;
     12 + 
     13 +import java.util.List;
     14 +import java.util.ListIterator;
     15 + 
     16 +/**
     17 + * Remove unnecessary return instructions for void methods
     18 + */
     19 +public class ProcessReturnInsns extends TracedRegionVisitor {
     20 + 
     21 + @Override
     22 + public void processBlockTraced(MethodNode mth, IBlock container, IRegion currentRegion) {
     23 + if (container.getClass() != BlockNode.class) {
     24 + return;
     25 + }
     26 + BlockNode block = (BlockNode) container;
     27 + if (block.getAttributes().contains(AttributeFlag.RETURN)) {
     28 + List<InsnNode> insns = block.getInstructions();
     29 + if (insns.size() == 1
     30 + && blockNotInLoop(mth, block)
     31 + && noTrailInstructions(block)) {
     32 + insns.remove(insns.size() - 1);
     33 + }
     34 + }
     35 + }
     36 + 
     37 + private boolean blockNotInLoop(MethodNode mth, BlockNode block) {
     38 + if (mth.getLoopForBlock(block) != null) {
     39 + return false;
     40 + }
     41 + for (IRegion region : regionStack) {
     42 + if (region.getClass() == LoopRegion.class) {
     43 + return false;
     44 + }
     45 + }
     46 + return true;
     47 + }
     48 + 
     49 + /**
     50 + * Check that there no code after this block in regions structure
     51 + */
     52 + private boolean noTrailInstructions(BlockNode block) {
     53 + IContainer curContainer = block;
     54 + for (IRegion region : regionStack) {
     55 + List<IContainer> subBlocks = region.getSubBlocks();
     56 + if (!subBlocks.isEmpty()) {
     57 + ListIterator<IContainer> itSubBlock = subBlocks.listIterator(subBlocks.size());
     58 + while (itSubBlock.hasPrevious()) {
     59 + IContainer subBlock = itSubBlock.previous();
     60 + if (subBlock == curContainer) {
     61 + break;
     62 + } else if (RegionUtils.notEmpty(subBlock)) {
     63 + return false;
     64 + }
     65 + }
     66 + }
     67 + curContainer = region;
     68 + }
     69 + return true;
     70 + }
     71 +}
     72 + 
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/MarkTryCatchRegions.java jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java
    skipped 25 lines
    26 26  /**
    27 27   * Extract blocks to separate try/catch region
    28 28   */
    29  -public class MarkTryCatchRegions extends AbstractRegionVisitor {
    30  - private static final Logger LOG = LoggerFactory.getLogger(MarkTryCatchRegions.class);
     29 +public class ProcessTryCatchRegions extends AbstractRegionVisitor {
     30 + private static final Logger LOG = LoggerFactory.getLogger(ProcessTryCatchRegions.class);
    31 31   private static final boolean DEBUG = false;
    32 32   
    33 33   static {
    34  - if (DEBUG)
    35  - LOG.debug("Debug enabled for " + MarkTryCatchRegions.class);
     34 + if (DEBUG) {
     35 + LOG.debug("Debug enabled for " + ProcessTryCatchRegions.class);
     36 + }
    36 37   }
    37 38   
    38 39   private final Map<BlockNode, TryCatchBlock> tryBlocksMap = new HashMap<BlockNode, TryCatchBlock>(2);
    39 40   
    40  - public MarkTryCatchRegions(MethodNode mth) {
    41  - if (mth.isNoCode() || mth.getExceptionHandlers() == null)
     41 + public ProcessTryCatchRegions(MethodNode mth) {
     42 + if (mth.isNoCode() || mth.getExceptionHandlers() == null) {
    42 43   return;
     44 + }
    43 45   
    44 46   Set<TryCatchBlock> tryBlocks = new HashSet<TryCatchBlock>();
    45 47   // collect all try/catch blocks
    46 48   for (BlockNode block : mth.getBasicBlocks()) {
    47 49   CatchAttr c = (CatchAttr) block.getAttributes().get(AttributeType.CATCH_BLOCK);
    48  - if (c != null)
     50 + if (c != null) {
    49 51   tryBlocks.add(c.getTryBlock());
     52 + }
    50 53   }
    51 54   
    52 55   // for each try block search nearest dominator block
    skipped 18 lines
    71 74   bs.andNot(block.getDoms());
    72 75   }
    73 76   domBlocks = BlockUtils.bitsetToBlocks(mth, bs);
    74  - if (domBlocks.size() != 1)
     77 + if (domBlocks.size() != 1) {
    75 78   throw new JadxRuntimeException(
    76 79   "Exception block dominator not found, method:" + mth + ". bs: " + bs);
     80 + }
    77 81   
    78 82   BlockNode domBlock = domBlocks.get(0);
    79 83   
    skipped 3 lines
    83 87   }
    84 88   }
    85 89   
    86  - if (DEBUG && !tryBlocksMap.isEmpty())
    87  - LOG.debug("MarkTryCatchRegions: \n {} \n {}", mth, tryBlocksMap);
     90 + if (DEBUG && !tryBlocksMap.isEmpty()) {
     91 + LOG.debug("ProcessTryCatchRegions: \n {} \n {}", mth, tryBlocksMap);
     92 + }
    88 93   }
    89 94   
    90 95   @Override
    91 96   public void leaveRegion(MethodNode mth, IRegion region) {
    92  - if (tryBlocksMap.isEmpty())
     97 + if (tryBlocksMap.isEmpty() || !(region instanceof Region)) {
    93 98   return;
    94  - 
    95  - if (!(region instanceof Region))
    96  - return;
    97  - 
     99 + }
    98 100   // search dominator blocks in this region (don't need to go deeper)
    99 101   for (BlockNode dominator : tryBlocksMap.keySet()) {
    100 102   if (region.getSubBlocks().contains(dominator)) {
    skipped 31 lines
    132 134   }
    133 135   }
    134 136   if (newRegion.getSubBlocks().size() != 0) {
    135  - if (DEBUG)
    136  - LOG.debug("MarkTryCatchRegions mark: {}", newRegion);
     137 + if (DEBUG) {
     138 + LOG.debug("ProcessTryCatchRegions mark: {}", newRegion);
     139 + }
    137 140   // replace first node by region
    138 141   IContainer firstNode = newRegion.getSubBlocks().get(0);
    139 142   int i = region.getSubBlocks().indexOf(firstNode);
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/internal/TestTryCatch.java
    skipped 5 lines
    6 6  import org.junit.Test;
    7 7   
    8 8  import static org.hamcrest.CoreMatchers.containsString;
     9 +import static org.hamcrest.CoreMatchers.not;
    9 10  import static org.junit.Assert.assertThat;
    10 11   
    11 12  public class TestTryCatch extends InternalJadxTest {
    skipped 16 lines
    28 29   assertThat(code, containsString("try {"));
    29 30   assertThat(code, containsString("Thread.sleep(50);"));
    30 31   assertThat(code, containsString("} catch (InterruptedException e) {"));
     32 + assertThat(code, not(containsString("return")));
    31 33   }
    32 34  }
    33 35   
Please wait...
Page is in error, reload to recover