📄 executionvisitor.java
字号:
package org.apache.bcel.verifier.structurals;
/* ====================================================================
* 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, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this 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:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this 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 this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache BCEL", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS 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 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This 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/>.
*/
import org.apache.bcel.Constants;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantDouble;
import org.apache.bcel.classfile.ConstantFloat;
import org.apache.bcel.classfile.ConstantInteger;
import org.apache.bcel.classfile.ConstantLong;
import org.apache.bcel.classfile.ConstantString;
/**
* This Visitor class may be used for a type-based Java Virtual Machine
* simulation.
* It does not check for correct types on the OperandStack or in the
* LocalVariables; nor does it check their sizes are sufficiently big.
* Thus, to use this Visitor for bytecode verifying, you have to make sure
* externally that the type constraints of the Java Virtual Machine instructions
* are satisfied. An InstConstraintVisitor may be used for this.
* Anyway, this Visitor does not mandate it. For example, when you
* visitIADD(IADD o), then there are two stack slots popped and one
* stack slot containing a Type.INT is pushed (where you could also
* pop only one slot if you know there are two Type.INT on top of the
* stack). Monitor-specific behaviour is not simulated.
*
* </P><B>Conventions:</B>
*
* Type.VOID will never be pushed onto the stack. Type.DOUBLE and Type.LONG
* that would normally take up two stack slots (like Double_HIGH and
* Double_LOW) are represented by a simple single Type.DOUBLE or Type.LONG
* object on the stack here.
* If a two-slot type is stored into a local variable, the next variable
* is given the type Type.UNKNOWN.
*
* @version $Id: ExecutionVisitor.java,v 1.2 2006/09/04 15:43:18 andos Exp $
* @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
* @see #visitDSTORE(DSTORE o)
* @see InstConstraintVisitor
*/
public class ExecutionVisitor extends EmptyVisitor implements Visitor{
/**
* The executionframe we're operating on.
*/
private Frame frame = null;
/**
* The ConstantPoolGen we're working with.
* @see #setConstantPoolGen(ConstantPoolGen)
*/
private ConstantPoolGen cpg = null;
/**
* Constructor. Constructs a new instance of this class.
*/
public ExecutionVisitor(){}
/**
* The OperandStack from the current Frame we're operating on.
* @see #setFrame(Frame)
*/
private OperandStack stack(){
return frame.getStack();
}
/**
* The LocalVariables from the current Frame we're operating on.
* @see #setFrame(Frame)
*/
private LocalVariables locals(){
return frame.getLocals();
}
/**
* Sets the ConstantPoolGen needed for symbolic execution.
*/
public void setConstantPoolGen(ConstantPoolGen cpg){
this.cpg = cpg;
}
/**
* The only method granting access to the single instance of
* the ExecutionVisitor class. Before actively using this
* instance, <B>SET THE ConstantPoolGen FIRST</B>.
* @see #setConstantPoolGen(ConstantPoolGen)
*/
public void setFrame(Frame f){
this.frame = f;
}
///** Symbolically executes the corresponding Java Virtual Machine instruction. */
//public void visitWIDE(WIDE o){
// The WIDE instruction is modelled as a flag
// of the embedded instructions in BCEL.
// Therefore BCEL checks for possible errors
// when parsing in the .class file: We don't
// have even the possibilty to care for WIDE
// here.
//}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitAALOAD(AALOAD o){
stack().pop(); // pop the index int
//System.out.print(stack().peek());
Type t = stack().pop(); // Pop Array type
if (t == Type.NULL){
stack().push(Type.NULL);
} // Do nothing stackwise --- a NullPointerException is thrown at Run-Time
else{
ArrayType at = (ArrayType) t;
stack().push(at.getElementType());
}
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitAASTORE(AASTORE o){
stack().pop();
stack().pop();
stack().pop();
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitACONST_NULL(ACONST_NULL o){
stack().push(Type.NULL);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitALOAD(ALOAD o){
stack().push(locals().get(o.getIndex()));
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitANEWARRAY(ANEWARRAY o){
stack().pop(); //count
stack().push( new ArrayType(o.getType(cpg), 1) );
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitARETURN(ARETURN o){
stack().pop();
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitARRAYLENGTH(ARRAYLENGTH o){
stack().pop();
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitASTORE(ASTORE o){
locals().set(o.getIndex(), stack().pop());
//System.err.println("TODO-DEBUG: set LV '"+o.getIndex()+"' to '"+locals().get(o.getIndex())+"'.");
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitATHROW(ATHROW o){
Type t = stack().pop();
stack().clear();
if (t.equals(Type.NULL))
stack().push(Type.getType("Ljava/lang/NullPointerException;"));
else
stack().push(t);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitBALOAD(BALOAD o){
stack().pop();
stack().pop();
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitBASTORE(BASTORE o){
stack().pop();
stack().pop();
stack().pop();
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitBIPUSH(BIPUSH o){
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitCALOAD(CALOAD o){
stack().pop();
stack().pop();
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitCASTORE(CASTORE o){
stack().pop();
stack().pop();
stack().pop();
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitCHECKCAST(CHECKCAST o){
// It's possibly wrong to do so, but SUN's
// ByteCode verifier seems to do (only) this, too.
// TODO: One could use a sophisticated analysis here to check
// if a type cannot possibly be cated to another and by
// so doing predict the ClassCastException at run-time.
stack().pop();
stack().push(o.getType(cpg));
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitD2F(D2F o){
stack().pop();
stack().push(Type.FLOAT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitD2I(D2I o){
stack().pop();
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitD2L(D2L o){
stack().pop();
stack().push(Type.LONG);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDADD(DADD o){
stack().pop();
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDALOAD(DALOAD o){
stack().pop();
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDASTORE(DASTORE o){
stack().pop();
stack().pop();
stack().pop();
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDCMPG(DCMPG o){
stack().pop();
stack().pop();
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDCMPL(DCMPL o){
stack().pop();
stack().pop();
stack().push(Type.INT);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDCONST(DCONST o){
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDDIV(DDIV o){
stack().pop();
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDLOAD(DLOAD o){
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDMUL(DMUL o){
stack().pop();
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDNEG(DNEG o){
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDREM(DREM o){
stack().pop();
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDRETURN(DRETURN o){
stack().pop();
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDSTORE(DSTORE o){
locals().set(o.getIndex(), stack().pop());
locals().set(o.getIndex()+1, Type.UNKNOWN);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDSUB(DSUB o){
stack().pop();
stack().pop();
stack().push(Type.DOUBLE);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDUP(DUP o){
Type t = stack().pop();
stack().push(t);
stack().push(t);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDUP_X1(DUP_X1 o){
Type w1 = stack().pop();
Type w2 = stack().pop();
stack().push(w1);
stack().push(w2);
stack().push(w1);
}
/** Symbolically executes the corresponding Java Virtual Machine instruction. */
public void visitDUP_X2(DUP_X2 o){
Type w1 = stack().pop();
Type w2 = stack().pop();
if (w2.getSize() == 2){
stack().push(w1);
stack().push(w2);
stack().push(w1);
}
else{
Type w3 = stack().pop();
stack().push(w1);
stack().push(w3);
stack().push(w2);
stack().push(w1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -