Adapted to new bytecode package.

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

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

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