Adapted to new bytecode package.

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1245 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 25 years ago
parent 723088e8be
commit b53430f5c5
  1. 1523
      jode/jode/jvm/CodeVerifier.java
  2. 1127
      jode/jode/jvm/CodeVerifier.java.in
  3. 76
      jode/jode/jvm/Interpreter.java
  4. 8
      jode/jode/jvm/Makefile.am
  5. 194
      jode/jode/jvm/SyntheticAnalyzer.java

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -20,7 +20,8 @@
package jode.jvm;
import jode.AssertError;
import jode.GlobalOptions;
import jode.bytecode.BytecodeInfo;
import jode.bytecode.BasicBlocks;
import jode.bytecode.Block;
import jode.bytecode.Handler;
import jode.bytecode.Instruction;
import jode.bytecode.Opcodes;
@ -29,7 +30,10 @@ import jode.bytecode.TypeSignature;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import @COLLECTIONS@.Arrays;
///#def COLLECTIONS java.util
import java.util.Arrays;
import java.util.Iterator;
///#enddef
/**
* This class is a java virtual machine written in java :-). Well not
@ -59,16 +63,16 @@ public class Interpreter implements Opcodes {
this.env = env;
}
private Value[] fillParameters(BytecodeInfo code,
private Value[] fillParameters(BasicBlocks bb,
Object cls, Object[] params) {
Value[] locals = new Value[code.getMaxLocals()];
Value[] locals = new Value[bb.getMaxLocals()];
for (int i=0; i< locals.length; i++)
locals[i] = new Value();
String myType = code.getMethodInfo().getType();
String myType = bb.getMethodInfo().getType();
String[] myParamTypes = TypeSignature.getParameterTypes(myType);
int slot = 0;
if (!code.getMethodInfo().isStatic())
if (!bb.getMethodInfo().isStatic())
locals[slot++].setObject(cls);
for (int i=0; i< myParamTypes.length; i++) {
locals[slot].setObject(params[i]);
@ -77,24 +81,39 @@ public class Interpreter implements Opcodes {
return locals;
}
public Object interpretMethod(BytecodeInfo code,
public Object interpretMethod(BasicBlocks bb,
Object instance, Object[] myParams)
throws InterpreterException, InvocationTargetException {
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_INTERPRT) != 0)
GlobalOptions.err.println("Interpreting "+code);
GlobalOptions.err.println("Interpreting "+bb);
Value[] locals = fillParameters(code, instance, myParams);
Value[] stack = new Value[code.getMaxStack()];
Value[] locals = fillParameters(bb, instance, myParams);
Value[] stack = new Value[bb.getMaxStack()];
for (int i=0; i < stack.length; i++)
stack[i] = new Value();
Instruction pc = (Instruction) code.getInstructions().get(0);
Block[] blocks = bb.getBlocks();
Block nextBlock = bb.getStartBlock();
int stacktop = 0;
Block[] succs = null;
Handler[] handlers = null;
Iterator iter = null;
big_loop:
for(;;) {
if (iter == null || !iter.hasNext()) {
/* If block is over continue with the next block */
if (nextBlock == null)
return Void.TYPE;
iter = nextBlock.getInstructions().iterator();
succs = nextBlock.getSuccs();
handlers = nextBlock.getCatchers();
nextBlock = succs.length > 0 ? succs[succs.length - 1] : null;
}
try {
Instruction instr = pc;
Instruction instr = (Instruction) iter.next();
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_INTERPRT) != 0) {
GlobalOptions.err.println(instr.getDescription());
@ -114,7 +133,6 @@ public class Interpreter implements Opcodes {
GlobalOptions.err.print(locals[i]+",");
GlobalOptions.err.println("]");
}
pc = instr.getNextByAddr();
int opcode = instr.getOpcode();
switch (opcode) {
case opc_nop:
@ -572,28 +590,26 @@ public class Interpreter implements Opcodes {
int opc_mask = 1 << opcode;
if (value > 0 && (opc_mask & CMP_GREATER_MASK) != 0
|| value < 0 && (opc_mask & CMP_LESS_MASK) != 0
|| value == 0 && (opc_mask & CMP_EQUAL_MASK) != 0)
pc = instr.getSingleSucc();
|| value == 0 && (opc_mask & CMP_EQUAL_MASK) != 0) {
nextBlock = succs[0];
}
break;
}
case opc_jsr:
case opc_jsr_w:
stack[stacktop++].setObject(instr);
/* fall through */
case opc_goto:
case opc_goto_w:
pc = instr.getSingleSucc();
stack[stacktop++].setObject(nextBlock);
nextBlock = succs[0];
break;
case opc_ret:
pc = (Instruction)locals[instr.getLocalSlot()].objectValue();
nextBlock
= (Block) locals[instr.getLocalSlot()].objectValue();
break;
case opc_lookupswitch: {
int value = stack[--stacktop].intValue();
int[] values = instr.getValues();
int pos = Arrays.binarySearch(values, value);
pc = pos < 0
? instr.getSuccs()[values.length]
: instr.getSuccs()[pos];
if (pos >= 0)
nextBlock = succs[pos];
break;
}
case opc_ireturn: case opc_freturn: case opc_areturn:
@ -734,16 +750,14 @@ public class Interpreter implements Opcodes {
throw new AssertError("Invalid opcode "+opcode);
}
} catch (InvocationTargetException ex) {
Handler[] handlers = code.getExceptionHandlers();
iter = null;
Throwable obj = ex.getTargetException();
for (int i=0; i< handlers.length; i++) {
if (handlers[i].start.compareTo(pc) <= 0
&& handlers[i].end.compareTo(pc) >= 0
&& (handlers[i].type == null
|| env.instanceOf(obj, handlers[i].type))) {
for (int i=0; i < handlers.length; i++) {
if (handlers[i].getType() == null
|| env.instanceOf(obj, handlers[i].getType())) {
stacktop = 0;
stack[stacktop++].setObject(obj);
pc = handlers[i].catcher;
nextBlock = handlers[i].getCatcher();
continue big_loop;
}
}

@ -1,10 +1,8 @@
## Input file for automake to generate the Makefile.in used by configure
JAR = @JAR@
JAVAC = @JAVAC@
JAVADEP = $(top_builddir)/javaDependencies.pl -subdir=$(subdir)\
-dependdir=$(top_builddir) -classpath=$(top_builddir):$(top_srcdir) \
-depfile=Makefile.dep
JAVADEP = $(PERL) -w -s $(top_srcdir)/scripts/javaDependencies.pl \
-subdir=$(subdir) -dependdir=$(top_builddir) \
-classpath=$(top_builddir):$(top_srcdir) -depfile=Makefile.dep
CLASSPATH = @CLASSPATH@
CLASSLIB = @CLASSLIB@
SUBSTCP = @SUBSTCP@

@ -19,7 +19,8 @@
package jode.jvm;
import jode.GlobalOptions;
import jode.bytecode.BytecodeInfo;
import jode.bytecode.BasicBlocks;
import jode.bytecode.Block;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.Handler;
@ -32,7 +33,9 @@ import jode.type.MethodType;
import java.lang.reflect.Modifier;
import @COLLECTIONS@.Iterator;
///#def COLLECTIONS java.util
import java.util.Iterator;
///#enddef
public class SyntheticAnalyzer implements Opcodes {
public final static int UNKNOWN = 0;
@ -47,11 +50,14 @@ public class SyntheticAnalyzer implements Opcodes {
int kind = UNKNOWN;
Reference reference;
ClassInfo classInfo;
MethodInfo method;
public SyntheticAnalyzer(MethodInfo method, boolean checkName) {
public SyntheticAnalyzer(ClassInfo classInfo, MethodInfo method,
boolean checkName) {
this.classInfo = classInfo;
this.method = method;
if (method.getBytecode() == null)
if (method.getBasicBlocks() == null)
return;
if (!checkName || method.getName().equals("class$"))
if (checkGetClass())
@ -94,37 +100,50 @@ public class SyntheticAnalyzer implements Opcodes {
.equals("(Ljava/lang/String;)Ljava/lang/Class;")))
return false;
BytecodeInfo bytecode = method.getBytecode();
BasicBlocks bb = method.getBasicBlocks();
Handler[] excHandlers = bytecode.getExceptionHandlers();
if (excHandlers.length != 1
|| !"java.lang.ClassNotFoundException".equals(excHandlers[0].type))
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock();
Handler[] excHandlers = bb.getExceptionHandlers();
if (startBlock == null
|| startBlock.getInstructions().size() != 3
|| excHandlers.length != 1
|| excHandlers[0].getStart() != startBlock
|| excHandlers[0].getEnd() != startBlock
|| !"java.lang.ClassNotFoundException"
.equals(excHandlers[0].getType()))
return false;
int excSlot = -1;
int i = 0;
for (Iterator iter = bytecode.getInstructions().iterator(); iter.hasNext(); i++) {
Instruction instr = (Instruction) iter.next();
if (i == getClassOpcodes.length
|| instr.getOpcode() != getClassOpcodes[i])
for (int i=0; i< 3; i++) {
Instruction instr =
(Instruction) startBlock.getInstructions().get(i);
if (instr.getOpcode() != getClassOpcodes[i])
return false;
if (i == 0 && (instr.getLocalSlot() != 0
|| excHandlers[0].start != instr))
if (getClassRefs[i] != null
&& !getClassRefs[i].equals(instr.getReference()))
return false;
if (i == 2 && excHandlers[0].end != instr)
if (i == 0 && instr.getLocalSlot() != 0)
return false;
if (i == 3) {
if (excHandlers[0].catcher != instr)
return false;
}
Block catchBlock = excHandlers[0].getCatcher();
if (catchBlock.getInstructions().size() != 7)
return false;
int excSlot = -1;
for (int i=0; i< 7; i++) {
Instruction instr = (Instruction)
catchBlock.getInstructions().get(i);
if (instr.getOpcode() != getClassOpcodes[3+i])
return false;
if (getClassRefs[3+i] != null
&& !getClassRefs[3+i].equals(instr.getReference()))
return false;
if (i == 0)
excSlot = instr.getLocalSlot();
}
if (i == 4 && !instr.getClazzType().equals
if (i == 1 && !instr.getClazzType().equals
("Ljava/lang/NoClassDefFoundError;"))
return false;
if (i == 6 && instr.getLocalSlot() != excSlot)
return false;
if (getClassRefs[i] != null
&& !getClassRefs[i].equals(instr.getReference()))
if (i == 3 && instr.getLocalSlot() != excSlot)
return false;
}
this.kind = GETCLASS;
@ -135,22 +154,35 @@ public class SyntheticAnalyzer implements Opcodes {
Modifier.PUBLIC | Modifier.STATIC);
public boolean checkStaticAccess() {
ClassInfo clazzInfo = method.getClazzInfo();
BytecodeInfo bytecode = method.getBytecode();
Iterator iter = bytecode.getInstructions().iterator();
BasicBlocks bb = method.getBasicBlocks();
Handler[] excHandlers = bb.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0)
return false;
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock();
if (startBlock == null)
return false;
Block[] succBlocks = startBlock.getSuccs();
if (succBlocks.length > 1 ||
(succBlocks.length == 1 && succBlocks[0] != null))
return false;
Iterator iter = startBlock.getInstructions().iterator();
if (!iter.hasNext())
return false;
Instruction instr = (Instruction) iter.next();
if (instr.getOpcode() == opc_getstatic) {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
FieldInfo refField
= clazzInfo.findField(ref.getName(), ref.getType());
= classInfo.findField(ref.getName(), ref.getType());
if ((refField.getModifiers() & modifierMask) !=
(Modifier.PRIVATE | Modifier.STATIC))
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
@ -167,6 +199,8 @@ public class SyntheticAnalyzer implements Opcodes {
params++;
slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
}
if (instr.getOpcode() == opc_putstatic) {
@ -176,13 +210,15 @@ public class SyntheticAnalyzer implements Opcodes {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
FieldInfo refField
= clazzInfo.findField(ref.getName(), ref.getType());
= classInfo.findField(ref.getName(), ref.getType());
if ((refField.getModifiers() & modifierMask) !=
(Modifier.PRIVATE | Modifier.STATIC))
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_return)
return false;
@ -194,20 +230,25 @@ public class SyntheticAnalyzer implements Opcodes {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
MethodInfo refMethod
= clazzInfo.findMethod(ref.getName(), ref.getType());
= classInfo.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(ref.getType());
if ((refMethod.getModifiers() & modifierMask) !=
(Modifier.PRIVATE | Modifier.STATIC)
|| refType.getParameterTypes().length != params)
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (refType.getReturnType() == Type.tVoid) {
if (instr.getOpcode() != opc_return)
if (iter.hasNext())
return false;
} else {
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
return false;
@ -222,33 +263,46 @@ public class SyntheticAnalyzer implements Opcodes {
}
public boolean checkAccess() {
ClassInfo clazzInfo = method.getClazzInfo();
BytecodeInfo bytecode = method.getBytecode();
Handler[] excHandlers = bytecode.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0)
return false;
if (method.isStatic()) {
if (checkStaticAccess())
return true;
}
Iterator iter = bytecode.getInstructions().iterator();
BasicBlocks bb = method.getBasicBlocks();
Handler[] excHandlers = bb.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0)
return false;
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock();
if (startBlock == null)
return false;
Block[] succBlocks = startBlock.getSuccs();
if (succBlocks.length > 1 ||
(succBlocks.length == 1 && succBlocks[0] != null))
return false;
Iterator iter = startBlock.getInstructions().iterator();
if (!iter.hasNext())
return false;
Instruction instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0)
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() == opc_getfield) {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
FieldInfo refField
= clazzInfo.findField(ref.getName(), ref.getType());
= classInfo.findField(ref.getName(), ref.getType());
if ((refField.getModifiers() & modifierMask) != Modifier.PRIVATE)
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
@ -265,6 +319,8 @@ public class SyntheticAnalyzer implements Opcodes {
params++;
slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
}
if (instr.getOpcode() == opc_putfield) {
@ -274,14 +330,13 @@ public class SyntheticAnalyzer implements Opcodes {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
FieldInfo refField
= clazzInfo.findField(ref.getName(), ref.getType());
= classInfo.findField(ref.getName(), ref.getType());
if ((refField.getModifiers() & modifierMask) != Modifier.PRIVATE)
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_return)
if (iter.hasNext())
return false;
reference = ref;
kind = ACCESSPUTFIELD;
@ -291,19 +346,21 @@ public class SyntheticAnalyzer implements Opcodes {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
MethodInfo refMethod
= clazzInfo.findMethod(ref.getName(), ref.getType());
= classInfo.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE
|| refType.getParameterTypes().length != params)
return false;
instr = (Instruction) iter.next();
if (refType.getReturnType() == Type.tVoid) {
if (instr.getOpcode() != opc_return)
if (iter.hasNext())
return false;
} else {
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
return false;
@ -318,16 +375,25 @@ public class SyntheticAnalyzer implements Opcodes {
}
public boolean checkConstructorAccess() {
ClassInfo clazzInfo = method.getClazzInfo();
BytecodeInfo bytecode = method.getBytecode();
Handler[] excHandlers = bytecode.getExceptionHandlers();
BasicBlocks bb = method.getBasicBlocks();
Handler[] excHandlers = bb.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0)
return false;
Iterator iter = bytecode.getInstructions().iterator();
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock();
if (startBlock == null)
return false;
Block[] succBlocks = startBlock.getSuccs();
if (succBlocks.length != 1 || succBlocks[0] != null)
return false;
Iterator iter = startBlock.getInstructions().iterator();
if (!iter.hasNext())
return false;
Instruction instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0)
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
// slot begins with 2. Slot 1 contains a dummy value, that
@ -339,25 +405,25 @@ public class SyntheticAnalyzer implements Opcodes {
params++;
slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
}
if (instr.getOpcode() == opc_invokespecial) {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
.equals(classInfo.getName().replace('.','/'))))
return false;
MethodInfo refMethod
= clazzInfo.findMethod(ref.getName(), ref.getType());
= classInfo.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE
|| !refMethod.getName().equals("<init>")
|| refType.getParameterTypes().length != params)
return false;
instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_return)
if (iter.hasNext())
return false;
/* For valid bytecode the types matches automatically */
reference = ref;
kind = ACCESSCONSTRUCTOR;
Loading…
Cancel
Save