--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, i list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, i list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "i product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, i acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from i software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from i software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * i SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF i SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * i software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.aspectj.apache.bcel.verifier;
+
+import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.generic.FieldInstruction;
+import org.aspectj.apache.bcel.generic.InstVisitor;
+import org.aspectj.apache.bcel.generic.Instruction;
+import org.aspectj.apache.bcel.generic.InstructionBranch;
+import org.aspectj.apache.bcel.generic.InstructionLV;
+import org.aspectj.apache.bcel.generic.InvokeInstruction;
+
+/**
+ * Traverse an instruction
+ *
+ * @author Andy Clement
+ */
+public class InstructionWalker implements Constants {
+
+ /**
+ * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call methods
+ * according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
+ *
+ * @param i the instruction to visit
+ * @param v Visitor object
+ */
+ public static void accept(Instruction i, InstVisitor v) {
+ switch (i.opcode) {
+ case IMPDEP1:
+ v.visitIMPDEP1(i);
+ break;
+ case IMPDEP2:
+ v.visitIMPDEP2(i);
+ break;
+ case MONITORENTER:
+ v.visitExceptionThrower(i);
+ v.visitStackConsumer(i);
+ v.visitMONITORENTER(i);
+ break;
+ case MONITOREXIT:
+ v.visitExceptionThrower(i);
+ v.visitStackConsumer(i);
+ v.visitMONITOREXIT(i);
+ break;
+ case LCMP:
+ v.visitTypedInstruction(i);
+ v.visitStackProducer(i);
+ v.visitStackConsumer(i);
+ v.visitLCMP(i);
+ break;
+ case FCMPL:
+ v.visitTypedInstruction(i);
+ v.visitStackProducer(i);
+ v.visitStackConsumer(i);
+ v.visitFCMPL(i);
+ break;
+ case FCMPG:
+ v.visitTypedInstruction(i);
+ v.visitStackProducer(i);
+ v.visitStackConsumer(i);
+ v.visitFCMPG(i);
+ break;
+ case DCMPL:
+ v.visitTypedInstruction(i);
+ v.visitStackProducer(i);
+ v.visitStackConsumer(i);
+ v.visitDCMPL(i);
+ break;
+ case DCMPG:
+ v.visitTypedInstruction(i);
+ v.visitStackProducer(i);
+ v.visitStackConsumer(i);
+ v.visitDCMPG(i);
+ break;
+ case NOP:
+ v.visitNOP(i);
+ break;
+ case BREAKPOINT:
+ v.visitBREAKPOINT(i);
+ break;
+ case SWAP:
+ v.visitStackConsumer(i);
+ v.visitStackProducer(i);
+ v.visitStackInstruction(i);
+ v.visitSWAP(i);
+ break;
+ case POP:
+ v.visitStackConsumer(i);
+ v.visitPopInstruction(i);
+ v.visitStackInstruction(i);
+ v.visitPOP(i);
+ break;
+ case POP2:
+ v.visitStackConsumer(i);
+ v.visitPopInstruction(i);
+ v.visitStackInstruction(i);
+ v.visitPOP2(i);
+ break;
+ case DUP2_X1:
+ v.visitStackInstruction(i);
+ v.visitDUP2_X1(i);
+ break;
+ case DUP2_X2:
+ v.visitStackInstruction(i);
+ v.visitDUP2_X2(i);
+ break;
+ case DUP2:
+ v.visitStackProducer(i);
+ v.visitPushInstruction(i);
+ v.visitStackInstruction(i);
+ v.visitDUP2(i);
+ break;
+ case DUP_X1:
+ v.visitStackInstruction(i);
+ v.visitDUP_X1(i);
+ break;
+ case DUP_X2:
+ v.visitStackInstruction(i);
+ v.visitDUP_X2(i);
+ break;
+ case DUP:
+ v.visitStackProducer(i);
+ v.visitPushInstruction(i);
+ v.visitStackInstruction(i);
+ v.visitDUP(i);
+ break;
+ case BASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitBASTORE(i);
+ break;
+ case CASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitCASTORE(i);
+ break;
+ case SASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitSASTORE(i);
+ break;
+ case DASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitDASTORE(i);
+ break;
+ case FASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitFASTORE(i);
+ break;
+ case LASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitLASTORE(i);
+ break;
+ case IASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitIASTORE(i);
+ break;
+ case AASTORE:
+ v.visitStackConsumer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitAASTORE(i);
+ break;
+ case SALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitSALOAD(i);
+ break;
+ case CALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitCALOAD(i);
+ break;
+ case DALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitDALOAD(i);
+ break;
+ case FALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitFALOAD(i);
+ break;
+ case LALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitLALOAD(i);
+ break;
+ case AALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitAALOAD(i);
+ break;
+ case ATHROW:
+ v.visitUnconditionalBranch(i);
+ v.visitExceptionThrower(i);
+ v.visitATHROW(i);
+ break;
+ case ACONST_NULL:
+ v.visitStackProducer(i);
+ v.visitPushInstruction(i);
+ v.visitTypedInstruction(i);
+ v.visitACONST_NULL(i);
+ break;
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ v.visitPushInstruction(i);
+ v.visitStackProducer(i);
+ v.visitTypedInstruction(i);
+ v.visitConstantPushInstruction(i);
+ v.visitICONST(i);
+ break;
+ case LCONST_0:
+ case LCONST_1:
+ v.visitPushInstruction(i);
+ v.visitStackProducer(i);
+ v.visitTypedInstruction(i);
+ v.visitConstantPushInstruction(i);
+ v.visitLCONST(i);
+ break;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ v.visitPushInstruction(i);
+ v.visitStackProducer(i);
+ v.visitTypedInstruction(i);
+ v.visitConstantPushInstruction(i);
+ v.visitFCONST(i);
+ break;
+ case DCONST_0:
+ case DCONST_1:
+ v.visitPushInstruction(i);
+ v.visitStackProducer(i);
+ v.visitTypedInstruction(i);
+ v.visitConstantPushInstruction(i);
+ v.visitDCONST(i);
+ break;
+ case BALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitBALOAD(i);
+ break;
+ case IALOAD:
+ v.visitStackProducer(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitArrayInstruction(i);
+ v.visitIALOAD(i);
+ break;
+ case BIPUSH:
+ v.visitPushInstruction(i);
+ v.visitStackProducer(i);
+ v.visitTypedInstruction(i);
+ v.visitConstantPushInstruction(i);
+ v.visitBIPUSH(i);
+ break;
+ case SIPUSH:
+ v.visitPushInstruction(i);
+ v.visitStackProducer(i);
+ v.visitTypedInstruction(i);
+ v.visitConstantPushInstruction(i);
+ v.visitSIPUSH(i);
+ break;
+ case LDC:
+ case LDC_W:
+ v.visitStackProducer(i);
+ v.visitPushInstruction(i);
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitCPInstruction(i);
+ v.visitLDC(i);
+ break;
+ case LDC2_W:
+ v.visitStackProducer(i);
+ v.visitPushInstruction(i);
+ v.visitTypedInstruction(i);
+ v.visitCPInstruction(i);
+ v.visitLDC2_W(i);
+ break;
+ case ARRAYLENGTH:
+ v.visitExceptionThrower(i);
+ v.visitStackProducer(i);
+ v.visitARRAYLENGTH(i);
+ break;
+ case ASTORE_0:
+ v.visitStackConsumer(i);
+ v.visitPopInstruction(i);
+ v.visitStoreInstruction(i);
+ v.visitTypedInstruction(i);
+ v.visitLocalVariableInstruction((InstructionLV) i);
+ v.visitStoreInstruction(i);
+ v.visitASTORE(i);
+ break;
+ case ALOAD_0:
+ v.visitStackConsumer(i);
+ v.visitPopInstruction(i);
+ v.visitStoreInstruction(i);
+ v.visitTypedInstruction(i);
+ v.visitLocalVariableInstruction((InstructionLV) i);
+ v.visitStoreInstruction(i);
+ v.visitALOAD(i);
+ break;
+ // for store instructions: ISTORE > ASTORE_3 - needs to visit the instruction too
+ // v.visitStackConsumer(i);
+ // v.visitPopInstruction(i);
+ // v.visitStoreInstruction(i);
+ // v.visitTypedInstruction(i);
+ // v.visitLocalVariableInstruction(i);
+ // v.visitStoreInstruction(i);
+ // for load instructions: ILOAD > ALOAD_3 - needs to visit the instruction too
+ // v.visitStackProducer(i);
+ // v.visitPushInstruction(i);
+ // v.visitTypedInstruction(i);
+ // v.visitLocalVariableInstruction(i);
+ // v.visitLoadInstruction(i);
+
+ // for conversion instructions: (all 15 of them) - needs to visit conversion instruction too
+ // v.visitTypedInstruction(i);
+ // v.visitStackProducer(i);
+ // v.visitStackConsumer(i);
+ // v.visitConversionInstruction(i);
+
+ // arithmetic instructions - need to visit the instructions too (iadd etc)
+ // v.visitTypedInstruction(i);
+ // v.visitStackProducer(i);
+ // v.visitStackConsumer(i);
+ // v.visitArithmeticInstruction(i);
+
+ case INVOKESTATIC:
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitStackConsumer(i);
+ v.visitStackProducer(i);
+ v.visitLoadClass(i);
+ v.visitCPInstruction(i);
+ v.visitFieldOrMethod(i);
+ v.visitInvokeInstruction((InvokeInstruction) i);
+ v.visitINVOKESTATIC((InvokeInstruction) i);
+ break;
+
+ case GOTO:
+ v.visitVariableLengthInstruction(i);
+ v.visitUnconditionalBranch(i);
+ v.visitBranchInstruction((InstructionBranch) i);
+ v.visitGotoInstruction(i);
+ v.visitGOTO(i);
+ break;
+ case PUTSTATIC:
+ v.visitExceptionThrower(i);
+ v.visitStackConsumer(i);
+ v.visitPopInstruction(i);
+ v.visitTypedInstruction(i);
+ v.visitLoadClass(i);
+ v.visitCPInstruction(i);
+ v.visitFieldOrMethod(i);
+ v.visitFieldInstruction(i);
+ v.visitPUTSTATIC((FieldInstruction) i);
+ break;
+ case RETURN:
+ v.visitExceptionThrower(i);
+ v.visitTypedInstruction(i);
+ v.visitStackConsumer(i);
+ v.visitReturnInstruction(i);
+ v.visitRETURN(i);
+ break;
+ default:
+ throw new IllegalStateException("visiting not yet implemented for " + i.getName().toUpperCase());
+ }
+ }
+}
import org.aspectj.apache.bcel.generic.RET;
import org.aspectj.apache.bcel.generic.TABLESWITCH;
import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.apache.bcel.verifier.InstructionWalker;
import org.aspectj.apache.bcel.verifier.PassVerifier;
import org.aspectj.apache.bcel.verifier.VerificationResult;
import org.aspectj.apache.bcel.verifier.Verifier;
import org.aspectj.apache.bcel.verifier.exc.StaticCodeInstructionOperandConstraintException;
/**
- * This PassVerifier verifies a class file according to
- * pass 3, static part as described in The Java Virtual
- * Machine Specification, 2nd edition.
- * More detailed information is to be found at the do_verify()
- * method's documentation.
- *
- * @version $Id: Pass3aVerifier.java,v 1.3 2008/05/30 17:29:27 aclement Exp $
+ * This PassVerifier verifies a class file according to pass 3, static part as described in The Java Virtual Machine Specification,
+ * 2nd edition. More detailed information is to be found at the do_verify() method's documentation.
+ *
+ * @version $Id: Pass3aVerifier.java,v 1.4 2008/08/28 00:02:13 aclement Exp $
* @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
* @see #do_verify()
*/
-public final class Pass3aVerifier extends PassVerifier{
+public final class Pass3aVerifier extends PassVerifier {
/** The Verifier that created this. */
- private Verifier myOwner;
+ private final Verifier myOwner;
- /**
- * The method number to verify.
- * This is the index in the array returned
- * by JavaClass.getMethods().
+ /**
+ * The method number to verify. This is the index in the array returned by JavaClass.getMethods().
*/
- private int method_no;
+ private final int method_no;
- /** The one and only InstructionList object used by an instance of this class. It's here for performance reasons by do_verify() and its callees. */
+ /**
+ * The one and only InstructionList object used by an instance of this class. It's here for performance reasons by do_verify()
+ * and its callees.
+ */
InstructionList instructionList;
- /** The one and only Code object used by an instance of this class. It's here for performance reasons by do_verify() and its callees. */
+ /**
+ * The one and only Code object used by an instance of this class. It's here for performance reasons by do_verify() and its
+ * callees.
+ */
Code code;
/** Should only be instantiated by a Verifier. */
- public Pass3aVerifier(Verifier owner, int method_no){
+ public Pass3aVerifier(Verifier owner, int method_no) {
myOwner = owner;
this.method_no = method_no;
}
/**
- * Pass 3a is the verification of static constraints of
- * JVM code (such as legal targets of branch instructions).
- * This is the part of pass 3 where you do not need data
- * flow analysis.
- * JustIce also delays the checks for a correct exception
- * table of a Code attribute and correct line number entries
- * in a LineNumberTable attribute of a Code attribute (which
- * conceptually belong to pass 2) to this pass. Also, most
- * of the check for valid local variable entries in a
- * LocalVariableTable attribute of a Code attribute is
- * delayed until this pass.
- * All these checks need access to the code array of the
- * Code attribute.
- *
+ * Pass 3a is the verification of static constraints of JVM code (such as legal targets of branch instructions). This is the
+ * part of pass 3 where you do not need data flow analysis. JustIce also delays the checks for a correct exception table of a
+ * Code attribute and correct line number entries in a LineNumberTable attribute of a Code attribute (which conceptually belong
+ * to pass 2) to this pass. Also, most of the check for valid local variable entries in a LocalVariableTable attribute of a Code
+ * attribute is delayed until this pass. All these checks need access to the code array of the Code attribute.
+ *
* @throws InvalidMethodException if the method to verify does not exist.
*/
- public VerificationResult do_verify(){
- if (myOwner.doPass2().equals(VerificationResult.VR_OK)){
+ public VerificationResult do_verify() {
+ if (myOwner.doPass2().equals(VerificationResult.VR_OK)) {
// Okay, class file was loaded correctly by Pass 1
// and satisfies static constraints of Pass 2.
JavaClass jc = Repository.lookupClass(myOwner.getClassName());
Method[] methods = jc.getMethods();
- if (method_no >= methods.length){
+ if (method_no >= methods.length) {
throw new InvalidMethodException("METHOD DOES NOT EXIST!");
}
Method method = methods[method_no];
code = method.getCode();
-
+
// No Code? Nothing to verify!
- if ( method.isAbstract() || method.isNative() ){ // IF mg HAS NO CODE (static constraint of Pass 2)
+ if (method.isAbstract() || method.isNative()) { // IF mg HAS NO CODE (static constraint of Pass 2)
return VerificationResult.VR_OK;
}
// That examination should be implemented in a byte-oriented way, i.e. look for
// an instruction, make sure its validity, count its length, find the next
// instruction and so on.
- try{
+ try {
instructionList = new InstructionList(method.getCode().getCode());
+ } catch (RuntimeException re) {
+ return new VerificationResult(VerificationResult.VERIFIED_REJECTED,
+ "Bad bytecode in the code array of the Code attribute of method '" + method + "'.");
}
- catch(RuntimeException re){
- return new VerificationResult(VerificationResult.VERIFIED_REJECTED, "Bad bytecode in the code array of the Code attribute of method '"+method+"'.");
- }
-
+
instructionList.setPositions(true);
// Start verification.
- VerificationResult vr = VerificationResult.VR_OK; //default
- try{
+ VerificationResult vr = VerificationResult.VR_OK; // default
+ try {
delayedPass2Checks();
- }
- catch(ClassConstraintException cce){
+ } catch (ClassConstraintException cce) {
vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, cce.getMessage());
return vr;
}
- try{
+ try {
pass3StaticInstructionChecks();
pass3StaticInstructionOperandsChecks();
- }
- catch(StaticCodeConstraintException scce){
+ } catch (StaticCodeConstraintException scce) {
vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, scce.getMessage());
}
return vr;
- }
- else{ //did not pass Pass 2.
+ } else { // did not pass Pass 2.
return VerificationResult.VR_NOTYET;
}
}
/**
- * These are the checks that could be done in pass 2 but are delayed to pass 3
- * for performance reasons. Also, these checks need access to the code array
- * of the Code attribute of a Method so it's okay to perform them here.
- * Also see the description of the do_verify() method.
- *
+ * These are the checks that could be done in pass 2 but are delayed to pass 3 for performance reasons. Also, these checks need
+ * access to the code array of the Code attribute of a Method so it's okay to perform them here. Also see the description of the
+ * do_verify() method.
+ *
* @throws ClassConstraintException if the verification fails.
* @see #do_verify()
*/
- private void delayedPass2Checks(){
+ private void delayedPass2Checks() {
int[] instructionPositions = instructionList.getInstructionPositions();
int codeLength = code.getCode().length;
- /////////////////////
+ // ///////////////////
// LineNumberTable //
- /////////////////////
+ // ///////////////////
LineNumberTable lnt = code.getLineNumberTable();
- if (lnt != null){
+ if (lnt != null) {
LineNumber[] lineNumbers = lnt.getLineNumberTable();
IntList offsets = new IntList();
- lineNumber_loop: for (int i=0; i < lineNumbers.length; i++){ // may appear in any order.
- for (int j=0; j < instructionPositions.length; j++){
+ lineNumber_loop: for (int i = 0; i < lineNumbers.length; i++) { // may appear in any order.
+ for (int j = 0; j < instructionPositions.length; j++) {
// TODO: Make this a binary search! The instructionPositions array is naturally ordered!
int offset = lineNumbers[i].getStartPC();
- if (instructionPositions[j] == offset){
- if (offsets.contains(offset)){
- addMessage("LineNumberTable attribute '"+code.getLineNumberTable()+"' refers to the same code offset ('"+offset+"') more than once which is violating the semantics [but is sometimes produced by IBM's 'jikes' compiler].");
- }
- else{
+ if (instructionPositions[j] == offset) {
+ if (offsets.contains(offset)) {
+ addMessage("LineNumberTable attribute '"
+ + code.getLineNumberTable()
+ + "' refers to the same code offset ('"
+ + offset
+ + "') more than once which is violating the semantics [but is sometimes produced by IBM's 'jikes' compiler].");
+ } else {
offsets.add(offset);
}
continue lineNumber_loop;
}
}
- throw new ClassConstraintException("Code attribute '"+code+"' has a LineNumberTable attribute '"+code.getLineNumberTable()+"' referring to a code offset ('"+lineNumbers[i].getStartPC()+"') that does not exist.");
+ throw new ClassConstraintException("Code attribute '" + code + "' has a LineNumberTable attribute '"
+ + code.getLineNumberTable() + "' referring to a code offset ('" + lineNumbers[i].getStartPC()
+ + "') that does not exist.");
}
}
- ///////////////////////////
+ // /////////////////////////
// LocalVariableTable(s) //
- ///////////////////////////
- /* We cannot use code.getLocalVariableTable() because there could be more
- than only one. This is a bug in BCEL. */
+ // /////////////////////////
+ /*
+ * We cannot use code.getLocalVariableTable() because there could be more than only one. This is a bug in BCEL.
+ */
Attribute[] atts = code.getAttributes();
- for (int a=0; a<atts.length; a++){
- if (atts[a] instanceof LocalVariableTable){
+ for (int a = 0; a < atts.length; a++) {
+ if (atts[a] instanceof LocalVariableTable) {
LocalVariableTable lvt = (LocalVariableTable) atts[a];
- if (lvt != null){
+ if (lvt != null) {
LocalVariable[] localVariables = lvt.getLocalVariableTable();
- for (int i=0; i<localVariables.length; i++){
+ for (int i = 0; i < localVariables.length; i++) {
int startpc = localVariables[i].getStartPC();
- int length = localVariables[i].getLength();
-
- if (!contains(instructionPositions, startpc)){
- throw new ClassConstraintException("Code attribute '"+code+"' has a LocalVariableTable attribute '"+code.getLocalVariableTable()+"' referring to a code offset ('"+startpc+"') that does not exist.");
+ int length = localVariables[i].getLength();
+
+ if (!contains(instructionPositions, startpc)) {
+ throw new ClassConstraintException("Code attribute '" + code + "' has a LocalVariableTable attribute '"
+ + code.getLocalVariableTable() + "' referring to a code offset ('" + startpc
+ + "') that does not exist.");
}
- if ( (!contains(instructionPositions, startpc+length)) && (startpc+length != codeLength) ){
- throw new ClassConstraintException("Code attribute '"+code+"' has a LocalVariableTable attribute '"+code.getLocalVariableTable()+"' referring to a code offset start_pc+length ('"+(startpc+length)+"') that does not exist.");
+ if (!contains(instructionPositions, startpc + length) && startpc + length != codeLength) {
+ throw new ClassConstraintException("Code attribute '" + code + "' has a LocalVariableTable attribute '"
+ + code.getLocalVariableTable() + "' referring to a code offset start_pc+length ('"
+ + (startpc + length) + "') that does not exist.");
}
}
}
}
}
-
- ////////////////////
+
+ // //////////////////
// ExceptionTable //
- ////////////////////
+ // //////////////////
// In BCEL's "classfile" API, the startPC/endPC-notation is
// inclusive/exclusive as in the Java Virtual Machine Specification.
// WARNING: This is not true for BCEL's "generic" API.
CodeException[] exceptionTable = code.getExceptionTable();
- for (int i=0; i<exceptionTable.length; i++){
+ for (int i = 0; i < exceptionTable.length; i++) {
int startpc = exceptionTable[i].getStartPC();
int endpc = exceptionTable[i].getEndPC();
int handlerpc = exceptionTable[i].getHandlerPC();
- if (startpc >= endpc){
- throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has its start_pc ('"+startpc+"') not smaller than its end_pc ('"+endpc+"').");
+ if (startpc >= endpc) {
+ throw new ClassConstraintException("Code attribute '" + code + "' has an exception_table entry '"
+ + exceptionTable[i] + "' that has its start_pc ('" + startpc + "') not smaller than its end_pc ('" + endpc
+ + "').");
}
- if (!contains(instructionPositions, startpc)){
- throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its start_pc ('"+startpc+"').");
+ if (!contains(instructionPositions, startpc)) {
+ throw new ClassConstraintException("Code attribute '" + code + "' has an exception_table entry '"
+ + exceptionTable[i] + "' that has a non-existant bytecode offset as its start_pc ('" + startpc + "').");
}
- if ( (!contains(instructionPositions, endpc)) && (endpc != codeLength)){
- throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its end_pc ('"+startpc+"') [that is also not equal to code_length ('"+codeLength+"')].");
+ if (!contains(instructionPositions, endpc) && endpc != codeLength) {
+ throw new ClassConstraintException("Code attribute '" + code + "' has an exception_table entry '"
+ + exceptionTable[i] + "' that has a non-existant bytecode offset as its end_pc ('" + startpc
+ + "') [that is also not equal to code_length ('" + codeLength + "')].");
}
- if (!contains(instructionPositions, handlerpc)){
- throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its handler_pc ('"+handlerpc+"').");
+ if (!contains(instructionPositions, handlerpc)) {
+ throw new ClassConstraintException("Code attribute '" + code + "' has an exception_table entry '"
+ + exceptionTable[i] + "' that has a non-existant bytecode offset as its handler_pc ('" + handlerpc + "').");
}
}
}
/**
- * These are the checks if constraints are satisfied which are described in the
- * Java Virtual Machine Specification, Second Edition as Static Constraints on
- * the instructions of Java Virtual Machine Code (chapter 4.8.1).
- *
+ * These are the checks if constraints are satisfied which are described in the Java Virtual Machine Specification, Second
+ * Edition as Static Constraints on the instructions of Java Virtual Machine Code (chapter 4.8.1).
+ *
* @throws StaticCodeConstraintException if the verification fails.
*/
- private void pass3StaticInstructionChecks(){
-
+ private void pass3StaticInstructionChecks() {
+
// Code array must not be empty:
// Enforced in pass 2 (also stated in the static constraints of the Code
// array in vmspec2), together with pass 1 (reading code_length bytes and
// interpreting them as code[]). So this must not be checked again here.
- if (! (code.getCode().length < 65536)){// contradicts vmspec2 page 152 ("Limitations"), but is on page 134.
- throw new StaticCodeInstructionConstraintException("Code array in code attribute '"+code+"' too big: must be smaller than 65536 bytes.");
+ if (!(code.getCode().length < 65536)) {// contradicts vmspec2 page 152 ("Limitations"), but is on page 134.
+ throw new StaticCodeInstructionConstraintException("Code array in code attribute '" + code
+ + "' too big: must be smaller than 65536 bytes.");
}
// First opcode at offset 0: okay, that's clear. Nothing to do.
-
+
// Only instances of the instructions documented in Section 6.4 may appear in
// the code array.
-
+
// For BCEL's sake, we cannot handle WIDE stuff, but hopefully BCEL does its job right :)
-
+
// The last byte of the last instruction in the code array must be the byte at index
// code_length-1 : See the do_verify() comments. We actually don't iterate through the
// byte array, but use an InstructionList so we cannot check for this. But BCEL does
// things right, so it's implicitly okay.
-
+
// TODO: Check how BCEL handles (and will handle) instructions like IMPDEP1, IMPDEP2,
- // BREAKPOINT... that BCEL knows about but which are illegal anyway.
- // We currently go the safe way here.
+ // BREAKPOINT... that BCEL knows about but which are illegal anyway.
+ // We currently go the safe way here.
InstructionHandle ih = instructionList.getStart();
- while (ih != null){
+ while (ih != null) {
Instruction i = ih.getInstruction();
- if (i.getOpcode()==Constants.IMPDEP1){
- throw new StaticCodeInstructionConstraintException("IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
+ if (i.getOpcode() == Constants.IMPDEP1) {
+ throw new StaticCodeInstructionConstraintException(
+ "IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
}
- if (i.getOpcode()==Constants.IMPDEP2){
- throw new StaticCodeInstructionConstraintException("IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
+ if (i.getOpcode() == Constants.IMPDEP2) {
+ throw new StaticCodeInstructionConstraintException(
+ "IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
}
- if (i.getOpcode()==Constants.BREAKPOINT){
- throw new StaticCodeInstructionConstraintException("BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM use!");
+ if (i.getOpcode() == Constants.BREAKPOINT) {
+ throw new StaticCodeInstructionConstraintException(
+ "BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM use!");
}
ih = ih.getNext();
}
-
+
// The original verifier seems to do this check here, too.
// An unreachable last instruction may also not fall through the
// end of the code, which is stupid -- but with the original
// verifier's subroutine semantics one cannot predict reachability.
Instruction last = instructionList.getEnd().getInstruction();
- if (! ((last.isReturnInstruction()) ||
- (last instanceof RET) ||
- (last.getOpcode()==Constants.GOTO || last.getOpcode()==Constants.GOTO_W) ||
- (last.getOpcode()==Constants.ATHROW))) // JSR / JSR_W would possibly RETurn and then fall off the code!
- throw new StaticCodeInstructionConstraintException("Execution must not fall off the bottom of the code array. This constraint is enforced statically as some existing verifiers do - so it may be a false alarm if the last instruction is not reachable.");
+ if (!(last.isReturnInstruction() || last instanceof RET || last.getOpcode() == Constants.GOTO
+ || last.getOpcode() == Constants.GOTO_W || last.getOpcode() == Constants.ATHROW)) {
+ throw new StaticCodeInstructionConstraintException(
+ "Execution must not fall off the bottom of the code array. This constraint is enforced statically as some existing verifiers do - so it may be a false alarm if the last instruction is not reachable.");
+ }
}
/**
- * These are the checks for the satisfaction of constraints which are described in the
- * Java Virtual Machine Specification, Second Edition as Static Constraints on
- * the operands of instructions of Java Virtual Machine Code (chapter 4.8.1).
- * BCEL parses the code array to create an InstructionList and therefore has to check
- * some of these constraints. Additional checks are also implemented here.
- *
+ * These are the checks for the satisfaction of constraints which are described in the Java Virtual Machine Specification,
+ * Second Edition as Static Constraints on the operands of instructions of Java Virtual Machine Code (chapter 4.8.1). BCEL
+ * parses the code array to create an InstructionList and therefore has to check some of these constraints. Additional checks
+ * are also implemented here.
+ *
* @throws StaticCodeConstraintException if the verification fails.
*/
- private void pass3StaticInstructionOperandsChecks(){
+ private void pass3StaticInstructionOperandsChecks() {
// When building up the InstructionList, BCEL has already done all those checks
// mentioned in The Java Virtual Machine Specification, Second Edition, as
// "static constraints on the operands of instructions in the code array".
// TODO: see the do_verify() comments. Maybe we should really work on the
- // byte array first to give more comprehensive messages.
+ // byte array first to give more comprehensive messages.
// TODO: Review Exception API, possibly build in some "offending instruction" thing
- // when we're ready to insulate the offending instruction by doing the
- // above thing.
+ // when we're ready to insulate the offending instruction by doing the
+ // above thing.
// TODO: Implement as much as possible here. BCEL does _not_ check everything.
ConstantPool cpg = new ConstantPool(Repository.lookupClass(myOwner.getClassName()).getConstantPool().getConstantPool());
InstOperandConstraintVisitor v = new InstOperandConstraintVisitor(cpg);
-
+
// Checks for the things BCEL does _not_ handle itself.
InstructionHandle ih = instructionList.getStart();
- while (ih != null){
+ while (ih != null) {
Instruction i = ih.getInstruction();
-
+
// An "own" constraint, due to JustIce's new definition of what "subroutine" means.
- if (i.isJsrInstruction()){
+ if (i.isJsrInstruction()) {
InstructionHandle target = ((InstructionBranch) i).getTarget();
- if (target == instructionList.getStart()){
- throw new StaticCodeInstructionOperandConstraintException("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may have a top-level instruction (such as the very first instruction, which is targeted by instruction '"+ih+"' as its target.");
+ if (target == instructionList.getStart()) {
+ throw new StaticCodeInstructionOperandConstraintException(
+ "Due to JustIce's clear definition of subroutines, no JSR or JSR_W may have a top-level instruction (such as the very first instruction, which is targeted by instruction '"
+ + ih + "' as its target.");
}
- if (!(target.getInstruction().isASTORE())){
- throw new StaticCodeInstructionOperandConstraintException("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may target anything else than an ASTORE instruction. Instruction '"+ih+"' targets '"+target+"'.");
+ if (!target.getInstruction().isASTORE()) {
+ throw new StaticCodeInstructionOperandConstraintException(
+ "Due to JustIce's clear definition of subroutines, no JSR or JSR_W may target anything else than an ASTORE instruction. Instruction '"
+ + ih + "' targets '" + target + "'.");
}
}
-
+
// vmspec2, page 134-137
- ih.accept(v);
-
+ InstructionWalker.accept(ih.getInstruction(), v);
+
ih = ih.getNext();
}
}
-
+
/** A small utility method returning if a given int i is in the given int[] ints. */
- private static boolean contains(int[] ints, int i){
- for (int j=0; j<ints.length; j++){
- if (ints[j]==i) return true;
+ private static boolean contains(int[] ints, int i) {
+ for (int j = 0; j < ints.length; j++) {
+ if (ints[j] == i) {
+ return true;
+ }
}
return false;
}
/** Returns the method number as supplied when instantiating. */
- public int getMethodNo(){
+ public int getMethodNo() {
return method_no;
}
/**
- * This visitor class does the actual checking for the instruction
- * operand's constraints.
+ * This visitor class does the actual checking for the instruction operand's constraints.
*/
- private class InstOperandConstraintVisitor extends org.aspectj.apache.bcel.verifier.EmptyInstVisitor{
+ private class InstOperandConstraintVisitor extends org.aspectj.apache.bcel.verifier.EmptyInstVisitor {
/** The ConstantPoolGen instance this Visitor operates on. */
- private ConstantPool cpg;
+ private final ConstantPool cpg;
/** The only Constructor. */
- InstOperandConstraintVisitor(ConstantPool cpg){
+ InstOperandConstraintVisitor(ConstantPool cpg) {
this.cpg = cpg;
}
/**
- * Utility method to return the max_locals value of the method verified
- * by the surrounding Pass3aVerifier instance.
+ * Utility method to return the max_locals value of the method verified by the surrounding Pass3aVerifier instance.
*/
- private int max_locals(){
+ private int max_locals() {
return Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getCode().getMaxLocals();
}
* A utility method to always raise an exeption.
*/
private void constraintViolated(Instruction i, String message) {
- throw new StaticCodeInstructionOperandConstraintException("Instruction "+i+" constraint violated: "+message);
+ throw new StaticCodeInstructionOperandConstraintException("Instruction " + i + " constraint violated: " + message);
}
/**
- * A utility method to raise an exception if the index is not
- * a valid constant pool index.
+ * A utility method to raise an exception if the index is not a valid constant pool index.
*/
- private void indexValid(Instruction i, int idx){
- if (idx < 0 || idx >= cpg.getSize()){
- constraintViolated(i, "Illegal constant pool index '"+idx+"'.");
+ private void indexValid(Instruction i, int idx) {
+ if (idx < 0 || idx >= cpg.getSize()) {
+ constraintViolated(i, "Illegal constant pool index '" + idx + "'.");
}
}
- ///////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////
// The Java Virtual Machine Specification, pages 134-137 //
- ///////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////
/**
- * Assures the generic preconditions of a LoadClass instance.
- * The referenced class is loaded and pass2-verified.
+ * Assures the generic preconditions of a LoadClass instance. The referenced class is loaded and pass2-verified.
*/
- public void visitLoadClass(Instruction o){
+ public void visitLoadClass(Instruction o) {
ObjectType t = o.getLoadClassType(cpg);
- if (t != null){// null means "no class is loaded"
+ if (t != null) {// null means "no class is loaded"
Verifier v = VerifierFactory.getVerifier(t.getClassName());
VerificationResult vr = v.doPass1();
- if (vr.getStatus() != VerificationResult.VERIFIED_OK){
- constraintViolated((Instruction) o, "Class '"+o.getLoadClassType(cpg).getClassName()+"' is referenced, but cannot be loaded: '"+vr+"'.");
+ if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
+ constraintViolated(o, "Class '" + o.getLoadClassType(cpg).getClassName()
+ + "' is referenced, but cannot be loaded: '" + vr + "'.");
}
}
}
-
+
// The target of each jump and branch instruction [...] must be the opcode [...]
// BCEL _DOES_ handle this.
// tableswitch: BCEL will do it, supposedly.
-
+
// lookupswitch: BCEL will do it, supposedly.
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
// LDC and LDC_W (LDC_W is a subclass of LDC in BCEL's model)
- public void visitLDC(Instruction o){
+ public void visitLDC(Instruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! ( (c instanceof ConstantInteger) ||
- (c instanceof ConstantFloat) ||
- (c instanceof ConstantString) ) ){
- constraintViolated(o, "Operand of LDC or LDC_W must be one of CONSTANT_Integer, CONSTANT_Float or CONSTANT_String, but is '"+c+"'.");
+ if (!(c instanceof ConstantInteger || c instanceof ConstantFloat || c instanceof ConstantString)) {
+ constraintViolated(o,
+ "Operand of LDC or LDC_W must be one of CONSTANT_Integer, CONSTANT_Float or CONSTANT_String, but is '" + c
+ + "'.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
// LDC2_W
- public void visitLDC2_W(Instruction o){
+ public void visitLDC2_W(Instruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! ( (c instanceof ConstantLong) ||
- (c instanceof ConstantDouble) ) ){
- constraintViolated(o, "Operand of LDC2_W must be CONSTANT_Long or CONSTANT_Double, but is '"+c+"'.");
- }
- try{
- indexValid(o, o.getIndex()+1);
+ if (!(c instanceof ConstantLong || c instanceof ConstantDouble)) {
+ constraintViolated(o, "Operand of LDC2_W must be CONSTANT_Long or CONSTANT_Double, but is '" + c + "'.");
}
- catch(StaticCodeInstructionOperandConstraintException e){
+ try {
+ indexValid(o, o.getIndex() + 1);
+ } catch (StaticCodeInstructionOperandConstraintException e) {
throw new AssertionViolatedException("OOPS: Does not BCEL handle that? LDC2_W operand has a problem.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- //getfield, putfield, getstatic, putstatic
- public void visitFieldInstruction(FieldInstruction o){
+ // getfield, putfield, getstatic, putstatic
+ public void visitFieldInstruction(FieldInstruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantFieldref)){
- constraintViolated(o, "Indexing a constant that's not a CONSTANT_Fieldref but a '"+c+"'.");
+ if (!(c instanceof ConstantFieldref)) {
+ constraintViolated(o, "Indexing a constant that's not a CONSTANT_Fieldref but a '" + c + "'.");
}
-
+
String field_name = o.getFieldName(cpg);
-
+
JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName());
Field[] fields = jc.getFields();
Field f = null;
- for (int i=0; i<fields.length; i++){
- if (fields[i].getName().equals(field_name)){
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals(field_name)) {
f = fields[i];
break;
}
}
- if (f == null){
+ if (f == null) {
/* TODO: also look up if the field is inherited! */
- constraintViolated(o, "Referenced field '"+field_name+"' does not exist in class '"+jc.getClassName()+"'.");
- }
- else{
- /* TODO: Check if assignment compatibility is sufficient.
- What does Sun do? */
+ constraintViolated(o, "Referenced field '" + field_name + "' does not exist in class '" + jc.getClassName() + "'.");
+ } else {
+ /*
+ * TODO: Check if assignment compatibility is sufficient. What does Sun do?
+ */
Type f_type = Type.getType(f.getSignature());
Type o_type = o.getType(cpg);
-
- /* TODO: Is there a way to make BCEL tell us if a field
- has a void method's signature, i.e. "()I" instead of "I"? */
-
- if (! f_type.equals(o_type)){
- constraintViolated(o, "Referenced field '"+field_name+"' has type '"+f_type+"' instead of '"+o_type+"' as expected.");
+
+ /*
+ * TODO: Is there a way to make BCEL tell us if a field has a void method's signature, i.e. "()I" instead of "I"?
+ */
+
+ if (!f_type.equals(o_type)) {
+ constraintViolated(o, "Referenced field '" + field_name + "' has type '" + f_type + "' instead of '" + o_type
+ + "' as expected.");
}
/* TODO: Check for access modifiers here. */
}
- }
+ }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitInvokeInstruction(InvokeInstruction o){
+ public void visitInvokeInstruction(InvokeInstruction o) {
indexValid(o, o.getIndex());
- if ( (o.getOpcode()==Constants.INVOKEVIRTUAL) ||
- (o.getOpcode()==Constants.INVOKESPECIAL) ||
- (o.getOpcode()==Constants.INVOKESTATIC) ){
+ if (o.getOpcode() == Constants.INVOKEVIRTUAL || o.getOpcode() == Constants.INVOKESPECIAL
+ || o.getOpcode() == Constants.INVOKESTATIC) {
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantMethodref)){
- constraintViolated(o, "Indexing a constant that's not a CONSTANT_Methodref but a '"+c+"'.");
- }
- else{
+ if (!(c instanceof ConstantMethodref)) {
+ constraintViolated(o, "Indexing a constant that's not a CONSTANT_Methodref but a '" + c + "'.");
+ } else {
// Constants are okay due to pass2.
- ConstantNameAndType cnat = (ConstantNameAndType) (cpg.getConstant(((ConstantMethodref) c).getNameAndTypeIndex()));
- ConstantUtf8 cutf8 = (ConstantUtf8) (cpg.getConstant(cnat.getNameIndex()));
- if (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME) && (!(o.getOpcode()==Constants.INVOKESPECIAL)) ){
+ ConstantNameAndType cnat = (ConstantNameAndType) cpg.getConstant(((ConstantMethodref) c).getNameAndTypeIndex());
+ ConstantUtf8 cutf8 = (ConstantUtf8) cpg.getConstant(cnat.getNameIndex());
+ if (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME) && !(o.getOpcode() == Constants.INVOKESPECIAL)) {
constraintViolated(o, "Only INVOKESPECIAL is allowed to invoke instance initialization methods.");
}
- if ( (! (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME)) ) && (cutf8.getBytes().startsWith("<")) ){
- constraintViolated(o, "No method with a name beginning with '<' other than the instance initialization methods may be called by the method invocation instructions.");
+ if (!cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME) && cutf8.getBytes().startsWith("<")) {
+ constraintViolated(
+ o,
+ "No method with a name beginning with '<' other than the instance initialization methods may be called by the method invocation instructions.");
}
}
- }
- else{ //if (o instanceof INVOKEINTERFACE){
+ } else { // if (o instanceof INVOKEINTERFACE){
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantInterfaceMethodref)){
- constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref but a '"+c+"'.");
+ if (!(c instanceof ConstantInterfaceMethodref)) {
+ constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref but a '" + c + "'.");
}
// TODO: From time to time check if BCEL allows to detect if the
// 'count' operand is consistent with the information in the
// CONSTANT_InterfaceMethodref and if the last operand is zero.
// By now, BCEL hides those two operands because they're superfluous.
-
+
// Invoked method must not be <init> or <clinit>
- ConstantNameAndType cnat = (ConstantNameAndType) (cpg.getConstant(((ConstantInterfaceMethodref)c).getNameAndTypeIndex()));
- String name = ((ConstantUtf8) (cpg.getConstant(cnat.getNameIndex()))).getBytes();
- if (name.equals(Constants.CONSTRUCTOR_NAME)){
- constraintViolated(o, "Method to invoke must not be '"+Constants.CONSTRUCTOR_NAME+"'.");
+ ConstantNameAndType cnat = (ConstantNameAndType) cpg.getConstant(((ConstantInterfaceMethodref) c)
+ .getNameAndTypeIndex());
+ String name = ((ConstantUtf8) cpg.getConstant(cnat.getNameIndex())).getBytes();
+ if (name.equals(Constants.CONSTRUCTOR_NAME)) {
+ constraintViolated(o, "Method to invoke must not be '" + Constants.CONSTRUCTOR_NAME + "'.");
}
- if (name.equals(Constants.STATIC_INITIALIZER_NAME)){
- constraintViolated(o, "Method to invoke must not be '"+Constants.STATIC_INITIALIZER_NAME+"'.");
+ if (name.equals(Constants.STATIC_INITIALIZER_NAME)) {
+ constraintViolated(o, "Method to invoke must not be '" + Constants.STATIC_INITIALIZER_NAME + "'.");
}
}
-
+
// The LoadClassType is the method-declaring class, so we have to check the other types.
-
+
Type t = o.getReturnType(cpg);
- if (t instanceof ArrayType){
+ if (t instanceof ArrayType) {
t = ((ArrayType) t).getBasicType();
}
- if (t instanceof ObjectType){
+ if (t instanceof ObjectType) {
Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName());
VerificationResult vr = v.doPass2();
- if (vr.getStatus() != VerificationResult.VERIFIED_OK){
- constraintViolated(o, "Return type class/interface could not be verified successfully: '"+vr.getMessage()+"'.");
+ if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
+ constraintViolated(o, "Return type class/interface could not be verified successfully: '" + vr.getMessage()
+ + "'.");
}
}
-
+
Type[] ts = o.getArgumentTypes(cpg);
- for (int i=0; i<ts.length; i++){
+ for (int i = 0; i < ts.length; i++) {
t = ts[i];
- if (t instanceof ArrayType){
+ if (t instanceof ArrayType) {
t = ((ArrayType) t).getBasicType();
}
- if (t instanceof ObjectType){
+ if (t instanceof ObjectType) {
Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName());
VerificationResult vr = v.doPass2();
- if (vr.getStatus() != VerificationResult.VERIFIED_OK){
- constraintViolated(o, "Argument type class/interface could not be verified successfully: '"+vr.getMessage()+"'.");
+ if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
+ constraintViolated(o, "Argument type class/interface could not be verified successfully: '"
+ + vr.getMessage() + "'.");
}
}
}
-
+
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitINSTANCEOF(Instruction o){
+ public void visitINSTANCEOF(Instruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantClass)){
- constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'.");
+ if (!(c instanceof ConstantClass)) {
+ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '" + c + "'.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitCHECKCAST(Instruction o){
+ public void visitCHECKCAST(Instruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantClass)){
- constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'.");
+ if (!(c instanceof ConstantClass)) {
+ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '" + c + "'.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitNEW(Instruction o){
+ public void visitNEW(Instruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantClass)){
- constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'.");
- }
- else{
- ConstantUtf8 cutf8 = (ConstantUtf8) (cpg.getConstant( ((ConstantClass) c).getNameIndex() ));
- Type t = Type.getType("L"+cutf8.getBytes()+";");
- if (t instanceof ArrayType){
+ if (!(c instanceof ConstantClass)) {
+ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '" + c + "'.");
+ } else {
+ ConstantUtf8 cutf8 = (ConstantUtf8) cpg.getConstant(((ConstantClass) c).getNameIndex());
+ Type t = Type.getType("L" + cutf8.getBytes() + ";");
+ if (t instanceof ArrayType) {
constraintViolated(o, "NEW must not be used to create an array.");
}
}
-
+
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitMULTIANEWARRAY(MULTIANEWARRAY o){
+ public void visitMULTIANEWARRAY(MULTIANEWARRAY o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantClass)){
- constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'.");
+ if (!(c instanceof ConstantClass)) {
+ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '" + c + "'.");
}
int dimensions2create = o.getDimensions();
- if (dimensions2create < 1){
+ if (dimensions2create < 1) {
constraintViolated(o, "Number of dimensions to create must be greater than zero.");
}
Type t = o.getType(cpg);
- if (t instanceof ArrayType){
+ if (t instanceof ArrayType) {
int dimensions = ((ArrayType) t).getDimensions();
- if (dimensions < dimensions2create){
- constraintViolated(o, "Not allowed to create array with more dimensions ('+dimensions2create+') than the one referenced by the CONSTANT_Class '"+t+"'.");
+ if (dimensions < dimensions2create) {
+ constraintViolated(o,
+ "Not allowed to create array with more dimensions ('+dimensions2create+') than the one referenced by the CONSTANT_Class '"
+ + t + "'.");
}
- }
- else{
- constraintViolated(o, "Expecting a CONSTANT_Class referencing an array type. [Constraint not found in The Java Virtual Machine Specification, Second Edition, 4.8.1]");
+ } else {
+ constraintViolated(
+ o,
+ "Expecting a CONSTANT_Class referencing an array type. [Constraint not found in The Java Virtual Machine Specification, Second Edition, 4.8.1]");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitANEWARRAY(Instruction o){
+ public void visitANEWARRAY(Instruction o) {
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
- if (! (c instanceof ConstantClass)){
- constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'.");
+ if (!(c instanceof ConstantClass)) {
+ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '" + c + "'.");
}
Type t = o.getType(cpg);
- if (t instanceof ArrayType){
+ if (t instanceof ArrayType) {
int dimensions = ((ArrayType) t).getDimensions();
- if (dimensions >= 255){
+ if (dimensions >= 255) {
constraintViolated(o, "Not allowed to create an array with more than 255 dimensions.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitNEWARRAY(Instruction o){
- byte t = ((InstructionByte)o).getTypecode();
- if (! ( (t == Constants.T_BOOLEAN) ||
- (t == Constants.T_CHAR) ||
- (t == Constants.T_FLOAT) ||
- (t == Constants.T_DOUBLE) ||
- (t == Constants.T_BYTE) ||
- (t == Constants.T_SHORT) ||
- (t == Constants.T_INT) ||
- (t == Constants.T_LONG) ) ){
+ public void visitNEWARRAY(Instruction o) {
+ byte t = ((InstructionByte) o).getTypecode();
+ if (!(t == Constants.T_BOOLEAN || t == Constants.T_CHAR || t == Constants.T_FLOAT || t == Constants.T_DOUBLE
+ || t == Constants.T_BYTE || t == Constants.T_SHORT || t == Constants.T_INT || t == Constants.T_LONG)) {
constraintViolated(o, "Illegal type code '+t+' for 'atype' operand.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitILOAD(Instruction o){
+ public void visitILOAD(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitFLOAD(Instruction o){
+ public void visitFLOAD(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitALOAD(Instruction o){
+ public void visitALOAD(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitISTORE(Instruction o){
+ public void visitISTORE(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitFSTORE(Instruction o){
+ public void visitFSTORE(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitASTORE(Instruction o){
+ public void visitASTORE(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitIINC(IINC o){
+ public void visitIINC(IINC o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitRET(RET o){
+ public void visitRET(RET o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative.");
- }
- else{
- int maxminus1 = max_locals()-1;
- if (idx > maxminus1){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
+ if (idx < 0) {
+ constraintViolated(o, "Index '" + idx + "' must be non-negative.");
+ } else {
+ int maxminus1 = max_locals() - 1;
+ if (idx > maxminus1) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-1 '" + maxminus1 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitLLOAD(Instruction o){
+ public void visitLLOAD(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
- }
- else{
- int maxminus2 = max_locals()-2;
- if (idx > maxminus2){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
+ if (idx < 0) {
+ constraintViolated(
+ o,
+ "Index '"
+ + idx
+ + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
+ } else {
+ int maxminus2 = max_locals() - 2;
+ if (idx > maxminus2) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-2 '" + maxminus2 + "'.");
}
}
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitDLOAD(Instruction o){
+ public void visitDLOAD(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
- }
- else{
- int maxminus2 = max_locals()-2;
- if (idx > maxminus2){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
+ if (idx < 0) {
+ constraintViolated(
+ o,
+ "Index '"
+ + idx
+ + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
+ } else {
+ int maxminus2 = max_locals() - 2;
+ if (idx > maxminus2) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-2 '" + maxminus2 + "'.");
}
}
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitLSTORE(Instruction o){
+ public void visitLSTORE(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
- }
- else{
- int maxminus2 = max_locals()-2;
- if (idx > maxminus2){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
+ if (idx < 0) {
+ constraintViolated(
+ o,
+ "Index '"
+ + idx
+ + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
+ } else {
+ int maxminus2 = max_locals() - 2;
+ if (idx > maxminus2) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-2 '" + maxminus2 + "'.");
}
}
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitDSTORE(Instruction o){
+ public void visitDSTORE(Instruction o) {
int idx = o.getIndex();
- if (idx < 0){
- constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
- }
- else{
- int maxminus2 = max_locals()-2;
- if (idx > maxminus2){
- constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
+ if (idx < 0) {
+ constraintViolated(
+ o,
+ "Index '"
+ + idx
+ + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
+ } else {
+ int maxminus2 = max_locals() - 2;
+ if (idx > maxminus2) {
+ constraintViolated(o, "Index '" + idx + "' must not be greater than max_locals-2 '" + maxminus2 + "'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitLOOKUPSWITCH(LOOKUPSWITCH o){
+ public void visitLOOKUPSWITCH(LOOKUPSWITCH o) {
int[] matchs = o.getMatchs();
int max = Integer.MIN_VALUE;
- for (int i=0; i<matchs.length; i++){
- if (matchs[i] == max && i != 0){
- constraintViolated(o, "Match '"+matchs[i]+"' occurs more than once.");
+ for (int i = 0; i < matchs.length; i++) {
+ if (matchs[i] == max && i != 0) {
+ constraintViolated(o, "Match '" + matchs[i] + "' occurs more than once.");
}
- if (matchs[i] < max){
+ if (matchs[i] < max) {
constraintViolated(o, "Lookup table must be sorted but isn't.");
- }
- else{
+ } else {
max = matchs[i];
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitTABLESWITCH(TABLESWITCH o){
+ public void visitTABLESWITCH(TABLESWITCH o) {
// "high" must be >= "low". We cannot check this, as BCEL hides
// it from us.
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitPUTSTATIC(FieldInstruction o){
+ public void visitPUTSTATIC(FieldInstruction o) {
String field_name = o.getFieldName(cpg);
JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName());
Field[] fields = jc.getFields();
Field f = null;
- for (int i=0; i<fields.length; i++){
- if (fields[i].getName().equals(field_name)){
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals(field_name)) {
f = fields[i];
break;
}
}
- if (f == null){
+ if (f == null) {
throw new AssertionViolatedException("Field not found?!?");
}
- if (f.isFinal()){
- if (!(myOwner.getClassName().equals(o.getClassType(cpg).getClassName()))){
- constraintViolated(o, "Referenced field '"+f+"' is final and must therefore be declared in the current class '"+myOwner.getClassName()+"' which is not the case: it is declared in '"+o.getClassType(cpg).getClassName()+"'.");
+ if (f.isFinal()) {
+ if (!myOwner.getClassName().equals(o.getClassType(cpg).getClassName())) {
+ constraintViolated(o, "Referenced field '" + f
+ + "' is final and must therefore be declared in the current class '" + myOwner.getClassName()
+ + "' which is not the case: it is declared in '" + o.getClassType(cpg).getClassName() + "'.");
}
}
- if (! (f.isStatic())){
- constraintViolated(o, "Referenced field '"+f+"' is not static which it should be.");
+ if (!f.isStatic()) {
+ constraintViolated(o, "Referenced field '" + f + "' is not static which it should be.");
}
String meth_name = Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getName();
// If it's an interface, it can be set only in <clinit>.
- if ((!(jc.isClass())) && (!(meth_name.equals(Constants.STATIC_INITIALIZER_NAME)))){
- constraintViolated(o, "Interface field '"+f+"' must be set in a '"+Constants.STATIC_INITIALIZER_NAME+"' method.");
+ if (!jc.isClass() && !meth_name.equals(Constants.STATIC_INITIALIZER_NAME)) {
+ constraintViolated(o, "Interface field '" + f + "' must be set in a '" + Constants.STATIC_INITIALIZER_NAME
+ + "' method.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitGETSTATIC(FieldInstruction o){
+ public void visitGETSTATIC(FieldInstruction o) {
String field_name = o.getFieldName(cpg);
JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName());
Field[] fields = jc.getFields();
Field f = null;
- for (int i=0; i<fields.length; i++){
- if (fields[i].getName().equals(field_name)){
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals(field_name)) {
f = fields[i];
break;
}
}
- if (f == null){
+ if (f == null) {
throw new AssertionViolatedException("Field not found?!?");
}
- if (! (f.isStatic())){
- constraintViolated(o, "Referenced field '"+f+"' is not static which it should be.");
+ if (!f.isStatic()) {
+ constraintViolated(o, "Referenced field '" + f + "' is not static which it should be.");
}
}
/* Checks if the constraints of operands of the said instruction(s) are satisfied. */
- //public void visitPUTFIELD(PUTFIELD o){
- // for performance reasons done in Pass 3b
- //}
-
+ // public void visitPUTFIELD(PUTFIELD o){
+ // for performance reasons done in Pass 3b
+ // }
/* Checks if the constraints of operands of the said instruction(s) are satisfied. */
- //public void visitGETFIELD(GETFIELD o){
- // for performance reasons done in Pass 3b
- //}
-
+ // public void visitGETFIELD(GETFIELD o){
+ // for performance reasons done in Pass 3b
+ // }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitINVOKEINTERFACE(INVOKEINTERFACE o){
+ public void visitINVOKEINTERFACE(INVOKEINTERFACE o) {
// INVOKEINTERFACE is a LoadClass; the Class where the referenced method is declared in,
// is therefore resolved/verified.
// INVOKEINTERFACE is an InvokeInstruction, the argument and return types are resolved/verified,
JavaClass jc = Repository.lookupClass(classname);
Method[] ms = jc.getMethods();
Method m = null;
- for (int i=0; i<ms.length; i++){
- if ( (ms[i].getName().equals(o.getMethodName(cpg))) &&
- (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) &&
- (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){
+ for (int i = 0; i < ms.length; i++) {
+ if (ms[i].getName().equals(o.getMethodName(cpg))
+ && Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))
+ && objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) {
m = ms[i];
break;
}
}
- if (m == null){
- constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superinterface, which the Java Virtual Machine Specification, Second Edition does not.");
+ if (m == null) {
+ constraintViolated(
+ o,
+ "Referenced method '"
+ + o.getMethodName(cpg)
+ + "' with expected signature not found in class '"
+ + jc.getClassName()
+ + "'. The native verfier does allow the method to be declared in some superinterface, which the Java Virtual Machine Specification, Second Edition does not.");
}
- if (jc.isClass()){
- constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is a class, but not an interface as expected.");
+ if (jc.isClass()) {
+ constraintViolated(o, "Referenced class '" + jc.getClassName() + "' is a class, but not an interface as expected.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitINVOKESPECIAL(InvokeInstruction o){
+ public void visitINVOKESPECIAL(InvokeInstruction o) {
// INVOKESPECIAL is a LoadClass; the Class where the referenced method is declared in,
// is therefore resolved/verified.
// INVOKESPECIAL is an InvokeInstruction, the argument and return types are resolved/verified,
JavaClass jc = Repository.lookupClass(classname);
Method[] ms = jc.getMethods();
Method m = null;
- for (int i=0; i<ms.length; i++){
- if ( (ms[i].getName().equals(o.getMethodName(cpg))) &&
- (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) &&
- (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){
+ for (int i = 0; i < ms.length; i++) {
+ if (ms[i].getName().equals(o.getMethodName(cpg))
+ && Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))
+ && objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) {
m = ms[i];
break;
}
}
- if (m == null){
- constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not.");
+ if (m == null) {
+ constraintViolated(
+ o,
+ "Referenced method '"
+ + o.getMethodName(cpg)
+ + "' with expected signature not found in class '"
+ + jc.getClassName()
+ + "'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not.");
}
-
+
JavaClass current = Repository.lookupClass(myOwner.getClassName());
- if (current.isSuper()){
-
- if ((Repository.instanceOf( current, jc )) && (!current.equals(jc))){
-
- if (! (o.getMethodName(cpg).equals(Constants.CONSTRUCTOR_NAME) )){
+ if (current.isSuper()) {
+
+ if (Repository.instanceOf(current, jc) && !current.equals(jc)) {
+
+ if (!o.getMethodName(cpg).equals(Constants.CONSTRUCTOR_NAME)) {
// Special lookup procedure for ACC_SUPER classes.
-
+
int supidx = -1;
-
+
Method meth = null;
- while (supidx != 0){
+ while (supidx != 0) {
supidx = current.getSuperclassNameIndex();
current = Repository.lookupClass(current.getSuperclassName());
-
+
Method[] meths = current.getMethods();
- for (int i=0; i<meths.length; i++){
- if ( (meths[i].getName().equals(o.getMethodName(cpg))) &&
- (Type.getReturnType(meths[i].getSignature()).equals(o.getReturnType(cpg))) &&
- (objarrayequals(Type.getArgumentTypes(meths[i].getSignature()), o.getArgumentTypes(cpg))) ){
+ for (int i = 0; i < meths.length; i++) {
+ if (meths[i].getName().equals(o.getMethodName(cpg))
+ && Type.getReturnType(meths[i].getSignature()).equals(o.getReturnType(cpg))
+ && objarrayequals(Type.getArgumentTypes(meths[i].getSignature()), o.getArgumentTypes(cpg))) {
meth = meths[i];
break;
}
}
- if (meth != null) break;
+ if (meth != null) {
+ break;
+ }
+ }
+ if (meth == null) {
+ constraintViolated(o, "ACC_SUPER special lookup procedure not successful: method '"
+ + o.getMethodName(cpg) + "' with proper signature not declared in superclass hierarchy.");
}
- if (meth == null){
- constraintViolated(o, "ACC_SUPER special lookup procedure not successful: method '"+o.getMethodName(cpg)+"' with proper signature not declared in superclass hierarchy.");
- }
}
}
}
-
-
+
}
-
+
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitINVOKESTATIC(InvokeInstruction o){
+ public void visitINVOKESTATIC(InvokeInstruction o) {
// INVOKESTATIC is a LoadClass; the Class where the referenced method is declared in,
// is therefore resolved/verified.
// INVOKESTATIC is an InvokeInstruction, the argument and return types are resolved/verified,
JavaClass jc = Repository.lookupClass(classname);
Method[] ms = jc.getMethods();
Method m = null;
- for (int i=0; i<ms.length; i++){
- if ( (ms[i].getName().equals(o.getMethodName(cpg))) &&
- (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) &&
- (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){
+ for (int i = 0; i < ms.length; i++) {
+ if (ms[i].getName().equals(o.getMethodName(cpg))
+ && Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))
+ && objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) {
m = ms[i];
break;
}
}
- if (m == null){
- constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verifier possibly allows the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not.");
+ if (m == null) {
+ constraintViolated(
+ o,
+ "Referenced method '"
+ + o.getMethodName(cpg)
+ + "' with expected signature not found in class '"
+ + jc.getClassName()
+ + "'. The native verifier possibly allows the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not.");
}
-
- if (! (m.isStatic())){ // implies it's not abstract, verified in pass 2.
- constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' has ACC_STATIC unset.");
+
+ if (!m.isStatic()) { // implies it's not abstract, verified in pass 2.
+ constraintViolated(o, "Referenced method '" + o.getMethodName(cpg) + "' has ACC_STATIC unset.");
}
-
- }
+ }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
- public void visitINVOKEVIRTUAL(InvokeInstruction o){
+ public void visitINVOKEVIRTUAL(InvokeInstruction o) {
// INVOKEVIRTUAL is a LoadClass; the Class where the referenced method is declared in,
// is therefore resolved/verified.
// INVOKEVIRTUAL is an InvokeInstruction, the argument and return types are resolved/verified,
JavaClass jc = Repository.lookupClass(classname);
Method[] ms = jc.getMethods();
Method m = null;
- for (int i=0; i<ms.length; i++){
- if ( (ms[i].getName().equals(o.getMethodName(cpg))) &&
- (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) &&
- (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){
+ for (int i = 0; i < ms.length; i++) {
+ if (ms[i].getName().equals(o.getMethodName(cpg))
+ && Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))
+ && objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) {
m = ms[i];
break;
}
}
- if (m == null){
- constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not.");
+ if (m == null) {
+ constraintViolated(
+ o,
+ "Referenced method '"
+ + o.getMethodName(cpg)
+ + "' with expected signature not found in class '"
+ + jc.getClassName()
+ + "'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not.");
}
- if (! (jc.isClass())){
- constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is an interface, but not a class as expected.");
+ if (!jc.isClass()) {
+ constraintViolated(o, "Referenced class '" + jc.getClassName() + "' is an interface, but not a class as expected.");
}
-
+
}
-
// WIDE stuff is BCEL-internal and cannot be checked here.
/**
- * A utility method like equals(Object) for arrays.
- * The equality of the elements is based on their equals(Object)
- * method instead of their object identity.
- */
- private boolean objarrayequals(Object[] o, Object[] p){
- if (o.length != p.length){
+ * A utility method like equals(Object) for arrays. The equality of the elements is based on their equals(Object) method
+ * instead of their object identity.
+ */
+ private boolean objarrayequals(Object[] o, Object[] p) {
+ if (o.length != p.length) {
return false;
}
-
- for (int i=0; i<o.length; i++){
- if (! (o[i].equals(p[i])) ){
+
+ for (int i = 0; i < o.length; i++) {
+ if (!o[i].equals(p[i])) {
return false;
}
}
-
+
return true;
}
import org.aspectj.apache.bcel.generic.InstructionSelect;
import org.aspectj.apache.bcel.generic.MethodGen;
import org.aspectj.apache.bcel.generic.RET;
+import org.aspectj.apache.bcel.verifier.InstructionWalker;
import org.aspectj.apache.bcel.verifier.exc.AssertionViolatedException;
import org.aspectj.apache.bcel.verifier.exc.StructuralCodeConstraintException;
/**
* This class represents a control flow graph of a method.
- *
- * @version $Id: ControlFlowGraph.java,v 1.2 2008/05/28 23:53:02 aclement Exp $
+ *
+ * @version $Id: ControlFlowGraph.java,v 1.3 2008/08/28 00:02:13 aclement Exp $
* @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
*/
-public class ControlFlowGraph{
+public class ControlFlowGraph {
/**
- * Objects of this class represent a node in a ControlFlowGraph.
- * These nodes are instructions, not basic blocks.
+ * Objects of this class represent a node in a ControlFlowGraph. These nodes are instructions, not basic blocks.
*/
- private class InstructionContextImpl implements InstructionContext{
+ private class InstructionContextImpl implements InstructionContext {
/**
- * The TAG field is here for external temporary flagging, such
- * as graph colouring.
- *
+ * The TAG field is here for external temporary flagging, such as graph colouring.
+ *
* @see #getTag()
* @see #setTag(int)
*/
/**
* The InstructionHandle this InstructionContext is wrapped around.
*/
- private InstructionHandle instruction;
+ private final InstructionHandle instruction;
/**
* The 'incoming' execution Frames.
*/
- private HashMap inFrames; // key: the last-executed JSR
+ private final HashMap inFrames; // key: the last-executed JSR
/**
* The 'outgoing' execution Frames.
*/
- private HashMap outFrames; // key: the last-executed JSR
+ private final HashMap outFrames; // key: the last-executed JSR
/**
- * The 'execution predecessors' - a list of type InstructionContext
- * of those instances that have been execute()d before in that order.
+ * The 'execution predecessors' - a list of type InstructionContext of those instances that have been execute()d before in
+ * that order.
*/
private ArrayList executionPredecessors = null; // Type: InstructionContext
-
+
/**
- * Creates an InstructionHandleImpl object from an InstructionHandle.
- * Creation of one per InstructionHandle suffices. Don't create more.
+ * Creates an InstructionHandleImpl object from an InstructionHandle. Creation of one per InstructionHandle suffices. Don't
+ * create more.
*/
- public InstructionContextImpl(InstructionHandle inst){
- if (inst == null) throw new AssertionViolatedException("Cannot instantiate InstructionContextImpl from NULL.");
-
+ public InstructionContextImpl(InstructionHandle inst) {
+ if (inst == null) {
+ throw new AssertionViolatedException("Cannot instantiate InstructionContextImpl from NULL.");
+ }
+
instruction = inst;
inFrames = new java.util.HashMap();
outFrames = new java.util.HashMap();
}
/* Satisfies InstructionContext.getTag(). */
- public int getTag(){
+ public int getTag() {
return TAG;
}
/* Satisfies InstructionContext.setTag(int). */
- public void setTag(int tag){
+ public void setTag(int tag) {
TAG = tag;
}
/**
* Returns the exception handlers of this instruction.
*/
- public ExceptionHandler[] getExceptionHandlers(){
+ public ExceptionHandler[] getExceptionHandlers() {
return exceptionhandlers.getExceptionHandlers(getInstruction());
}
/**
* Returns a clone of the "outgoing" frame situation with respect to the given ExecutionChain.
- */
- public Frame getOutFrame(ArrayList execChain){
+ */
+ public Frame getOutFrame(ArrayList execChain) {
executionPredecessors = execChain;
Frame org;
org = (Frame) outFrames.get(jsr);
- if (org == null){
- throw new AssertionViolatedException("outFrame not set! This:\n"+this+"\nExecutionChain: "+getExecutionChain()+"\nOutFrames: '"+outFrames+"'.");
+ if (org == null) {
+ throw new AssertionViolatedException("outFrame not set! This:\n" + this + "\nExecutionChain: "
+ + getExecutionChain() + "\nOutFrames: '" + outFrames + "'.");
}
return org.getClone();
}
/**
- * "Merges in" (vmspec2, page 146) the "incoming" frame situation;
- * executes the instructions symbolically
- * and therefore calculates the "outgoing" frame situation.
- * Returns: True iff the "incoming" frame situation changed after
- * merging with "inFrame".
- * The execPreds ArrayList must contain the InstructionContext
- * objects executed so far in the correct order. This is just
- * one execution path [out of many]. This is needed to correctly
- * "merge" in the special case of a RET's successor.
- * <B>The InstConstraintVisitor and ExecutionVisitor instances
- * must be set up correctly.</B>
- * @return true - if and only if the "outgoing" frame situation
- * changed from the one before execute()ing.
+ * "Merges in" (vmspec2, page 146) the "incoming" frame situation; executes the instructions symbolically and therefore
+ * calculates the "outgoing" frame situation. Returns: True iff the "incoming" frame situation changed after merging with
+ * "inFrame". The execPreds ArrayList must contain the InstructionContext objects executed so far in the correct order. This
+ * is just one execution path [out of many]. This is needed to correctly "merge" in the special case of a RET's successor.
+ * <B>The InstConstraintVisitor and ExecutionVisitor instances must be set up correctly.</B>
+ *
+ * @return true - if and only if the "outgoing" frame situation changed from the one before execute()ing.
*/
- public boolean execute(Frame inFrame, ArrayList execPreds, InstConstraintVisitor icv, ExecutionVisitor ev){
+ public boolean execute(Frame inFrame, ArrayList execPreds, InstConstraintVisitor icv, ExecutionVisitor ev) {
executionPredecessors = (ArrayList) execPreds.clone();
- //sanity check
- if ( (lastExecutionJSR() == null) && (subroutines.subroutineOf(getInstruction()) != subroutines.getTopLevel() ) ){
- throw new AssertionViolatedException("Huh?! Am I '"+this+"' part of a subroutine or not?");
+ // sanity check
+ if (lastExecutionJSR() == null && subroutines.subroutineOf(getInstruction()) != subroutines.getTopLevel()) {
+ throw new AssertionViolatedException("Huh?! Am I '" + this + "' part of a subroutine or not?");
}
- if ( (lastExecutionJSR() != null) && (subroutines.subroutineOf(getInstruction()) == subroutines.getTopLevel() ) ){
- throw new AssertionViolatedException("Huh?! Am I '"+this+"' part of a subroutine or not?");
+ if (lastExecutionJSR() != null && subroutines.subroutineOf(getInstruction()) == subroutines.getTopLevel()) {
+ throw new AssertionViolatedException("Huh?! Am I '" + this + "' part of a subroutine or not?");
}
Frame inF = (Frame) inFrames.get(lastExecutionJSR());
- if (inF == null){// no incoming frame was set, so set it.
+ if (inF == null) {// no incoming frame was set, so set it.
inFrames.put(lastExecutionJSR(), inFrame);
inF = inFrame;
- }
- else{// if there was an "old" inFrame
- if (inF.equals(inFrame)){ //shortcut: no need to merge equal frames.
+ } else {// if there was an "old" inFrame
+ if (inF.equals(inFrame)) { // shortcut: no need to merge equal frames.
return false;
}
- if (! mergeInFrames(inFrame)){
+ if (!mergeInFrames(inFrame)) {
return false;
}
}
-
+
// Now we're sure the inFrame has changed!
-
- // new inFrame is already merged in, see above.
+
+ // new inFrame is already merged in, see above.
Frame workingFrame = inF.getClone();
- try{
+ try {
// This verifies the InstructionConstraint for the current
// instruction, but does not modify the workingFrame object.
-//InstConstraintVisitor icv = InstConstraintVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
+ // InstConstraintVisitor icv =
+ // InstConstraintVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
icv.setFrame(workingFrame);
- getInstruction().accept(icv);
- }
- catch(StructuralCodeConstraintException ce){
- ce.extendMessage("","\nInstructionHandle: "+getInstruction()+"\n");
- ce.extendMessage("","\nExecution Frame:\n"+workingFrame);
+ InstructionWalker.accept(getInstruction().getInstruction(), icv);
+ } catch (StructuralCodeConstraintException ce) {
+ ce.extendMessage("", "\nInstructionHandle: " + getInstruction() + "\n");
+ ce.extendMessage("", "\nExecution Frame:\n" + workingFrame);
extendMessageWithFlow(ce);
throw ce;
}
// This executes the Instruction.
// Therefore the workingFrame object is modified.
-//ExecutionVisitor ev = ExecutionVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
+ // ExecutionVisitor ev = ExecutionVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
ev.setFrame(workingFrame);
- getInstruction().accept(ev);
- //getInstruction().accept(ExecutionVisitor.withFrame(workingFrame));
+ InstructionWalker.accept(getInstruction().getInstruction(), ev);
+ // getInstruction().accept(ExecutionVisitor.withFrame(workingFrame));
outFrames.put(lastExecutionJSR(), workingFrame);
- return true; // new inFrame was different from old inFrame so merging them
- // yielded a different this.inFrame.
+ return true; // new inFrame was different from old inFrame so merging them
+ // yielded a different this.inFrame.
}
/**
* Returns a simple String representation of this InstructionContext.
*/
- public String toString(){
- //TODO: Put information in the brackets, e.g.
- // Is this an ExceptionHandler? Is this a RET? Is this the start of
- // a subroutine?
- String ret = getInstruction().toString(false)+"\t[InstructionContext]";
+ public String toString() {
+ // TODO: Put information in the brackets, e.g.
+ // Is this an ExceptionHandler? Is this a RET? Is this the start of
+ // a subroutine?
+ String ret = getInstruction().toString(false) + "\t[InstructionContext]";
return ret;
}
/**
- * Does the actual merging (vmspec2, page 146).
- * Returns true IFF this.inFrame was changed in course of merging with inFrame.
+ * Does the actual merging (vmspec2, page 146). Returns true IFF this.inFrame was changed in course of merging with inFrame.
*/
- private boolean mergeInFrames(Frame inFrame){
+ private boolean mergeInFrames(Frame inFrame) {
// TODO: Can be performance-improved.
Frame inF = (Frame) inFrames.get(lastExecutionJSR());
OperandStack oldstack = inF.getStack().getClone();
LocalVariables oldlocals = inF.getLocals().getClone();
- try{
+ try {
inF.getStack().merge(inFrame.getStack());
inF.getLocals().merge(inFrame.getLocals());
- }
- catch (StructuralCodeConstraintException sce){
+ } catch (StructuralCodeConstraintException sce) {
extendMessageWithFlow(sce);
throw sce;
}
- if ( oldstack.equals(inF.getStack()) &&
- oldlocals.equals(inF.getLocals()) ){
+ if (oldstack.equals(inF.getStack()) && oldlocals.equals(inF.getLocals())) {
return false;
- }
- else{
+ } else {
return true;
}
}
/**
- * Returns the control flow execution chain. This is built
- * while execute(Frame, ArrayList)-ing the code represented
- * by the surrounding ControlFlowGraph.
+ * Returns the control flow execution chain. This is built while execute(Frame, ArrayList)-ing the code represented by the
+ * surrounding ControlFlowGraph.
*/
- private String getExecutionChain(){
+ private String getExecutionChain() {
String s = this.toString();
- for (int i=executionPredecessors.size()-1; i>=0; i--){
- s = executionPredecessors.get(i)+"\n" + s;
+ for (int i = executionPredecessors.size() - 1; i >= 0; i--) {
+ s = executionPredecessors.get(i) + "\n" + s;
}
return s;
}
-
/**
- * Extends the StructuralCodeConstraintException ("e") object with an at-the-end-extended message.
- * This extended message will then reflect the execution flow needed to get to the constraint
- * violation that triggered the throwing of the "e" object.
+ * Extends the StructuralCodeConstraintException ("e") object with an at-the-end-extended message. This extended message
+ * will then reflect the execution flow needed to get to the constraint violation that triggered the throwing of the "e"
+ * object.
*/
- private void extendMessageWithFlow(StructuralCodeConstraintException e){
+ private void extendMessageWithFlow(StructuralCodeConstraintException e) {
String s = "Execution flow:\n";
- e.extendMessage("", s+getExecutionChain());
+ e.extendMessage("", s + getExecutionChain());
}
/*
* Fulfils the contract of InstructionContext.getInstruction().
*/
- public InstructionHandle getInstruction(){
+ public InstructionHandle getInstruction() {
return instruction;
}
/**
- * Returns the InstructionContextImpl with an JSR/JSR_W
- * that was last in the ExecutionChain, without
- * a corresponding RET, i.e.
- * we were called by this one.
- * Returns null if we were called from the top level.
+ * Returns the InstructionContextImpl with an JSR/JSR_W that was last in the ExecutionChain, without a corresponding RET,
+ * i.e. we were called by this one. Returns null if we were called from the top level.
*/
- private InstructionContextImpl lastExecutionJSR(){
-
+ private InstructionContextImpl lastExecutionJSR() {
+
int size = executionPredecessors.size();
int retcount = 0;
-
- for (int i=size-1; i>=0; i--){
- InstructionContextImpl current = (InstructionContextImpl) (executionPredecessors.get(i));
+
+ for (int i = size - 1; i >= 0; i--) {
+ InstructionContextImpl current = (InstructionContextImpl) executionPredecessors.get(i);
Instruction currentlast = current.getInstruction().getInstruction();
- if (currentlast instanceof RET) retcount++;
- if (currentlast.isJsrInstruction()){
+ if (currentlast instanceof RET) {
+ retcount++;
+ }
+ if (currentlast.isJsrInstruction()) {
retcount--;
- if (retcount == -1) return current;
+ if (retcount == -1) {
+ return current;
+ }
}
}
return null;
}
/* Satisfies InstructionContext.getSuccessors(). */
- public InstructionContext[] getSuccessors(){
+ public InstructionContext[] getSuccessors() {
return contextsOf(_getSuccessors());
}
/**
- * A utility method that calculates the successors of a given InstructionHandle
- * That means, a RET does have successors as defined here.
- * A JsrInstruction has its target as its successor
- * (opposed to its physical successor) as defined here.
+ * A utility method that calculates the successors of a given InstructionHandle That means, a RET does have successors as
+ * defined here. A JsrInstruction has its target as its successor (opposed to its physical successor) as defined here.
*/
-// TODO: implement caching!
- private InstructionHandle[] _getSuccessors(){
+ // TODO: implement caching!
+ private InstructionHandle[] _getSuccessors() {
final InstructionHandle[] empty = new InstructionHandle[0];
final InstructionHandle[] single = new InstructionHandle[1];
final InstructionHandle[] pair = new InstructionHandle[2];
-
+
Instruction inst = getInstruction().getInstruction();
-
- if (inst instanceof RET){
+
+ if (inst instanceof RET) {
Subroutine s = subroutines.subroutineOf(getInstruction());
- if (s==null){ //return empty; // RET in dead code. "empty" would be the correct answer, but we know something about the surrounding project...
+ if (s == null) { // return empty; // RET in dead code. "empty" would be the correct answer, but we know something
+ // about the surrounding project...
throw new AssertionViolatedException("Asking for successors of a RET in dead code?!");
}
-//TODO: remove
-throw new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");
-/*
- InstructionHandle[] jsrs = s.getEnteringJsrInstructions();
- InstructionHandle[] ret = new InstructionHandle[jsrs.length];
- for (int i=0; i<jsrs.length; i++){
- ret[i] = jsrs[i].getNext();
- }
- return ret;
-*/
+ // TODO: remove
+ throw new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");
+ /*
+ * InstructionHandle[] jsrs = s.getEnteringJsrInstructions(); InstructionHandle[] ret = new
+ * InstructionHandle[jsrs.length]; for (int i=0; i<jsrs.length; i++){ ret[i] = jsrs[i].getNext(); } return ret;
+ */
}
-
+
// Terminates method normally.
if (inst.isReturnInstruction()) {
return empty;
}
-
+
// Terminates method abnormally, because JustIce mandates
// subroutines not to be protected by exception handlers.
- if (inst.getOpcode()==Constants.ATHROW){
+ if (inst.getOpcode() == Constants.ATHROW) {
return empty;
}
-
+
// See method comment.
- if (inst.isJsrInstruction()){
+ if (inst.isJsrInstruction()) {
single[0] = ((InstructionBranch) inst).getTarget();
return single;
}
- if (inst.getOpcode()==Constants.GOTO || inst.getOpcode()==Constants.GOTO_W){
+ if (inst.getOpcode() == Constants.GOTO || inst.getOpcode() == Constants.GOTO_W) {
single[0] = ((InstructionBranch) inst).getTarget();
return single;
}
- if (inst instanceof InstructionBranch){
- if (inst instanceof InstructionSelect){
+ if (inst instanceof InstructionBranch) {
+ if (inst instanceof InstructionSelect) {
// BCEL's getTargets() returns only the non-default targets,
// thanks to Eli Tilevich for reporting.
InstructionHandle[] matchTargets = ((InstructionSelect) inst).getTargets();
- InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
+ InstructionHandle[] ret = new InstructionHandle[matchTargets.length + 1];
ret[0] = ((InstructionSelect) inst).getTarget();
System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
return ret;
- }
- else{
+ } else {
pair[0] = getInstruction().getNext();
pair[1] = ((InstructionBranch) inst).getTarget();
return pair;
}
}
- // default case: Fall through.
+ // default case: Fall through.
single[0] = getInstruction().getNext();
return single;
}
private final ExceptionHandlers exceptionhandlers;
/** All InstructionContext instances of this ControlFlowGraph. */
- private Hashtable instructionContexts = new Hashtable(); //keys: InstructionHandle, values: InstructionContextImpl
+ private final Hashtable instructionContexts = new Hashtable(); // keys: InstructionHandle, values: InstructionContextImpl
- /**
+ /**
* A Control Flow Graph.
*/
- public ControlFlowGraph(MethodGen method_gen){
+ public ControlFlowGraph(MethodGen method_gen) {
subroutines = new Subroutines(method_gen);
exceptionhandlers = new ExceptionHandlers(method_gen);
InstructionHandle[] instructionhandles = method_gen.getInstructionList().getInstructionHandles();
- for (int i=0; i<instructionhandles.length; i++){
+ for (int i = 0; i < instructionhandles.length; i++) {
instructionContexts.put(instructionhandles[i], new InstructionContextImpl(instructionhandles[i]));
}
-
+
this.method_gen = method_gen;
}
/**
* Returns the InstructionContext of a given instruction.
*/
- public InstructionContext contextOf(InstructionHandle inst){
+ public InstructionContext contextOf(InstructionHandle inst) {
InstructionContext ic = (InstructionContext) instructionContexts.get(inst);
- if (ic == null){
+ if (ic == null) {
throw new AssertionViolatedException("InstructionContext requested for an InstructionHandle that's not known!");
}
return ic;
}
/**
- * Returns the InstructionContext[] of a given InstructionHandle[],
- * in a naturally ordered manner.
+ * Returns the InstructionContext[] of a given InstructionHandle[], in a naturally ordered manner.
*/
- public InstructionContext[] contextsOf(InstructionHandle[] insts){
+ public InstructionContext[] contextsOf(InstructionHandle[] insts) {
InstructionContext[] ret = new InstructionContext[insts.length];
- for (int i=0; i<insts.length; i++){
+ for (int i = 0; i < insts.length; i++) {
ret[i] = contextOf(insts[i]);
}
return ret;
}
/**
- * Returns an InstructionContext[] with all the InstructionContext instances
- * for the method whose control flow is represented by this ControlFlowGraph
- * <B>(NOT ORDERED!)</B>.
+ * Returns an InstructionContext[] with all the InstructionContext instances for the method whose control flow is represented by
+ * this ControlFlowGraph <B>(NOT ORDERED!)</B>.
*/
- public InstructionContext[] getInstructionContexts(){
+ public InstructionContext[] getInstructionContexts() {
InstructionContext[] ret = new InstructionContext[instructionContexts.values().size()];
return (InstructionContext[]) instructionContexts.values().toArray(ret);
}
/**
- * Returns true, if and only if the said instruction is not reachable; that means,
- * if it not part of this ControlFlowGraph.
+ * Returns true, if and only if the said instruction is not reachable; that means, if it not part of this ControlFlowGraph.
*/
- public boolean isDead(InstructionHandle i){
+ public boolean isDead(InstructionHandle i) {
return instructionContexts.containsKey(i);
- }
+ }
}
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.RET;
import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.apache.bcel.verifier.InstructionWalker;
/* ====================================================================
* The Apache Software License, Version 1.1
*/
/**
- * Factory creates il.append() statements, and sets instruction targets.
- * A helper class for BCELifier.
- *
+ * Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier.
+ *
* @see BCELifier
- * @version $Id: BCELFactory.java,v 1.3 2008/05/30 17:29:27 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
+ * @version $Id: BCELFactory.java,v 1.4 2008/08/28 00:02:14 aclement Exp $
+ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
class BCELFactory extends org.aspectj.apache.bcel.verifier.EmptyInstVisitor {
- private MethodGen _mg;
- private PrintWriter _out;
- private ConstantPool _cp;
-
- BCELFactory(MethodGen mg, PrintWriter out) {
- _mg = mg;
- _cp = mg.getConstantPool();
- _out = out;
- }
-
- private HashMap branch_map = new HashMap(); // Map<Instruction, InstructionHandle>
-
- public void start() {
- if(!_mg.isAbstract() && !_mg.isNative()) {
- for(InstructionHandle ih = _mg.getInstructionList().getStart();
- ih != null; ih = ih.getNext()) {
- Instruction i = ih.getInstruction();
-
- if(i instanceof InstructionBranch) {
- branch_map.put(i, ih); // memorize container
+ private final MethodGen _mg;
+ private final PrintWriter _out;
+ private final ConstantPool _cp;
+
+ BCELFactory(MethodGen mg, PrintWriter out) {
+ _mg = mg;
+ _cp = mg.getConstantPool();
+ _out = out;
+ }
+
+ private final HashMap branch_map = new HashMap(); // Map<Instruction, InstructionHandle>
+
+ public void start() {
+ if (!_mg.isAbstract() && !_mg.isNative()) {
+ for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih.getNext()) {
+ Instruction i = ih.getInstruction();
+
+ if (i instanceof InstructionBranch) {
+ branch_map.put(i, ih); // memorize container
+ }
+
+ if (ih.hasTargeters()) {
+ if (i instanceof InstructionBranch) {
+ _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
+ } else {
+ _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
+ }
+ } else {
+ _out.print(" ");
+ }
+
+ if (!visitInstruction(i)) {
+ InstructionWalker.accept(i, this);
+ }
+ }
+
+ updateBranchTargets();
+ updateExceptionHandlers();
+ }
+ }
+
+ private boolean visitInstruction(Instruction i) {
+ short opcode = i.getOpcode();
+
+ if (InstructionConstants.INSTRUCTIONS[opcode] != null && !i.isConstantInstruction() && !i.isReturnInstruction()) { // Handled
+ // below
+ _out.println("il.append(InstructionConstants." + i.getName().toUpperCase() + ");");
+ return true;
+ }
+
+ return false;
+ }
+
+ public void visitLocalVariableInstruction(Instruction i) {
+ short opcode = i.getOpcode();
+ Type type = i.getType(_cp);
+
+ if (opcode == Constants.IINC) {
+ _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() + "));");
+ } else {
+ String kind = opcode < Constants.ISTORE ? "Load" : "Store";
+ _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) + ", " + i.getIndex() + "));");
+ }
+ }
+
+ public void visitArrayInstruction(Instruction i) {
+ short opcode = i.getOpcode();
+ Type type = i.getType(_cp);
+ String kind = opcode < Constants.IASTORE ? "Load" : "Store";
+
+ _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type) + "));");
+ }
+
+ public void visitFieldInstruction(FieldInstruction i) {
+ short opcode = i.getOpcode();
+
+ String class_name = i.getClassName(_cp);
+ String field_name = i.getFieldName(_cp);
+ Type type = i.getFieldType(_cp);
+
+ _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name + "\", "
+ + BCELifier.printType(type) + ", " + "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() + "));");
+ }
+
+ public void visitInvokeInstruction(InvokeInstruction i) {
+ short opcode = i.getOpcode();
+ String class_name = i.getClassName(_cp);
+ String method_name = i.getMethodName(_cp);
+ Type type = i.getReturnType(_cp);
+ Type[] arg_types = i.getArgumentTypes(_cp);
+
+ _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name + "\", "
+ + BCELifier.printType(type) + ", " + BCELifier.printArgumentTypes(arg_types) + ", " + "Constants."
+ + Constants.OPCODE_NAMES[opcode].toUpperCase() + "));");
+ }
+
+ public void visitAllocationInstruction(Instruction i) {
+ Type type;
+
+ if (i.isConstantPoolInstruction()) {
+ type = ((InstructionCP) i).getType(_cp);
+ } else {
+ type = ((InstructionByte) i).getType();
+ }
+
+ short opcode = i.getOpcode();
+ int dim = 1;
+
+ switch (opcode) {
+ case Constants.NEW:
+ _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() + "\"));");
+ break;
+
+ case Constants.MULTIANEWARRAY:
+ dim = ((MULTIANEWARRAY) i).getDimensions();
+
+ case Constants.ANEWARRAY:
+ case Constants.NEWARRAY:
+ _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type) + ", (short) " + dim + "));");
+ break;
+
+ default:
+ throw new RuntimeException("Oops: " + opcode);
+ }
+ }
+
+ private void createConstant(Object value) {
+ String embed = value.toString();
+
+ if (value instanceof String) {
+ embed = '"' + Utility.convertString(value.toString()) + '"';
+ } else if (value instanceof Character) {
+ embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
+ }
+
+ _out.println("il.append(new PUSH(_cp, " + embed + "));");
+ }
+
+ public void visitLDC(Instruction i) {
+ createConstant(i.getValue(_cp));
+ }
+
+ public void visitLDC2_W(Instruction i) {
+ createConstant(i.getValue(_cp));
+ }
+
+ public void visitConstantPushInstruction(Instruction i) {
+ createConstant(i.getValue());
+ }
+
+ public void visitINSTANCEOF(Instruction i) {
+ Type type = i.getType(_cp);
+
+ _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));");
+ }
+
+ public void visitCHECKCAST(Instruction i) {
+ Type type = i.getType(_cp);
+
+ _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));");
}
- if(ih.hasTargeters()) {
- if(i instanceof InstructionBranch) {
- _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
- } else {
- _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
- }
- } else {
- _out.print(" ");
+ public void visitReturnInstruction(Instruction i) {
+ Type type = i.getType(_cp);
+
+ _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));");
}
- if(!visitInstruction(i))
- i.accept(this);
- }
-
- updateBranchTargets();
- updateExceptionHandlers();
- }
- }
-
- private boolean visitInstruction(Instruction i) {
- short opcode = i.getOpcode();
-
- if((InstructionConstants.INSTRUCTIONS[opcode] != null) &&
- !(i.isConstantInstruction()) &&
- !(i.isReturnInstruction())) { // Handled below
- _out.println("il.append(InstructionConstants." +
- i.getName().toUpperCase() + ");");
- return true;
- }
-
- return false;
- }
-
- public void visitLocalVariableInstruction(Instruction i) {
- short opcode = i.getOpcode();
- Type type = i.getType(_cp);
-
- if(opcode == Constants.IINC) {
- _out.println("il.append(new IINC(" + i.getIndex() + ", " +
- ((IINC)i).getIncrement() + "));");
- } else {
- String kind = (opcode < Constants.ISTORE)? "Load" : "Store";
- _out.println("il.append(_factory.create" + kind + "(" +
- BCELifier.printType(type) + ", " +
- i.getIndex() + "));");
- }
- }
-
- public void visitArrayInstruction(Instruction i) {
- short opcode = i.getOpcode();
- Type type = i.getType(_cp);
- String kind = (opcode < Constants.IASTORE)? "Load" : "Store";
-
- _out.println("il.append(_factory.createArray" + kind + "(" +
- BCELifier.printType(type) + "));");
- }
-
- public void visitFieldInstruction(FieldInstruction i) {
- short opcode = i.getOpcode();
-
- String class_name = i.getClassName(_cp);
- String field_name = i.getFieldName(_cp);
- Type type = i.getFieldType(_cp);
-
- _out.println("il.append(_factory.createFieldAccess(\"" +
- class_name + "\", \"" + field_name + "\", " +
- BCELifier.printType(type) + ", " +
- "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() +
- "));");
- }
-
- public void visitInvokeInstruction(InvokeInstruction i) {
- short opcode = i.getOpcode();
- String class_name = i.getClassName(_cp);
- String method_name = i.getMethodName(_cp);
- Type type = i.getReturnType(_cp);
- Type[] arg_types = i.getArgumentTypes(_cp);
-
- _out.println("il.append(_factory.createInvoke(\"" +
- class_name + "\", \"" + method_name + "\", " +
- BCELifier.printType(type) + ", " +
- BCELifier.printArgumentTypes(arg_types) + ", " +
- "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() +
- "));");
- }
-
- public void visitAllocationInstruction(Instruction i) {
- Type type;
-
- if(i.isConstantPoolInstruction()) {
- type = ((InstructionCP)i).getType(_cp);
- } else {
- type = ((InstructionByte)i).getType();
- }
-
- short opcode = ((Instruction)i).getOpcode();
- int dim = 1;
-
- switch(opcode) {
- case Constants.NEW:
- _out.println("il.append(_factory.createNew(\"" +
- ((ObjectType)type).getClassName() + "\"));");
- break;
-
- case Constants.MULTIANEWARRAY:
- dim = ((MULTIANEWARRAY)i).getDimensions();
-
- case Constants.ANEWARRAY:
- case Constants.NEWARRAY:
- _out.println("il.append(_factory.createNewArray(" +
- BCELifier.printType(type) + ", (short) " + dim + "));");
- break;
-
- default:
- throw new RuntimeException("Oops: " + opcode);
- }
- }
-
- private void createConstant(Object value) {
- String embed = value.toString();
-
- if(value instanceof String)
- embed = '"' + Utility.convertString(value.toString()) + '"';
- else if(value instanceof Character)
- embed = "(char)0x" + Integer.toHexString(((Character)value).charValue());
-
- _out.println("il.append(new PUSH(_cp, " + embed + "));");
- }
-
- public void visitLDC(Instruction i) {
- createConstant(i.getValue(_cp));
- }
-
- public void visitLDC2_W(Instruction i) {
- createConstant(i.getValue(_cp));
- }
-
- public void visitConstantPushInstruction(Instruction i) {
- createConstant(i.getValue());
- }
-
- public void visitINSTANCEOF(Instruction i) {
- Type type = i.getType(_cp);
-
- _out.println("il.append(new INSTANCEOF(_cp.addClass(" +
- BCELifier.printType(type) + ")));");
- }
-
- public void visitCHECKCAST(Instruction i) {
- Type type = i.getType(_cp);
-
- _out.println("il.append(_factory.createCheckCast(" +
- BCELifier.printType(type) + "));");
- }
-
- public void visitReturnInstruction(Instruction i) {
- Type type = i.getType(_cp);
-
- _out.println("il.append(_factory.createReturn(" +
- BCELifier.printType(type) + "));");
- }
-
- // Memorize BranchInstructions that need an update
- private ArrayList branches = new ArrayList();
-
- public void visitBranchInstruction(InstructionBranch bi) {
- BranchHandle bh = (BranchHandle)branch_map.get(bi);
- int pos = bh.getPosition();
- String name = bi.getName() + "_" + pos;
-
- if(bi instanceof InstructionSelect) {
- InstructionSelect s = (InstructionSelect)bi;
- branches.add(bi);
-
- StringBuffer args = new StringBuffer("new int[] { ");
- int[] matchs = s.getMatchs();
-
- for(int i=0; i < matchs.length; i++) {
- args.append(matchs[i]);
-
- if(i < matchs.length - 1)
- args.append(", ");
- }
-
- args.append(" }");
-
- _out.print(" Select " + name + " = new " +
- bi.getName().toUpperCase() + "(" + args +
- ", new InstructionHandle[] { ");
-
- for(int i=0; i < matchs.length; i++) {
- _out.print("null");
-
- if(i < matchs.length - 1)
- _out.print(", ");
- }
-
- _out.println(");");
- } else {
- int t_pos = bh.getTarget().getPosition();
- String target;
-
- if(pos > t_pos) {
- target = "ih_" + t_pos;
- } else {
- branches.add(bi);
- target = "null";
- }
-
- _out.println(" BranchInstruction " + name +
- " = _factory.createBranchInstruction(" +
- "Constants." + bi.getName().toUpperCase() + ", " +
- target + ");");
- }
-
- if(bh.hasTargeters())
- _out.println(" ih_" + pos + " = il.append(" + name + ");");
- else
- _out.println(" il.append(" + name + ");");
- }
-
- public void visitRET(RET i) {
- _out.println("il.append(new RET(" + i.getIndex() + ")));");
- }
-
- private void updateBranchTargets() {
- for(Iterator i = branches.iterator(); i.hasNext(); ) {
- InstructionBranch bi = (InstructionBranch)i.next();
- BranchHandle bh = (BranchHandle)branch_map.get(bi);
- int pos = bh.getPosition();
- String name = bi.getName() + "_" + pos;
- int t_pos = bh.getTarget().getPosition();
-
- _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
-
- if(bi instanceof InstructionSelect) {
- InstructionHandle[] ihs = ((InstructionSelect)bi).getTargets();
-
- for(int j = 0; j < ihs.length; j++) {
- t_pos = ihs[j].getPosition();
-
- _out.println(" " + name + ".setTarget(" + j +
- ", ih_" + t_pos + ");");
+ // Memorize BranchInstructions that need an update
+ private final ArrayList branches = new ArrayList();
+
+ public void visitBranchInstruction(InstructionBranch bi) {
+ BranchHandle bh = (BranchHandle) branch_map.get(bi);
+ int pos = bh.getPosition();
+ String name = bi.getName() + "_" + pos;
+
+ if (bi instanceof InstructionSelect) {
+ InstructionSelect s = (InstructionSelect) bi;
+ branches.add(bi);
+
+ StringBuffer args = new StringBuffer("new int[] { ");
+ int[] matchs = s.getMatchs();
+
+ for (int i = 0; i < matchs.length; i++) {
+ args.append(matchs[i]);
+
+ if (i < matchs.length - 1) {
+ args.append(", ");
+ }
+ }
+
+ args.append(" }");
+
+ _out.print(" Select " + name + " = new " + bi.getName().toUpperCase() + "(" + args + ", new InstructionHandle[] { ");
+
+ for (int i = 0; i < matchs.length; i++) {
+ _out.print("null");
+
+ if (i < matchs.length - 1) {
+ _out.print(", ");
+ }
+ }
+
+ _out.println(");");
+ } else {
+ int t_pos = bh.getTarget().getPosition();
+ String target;
+
+ if (pos > t_pos) {
+ target = "ih_" + t_pos;
+ } else {
+ branches.add(bi);
+ target = "null";
+ }
+
+ _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction(" + "Constants."
+ + bi.getName().toUpperCase() + ", " + target + ");");
+ }
+
+ if (bh.hasTargeters()) {
+ _out.println(" ih_" + pos + " = il.append(" + name + ");");
+ } else {
+ _out.println(" il.append(" + name + ");");
+ }
+ }
+
+ public void visitRET(RET i) {
+ _out.println("il.append(new RET(" + i.getIndex() + ")));");
+ }
+
+ private void updateBranchTargets() {
+ for (Iterator i = branches.iterator(); i.hasNext();) {
+ InstructionBranch bi = (InstructionBranch) i.next();
+ BranchHandle bh = (BranchHandle) branch_map.get(bi);
+ int pos = bh.getPosition();
+ String name = bi.getName() + "_" + pos;
+ int t_pos = bh.getTarget().getPosition();
+
+ _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
+
+ if (bi instanceof InstructionSelect) {
+ InstructionHandle[] ihs = ((InstructionSelect) bi).getTargets();
+
+ for (int j = 0; j < ihs.length; j++) {
+ t_pos = ihs[j].getPosition();
+
+ _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");");
+ }
+ }
+ }
+ }
+
+ private void updateExceptionHandlers() {
+ CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
+
+ for (int i = 0; i < handlers.length; i++) {
+ CodeExceptionGen h = handlers[i];
+ String type = h.getCatchType() == null ? "null" : BCELifier.printType(h.getCatchType());
+
+ _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition() + ", " + "ih_"
+ + h.getEndPC().getPosition() + ", " + "ih_" + h.getHandlerPC().getPosition() + ", " + type + ");");
+ }
}
- }
- }
- }
-
- private void updateExceptionHandlers() {
- CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
-
- for(int i=0; i < handlers.length; i++) {
- CodeExceptionGen h = handlers[i];
- String type = (h.getCatchType() == null)?
- "null" : BCELifier.printType(h.getCatchType());
-
- _out.println(" method.addExceptionHandler(" +
- "ih_" + h.getStartPC().getPosition() + ", " +
- "ih_" + h.getEndPC().getPosition() + ", " +
- "ih_" + h.getHandlerPC().getPosition() + ", " +
- type + ");");
- }
- }
}