📄 loader.c
字号:
* parameters: field access flags, isInterface * returns: nothing *=======================================================================*/static void verifyFieldFlags(unsigned short flags, unsigned short classFlags){ if ((classFlags & ACC_INTERFACE) == 0) { /* Class or instance fields */ int accessFlags = flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED); /* Make sure that accessFlags has one of the four legal values, by * looking it up in a bit mask */ if (( (1 << accessFlags) & ((1 << 0) + (1 << ACC_PUBLIC) + (1 << ACC_PRIVATE) + (1 << ACC_PROTECTED))) == 0) { goto failed; } if ((flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE)){ /* A field can't be both final and volatile */ goto failed; } } else { /* interface fields */ if (flags != (ACC_STATIC | ACC_FINAL | ACC_PUBLIC)) { goto failed; } } return; failed: fatalError(KVM_MSG_BAD_FIELD_ACCESS_FLAGS);}/*========================================================================= * FUNCTION: verifyFieldType() * TYPE: private class file load operation * OVERVIEW: validate field signature * INTERFACE: * parameters: field signature * returns: nothing *=======================================================================*/static void verifyFieldType(const char* type){ unsigned short length = (unsigned short)strlen(type); const char *p = skipOverFieldType(type, FALSE, length); if (p == NULL || p - type != length) { fatalError(KVM_MSG_BAD_FIELD_SIGNATURE); }}/*========================================================================= * FUNCTION: verifyMethodFlags() * TYPE: private class file load operation * OVERVIEW: validate method access flags * INTERFACE: * parameters: method access flags, isInterface, methodName * returns: nothing *=======================================================================*/static void verifyMethodFlags(unsigned short flags, unsigned short classFlags, const char* name){ /* These are all small bits. The value is between 0 and 7. */ int accessFlags = flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED); /* Make sure that accessFlags has one of the four legal values, by * looking it up in a bit mask */ if (( (1 << accessFlags) & ((1 << 0) | (1 << ACC_PUBLIC) | (1 << ACC_PRIVATE) | (1 << ACC_PROTECTED))) == 0) { goto failed; } if ((classFlags & ACC_INTERFACE) == 0) { /* class or instance methods */ if (flags & ACC_ABSTRACT) { if (flags & (ACC_FINAL | ACC_NATIVE | ACC_SYNCHRONIZED | ACC_PRIVATE | ACC_STATIC)) { goto failed; } } } else { /* interface methods */ if ( (flags & (ACC_ABSTRACT | ACC_PUBLIC | ACC_STATIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) { /* Note that <clinit> is special, and not handled by this * function. It's not abstract, and static. */ goto failed; } } if (strcmp(name, "<init>") == 0) { if (flags & ~(ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE)) goto failed; } return; failed: fatalError(KVM_MSG_BAD_METHOD_ACCESS_FLAGS);}/*========================================================================= * FUNCTION: verifyMethodType() * TYPE: private class file load operation * OVERVIEW: validate method signature * INTERFACE: * parameters: method name, signature * returns: argument size *=======================================================================*/static unsigned shortverifyMethodType(const char *name, const char* signature){ unsigned short args_size = 0; const char *p = signature; unsigned short length = (unsigned short)strlen(signature); const char *next_p; /* The first character must be a '(' */ if ((length > 0) && (*p++ == '(')) { length--; /* Skip over however many legal field signatures there are */ while ((length > 0) && (next_p = skipOverFieldType(p, FALSE, length))) { args_size++; if (p[0] == 'J' || p[0] == 'D') args_size++; length -= (next_p - p); p = next_p; } /* The first non-signature thing better be a ')' */ if ((length > 0) && (*p++ == ')')) { length --; if (strlen(name) > 0 && name[0] == '<') { /* All internal methods must return void */ if ((length == 1) && (p[0] == 'V')) return args_size; } else { /* Now, we better just have a return value. */ next_p = skipOverFieldType(p, TRUE, length); if (next_p && (length == next_p - p)) return args_size; } } } fatalError(KVM_MSG_BAD_METHOD_SIGNATURE); return 0; /* never reached */}/*========================================================================= * FUNCTION: verifyConstantPoolEntry() * TYPE: private class file load operation * OVERVIEW: validate constant pool index * INTERFACE: * parameters: constant pool, index, and expected tag * returns: nothing *=======================================================================*/static voidverifyConstantPoolEntry(INSTANCE_CLASS CurrentClass, unsigned short index, unsigned char tag){ CONSTANTPOOL ConstantPool = CurrentClass->constPool; unsigned short length = (unsigned short)CONSTANTPOOL_LENGTH(ConstantPool); unsigned char tag2 = CONSTANTPOOL_TAGS(ConstantPool)[index]; if (index >= length || tag2 != tag) { fatalError(KVM_MSG_BAD_CONSTANT_INDEX); }}/*========================================================================= * Class loading operations *=======================================================================*//*========================================================================= * FUNCTION: loadVersionInfo() * TYPE: private class file load operation * OVERVIEW: Load the first few bytes of a Java class file, * checking the file type and version information. * INTERFACE: * parameters: classfile pointer * returns: <nothing> *=======================================================================*/static void loadVersionInfo(FILEPOINTER_HANDLE ClassFileH){ UNUSEDPARAMETER(CurrentClass) long magic;#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Loading version information\n"); }#endif /* INCLUDEDEBUGCODE */ magic = loadCell(ClassFileH); if (magic != 0xCAFEBABE) { /* This should actually be an exception rather than a fatal error */ /* but it is unlikely that we would be able to continue execution */ fatalError(KVM_MSG_NOT_A_JAVA_CLASSFILE); } skipBytes(ClassFileH, 4); /* ignore minorVersion and majorVersion */}/*========================================================================= * FUNCTION: loadConstantPool() * TYPE: private class file load operation * OVERVIEW: Load the constant pool part of a Java class file, * building the runtime class constant pool structure * during the loading process. * INTERFACE: * parameters: classfile pointer * returns: constant pool pointer *=======================================================================*/static POINTERLISTloadConstantPool(FILEPOINTER_HANDLE ClassFileH, INSTANCE_CLASS CurrentClass){ unsigned short constantCount = loadShort(ClassFileH); CONSTANTPOOL ConstantPool; int cpIndex; POINTERLIST result; int lastNonUtfIndex = -1;#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Loading constant pool\n"); }#endif /* INCLUDEDEBUGCODE */ START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(CONSTANTPOOL_ENTRY, RawPool, (CONSTANTPOOL_ENTRY)mallocBytes(constantCount * (1 + sizeof(*RawPool)))); DECLARE_TEMPORARY_ROOT(POINTERLIST, StringPool, (POINTERLIST)callocObject(SIZEOF_POINTERLIST(constantCount), GCT_POINTERLIST)); StringPool->length = constantCount;#define RAW_POOL(i) (RawPool[i])#define CP_ENTRY(i) (ConstantPool->entries[i]) /* Read the constant pool entries from the class file */ for (cpIndex = 1; cpIndex < constantCount; cpIndex++) { unsigned char tag = loadByte(ClassFileH); unsigned char *Tags = (unsigned char *)(&RawPool[constantCount]); Tags[cpIndex] = tag; switch (tag) { case CONSTANT_String: case CONSTANT_Class: { /* A single 16-bit entry that points to a UTF string */ unsigned short nameIndex = loadShort(ClassFileH); RAW_POOL(cpIndex).integer = nameIndex; break; } case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: { /* Two 16-bit entries */ unsigned short classIndex = loadShort(ClassFileH); unsigned short nameTypeIndex = loadShort(ClassFileH); RAW_POOL(cpIndex).method.classIndex = classIndex; RAW_POOL(cpIndex).method.nameTypeIndex = nameTypeIndex; break; } case CONSTANT_Float: #if !IMPLEMENTS_FLOAT fatalError(KVM_MSG_FLOATING_POINT_NOT_SUPPORTED);#endif case CONSTANT_Integer: { /* A signal 32-bit value */ long value = loadCell(ClassFileH); RAW_POOL(cpIndex).integer = value; break; } case CONSTANT_Double:#if !IMPLEMENTS_FLOAT fatalError(KVM_MSG_FLOATING_POINT_NOT_SUPPORTED);#endif case CONSTANT_Long: /* A 64-bit value */ RAW_POOL(cpIndex).integer = loadCell(ClassFileH); cpIndex++; if (cpIndex >= constantCount) { fatalError(KVM_MSG_BAD_64BIT_CONSTANT); } RAW_POOL(cpIndex).integer = loadCell(ClassFileH); break; case CONSTANT_NameAndType: { /* Like Fieldref, etc */ unsigned short nameIndex = loadShort(ClassFileH); unsigned short typeIndex = loadShort(ClassFileH); /* In the second pass, below, these will be replaced with the * actual nameKey and typeKey. Currently, they are indices * to items in the constant pool that may not yet have been * loaded */ RAW_POOL(cpIndex).nameTypeKey.nt.nameKey = nameIndex; RAW_POOL(cpIndex).nameTypeKey.nt.typeKey = typeIndex; break; } case CONSTANT_Utf8: { unsigned short length = loadShort(ClassFileH); /* This allocation may invalidate ClassFile */ char *string = mallocBytes(length + 1); STRING_POOL(cpIndex) = string; loadBytes(ClassFileH, string, length); string[length] = '\0'; verifyUTF8String(string, length); } break; default: fatalError(KVM_MSG_INVALID_CONSTANT_POOL_ENTRY); break; } if (tag != CONSTANT_Utf8) { lastNonUtfIndex = cpIndex; } } { int numberOfEntries = lastNonUtfIndex + 1; int tableSize = numberOfEntries + ((numberOfEntries + (CELL - 1)) >> log2CELL);#if USESTATIC IS_TEMPORARY_ROOT(ConstantPool,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -