Commit 9cea0163 authored by Skylot's avatar Skylot

core: fix BlockNode hashCode function

parent 577176dd
...@@ -10,7 +10,7 @@ import java.util.Set; ...@@ -10,7 +10,7 @@ import java.util.Set;
public class IgnoreEdgeAttr implements IAttribute { public class IgnoreEdgeAttr implements IAttribute {
private final Set<BlockNode> blocks = new HashSet<BlockNode>(); private final Set<BlockNode> blocks = new HashSet<BlockNode>(3);
public Set<BlockNode> getBlocks() { public Set<BlockNode> getBlocks() {
return blocks; return blocks;
......
...@@ -179,7 +179,7 @@ public class BlockNode extends AttrNode implements IBlock { ...@@ -179,7 +179,7 @@ public class BlockNode extends AttrNode implements IBlock {
@Override @Override
public int hashCode() { public int hashCode() {
return id; // TODO id can change during reindex return startOffset;
} }
@Override @Override
...@@ -187,23 +187,11 @@ public class BlockNode extends AttrNode implements IBlock { ...@@ -187,23 +187,11 @@ public class BlockNode extends AttrNode implements IBlock {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) {
return false;
}
if (hashCode() != obj.hashCode()) {
return false;
}
if (!(obj instanceof BlockNode)) { if (!(obj instanceof BlockNode)) {
return false; return false;
} }
BlockNode other = (BlockNode) obj; BlockNode other = (BlockNode) obj;
if (id != other.id) { return id == other.id && startOffset == other.startOffset;
return false;
}
if (startOffset != other.startOffset) {
return false;
}
return true;
} }
@Override @Override
......
...@@ -86,6 +86,17 @@ public class SimplifyVisitor extends AbstractVisitor { ...@@ -86,6 +86,17 @@ public class SimplifyVisitor extends AbstractVisitor {
} }
break; break;
case MOVE:
InsnArg firstArg = insn.getArg(0);
if (firstArg.isLiteral()) {
InsnNode constInsn = new InsnNode(InsnType.CONST, 1);
constInsn.setResult(insn.getResult());
constInsn.addArg(firstArg);
constInsn.copyAttributesFrom(insn);
return constInsn;
}
break;
default: default:
break; break;
} }
......
...@@ -359,7 +359,7 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -359,7 +359,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
BlockNode sOut = out.getSecond(); BlockNode sOut = out.getSecond();
// redirect out edges // redirect out edges
List<BlockNode> filtPreds = filterPredecessors(sOut); List<BlockNode> filtPreds = BlockUtils.filterPredecessors(sOut);
if (filtPreds.size() > 1) { if (filtPreds.size() > 1) {
BlockNode pred = sOut.getPredecessors().get(0); BlockNode pred = sOut.getPredecessors().get(0);
BlockNode newPred = BlockSplitter.insertBlockBetween(mth, pred, sOut); BlockNode newPred = BlockSplitter.insertBlockBetween(mth, pred, sOut);
...@@ -446,18 +446,6 @@ public class BlockFinallyExtract extends AbstractVisitor { ...@@ -446,18 +446,6 @@ public class BlockFinallyExtract extends AbstractVisitor {
edgeAttr.getBlocks().add(toBlock); edgeAttr.getBlocks().add(toBlock);
} }
private static List<BlockNode> filterPredecessors(BlockNode block) {
List<BlockNode> predecessors = block.getPredecessors();
List<BlockNode> list = new ArrayList<BlockNode>(predecessors.size());
for (BlockNode pred : predecessors) {
IgnoreEdgeAttr edgeAttr = pred.get(AType.IGNORE_EDGE);
if (edgeAttr == null || !edgeAttr.contains(block)) {
list.add(pred);
}
}
return list;
}
private static int countInstructions(ExceptionHandler excHandler) { private static int countInstructions(ExceptionHandler excHandler) {
int totalSize = 0; int totalSize = 0;
for (BlockNode excBlock : excHandler.getBlocks()) { for (BlockNode excBlock : excHandler.getBlocks()) {
......
...@@ -315,11 +315,19 @@ public class BlockProcessor extends AbstractVisitor { ...@@ -315,11 +315,19 @@ public class BlockProcessor extends AbstractVisitor {
return false; return false;
} }
BlockNode exitBlock = mth.getExitBlocks().get(0); BlockNode exitBlock = mth.getExitBlocks().get(0);
if (exitBlock.getPredecessors().size() > 1 if (exitBlock.getInstructions().size() != 1
&& exitBlock.getInstructions().size() == 1 || exitBlock.contains(AFlag.SYNTHETIC)) {
&& !exitBlock.contains(AFlag.SYNTHETIC)) { return false;
}
List<BlockNode> preds = exitBlock.getPredecessors();
if (preds.size() < 2) {
return false;
}
preds = BlockUtils.filterPredecessors(exitBlock);
if (preds.size() < 2) {
return false;
}
InsnNode returnInsn = exitBlock.getInstructions().get(0); InsnNode returnInsn = exitBlock.getInstructions().get(0);
List<BlockNode> preds = new ArrayList<BlockNode>(exitBlock.getPredecessors());
if (returnInsn.getArgsCount() != 0 && !isReturnArgAssignInPred(preds, returnInsn)) { if (returnInsn.getArgsCount() != 0 && !isReturnArgAssignInPred(preds, returnInsn)) {
return false; return false;
} }
...@@ -342,8 +350,6 @@ public class BlockProcessor extends AbstractVisitor { ...@@ -342,8 +350,6 @@ public class BlockProcessor extends AbstractVisitor {
cleanExitNodes(mth); cleanExitNodes(mth);
return true; return true;
} }
return false;
}
private static boolean isReturnArgAssignInPred(List<BlockNode> preds, InsnNode returnInsn) { private static boolean isReturnArgAssignInPred(List<BlockNode> preds, InsnNode returnInsn) {
RegisterArg arg = (RegisterArg) returnInsn.getArg(0); RegisterArg arg = (RegisterArg) returnInsn.getArg(0);
......
...@@ -2,6 +2,7 @@ package jadx.core.utils; ...@@ -2,6 +2,7 @@ package jadx.core.utils;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.IgnoreEdgeAttr;
import jadx.core.dex.attributes.nodes.PhiListAttr; import jadx.core.dex.attributes.nodes.PhiListAttr;
import jadx.core.dex.instructions.IfNode; import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
...@@ -79,6 +80,25 @@ public class BlockUtils { ...@@ -79,6 +80,25 @@ public class BlockUtils {
return ret; return ret;
} }
/**
* Return predecessors list without blocks contains 'IGNORE_EDGE' attribute.
*
* @return new list of filtered predecessors
*/
public static List<BlockNode> filterPredecessors(BlockNode block) {
List<BlockNode> predecessors = block.getPredecessors();
List<BlockNode> list = new ArrayList<BlockNode>(predecessors.size());
for (BlockNode pred : predecessors) {
IgnoreEdgeAttr edgeAttr = pred.get(AType.IGNORE_EDGE);
if (edgeAttr == null) {
list.add(pred);
} else if (!edgeAttr.contains(block)) {
list.add(pred);
}
}
return list;
}
public static boolean isBackEdge(BlockNode from, BlockNode to) { public static boolean isBackEdge(BlockNode from, BlockNode to) {
if (to == null) { if (to == null) {
return false; return false;
......
...@@ -30,7 +30,6 @@ public class TestFinallyExtract extends IntegrationTest { ...@@ -30,7 +30,6 @@ public class TestFinallyExtract extends IntegrationTest {
@Test @Test
public void test() { public void test() {
setOutputCFG();
ClassNode cls = getClassNode(TestCls.class); ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString(); String code = cls.getCode().toString();
......
package jadx.tests.integration.trycatch;
import jadx.core.clsp.NClass;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestTryCatchFinally2 extends IntegrationTest {
public static class TestCls {
private NClass[] classes;
public void test(OutputStream output) throws IOException {
DataOutputStream out = new DataOutputStream(output);
try {
out.writeByte(1);
out.writeInt(classes.length);
for (NClass cls : classes) {
writeString(out, cls.getName());
}
for (NClass cls : classes) {
NClass[] parents = cls.getParents();
out.writeByte(parents.length);
for (NClass parent : parents) {
out.writeInt(parent.getId());
}
}
} finally {
out.close();
}
}
private void writeString(DataOutputStream out, String name) {
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("} finally {"));
assertThat(code, containsOne("out.close();"));
assertThat(code, containsOne("for (NClass parent : parents) {"));
// TODO
// assertThat(code, countString(2, "for (NClass cls : classes) {"));
assertThat(code, containsOne("for (NClass cls : this.classes) {"));
assertThat(code, containsOne("for (NClass cls2 : this.classes) {"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment