git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1347 379699f6-c40d-0410-875b-85095c16579emaster
parent
7714d5d503
commit
14b4dd94f8
@ -0,0 +1,214 @@ |
||||
package net.sf.jode.bytecode; |
||||
import junit.framework.*; |
||||
import java.io.*; |
||||
|
||||
public class BasicBlockWriterTest extends TestCase implements Opcodes { |
||||
public BasicBlockWriterTest(String name) { |
||||
super(name); |
||||
} |
||||
|
||||
GrowableConstantPool gcp = new GrowableConstantPool(); |
||||
Instruction[] someNops; |
||||
Instruction[] manyNops; |
||||
Instruction[] whileHead; |
||||
Instruction[] whileCond; |
||||
Instruction[] whileFoot; |
||||
|
||||
/** |
||||
* The whileHead block in bytecode |
||||
*/ |
||||
private final static String whileHeadStr="\3="; |
||||
/** |
||||
* The whileCond block in bytecode, without the if_icmpeq instruction. |
||||
*/ |
||||
private final static String whileCondStr="\34\33"; |
||||
/** |
||||
* The whileFoot block in bytecode. |
||||
*/ |
||||
private final static String whileFootStr="\204\2\1"; |
||||
/** |
||||
* The someNops block in bytecode, without the if_icmpeq instruction. |
||||
*/ |
||||
private final static String someNopsStr="\0\0"; |
||||
|
||||
public void setUp() { |
||||
Instruction nop = Instruction.forOpcode(opc_nop); |
||||
someNops = new Instruction[] { nop, nop }; |
||||
manyNops = new Instruction[35000]; |
||||
for (int i = 0; i < manyNops.length; i++) |
||||
manyNops[i] = nop; |
||||
|
||||
whileHead = new Instruction[] { |
||||
Instruction.forOpcode(opc_ldc, new Integer(0)), |
||||
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(2)), |
||||
}; |
||||
whileCond = new Instruction[] { |
||||
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(2)), |
||||
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||
Instruction.forOpcode(opc_if_icmpeq) |
||||
}; |
||||
whileFoot = new Instruction[] { |
||||
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(2), 1), |
||||
}; |
||||
} |
||||
|
||||
public byte[] write(BasicBlockWriter bbw) throws IOException { |
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
DataOutputStream dos = new DataOutputStream(baos); |
||||
bbw.write(gcp, dos); |
||||
dos.close(); |
||||
return baos.toByteArray(); |
||||
} |
||||
|
||||
public void testEmpty() throws IOException { |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0)); |
||||
bb.setBlocks(new Block[0], null, new Handler[0]); |
||||
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||
|
||||
assertEquals("Code differs", |
||||
"\0\0\0\1\0\0\0\1" /* no stack, one local, length 1 */ |
||||
+"\261" /* opc_return */ |
||||
+"\0\0" /* no exception handlers */, |
||||
new String(write(bbw))); |
||||
} |
||||
|
||||
public void testSimple() throws IOException { |
||||
Block bb1 = new Block(); |
||||
Block bb2 = new Block(); |
||||
bb1.setCode(someNops, new Block[] {bb2}); |
||||
bb2.setCode(someNops, new Block[] {null}); |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0)); |
||||
bb.setBlocks(new Block[] { bb1, bb2}, bb1, new Handler[0]); |
||||
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||
|
||||
assertEquals("Code differs", |
||||
"\0\0\0\1\0\0\0\5" /* no stack, one local, length 5 */ |
||||
+someNopsStr+someNopsStr+"\261" |
||||
+"\0\0" /* no exception handlers */, |
||||
new String(write(bbw))); |
||||
} |
||||
|
||||
public void testWhile() throws IOException { |
||||
Block b1 = new Block(); |
||||
Block b2 = new Block(); |
||||
Block b3 = new Block(); |
||||
Block b4 = new Block(); |
||||
b1.setCode(whileHead, new Block[] { b2 }); |
||||
b2.setCode(whileCond, new Block[] { null, b3 }); |
||||
b3.setCode(someNops, new Block[] { b4 }); |
||||
b4.setCode(whileFoot, new Block[] { b2 }); |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("a", "(I)V", 0)); |
||||
bb.setBlocks(new Block[] { b1, b2, b3, b4}, b1, new Handler[0]); |
||||
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||
assertEquals(5, bbw.blockAddr.length); |
||||
assertEquals(0, bbw.blockAddr[0]); |
||||
assertEquals(2, bbw.blockAddr[1]); |
||||
assertEquals(7, bbw.blockAddr[2]); |
||||
assertEquals(9, bbw.blockAddr[3]); |
||||
assertEquals(16, bbw.blockAddr[4]); |
||||
|
||||
assertEquals("Code differs", |
||||
"\0\2\0\3\0\0\0\20" |
||||
+whileHeadStr+whileCondStr+"\237\0\13" |
||||
+someNopsStr+whileFootStr+"\247\377\366"+"\261"+"\0\0", |
||||
new String(write(bbw))); |
||||
} |
||||
|
||||
public void testTableSwitch() throws IOException { |
||||
Block b1 = new Block(); |
||||
Block b2 = new Block(); |
||||
Instruction[] switchBlock = new Instruction[] { |
||||
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||
Instruction.forOpcode(opc_lookupswitch, new int[] { 1, 3, 5}) |
||||
}; |
||||
b1.setCode(switchBlock, new Block[] { b2, null, b1, null }); |
||||
b2.setCode(someNops, new Block[] { null }); |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("s", "(I)V", 0)); |
||||
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[0]); |
||||
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||
assertEquals(3, bbw.blockAddr.length); |
||||
assertEquals(0, bbw.blockAddr[0]); |
||||
assertEquals(36, bbw.blockAddr[1]); |
||||
assertEquals(39, bbw.blockAddr[2]); |
||||
assertEquals("Code differs", |
||||
"\0\1\0\2\0\0\0\47" |
||||
+"\33\252\0\0" /*iload_0 + tableswitch + align */ |
||||
+"\0\0\0\45\0\0\0\1\0\0\0\5" /* def, low, high */ |
||||
+"\0\0\0\43\0\0\0\45\0\0\0\45\0\0\0\45\377\377\377\377" |
||||
+someNopsStr+"\261"+"\0\0", |
||||
new String(write(bbw))); |
||||
} |
||||
|
||||
public void testLookupSwitch() throws IOException { |
||||
Block b1 = new Block(); |
||||
Block b2 = new Block(); |
||||
Instruction[] switchBlock = new Instruction[] { |
||||
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||
Instruction.forOpcode(opc_lookupswitch, new int[] { 1, 5, 7}) |
||||
}; |
||||
b1.setCode(switchBlock, new Block[] { b2, null, b1, null }); |
||||
b2.setCode(someNops, new Block[] { null }); |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("s", "(I)V", 0)); |
||||
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[0]); |
||||
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||
assertEquals(3, bbw.blockAddr.length); |
||||
assertEquals(0, bbw.blockAddr[0]); |
||||
assertEquals(36, bbw.blockAddr[1]); |
||||
assertEquals(39, bbw.blockAddr[2]); |
||||
assertEquals("Code differs", |
||||
"\0\1\0\2\0\0\0\47" |
||||
+"\33\253\0\0" /*iload_0 + lookupswitch + align */ |
||||
+"\0\0\0\45\0\0\0\3" /* def , nitem */ |
||||
+"\0\0\0\1\0\0\0\43" |
||||
+"\0\0\0\5\0\0\0\45" |
||||
+"\0\0\0\7\377\377\377\377" |
||||
+someNopsStr+"\261"+"\0\0", |
||||
new String(write(bbw))); |
||||
} |
||||
|
||||
public void testException() throws IOException { |
||||
Block b1 = new Block(); |
||||
Block b2 = new Block(); |
||||
Instruction[] catchInstrs = new Instruction[] { |
||||
Instruction.forOpcode(opc_athrow) |
||||
}; |
||||
b1.setCode(someNops, new Block[] { null }); |
||||
b2.setCode(catchInstrs, new Block[0]); |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("e", "()V", 0)); |
||||
Handler h = new Handler(b1, b1, b2, "java.lang.RuntimeException"); |
||||
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[] {h}); |
||||
assertEquals(0, b1.blockNr); |
||||
assertEquals(1, b2.blockNr); |
||||
assertEquals(1, b1.catchers.length); |
||||
assertEquals(0, b2.catchers.length); |
||||
assertSame(h, b1.catchers[0]); |
||||
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||
int cpoolEntry = gcp.putClassName("java.lang.RuntimeException"); |
||||
assertEquals(3, bbw.blockAddr.length); |
||||
assertEquals(0, bbw.blockAddr[0]); |
||||
assertEquals(3, bbw.blockAddr[1]); |
||||
assertEquals(4, bbw.blockAddr[2]); |
||||
assertEquals("Code differs", |
||||
"\0\1\0\1\0\0\0\4" |
||||
+ someNopsStr + "\261" + "\277" |
||||
+ "\0\1\0\0\0\3\0\3\0"+(char)cpoolEntry, |
||||
new String(write(bbw))); |
||||
} |
||||
|
||||
public static Test suite() { |
||||
TestSuite suite = new TestSuite(); |
||||
suite.addTest(new BasicBlockWriterTest("testEmpty")); |
||||
suite.addTest(new BasicBlockWriterTest("testSimple")); |
||||
suite.addTest(new BasicBlockWriterTest("testWhile")); |
||||
suite.addTest(new BasicBlockWriterTest("testTableSwitch")); |
||||
suite.addTest(new BasicBlockWriterTest("testLookupSwitch")); |
||||
suite.addTest(new BasicBlockWriterTest("testException")); |
||||
return suite; |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
package net.sf.jode.bytecode; |
||||
import junit.framework.*; |
||||
import java.io.*; |
||||
|
||||
public class BasicBlocksTest extends TestCase implements Opcodes { |
||||
public BasicBlocksTest(String name) { |
||||
super(name); |
||||
} |
||||
|
||||
public void testJsr() { |
||||
Block b0 = new Block(); |
||||
Block b1 = new Block(); |
||||
Block b2 = new Block(); |
||||
b0.setCode(new Instruction[] { |
||||
Instruction.forOpcode(opc_jsr) |
||||
}, 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(0)), |
||||
}, new Block[0]); |
||||
assertEquals("pop0", 0, b0.maxpop); |
||||
assertEquals("push0", 0, b0.maxpush); |
||||
assertEquals("delta0", 0, b0.delta); |
||||
assertEquals("pop1", 1, b1.maxpop); |
||||
assertEquals("push1", 0, b1.maxpush); |
||||
assertEquals("delta1", -1, b1.delta); |
||||
assertEquals("pop2", 0, b2.maxpop); |
||||
assertEquals("push2", 0, b2.maxpush); |
||||
assertEquals("delta2", 0, b2.delta); |
||||
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "(I)V", 0)); |
||||
bb.setBlocks(new Block[] { b0, b1, b2 }, b0, new Handler[0]); |
||||
assertEquals("stack0", 0, b0.stackHeight); |
||||
assertEquals("stack1", 1, b1.stackHeight); |
||||
assertEquals("stack2", 0, b2.stackHeight); |
||||
} |
||||
|
||||
public static Test suite() { |
||||
TestSuite suite = new TestSuite(); |
||||
suite.addTest(new BasicBlocksTest("testJsr")); |
||||
return suite; |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
package net.sf.jode.bytecode; |
||||
import junit.framework.*; |
||||
import java.io.*; |
||||
|
||||
public class BlockTest extends TestCase implements Opcodes { |
||||
public BlockTest(String name) { |
||||
super(name); |
||||
} |
||||
|
||||
public void testJsr() { |
||||
Block b1 = new Block(); |
||||
Block b2 = new Block(); |
||||
Instruction jsr = Instruction.forOpcode(opc_jsr); |
||||
b1.setCode(new Instruction[] { jsr }, new Block[] { b2, null } ); |
||||
assertEquals("pop", 0, b1.maxpop); |
||||
assertEquals("push", 0, b1.maxpush); |
||||
assertEquals("delta", 0, b1.delta); |
||||
try { |
||||
b1.setCode(new Instruction[] { jsr }, new Block[] { b2 }); |
||||
fail("jsr must have two successors"); |
||||
} catch (IllegalArgumentException ex) { |
||||
} |
||||
try { |
||||
b1.setCode(new Instruction[] { jsr }, |
||||
new Block[] { null, b2 }); |
||||
fail("jsr succ mustn't be null"); |
||||
} catch (IllegalArgumentException ex) { |
||||
} |
||||
try { |
||||
b1.setCode(new Instruction[] { jsr, |
||||
Instruction.forOpcode(opc_nop) }, |
||||
new Block[] { null, b2 }); |
||||
fail("jsr must be last in block"); |
||||
} catch (IllegalArgumentException ex) { |
||||
} |
||||
|
||||
} |
||||
|
||||
public static Test suite() { |
||||
TestSuite suite = new TestSuite(); |
||||
suite.addTest(new BlockTest("testJsr")); |
||||
return suite; |
||||
} |
||||
} |
@ -0,0 +1,358 @@ |
||||
package net.sf.jode.flow; |
||||
import net.sf.jode.decompiler.LocalInfo; |
||||
import junit.framework.*; |
||||
import net.sf.jode.expr.*; |
||||
import net.sf.jode.type.Type; |
||||
import net.sf.jode.decompiler.TabbedPrintWriter; |
||||
import net.sf.jode.GlobalOptions; |
||||
|
||||
public class TrExcTest extends TestCase { |
||||
private static final boolean VERBOSE = false; |
||||
|
||||
public TrExcTest(String name) { |
||||
super (name); |
||||
} |
||||
|
||||
public void setUp() { |
||||
GlobalOptions.debuggingFlags |= GlobalOptions.DEBUG_CHECK; |
||||
if (VERBOSE) |
||||
GlobalOptions.debuggingFlags |
||||
|= GlobalOptions.DEBUG_ANALYZE | GlobalOptions.DEBUG_FLOW; |
||||
} |
||||
|
||||
FlowBlock[] createFlowBlocks(int n) { |
||||
FlowBlock[] flows = new FlowBlock[n]; |
||||
for (int i = 0; i < n; i++) |
||||
flows[i] = new FlowBlock(null, i, i > 0 ? flows[i-1] : null); |
||||
return flows; |
||||
} |
||||
|
||||
public void testSynchronized11() throws java.io.IOException { |
||||
FlowBlock[] flows = createFlowBlocks(5); |
||||
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||
|
||||
/* Monitorenter */ |
||||
flows[0].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[0].appendBlock |
||||
(new InstructionBlock(new MonitorEnterOperator())); |
||||
flows[0].setSuccessors(new FlowBlock[] { flows[1] }); |
||||
|
||||
/* Synchronized Blocks */ |
||||
flows[1].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[1].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||
flows[1].appendBlock(new JsrBlock()); |
||||
flows[1].setSuccessors(new FlowBlock[] { flows[4], flows[2] }); |
||||
|
||||
flows[2].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||
flows[2].appendBlock |
||||
(new ReturnBlock(new NopOperator(Type.tUObject))); |
||||
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||
|
||||
/* Catch Exception Blocks */ |
||||
flows[3].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[3].appendBlock |
||||
(new InstructionBlock(new MonitorExitOperator())); |
||||
flows[3].appendBlock |
||||
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||
flows[3].setSuccessors(new FlowBlock[0]); |
||||
|
||||
/* monitorexit subroutine */ |
||||
flows[4].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local); |
||||
flows[4].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[4].appendBlock |
||||
(new InstructionBlock(new MonitorExitOperator())); |
||||
flows[4].appendReadBlock |
||||
(new RetBlock(tmp2Local), tmp2Local); |
||||
flows[4].setSuccessors(new FlowBlock[0]); |
||||
|
||||
flows[0].addStartPred(); |
||||
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||
exc.addHandler(flows[1],flows[2],flows[3], null); |
||||
exc.analyze(); |
||||
flows[0].analyze(); |
||||
flows[0].removeStartPred(); |
||||
if (VERBOSE) |
||||
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||
assertTrue(flows[0].getBlock() instanceof SynchronizedBlock); |
||||
assertTrue(flows[0].getBlock().getSubBlocks()[0] |
||||
instanceof ReturnBlock); |
||||
} |
||||
|
||||
public void testSynchronized13() throws java.io.IOException { |
||||
FlowBlock[] flows = createFlowBlocks(5); |
||||
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||
|
||||
/* Monitorenter */ |
||||
flows[0].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[0].appendBlock |
||||
(new InstructionBlock(new MonitorEnterOperator())); |
||||
flows[0].setSuccessors(new FlowBlock[] { flows[1] }); |
||||
|
||||
/* Synchronized Blocks */ |
||||
flows[1].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[1].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||
flows[1].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[1].appendBlock |
||||
(new InstructionBlock(new MonitorExitOperator())); |
||||
flows[1].setSuccessors(new FlowBlock[] { flows[2] }); |
||||
|
||||
flows[2].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||
flows[2].appendBlock |
||||
(new ReturnBlock(new NopOperator(Type.tUObject))); |
||||
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||
|
||||
/* Catch Exception Blocks */ |
||||
flows[3].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[3].appendBlock |
||||
(new InstructionBlock(new MonitorExitOperator())); |
||||
flows[3].appendBlock |
||||
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||
flows[3].setSuccessors(new FlowBlock[0]); |
||||
|
||||
/* monitorexit subroutine */ |
||||
flows[4].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local); |
||||
flows[4].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[4].appendBlock |
||||
(new InstructionBlock(new MonitorExitOperator())); |
||||
flows[4].appendReadBlock |
||||
(new RetBlock(tmp2Local), tmp2Local); |
||||
flows[4].setSuccessors(new FlowBlock[0]); |
||||
|
||||
flows[0].addStartPred(); |
||||
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||
exc.addHandler(flows[1],flows[2],flows[3], null); |
||||
exc.analyze(); |
||||
flows[0].analyze(); |
||||
flows[0].removeStartPred(); |
||||
if (VERBOSE) |
||||
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||
assertTrue(flows[0].getBlock() instanceof SynchronizedBlock); |
||||
assertTrue(flows[0].getBlock().getSubBlocks()[0] |
||||
instanceof ReturnBlock); |
||||
} |
||||
|
||||
public void testSpecialFin() throws java.io.IOException { |
||||
FlowBlock[] flows = createFlowBlocks(3); |
||||
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||
|
||||
/* Try Blocks */ |
||||
flows[0].setSuccessors(new FlowBlock[] { flows[2] }); |
||||
|
||||
/* Catch Exception Blocks */ |
||||
flows[1].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0)); |
||||
flows[1].setSuccessors(new FlowBlock[] { flows[2] }); |
||||
|
||||
/* subroutine */ |
||||
flows[2].appendBlock(new DescriptionBlock("/*FINALLY*/")); |
||||
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||
|
||||
flows[0].addStartPred(); |
||||
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||
exc.analyze(); |
||||
flows[0].analyze(); |
||||
flows[0].removeStartPred(); |
||||
if (VERBOSE) |
||||
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||
assertTrue("Try", flows[0].getBlock() instanceof TryBlock); |
||||
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0] instanceof EmptyBlock); |
||||
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[1] instanceof FinallyBlock); |
||||
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1].getSubBlocks()[0] instanceof DescriptionBlock); |
||||
} |
||||
|
||||
public void testSpecialFinTryLoops() throws java.io.IOException { |
||||
FlowBlock[] flows = createFlowBlocks(3); |
||||
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||
|
||||
/* Try Blocks */ |
||||
flows[0].setSuccessors(new FlowBlock[] { flows[0] }); |
||||
|
||||
/* Catch Exception Blocks */ |
||||
flows[1].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0)); |
||||
flows[1].setSuccessors(new FlowBlock[] { flows[2] }); |
||||
|
||||
/* subroutine */ |
||||
flows[2].appendBlock(new DescriptionBlock("/*FINALLY*/")); |
||||
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||
|
||||
flows[0].addStartPred(); |
||||
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||
exc.analyze(); |
||||
flows[0].analyze(); |
||||
flows[0].removeStartPred(); |
||||
if (VERBOSE) |
||||
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||
assertTrue("Try", flows[0].getBlock() instanceof TryBlock); |
||||
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock); |
||||
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock); |
||||
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[1] instanceof FinallyBlock); |
||||
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1].getSubBlocks()[0] instanceof DescriptionBlock); |
||||
} |
||||
|
||||
public void testFinBreaksJikes() throws java.io.IOException { |
||||
FlowBlock[] flows = createFlowBlocks(5); |
||||
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||
|
||||
/* Try Blocks */ |
||||
flows[0].appendBlock(new JsrBlock()); |
||||
flows[0].setSuccessors(new FlowBlock[] { flows[3], flows[4] }); |
||||
|
||||
/* Catch Exception Blocks */ |
||||
flows[1].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||
flows[1].appendBlock(new JsrBlock()); |
||||
flows[1].setSuccessors(new FlowBlock[] { flows[3], flows[2] }); |
||||
|
||||
flows[2].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||
flows[2].appendBlock |
||||
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||
flows[2].setSuccessors(new FlowBlock[0]); |
||||
|
||||
/* subroutine */ |
||||
flows[3].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0)); |
||||
flows[3].setSuccessors(new FlowBlock[] { flows[4] }); |
||||
|
||||
flows[4].appendBlock(new DescriptionBlock("/*HERE*/")); |
||||
flows[4].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||
|
||||
flows[0].addStartPred(); |
||||
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||
exc.analyze(); |
||||
flows[0].analyze(); |
||||
flows[0].removeStartPred(); |
||||
if (VERBOSE) |
||||
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||
assertTrue("Sequ", flows[0].getBlock() instanceof SequentialBlock); |
||||
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock); |
||||
assertTrue("Try", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof TryBlock); |
||||
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock); |
||||
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1] instanceof FinallyBlock); |
||||
assertTrue("Break", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0] instanceof BreakBlock); |
||||
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1] |
||||
instanceof DescriptionBlock); |
||||
} |
||||
|
||||
public void testFinCondBreaks() throws java.io.IOException { |
||||
FlowBlock[] flows = createFlowBlocks(6); |
||||
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||
|
||||
/* Try Blocks */ |
||||
flows[0].appendBlock(new JsrBlock()); |
||||
flows[0].setSuccessors(new FlowBlock[] { flows[3], flows[5] }); |
||||
|
||||
/* Catch Exception Blocks */ |
||||
flows[1].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||
flows[1].appendBlock(new JsrBlock()); |
||||
flows[1].setSuccessors(new FlowBlock[] { flows[3], flows[2] }); |
||||
|
||||
flows[2].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||
flows[2].appendBlock |
||||
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||
flows[2].setSuccessors(new FlowBlock[0]); |
||||
|
||||
/* subroutine */ |
||||
flows[3].appendWriteBlock |
||||
(new InstructionBlock |
||||
(new StoreInstruction |
||||
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local); |
||||
flows[3].appendReadBlock |
||||
(new InstructionBlock |
||||
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||
flows[3].appendBlock(new ConditionalBlock |
||||
(new CompareUnaryOperator |
||||
(Type.tUObject, Operator.EQUALS_OP))); |
||||
flows[3].setSuccessors(new FlowBlock[] { flows[4], flows[5] }); |
||||
flows[4].appendReadBlock |
||||
(new RetBlock(tmp2Local), tmp2Local); |
||||
flows[4].setSuccessors(new FlowBlock[0]); |
||||
|
||||
flows[5].appendBlock(new DescriptionBlock("/*HERE*/")); |
||||
flows[5].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||
|
||||
flows[0].addStartPred(); |
||||
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||
exc.analyze(); |
||||
flows[0].analyze(); |
||||
flows[0].removeStartPred(); |
||||
if (VERBOSE) |
||||
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||
assertTrue("Sequ", flows[0].getBlock() instanceof SequentialBlock); |
||||
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock); |
||||
assertTrue("Try", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof TryBlock); |
||||
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock); |
||||
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1] instanceof FinallyBlock); |
||||
assertTrue("If", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0] instanceof IfThenElseBlock); |
||||
assertTrue("Break", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0].getSubBlocks()[0] instanceof BreakBlock); |
||||
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1] |
||||
instanceof DescriptionBlock); |
||||
} |
||||
|
||||
public static Test suite() { |
||||
TestSuite suite = new TestSuite(); |
||||
suite.addTest(new TrExcTest("testSynchronized11")); |
||||
suite.addTest(new TrExcTest("testSynchronized13")); |
||||
suite.addTest(new TrExcTest("testSpecialFin")); |
||||
suite.addTest(new TrExcTest("testSpecialFinTryLoops")); |
||||
suite.addTest(new TrExcTest("testFinBreaksJikes")); |
||||
suite.addTest(new TrExcTest("testFinCondBreaks")); |
||||
return suite; |
||||
} |
||||
} |
@ -0,0 +1,186 @@ |
||||
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; |
||||
} |
||||
} |
Loading…
Reference in new issue