⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verify3a.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * verify3a.c * * Copyright 2004 *   Kaffe.org contributors. See ChangeLog for details. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. * * * Performs pass 3a of bytecode verification: * verification of static constaints. */#include "config.h"#ifdef HAVE_STRING_H#include <string.h>#endif#include "baseClasses.h"#include "bytecode.h"#include "classMethod.h"#include "code.h"#include "constants.h"#include "exception.h"#include "errors.h"#include "debug.h"#include "gc.h"#include "lookup.h"#include "soft.h"#include "verify.h"#include "verify-block.h"#include "verify-debug.h"#include "verify-errors.h"/* * Helper function for error reporting in BRANCH_IN_BOUNDS macro in verifyMethod3a. */static inlineboolbranchInBoundsErrorInVerifyMethod3a(Verifier* v,				    uint32 codelen,				    uint32 n){	DBG(VERIFY3, dprintf("ERROR: branch to (%d) out of bound (%d) \n", n, codelen); );	return verifyError(v, "branch out of method code");}/* * Helper function for error reporting in CHECK_LOCAL_INDEX macro in verifyMethod3a. */static inlineboolcheckLocalIndexErrorInVerifyMethod3a(Verifier* v,				     uint32 pc,				     unsigned char* code,				     uint32 n){	DBG(VERIFY3,	    dprintf("ERROR:  pc = %d, instruction = ", pc);	    printInstruction(code[pc]);	    dprintf(", localsz = %d, localindex = %d\n", v->method->localsz, n);	    );	return verifyError(v, "attempting to access a local variable beyond local array");}/* * verifyMethod3a() *     check static constraints.  section 4.8.1 of JVML Spec 2. * * NOTE: we don't check whether execution can fall off the end of method code here as *       that would require us to know whether the last statements are reachable. *       Sun's verifier, for instance, rejects code with an unreachable NOP at the end! *       Thus we check whether execution can fall off the end during the data flow analysis *       of pass 3b, structural constraint checking. * * TODO: turn some of these macros into inlined functions */voidverifyMethod3a(Verifier* v){#define ENSURE_NON_WIDE \	if (wide) { \		verifyError(v, "illegal instruction following wide instruction"); \                return; \	}#define CHECK_POOL_IDX(_IDX) \	if (_IDX > pool->size) { \		verifyError(v, "attempt to access a constant pool index beyond constant pool range"); \                return; \	}	#define GET_IDX(_IDX, _PC) \	(_IDX) = getIdx(code, _PC); \	CHECK_POOL_IDX(_IDX)#define GET_WIDX(_IDX, _PC) \	_IDX = getWIdx(code, _PC); \	CHECK_POOL_IDX(_IDX)#define BRANCH_IN_BOUNDS(_N, _INST) \	if (_N >= codelen) { \		branchInBoundsErrorInVerifyMethod3a(v, codelen, _N); \		return; \	}        /* makes sure the index given for a local variable is within the correct index */#define CHECK_LOCAL_INDEX(_N) \	if ((_N) >= v->method->localsz) { \		checkLocalIndexErrorInVerifyMethod3a(v, pc, code, _N); \		return; \	}		const constants* pool = CLASS_CONSTANTS(v->method->class);		/* used for looking at method signatures... */	const char* sig;		uint32 codelen      = (uint32)METHOD_BYTECODE_LEN(v->method);	unsigned char* code = METHOD_BYTECODE_CODE(v->method);		uint32 pc = 0, newpc = 0, n = 0, idx = 0;	int32 branchoffset = 0;	int32 low, high;		bool wide;	bool inABlock; /* used when calculating the start/return address of each block */		uint32 blockCount  = 0;	BlockInfo** blocks = NULL;			DBG(VERIFY3, dprintf("    Verifier Pass 3a: checking static constraints and finding basic blocks...\n"); );	if (METHOD_BYTECODE_LEN(v->method) < 0) {		verifyError(v, "method bytecode length is less than 0");	}		/* find the start of every instruction and basic block to determine legal branches	 *	 * also, this makes sure that only legal instructions follow the WIDE instruction	 */	v->status[0] |= START_BLOCK;	wide = false;	pc = 0;	while(pc < codelen) {		v->status[pc] |= IS_INSTRUCTION;				DBG(VERIFY3, dprintf("        instruction: (%d) ", pc); printInstruction(code[pc]); dprintf("\n"); );				if (codelen < getNextPC(code, pc)) {			verifyError(v, "last operand in code array is cut off");			return;		}				switch(code[pc]) {		case ALOAD_0: case ASTORE_0:		case ILOAD_0: case ISTORE_0:		case FLOAD_0: case FSTORE_0:			ENSURE_NON_WIDE;			CHECK_LOCAL_INDEX(0);			break;		case ALOAD_1: case ASTORE_1:		case ILOAD_1: case ISTORE_1:		case FLOAD_1: case FSTORE_1:		case LLOAD_0: case LSTORE_0:		case DLOAD_0: case DSTORE_0:			ENSURE_NON_WIDE;			CHECK_LOCAL_INDEX(1);			break;		case ALOAD_2: case ASTORE_2:		case ILOAD_2: case ISTORE_2:		case FLOAD_2: case FSTORE_2:		case LLOAD_1: case LSTORE_1:		case DLOAD_1: case DSTORE_1:			ENSURE_NON_WIDE;			CHECK_LOCAL_INDEX(2);			break;		case ALOAD_3: case ASTORE_3:		case ILOAD_3: case ISTORE_3:		case FLOAD_3: case FSTORE_3:		case LLOAD_2: case LSTORE_2:		case DLOAD_2: case DSTORE_2:			ENSURE_NON_WIDE;			CHECK_LOCAL_INDEX(3);			break;		case LLOAD_3: case LSTORE_3:		case DLOAD_3: case DSTORE_3:			ENSURE_NON_WIDE;			CHECK_LOCAL_INDEX(4);			break;								case LDC1:			GET_IDX(idx, pc);			goto LDC_common;		case LDC2:			GET_WIDX(idx, pc);		LDC_common:			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Integer && n != CONSTANT_Float &&			    n != CONSTANT_String && n != CONSTANT_ResolvedString) {				verifyError(v, "ldc* on constant pool entry other than int/float/string");				return;			}			break;					case LDC2W:			GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Double && n != CONSTANT_Long) {				verifyError(v, "ldc2_w on constant pool entry other than long or double");				return;			}			break;					case GETFIELD:  case PUTFIELD:		case GETSTATIC: case PUTSTATIC:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			idx = CONST_TAG(idx, pool);			if (idx != CONSTANT_Fieldref) {				verifyError(v, "[get/put][field/static] accesses something in the constant pool that is not a CONSTANT_Fieldref");				return;			}			break;					case INVOKEVIRTUAL:		case INVOKESTATIC:		case INVOKESPECIAL:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Methodref) {				verifyError(v, "invoke* accesses something in the constant pool that is not a CONSTANT_Methodref");				return;			}						sig = METHODREF_SIGD(idx, pool);			if (*sig == '<') {				if (!strcmp(constructor_name->data, sig)) {					if (code[pc] != INVOKESPECIAL) {						 verifyError(v, "only invokespecial can be used to execute <init> methods");						 return;					}				} else {					verifyError(v, "no method with a name whose first character is '<' may be called by an invoke instruction");					return;				}			}						break;									/* invokeinterface is a 5 byte instruction.  the first byte is the instruction.			 * the next two are the index into the constant pool for the methodreference.			 * the fourth is the number of parameters expected by the method, and the verifier			 * must check that the actual method signature of the method to be invoked matches			 * this number.  the 5th must be zero.  these are apparently present for historical			 * reasons (yeah Sun :::smirk:::).			 */		case INVOKEINTERFACE:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_InterfaceMethodref) {				verifyError(v, "invokeinterface accesses something in the constant pool that is not a CONSTANT_InterfaceMethodref");				return;			}						sig = INTERFACEMETHODREF_SIGD(idx, pool);			if (*sig == '<') {				verifyError(v, "invokeinterface cannot be used to invoke any instruction with a name starting with '<'");				return;			}						if (code[pc + 3] == 0) {				verifyError(v, "fourth byte of invokeinterface is zero");				return;			} else if (code[pc + 4] != 0) {				verifyError(v, "fifth byte of invokeinterface is not zero");				return;			}						break;								case INSTANCEOF:		case CHECKCAST:			ENSURE_NON_WIDE;						GET_WIDX(n, pc);			n = CONST_TAG(n, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				verifyError(v, "instanceof/checkcast indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");				return;			}						break;								case MULTIANEWARRAY:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				verifyError(v, "multinewarray indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");				return;			}						/* number of dimensions must be <= num dimensions of array type being created */			sig = CLASS_NAMED(idx, pool);			newpc = code[pc + 3];			if (newpc == 0) {				verifyError(v, "dimensions operand of multianewarray must be non-zero");				return;			}			for(n = 0; *sig == '['; sig++, n++);			if (n < newpc) {				verifyError(v, "dimensions operand of multianewarray is > the number of dimensions in array being created");				return;			}						break;								case NEW:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				verifyError(v, "new indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");				return;			}						/* cannot create arrays with NEW */			sig = CLASS_NAMED(idx, pool);			if (*sig == '[') {				verifyError(v, "new instruction used to create a new array");				return;			}			break;								case ANEWARRAY:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				verifyError(v, "anewarray indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");				return;			}						/* count the number of dimensions of the array being created...it must be <= 255 */			sig = CLASS_NAMED(idx, pool);			for (n = 0; *sig == '['; sig++, n++);			if (n > 255) {				verifyError(v, "anewarray used to create an array of > 255 dimensions");				return;			}						break;					case NEWARRAY:			ENSURE_NON_WIDE;						n = code[pc + 1];			if (n < 4 || n > 11) {				verifyError(v, "newarray operand must be in the range [4,11]");				return;			}						break;												/***********************************************************			 * Instructions that can be modified by WIDE			 ***********************************************************/		case WIDE:			ENSURE_NON_WIDE;			wide = true;			break;								case ALOAD: case ASTORE:		case ILOAD: case ISTORE:		case FLOAD: case FSTORE:			if (wide == true) {			        /* the WIDE is considered the beginning of the instruction */				v->status[pc] ^= IS_INSTRUCTION;				v->status[pc] |= WIDE_MODDED;								pc++;				wide = false;								n = getWord(code, pc);			}			else {				n = code[pc + 1];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -