📄 loader.c
字号:
/*0270*/
/*0271*//*=========================================================================
/*0272./ * FUNCTION: verifyName()
/*0273./ * TYPE: private class file load operation
/*0274./ * OVERVIEW: validate a class, field, or method name
/*0275./ * INTERFACE:
/*0276./ * parameters: pointer to a name, name type
/*0277./ * returns: nothing
/*0278./ *=======================================================================*/
/*0279*/
/*0280*/bool_t
/*0281*/verifyName(const char* name, enum verifyName_type type, bool_t abortOnError)
/*0282*/{
/*0283*/ bool_t result;
/*0284*/ unsigned short length = (unsigned short)strlen(name);
/*0285*/
/*0286*/ if (length > 0) {
/*0287*/ if (name[0] == '<') {
/*0288*/ result = (type == LegalMethod) &&
/*0289*/ ((strcmp(name, "<init>") == 0) ||
/*0290*/ (strcmp(name, "<clinit>") == 0));
/*0291*/ } else {
/*0292*/ const char *p;
/*0293*/ if (type == LegalClass && name[0] == '[') {
/*0294*/ p = skipOverFieldType(name, FALSE, length);
/*0295*/ } else {
/*0296*/ p = skipOverFieldName(name,
/*0297*/ type == LegalClass,
/*0298*/ length);
/*0299*/ }
/*0300*/ result = (p != NULL) && (p - name == length);
/*0301*/ }
/*0302*/ } else {
/*0303*/ result = FALSE;
/*0304*/ }
/*0305*/ if (!result && abortOnError) {
/*0306*/ fatalError(KVM_MSG_BAD_NAME);
/*0307*/ }
/*0308*/ return result;
/*0309*/}
/*0310*/
/*0311*//*=========================================================================
/*0312./ * FUNCTION: verifyClassFlags()
/*0313./ * TYPE: private class file load operation
/*0314./ * OVERVIEW: validate class access flags
/*0315./ * INTERFACE:
/*0316./ * parameters: class access flags
/*0317./ * returns: nothing
/*0318./ *=======================================================================*/
/*0319*/
/*0320*/static void
/*0321*/verifyClassFlags(unsigned short flags)
/*0322*/{
/*0323*/ if (flags & ACC_INTERFACE) {
/*0324*/ if ((flags & ACC_ABSTRACT) == 0)
/*0325*/ goto failed;
/*0326*/ if (flags & ACC_FINAL)
/*0327*/ goto failed;
/*0328*/ } else {
/*0329*/ if ((flags & ACC_FINAL) && (flags & ACC_ABSTRACT))
/*0330*/ goto failed;
/*0331*/ }
/*0332*/ return;
/*0333*/
/*0334*/ failed:
/*0335*/ fatalError(KVM_MSG_BAD_CLASS_ACCESS_FLAGS);
/*0336*/}
/*0337*/
/*0338*//*=========================================================================
/*0339./ * FUNCTION: verifyFieldFlags()
/*0340./ * TYPE: private class file load operation
/*0341./ * OVERVIEW: validate field access flags
/*0342./ * INTERFACE:
/*0343./ * parameters: field access flags, isInterface
/*0344./ * returns: nothing
/*0345./ *=======================================================================*/
/*0346*/
/*0347*/static void
/*0348*/verifyFieldFlags(unsigned short flags, unsigned short classFlags)
/*0349*/{
/*0350*/ if ((classFlags & ACC_INTERFACE) == 0) {
/*0351*/ /* Class or instance fields */
/*0352*/ int accessFlags = flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
/*0353*/
/*0354*/ /* Make sure that accessFlags has one of the four legal values, by
/*0355./ * looking it up in a bit mask */
/*0356*/ if (( (1 << accessFlags) & ((1 << 0) + (1 << ACC_PUBLIC)
/*0357*/ + (1 << ACC_PRIVATE) + (1 << ACC_PROTECTED))) == 0) {
/*0358*/ goto failed;
/*0359*/ }
/*0360*/
/*0361*/ if ((flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE)){
/*0362*/ /* A field can't be both final and volatile */
/*0363*/ goto failed;
/*0364*/ }
/*0365*/ } else {
/*0366*/ /* interface fields */
/*0367*/ if (flags != (ACC_STATIC | ACC_FINAL | ACC_PUBLIC)) {
/*0368*/ goto failed;
/*0369*/ }
/*0370*/ }
/*0371*/ return;
/*0372*/
/*0373*/ failed:
/*0374*/ fatalError(KVM_MSG_BAD_FIELD_ACCESS_FLAGS);
/*0375*/}
/*0376*/
/*0377*//*=========================================================================
/*0378./ * FUNCTION: verifyFieldType()
/*0379./ * TYPE: private class file load operation
/*0380./ * OVERVIEW: validate field signature
/*0381./ * INTERFACE:
/*0382./ * parameters: field signature
/*0383./ * returns: nothing
/*0384./ *=======================================================================*/
/*0385*/
/*0386*/static void
/*0387*/verifyFieldType(const char* type)
/*0388*/{
/*0389*/ unsigned short length = (unsigned short)strlen(type);
/*0390*/ const char *p = skipOverFieldType(type, FALSE, length);
/*0391*/
/*0392*/ if (p == NULL || p - type != length) {
/*0393*/ fatalError(KVM_MSG_BAD_FIELD_SIGNATURE);
/*0394*/ }
/*0395*/}
/*0396*/
/*0397*//*=========================================================================
/*0398./ * FUNCTION: verifyMethodFlags()
/*0399./ * TYPE: private class file load operation
/*0400./ * OVERVIEW: validate method access flags
/*0401./ * INTERFACE:
/*0402./ * parameters: method access flags, isInterface, methodName
/*0403./ * returns: nothing
/*0404./ *=======================================================================*/
/*0405*/
/*0406*/static void
/*0407*/verifyMethodFlags(unsigned short flags, unsigned short classFlags,
/*0408*/ const char* name)
/*0409*/{
/*0410*/ /* These are all small bits. The value is between 0 and 7. */
/*0411*/ int accessFlags = flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
/*0412*/
/*0413*/ /* Make sure that accessFlags has one of the four legal values, by
/*0414./ * looking it up in a bit mask */
/*0415*/
/*0416*/ if (( (1 << accessFlags)
/*0417*/ & ((1 << 0)
/*0418*/ | (1 << ACC_PUBLIC)
/*0419*/ | (1 << ACC_PRIVATE) | (1 << ACC_PROTECTED))) == 0) {
/*0420*/ goto failed;
/*0421*/ }
/*0422*/
/*0423*/ if ((classFlags & ACC_INTERFACE) == 0) {
/*0424*/ /* class or instance methods */
/*0425*/ if (flags & ACC_ABSTRACT) {
/*0426*/ if (flags & (ACC_FINAL | ACC_NATIVE | ACC_SYNCHRONIZED
/*0427*/ | ACC_PRIVATE | ACC_STATIC)) {
/*0428*/ goto failed;
/*0429*/ }
/*0430*/ }
/*0431*/ } else {
/*0432*/ /* interface methods */
/*0433*/ if ( (flags & (ACC_ABSTRACT | ACC_PUBLIC | ACC_STATIC))
/*0434*/ != (ACC_ABSTRACT | ACC_PUBLIC)) {
/*0435*/ /* Note that <clinit> is special, and not handled by this
/*0436./ * function. It's not abstract, and static. */
/*0437*/ goto failed;
/*0438*/ }
/*0439*/ }
/*0440*/
/*0441*/ if (strcmp(name, "<init>") == 0) {
/*0442*/ if (flags & ~(ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE))
/*0443*/ goto failed;
/*0444*/ }
/*0445*/ return;
/*0446*/
/*0447*/ failed:
/*0448*/ fatalError(KVM_MSG_BAD_METHOD_ACCESS_FLAGS);
/*0449*/}
/*0450*/
/*0451*//*=========================================================================
/*0452./ * FUNCTION: verifyMethodType()
/*0453./ * TYPE: private class file load operation
/*0454./ * OVERVIEW: validate method signature
/*0455./ * INTERFACE:
/*0456./ * parameters: method name, signature
/*0457./ * returns: argument size
/*0458./ *=======================================================================*/
/*0459*/
/*0460*/static unsigned short
/*0461*/verifyMethodType(const char *name, const char* signature)
/*0462*/{
/*0463*/ unsigned short args_size = 0;
/*0464*/ const char *p = signature;
/*0465*/ unsigned short length = (unsigned short)strlen(signature);
/*0466*/ const char *next_p;
/*0467*/
/*0468*/ /* The first character must be a '(' */
/*0469*/ if ((length > 0) && (*p++ == '(')) {
/*0470*/ length--;
/*0471*/ /* Skip over however many legal field signatures there are */
/*0472*/ while ((length > 0) &&
/*0473*/ (next_p = skipOverFieldType(p, FALSE, length))) {
/*0474*/ args_size++;
/*0475*/ if (p[0] == 'J' || p[0] == 'D')
/*0476*/ args_size++;
/*0477*/ length -= (next_p - p);
/*0478*/ p = next_p;
/*0479*/ }
/*0480*/ /* The first non-signature thing better be a ')' */
/*0481*/ if ((length > 0) && (*p++ == ')')) {
/*0482*/ length --;
/*0483*/ if (strlen(name) > 0 && name[0] == '<') {
/*0484*/ /* All internal methods must return void */
/*0485*/ if ((length == 1) && (p[0] == 'V'))
/*0486*/ return args_size;
/*0487*/ } else {
/*0488*/ /* Now, we better just have a return value. */
/*0489*/ next_p = skipOverFieldType(p, TRUE, length);
/*0490*/ if (next_p && (length == next_p - p))
/*0491*/ return args_size;
/*0492*/ }
/*0493*/ }
/*0494*/ }
/*0495*/ fatalError(KVM_MSG_BAD_METHOD_SIGNATURE);
/*0496*/ return 0; /* never reached */
/*0497*/}
/*0498*/
/*0499*//*=========================================================================
/*0500./ * FUNCTION: verifyConstantPoolEntry()
/*0501./ * TYPE: private class file load operation
/*0502./ * OVERVIEW: validate constant pool index
/*0503./ * INTERFACE:
/*0504./ * parameters: constant pool, index, and expected tag
/*0505./ * returns: nothing
/*0506./ *=======================================================================*/
/*0507*/
/*0508*/static void
/*0509*/verifyConstantPoolEntry(INSTANCE_CLASS CurrentClass,
/*0510*/ unsigned short index,
/*0511*/ unsigned char tag)
/*0512*/{
/*0513*/ CONSTANTPOOL ConstantPool = CurrentClass->constPool;
/*0514*/ unsigned short length = (unsigned short)CONSTANTPOOL_LENGTH(ConstantPool);
/*0515*/ unsigned char tag2 = CONSTANTPOOL_TAGS(ConstantPool)[index];
/*0516*/ if (index >= length || tag2 != tag) {
/*0517*/ fatalError(KVM_MSG_BAD_CONSTANT_INDEX);
/*0518*/ }
/*0519*/}
/*0520*/
/*0521*//*=========================================================================
/*0522./ * Class loading operations
/*0523./ *=======================================================================*/
/*0524*/
/*0525*//*=========================================================================
/*0526./ * FUNCTION: loadVersionInfo()
/*0527./ * TYPE: private class file load operation
/*0528./ * OVERVIEW: Load the first few bytes of a Java class file,
/*0529./ * checking the file type and version information.
/*0530./ * INTERFACE:
/*0531./ * parameters: classfile pointer
/*0532./ * returns: <nothing>
/*0533./ *=======================================================================*/
/*0534*/
/*0535*/static void
/*0536*/loadVersionInfo(FILEPOINTER_HANDLE ClassFileH)
/*0537*/{
/*0538*/ UNUSEDPARAMETER(CurrentClass) //\\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -