📄 loader.c
字号:
} } END_TEMPORARY_ROOTS return bytesRead;}/*========================================================================= * FUNCTION: loadMethodAttributes() * TYPE: private class file load operation * OVERVIEW: Load the "Code" and "Exceptions" attributes * of a method in a class file, ignoring all the * other possible method attributes. * INTERFACE: * parameters: classfile pointer, constant pool pointer, * method attribute count, pointer to the runtime method struct * returns: <nothing> *=======================================================================*/static unsigned int loadCodeAttribute(FILEPOINTER_HANDLE ClassFileH, METHOD_HANDLE thisMethodH, POINTERLIST_HANDLE StringPoolH){ unsigned int actualAttrLength; unsigned int codeLength; int nCodeAttrs; int codeAttrIndex; BYTE *code; bool_t needStackMap = TRUE; METHOD thisMethod = unhand(thisMethodH); /* Create a code object and store it in the method */ thisMethod->u.java.maxStack = loadShort(ClassFileH); /* max stack */ thisMethod->frameSize = loadShort(ClassFileH); /* frame size */ codeLength = loadCell(ClassFileH); /* Code length */ if (codeLength >= 0x7FFF) { fatalError(KVM_MSG_METHOD_LONGER_THAN_32KB); } if (thisMethod->u.java.maxStack + thisMethod->frameSize > MAXIMUM_STACK_AND_LOCALS) { fatalError(KVM_MSG_TOO_MANY_LOCALS_AND_STACK); } /* Allocate memory for storing the bytecode array */ if (USESTATIC && !ENABLEFASTBYTECODES) { code = (BYTE *)mallocBytes(codeLength); } else { code = (BYTE *)callocPermanentObject(ByteSizeToCellSize(codeLength)); } thisMethod = unhand(thisMethodH); thisMethod->u.java.code = code; thisMethod->u.java.codeLength = codeLength; loadBytes(ClassFileH, (char *)thisMethod->u.java.code, codeLength); actualAttrLength = 2 + 2 + 4 + codeLength; /* Load exception handlers associated with the method */ actualAttrLength += loadExceptionHandlers(ClassFileH, thisMethodH); nCodeAttrs = loadShort(ClassFileH); actualAttrLength += 2; for (codeAttrIndex = 0; codeAttrIndex < nCodeAttrs; codeAttrIndex++) { unsigned short codeAttrNameIndex = loadShort(ClassFileH); unsigned int codeAttrLength = loadCell(ClassFileH); char* codeAttrName = getUTF8String(StringPoolH, codeAttrNameIndex); /* Check if the attribute contains stack maps */ if (!strcmp(codeAttrName, "StackMap")) { unsigned int stackMapAttrSize; if (!needStackMap) { fatalError(KVM_MSG_DUPLICATE_STACKMAP_ATTRIBUTE); } needStackMap = FALSE; stackMapAttrSize = loadStackMaps(ClassFileH, thisMethodH); if (stackMapAttrSize != codeAttrLength) { fatalError(KVM_MSG_BAD_ATTRIBUTE_SIZE); } } else { skipBytes(ClassFileH, codeAttrLength); } actualAttrLength += 6 + codeAttrLength; } return actualAttrLength;}static void loadMethodAttributes(FILEPOINTER_HANDLE ClassFileH, METHOD_HANDLE thisMethodH, POINTERLIST_HANDLE StringPoolH){ unsigned short attrCount = loadShort(ClassFileH); METHOD thisMethod = unhand(thisMethodH); int attrIndex; bool_t needCode = !(thisMethod->accessFlags & (ACC_NATIVE | ACC_ABSTRACT)); bool_t needExceptionTable = TRUE; /* always optional */ /* See if the field has any attributes in the class file */ for (attrIndex = 0; attrIndex < attrCount; attrIndex++) { unsigned short attrNameIndex = loadShort(ClassFileH); unsigned int attrLength = loadCell(ClassFileH); char* attrName = getUTF8String(StringPoolH, attrNameIndex); /* Check if the attribute contains source code */ if (strcmp(attrName, "Code") == 0) { unsigned int actualLength; if (!needCode) { fatalError(KVM_MSG_DUPLICATE_CODE_ATTRIBUTE); } actualLength = loadCodeAttribute(ClassFileH, thisMethodH, StringPoolH); if (actualLength != attrLength) { fatalError(KVM_MSG_BAD_CODE_ATTRIBUTE_LENGTH); } needCode = FALSE; } else if (!strcmp(attrName, "Exceptions")) { /* Do minimal checking of this attribute. */ unsigned int exceptionCount; unsigned int i; if (!needExceptionTable) { fatalError(KVM_MSG_DUPLICATE_EXCEPTION_TABLE); } needExceptionTable = FALSE; exceptionCount = loadShort(ClassFileH); if (2 * exceptionCount + 2 != attrLength) { fatalError(KVM_MSG_BAD_EXCEPTION_ATTRIBUTE); } for (i = 0; i < exceptionCount; i++) { unsigned short exception = loadShort(ClassFileH); if (exception != 0) { verifyConstantPoolEntry(unhand(thisMethodH)->ofClass, exception, CONSTANT_Class); } } } else { /* Unrecognized attribute; skip */ skipBytes(ClassFileH, attrLength); } } if (needCode) { fatalError(KVM_MSG_MISSING_CODE_ATTRIBUTE); }}/*========================================================================= * FUNCTION: loadMethods() * TYPE: private class file load operation * OVERVIEW: Load the methods defined in a Java class file. * INTERFACE: * parameters: classfile pointer, current class pointer * returns: <nothing> *=======================================================================*/static voidloadOneMethod(FILEPOINTER_HANDLE ClassFileH, INSTANCE_CLASS CurrentClass, METHOD_HANDLE thisMethodH, POINTERLIST_HANDLE StringPoolH) { METHOD thisMethod; unsigned short accessFlags = loadShort(ClassFileH) & RECOGNIZED_METHOD_FLAGS; unsigned short nameIndex = loadShort(ClassFileH); unsigned short typeIndex = loadShort(ClassFileH); START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(const char *, methodName, getUTF8String(StringPoolH, nameIndex)); DECLARE_TEMPORARY_ROOT(const char *, signature, getUTF8String(StringPoolH, typeIndex)); NameTypeKey result; if (strcmp(methodName, "<clinit>") == 0) { accessFlags = ACC_STATIC; } else { verifyMethodFlags(accessFlags, CurrentClass->clazz.accessFlags, methodName); } verifyName(methodName, LegalMethod, TRUE); result.nt.nameKey = change_Name_to_Key(&methodName, 0, strlen(methodName)); result.nt.typeKey = change_MethodSignature_to_Key(&signature, 0, strlen(signature)); ASSERTING_NO_ALLOCATION thisMethod = unhand(thisMethodH); thisMethod->nameTypeKey = result; thisMethod->argCount = verifyMethodType(methodName, signature); /* If this is a virtual method, increment argument counter */ if (!(accessFlags & ACC_STATIC)) { thisMethod->argCount++; } if (thisMethod->argCount > 255) { fatalError(KVM_MSG_TOO_MANY_METHOD_ARGUMENTS); }#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Method '%s' loaded\n", methodName); }#endif /* INCLUDEDEBUGCODE */ /* Check if the field is double length, or is a pointer type. If so * set the appropriate bit in the word */ switch (strchr(signature, ')')[1]) { case 'D': case 'J': accessFlags |= ACC_DOUBLE; break; case 'L': case '[': accessFlags |= ACC_POINTER; break; case 'V': accessFlags |= (ACC_POINTER | ACC_DOUBLE); break; } thisMethod->accessFlags = accessFlags; thisMethod->ofClass = CurrentClass; /* These values will be initialized later */ thisMethod->frameSize = 0; thisMethod->u.java.maxStack = 0; thisMethod->u.java.handlers = NIL; END_ASSERTING_NO_ALLOCATION loadMethodAttributes(ClassFileH, thisMethodH, StringPoolH); /* Garbage collection may have happened */ thisMethod = unhand(thisMethodH); if (!(thisMethod->accessFlags & (ACC_NATIVE | ACC_ABSTRACT))) { if ( thisMethod->frameSize < thisMethod->argCount) { fatalError(KVM_MSG_BAD_FRAME_SIZE); } } if (accessFlags & ACC_NATIVE) { /* Store native function pointer in the code field */ thisMethod->u.native.info = NULL; thisMethod->u.native.code = getNativeFunction(CurrentClass, methodName, signature); } END_TEMPORARY_ROOTS} static void loadMethods(FILEPOINTER_HANDLE ClassFileH, INSTANCE_CLASS CurrentClass, POINTERLIST_HANDLE StringPoolH){ unsigned short methodCount = loadShort(ClassFileH); if (methodCount == 0) { return; } START_TEMPORARY_ROOTS int tableSize = SIZEOF_METHODTABLE(methodCount); unsigned int index;#if USESTATIC DECLARE_TEMPORARY_ROOT(METHODTABLE, methodTable, (METHODTABLE)callocObject(tableSize, GCT_METHODTABLE));#else METHODTABLE methodTable = (METHODTABLE)callocPermanentObject(tableSize);#endif methodTable->length = methodCount; CurrentClass->methodTable = methodTable;#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Loading methods\n"); }#endif /* INCLUDEDEBUGCODE */ for (index = 0; index < methodCount; index++) { #if USESTATIC START_TEMPORARY_ROOTS DECLARE_TEMPORARY_METHOD_ROOT(thisMethod, methodTable, index); loadOneMethod(ClassFileH, CurrentClass, &thisMethod, StringPoolH); END_TEMPORARY_ROOTS#else METHOD thisMethod = &methodTable->methods[index]; loadOneMethod(ClassFileH, CurrentClass, &thisMethod, StringPoolH);#endif } END_TEMPORARY_ROOTS if (methodCount >= 2) { /* Check to see if there are two methods with the same name/type */ METHODTABLE methodTable = CurrentClass->methodTable; METHOD firstMethod = &methodTable->methods[0]; METHOD lastMethod = firstMethod + (methodCount - 1); METHOD outer, inner; for (outer = firstMethod; outer < lastMethod; outer++) { for (inner = outer + 1; inner <= lastMethod; inner++) { if (outer->nameTypeKey.i == inner->nameTypeKey.i) { fatalError(KVM_MSG_DUPLICATE_METHOD_FOUND); } } } }#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Methods loaded ok\n"); }#endif /* INCLUDEDEBUGCODE */}/*========================================================================= * FUNCTION: ignoreAttributes() * TYPE: private class file load operation * OVERVIEW: Load the possible extra attributes (e.g., the * "SourceFile" attribute) supplied in a Java class file. * The current implementation ignores all these attributes. * INTERFACE: * parameters: classfile pointer, current class pointer * returns: <nothing> *=======================================================================*/static void ignoreAttributes(FILEPOINTER_HANDLE ClassFileH, POINTERLIST_HANDLE StringPoolH){ unsigned short attrCount = loadShort(ClassFileH); int attrIndex; #if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Loading extra attributes\n"); }#endif /* INCLUDEDEBUGCODE */ for (attrIndex = 0; attrIndex < attrCount; attrIndex++) { unsigned short attrNameIndex = loadShort(ClassFileH); unsigned int attrLength = loadCell(ClassFileH); /* This verifies that the attribute index is legitimate */ (void)getUTF8String(StringPoolH, attrNameIndex); skipBytes(ClassFileH, attrLength); }#if INCLUDEDEBUGCODE if (traceclassloadingverbose) fprintf(stdout, "Extra attributes loaded\n");#endif /* INCLUDEDEBUGCODE */}/*===================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -