📄 check_code.c
字号:
work_to_do = TRUE;#ifdef DEBUG_VERIFIER if (verify_verbose) { int opcode = this_idata->opcode; char *opname = (opcode == opc_invokeinit) ? "invokeinit" : opnames[opcode]; jio_fprintf(stdout, "Instruction %d: ", inumber); print_stack(context, &this_idata->stack_info); print_registers(context, &this_idata->register_info); print_flags(context, this_idata->and_flags, this_idata->or_flags); jio_fprintf(stdout, " %s(%d)", opname, this_idata->operand.i); fflush(stdout); }#endif /* Make sure the registers and flags are appropriate */ check_register_values(context, inumber); check_flags(context, inumber); /* Make sure the stack can deal with this instruction */ pop_stack(context, inumber, &new_stack_info); /* Update the registers and flags */ update_registers(context, inumber, &new_register_info); update_flags(context, inumber, &new_and_flags, &new_or_flags); /* Update the stack. */ push_stack(context, inumber, &new_stack_info); if (new_stack_info.stack_size > max_stack_size) CCerror(context, "Stack size too large");#ifdef DEBUG_VERIFIER if (verify_verbose) { jio_fprintf(stdout, " "); print_stack(context, &new_stack_info); print_registers(context, &new_register_info); print_flags(context, new_and_flags, new_or_flags); fflush(stdout); }#endif /* Add the new stack and register information to any * instructions that can follow this instruction. */ merge_into_successors(context, inumber, &new_register_info, &new_stack_info, new_and_flags, new_or_flags); } } }}/*========================================================================= * FUNCTION: check_register_values * OVERVIEW: Make sure that the registers contain a legitimate value * for the given instruction. * INTERFACE: * parameters: pointer to the context_type * int inumber * returns: nothing *=======================================================================*/static voidcheck_register_values(context_type *context, int inumber){ instruction_data_type *idata = context->instruction_data; instruction_data_type *this_idata = &idata[inumber]; opcode_type opcode = this_idata->opcode; int operand = this_idata->operand.i; int register_count = this_idata->register_info.register_count; fullinfo_type *registers = this_idata->register_info.registers; bool_t double_word = FALSE; /* default value */ int type; switch (opcode) { default: return; case opc_iload: case opc_iinc: type = ITEM_Integer; break; case opc_fload: type = ITEM_Float; break; case opc_aload: type = ITEM_Object; break; case opc_ret: type = ITEM_ReturnAddress; break; case opc_lload: type = ITEM_Long; double_word = TRUE; break; case opc_dload: type = ITEM_Double; double_word = TRUE; break; } if (!double_word) { fullinfo_type reg = registers[operand]; /* Make sure we don't have an illegal register or one with wrong type */ if (operand >= register_count) { CCerror(context, "Accessing value from uninitialized register %d", operand); } else if (WITH_ZERO_EXTRA_INFO(reg) == MAKE_FULLINFO(type, 0, 0)) { /* the register is obviously of the given type */ return; } else if (GET_INDIRECTION(reg) > 0 && type == ITEM_Object) { /* address type stuff be used on all arrays */ return; } else if (GET_ITEM_TYPE(reg) == ITEM_ReturnAddress) { CCerror(context, "Cannot load return address from register %d", operand); /* alternatively (GET_ITEM_TYPE(reg) == ITEM_ReturnAddress) && (opcode == opc_iload) && (type == ITEM_Object || type == ITEM_Integer) but this never occurs */ } else if (reg == ITEM_InitObject && type == ITEM_Object) { return; } else if (WITH_ZERO_EXTRA_INFO(reg) == MAKE_FULLINFO(ITEM_NewObject, 0, 0) && type == ITEM_Object) { return; } else { CCerror(context, "Register %d contains wrong type", operand); } } else { /* Make sure we don't have an illegal register or one with wrong type */ if ((operand + 1) >= register_count) { CCerror(context, "Accessing value from uninitialized register pair %d/%d", operand, operand+1); } else { if ((registers[operand] == MAKE_FULLINFO(type, 0, 0)) && (registers[operand + 1] == MAKE_FULLINFO(type + 1, 0, 0))) { return; } else { CCerror(context, "Register pair %d/%d contains wrong type", operand, operand+1); } } } }/*========================================================================= * FUNCTION: check_flags * OVERVIEW: Make sure that the flags contain legitimate values for this * instruction. * INTERFACE: * parameters: pointer to the context_type * int: instruction number * returns: nothing *=======================================================================*/static voidcheck_flags(context_type *context, int inumber){ instruction_data_type *idata = context->instruction_data; instruction_data_type *this_idata = &idata[inumber]; opcode_type opcode = this_idata->opcode; if (opcode == opc_return) { /* We need a constructor, but we aren't guaranteed it's called */ if ((this_idata->or_flags & FLAG_NEED_CONSTRUCTOR) && !(this_idata->and_flags & FLAG_CONSTRUCTED)) CCerror(context, "Constructor must call super() or this()"); /* fall through */ } else if ((opcode == opc_ireturn) || (opcode == opc_lreturn) || (opcode == opc_freturn) || (opcode == opc_dreturn) || (opcode == opc_areturn)) { if (this_idata->or_flags & FLAG_NO_RETURN) /* This method cannot exit normally */ CCerror(context, "Cannot return normally"); }}/*========================================================================= * FUNCTION: pop_stack * OVERVIEW: Make sure that the top of the stack contains reasonable * values for the given instruction. The post-pop values of * the stack and its size are returned in *new_stack_info. * INTERFACE: * parameters: pointer to the context_type * int: instruction number * stack_info_type: *new_stack_info * returns: nothing *=======================================================================*/static void pop_stack(context_type *context, int inumber, stack_info_type *new_stack_info){ instruction_data_type *idata = context->instruction_data; instruction_data_type *this_idata = &idata[inumber]; opcode_type opcode = this_idata->opcode; stack_item_type *stack = this_idata->stack_info.stack; int stack_size = this_idata->stack_info.stack_size; char *stack_operands, *p; char buffer[257]; /* for holding manufactured argument lists */ fullinfo_type stack_extra_info_buffer[256]; /* save info popped off stack */ fullinfo_type *stack_extra_info = &stack_extra_info_buffer[256]; fullinfo_type full_info, put_full_info; switch(opcode) { default: /* For most instructions, we just use a built-in table */ stack_operands = opcode_in_out[opcode][0]; break; case opc_putstatic: case opc_putfield: { /* The top thing on the stack depends on the signature of * the object. */ int operand = this_idata->operand.i; char *signature = cp_index_to_signature(context, operand); char *ip = buffer;#ifdef DEBUG_VERIFIER if (verify_verbose) { print_formatted_fieldname(context, operand); }#endif if (opcode == opc_putfield) *ip++ = 'A'; /* object for putfield */ *ip++ = signature_to_fieldtype(context, &signature, &put_full_info); *ip = '\0'; stack_operands = buffer; break; } case opc_invokevirtual: case opc_invokespecial: case opc_invokeinit: /* invokespecial call to <init> */ case opc_invokestatic: case opc_invokeinterface: { /* The top stuff on the stack depends on the method signature */ int operand = this_idata->operand.i; char *signature = cp_index_to_signature(context, operand); char *ip = buffer; char *p;#ifdef DEBUG_VERIFIER if (verify_verbose) { print_formatted_fieldname(context, operand); }#endif if (opcode != opc_invokestatic) /* First, push the object */ *ip++ = (opcode == opc_invokeinit ? '@' : 'A'); for (p = signature + 1; *p != SIGNATURE_ENDFUNC; ) { *ip++ = signature_to_fieldtype(context, &p, &full_info); if (ip >= buffer + sizeof(buffer) - 1) CCerror(context, "Signature %s has too many arguments", signature); } *ip = 0; stack_operands = buffer; break; } case opc_multianewarray: { /* Count can't be larger than 255. So can't overflow buffer */ int count = this_idata->operand2.i; /* number of ints on stack */ memset(buffer, 'I', count); buffer[count] = '\0'; stack_operands = buffer; break; } } /* of switch */ /* Run through the list of operands >>backwards<< */ for ( p = stack_operands + strlen(stack_operands); p > stack_operands; stack = stack->next) { int type = *--p; fullinfo_type top_type = stack ? stack->item : 0; int size = (type == 'D' || type == 'L') ? 2 : 1; *--stack_extra_info = top_type; if (stack == NULL) CCerror(context, "Unable to pop operand off an empty stack"); switch (type) { case 'I': if (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0)) CCerror(context, "Expecting to find integer on stack"); break; case 'F': if (top_type != MAKE_FULLINFO(ITEM_Float, 0, 0)) CCerror(context, "Expecting to find float on stack"); break; case 'A': /* object or array */ if ( (GET_ITEM_TYPE(top_type) != ITEM_Object) && (GET_INDIRECTION(top_type) == 0)) { /* The thing isn't an object or an array. Let's see if it's * one of the special cases */ if ( (WITH_ZERO_EXTRA_INFO(top_type) == MAKE_FULLINFO(ITEM_ReturnAddress, 0, 0)) && (opcode == opc_astore)) break; if ( (GET_ITEM_TYPE(top_type) == ITEM_NewObject || (GET_ITEM_TYPE(top_type) == ITEM_InitObject)) && ((opcode == opc_astore) || (opcode == opc_aload))) break; /* The 2nd edition VM of the specification allows field * initializations before the superclass initializer, * if the field is defined within the current class. */ if ( (GET_ITEM_TYPE(top_type) == ITEM_InitObject) && (opcode == opc_putfield)) { int num_fields; int key = this_idata->operand.i; fullinfo_type clazz_info = cp_index_to_class_fullinfo( context, key, TRUE); char *name = cp_index_to_fieldname(context, key); char *signature = cp_index_to_signature(context, key); unsigned ID = NameAndTypeToHash(name, signature); ClassClass *calledClass = object_fullinfo_to_classclass(context, clazz_info); struct fieldblock *fb; if (ID == 0) { /* NameAndTypeToHash returns 0 * if out of memory */ CCerror(context, "Out of memory"); break; } num_fields = cbFieldsCount(calledClass); fb = cbFields(calledClass); for (; --num_fields >= 0; fb++) { if (fb->ID == ID) { break; } } if (num_fields != -1) { top_type = context->currentclass_info; *stack_extra_info = top_type; break; } } CCerror(context, "Expecting to find object/array on stack"); } break; case '@': { /* unitialized object, for call to <init> */ int item_type = GET_ITEM_TYPE(top_type); if (item_type != ITEM_NewObject && item_type != ITEM_InitObject) CCerror(context, "Expecting to find unitialized object on stack"); break; } case 'O': /* object, not array */ if (WITH_ZERO_EXTRA_INFO(top_type) != MAKE_FULLINFO(ITEM_Object, 0, 0)) CCerror(context, "Expecting to find object on stack"); break; case 'a': /* integer, object, or array */ if ( (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0)) && (GET_ITEM_TYPE(top_type) != ITEM_Object) && (GET_INDIRECTION(top_type) == 0)) CCerror(context, "Expecting to find object, array, or int on stack"); break; case 'D': /* double */ if (top_type != MAKE_FULLINFO(ITEM_Double, 0, 0)) CCerror(context, "Expecting to find double on stack"); break; case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -