use member functions to access Instruction fields

cleaned up imports


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1067 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 25 years ago
parent 4280f1d6ce
commit f301603e87
  1. 222
      jode/jode/jvm/CodeVerifier.java
  2. 89
      jode/jode/jvm/Interpreter.java
  3. 1
      jode/jode/jvm/InterpreterException.java
  4. 1
      jode/jode/jvm/NewObject.java
  5. 11
      jode/jode/jvm/SimpleRuntimeEnvironment.java
  6. 116
      jode/jode/jvm/SyntheticAnalyzer.java

@ -18,10 +18,20 @@
*/
package jode.jvm;
import jode.bytecode.*;
import jode.type.*;
import jode.AssertError;
import jode.GlobalOptions;
import jode.bytecode.BytecodeInfo;
import jode.bytecode.ClassInfo;
import jode.bytecode.Handler;
import jode.bytecode.Instruction;
import jode.bytecode.MethodInfo;
import jode.bytecode.Opcodes;
import jode.bytecode.Reference;
import jode.type.ArrayType;
import jode.type.ClassInterfacesType;
import jode.type.MethodType;
import jode.type.Type;
import java.util.BitSet;
import java.util.Stack;
@ -297,12 +307,12 @@ public class CodeVerifier implements Opcodes {
public boolean mergeInfo(Instruction instr, VerifyInfo info)
throws VerifyException {
if (instr.tmpInfo == null) {
instr.tmpInfo = info;
if (instr.getTmpInfo() == null) {
instr.setTmpInfo(info);
return true;
}
boolean changed = false;
VerifyInfo oldInfo = (VerifyInfo) instr.tmpInfo;
VerifyInfo oldInfo = (VerifyInfo) instr.getTmpInfo();
if (oldInfo.stackHeight != info.stackHeight)
throw new VerifyException("Stack height differ at: "
+ instr.getDescription());
@ -371,17 +381,18 @@ public class CodeVerifier implements Opcodes {
int jsrLength =
prevInfo.jsrTargets != null ? prevInfo.jsrTargets.length : 0;
VerifyInfo result = (VerifyInfo) prevInfo.clone();
switch (instr.opcode) {
switch (instr.getOpcode()) {
case opc_nop:
case opc_goto:
break;
case opc_ldc: {
Type type;
if (instr.objData == null)
Object constant = instr.getConstant();
if (constant == null)
type = Type.tUObject;
else if (instr.objData instanceof Integer)
else if (constant instanceof Integer)
type = Type.tInt;
else if (instr.objData instanceof Float)
else if (constant instanceof Float)
type = Type.tFloat;
else
type = Type.tString;
@ -390,7 +401,8 @@ public class CodeVerifier implements Opcodes {
}
case opc_ldc2_w: {
Type type;
if (instr.objData instanceof Long)
Object constant = instr.getConstant();
if (constant instanceof Long)
type = Type.tLong;
else
type = Type.tDouble;
@ -404,25 +416,25 @@ public class CodeVerifier implements Opcodes {
case opc_dload:
case opc_aload: {
if (jsrLength > 0
&& (!result.jsrLocals[jsrLength-1].get(instr.localSlot)
|| ((instr.opcode & 0x1) == 0
&& (!result.jsrLocals[jsrLength-1].get(instr.getLocalSlot())
|| ((instr.getOpcode() & 0x1) == 0
&& !result.jsrLocals[jsrLength-1]
.get(instr.localSlot+1)))) {
.get(instr.getLocalSlot()+1)))) {
result.jsrLocals = (BitSet[]) result.jsrLocals.clone();
result.jsrLocals[jsrLength-1]
= (BitSet) result.jsrLocals[jsrLength-1].clone();
result.jsrLocals[jsrLength-1].set(instr.localSlot);
if ((instr.opcode & 0x1) == 0)
result.jsrLocals[jsrLength-1].set(instr.localSlot + 1);
result.jsrLocals[jsrLength-1].set(instr.getLocalSlot());
if ((instr.getOpcode() & 0x1) == 0)
result.jsrLocals[jsrLength-1].set(instr.getLocalSlot() + 1);
}
if ((instr.opcode & 0x1) == 0
&& result.locals[instr.localSlot+1] != Type.tVoid)
if ((instr.getOpcode() & 0x1) == 0
&& result.locals[instr.getLocalSlot()+1] != Type.tVoid)
throw new VerifyException(instr.getDescription());
Type type = result.locals[instr.localSlot];
if (!isOfType(type, types[instr.opcode - opc_iload]))
Type type = result.locals[instr.getLocalSlot()];
if (!isOfType(type, types[instr.getOpcode() - opc_iload]))
throw new VerifyException(instr.getDescription());
result.push(type);
if ((instr.opcode & 0x1) == 0)
if ((instr.getOpcode() & 0x1) == 0)
result.push(Type.tVoid);
break;
}
@ -433,50 +445,50 @@ public class CodeVerifier implements Opcodes {
throw new VerifyException(instr.getDescription());
Type arrType = result.pop();
if (!isOfType(arrType,
Type.tArray(types[instr.opcode - opc_iaload]))
&& (instr.opcode != opc_baload
Type.tArray(types[instr.getOpcode() - opc_iaload]))
&& (instr.getOpcode() != opc_baload
|| !isOfType(arrType, Type.tArray(Type.tBoolean))))
throw new VerifyException(instr.getDescription());
Type elemType = (arrType.equals(Type.tUObject)
? types[instr.opcode - opc_iaload]
? types[instr.getOpcode() - opc_iaload]
:((ArrayType)arrType).getElementType());
result.push(elemType);
if (((1 << instr.opcode - opc_iaload) & 0xa) != 0)
if (((1 << instr.getOpcode() - opc_iaload) & 0xa) != 0)
result.push(Type.tVoid);
break;
}
case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore: {
if (jsrLength > 0
&& (!result.jsrLocals[jsrLength-1].get(instr.localSlot)
|| ((instr.opcode & 0x1) != 0
&& (!result.jsrLocals[jsrLength-1].get(instr.getLocalSlot())
|| ((instr.getOpcode() & 0x1) != 0
&& !result.jsrLocals[jsrLength-1]
.get(instr.localSlot+1)))) {
.get(instr.getLocalSlot()+1)))) {
result.jsrLocals = (BitSet[]) result.jsrLocals.clone();
result.jsrLocals[jsrLength-1]
= (BitSet) result.jsrLocals[jsrLength-1].clone();
result.jsrLocals[jsrLength-1].set(instr.localSlot);
if ((instr.opcode & 0x1) != 0)
result.jsrLocals[jsrLength-1].set(instr.localSlot + 1);
result.jsrLocals[jsrLength-1].set(instr.getLocalSlot());
if ((instr.getOpcode() & 0x1) != 0)
result.jsrLocals[jsrLength-1].set(instr.getLocalSlot() + 1);
}
if ((instr.opcode & 0x1) != 0
if ((instr.getOpcode() & 0x1) != 0
&& result.pop() != Type.tVoid)
throw new VerifyException(instr.getDescription());
Type type = result.pop();
if (instr.opcode != opc_astore
if (instr.getOpcode() != opc_astore
|| !(type instanceof ReturnAddressType))
if (!isOfType(type, types[instr.opcode - opc_istore]))
if (!isOfType(type, types[instr.getOpcode() - opc_istore]))
throw new VerifyException(instr.getDescription());
result.locals[instr.localSlot] = type;
if ((instr.opcode & 0x1) != 0)
result.locals[instr.localSlot+1] = Type.tVoid;
result.locals[instr.getLocalSlot()] = type;
if ((instr.getOpcode() & 0x1) != 0)
result.locals[instr.getLocalSlot()+1] = Type.tVoid;
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: {
if (((1 << instr.opcode - opc_iastore) & 0xa) != 0
if (((1 << instr.getOpcode() - opc_iastore) & 0xa) != 0
&& result.pop() != Type.tVoid)
throw new VerifyException(instr.getDescription());
Type type = result.pop();
@ -484,24 +496,24 @@ public class CodeVerifier implements Opcodes {
throw new VerifyException(instr.getDescription());
Type arrType = result.pop();
if (!isOfType(arrType,
Type.tArray(types[instr.opcode - opc_iastore]))
&& (instr.opcode != opc_bastore
Type.tArray(types[instr.getOpcode() - opc_iastore]))
&& (instr.getOpcode() != opc_bastore
|| !isOfType(arrType, Type.tArray(Type.tBoolean))))
throw new VerifyException(instr.getDescription());
Type elemType = instr.opcode >= opc_bastore ? Type.tInt
: types[instr.opcode - opc_iastore];
Type elemType = instr.getOpcode() >= opc_bastore ? Type.tInt
: types[instr.getOpcode() - opc_iastore];
if (!isOfType(type, elemType))
throw new VerifyException(instr.getDescription());
break;
}
case opc_pop: case opc_pop2: {
int count = instr.opcode - (opc_pop-1);
int count = instr.getOpcode() - (opc_pop-1);
result.need(count);
result.stackHeight -= count;
break;
}
case opc_dup: case opc_dup_x1: case opc_dup_x2: {
int depth = instr.opcode - opc_dup;
int depth = instr.getOpcode() - opc_dup;
result.reserve(1);
result.need(depth+1);
if (result.stack[result.stackHeight-1] == Type.tVoid)
@ -517,7 +529,7 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: {
int depth = instr.opcode - opc_dup2;
int depth = instr.getOpcode() - opc_dup2;
result.reserve(2);
result.need(depth+2);
if (result.stack[result.stackHeight-2] == Type.tVoid)
@ -552,13 +564,13 @@ public class CodeVerifier implements Opcodes {
case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul:
case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv:
case opc_irem: case opc_lrem: case opc_frem: case opc_drem: {
Type type = types[(instr.opcode - opc_iadd) & 3];
if ((instr.opcode & 1) != 0
Type type = types[(instr.getOpcode() - opc_iadd) & 3];
if ((instr.getOpcode() & 1) != 0
&& result.pop() != Type.tVoid)
throw new VerifyException(instr.getDescription());
if (!isOfType(result.pop(), type))
throw new VerifyException(instr.getDescription());
if ((instr.opcode & 1) != 0) {
if ((instr.getOpcode() & 1) != 0) {
result.need(2);
if (result.stack[result.stackHeight-1] != Type.tVoid
|| !isOfType(result.stack[result.stackHeight-2], type))
@ -571,8 +583,8 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: {
Type type = types[(instr.opcode - opc_ineg) & 3];
if ((instr.opcode & 1) != 0) {
Type type = types[(instr.getOpcode() - opc_ineg) & 3];
if ((instr.getOpcode() & 1) != 0) {
result.need(2);
if (result.stack[result.stackHeight-1] != Type.tVoid
|| !isOfType(result.stack[result.stackHeight-2], type))
@ -590,7 +602,7 @@ public class CodeVerifier implements Opcodes {
if (!isOfType(result.pop(), Type.tInt))
throw new VerifyException(instr.getDescription());
if ((instr.opcode & 1) != 0) {
if ((instr.getOpcode() & 1) != 0) {
result.need(2);
if (result.stack[result.stackHeight-1] != Type.tVoid ||
!isOfType(result.stack[result.stackHeight-2],Type.tLong))
@ -605,13 +617,13 @@ public class CodeVerifier implements Opcodes {
case opc_iand: case opc_land:
case opc_ior : case opc_lor :
case opc_ixor: case opc_lxor:
if ((instr.opcode & 1) != 0
if ((instr.getOpcode() & 1) != 0
&& result.pop() != Type.tVoid)
throw new VerifyException(instr.getDescription());
if (!isOfType(result.pop(),
types[instr.opcode & 1]))
types[instr.getOpcode() & 1]))
throw new VerifyException(instr.getDescription());
if ((instr.opcode & 1) != 0) {
if ((instr.getOpcode() & 1) != 0) {
result.need(2);
if (result.stack[result.stackHeight-1] != Type.tVoid
|| !isOfType(result.stack[result.stackHeight-2],
@ -626,15 +638,15 @@ public class CodeVerifier implements Opcodes {
break;
case opc_iinc:
if (!isOfType(result.locals[instr.localSlot], Type.tInt))
if (!isOfType(result.locals[instr.getLocalSlot()], Type.tInt))
throw new VerifyException(instr.getDescription());
break;
case opc_i2l: case opc_i2f: case opc_i2d:
case opc_l2i: case opc_l2f: case opc_l2d:
case opc_f2i: case opc_f2l: case opc_f2d:
case opc_d2i: case opc_d2l: case opc_d2f: {
int from = (instr.opcode-opc_i2l)/3;
int to = (instr.opcode-opc_i2l)%3;
int from = (instr.getOpcode()-opc_i2l)/3;
int to = (instr.getOpcode()-opc_i2l)%3;
if (to >= from)
to++;
if ((from & 1) != 0
@ -714,23 +726,23 @@ public class CodeVerifier implements Opcodes {
case opc_ireturn: case opc_lreturn:
case opc_freturn: case opc_dreturn: case opc_areturn: {
if (((1 << instr.opcode - opc_ireturn) & 0xa) != 0
if (((1 << instr.getOpcode() - opc_ireturn) & 0xa) != 0
&& result.pop() != Type.tVoid)
throw new VerifyException(instr.getDescription());
Type type = result.pop();
if (!isOfType(type, types[instr.opcode - opc_ireturn])
if (!isOfType(type, types[instr.getOpcode() - opc_ireturn])
|| !isOfType(type, mt.getReturnType()))
throw new VerifyException(instr.getDescription());
break;
}
case opc_jsr: {
result.stack[result.stackHeight++]
= new ReturnAddressType(instr.succs[0]);
= new ReturnAddressType(instr.getSuccs()[0]);
result.jsrTargets = new Instruction[jsrLength+1];
result.jsrLocals = new BitSet[jsrLength+1];
if (jsrLength > 0) {
for (int i=0; i< prevInfo.jsrTargets.length; i++)
if (prevInfo.jsrTargets[i] == instr.succs[0])
if (prevInfo.jsrTargets[i] == instr.getSuccs()[0])
throw new VerifyException(instr.getDescription()+
" is recursive");
System.arraycopy(prevInfo.jsrTargets, 0,
@ -738,7 +750,7 @@ public class CodeVerifier implements Opcodes {
System.arraycopy(prevInfo.jsrLocals, 0,
result.jsrLocals, 0, jsrLength);
}
result.jsrTargets[jsrLength] = instr.succs[0];
result.jsrTargets[jsrLength] = instr.getSuccs()[0];
result.jsrLocals[jsrLength] = new BitSet();
break;
}
@ -748,7 +760,7 @@ public class CodeVerifier implements Opcodes {
break;
case opc_getstatic: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
Type type = Type.tType(ref.getType());
result.push(type);
if (type.stackSize() == 2)
@ -756,7 +768,7 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_getfield: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
Type classType = Type.tType(ref.getClazz());
if (!isOfType(result.pop(), classType))
throw new VerifyException(instr.getDescription());
@ -767,7 +779,7 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_putstatic: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
Type type = Type.tType(ref.getType());
if (type.stackSize() == 2
&& result.pop() != Type.tVoid)
@ -777,7 +789,7 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_putfield: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
Type type = Type.tType(ref.getType());
if (type.stackSize() == 2
&& result.pop() != Type.tVoid)
@ -793,7 +805,7 @@ public class CodeVerifier implements Opcodes {
case opc_invokespecial:
case opc_invokestatic :
case opc_invokeinterface: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
MethodType refmt = (MethodType) Type.tType(ref.getType());
Type[] paramTypes = refmt.getParameterTypes();
for (int i=paramTypes.length - 1; i >= 0; i--) {
@ -825,7 +837,7 @@ public class CodeVerifier implements Opcodes {
for (int i=0; i< result.locals.length; i++)
if (result.locals[i] == clazz)
result.locals[i] = newType;
} else if (instr.opcode != opc_invokestatic) {
} else if (instr.getOpcode() != opc_invokestatic) {
Type classType = Type.tType(ref.getClazz());
if (!isOfType(result.pop(), classType))
throw new VerifyException(instr.getDescription());
@ -839,7 +851,7 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_new: {
String clName = (String) instr.objData;
String clName = instr.getClazzType();
ClassInfo ci = ClassInfo.forName
(clName.substring(1, clName.length()-1).replace('/','.'));
result.stack[result.stackHeight++] =
@ -859,7 +871,7 @@ public class CodeVerifier implements Opcodes {
break;
}
case opc_checkcast: {
Type classType = Type.tType((String) instr.objData);
Type classType = Type.tType(instr.getClazzType());
if (!isOfType(result.pop(), Type.tUObject))
throw new VerifyException(instr.getDescription());
result.push(classType);
@ -877,16 +889,16 @@ public class CodeVerifier implements Opcodes {
throw new VerifyException(instr.getDescription());
break;
case opc_multianewarray: {
int dimension = instr.intData;
int dimension = instr.getIntData();
for (int i=dimension - 1; i >= 0; i--)
if (!isOfType(result.pop(), Type.tInt))
throw new VerifyException(instr.getDescription());
Type classType = Type.tType((String) instr.objData);
Type classType = Type.tType(instr.getClazzType());
result.push(classType);
break;
}
default:
throw new AssertError("Invalid opcode "+instr.opcode);
throw new AssertError("Invalid opcode "+instr.getOpcode());
}
return result;
}
@ -894,28 +906,28 @@ public class CodeVerifier implements Opcodes {
public void doVerify() throws VerifyException {
Stack instrStack = new Stack();
bi.getFirstInstr().tmpInfo = initInfo();
bi.getFirstInstr().setTmpInfo(initInfo());
instrStack.push(bi.getFirstInstr());
Handler[] handlers = bi.getExceptionHandlers();
while (!instrStack.isEmpty()) {
Instruction instr = (Instruction) instrStack.pop();
if (!instr.alwaysJumps && instr.nextByAddr == null)
if (!instr.doesAlwaysJump() && instr.getNextByAddr() == null)
throw new VerifyException("Flow can fall off end of method");
VerifyInfo prevInfo = (VerifyInfo) instr.tmpInfo;
if (instr.opcode == opc_ret) {
VerifyInfo prevInfo = (VerifyInfo) instr.getTmpInfo();
if (instr.getOpcode() == opc_ret) {
if (prevInfo.jsrTargets == null
|| !(prevInfo.locals[instr.localSlot]
|| !(prevInfo.locals[instr.getLocalSlot()]
instanceof ReturnAddressType))
throw new VerifyException(instr.getDescription());
int jsrLength = prevInfo.jsrTargets.length - 1;
Instruction jsrTarget =
((ReturnAddressType)
prevInfo.locals[instr.localSlot]).jsrTarget;
prevInfo.locals[instr.getLocalSlot()]).jsrTarget;
while (jsrTarget != prevInfo.jsrTargets[jsrLength])
if (--jsrLength < 0)
throw new VerifyException(instr.getDescription());
VerifyInfo jsrTargetInfo = (VerifyInfo) jsrTarget.tmpInfo;
VerifyInfo jsrTargetInfo = (VerifyInfo) jsrTarget.getTmpInfo();
if (jsrTargetInfo.retInstr == null)
jsrTargetInfo.retInstr = instr;
else if (jsrTargetInfo.retInstr != instr)
@ -935,37 +947,37 @@ public class CodeVerifier implements Opcodes {
nextTargets = null;
nextLocals = null;
}
for (int i=0; i < jsrTarget.preds.length; i++) {
Instruction jsrInstr = jsrTarget.preds[i];
if (jsrInstr.tmpInfo != null)
for (int i=0; i < jsrTarget.getPreds().length; i++) {
Instruction jsrInstr = jsrTarget.getPreds()[i];
if (jsrInstr.getTmpInfo() != null)
instrStack.push(jsrInstr);
}
} else {
VerifyInfo info = modelEffect(instr, prevInfo);
if (!instr.alwaysJumps)
if (mergeInfo(instr.nextByAddr, info))
instrStack.push(instr.nextByAddr);
if (instr.opcode == opc_jsr) {
if (!instr.doesAlwaysJump())
if (mergeInfo(instr.getNextByAddr(), info))
instrStack.push(instr.getNextByAddr());
if (instr.getOpcode() == opc_jsr) {
VerifyInfo targetInfo =
(VerifyInfo) instr.succs[0].tmpInfo;
(VerifyInfo) instr.getSuccs()[0].getTmpInfo();
if (targetInfo != null && targetInfo.retInstr != null) {
VerifyInfo afterJsrInfo
= (VerifyInfo) prevInfo.clone();
VerifyInfo retInfo
= (VerifyInfo) targetInfo.retInstr.tmpInfo;
= (VerifyInfo) targetInfo.retInstr.getTmpInfo();
BitSet usedLocals
= retInfo.jsrLocals[retInfo.jsrLocals.length-1];
for (int j = 0; j < bi.getMaxLocals(); j++) {
if (usedLocals.get(j))
afterJsrInfo.locals[j] = retInfo.locals[j];
}
if (mergeInfo(instr.nextByAddr, afterJsrInfo))
instrStack.push(instr.nextByAddr);
if (mergeInfo(instr.getNextByAddr(), afterJsrInfo))
instrStack.push(instr.getNextByAddr());
}
}
if (instr.succs != null) {
for (int i=0; i< instr.succs.length; i++) {
if (instr.succs[i].addr < instr.addr) {
if (instr.getSuccs() != null) {
for (int i=0; i< instr.getSuccs().length; i++) {
if (instr.getSuccs()[i].getAddr() < instr.getAddr()) {
/* This is a backwards branch */
for (int j = 0; j < prevInfo.locals.length; j++) {
if (prevInfo.locals[j]
@ -980,14 +992,14 @@ public class CodeVerifier implements Opcodes {
("Uninitialized stack in back-branch");
}
}
if (mergeInfo(instr.succs[i],
if (mergeInfo(instr.getSuccs()[i],
(VerifyInfo) info.clone()))
instrStack.push(instr.succs[i]);
instrStack.push(instr.getSuccs()[i]);
}
}
for (int i=0; i<handlers.length; i++) {
if (handlers[i].start.addr <= instr.addr
&& handlers[i].end.addr >= instr.addr) {
if (handlers[i].start.getAddr() <= instr.getAddr()
&& handlers[i].end.getAddr() >= instr.getAddr()) {
for (int j = 0; j < prevInfo.locals.length; j++) {
if (prevInfo.locals[j]
instanceof UninitializedClassType)
@ -1011,9 +1023,9 @@ public class CodeVerifier implements Opcodes {
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_VERIFIER) != 0) {
for (Instruction instr = bi.getFirstInstr(); instr != null;
instr = instr.nextByAddr) {
instr = instr.getNextByAddr()) {
VerifyInfo info = (VerifyInfo) instr.tmpInfo;
VerifyInfo info = (VerifyInfo) instr.getTmpInfo();
if (info != null)
GlobalOptions.err.println(info.toString());
GlobalOptions.err.println(instr.getDescription());
@ -1021,8 +1033,8 @@ public class CodeVerifier implements Opcodes {
}
}
for (Instruction instr = bi.getFirstInstr(); instr != null;
instr = instr.nextByAddr)
instr.tmpInfo = null;
instr = instr.getNextByAddr())
instr.setTmpInfo(null);
}
@ -1031,14 +1043,14 @@ public class CodeVerifier implements Opcodes {
doVerify();
} catch (VerifyException ex) {
for (Instruction instr = bi.getFirstInstr(); instr != null;
instr = instr.nextByAddr) {
instr = instr.getNextByAddr()) {
VerifyInfo info = (VerifyInfo) instr.tmpInfo;
VerifyInfo info = (VerifyInfo) instr.getTmpInfo();
if (info != null)
GlobalOptions.err.println(info.toString());
GlobalOptions.err.println(instr.getDescription());
instr.tmpInfo = null;
instr.setTmpInfo(null);
}
throw ex;
}

@ -20,9 +20,14 @@
package jode.jvm;
import jode.AssertError;
import jode.GlobalOptions;
import jode.type.*;
import jode.bytecode.*;
import jode.decompiler.ClassAnalyzer;
import jode.bytecode.BytecodeInfo;
import jode.bytecode.Handler;
import jode.bytecode.Instruction;
import jode.bytecode.Opcodes;
import jode.bytecode.Reference;
import jode.type.MethodType;
import jode.type.Type;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
@ -53,7 +58,7 @@ public class Interpreter implements Opcodes {
throws InterpreterException, InvocationTargetException {
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_INTERPRT) != 0)
GlobalOptions.err.println("Interpreting "+code.getMethodInfo());
GlobalOptions.err.println("Interpreting "+code);
Value[] stack = new Value[code.getMaxStack()];
for (int i=0; i< stack.length; i++)
stack[i] = new Value();
@ -82,23 +87,23 @@ public class Interpreter implements Opcodes {
GlobalOptions.err.print(locals[i]+",");
GlobalOptions.err.println("]");
}
pc = instr.nextByAddr;
int opcode = instr.opcode;
pc = instr.getNextByAddr();
int opcode = instr.getOpcode();
switch (opcode) {
case opc_nop:
break;
case opc_ldc:
stack[stacktop++].setObject(instr.objData);
stack[stacktop++].setObject(instr.getConstant());
break;
case opc_ldc2_w:
stack[stacktop].setObject(instr.objData);
stack[stacktop].setObject(instr.getConstant());
stacktop += 2;
break;
case opc_iload: case opc_fload: case opc_aload:
stack[stacktop++].setValue(locals[instr.localSlot]);
stack[stacktop++].setValue(locals[instr.getLocalSlot()]);
break;
case opc_lload: case opc_dload:
stack[stacktop].setValue(locals[instr.localSlot]);
stack[stacktop].setValue(locals[instr.getLocalSlot()]);
stacktop += 2;
break;
case opc_iaload: case opc_laload:
@ -136,10 +141,10 @@ public class Interpreter implements Opcodes {
break;
}
case opc_istore: case opc_fstore: case opc_astore:
locals[instr.localSlot].setValue(stack[--stacktop]);
locals[instr.getLocalSlot()].setValue(stack[--stacktop]);
break;
case opc_lstore: case opc_dstore:
locals[instr.localSlot].setValue(stack[stacktop -= 2]);
locals[instr.getLocalSlot()].setValue(stack[stacktop -= 2]);
break;
case opc_lastore: case opc_dastore:
@ -404,8 +409,8 @@ public class Interpreter implements Opcodes {
break;
case opc_iinc:
locals[instr.localSlot].setInt
(locals[instr.localSlot].intValue() + instr.intData);
locals[instr.getLocalSlot()].setInt
(locals[instr.getLocalSlot()].intValue() + instr.getIntData());
break;
case opc_i2l:
stack[stacktop-1]
@ -541,7 +546,7 @@ public class Interpreter implements Opcodes {
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.succs[0];
pc = instr.getSuccs()[0];
break;
}
case opc_jsr:
@ -550,27 +555,27 @@ public class Interpreter implements Opcodes {
/* fall through */
case opc_goto:
case opc_goto_w:
pc = instr.succs[0];
pc = instr.getSuccs()[0];
break;
case opc_ret:
pc = (Instruction)locals[instr.localSlot].objectValue();
pc = (Instruction)locals[instr.getLocalSlot()].objectValue();
break;
case opc_tableswitch: {
int value = stack[--stacktop].intValue();
int low = instr.intData;
if (value >= low && value <= low + instr.succs.length - 2)
pc = instr.succs[value - low];
int low = instr.getIntData();
if (value >= low && value <= low + instr.getSuccs().length - 2)
pc = instr.getSuccs()[value - low];
else
pc = instr.succs[instr.succs.length-1];
pc = instr.getSuccs()[instr.getSuccs().length-1];
break;
}
case opc_lookupswitch: {
int value = stack[--stacktop].intValue();
int[] values = (int[]) instr.objData;
pc = instr.succs[values.length];
int[] values = instr.getValues();
pc = instr.getSuccs()[values.length];
for (int i=0; i< values.length; i++) {
if (values[i] == value) {
pc = instr.succs[i];
pc = instr.getSuccs()[i];
break;
}
}
@ -583,46 +588,46 @@ public class Interpreter implements Opcodes {
case opc_return:
return Void.TYPE;
case opc_getstatic: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
stack[stacktop].setObject
(env.getField((Reference) instr.objData, null));
(env.getField(instr.getReference(), null));
stacktop += Type.tType(ref.getType()).stackSize();
break;
}
case opc_getfield: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
Object cls = stack[--stacktop];
if (cls == null)
throw new InvocationTargetException
(new NullPointerException());
stack[stacktop].setObject
(env.getField((Reference) instr.objData, cls));
(env.getField(instr.getReference(), cls));
stacktop += Type.tType(ref.getType()).stackSize();
break;
}
case opc_putstatic: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
stacktop -= Type.tType(ref.getType()).stackSize();
Object value = stack[stacktop];
env.putField((Reference) instr.objData, null, value);
env.putField(instr.getReference(), null, value);
break;
}
case opc_putfield: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
stacktop -= Type.tType(ref.getType()).stackSize();
Object value = stack[stacktop];
Object cls = stack[--stacktop];
if (cls == null)
throw new InvocationTargetException
(new NullPointerException());
env.putField((Reference) instr.objData, cls, value);
env.putField(instr.getReference(), cls, value);
break;
}
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic :
case opc_invokeinterface: {
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
MethodType mt = (MethodType) Type.tType(ref.getType());
Object[] args = new Object[mt.getParameterTypes().length];
for (int i=args.length - 1; i >= 0; i--) {
@ -654,14 +659,14 @@ public class Interpreter implements Opcodes {
break;
}
case opc_new: {
String clazz = (String) instr.objData;
String clazz = instr.getClazzType();
stack[stacktop++].setNewObject(new NewObject(clazz));
break;
}
case opc_newarray: {
int length = stack[--stacktop].intValue();
try {
switch (instr.intData) {
switch (instr.getIntData()) {
case 4:
stack[stacktop++].setObject(new boolean[length]);
break;
@ -698,7 +703,7 @@ public class Interpreter implements Opcodes {
int length = stack[--stacktop].intValue();
try {
stack[stacktop++].setObject
(env.newArray((String) instr.objData,
(env.newArray(instr.getClazzType(),
new int[] { length }));
} catch (NegativeArraySizeException ex) {
throw new InvocationTargetException(ex);
@ -719,7 +724,7 @@ public class Interpreter implements Opcodes {
case opc_checkcast: {
Object obj = stack[stacktop-1].objectValue();
if (obj != null
&& !env.instanceOf(obj, (String) instr.objData))
&& !env.instanceOf(obj, instr.getClazzType()))
throw new InvocationTargetException
(new ClassCastException(obj.getClass().getName()));
break;
@ -727,7 +732,7 @@ public class Interpreter implements Opcodes {
case opc_instanceof: {
Object obj = stack[--stacktop].objectValue();
stack[stacktop++].setInt
(env.instanceOf(obj, (String) instr.objData) ? 1 : 0);
(env.instanceOf(obj, instr.getClazzType()) ? 1 : 0);
break;
}
case opc_monitorenter:
@ -737,13 +742,13 @@ public class Interpreter implements Opcodes {
env.exitMonitor(stack[--stacktop].objectValue());
break;
case opc_multianewarray: {
int dimension = instr.intData;
int dimension = instr.getIntData();
int[] dims = new int[dimension];
for (int i=dimension - 1; i >= 0; i--)
dims[i] = stack[--stacktop].intValue();
try {
stack[stacktop++].setObject
(env.newArray((String) instr.objData, dims));
(env.newArray(instr.getClazzType(), dims));
} catch (NegativeArraySizeException ex) {
throw new InvocationTargetException(ex);
}
@ -756,8 +761,8 @@ public class Interpreter implements Opcodes {
Handler[] handlers = code.getExceptionHandlers();
Throwable obj = ex.getTargetException();
for (int i=0; i< handlers.length; i++) {
if (handlers[i].start.addr <= pc.addr
&& handlers[i].end.addr >= pc.addr
if (handlers[i].start.getAddr() <= pc.getAddr()
&& handlers[i].end.getAddr() >= pc.getAddr()
&& (handlers[i].type == null
|| env.instanceOf(obj, handlers[i].type))) {
stacktop = 0;

@ -18,7 +18,6 @@
*/
package jode.jvm;
import jode.bytecode.*;
/**
* This exception is thrown by the interpreter on various conditions.

@ -18,7 +18,6 @@
*/
package jode.jvm;
import jode.bytecode.*;
/**
* This class represents a new object, that may not be initialized yet.

@ -20,8 +20,15 @@
package jode.jvm;
import jode.AssertError;
import jode.bytecode.Reference;
import jode.type.*;
import java.lang.reflect.*;
import jode.type.Type;
import jode.type.IntegerType;
import jode.type.MethodType;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class SimpleRuntimeEnvironment implements RuntimeEnvironment {

@ -63,10 +63,10 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
opc_astore, opc_new, opc_dup, opc_aload,
opc_invokevirtual, opc_invokespecial, opc_athrow
};
private static final Object[] getClassRefs = {
private static final Reference[] getClassRefs = {
null, Reference.getReference("Ljava/lang/Class;", "forName",
"(Ljava/lang/String;)Ljava/lang/Class;"),
null, null, "Ljava/lang/NoClassDefFoundError;", null, null,
null, null, null, null, null,
Reference.getReference("Ljava/lang/Throwable;", "getMessage",
"()Ljava/lang/String;"),
Reference.getReference("Ljava/lang/NoClassDefFoundError;", "<init>",
@ -88,25 +88,29 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
int excSlot = -1;
Instruction instr = bytecode.getFirstInstr();
if (excHandlers[0].start != instr)
if (excHandlers[0].start != instr
|| !"java.lang.ClassNotFoundException".equals(excHandlers[0].type))
return false;
for (int i=0; i< getClassOpcodes.length; i++) {
if (instr.opcode != getClassOpcodes[i])
if (instr.getOpcode() != getClassOpcodes[i])
return false;
if (i==0 && instr.localSlot != 0)
if (i==0 && instr.getLocalSlot() != 0)
return false;
if (i == 3)
excSlot = instr.localSlot;
if (i == 6 && instr.localSlot != excSlot)
excSlot = instr.getLocalSlot();
if (i == 6 && instr.getLocalSlot() != excSlot)
return false;
if (i == 2 && excHandlers[0].end != instr)
return false;
if (i == 3 && excHandlers[0].catcher != instr)
return false;
if (i == 4 && !instr.getClazzType().equals
("Ljava/lang/NoClassDefFoundError;"))
return false;
if (getClassRefs[i] != null
&& !getClassRefs[i].equals(instr.objData))
&& !getClassRefs[i].equals(instr.getReference()))
return false;
instr = instr.nextByAddr;
instr = instr.getNextByAddr();
}
if (instr != null)
return false;
@ -122,8 +126,8 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
BytecodeInfo bytecode = method.getBytecode();
Instruction instr = bytecode.getFirstInstr();
if (instr.opcode == opc_getstatic) {
Reference ref = (Reference) instr.objData;
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('.','/'))))
@ -133,10 +137,11 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
if ((refField.getModifiers() & modifierMask) !=
(Modifier.PRIVATE | Modifier.STATIC))
return false;
instr = instr.nextByAddr;
if (instr.opcode < opc_ireturn || instr.opcode > opc_areturn)
instr = instr.getNextByAddr();
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
return false;
if (instr.nextByAddr != null)
if (instr.getNextByAddr() != null)
return false;
/* For valid bytecode the type matches automatically */
reference = ref;
@ -144,18 +149,19 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
return true;
}
int params = 0, slot = 0;
while (instr.opcode >= opc_iload && instr.opcode <= opc_aload
&& instr.localSlot == slot) {
while (instr.getOpcode() >= opc_iload
&& instr.getOpcode() <= opc_aload
&& instr.getLocalSlot() == slot) {
params++;
slot += (instr.opcode == opc_lload
|| instr.opcode == opc_dload) ? 2 : 1;
instr = instr.nextByAddr;
slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1;
instr = instr.getNextByAddr();
}
if (instr.opcode == opc_putstatic) {
if (instr.getOpcode() == opc_putstatic) {
if (params != 1)
return false;
/* For valid bytecode the type of param matches automatically */
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
@ -165,17 +171,17 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
if ((refField.getModifiers() & modifierMask) !=
(Modifier.PRIVATE | Modifier.STATIC))
return false;
instr = instr.nextByAddr;
if (instr.opcode != opc_return)
instr = instr.getNextByAddr();
if (instr.getOpcode() != opc_return)
return false;
if (instr.nextByAddr != null)
if (instr.getNextByAddr() != null)
return false;
reference = ref;
kind = ACCESSPUTSTATIC;
return true;
}
if (instr.opcode == opc_invokestatic) {
Reference ref = (Reference) instr.objData;
if (instr.getOpcode() == opc_invokestatic) {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
@ -187,15 +193,16 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
(Modifier.PRIVATE | Modifier.STATIC)
|| refType.getParameterTypes().length != params)
return false;
instr = instr.nextByAddr;
instr = instr.getNextByAddr();
if (refType.getReturnType() == Type.tVoid) {
if (instr.opcode != opc_return)
if (instr.getOpcode() != opc_return)
return false;
} else {
if (instr.opcode < opc_ireturn || instr.opcode > opc_areturn)
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
return false;
}
if (instr.nextByAddr != null)
if (instr.getNextByAddr() != null)
return false;
/* For valid bytecode the types matches automatically */
@ -219,12 +226,12 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
}
Instruction instr = bytecode.getFirstInstr();
if (instr.opcode != opc_aload || instr.localSlot != 0)
if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0)
return false;
instr = instr.nextByAddr;
instr = instr.getNextByAddr();
if (instr.opcode == opc_getfield) {
Reference ref = (Reference) instr.objData;
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('.','/'))))
@ -233,10 +240,11 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
= clazzInfo.findField(ref.getName(), ref.getType());
if ((refField.getModifiers() & modifierMask) != Modifier.PRIVATE)
return false;
instr = instr.nextByAddr;
if (instr.opcode < opc_ireturn || instr.opcode > opc_areturn)
instr = instr.getNextByAddr();
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
return false;
if (instr.nextByAddr != null)
if (instr.getNextByAddr() != null)
return false;
/* For valid bytecode the type matches automatically */
reference = ref;
@ -244,18 +252,19 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
return true;
}
int params = 0, slot = 1;
while (instr.opcode >= opc_iload && instr.opcode <= opc_aload
&& instr.localSlot == slot) {
while (instr.getOpcode() >= opc_iload
&& instr.getOpcode() <= opc_aload
&& instr.getLocalSlot() == slot) {
params++;
slot += (instr.opcode == opc_lload
|| instr.opcode == opc_dload) ? 2 : 1;
instr = instr.nextByAddr;
slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1;
instr = instr.getNextByAddr();
}
if (instr.opcode == opc_putfield) {
if (instr.getOpcode() == opc_putfield) {
if (params != 1)
return false;
/* For valid bytecode the type of param matches automatically */
Reference ref = (Reference) instr.objData;
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
if (!(refClazz.substring(0, refClazz.length()-1)
.equals(clazzInfo.getName().replace('.','/'))))
@ -264,17 +273,17 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
= clazzInfo.findField(ref.getName(), ref.getType());
if ((refField.getModifiers() & modifierMask) != Modifier.PRIVATE)
return false;
instr = instr.nextByAddr;
if (instr.opcode != opc_return)
instr = instr.getNextByAddr();
if (instr.getOpcode() != opc_return)
return false;
if (instr.nextByAddr != null)
if (instr.getNextByAddr() != null)
return false;
reference = ref;
kind = ACCESSPUTFIELD;
return true;
}
if (instr.opcode == opc_invokespecial) {
Reference ref = (Reference) instr.objData;
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('.','/'))))
@ -285,15 +294,16 @@ public class SyntheticAnalyzer implements jode.bytecode.Opcodes {
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE
|| refType.getParameterTypes().length != params)
return false;
instr = instr.nextByAddr;
instr = instr.getNextByAddr();
if (refType.getReturnType() == Type.tVoid) {
if (instr.opcode != opc_return)
if (instr.getOpcode() != opc_return)
return false;
} else {
if (instr.opcode < opc_ireturn || instr.opcode > opc_areturn)
if (instr.getOpcode() < opc_ireturn
|| instr.getOpcode() > opc_areturn)
return false;
}
if (instr.nextByAddr != null)
if (instr.getNextByAddr() != null)
return false;
/* For valid bytecode the types matches automatically */

Loading…
Cancel
Save