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

📄 verify.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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. */staticBlockInfo**verifyMethod3a(errorInfo* einfo,	       Method* method,	       uint32* status,    /* array of status info for all opcodes */	       uint32* numBlocks) /* number of basic blocks */{#define VERIFY_ERROR(_MSG) \	if (einfo->type == 0) { \		postExceptionMessage(einfo, JAVA_LANG(VerifyError), \				     "in method \"%s.%s\": %s", \				     CLASS_CNAME(method->class), METHOD_NAMED(method), _MSG); \	} \	return NULL#define ENSURE_NON_WIDE \	if (wide) { \		VERIFY_ERROR("illegal instruction following wide instruction"); \	}#define CHECK_POOL_IDX(_IDX) \	if (_IDX > pool->size) { \		VERIFY_ERROR("attempt to access a constant pool index beyond constant pool range"); \	}	#define GET_IDX(_IDX, _PC) \	(_IDX) = (_PC) + 1; \	(_IDX) = code[_IDX]; \	CHECK_POOL_IDX(_IDX)	#define GET_WIDX(_IDX, _PC) \	_IDX = (_PC) + 1; \	_IDX = WORD(code, _IDX); \	CHECK_POOL_IDX(_IDX)#define BRANCH_IN_BOUNDS(_N, _INST) \	if (_N < 0 || _N >= codelen) { \		DBG(VERIFY3, dprintf("ERROR: branch to (%d) out of bound (%d) \n", _N, codelen); ); \		VERIFY_ERROR("branch out of method code"); \	}        /* makes sure the index given for a local variable is within the correct index */#define CHECK_LOCAL_INDEX(_N) \	if ((_N) >= method->localsz) { \		DBG(VERIFY3, \		    dprintf("ERROR:  pc = %d, instruction = ", pc); \		    printInstruction(code[pc]); \		    dprintf(", localsz = %d, localindex = %d\n", method->localsz, _N); \		    ); \		VERIFY_ERROR("attempting to access a local variable beyond local array");  \	}			constants* pool     = CLASS_CONSTANTS(method->class);		/* used for looking at method signatures... */	const char* sig;		int codelen         = METHOD_BYTECODE_LEN(method);	unsigned char* code = METHOD_BYTECODE_CODE(method);		uint32 pc = 0, newpc = 0, n = 0, idx = 0;#define NEXTPC (pc + insnLen[code[pc]])	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"); );			/* 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	 */	status[0] |= START_BLOCK;	wide = false;	pc = 0;	while(pc < codelen) {		status[pc] |= IS_INSTRUCTION;				DBG(VERIFY3, dprintf("        instruction: (%d) ", pc); printInstruction(code[pc]); dprintf("\n"); );				if (codelen - pc < insnLen[code[pc]]) {			VERIFY_ERROR("last operand in code array is cut off");		}				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) {				VERIFY_ERROR("ldc* on constant pool entry other than int/float/string");			}			break;					case LDC2W:			GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Double && n != CONSTANT_Long) {				VERIFY_ERROR("ldc2_w on constant pool entry other than long or double");			}			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) {				VERIFY_ERROR("[get/put][field/static] accesses something in the constant pool that is not a CONSTANT_Fieldref");			}			break;					case INVOKEVIRTUAL:		case INVOKESTATIC:		case INVOKESPECIAL:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Methodref) {				VERIFY_ERROR("invoke* accesses something in the constant pool that is not a CONSTANT_Methodref");			}						sig = METHODREF_SIGD(idx, pool);			if (*sig == '<') {				if (!strcmp(constructor_name->data, sig)) {					if (code[pc] != INVOKESPECIAL) {						VERIFY_ERROR("only invokespecial can be used to execute <init> methods");					}				} else {					VERIFY_ERROR("no method with a name whose first character is '<' may be called by an invoke instruction");				}			}						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) {				VERIFY_ERROR("invokeinterface accesses something in the constant pool that is not a CONSTANT_InterfaceMethodref");			}						sig = INTERFACEMETHODREF_SIGD(idx, pool);			if (*sig == '<') {				VERIFY_ERROR("invokeinterface cannot be used to invoke any instruction with a name starting with '<'");			}						if (code[pc + 3] == 0) {				VERIFY_ERROR("fourth byte of invokeinterface is zero");			} else if (code[pc + 4] != 0) {				VERIFY_ERROR("fifth byte of invokeinterface is not zero");			}						break;								case INSTANCEOF:		case CHECKCAST:			ENSURE_NON_WIDE;						GET_WIDX(n, pc);			n = CONST_TAG(n, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				VERIFY_ERROR("instanceof/checkcast indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");			}						break;								case MULTIANEWARRAY:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				VERIFY_ERROR("multinewarray indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");			}						/* number of dimensions must be <= num dimensions of array type being created */			sig = CLASS_NAMED(idx, pool);			newpc = code[pc + 3];			if (newpc == 0) {				VERIFY_ERROR("dimensions operand of multianewarray must be non-zero");			}			for(n = 0; *sig == '['; sig++, n++);			if (n < newpc) {				VERIFY_ERROR("dimensions operand of multianewarray is > the number of dimensions in array being created");			}						break;								case NEW:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				VERIFY_ERROR("new indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");			}						/* cannot create arrays with NEW */			sig = CLASS_NAMED(idx, pool);			if (*sig == '[') {				VERIFY_ERROR("new instruction used to create a new array");			}			break;								case ANEWARRAY:			ENSURE_NON_WIDE;						GET_WIDX(idx, pc);			n = CONST_TAG(idx, pool);			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {				VERIFY_ERROR("anewarray indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");			}						/* 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) {				VERIFY_ERROR("anewarray used to create an array of > 255 dimensions");			}						break;					case NEWARRAY:			ENSURE_NON_WIDE;						n = code[pc + 1];			if (n < 4 || n > 11) {				VERIFY_ERROR("newarray operand must be in the range [4,11]");			}						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 */				status[pc] ^= IS_INSTRUCTION;				status[pc] |= WIDE_MODDED;								pc++;				wide = false;								n = WORD(code, pc);			}			else {				n = code[pc + 1];			}						CHECK_LOCAL_INDEX(n);			break;					case LLOAD: case LSTORE:		case DLOAD: case DSTORE:			if (wide == true) {			        /* the WIDE is considered the beginning of the instruction */				status[pc] ^= IS_INSTRUCTION;				status[pc] |= WIDE_MODDED;								pc++;				wide = false;								n = WORD(code, pc);			}			else {				GET_IDX(n, pc);			}						/* makes sure the index given for a local variable is within the correct index			 *			 * REM: longs and doubles take two consecutive local spots			 */			CHECK_LOCAL_INDEX(n + 1);			break;								case IINC:			if (wide == true) {			        /* the WIDE is considered the beginning of the instruction */				status[pc] ^= IS_INSTRUCTION;				status[pc] |= WIDE_MODDED;								pc += 2;				wide = false;			}			break;									/********************************************************************			 * BRANCHING INSTRUCTIONS			 ********************************************************************/		case GOTO:			ENSURE_NON_WIDE;			status[pc] |= END_BLOCK;						n = pc + 1;			branchoffset = WORD(code, n);			newpc = pc + branchoffset;			BRANCH_IN_BOUNDS(newpc, "goto");			status[newpc] |= START_BLOCK;			break;					case GOTO_W:			ENSURE_NON_WIDE;			status[pc] |= END_BLOCK;						n = pc + 1;			branchoffset = DWORD(code, n);			newpc = pc + branchoffset;			BRANCH_IN_BOUNDS(newpc, "goto_w");			status[newpc] |= START_BLOCK;			break;								case IF_ACMPEQ:  case IFNONNULL:		case IF_ACMPNE:  case IFNULL:		case IF_ICMPEQ:  case IFEQ:		case IF_ICMPNE:	 case IFNE:		case IF_ICMPGT:	 case IFGT:		case IF_ICMPGE:	 case IFGE:		case IF_ICMPLT:	 case IFLT:		case IF_ICMPLE:	 case IFLE:			ENSURE_NON_WIDE;			status[pc] |= END_BLOCK;						newpc = NEXTPC;			BRANCH_IN_BOUNDS(newpc, "if<condition> = false");			status[newpc] |= START_BLOCK;						n            = pc + 1;			branchoffset = WORD(code, n);			newpc        = pc + branchoffset;			BRANCH_IN_BOUNDS(newpc, "if<condition> = true");			status[newpc] |= START_BLOCK;			break;								case JSR:			newpc = pc + 1;			newpc = pc + WORD(code, newpc);			goto JSR_common;		case JSR_W:			newpc = pc + 1;			newpc = pc + DWORD(code, newpc);					JSR_common:			ENSURE_NON_WIDE;			status[pc] |= END_BLOCK;

⌨️ 快捷键说明

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