Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@399 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 4e93ed861f
commit d5c76c287d
  1. 812
      jode/jode/jvm/Interpreter.java
  2. 35
      jode/jode/jvm/InterpreterException.java
  3. 43
      jode/jode/jvm/NewObject.java
  4. 30
      jode/jode/jvm/ReturnAddress.java
  5. 86
      jode/jode/jvm/Value.java

@ -0,0 +1,812 @@
/*
* Opcodes (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.jvm;
import jode.bytecode.*;
import java.lang.reflect.*;
/**
* This class is a java virtual machine written in java :-). Well not
* exactly. It does only handle a subset of the opcodes and is mainly
* written do deobfuscate Strings.
*
* @author Jochen Hoenicke
*/
public class Interpreter implements Opcodes {
public static Object interpretMethod
(ClassInfo currentClass, byte[] code, Value[] locals, Value[] stack)
throws InterpreterException, ClassFormatException {
try {
ConstantPool cpool = currentClass.getConstantPool();
int pc = 0;
int stacktop = 0;
for(;;) {
int opcode = code[pc++] & 0xff;
switch (opcode) {
case opc_nop:
break;
case opc_aconst_null:
stack[stacktop++].setObject(null);
break;
case opc_iconst_m1:
case opc_iconst_0: case opc_iconst_1: case opc_iconst_2:
case opc_iconst_3: case opc_iconst_4: case opc_iconst_5:
stack[stacktop++].setInt(opcode - opc_iconst_0);
break;
case opc_lconst_0: case opc_lconst_1:
stack[stacktop++].setLong(opcode - opc_lconst_0);
break;
case opc_fconst_0: case opc_fconst_1: case opc_fconst_2:
stack[stacktop++].setFloat(opcode - opc_fconst_0);
break;
case opc_dconst_0: case opc_dconst_1:
stack[stacktop++].setDouble(opcode - opc_dconst_0);
break;
case opc_bipush:
stack[stacktop++].setInt(code[pc++]);
break;
case opc_sipush:
stack[stacktop++].setInt((code[pc++] << 8)
| (code[pc++] & 0xff));
break;
case opc_ldc:
stack[stacktop++].setObject
(cpool.getConstant(code[pc++] & 0xff));
break;
case opc_ldc_w:
case opc_ldc2_w: {
int index = (code[pc++] << 8) & 0xff00 | code[pc++] & 0xff;
stack[stacktop++].setObject(cpool.getConstant(index));
break;
}
case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload:
stack[stacktop++].setValue(locals[code[pc++]]);
break;
case opc_iload_0: case opc_iload_1:
case opc_iload_2: case opc_iload_3:
case opc_lload_0: case opc_lload_1:
case opc_lload_2: case opc_lload_3:
case opc_fload_0: case opc_fload_1:
case opc_fload_2: case opc_fload_3:
case opc_dload_0: case opc_dload_1:
case opc_dload_2: case opc_dload_3:
case opc_aload_0: case opc_aload_1:
case opc_aload_2: case opc_aload_3:
stack[stacktop++].setValue(locals[(opcode - opc_iload_0) & 3]);
break;
case opc_iaload: case opc_laload:
case opc_faload: case opc_daload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload: {
int index = stack[--stacktop].intValue();
Object array = stack[--stacktop].objectValue();
switch(opcode) {
case opc_baload:
stack[stacktop++].setInt(((byte[])array)[index]);
break;
case opc_caload:
stack[stacktop++].setInt(((char[])array)[index]);
break;
case opc_saload:
stack[stacktop++].setInt(((short[])array)[index]);
break;
case opc_iaload:
stack[stacktop++].setInt(((int[])array)[index]);
break;
case opc_laload:
stack[stacktop++].setLong(((long[])array)[index]);
break;
case opc_faload:
stack[stacktop++].setFloat(((float[])array)[index]);
break;
case opc_daload:
stack[stacktop++].setDouble(((double[])array)[index]);
break;
case opc_aaload:
stack[stacktop++].setObject(((Object[])array)[index]);
break;
}
break;
}
case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore:
locals[code[pc++]].setValue(stack[--stacktop]);
break;
case opc_istore_0: case opc_istore_1:
case opc_istore_2: case opc_istore_3:
case opc_lstore_0: case opc_lstore_1:
case opc_lstore_2: case opc_lstore_3:
case opc_fstore_0: case opc_fstore_1:
case opc_fstore_2: case opc_fstore_3:
case opc_dstore_0: case opc_dstore_1:
case opc_dstore_2: case opc_dstore_3:
case opc_astore_0: case opc_astore_1:
case opc_astore_2: case opc_astore_3:
locals[(opcode-opc_istore_0) & 3].setValue(stack[--stacktop]);
break;
case opc_iastore: case opc_lastore:
case opc_fastore: case opc_dastore: case opc_aastore:
case opc_bastore: case opc_castore: case opc_sastore: {
Value value = stack[--stacktop];
int index = stack[--stacktop].intValue();
Object array = stack[--stacktop].objectValue();
switch(opcode) {
case opc_baload:
((byte[])array)[index] = (byte) value.intValue();
break;
case opc_caload:
((char[])array)[index] = (char) value.intValue();
break;
case opc_saload:
((short[])array)[index] = (short) value.intValue();
break;
case opc_iaload:
((int[])array)[index] = value.intValue();
break;
case opc_laload:
((long[])array)[index] = value.longValue();
break;
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;
}
case opc_pop: case opc_pop2:
stacktop -= opcode - (opc_pop-1);
break;
case opc_dup: case opc_dup_x1: case opc_dup_x2: {
int depth = (opcode - opc_dup)%3;
for (int i=0; i < depth+1; i++)
stack[stacktop+1-i].setValue(stack[stacktop-i]);
stack[stacktop-depth].setValue(stack[stacktop]);
stacktop++;
break;
}
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: {
int depth = (opcode - opc_dup)%3;
for (int i=0; i < depth+2; i++)
stack[stacktop+2-i] = stack[stacktop-i];
stack[stacktop-depth].setValue(stack[stacktop+1]);
stack[stacktop-depth-1].setValue(stack[stacktop]);
stacktop += 2;
}
case opc_swap: {
Value tmp = stack[stacktop-1];
stack[stacktop-1] = stack[stacktop-2];
stack[stacktop-2] = tmp;
}
case opc_iadd:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
+ stack[stacktop-1].intValue());
stacktop--;
break;
case opc_isub:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
- stack[stacktop-1].intValue());
stacktop--;
break;
case opc_imul:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
* stack[stacktop-1].intValue());
stacktop--;
break;
case opc_idiv:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
/ stack[stacktop-1].intValue());
stacktop--;
break;
case opc_irem:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
% stack[stacktop-1].intValue());
stacktop--;
break;
case opc_ladd:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
+ stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lsub:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
- stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lmul:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
* stack[stacktop-1].longValue());
stacktop--;
break;
case opc_ldiv:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
/ stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lrem:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
% stack[stacktop-1].longValue());
stacktop--;
break;
case opc_fadd:
stack[stacktop-2].setFloat(stack[stacktop-2].floatValue()
+ stack[stacktop-1].floatValue());
stacktop--;
break;
case opc_fsub:
stack[stacktop-2].setFloat(stack[stacktop-2].floatValue()
- stack[stacktop-1].floatValue());
stacktop--;
break;
case opc_fmul:
stack[stacktop-2].setFloat(stack[stacktop-2].floatValue()
* stack[stacktop-1].floatValue());
stacktop--;
break;
case opc_fdiv:
stack[stacktop-2].setFloat(stack[stacktop-2].floatValue()
/ stack[stacktop-1].floatValue());
stacktop--;
break;
case opc_frem:
stack[stacktop-2].setFloat(stack[stacktop-2].floatValue()
% stack[stacktop-1].floatValue());
stacktop--;
break;
case opc_dadd:
stack[stacktop-2].setDouble(stack[stacktop-2].doubleValue()
+ stack[stacktop-1].doubleValue());
stacktop--;
break;
case opc_dsub:
stack[stacktop-2].setDouble(stack[stacktop-2].doubleValue()
- stack[stacktop-1].doubleValue());
stacktop--;
break;
case opc_dmul:
stack[stacktop-2].setDouble(stack[stacktop-2].doubleValue()
* stack[stacktop-1].doubleValue());
stacktop--;
break;
case opc_ddiv:
stack[stacktop-2].setDouble(stack[stacktop-2].doubleValue()
/ stack[stacktop-1].doubleValue());
stacktop--;
break;
case opc_drem:
stack[stacktop-2].setDouble(stack[stacktop-2].doubleValue()
% stack[stacktop-1].doubleValue());
stacktop--;
break;
case opc_ineg:
stack[stacktop-1].setInt(-stack[stacktop-1].intValue());
break;
case opc_lneg:
stack[stacktop-1].setLong(-stack[stacktop-1].longValue());
break;
case opc_fneg:
stack[stacktop-1].setFloat(-stack[stacktop-1].floatValue());
break;
case opc_dneg:
stack[stacktop-1].setDouble(-stack[stacktop-1].doubleValue());
break;
case opc_ishl:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
<< stack[stacktop-1].intValue());
stacktop--;
break;
case opc_ishr:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
>> stack[stacktop-1].intValue());
stacktop--;
break;
case opc_iushr:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
>>> stack[stacktop-1].intValue());
stacktop--;
break;
case opc_iand:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
& stack[stacktop-1].intValue());
stacktop--;
break;
case opc_ior :
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
| stack[stacktop-1].intValue());
stacktop--;
break;
case opc_ixor:
stack[stacktop-2].setInt(stack[stacktop-2].intValue()
^ stack[stacktop-1].intValue());
stacktop--;
break;
case opc_lshl:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
<< stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lshr:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
>> stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lushr:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
>>> stack[stacktop-1].longValue());
stacktop--;
break;
case opc_land:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
& stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lor :
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
| stack[stacktop-1].longValue());
stacktop--;
break;
case opc_lxor:
stack[stacktop-2].setLong(stack[stacktop-2].longValue()
^ stack[stacktop-1].longValue());
stacktop--;
break;
case opc_iinc: {
int slot = code[pc++] & 0xff;
locals[slot].setInt(locals[slot].intValue() + code[pc++]);
break;
}
case opc_i2l:
stack[stacktop-1]
.setLong((long)stack[stacktop-1].intValue());
break;
case opc_i2f:
stack[stacktop-1]
.setFloat((float)stack[stacktop-1].intValue());
break;
case opc_i2d:
stack[stacktop-1]
.setDouble((double)stack[stacktop-1].intValue());
break;
case opc_l2i:
stack[stacktop-1]
.setInt((int)stack[stacktop-1].longValue());
break;
case opc_l2f:
stack[stacktop-1]
.setFloat((float)stack[stacktop-1].longValue());
break;
case opc_l2d:
stack[stacktop-1]
.setDouble((double)stack[stacktop-1].longValue());
break;
case opc_f2i:
stack[stacktop-1]
.setInt((int)stack[stacktop-1].floatValue());
break;
case opc_f2l:
stack[stacktop-1]
.setLong((long)stack[stacktop-1].floatValue());
break;
case opc_f2d:
stack[stacktop-1]
.setDouble((double)stack[stacktop-1].floatValue());
break;
case opc_d2i:
stack[stacktop-1]
.setInt((int)stack[stacktop-1].doubleValue());
break;
case opc_d2l:
stack[stacktop-1]
.setLong((long)stack[stacktop-1].doubleValue());
break;
case opc_d2f:
stack[stacktop-1]
.setFloat((float)stack[stacktop-1].doubleValue());
break;
case opc_i2b:
stack[stacktop-1]
.setInt((byte)stack[stacktop-1].intValue());
break;
case opc_i2c:
stack[stacktop-1]
.setInt((char)stack[stacktop-1].intValue());
break;
case opc_i2s:
stack[stacktop-1]
.setInt((short)stack[stacktop-1].intValue());
break;
case opc_lcmp: {
long val1 = stack[stacktop-2].longValue();
long val2 = stack[--stacktop].longValue();
stack[stacktop-1].setInt
(val1 == val2 ? 0 : val1 < val2 ? -1 : 1);
break;
}
case opc_fcmpl: case opc_fcmpg: {
float val1 = stack[stacktop-2].floatValue();
float val2 = stack[--stacktop].floatValue();
stack[stacktop-1].setInt
(val1 == val2 ? 0
: ( opcode == opc_fcmpg
? (val1 < val2 ? -1 : 1)
: (val1 > val2 ? 1 : -1)));
break;
}
case opc_dcmpl: case opc_dcmpg: {
double val1 = stack[stacktop-2].doubleValue();
double val2 = stack[--stacktop].doubleValue();
stack[stacktop-1].setInt
(val1 == val2 ? 0
: ( opcode == opc_dcmpg
? (val1 < val2 ? -1 : 1)
: (val1 > val2 ? 1 : -1)));
break;
}
case opc_ifeq: case opc_ifne:
case opc_iflt: case opc_ifge:
case opc_ifgt: case opc_ifle:
case opc_if_icmpeq: case opc_if_icmpne:
case opc_if_icmplt: case opc_if_icmpge:
case opc_if_icmpgt: case opc_if_icmple:
case opc_if_acmpeq: case opc_if_acmpne:
case opc_ifnull: case opc_ifnonnull: {
int value;
if (opcode >= opc_if_acmpeq) {
if (opcode >= opc_ifnull) {
value =
stack[--stacktop].objectValue() == null ? 0 : 1;
opcode += opc_ifeq - opc_ifnull;
} else {
value =
stack[--stacktop].objectValue()
== stack[--stacktop].objectValue() ? 0 : 1;
opcode += opc_ifeq - opc_if_acmpeq;
}
} else {
value = stack[--stacktop].intValue();
if (opcode >= opc_if_icmpeq) {
int val1 = stack[--stacktop].intValue();
value = (val1 == value ? 0
: val1 < value ? -1 : 1);
opcode += opc_ifeq - opc_if_icmpeq;
}
}
int offset = ((code[pc++] << 8) | (code[pc++] & 0xff)) - 3;
if (value > 0 && (opcode == opc_ifgt || opcode == opc_ifge)
|| value < 0 && (opcode == opc_iflt || opcode == opc_ifle)
|| value == 0 && (opcode == opc_ifge || opcode == opc_ifle
|| opcode == opc_ifeq))
pc += opcode;
break;
}
case opc_jsr:
stack[stacktop++].setObject(new ReturnAddress(pc));
/* fall through */
case opc_goto:
pc = (pc-1) + ((code[pc] << 8) | (code[pc+1] & 0xff));
break;
case opc_ret:
pc = ((ReturnAddress) locals[code[pc] & 0xff].objectValue())
.getPC();
break;
case opc_tableswitch: {
int value = stack[--stacktop].intValue();
int start = pc - 1;
pc += 3-(start % 4);
int dest = ((code[pc++] << 8) | (code[pc++] & 0xff));
int low = ((code[pc++] << 8) | (code[pc++] & 0xff));
int high = ((code[pc++] << 8) | (code[pc++] & 0xff));
if (value >= low && value <= high) {
pc += (value - low) << 1;
dest = ((code[pc] << 8) | (code[pc+1] & 0xff));
}
pc = start + dest;
break;
}
case opc_lookupswitch: {
int value = stack[--stacktop].intValue();
int start = pc - 1;
pc += 3-(start % 4);
int dest = ((code[pc++] << 8) | (code[pc++] & 0xff));
int npairs = ((code[pc++] << 8) | (code[pc++] & 0xff));
for (int i=0; i < npairs; i++) {
if (value == ((code[pc++] << 8) | (code[pc++] & 0xff))) {
dest = ((code[pc++] << 8) | (code[pc++] & 0xff));
break;
}
pc+=2;
}
pc = start + dest;
break;
}
case opc_ireturn: case opc_lreturn:
case opc_freturn: case opc_dreturn: case opc_areturn:
return stack[--stacktop].objectValue();
case opc_return:
return Void.TYPE;
case opc_getstatic:
case opc_getfield:
case opc_putstatic:
case opc_putfield:
throw new InterpreterException
("Implement get/put-static/field?");
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic :
case opc_invokeinterface: {
String[] ref = cpool.getRef((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff);
int argcount= (opcode == opc_invokeinterface)
? (code[pc++] << 8) | (code[pc++] & 0xff) : -1;
// if (ref[0] == currentClass.getName()) {
// /* invoke interpreter again */
// } else {
Class clazz;
try {
clazz = Class.forName
(cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff)
.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++) {
/* check types XXX */
c = cs[i];
break;
}
if (c == null)
throw new InterpreterException("Constructor "
+ref[0]+"."
+ref[1]+" not found.");
Object[] args
= new Object[c.getParameterTypes().length];
for (int i=args.length - 1; i >= 0; i--)
args[i] = stack[--stacktop].objectValue();
NewObject newObj =
(NewObject) stack[--stacktop].objectValue();
if (!newObj.getClass().equals(ref[0]))
throw new InterpreterException("constructor not called"
+" on new instance");
newObj.setObject(c.newInstance(args));
} else {
Method[] ms = clazz.getMethods();
Method m = null;
for (int i=0; i< ms.length; i++) {
if (ms[i].getName().equals(ref[1])) {
/* check types XXX */
m = ms[i];
break;
}
}
if (m == null)
throw new InterpreterException("Method "+ref[0]+"."
+ref[1]+" not found.");
Object obj = null;
Object[] args
= new Object[m.getParameterTypes().length];
for (int i=args.length - 1; i >= 0; i--)
args[i] = stack[--stacktop].objectValue();
if (opcode != opc_invokestatic)
obj = stack[--stacktop].objectValue();
/* special and constructor? XXX*/
Object result = m.invoke(obj, args);
if (m.getReturnType() != Void.TYPE)
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?*/
}
break;
}
case opc_new: {
String clazz = cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff);
stack[stacktop++].setObject(new NewObject(clazz));
break;
}
case opc_newarray: {
int length = stack[--stacktop].intValue();
switch (code[pc++]) {
case 4:
stack[stacktop++].setObject(new boolean[length]);
break;
case 5:
stack[stacktop++].setObject(new char[length]);
break;
case 6:
stack[stacktop++].setObject(new float[length]);
break;
case 7:
stack[stacktop++].setObject(new double[length]);
break;
case 8:
stack[stacktop++].setObject(new byte[length]);
break;
case 9:
stack[stacktop++].setObject(new short[length]);
break;
case 10:
stack[stacktop++].setObject(new int[length]);
break;
case 11:
stack[stacktop++].setObject(new long[length]);
break;
default:
throw new ClassFormatException("Invalid newarray operand");
}
break;
}
case opc_anewarray: {
int length = stack[--stacktop].intValue();
Class clazz;
try {
clazz = Class.forName
(cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff)
.replace('/','.'));
} catch (ClassNotFoundException ex) {
throw new InterpreterException
("Class "+ex.getMessage()+" not found");
}
stack[stacktop++].setObject(Array.newInstance(clazz, length));
break;
}
case opc_arraylength: {
Object array = stack[--stacktop].objectValue();
stack[stacktop++].setInt(Array.getLength(array));
break;
}
case opc_athrow:
/*XXX Throw and catch ?? */
throw new InterpreterException("Throw not implemented");
case opc_checkcast: {
Class clazz;
try {
clazz = Class.forName
(cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff)
.replace('/','.'));
} catch (ClassNotFoundException ex) {
throw new InterpreterException
("Class "+ex.getMessage()+" not found");
}
Object obj = stack[--stacktop].objectValue();
if (obj != null && !clazz.isInstance(obj)) {
/*XXX*/
throw new InterpreterException
("Throw ClassCastException not implemented");
}
break;
}
case opc_instanceof: {
Class clazz;
try {
clazz = Class.forName
(cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff)
.replace('/','.'));
} catch (ClassNotFoundException ex) {
throw new InterpreterException
("Class "+ex.getMessage()+" not found");
}
Object obj = stack[--stacktop].objectValue();
if (obj != null && !clazz.isInstance(obj)) {
/*XXX*/
throw new InterpreterException
("Throw ClassCastException not implemented");
}
break;
}
case opc_monitorenter:
case opc_monitorexit:
throw new InterpreterException
("MonitorEnter/Exit not implemented");
case opc_wide: {
opcode = code[pc++] & 0xff;
switch (opcode) {
case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload: {
int slot = (code[pc++] << 8) | (code[pc++] & 0xff);
stack[stacktop++].setValue(locals[slot & 0xffff]);
break;
}
case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore: {
int slot = (code[pc++] << 8) & 0xff00 | code[pc++] & 0xff;
locals[slot & 0xffff].setValue(stack[--stacktop]);
break;
}
case opc_iinc: {
int slot = (code[pc++] << 8) & 0xff00 | code[pc++] & 0xff;
int value = (code[pc++] << 8) | code[pc++] & 0xff;
locals[slot].setInt(locals[slot].intValue()
+ value);
}
case opc_ret: {
int slot = (code[pc++] << 8) & 0xff00 | code[pc++] & 0xff;
pc = ((ReturnAddress)locals[slot].objectValue()).getPC();
}
default:
throw new
ClassFormatException("Invalid wide opcode "+opcode);
}
}
case opc_multianewarray: {
Class clazz;
try {
clazz = Class.forName
(cpool.getClassName((code[pc++] << 8) & 0xff00
| code[pc++] & 0xff)
.replace('/','.'));
} catch (ClassNotFoundException ex) {
throw new InterpreterException
("Class "+ex.getMessage()+" not found");
}
int dimension = code[pc++] & 0xff;
int[] dims = new int[dimension];
for (int i=dimension-1; i >= 0; i--)
dims[i-1] = stack[--stacktop].intValue();
stack[stacktop++].setObject(Array.newInstance(clazz, dims));
break;
}
case opc_jsr_w:
stack[stacktop++].setObject(new ReturnAddress(pc));
/* fall through */
case opc_goto_w:
pc = pc-1 + (code[pc] << 24 | ((code[pc+1]&0xff) << 16)
| ((code[pc+2]&0xff) << 8) | code[pc+3]&0xff);
default:
throw new ClassFormatException("Invalid opcode "+opcode);
}
}
} catch(RuntimeException ex) {
throw new InterpreterException("Caught RuntimeException: "
+ ex.toString());
}
}
}

@ -0,0 +1,35 @@
/*
* InterpreterException (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.jvm;
import jode.bytecode.*;
/**
* This exception is thrown by the interpreter on various conditions.
*
* @author Jochen Hoenicke
*/
public class InterpreterException extends Exception {
public InterpreterException(String detail) {
super(detail);
}
public InterpreterException() {
super();
}
}

@ -0,0 +1,43 @@
/*
* NewObject (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.jvm;
import jode.bytecode.*;
/**
* This class represents a new object, that may not be initialized yet.
*
* @author Jochen Hoenicke
*/
public class NewObject {
Object instance;
String type;
public NewObject(String type) {
this.type = type;
}
public void setObject(Object obj) {
instance = obj;
}
public Object objectValue() {
return instance;
}
}

@ -0,0 +1,30 @@
/*
* ReturnAddress (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.jvm;
class ReturnAddress {
int pc;
public ReturnAddress(int pc) {
this.pc = pc;
}
public int getPC() {
return pc;
}
}

@ -0,0 +1,86 @@
/*
* Value (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.jvm;
import jode.bytecode.*;
/**
* This class represents a stack value.
*
* @author Jochen Hoenicke
*/
public class Value {
Object value;
NewObject newObj;
public void setObject(Object obj) {
value = obj;
}
public Object objectValue() {
if (newObj != null)
return newObj.objectValue();
return value;
}
public void setInt(int i) {
value = new Integer(i);
}
public int intValue() {
return ((Integer)value).intValue();
}
public void setLong(long i) {
value = new Long(i);
}
public long longValue() {
return ((Long)value).longValue();
}
public void setFloat(float i) {
value = new Float(i);
}
public float floatValue() {
return ((Float)value).floatValue();
}
public void setDouble(double i) {
value = new Double(i);
}
public double doubleValue() {
return ((Double)value).doubleValue();
}
public void setNewObject(NewObject n) {
newObj = n;
}
public NewObject getNewObject() {
return newObj;
}
public void setValue(Value val) {
value = val.value;
newObj = val.newObj;
}
}
Loading…
Cancel
Save