verifycode.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,993 行 · 第 1/5 页
C
1,993 行
* Because a piece of code can possibly be reached through multiple subroutine calls (think * nested try...finally blocks), we have to compute one of these masks for each * path. Thus each struct mask_type has an entry field, giving the instruction number of * a subroutine entry point, i.e. an instruction which is the target of a jsr. */struct mask_type { int entry; int *modifies;};typedef unsigned short flag_type;/* * Before any dataflow is done, the instructions are unpacked into struct instruction_data_type. * Some opcodes are folded together because it is not important to distinguish between them, * and at lease one opcode is split off as a special case: opc_invokeinit. * Operands are broken out and unpacked. * During the course of computation, additional information is added (see use of operand2 * for the jsr), and it is decorated with the entire state of the computation BEFORE EXECUTION * of the instruction. * All references to the instruction stream are converted into instruction numbers, which are * indexes into an array of this structure. */struct instruction_data_type { opcode_type opcode; /* may turn into "canonical" opcode */ unsigned changed:1; /* has it changed */ unsigned protected:1; /* must accessor be a subclass of "this" */ union { int i; /* operand to the opcode */ int *ip; fullinfo_type fi; } operand, operand2; fullinfo_type p; struct stack_info_type stack_info; struct register_info_type register_info;#define FLAG_REACHED 0x01 /* instruction reached */#define FLAG_NEED_CONSTRUCTOR 0x02 /* must call this.<init> or super.<init> */#define FLAG_NO_RETURN 0x04 /* must throw out of method */ flag_type or_flags; /* true for at least one path to this inst */#define FLAG_CONSTRUCTED 0x01 /* this.<init> or super.<init> called */ flag_type and_flags; /* true for all paths to this instruction */};/* * As in a class file, a handler has a starting and ending range and a beginning, * but this has then as instruction indexes. The initial stack is always * a single item of the class type being caught by the handler. */struct handler_info_type { int start, end, handler; struct stack_info_type stack_info;};/* * See struct stack_info_type above, which has a pointer to a linked list of these. */struct stack_item_type { fullinfo_type item; struct stack_item_type *next;};typedef struct context_type context_type;typedef struct instruction_data_type instruction_data_type;typedef struct stack_item_type stack_item_type;typedef struct register_info_type register_info_type;typedef struct stack_info_type stack_info_type;typedef struct mask_type mask_type;static void verify_method(context_type *context, CVMClassBlock *cb, CVMMethodBlock *mb);#if 0 /* See comment in verify_field(). */static void verify_field(context_type *context, CVMClassBlock *cb, CVMFieldBlock *fb);#endifstatic void verify_opcode_operands (context_type *, int inumber, int offset);static void set_protected(context_type *, int inumber, int key, opcode_type);static jboolean is_superclass(context_type *, fullinfo_type);static void initialize_exception_table(context_type *);static jboolean isLegalTarget(context_type *, int offset);static void verify_constant_pool_type(context_type *, int, unsigned);static void initialize_dataflow(context_type *);static void run_dataflow(context_type *context);static void check_register_values(context_type *context, int inumber);static void check_flags(context_type *context, int inumber);static void pop_stack(context_type *, int inumber, stack_info_type *);static void update_registers(context_type *, int inumber, register_info_type *);static void update_flags(context_type *, int inumber, flag_type *new_and_flags, flag_type *new_or_flags);static void push_stack(context_type *, int inumber, stack_info_type *stack);static void merge_into_successors(context_type *, int inumber, register_info_type *register_info, stack_info_type *stack_info, flag_type and_flags, flag_type or_flags);static void merge_into_one_successor(context_type *context, int from_inumber, int inumber, register_info_type *register_info, stack_info_type *stack_info, flag_type and_flags, flag_type or_flags, jboolean isException);static void merge_stack(context_type *, int inumber, int to_inumber, stack_info_type *);static void merge_registers(context_type *, int inumber, int to_inumber, register_info_type *);static void merge_flags(context_type *context, int from_inumber, int to_inumber, flag_type new_and_flags, flag_type new_or_flags);static stack_item_type *copy_stack(context_type *, stack_item_type *);static mask_type *copy_masks(context_type *, mask_type *masks, int mask_count);static mask_type *add_to_masks(context_type *, mask_type *, int , int);static fullinfo_type decrement_indirection(fullinfo_type);static fullinfo_type merge_fullinfo_types(context_type *context, fullinfo_type a, fullinfo_type b, jboolean assignment);static jboolean isAssignableTo(context_type *, fullinfo_type a, fullinfo_type b);static CVMClassBlock *object_fullinfo_to_classclass(context_type *, fullinfo_type);#define NEW(type, count) \ ((type *)CCalloc(context, (count)*(sizeof(type)), JNI_FALSE))#define ZNEW(type, count) \ ((type *)CCalloc(context, (count)*(sizeof(type)), JNI_TRUE))static void CCinit(context_type *context);static void CCreinit(context_type *context);static void CCdestroy(context_type *context);static void *CCalloc(context_type *context, int size, jboolean zero);static fullinfo_type cp_index_to_class_fullinfo(context_type *, int, int);static char signature_to_fieldtype(context_type *context, CVMFieldTypeID fieldID, fullinfo_type *info);static void CCerror (context_type *, char *format, ...);static void CCout_of_memory (context_type *);#ifdef CVM_TRACEstatic void print_stack (context_type *, stack_info_type *stack_info);static void print_registers(context_type *, register_info_type *register_info);static void print_flags(context_type *, flag_type, flag_type);static void print_formatted_fieldname(context_type *context, int index);static void print_formatted_methodname(context_type *context, int index);#endifstatic void initialize_class_hash(context_type *context) { hash_table_type *class_hash = &(context->class_hash); class_hash->buckets = (hash_bucket_type **) calloc(MAX_HASH_ENTRIES / HASH_ROW_SIZE, sizeof(hash_bucket_type *)); class_hash->table = (unsigned short *) calloc(HASH_TABLE_SIZE, sizeof(unsigned short)); if (class_hash->buckets == 0 || class_hash->table == 0) CCout_of_memory(context); class_hash->entries_used = 0;}static void finalize_class_hash(context_type *context){ hash_table_type *class_hash = &(context->class_hash); int i; if (class_hash->buckets) { for (i=0;i<MAX_HASH_ENTRIES / HASH_ROW_SIZE; i++) { if (class_hash->buckets[i] == 0) break; free(class_hash->buckets[i]); } } free(class_hash->buckets); free(class_hash->table);}static hash_bucket_type * new_bucket(context_type *context, unsigned short *pID){ hash_table_type *class_hash = &(context->class_hash); int i = *pID = class_hash->entries_used + 1; int row = i / HASH_ROW_SIZE; if (i >= MAX_HASH_ENTRIES) CCerror(context, "Exceeded verifier's limit of 65535 referred classes"); if (class_hash->buckets[row] == 0) { class_hash->buckets[row] = (hash_bucket_type*) calloc(HASH_ROW_SIZE, sizeof(hash_bucket_type)); if (class_hash->buckets[row] == 0) CCout_of_memory(context); } class_hash->entries_used++; /* only increment when we are sure there is no overflow. */ return GET_BUCKET(class_hash, i);}/* * Find a class using the defining loader of the current class * and return a local reference to it. */static CVMClassBlock*load_class_local(context_type *context, CVMClassTypeID classname){ CVMClassBlock *cb = CVMclassLookupByTypeFromClass(context->ee, classname, CVM_FALSE, context->class); if (cb == 0) CCerror(context, "Cannot find class %!C", classname); return cb;} /* * Find a class using the defining loader of the current class * and return a global reference to it. */static CVMClassBlock *load_class_global(context_type *context, CVMClassTypeID classname){ return load_class_local(context, classname);} /* * Return a unique ID given a local class reference. The loadable * flag is true if the defining class loader of context->class * is known to be capable of loading the class. */static int class_to_ID(context_type *context, CVMClassBlock *cb, jboolean loadable){ hash_table_type *class_hash = &(context->class_hash); unsigned int hash; hash_bucket_type *bucket; unsigned short *pID; CVMClassTypeID name = CVMcbClassName(cb); hash = name; pID = &(class_hash->table[hash % HASH_TABLE_SIZE]); while (*pID) { bucket = GET_BUCKET(class_hash, *pID); if (name == bucket->name) { /* * There is an unresolved entry with our name * so we're forced to load it in case it matches us. */ if (bucket->class == 0) { CVMassert(bucket->loadable == JNI_TRUE); bucket->class = load_class_global(context, name); } /* * It's already in the table. Update the loadable * state if it's known and then we're done. */ if (cb == bucket->class) { if (loadable && !bucket->loadable) bucket->loadable = JNI_TRUE; goto done; } } pID = &bucket->next; } bucket = new_bucket(context, pID); bucket->next = 0; bucket->name = name; bucket->loadable = loadable; bucket->class = cb;done: return *pID;}/* * Return a unique ID given a class name from the constant pool. * All classes are lazily loaded from the defining loader of * context->class. */static int class_name_to_ID(context_type *context, CVMClassTypeID name){ hash_table_type *class_hash = &(context->class_hash); unsigned int hash = name; hash_bucket_type *bucket; unsigned short *pID; jboolean force_load = JNI_FALSE; CVMassert(name == CVMtypeidGetType(name)); pID = &(class_hash->table[hash % HASH_TABLE_SIZE]); while (*pID) { bucket = GET_BUCKET(class_hash, *pID); if (name == bucket->name) { if (bucket->loadable) goto done; force_load = JNI_TRUE; } pID = &bucket->next; } if (force_load) { /* * We found at least one matching named entry for a class that * was not known to be loadable through the defining class loader * of context->class. We must load our named class and update * the hash table in case one these entries matches our class. */ CVMClassBlock *cb = load_class_local(context, name); int id = class_to_ID(context, cb, JNI_TRUE); return id; } bucket = new_bucket(context, pID); bucket->next = 0; bucket->class = 0; bucket->loadable = JNI_TRUE; /* name-only IDs are implicitly loadable */ bucket->name = name;done: return *pID;}#ifdef CVM_TRACEstatic CVMClassTypeIDID_to_class_name(context_type *context, int ID){ hash_table_type *class_hash = &(context->class_hash); hash_bucket_type *bucket = GET_BUCKET(class_hash, ID); return bucket->name;}#endifstatic CVMClassBlock *ID_to_class(context_type *context, int ID){ hash_table_type *class_hash = &(context->class_hash); hash_bucket_type *bucket = GET_BUCKET(class_hash, ID); if (bucket->class == 0) { CVMassert(bucket->loadable == JNI_TRUE); bucket->class = load_class_global(context, bucket->name); } return bucket->class;}static fullinfo_type make_loadable_class_info(context_type *context, CVMClassBlock *cb){ return MAKE_FULLINFO(ITEM_Object, 0, class_to_ID(context, cb, JNI_TRUE));}static fullinfo_type make_class_info(context_type *context, CVMClassBlock *cb){ return MAKE_FULLINFO(ITEM_Object, 0, class_to_ID(context, cb, JNI_FALSE));}static fullinfo_typemake_class_info_from_name(context_type *context, CVMClassTypeID name){ return MAKE_FULLINFO(ITEM_Object, 0, class_name_to_ID(context, name));}/* * Called by CVMclassVerify. Verify the code of each of the methods * in a class. */jbooleanVerifyClass(CVMExecEnv *ee, CVMClassBlock *cb, char *buffer, jint len){ context_type *context = (context_type *)malloc(sizeof(context_type)); jboolean result = JNI_TRUE; int i; if (context == NULL) { jio_snprintf(buffer, len, "(class: %C) Out Of Memory", cb); return JNI_FALSE; } memset(context, 0, sizeof(context_type)); context->major_version = cb->major_version; context->message = buffer; context->message_buf_len = len; context->ee = ee; context->class = cb; /* Set invalid method/field index of the context, in case anyone calls CCerror */ context->mb = 0;#if 0 /* See comment in verify_field(). */ context->fb = 0;#endif /* Don't call CCerror or anything that can call it above the setjmp! */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?