📄 classloader.c
字号:
unsigned Signature2ArgsSize(char *method_signature){ char *p; int args_size = 0; for (p = method_signature; *p != SIGNATURE_ENDFUNC; p++) { switch (*p) { case SIGNATURE_FLOAT: if (no_floating_point) { panic("floating-point arguments should not appear"); } case SIGNATURE_BOOLEAN: case SIGNATURE_BYTE: case SIGNATURE_CHAR: case SIGNATURE_SHORT: case SIGNATURE_INT: args_size += 1; break; case SIGNATURE_CLASS: args_size += 1; while (*p != SIGNATURE_ENDCLASS) p++; break; case SIGNATURE_ARRAY: args_size += 1; while ((*p == SIGNATURE_ARRAY)) p++; /* If an array of classes, skip over class name, too. */ if (*p == SIGNATURE_CLASS) { while (*p != SIGNATURE_ENDCLASS) p++; } break; case SIGNATURE_DOUBLE: if (no_floating_point) { panic("floating-point arguments should not appear"); } case SIGNATURE_LONG: args_size += 2; break; case SIGNATURE_FUNC: /* ignore initial (, if given */ break; default: /* Indicates an error. */ return 0; } } return args_size;}/*========================================================================= * FUNCTION: free_clinit_memory * OVERVIEW: Frees clinit memory. * * INTERFACE: * parameters: struct methodblock *: mb * * returns: nothing *=======================================================================*/void free_clinit_memory(struct methodblock *mb){ /* This function is somewhat a hack. It fixes the problem in 1.1.3 * and before. sysFree may be called on the wrong memory block if * the exception attribute comes before the code attribute. */ /* If there is no exceptions attribute, or if both have already * been freed. */ if (mb->exceptions == NULL) { if (mb->code) { sysFree(mb->code); mb->code = NULL; } return; } /* If both attributes exist, free the one at the lower address */ if ((char *)mb->code < (char *)mb->exceptions) sysFree(mb->code); else sysFree(mb->exceptions); mb->code = NULL; mb->exceptions = NULL;}/*========================================================================= * FUNCTION: FreeClass * OVERVIEW: Frees class. * * INTERFACE: * parameters: ClassClass *: cb * * returns: nothing *=======================================================================*/void FreeClass(ClassClass *cb){ int i; struct methodblock *mb; for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) { if (strcmp(mb->fb.name, "<clinit>") == 0 && strcmp(mb->fb.signature, "()V") == 0 && mb->code_length /* not external */ ) free_clinit_memory(mb); } sysFree(cbConstantPool(cb)); sysFree(cbMethodTableMem(cb)); sysFree(cbSlotTable(cb)); /* Interface method tables can be shared between child and * super classes. */ if (cbImplementsCount(cb) != 0 || cbIsInterface(cb)) sysFree(cbIntfMethodTable(cb));}/*========================================================================= * FUNCTION: get1byte * OVERVIEW: Gets one byte from the class file. * * INTERFACE: * parameters: CICcontext *: context * * returns: value read or 0 if an error occurred. *=======================================================================*/static unsigned char get1byte(CICcontext *context){ unsigned char *ptr = context->ptr; if (context->end_ptr - ptr < 1) { JAVA_ERROR(context, "Truncated class file"); return 0; } else { unsigned char *ptr = context->ptr; unsigned char value = ptr[0]; (context->ptr) += 1; return value; }}/*========================================================================= * FUNCTION: get2bytes * OVERVIEW: Gets two bytes from the class file. * * INTERFACE: * parameters: CICcontext *: context * * returns: value read or 0 if an error occurred. *=======================================================================*/static unsigned short get2bytes(CICcontext *context){ unsigned char *ptr = context->ptr; if (context->end_ptr - ptr < 2) { JAVA_ERROR(context, "Truncated class file"); return 0; } else { unsigned short value = (ptr[0] << 8) + ptr[1]; (context->ptr) += 2; return value; }}/*========================================================================= * FUNCTION: get4bytes * OVERVIEW: Gets four bytes from the class file. * * INTERFACE: * parameters: CICcontext *: context * * returns: value read or 0 if an error occurred. *=======================================================================*/static unsigned long get4bytes(CICcontext *context){ unsigned char *ptr = context->ptr; if (context->end_ptr - ptr < 4) { JAVA_ERROR(context, "Truncated class file"); return 0; } else { unsigned long value = (ptr[0] << 24) + (ptr[1] << 16) + (ptr[2] << 8) + ptr[3]; (context->ptr) += 4; return value; }}/*========================================================================= * FUNCTION: getNbytes * OVERVIEW: Gets N bytes from the class file specified by the count * parameter. If buffer is not null, it will also copy the * count number of bytes read into the buffer as well. * Note that this function seems to be always invoked with * a NULL argument for the buffer, except when it loads the * UTF8 entry from the constant pool and when the code * attribute is loaded. * * INTERFACE: * parameters: CICcontext *: context * int: count * char *: buffer * * returns: nothing *=======================================================================*/static void getNbytes(CICcontext *context, int count, char *buffer){ unsigned char *ptr = context->ptr; if (context->end_ptr - ptr < count) JAVA_ERROR(context, "Truncated class file"); if (buffer != NULL) memcpy(buffer, ptr, count); (context->ptr) += count;}/*========================================================================= * FUNCTION: getAsciz * OVERVIEW: Reads the next two bytes and uses this value to look up for * the corresponding constant pool entry. * Returns null if the value is 0 and zeroOkay flag is set. * * INTERFACE: * parameters: CICcontext *: context * bool_t : zeroOkay * * returns: char * or NULL *=======================================================================*/static char *getAsciz(CICcontext *context, bool_t zeroOkay){ ClassClass *cb = context->cb; union cp_item_type *constant_pool = cbConstantPool(cb); int nconstants = cbConstantPoolCount(cb); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; int value = get2bytes(context); if (value == 0 && zeroOkay) { return NULL; } else if ((value == 0) || (value >= nconstants) || type_table[value] != (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED)) JAVA_ERROR(context, "Illegal constant pool index"); return constant_pool[value].cp;}/*========================================================================= * FUNCTION: getAscizFromClass * OVERVIEW: Given the constant pool index, returns the name of the class * which corresponds to this constant pool entry. * * INTERFACE: * parameters: CICcontext *: context * int: value * * returns: char * or NULL *=======================================================================*/static char *getAscizFromClass(CICcontext *context, int value){ ClassClass *cb = context->cb; union cp_item_type *constant_pool = cbConstantPool(cb); int nconstants = cbConstantPoolCount(cb); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; if ((value > 0) && (value < nconstants)) { if (type_table[value] == CONSTANT_Class) { value = constant_pool[value].i; if ((value <= 0) || (value >= nconstants) || (type_table[value] != (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED))) JAVA_ERROR(context, "Illegal constant pool index"); return constant_pool[value].cp; } else if (type_table[value] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED)) { ClassClass *cb = constant_pool[value].clazz; return cbName(cb); } else { JAVA_ERROR(context, "Illegal constant pool index"); } } else { JAVA_ERROR(context, "Illegal constant pool index"); } return NULL; /* not reached */}/* In order to avoid possible alignment errors, round up all sizes to * multiples of eight. */#define ROUNDUP_SIZE(s) while ((s) % 8 != 0) (s)++/*========================================================================= * FUNCTION: allocNBytes * OVERVIEW: Memory allocation function for internal class file * structures. * It calculates the number of allocations needed for the * two passes, and the allocations required for the clinit * method. * * INTERFACE: * parameters: CICcontext *: context * int : size * * returns: void * *=======================================================================*/static void *allocNBytes(CICcontext *context, int size){ void *result; if (context->pass == 1) { /* The first pass * A more sophisticated scheme could reduce the number of mallocs. */ CICmallocs *mallocs = (CICmallocs *)sysCalloc(1, sizeof(CICmallocs) + size); if (mallocs == 0) JAVA_ERROR(context, "out of memory"); result = (void *)(mallocs + 1); mallocs->next = context->pass1.mallocs; ROUNDUP_SIZE(size); if (context->in_clinit) context->clinit_size += size; else context->malloc_size += size; context->pass1.mallocs = mallocs; } else { /* The second pass */ ROUNDUP_SIZE(size);#define ALLOC_BLOCK(ptr,buf,sizelimit) \ result = (ptr); \ (ptr) += (size); \ sysAssert((ptr) <= (buf) + (sizelimit)) if (context->in_clinit) { /* Make sure that this clinit pointer is not null */ sysAssert(context->pass2.clinit_ptr != NULL); ALLOC_BLOCK(context->pass2.clinit_ptr, context->pass2.clinit_buffer, context->clinit_size*sizeof(char)); } else { /* Make sure that this malloc pointer is not null */ sysAssert(context->pass2.malloc_ptr != NULL); ALLOC_BLOCK(context->pass2.malloc_ptr, context->pass2.malloc_buffer, context->malloc_size); } } return result;}/*========================================================================= * FUNCTION: freeBuffers * OVERVIEW: Frees buffers allocated by allocNBytes(). * * INTERFACE: * parameters: CICcontext *: context * * returns: nothing *=======================================================================*/static void freeBuffers(CICcontext * context){ if (context->pass == 1) { CICmallocs *mallocs = context->pass1.mallocs; while (mallocs) { CICmallocs *tmp = mallocs; mallocs = mallocs->next; if (tmp != NULL) { sysFree(tmp); } } context->pass1.mallocs = 0; } else { /* context->pass = 2 *//* Note: this code is here just for historical reasons. Actually, these * buffers cannot really be freed here since the data in them is still * pointed to by the class buffer (cb) and we are not yet done loading * the class. If the class loading fails, FreeClass() will free the method * blocks and the clinit memory. */ if (context->pass2.malloc_buffer != NULL) { sysFree(context->pass2.malloc_buffer); /* Reset only if buffer was freed */ context->pass2.malloc_buffer = 0; } if (context->pass2.clinit_buffer != NULL) { sysFree(context->pass2.clinit_buffer); /* Initialize only if buffer was freed */ context->pass2.clinit_buffer = 0; } }}/*========================================================================= * FUNCTION: GetClassConstantClassName * OVERVIEW: Returns class name corresponding to the constant pool entry * for the given cpIndex. This is desirable in cases when we * may simply be interested in the name of the class, but may * not necessarily want to resolve the class reference if it * isn't already. * * INTERFACE: * parameters: cp_item_type *: constant pool * int : index * * returns: char *: class name *=======================================================================*/char *GetClassConstantClassName(cp_item_type *constant_pool, int index){ unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; switch(type_table[index]) { case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED: { ClassClass *cb = constant_pool[index].clazz; return cbName(cb); } case CONSTANT_Class: { int name_index = constant_pool[index].i; return constant_pool[name_index].cp; } default: return (char *)0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -