diff --git a/jode/jode/jvm/CodeVerifier.java b/jode/jode/jvm/CodeVerifier.java index 2211772..22babc9 100644 --- a/jode/jode/jvm/CodeVerifier.java +++ b/jode/jode/jvm/CodeVerifier.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= 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; } diff --git a/jode/jode/jvm/Interpreter.java b/jode/jode/jvm/Interpreter.java index b5d36a3..8883b5d 100644 --- a/jode/jode/jvm/Interpreter.java +++ b/jode/jode/jvm/Interpreter.java @@ -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; diff --git a/jode/jode/jvm/InterpreterException.java b/jode/jode/jvm/InterpreterException.java index 1901507..bdbf5e9 100644 --- a/jode/jode/jvm/InterpreterException.java +++ b/jode/jode/jvm/InterpreterException.java @@ -18,7 +18,6 @@ */ package jode.jvm; -import jode.bytecode.*; /** * This exception is thrown by the interpreter on various conditions. diff --git a/jode/jode/jvm/NewObject.java b/jode/jode/jvm/NewObject.java index 9412b32..3020f3d 100644 --- a/jode/jode/jvm/NewObject.java +++ b/jode/jode/jvm/NewObject.java @@ -18,7 +18,6 @@ */ package jode.jvm; -import jode.bytecode.*; /** * This class represents a new object, that may not be initialized yet. diff --git a/jode/jode/jvm/SimpleRuntimeEnvironment.java b/jode/jode/jvm/SimpleRuntimeEnvironment.java index 891a7cb..201ca89 100644 --- a/jode/jode/jvm/SimpleRuntimeEnvironment.java +++ b/jode/jode/jvm/SimpleRuntimeEnvironment.java @@ -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 { diff --git a/jode/jode/jvm/SyntheticAnalyzer.java b/jode/jode/jvm/SyntheticAnalyzer.java index 16a0c7f..1efe940 100644 --- a/jode/jode/jvm/SyntheticAnalyzer.java +++ b/jode/jode/jvm/SyntheticAnalyzer.java @@ -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;", "", @@ -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 */