Remove unneeded 'return' instructions
This commit is contained in:
@@ -4,6 +4,7 @@ import jadx.Consts;
|
||||
import jadx.dex.attributes.AttrNode;
|
||||
import jadx.dex.attributes.AttributeFlag;
|
||||
import jadx.dex.attributes.JumpAttribute;
|
||||
import jadx.dex.attributes.LoopAttr;
|
||||
import jadx.dex.attributes.annotations.Annotation;
|
||||
import jadx.dex.info.AccessInfo;
|
||||
import jadx.dex.info.AccessInfo.AFType;
|
||||
@@ -64,6 +65,7 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
|
||||
private IContainer region;
|
||||
private List<ExceptionHandler> exceptionHandlers;
|
||||
private List<LoopAttr> loops = Collections.emptyList();
|
||||
|
||||
public MethodNode(ClassNode classNode, Method mthData) {
|
||||
this.mthInfo = MethodInfo.fromDex(classNode.dex(), mthData.getMethodIndex());
|
||||
@@ -411,6 +413,21 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
this.exitBlocks.add(exitBlock);
|
||||
}
|
||||
|
||||
public void registerLoop(LoopAttr loop) {
|
||||
if(loops.isEmpty()) {
|
||||
loops = new ArrayList<LoopAttr>(5);
|
||||
}
|
||||
loops.add(loop);
|
||||
}
|
||||
|
||||
public LoopAttr getLoopForBlock(BlockNode block) {
|
||||
for (LoopAttr loop : loops) {
|
||||
if(loop.getLoopBlocks().contains(block))
|
||||
return loop;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ExceptionHandler addExceptionHandler(ExceptionHandler handler) {
|
||||
if (exceptionHandlers == null) {
|
||||
exceptionHandlers = new ArrayList<ExceptionHandler>(2);
|
||||
|
||||
@@ -180,6 +180,8 @@ public class BlockMakerVisitor extends AbstractVisitor {
|
||||
if (i > 100)
|
||||
throw new AssertionError("Can't fix method cfg: " + mth);
|
||||
}
|
||||
|
||||
registerLoops(mth);
|
||||
}
|
||||
|
||||
private static BlockNode getBlock(int offset, Map<Integer, BlockNode> blocksMap) {
|
||||
@@ -307,6 +309,16 @@ public class BlockMakerVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerLoops(MethodNode mth) {
|
||||
for (BlockNode block : mth.getBasicBlocks()) {
|
||||
AttributesList attributes = block.getAttributes();
|
||||
IAttribute loop = attributes.get(AttributeType.LOOP);
|
||||
if(loop != null && attributes.contains(AttributeFlag.LOOP_START)) {
|
||||
mth.registerLoop((LoopAttr) loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean modifyBlocksTree(MethodNode mth) {
|
||||
for (BlockNode block : mth.getBasicBlocks()) {
|
||||
if (block.getPredecessors().isEmpty() && block != mth.getEnterBlock()) {
|
||||
|
||||
@@ -1,33 +1,50 @@
|
||||
package jadx.dex.visitors.regions;
|
||||
|
||||
import jadx.dex.instructions.InsnType;
|
||||
import jadx.dex.instructions.args.ArgType;
|
||||
import jadx.dex.nodes.BlockNode;
|
||||
import jadx.dex.nodes.IBlock;
|
||||
import jadx.dex.nodes.IRegion;
|
||||
import jadx.dex.nodes.InsnNode;
|
||||
import jadx.dex.nodes.MethodNode;
|
||||
import jadx.dex.regions.LoopRegion;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class FinishRegions implements IRegionVisitor {
|
||||
|
||||
public class FinishRegions extends TracedRegionVisitor {
|
||||
@Override
|
||||
public void processBlock(MethodNode mth, IBlock block) {
|
||||
public void processBlockTraced(MethodNode mth, IBlock container, IRegion currentRegion) {
|
||||
if (container.getClass() != BlockNode.class)
|
||||
return;
|
||||
|
||||
// remove return from class init method
|
||||
if (mth.getMethodInfo().isClassInit()) {
|
||||
BlockNode block = (BlockNode) container;
|
||||
|
||||
// remove last return in void functions
|
||||
if (block.getCleanSuccessors().isEmpty()
|
||||
&& mth.getReturnType().equals(ArgType.VOID)) {
|
||||
List<InsnNode> insns = block.getInstructions();
|
||||
if (insns.size() != 0) {
|
||||
InsnNode last = insns.get(insns.size() - 1);
|
||||
if (last.getType() == InsnType.RETURN) {
|
||||
insns.remove(insns.size() - 1);
|
||||
int lastIndex = insns.size() - 1;
|
||||
if (lastIndex != -1) {
|
||||
InsnNode last = insns.get(lastIndex);
|
||||
if (last.getType() == InsnType.RETURN
|
||||
&& blockNotInLoop(mth, block)) {
|
||||
insns.remove(lastIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterRegion(MethodNode mth, IRegion region) {
|
||||
private boolean blockNotInLoop(MethodNode mth, BlockNode block) {
|
||||
if (mth.getLoopForBlock(block) != null)
|
||||
return false;
|
||||
|
||||
for (Iterator<IRegion> it = regionStack.descendingIterator(); it.hasNext(); ) {
|
||||
IRegion region = it.next();
|
||||
if (region.getClass() == LoopRegion.class)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,6 +53,6 @@ public class FinishRegions implements IRegionVisitor {
|
||||
LoopRegion loop = (LoopRegion) region;
|
||||
loop.mergePreCondition();
|
||||
}
|
||||
super.leaveRegion(mth, region);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import jadx.dex.nodes.IBlock;
|
||||
import jadx.dex.nodes.IRegion;
|
||||
import jadx.dex.nodes.MethodNode;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
public abstract class TracedRegionVisitor implements IRegionVisitor {
|
||||
|
||||
private final Stack<IRegion> regionStack = new Stack<IRegion>();
|
||||
protected final Deque<IRegion> regionStack = new ArrayDeque<IRegion>();
|
||||
|
||||
@Override
|
||||
public void enterRegion(MethodNode mth, IRegion region) {
|
||||
@@ -27,5 +28,4 @@ public abstract class TracedRegionVisitor implements IRegionVisitor {
|
||||
public void leaveRegion(MethodNode mth, IRegion region) {
|
||||
regionStack.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user