📄 loader.c
字号:
/* * Copyright (c) 1998-2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * * Use is subject to license terms. *//*========================================================================= * SYSTEM: KVM * SUBSYSTEM: Class loader * FILE: loader.c * OVERVIEW: Structures and operations needed for loading * Java classfiles (class loader). * AUTHOR: Antero Taivalsaari, Sun Labs * Edited by Doug Simon 11/1998 * Extensive changes for spec-compliance by Sheng Liang * Frank Yellin (lots of additional checks for JLS (Java * Language Spec) compliance) *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include "global.h"/*========================================================================= * Macros and constants *=======================================================================*/#define STRING_POOL(i) (*((char **)(&StringPool->data[i])))#define RECOGNIZED_CLASS_FLAGS (ACC_PUBLIC | \ ACC_FINAL | \ ACC_SUPER | \ ACC_INTERFACE | \ ACC_ABSTRACT) #define RECOGNIZED_FIELD_FLAGS (ACC_PUBLIC | \ ACC_PRIVATE | \ ACC_PROTECTED | \ ACC_STATIC | \ ACC_FINAL | \ ACC_VOLATILE | \ ACC_TRANSIENT)#define RECOGNIZED_METHOD_FLAGS (ACC_PUBLIC | \ ACC_PRIVATE | \ ACC_PROTECTED | \ ACC_STATIC | \ ACC_FINAL | \ ACC_SYNCHRONIZED | \ ACC_NATIVE | \ ACC_ABSTRACT )/*========================================================================= * Static functions (used only in this file) *=======================================================================*/#if USESTATICstatic void moveClassFieldsToStatic(INSTANCE_CLASS CurrentClass);#else# define moveClassFieldsToStatic(CurrentClass)#endifstatic void ignoreAttributes(FILEPOINTER_HANDLE ClassFile, POINTERLIST_HANDLE StringPool);static void NoClassDefFoundError(INSTANCE_CLASS thisClass);/*========================================================================= * Class file verification operations (performed during class loading) *=======================================================================*//*========================================================================= * FUNCTION: skipOverFieldName() * TYPE: private class file load operation * OVERVIEW: skip over a legal field name in a get a given string * INTERFACE: * parameters: string: a string in which the field name is skipped * slash_okay: is '/' OK. * length: length of the string * returns: what's remaining after skipping the field name *=======================================================================*/static const char *skipOverFieldName(const char *string, bool_t slash_okay, unsigned short length){ const char *p; unsigned short ch; unsigned short last_ch = 0; /* last_ch == 0 implies we are looking at the first char. */ for (p = string; p != string + length; last_ch = ch) { const char *old_p = p; ch = *p; if (ch < 128) { p++; /* quick check for ascii */ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (last_ch && ch >= '0' && ch <= '9')) { continue; } } else { /* KVM simplification: we give up checking for those Unicode chars larger than 127. Otherwise we'll have to include a couple of large Unicode tables, bloating the footprint by 8~10K. */ const char *tmp_p = p; ch = utf2unicode((const char**)&tmp_p); p = tmp_p; continue; } if (slash_okay && ch == '/' && last_ch) { if (last_ch == '/') { return NULL; /* Don't permit consecutive slashes */ } } else if (ch == '_' || ch == '$') { /* continue */ } else { return last_ch ? old_p : NULL; } } return last_ch ? p : NULL;}/*========================================================================= * FUNCTION: skipOverFieldType() * TYPE: private class file load operation * OVERVIEW: skip over a legal field signature in a get a given string * INTERFACE: * parameters: string: a string in which the field signature is skipped * slash_okay: is '/' OK. * length: length of the string * returns: what's remaining after skipping the field signature *=======================================================================*/static const char *skipOverFieldType(const char *string, bool_t void_okay, unsigned short length){ unsigned int depth = 0; for (;length > 0;) { switch (string[0]) { case 'V': if (!void_okay) return NULL; /* FALL THROUGH */ case 'Z': case 'B': case 'C': case 'S': case 'I': case 'J':#if IMPLEMENTS_FLOAT case 'F': case 'D':#endif return string + 1; case 'L': { /* Skip over the class name, if one is there. */ const char *p = skipOverFieldName((const char *) (string + 1), TRUE, (unsigned short) (length - 1)); /* The next character better be a semicolon. */ if (p != NULL && p < string + length && p[0] == ';') { return p + 1; } return NULL; } case '[': /* The rest of what's there better be a legal signature. */ string++; length--; if (++depth == 256) { return NULL; } void_okay = FALSE; break; default: return NULL; } } return NULL;}/*========================================================================= * FUNCTION: getUTF8String() * TYPE: private class file load operation * OVERVIEW: get a UTF8 string from string pool, check index validity * INTERFACE: * parameters: String pool, index * returns: Pointer to UTF8 string *=======================================================================*/static char *getUTF8String(POINTERLIST_HANDLE StringPoolH, unsigned short index){ POINTERLIST StringPool = unhand(StringPoolH); if (index >= StringPool->length || STRING_POOL(index) == NULL) { fatalError(KVM_MSG_BAD_UTF8_INDEX); } return STRING_POOL(index);}/*========================================================================= * FUNCTION: verifyUTF8String() * TYPE: private class file load operation * OVERVIEW: validate a UTF8 string * INTERFACE: * parameters: pointer to UTF8 string * returns: nothing *=======================================================================*/static voidverifyUTF8String(char* bytes, unsigned short length){ unsigned int i; for (i=0; i<length; i++) { unsigned int c = ((unsigned char *)bytes)[i]; if (c == 0) /* no embedded zeros */ goto failed; if (c < 128) continue; switch (c >> 4) { default: break; case 0x8: case 0x9: case 0xA: case 0xB: case 0xF: goto failed; case 0xC: case 0xD: /* 110xxxxx 10xxxxxx */ i++; if (i >= length) goto failed; if ((bytes[i] & 0xC0) == 0x80) break; goto failed; case 0xE: /* 1110xxxx 10xxxxxx 10xxxxxx */ i += 2; if (i >= length) goto failed; if (((bytes[i-1] & 0xC0) == 0x80) && ((bytes[i] & 0xC0) == 0x80)) break; goto failed; } /* end of switch */ } return; failed: fatalError(KVM_MSG_BAD_UTF8_STRING);}/*========================================================================= * FUNCTION: verifyName() * TYPE: private class file load operation * OVERVIEW: validate a class, field, or method name * INTERFACE: * parameters: pointer to a name, name type * returns: nothing *=======================================================================*/bool_tverifyName(const char* name, enum verifyName_type type, bool_t abortOnError){ bool_t result; unsigned short length = (unsigned short)strlen(name); if (length > 0) { if (name[0] == '<') { result = (type == LegalMethod) && ((strcmp(name, "<init>") == 0) || (strcmp(name, "<clinit>") == 0)); } else { const char *p; if (type == LegalClass && name[0] == '[') { p = skipOverFieldType(name, FALSE, length); } else { p = skipOverFieldName(name, type == LegalClass, length); } result = (p != NULL) && (p - name == length); } } else { result = FALSE; } if (!result && abortOnError) { fatalError(KVM_MSG_BAD_NAME); } return result;}/*========================================================================= * FUNCTION: verifyClassFlags() * TYPE: private class file load operation * OVERVIEW: validate class access flags * INTERFACE: * parameters: class access flags * returns: nothing *=======================================================================*/static void verifyClassFlags(unsigned short flags){ if (flags & ACC_INTERFACE) { if ((flags & ACC_ABSTRACT) == 0) goto failed; if (flags & ACC_FINAL) goto failed; } else { if ((flags & ACC_FINAL) && (flags & ACC_ABSTRACT)) goto failed; } return; failed: fatalError(KVM_MSG_BAD_CLASS_ACCESS_FLAGS);}/*========================================================================= * FUNCTION: verifyFieldFlags() * TYPE: private class file load operation * OVERVIEW: validate field access flags * INTERFACE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -