📄 check_code.c
字号:
if (extra == 0) { panic("unexpected"); } else { char *name = ID2Str_Local(context, context->classHash, extra, 0); strcpy(buf, name); if (indirection) strcat(buf, ";"); } return; } default: panic("bad type"); } *buf = '\0';}/*========================================================================= * FUNCTION: check_class_constant * OVERVIEW: Checks and returns the index corresponding to the given * UTF8 constant entry within the constant pool. * Returns -1 if none was found. * Invoked by get_type_code(). * INTERFACE: * parameters: pointer to the ClassClass structure. * char *: utf8 * * returns: long type *=======================================================================*/long check_class_constant(ClassClass *cb, char *utf8){ int i; cp_item_type *constant_pool = cbConstantPool(cb); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; for (i = 0; i < cbConstantPoolCount(cb); i++) { if (type_table[i] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED) && strcmp(utf8, cbName(constant_pool[i].clazz)) == 0) { return i; } if (type_table[i] == CONSTANT_Class && strcmp(utf8, constant_pool[constant_pool[i].i].cp) == 0) { return i; } } return -1;}/*========================================================================= * FUNCTION: get_type_code * OVERVIEW: Retrieves the type code entry given the item type. * Invoked by verify_method() to retrieve the type code * for the stack map entries. * INTERFACE: * parameters: pointer to the context_type structure. * fullinfo_type: type * * returns: struct map_entry *=======================================================================*/struct map_entry get_type_code(context_type *context, fullinfo_type type){ struct map_entry result = {0,0}; switch (type) { case ITEM_Double_2: case ITEM_Long_2: case ITEM_Bogus: result.type = CF_ITEM_Bogus; return result; case ITEM_Integer: result.type = CF_ITEM_Integer; return result; case ITEM_Float: result.type = CF_ITEM_Float; return result; case ITEM_Double: result.type = CF_ITEM_Double; return result; case ITEM_Long: result.type = CF_ITEM_Long; return result; case ITEM_InitObject: result.type = CF_ITEM_InitObject; return result; default: if (GET_ITEM_TYPE(type) == ITEM_NewObject) { int inum = GET_EXTRA_INFO(type); result.type = CF_ITEM_NewObject; result.info = context->instruction_data[inum].offset; return result; } else if (GET_ITEM_TYPE(type) == ITEM_Object && GET_EXTRA_INFO(type) == 0) { result.type = CF_ITEM_Null; return result; } else if (GET_ITEM_TYPE(type) == ITEM_Object || GET_INDIRECTION(type) > 0) { char type_name[1024]; int i; result.type = CF_ITEM_Object; get_type_name(context, type, type_name); i = check_class_constant(context->class, type_name); if (i >= 0) { result.info = i; return result; } for (i = 0; i < unhand(context->class)->n_new_class_entries; i++) { if (strcmp(type_name, unhand(context->class)->new_class_entries[i]) == 0) { result.info = ~i; return result; } } { int entries = unhand(context->class)->n_new_class_entries; unhand(context->class)->new_class_entries[entries] = strdup(type_name); result.info = ~entries; unhand(context->class)->n_new_class_entries = entries + 1; return result; } } else { panic("bad type code"); return result; /* not reached */ } }}/*========================================================================= * FUNCTION: verify_method * OVERVIEW: Verifies the code for one method within a class file. * Invoked by verify_class_codes(). * INTERFACE: * parameters: pointer to the context_type structure. * struct methodblock*: mb * * returns: nothing *=======================================================================*/static voidverify_method(context_type *context, struct methodblock *mb){ int access_bits = mb->fb.access; unsigned char *code; int code_length; short *code_data; instruction_data_type *idata = 0; int instruction_count; int i, offset, inumber; int exception_count; int n_stack_maps, dead_count, jsr_count; again: code = mb->code; code_length = mb->code_length; /* CCerror can give method-specific info once this is set */ context->mb = mb; CCreinit(context); /* initial heap */ code_data = NEW(short, code_length);#ifdef DEBUG_VERIFIER if (verify_verbose) { jio_fprintf(stdout, "Looking at %s.%s%s 0x%x\n", cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature, (long)mb); }#endif if (((access_bits & ACC_PUBLIC) != 0) && ((access_bits & (ACC_PRIVATE | ACC_PROTECTED)) != 0)) { CCerror(context, "Inconsistent access bits."); } if ((access_bits & (ACC_ABSTRACT | ACC_NATIVE)) != 0) { /* not much to do for abstract or native methods */ return; } if (code_length >= 65535) { CCerror(context, "Code of a method longer than 65535 bytes"); } /* Run through the code. Mark the start of each instruction, and give * the instruction a number */ for (i = 0, offset = 0; offset < code_length; i++) { int length = instruction_length(&code[offset]); int next_offset = offset + length; if (length <= 0) CCerror(context, "Illegal instruction found at offset %d", offset); if (next_offset > code_length) CCerror(context, "Code stops in the middle of instruction " " starting at offset %d", offset); code_data[offset] = i; while (++offset < next_offset) code_data[offset] = -1; /* illegal location */ } instruction_count = i; /* number of instructions in code */ /* Allocate a structure to hold info about each instruction. */ idata = NEW(instruction_data_type, instruction_count); /* Initialize the heap, and other info in the context structure. */ context->code = code; context->instruction_data = idata; context->code_data = code_data; context->instruction_count = instruction_count; context->handler_info = NEW(struct handler_info_type, mb->exception_table_length); context->bitmask_size = (mb->nlocals + (BITS_PER_INT - 1))/BITS_PER_INT; if (instruction_count == 0) CCerror(context, "Empty code"); for (inumber = 0, offset = 0; offset < code_length; inumber++) { int length = instruction_length(&code[offset]); instruction_data_type *this_idata = &idata[inumber]; this_idata->opcode = code[offset]; this_idata->offset = offset; this_idata->length = length; this_idata->stack_info.stack = NULL; this_idata->stack_info.stack_size = UNKNOWN_STACK_SIZE; this_idata->register_info.register_count = UNKNOWN_REGISTER_COUNT; this_idata->changed = FALSE; /* no need to look at it yet. */ this_idata->protected = FALSE; /* no need to look at it yet. */ /* Added for inlinejsr */ this_idata->is_target = FALSE; /* no need to look at it yet. */ this_idata->and_flags = (flag_type) -1; /* "bottom" and value */ this_idata->or_flags = 0; /* "bottom" or value*/ /* This also sets up this_data->operand. It also makes the * xload_x and xstore_x instructions look like the generic form. */ verify_opcode_operands(context, inumber, offset); offset += length; } /* make sure exception table is reasonable. */ initialize_exception_table(context); /* Set up first instruction, and start of exception handlers. */ initialize_dataflow(context); /* Run data flow analysis on the instructions. */ context->redoJsr = FALSE; run_dataflow(context); for (inumber = 0; inumber < instruction_count; inumber++) { instruction_data_type *this_idata = &idata[inumber]; if ( (this_idata->or_flags & FLAG_REACHED) && ((this_idata->opcode == opc_jsr) || (this_idata->opcode == opc_jsr_w)) && (this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION)) { this_idata->changed = TRUE; context->redoJsr = TRUE; } } if (context->redoJsr) { run_dataflow(context); } /* verify checked exceptions, if any */ if ((exception_count = mb->nexceptions) > 0) { unsigned short *exceptions = mb->exceptions; for (i = 0; i < (int)exception_count; i++) { /* Make sure the constant pool item is CONSTANT_Class */ verify_constant_pool_type(context, (int)exceptions[i], 1 << CONSTANT_Class); } } dead_count = jsr_count = 0; for (inumber = 0; inumber < instruction_count; inumber++) { instruction_data_type *this_idata = &idata[inumber]; if ((this_idata->or_flags & FLAG_REACHED) == 0) { dead_count++; } else if (this_idata->opcode == opc_jsr || this_idata->opcode == opc_jsr_w) { jsr_count++; } } if (dead_count > 0 || jsr_count > 0) { rewriteCode(context, mb); goto again; } n_stack_maps = 0; for (inumber = 0; inumber < instruction_count; inumber++) { instruction_data_type *this_idata = &idata[inumber]; if (this_idata->is_target) { n_stack_maps++; } } mb->n_stack_maps = n_stack_maps; mb->stack_maps = (struct stack_map *)malloc(n_stack_maps * sizeof(struct stack_map)); n_stack_maps = 0; for (inumber = 0; inumber < instruction_count; inumber++) { instruction_data_type *this_idata = &idata[inumber]; if (this_idata->is_target) { struct stack_info_type *stack_info = &this_idata->stack_info; struct register_info_type *register_info = &this_idata->register_info; int register_count = register_info->register_count; struct stack_item_type *stack; struct map_entry *new_entries; int index, index2; /* We may be allocating too big a structure if there are longs * or doubles on the stack, but that's okay */ new_entries = (struct map_entry *)malloc(register_count * sizeof(struct map_entry)); for (index2 = 0, index = 0; index < register_count; index++) { fullinfo_type info = register_info->registers[index]; if (info == ITEM_Double || info == ITEM_Long) { if (index + 1 < register_count && register_info->registers[index + 1] == info+1) { new_entries[index2++] = get_type_code(context, info); index++; } else { new_entries[index2++] = get_type_code(context, ITEM_Bogus); } } else { new_entries[index2++] = get_type_code(context, info); } } mb->stack_maps[n_stack_maps].offset = this_idata->offset; mb->stack_maps[n_stack_maps].locals = new_entries; mb->stack_maps[n_stack_maps].nlocals = index2; mb->stack_maps[n_stack_maps].nstacks = 0; for (stack = stack_info->stack; stack; stack = stack->next) { mb->stack_maps[n_stack_maps].nstacks++; } new_entries = (struct map_entry *)malloc(mb->stack_maps[n_stack_maps].nstacks * sizeof(struct map_entry)); index = 0; for (stack = stack_info->stack; stack; stack = stack->next) { new_entries[mb->stack_maps[n_stack_maps].nstacks - (++index)] = get_type_code(context, stack->item); } mb->stack_maps[n_stack_maps].stacks = new_entries; unhand(context->class)->has_stack_maps = 1; n_stack_maps++; } }}/*========================================================================= * FUNCTION: verify_opcode_operands * OVERVIEW: Verifies the operands of a single instruction given an * instruction number and an offset. * Also, for simplicity, move the operand into the ->operand * field. * Make sure that branches do not go into the middle * of nowhere. * Invoked by verify_method(). * INTERFACE: * parameters: context_type *: context * int: inumber * int: offset * * returns: nothing *=======================================================================*/static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -