You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
6.4 KiB
186 lines
6.4 KiB
package net.sf.jode.obfuscator.modules;
|
|
import net.sf.jode.bytecode.*;
|
|
import net.sf.jode.GlobalOptions;
|
|
import junit.framework.*;
|
|
import java.util.BitSet;
|
|
import java.io.PrintWriter;
|
|
|
|
public class ConstAnaTest extends TestCase implements Opcodes {
|
|
ConstantAnalyzer ca;
|
|
Instruction[] callJsrInstr;
|
|
BasicBlocks jsrMethod;
|
|
|
|
public ConstAnaTest(String name) {
|
|
super(name);
|
|
}
|
|
|
|
public void setUp() {
|
|
ca = new ConstantAnalyzer();
|
|
createJsrMethod();
|
|
}
|
|
|
|
public void createJsrMethod() {
|
|
callJsrInstr = new Instruction[] {
|
|
Instruction.forOpcode(opc_jsr)
|
|
};
|
|
|
|
Block b0 = new Block();
|
|
Block b1 = new Block();
|
|
Block b2 = new Block();
|
|
b0.setCode(callJsrInstr, new Block[] { b1, null });
|
|
b1.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)),
|
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), -1),
|
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
|
|
Instruction.forOpcode(opc_ifeq)
|
|
}, new Block[] { b2, b0 });
|
|
b2.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(2)),
|
|
}, new Block[0]);
|
|
jsrMethod = new BasicBlocks(new MethodInfo("foo", "(I)V", 0));
|
|
jsrMethod.setBlocks(new Block[] { b0, b1, b2 },
|
|
b0, new Handler[0]);
|
|
}
|
|
|
|
public void testSimple() throws Exception {
|
|
Block b0 = new Block();
|
|
Block b1 = new Block();
|
|
Block b2 = new Block();
|
|
b0.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), 1),
|
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(2), 1),
|
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(3), 1),
|
|
}, new Block[] { b1 });
|
|
b1.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_ldc, new Integer(0)),
|
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(1)),
|
|
Instruction.forOpcode(opc_ldc, new Integer(4)),
|
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(2)),
|
|
Instruction.forOpcode(opc_ldc, new Integer(0)),
|
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(3)),
|
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
|
|
Instruction.forOpcode(opc_ifeq)
|
|
}, new Block[] { b2, b0 });
|
|
b2.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), 1),
|
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
|
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(2)),
|
|
Instruction.forOpcode(opc_if_icmplt)
|
|
}, new Block[] { b2, null });
|
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0));
|
|
bb.setBlocks(new Block[] { b0, b1, b2 }, b1, new Handler[0]);
|
|
|
|
ca.analyzeCode(null, bb);
|
|
|
|
BitSet reachable = (BitSet) ca.bbInfos.get(bb);
|
|
assertEquals("Reachable set",
|
|
"{1, 2}", reachable.toString());
|
|
assertEquals("constant flow",
|
|
ca.CONSTANTFLOW,
|
|
Class.forName("net.sf.jode.obfuscator.modules.ConstantAnalyzer$ConstantInfo")
|
|
.getDeclaredField("flags")
|
|
.getInt(ca.constantInfos.get(b1.getInstructions()[7])));
|
|
ca.transformCode(bb);
|
|
|
|
Block[] blocks = bb.getBlocks();
|
|
assertEquals(2, blocks.length);
|
|
assertEquals(1, blocks[0].getSuccs().length);
|
|
assertEquals(blocks[1], blocks[0].getSuccs()[0]);
|
|
assertEquals(2, blocks[1].getSuccs().length);
|
|
assertEquals(blocks[1], blocks[1].getSuccs()[0]);
|
|
assertEquals(null, blocks[1].getSuccs()[1]);
|
|
}
|
|
|
|
public void testJsr() throws Exception {
|
|
Block[] blocks = jsrMethod.getBlocks();
|
|
|
|
ca.analyzeCode(null, jsrMethod);
|
|
|
|
BitSet reachable = (BitSet) ca.bbInfos.get(jsrMethod);
|
|
assertEquals("Reachable set",
|
|
"{0, 1, 2}", reachable.toString());
|
|
ca.transformCode(jsrMethod);
|
|
|
|
blocks = jsrMethod.getBlocks();
|
|
assertEquals(3, blocks.length);
|
|
assertEquals(2, blocks[0].getSuccs().length);
|
|
assertEquals(blocks[1], blocks[0].getSuccs()[0]);
|
|
assertEquals(null, blocks[0].getSuccs()[1]);
|
|
assertEquals(2, blocks[1].getSuccs().length);
|
|
assertEquals(0, blocks[2].getSuccs().length);
|
|
}
|
|
|
|
public void testNestedJsr() throws Exception {
|
|
Block b0 = new Block();
|
|
Block b1 = new Block();
|
|
Block b2 = new Block();
|
|
Block b3 = new Block();
|
|
Block b4 = new Block();
|
|
Block b5 = new Block();
|
|
Block b6 = new Block();
|
|
Block b7 = new Block();
|
|
Block b8 = new Block();
|
|
Block b9 = new Block();
|
|
|
|
b0.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_jsr)
|
|
}, new Block[] { b2, b1 });
|
|
b1.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_jsr)
|
|
}, new Block[] { b5, null });
|
|
b2.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)),
|
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
|
|
Instruction.forOpcode(opc_ifeq)
|
|
}, new Block[] { b3, b7 });
|
|
b3.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_jsr)
|
|
}, new Block[] { b5, b1 });
|
|
b4.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(2)),
|
|
}, new Block[0]);
|
|
b5.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(3)),
|
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(3)),
|
|
}, new Block[0]);
|
|
b6.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(3))
|
|
}, new Block[] { b4 });
|
|
b7.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
|
|
Instruction.forOpcode(opc_ifeq)
|
|
}, new Block[] { b8, b4 });
|
|
b8.setCode(new Instruction[] {
|
|
Instruction.forOpcode(opc_jsr)
|
|
}, new Block[] { b6, b9 });
|
|
b9.setCode(new Instruction[0], new Block[] { b7 });
|
|
|
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "(I)V", 0));
|
|
bb.setBlocks(new Block[] { b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 },
|
|
b0, new Handler[0]);
|
|
ca.analyzeCode(null, bb);
|
|
|
|
BitSet reachable = (BitSet) ca.bbInfos.get(bb);
|
|
assertEquals("Reachable set",
|
|
"{0, 1, 2, 3, 4, 5, 6, 7, 8}", reachable.toString());
|
|
assertNotNull("Constant Flow",
|
|
ca.constantInfos.get(b8.getInstructions()[0]));
|
|
|
|
ca.transformCode(bb);
|
|
|
|
Block[] blocks = bb.getBlocks();
|
|
assertEquals(9, blocks.length);
|
|
assertEquals(2, blocks[0].getSuccs().length);
|
|
assertEquals(2, blocks[1].getSuccs().length);
|
|
assertEquals(2, blocks[3].getSuccs().length);
|
|
assertEquals(1, blocks[8].getSuccs().length);
|
|
}
|
|
|
|
public static Test suite() {
|
|
TestSuite suite = new TestSuite();
|
|
suite.addTest(new ConstAnaTest("testSimple"));
|
|
suite.addTest(new ConstAnaTest("testJsr"));
|
|
suite.addTest(new ConstAnaTest("testNestedJsr"));
|
|
return suite;
|
|
}
|
|
}
|
|
|