many fixes (it does now work :-)

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@410 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent ebb0f39f23
commit 40f583a1f0
  1. 337
      jode/jode/jvm/Interpreter.java

@ -18,6 +18,9 @@
*/ */
package jode.jvm; package jode.jvm;
import jode.bytecode.*; import jode.bytecode.*;
import jode.decompiler.ClassAnalyzer;
import jode.MethodType;
import jode.Type;
import java.lang.reflect.*; import java.lang.reflect.*;
/** /**
@ -28,14 +31,109 @@ import java.lang.reflect.*;
* @author Jochen Hoenicke * @author Jochen Hoenicke
*/ */
public class Interpreter implements Opcodes { public class Interpreter implements Opcodes {
static int checkType(String typesig, int pos, Class type) {
switch (typesig.charAt(pos++)) {
case 'Z':
if (type != Boolean.TYPE)
return -1;
break;
case 'B':
if (type != Byte.TYPE)
return -1;
break;
case 'C':
if (type != Character.TYPE)
return -1;
break;
case 'S':
if (type != Short.TYPE)
return -1;
break;
case 'I':
if (type != Integer.TYPE)
return -1;
break;
case 'J':
if (type != Long.TYPE)
return -1;
break;
case 'F':
if (type != Float.TYPE)
return -1;
break;
case 'D':
if (type != Double.TYPE)
return -1;
break;
case 'V':
if (type != Void.TYPE)
return -1;
break;
case '[':
if (!type.isArray())
return -1;
pos = checkType(typesig, pos, type.getComponentType());
break;
case 'L': {
int index = typesig.indexOf(';', pos);
if (index == -1)
return -1;
if (!type.getName().replace('.','/')
.equals(typesig.substring(pos, index)))
return -1;
pos = index+1;
break;
}
default:
return -1;
}
return pos;
}
static boolean checkMethod(String typesig,
Class[] paramTypes, Class retType) {
if (typesig.charAt(0) != '(')
return false;
int pos = 1;
int i = 0;
while (typesig.charAt(pos) != ')') {
if (i >= paramTypes.length)
return false;
pos = checkType(typesig, pos, paramTypes[i++]);
if (pos == -1) {
return false;
}
}
if (i != paramTypes.length)
return false;
pos++;
pos = checkType(typesig, pos, retType);
return pos == typesig.length();
}
public static Object interpretMethod public static Object interpretMethod
(ClassInfo currentClass, byte[] code, Value[] locals, Value[] stack) (ClassAnalyzer ca, byte[] code, Value[] locals, Value[] stack)
throws InterpreterException, ClassFormatException { throws InterpreterException, ClassFormatException {
try { try {
ConstantPool cpool = currentClass.getConstantPool(); ConstantPool cpool = ca.getClazz().getConstantPool();
int pc = 0; int pc = 0;
int stacktop = 0; int stacktop = 0;
for(;;) { for(;;) {
// System.err.print(pc+": [");
// for (int i=0; i<stacktop; i++) {
// if (i>0)
// System.err.print(",");
// System.err.print(stack[i]);
// if (stack[i].objectValue() instanceof char[]) {
// System.err.print(new String((char[])stack[i].objectValue()));
// }
// }
// System.err.println("]");
// System.err.print("local: [");
// for (int i=0; i<locals.length; i++)
// System.err.print(locals[i]+",");
// System.err.println("]");
int opcode = code[pc++] & 0xff; int opcode = code[pc++] & 0xff;
switch (opcode) { switch (opcode) {
case opc_nop: case opc_nop:
@ -97,8 +195,10 @@ public class Interpreter implements Opcodes {
Object array = stack[--stacktop].objectValue(); Object array = stack[--stacktop].objectValue();
switch(opcode) { switch(opcode) {
case opc_baload: case opc_baload:
stack[stacktop++].setInt(((byte[])array)[index]); stack[stacktop++].setInt
break; (array instanceof byte[]
? ((byte[])array)[index]
: ((boolean[])array)[index] ? 1 : 0);
case opc_caload: case opc_caload:
stack[stacktop++].setInt(((char[])array)[index]); stack[stacktop++].setInt(((char[])array)[index]);
break; break;
@ -106,19 +206,11 @@ public class Interpreter implements Opcodes {
stack[stacktop++].setInt(((short[])array)[index]); stack[stacktop++].setInt(((short[])array)[index]);
break; break;
case opc_iaload: case opc_iaload:
stack[stacktop++].setInt(((int[])array)[index]);
break;
case opc_laload: case opc_laload:
stack[stacktop++].setLong(((long[])array)[index]);
break;
case opc_faload: case opc_faload:
stack[stacktop++].setFloat(((float[])array)[index]);
break;
case opc_daload: case opc_daload:
stack[stacktop++].setDouble(((double[])array)[index]);
break;
case opc_aaload: case opc_aaload:
stack[stacktop++].setObject(((Object[])array)[index]); stack[stacktop++].setObject(Array.get(array, index));
break; break;
} }
break; break;
@ -146,30 +238,24 @@ public class Interpreter implements Opcodes {
int index = stack[--stacktop].intValue(); int index = stack[--stacktop].intValue();
Object array = stack[--stacktop].objectValue(); Object array = stack[--stacktop].objectValue();
switch(opcode) { switch(opcode) {
case opc_baload: case opc_bastore:
((byte[])array)[index] = (byte) value.intValue(); if (array instanceof byte[])
((byte[])array)[index] = (byte) value.intValue();
else
((boolean[])array)[index] = value.intValue() != 0;
break; break;
case opc_caload: case opc_castore:
((char[])array)[index] = (char) value.intValue(); ((char[])array)[index] = (char) value.intValue();
break; break;
case opc_saload: case opc_sastore:
((short[])array)[index] = (short) value.intValue(); ((short[])array)[index] = (short) value.intValue();
break; break;
case opc_iaload: case opc_iastore:
((int[])array)[index] = value.intValue(); case opc_lastore:
break; case opc_fastore:
case opc_laload: case opc_dastore:
((long[])array)[index] = value.longValue(); case opc_aastore:
break; Array.set(array, index, value.objectValue());
case opc_faload:
((float[])array)[index] = value.floatValue();
break;
case opc_daload:
((double[])array)[index] = value.doubleValue();
break;
case opc_aaload:
((Object[])array)[index] = value.objectValue();
break;
} }
break; break;
} }
@ -177,25 +263,27 @@ public class Interpreter implements Opcodes {
stacktop -= opcode - (opc_pop-1); stacktop -= opcode - (opc_pop-1);
break; break;
case opc_dup: case opc_dup_x1: case opc_dup_x2: { case opc_dup: case opc_dup_x1: case opc_dup_x2: {
int depth = (opcode - opc_dup)%3; int depth = opcode - opc_dup;
for (int i=0; i < depth+1; i++) for (int i=0; i < depth+1; i++)
stack[stacktop+1-i].setValue(stack[stacktop-i]); stack[stacktop-i].setValue(stack[stacktop-i-1]);
stack[stacktop-depth].setValue(stack[stacktop]); stack[stacktop-depth-1].setValue(stack[stacktop]);
stacktop++; stacktop++;
break; break;
} }
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: { case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: {
int depth = (opcode - opc_dup)%3; int depth = opcode - opc_dup2;
for (int i=0; i < depth+2; i++) for (int i=0; i < depth+2; i++)
stack[stacktop+2-i] = stack[stacktop-i]; stack[stacktop+1-i].setValue(stack[stacktop-1-i]);
stack[stacktop-depth].setValue(stack[stacktop+1]); stack[stacktop-depth-1].setValue(stack[stacktop+1]);
stack[stacktop-depth-1].setValue(stack[stacktop]); stack[stacktop-depth-2].setValue(stack[stacktop]);
stacktop += 2; stacktop += 2;
break;
} }
case opc_swap: { case opc_swap: {
Value tmp = stack[stacktop-1]; Value tmp = stack[stacktop-1];
stack[stacktop-1] = stack[stacktop-2]; stack[stacktop-1] = stack[stacktop-2];
stack[stacktop-2] = tmp; stack[stacktop-2] = tmp;
break;
} }
case opc_iadd: case opc_iadd:
stack[stacktop-2].setInt(stack[stacktop-2].intValue() stack[stacktop-2].setInt(stack[stacktop-2].intValue()
@ -506,7 +594,7 @@ public class Interpreter implements Opcodes {
|| value < 0 && (opcode == opc_iflt || opcode == opc_ifle) || value < 0 && (opcode == opc_iflt || opcode == opc_ifle)
|| value == 0 && (opcode == opc_ifge || opcode == opc_ifle || value == 0 && (opcode == opc_ifge || opcode == opc_ifle
|| opcode == opc_ifeq)) || opcode == opc_ifeq))
pc += opcode; pc += offset;
break; break;
} }
case opc_jsr: case opc_jsr:
@ -523,12 +611,16 @@ public class Interpreter implements Opcodes {
int value = stack[--stacktop].intValue(); int value = stack[--stacktop].intValue();
int start = pc - 1; int start = pc - 1;
pc += 3-(start % 4); pc += 3-(start % 4);
int dest = ((code[pc++] << 8) | (code[pc++] & 0xff)); int dest = (code[pc++] << 24 | (code[pc++] & 0xff) << 16
int low = ((code[pc++] << 8) | (code[pc++] & 0xff)); | (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff));
int high = ((code[pc++] << 8) | (code[pc++] & 0xff)); int low = (code[pc++] << 24 | (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff));
int high = (code[pc++] << 24 | (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff));
if (value >= low && value <= high) { if (value >= low && value <= high) {
pc += (value - low) << 1; pc += (value - low) << 2;
dest = ((code[pc] << 8) | (code[pc+1] & 0xff)); dest = (code[pc++] << 24 | (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff));
} }
pc = start + dest; pc = start + dest;
break; break;
@ -537,11 +629,23 @@ public class Interpreter implements Opcodes {
int value = stack[--stacktop].intValue(); int value = stack[--stacktop].intValue();
int start = pc - 1; int start = pc - 1;
pc += 3-(start % 4); pc += 3-(start % 4);
int dest = ((code[pc++] << 8) | (code[pc++] & 0xff)); int dest = (code[pc++] << 24
int npairs = ((code[pc++] << 8) | (code[pc++] & 0xff)); | (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8
| (code[pc++] & 0xff));
int npairs = (code[pc++] << 24
| (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8
| (code[pc++] & 0xff));
for (int i=0; i < npairs; i++) { for (int i=0; i < npairs; i++) {
if (value == ((code[pc++] << 8) | (code[pc++] & 0xff))) { if (value == (code[pc++] << 24
dest = ((code[pc++] << 8) | (code[pc++] & 0xff)); | (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8
| (code[pc++] & 0xff))) {
dest = (code[pc++] << 24
| (code[pc++] & 0xff) << 16
| (code[pc++] & 0xff) << 8
| (code[pc++] & 0xff));
break; break;
} }
pc+=2; pc+=2;
@ -569,84 +673,102 @@ public class Interpreter implements Opcodes {
int argcount= (opcode == opc_invokeinterface) int argcount= (opcode == opc_invokeinterface)
? (code[pc++] << 8) | (code[pc++] & 0xff) : -1; ? (code[pc++] << 8) | (code[pc++] & 0xff) : -1;
// if (ref[0] == currentClass.getName()) { if (ref[0].equals(ca.getClazz().getName().replace('.','/'))) {
// /* invoke interpreter again */ boolean isStatic = opcode == opc_invokestatic;
// } else { MethodType mt = new MethodType(isStatic, ref[2]);
Class clazz; CodeInfo info = ca.getMethod(ref[1], mt)
try { .getCode().getCodeInfo();
clazz = Class.forName Value[] newLocals = new Value[info.getMaxLocals()];
(cpool.getClassName((code[pc++] << 8) & 0xff00 for (int i=0; i< newLocals.length; i++)
| code[pc++] & 0xff) newLocals[i] = new Value();
.replace('/','.')); Value[] newStack = new Value[info.getMaxStack()];
} catch (ClassNotFoundException ex) { for (int i=0; i< newStack.length; i++)
throw new InterpreterException newStack[i] = new Value();
("Class "+ref[0]+" not found"); for (int i=mt.getParameterTypes().length - 1; i >= 0; i--)
} newLocals[i].setValue(stack[--stacktop]);
try { Object result = interpretMethod(ca, info.getCode(),
if (ref[1].equals("<init>")) { newLocals, newStack);
Constructor[] cs = clazz.getConstructors(); if (mt.getReturnType() != Type.tVoid) {
Constructor c = null; stack[stacktop++].setObject(result);
for (int i=0; i< cs.length; i++) { }
/* check types XXX */ } else {
c = cs[i]; Class clazz;
break; try {
} clazz = Class.forName(ref[0].replace('/','.'));
} catch (ClassNotFoundException ex) {
throw new InterpreterException
("Class "+ref[0]+" not found");
}
try {
if (ref[1].equals("<init>")) {
Constructor[] cs = clazz.getConstructors();
Constructor c = null;
for (int i=0; i< cs.length; i++) {
if (checkMethod(ref[2], cs[i].getParameterTypes(),
Void.TYPE)) {
c = cs[i];
break;
}
}
if (c == null) if (c == null)
throw new InterpreterException("Constructor " throw new InterpreterException("Constructor "
+ref[0]+"." +ref[0]+"."
+ref[1]+" not found."); +ref[1]+" not found.");
Object[] args Object[] args
= new Object[c.getParameterTypes().length]; = new Object[c.getParameterTypes().length];
for (int i=args.length - 1; i >= 0; i--) for (int i=args.length - 1; i >= 0; i--)
args[i] = stack[--stacktop].objectValue(); args[i] = stack[--stacktop].objectValue();
NewObject newObj = NewObject newObj = stack[--stacktop].getNewObject();
(NewObject) stack[--stacktop].objectValue(); if (!newObj.getType().equals(ref[0]))
if (!newObj.getClass().equals(ref[0]))
throw new InterpreterException("constructor not called" throw new InterpreterException("constructor not called"
+" on new instance"); +" on new instance");
newObj.setObject(c.newInstance(args)); newObj.setObject(c.newInstance(args));
} else { } else {
Method[] ms = clazz.getMethods(); Method[] ms = clazz.getMethods();
Method m = null; Method m = null;
for (int i=0; i< ms.length; i++) { for (int i=0; i< ms.length; i++) {
if (ms[i].getName().equals(ref[1])) { if (ms[i].getName().equals(ref[1])) {
/* check types XXX */ if (checkMethod(ref[2],
m = ms[i]; ms[i].getParameterTypes(),
break; ms[i].getReturnType())) {
m = ms[i];
break;
}
}
} }
} if (m == null)
if (m == null) throw new InterpreterException("Method "+ref[0]+"."
throw new InterpreterException("Method "+ref[0]+"." +ref[1]+" not found.");
+ref[1]+" not found."); Object obj = null;
Object obj = null; Object[] args
Object[] args = new Object[m.getParameterTypes().length];
= new Object[m.getParameterTypes().length]; for (int i=args.length - 1; i >= 0; i--)
for (int i=args.length - 1; i >= 0; i--) args[i] = stack[--stacktop].objectValue();
args[i] = stack[--stacktop].objectValue(); if (opcode != opc_invokestatic)
if (opcode != opc_invokestatic) obj = stack[--stacktop].objectValue();
obj = stack[--stacktop].objectValue(); /* special and constructor? XXX*/
/* special and constructor? XXX*/
Object result = m.invoke(obj, args); Object result = m.invoke(obj, args);
if (m.getReturnType() != Void.TYPE) if (m.getReturnType() != Void.TYPE)
stack[stacktop++].setObject(result); stack[stacktop++].setObject(result);
}
} catch (IllegalAccessException ex) {
throw new InterpreterException
("Method "+ref[0]+"."+ref[1]+" not accessible");
} catch (InstantiationException ex) {
throw new InterpreterException
("InstantiationException in "+ref[0]+"."+ref[1]+".");
} catch (InvocationTargetException ex) {
throw new InterpreterException
("Method "+ref[0]+"."+ref[1]+" throwed an exception");
/*XXX exception handler?*/
} }
} catch (IllegalAccessException ex) {
throw new InterpreterException
("Method "+ref[0]+"."+ref[1]+" not accessible");
} catch (InstantiationException ex) {
throw new InterpreterException
("InstantiationException in "+ref[0]+"."+ref[1]+".");
} catch (InvocationTargetException ex) {
throw new InterpreterException
("Method "+ref[0]+"."+ref[1]+" throwed an exception");
/*XXX exception handler?*/
} }
break; break;
} }
case opc_new: { case opc_new: {
String clazz = cpool.getClassName((code[pc++] << 8) & 0xff00 String clazz = cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff); | code[pc++] & 0xff);
stack[stacktop++].setObject(new NewObject(clazz)); stack[stacktop++].setNewObject(new NewObject(clazz));
break; break;
} }
case opc_newarray: { case opc_newarray: {
@ -805,6 +927,7 @@ public class Interpreter implements Opcodes {
} }
} }
} catch(RuntimeException ex) { } catch(RuntimeException ex) {
ex.printStackTrace();
throw new InterpreterException("Caught RuntimeException: " throw new InterpreterException("Caught RuntimeException: "
+ ex.toString()); + ex.toString());
} }

Loading…
Cancel
Save