X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Floader.c;h=dafe80ed90c1e340b2e4080ee35ff50f41a299c5;hb=5e09941e35ef3e36204485f2e9d7f3033d0b9baa;hp=86d8b4773ee54bbbdfa0a3e65c190976368783ca;hpb=7cd291b4693df671f7d015387783a27488fafd07;p=cacao.git diff --git a/src/vm/loader.c b/src/vm/loader.c index 86d8b4773..dafe80ed9 100644 --- a/src/vm/loader.c +++ b/src/vm/loader.c @@ -32,7 +32,7 @@ Edwin Steiner Christian Thalinger - $Id: loader.c 1329 2004-07-21 15:36:33Z twisti $ + $Id: loader.c 1553 2004-11-19 15:47:13Z carolyn $ */ @@ -50,7 +50,6 @@ #include "builtin.h" #include "jit/jit.h" #include "asmpart.h" -#include "options.h" #include "statistics.h" #include "toolbox/memory.h" #include "toolbox/logging.h" @@ -123,7 +122,8 @@ utf *array_packagename = NULL; list of classpath entries (either filesystem directories or ZIP/JAR archives ********************************************************************/ -static classpath_info *classpath_entries=0; + +static classpath_info *classpath_entries = NULL; /****************************************************************************** @@ -150,11 +150,6 @@ primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { }; -/* instances of important system classes **************************************/ - -java_objectheader *proto_java_lang_NullPointerException; - - /************* functions for reading classdata ********************************* getting classdata in blocks of variable size @@ -162,9 +157,6 @@ java_objectheader *proto_java_lang_NullPointerException; *******************************************************************************/ -static char *classpath = ""; /* searchpath for classfiles */ - - /* check_classbuffer_size ****************************************************** assert that at least bytes are left to read @@ -233,11 +225,6 @@ inline u4 suck_u4(classbuffer *cb) return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d; } -#define suck_s8(a) (s8) suck_u8((a)) -#define suck_s2(a) (s2) suck_u2((a)) -#define suck_s4(a) (s4) suck_u4((a)) -#define suck_s1(a) (s1) suck_u1((a)) - /* get u8 from classfile data */ static u8 suck_u8(classbuffer *cb) @@ -256,6 +243,12 @@ static u8 suck_u8(classbuffer *cb) } +#define suck_s8(a) (s8) suck_u8((a)) +#define suck_s2(a) (s2) suck_u2((a)) +#define suck_s4(a) (s4) suck_u4((a)) +#define suck_s1(a) (s1) suck_u1((a)) + + /* get float from classfile data */ static float suck_float(classbuffer *cb) { @@ -320,98 +313,93 @@ static double suck_double(classbuffer *cb) *******************************************************************************/ -void suck_init(char *cpath) +void suck_init(char *classpath) { - char *filename=0; char *start; char *end; - int isZip; - int filenamelen; - union classpath_info *tmp; - union classpath_info *insertAfter=0; + char *filename; + s4 filenamelen; + bool is_zip; + classpath_info *cpi; + classpath_info *lastcpi; - if (!cpath) + if (!classpath) return; - classpath = cpath; - - if (classpath_entries) - panic("suck_init should be called only once"); - for (start = classpath; (*start) != '\0';) { + + /* search for ':' delimiter to get the end of the current entry */ for (end = start; ((*end) != '\0') && ((*end) != ':'); end++); if (start != end) { - isZip = 0; + is_zip = false; filenamelen = end - start; if (filenamelen > 3) { if (strncasecmp(end - 3, "zip", 3) == 0 || strncasecmp(end - 3, "jar", 3) == 0) { - isZip = 1; + is_zip = true; } } - if (filenamelen >= (CLASSPATH_MAXFILENAME - 1)) - panic("path length >= MAXFILENAME in suck_init"); - - if (!filename) - filename = MNEW(char, CLASSPATH_MAXFILENAME); + /* allocate memory for filename and fill it */ + filename = MNEW(char, filenamelen + 2); /* 2 = "/\0" */ strncpy(filename, start, filenamelen); filename[filenamelen + 1] = '\0'; - tmp = NULL; + cpi = NULL; - if (isZip) { + if (is_zip) { #if defined(USE_ZLIB) unzFile uf = unzOpen(filename); if (uf) { - tmp = (union classpath_info *) NEW(classpath_info); - tmp->archive.type = CLASSPATH_ARCHIVE; - tmp->archive.uf = uf; - tmp->archive.next = NULL; - filename = NULL; + cpi = (union classpath_info *) NEW(classpath_info); + cpi->archive.type = CLASSPATH_ARCHIVE; + cpi->archive.uf = uf; + cpi->archive.next = NULL; } #else - throw_cacao_exception_exit(string_java_lang_InternalError, "zip/jar files not supported"); + throw_cacao_exception_exit(string_java_lang_InternalError, + "zip/jar files not supported"); #endif } else { - tmp = (union classpath_info *) NEW(classpath_info); - tmp->filepath.type = CLASSPATH_PATH; - tmp->filepath.next = 0; + cpi = (union classpath_info *) NEW(classpath_info); + cpi->filepath.type = CLASSPATH_PATH; + cpi->filepath.next = NULL; if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */ filename[filenamelen] = '/'; filename[filenamelen + 1] = '\0'; filenamelen++; } - - tmp->filepath.filename = filename; - tmp->filepath.pathlen = filenamelen; - filename = NULL; + + cpi->filepath.path = filename; + cpi->filepath.pathlen = filenamelen; } - if (tmp) { - if (insertAfter) { - insertAfter->filepath.next = tmp; + /* attach current classpath entry */ + + if (cpi) { + if (!classpath_entries) { + classpath_entries = cpi; } else { - classpath_entries = tmp; + lastcpi->filepath.next = cpi; } - insertAfter = tmp; + + lastcpi = cpi; } } - if ((*end) == ':') + /* goto next classpath entry, skip ':' delimiter */ + + if ((*end) == ':') { start = end + 1; - else + + } else { start = end; - - if (filename) { - MFREE(filename, char, CLASSPATH_MAXFILENAME); - filename = NULL; } } } @@ -455,16 +443,19 @@ void create_all_classes() classbuffer *suck_start(classinfo *c) { - classpath_info *currPos; - char *utf_ptr; - char ch; - char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */ - int filenamelen=0; + classpath_info *cpi; +/* char *utf_ptr; */ +/* char ch; */ + char *filename; + s4 filenamelen; + char *path; FILE *classfile; int err; + s4 len; struct stat buffer; classbuffer *cb; +#if 0 utf_ptr = c->name->text; while (utf_ptr < utf_end(c->name)) { @@ -482,50 +473,64 @@ classbuffer *suck_start(classinfo *c) ch = '?'; filename[filenamelen++] = ch; } +#endif + + /* initialize return value */ - strcpy(filename + filenamelen, ".class"); - filenamelen += 6; + cb = NULL; - for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) { + filenamelen = utf_strlen(c->name) + 7; /* 7 = ".class\0" */ + filename = MNEW(char, filenamelen); + + utf_sprint(filename, c->name); + strcat(filename, ".class"); + + /* walk through all classpath entries */ + + for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->filepath.next) { #if defined(USE_ZLIB) - if (currPos->filepath.type == CLASSPATH_ARCHIVE) { - if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) { + if (cpi->filepath.type == CLASSPATH_ARCHIVE) { + if (cacao_locate(cpi->archive.uf, c->name) == UNZ_OK) { unz_file_info file_info; - /*log_text("Class found in zip file");*/ - if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename, - sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) { - if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) { + + if (unzGetCurrentFileInfo(cpi->archive.uf, &file_info, filename, + sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) { + if (unzOpenCurrentFile(cpi->archive.uf) == UNZ_OK) { cb = NEW(classbuffer); cb->class = c; cb->size = file_info.uncompressed_size; cb->data = MNEW(u1, cb->size); cb->pos = cb->data - 1; - /*printf("classfile size: %d\n",file_info.uncompressed_size);*/ - if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) { - unzCloseCurrentFile(currPos->archive.uf); - return cb; - - } else { - MFREE(cb->data, u1, cb->size); - FREE(cb, classbuffer); + + len = unzReadCurrentFile(cpi->archive.uf, cb->data, cb->size); + + if (len != cb->size) { + suck_stop(cb); log_text("Error while unzipping"); } - } else log_text("Error while opening file in archive"); - } else log_text("Error while retrieving fileinfo"); + + } else { + log_text("Error while opening file in archive"); + } + + } else { + log_text("Error while retrieving fileinfo"); + } } - unzCloseCurrentFile(currPos->archive.uf); + unzCloseCurrentFile(cpi->archive.uf); } else { -#endif - if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue; - strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename); - classfile = fopen(currPos->filepath.filename, "r"); - if (classfile) { /* file exists */ +#endif /* USE_ZLIB */ + + path = MNEW(char, cpi->filepath.pathlen + filenamelen + 1); + strcpy(path, cpi->filepath.path); + strcat(path, filename); - /* determine size of classfile */ + classfile = fopen(path, "r"); - /* dolog("File: %s",filename); */ - err = stat(currPos->filepath.filename, &buffer); + if (classfile) { /* file exists */ + /* determine size of classfile */ + err = stat(path, &buffer); if (!err) { /* read classfile data */ cb = NEW(classbuffer); @@ -533,22 +538,32 @@ classbuffer *suck_start(classinfo *c) cb->size = buffer.st_size; cb->data = MNEW(u1, cb->size); cb->pos = cb->data - 1; - fread(cb->data, 1, cb->size, classfile); - fclose(classfile); - return cb; + /* read class data */ + len = fread(cb->data, 1, cb->size, classfile); + + if (len != buffer.st_size) { + suck_stop(cb); +/* if (ferror(classfile)) { */ +/* } */ + } } } + + MFREE(path, char, cpi->filepath.pathlen + filenamelen + 1); #if defined(USE_ZLIB) } #endif } - if (verbose) { - dolog("Warning: Can not open class file '%s'", filename); + if (opt_verbose) { + if (err) + dolog("Warning: Can not open class file '%s'", filename); } - return NULL; + MFREE(filename, char, filenamelen); + + return cb; } @@ -660,17 +675,39 @@ static bool skipattributes(classbuffer *cb, u4 num) } +/******************** function:: class_getconstant ***************************** + + retrieves the value at position 'pos' of the constantpool of a class + if the type of the value is other than 'ctype' the system is stopped + +*******************************************************************************/ + +voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype) +{ + /* check index and type of constantpool entry */ + /* (pos == 0 is caught by type comparison) */ + if (pos >= c->cpcount || c->cptags[pos] != ctype) { + *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); + return NULL; + } + + return c->cpinfos[pos]; +} + + /******************** function: innerclass_getconstant ************************ like class_getconstant, but if cptags is ZERO null is returned *******************************************************************************/ -voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) +voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) { /* invalid position in constantpool */ - if (pos >= c->cpcount) - panic("Attempt to access constant outside range"); + if (pos >= c->cpcount) { + *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); + return NULL; + } /* constantpool entry of type 0 */ if (!c->cptags[pos]) @@ -678,14 +715,31 @@ voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) /* check type of constantpool entry */ if (c->cptags[pos] != ctype) { - error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)", - (int) ctype, (int) c->cptags[pos] ); + *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); + return NULL; } return c->cpinfos[pos]; } +/********************* Function: class_constanttype **************************** + + Determines the type of a class entry in the ConstantPool + +*******************************************************************************/ + +u4 class_constanttype(classinfo *c, u4 pos) +{ + if (pos <= 0 || pos >= c->cpcount) { + *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); + return 0; + } + + return c->cptags[pos]; +} + + /************************ function: attribute_load **************************** read attributes from classfile @@ -694,26 +748,29 @@ voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) static bool attribute_load(classbuffer *cb, classinfo *c, u4 num) { + utf *aname; u4 i, j; for (i = 0; i < num; i++) { - utf *aname; - /* retrieve attribute name */ if (!check_classbuffer_size(cb, 2)) return false; - aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); + if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; if (aname == utf_innerclasses) { /* innerclasses attribute */ - if (c->innerclass != NULL) - panic("Class has more than one InnerClasses attribute"); + if (c->innerclass) { + *exceptionptr = + new_classformaterror(c, "Multiple InnerClasses attributes"); + return false; + } if (!check_classbuffer_size(cb, 4 + 2)) return false; - /* skip attribute length */ + /* skip attribute length */ suck_u4(cb); /* number of records */ @@ -727,7 +784,7 @@ static bool attribute_load(classbuffer *cb, classinfo *c, u4 num) for (j = 0; j < c->innerclasscount; j++) { /* The innerclass structure contains a class with an encoded - name, its defining scope, its simple name and a bitmask of + name, its defining scope, its simple name and a bitmask of the access flags. If an inner class is not a member, its outer_class is NULL, if a class is anonymous, its name is NULL. */ @@ -747,8 +804,20 @@ static bool attribute_load(classbuffer *cb, classinfo *c, u4 num) if (!check_classbuffer_size(cb, 4 + 2)) return false; - suck_u4(cb); - c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); + if (suck_u4(cb) != 2) { + *exceptionptr = + new_classformaterror(c, "Wrong size for VALUE attribute"); + return false; + } + + if (c->sourcefile) { + *exceptionptr = + new_classformaterror(c, "Multiple SourceFile attributes"); + return false; + } + + if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; } else { /* unknown attribute */ @@ -963,38 +1032,51 @@ void print_arraydescriptor(FILE *file, arraydescriptor *desc) static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f) { - u4 attrnum,i; + u4 attrnum, i; u4 jtype; u4 pindex = field_load_NOVALUE; /* constantvalue_index */ + utf *u; if (!check_classbuffer_size(cb, 2 + 2 + 2)) return false; f->flags = suck_u2(cb); - f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); - f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); - + + if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; + f->name = u; + + if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; + f->descriptor = u; + if (opt_verify) { /* check name */ if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') panic("Field with invalid name"); /* check flag consistency */ - i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)); - - if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) - panic("Field has invalid access flags"); + i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED); - if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE)) - panic("Field is declared final and volatile"); - - if ((c->flags & ACC_INTERFACE) != 0) { - if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) - != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) - panic("Interface field is not declared static final public"); + if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) || + ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) { + *exceptionptr = + new_classformaterror(c, + "Illegal field modifiers: 0x%X", + f->flags); + return false; + } - if ((f->flags & ACC_TRANSIENT) != 0) - panic("Interface field declared transient"); + if (c->flags & ACC_INTERFACE) { + if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) + != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) || + f->flags & ACC_TRANSIENT) { + *exceptionptr = + new_classformaterror(c, + "Illegal field modifiers: 0x%X", + f->flags); + return false; + } } /* check descriptor */ @@ -1025,29 +1107,30 @@ static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f) attrnum = suck_u2(cb); for (i = 0; i < attrnum; i++) { - utf *aname; - if (!check_classbuffer_size(cb, 2)) return false; - aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); - - if (aname != utf_constantvalue) { - /* unknown attribute */ - if (!skipattributebody(cb)) - return false; + if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; - } else { - /* constant value attribute */ - if (pindex != field_load_NOVALUE) - panic("Field has more than one ConstantValue attribute"); - + if (u == utf_constantvalue) { if (!check_classbuffer_size(cb, 4 + 2)) return false; /* check attribute length */ - if (suck_u4(cb) != 2) - panic("ConstantValue attribute has invalid length"); + if (suck_u4(cb) != 2) { + *exceptionptr = + new_classformaterror(c, "Wrong size for VALUE attribute"); + return false; + } + + /* constant value attribute */ + if (pindex != field_load_NOVALUE) { + *exceptionptr = + new_classformaterror(c, + "Multiple ConstantValue attributes"); + return false; + } /* index of value in constantpool */ pindex = suck_u2(cb); @@ -1055,43 +1138,61 @@ static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f) /* initialize field with value from constantpool */ switch (jtype) { case TYPE_INT: { - constant_integer *ci = - class_getconstant(c, pindex, CONSTANT_Integer); + constant_integer *ci; + + if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer))) + return false; + f->value.i = ci->value; } break; case TYPE_LONG: { - constant_long *cl = - class_getconstant(c, pindex, CONSTANT_Long); + constant_long *cl; + + if (!(cl = class_getconstant(c, pindex, CONSTANT_Long))) + return false; + f->value.l = cl->value; } break; case TYPE_FLOAT: { - constant_float *cf = - class_getconstant(c, pindex, CONSTANT_Float); + constant_float *cf; + + if (!(cf = class_getconstant(c, pindex, CONSTANT_Float))) + return false; + f->value.f = cf->value; } break; case TYPE_DOUBLE: { - constant_double *cd = - class_getconstant(c, pindex, CONSTANT_Double); + constant_double *cd; + + if (!(cd = class_getconstant(c, pindex, CONSTANT_Double))) + return false; + f->value.d = cd->value; } break; - case TYPE_ADDRESS: { - utf *u = class_getconstant(c, pindex, CONSTANT_String); - /* create javastring from compressed utf8-string */ + case TYPE_ADDRESS: + if (!(u = class_getconstant(c, pindex, CONSTANT_String))) + return false; + + /* create javastring from compressed utf8-string */ f->value.a = literalstring_new(u); - } - break; + break; default: - log_text ("Invalid Constant - Type"); + log_text("Invalid Constant - Type"); } + + } else { + /* unknown attribute */ + if (!skipattributebody(cb)) + return false; } } @@ -1143,6 +1244,11 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) s4 i, j; u4 attrnum; u4 codeattrnum; + utf *u; + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + initObjectLock(&m->header); +#endif #ifdef STATISTICS if (opt_stat) @@ -1159,8 +1265,14 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) return false; m->flags = suck_u2(cb); - m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); - m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); + + if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; + m->name = u; + + if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; + m->descriptor = u; if (opt_verify) { if (!is_valid_name_utf(m->name)) @@ -1177,37 +1289,48 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) argcount++; /* count the 'this' argument */ if (opt_verify) { - if (argcount > 255) - panic("Too many arguments in signature"); + if (argcount > 255) { + *exceptionptr = + new_classformaterror(c, "Too many arguments in signature"); + return false; + } /* check flag consistency */ if (m->name != utf_clinit) { i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)); - if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) - panic("Method has invalid access flags"); + if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) { + *exceptionptr = + new_classformaterror(c, + "Illegal method modifiers: 0x%X", + m->flags); + return false; + } - if ((m->flags & ACC_ABSTRACT) != 0) { + if (m->flags & ACC_ABSTRACT) { if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) { *exceptionptr = new_classformaterror(c, - "Illegal method modifiers: 0x%x", + "Illegal method modifiers: 0x%X", m->flags); - return false; } } - if ((c->flags & ACC_INTERFACE) != 0) { - if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) - != (ACC_ABSTRACT | ACC_PUBLIC)) - panic("Interface method is not declared abstract and public"); + if (c->flags & ACC_INTERFACE) { + if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) { + *exceptionptr = + new_classformaterror(c, + "Illegal method modifiers: 0x%X", + m->flags); + return false; + } } if (m->name == utf_init) { - if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED - | ACC_NATIVE | ACC_ABSTRACT)) != 0) + if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED | + ACC_NATIVE | ACC_ABSTRACT)) panic("Instance initialization method has invalid flags set"); } } @@ -1222,7 +1345,6 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) m->stackcount = 0; m->stack = NULL; m->exceptiontable = NULL; - m->registerdata = NULL; m->stubroutine = NULL; m->mcode = NULL; m->entrypoint = NULL; @@ -1237,9 +1359,16 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) m->stubroutine = createcompilerstub(m); } else { + /*if (useinlining) { + log_text("creating native stub:"); + method_display(m); + }*/ functionptr f = native_findfunction(c->name, m->name, m->descriptor, - (m->flags & ACC_STATIC) != 0); - if (f) { + (m->flags & ACC_STATIC) != 0); +#ifdef STATIC_CLASSPATH + if (f) +#endif + { m->stubroutine = createnativestub(f, m); } } @@ -1254,34 +1383,10 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) if (!check_classbuffer_size(cb, 2)) return false; - aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); - - if (aname != utf_code) { - if (aname == utf_exceptions) { - s4 j; - - if (!check_classbuffer_size(cb, 4 + 2)) - return false; - - suck_u4(cb); /*length*/ - m->thrownexceptionscount = suck_u2(cb); - - if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount)) - return false; - - m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount); - - for (j = 0; j < m->thrownexceptionscount; j++) { - (m->thrownexceptions)[j] = - class_getconstant(c, suck_u2(cb), CONSTANT_Class); - } - - } else { - if (!skipattributebody(cb)) - return false; - } + if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; - } else { + if (aname == utf_code) { if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) { *exceptionptr = new_classformaterror(c, @@ -1341,7 +1446,6 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) return false; m->exceptiontablelength = suck_u2(cb); - if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength)) return false; @@ -1365,8 +1469,9 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) m->exceptiontable[j].catchtype = NULL; } else { - m->exceptiontable[j].catchtype = - class_getconstant(c, idx, CONSTANT_Class); + if (!(m->exceptiontable[j].catchtype = + class_getconstant(c, idx, CONSTANT_Class))) + return false; } } @@ -1381,7 +1486,8 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) if (!check_classbuffer_size(cb, 2)) return false; - caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); + if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + return false; if (caname == utf_linenumbertable) { u2 lncid; @@ -1408,11 +1514,42 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) return false; break; + } else { if (!skipattributebody(cb)) return false; } } + + } else if (aname == utf_exceptions) { + s4 j; + + if (m->thrownexceptions) { + *exceptionptr = + new_classformaterror(c, "Multiple Exceptions attributes"); + return false; + } + + if (!check_classbuffer_size(cb, 4 + 2)) + return false; + + suck_u4(cb); /* length */ + m->thrownexceptionscount = suck_u2(cb); + + if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount)) + return false; + + m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount); + + for (j = 0; j < m->thrownexceptionscount; j++) { + if (!((m->thrownexceptions)[j] = + class_getconstant(c, suck_u2(cb), CONSTANT_Class))) + return false; + } + + } else { + if (!skipattributebody(cb)) + return false; } } @@ -1423,6 +1560,8 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m) } /* everything was ok */ + /* utf_display(m->name); + printf("\nexceptiontablelength:%ld\n",m->exceptiontablelength);*/ return true; } @@ -1469,6 +1608,24 @@ void method_display(methodinfo *m) printf("\n"); } +/************** Function: method_display_w_class (debugging only) **************/ + +void method_display_w_class(methodinfo *m) +{ + printflags(m->class->flags); + printf(" "); fflush(stdout); + utf_display(m->class->name); + printf(".");fflush(stdout); + + printf(" "); + printflags(m->flags); + printf(" "); fflush(stdout); + utf_display(m->name); + printf(" "); fflush(stdout); + utf_display(m->descriptor); + printf("\n"); fflush(stdout); +} + /************** Function: method_display_flags_last (debugging only) **************/ void method_display_flags_last(methodinfo *m) @@ -1499,52 +1656,6 @@ static bool method_canoverwrite(methodinfo *m, methodinfo *old) } -/******************************************************************************/ -/************************ Functions for class *********************************/ -/******************************************************************************/ - - -/******************** function:: class_getconstant ***************************** - - retrieves the value at position 'pos' of the constantpool of a class - if the type of the value is other than 'ctype' the system is stopped - -*******************************************************************************/ - -voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype) -{ - /* invalid position in constantpool */ - /* (pos == 0 is caught by type comparison) */ - if (pos >= c->cpcount) - panic("Attempt to access constant outside range"); - - /* check type of constantpool entry */ - - if (c->cptags[pos] != ctype) { - class_showconstantpool(c); - error("Type mismatch on constant: %d requested, %d here (class_getconstant)", - (int) ctype, (int) c->cptags[pos]); - } - - return c->cpinfos[pos]; -} - - -/********************* Function: class_constanttype **************************** - - Determines the type of a class entry in the ConstantPool - -*******************************************************************************/ - -u4 class_constanttype(classinfo *c, u4 pos) -{ - if (pos >= c->cpcount) - panic("Attempt to access constant outside range"); - - return c->cptags[pos]; -} - - /******************** function: class_loadcpool ******************************** loads the constantpool of a class, @@ -1562,17 +1673,17 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) been traversed the references can be resolved. (only in specific order) */ - /* CONSTANT_Class_info entries */ - typedef struct forward_class { - struct forward_class *next; - u2 thisindex; - u2 name_index; - } forward_class; - - /* CONSTANT_String */ - typedef struct forward_string { - struct forward_string *next; - u2 thisindex; + /* CONSTANT_Class entries */ + typedef struct forward_class { + struct forward_class *next; + u2 thisindex; + u2 name_index; + } forward_class; + + /* CONSTANT_String */ + typedef struct forward_string { + struct forward_string *next; + u2 thisindex; u2 string_index; } forward_string; @@ -1585,7 +1696,7 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) } forward_nameandtype; /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */ - typedef struct forward_fieldmethint { + typedef struct forward_fieldmethint { struct forward_fieldmethint *next; u2 thisindex; u1 tag; @@ -1595,13 +1706,17 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) u4 idx; - long int dumpsize = dump_size (); forward_class *forward_classes = NULL; forward_string *forward_strings = NULL; forward_nameandtype *forward_nameandtypes = NULL; forward_fieldmethint *forward_fieldmethints = NULL; + forward_class *nfc; + forward_string *nfs; + forward_nameandtype *nfn; + forward_fieldmethint *nff; + u4 cpcount; u1 *cptags; voidptr *cpinfos; @@ -1616,8 +1731,10 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) cptags = c->cptags = MNEW(u1, cpcount); cpinfos = c->cpinfos = MNEW(voidptr, cpcount); - if (!cpcount) - panic("Invalid constant_pool_count (0)"); + if (cpcount < 1) { + *exceptionptr = new_classformaterror(c, "Illegal constant pool size"); + return false; + } #if defined(STATISTICS) if (opt_stat) @@ -1646,8 +1763,8 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) t = suck_u1(cb); switch (t) { - case CONSTANT_Class: { - forward_class *nfc = DNEW(forward_class); + case CONSTANT_Class: + nfc = NEW(forward_class); nfc->next = forward_classes; forward_classes = nfc; @@ -1661,36 +1778,9 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) idx++; break; - } - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: { - forward_fieldmethint *nff = DNEW(forward_fieldmethint); - - nff->next = forward_fieldmethints; - forward_fieldmethints = nff; - - nff->thisindex = idx; - /* constant type */ - nff->tag = t; - - if (!check_classbuffer_size(cb, 2 + 2)) - return false; - - /* class or interface type that contains the declaration of the - field or method */ - nff->class_index = suck_u2(cb); - - /* name and descriptor of the field or method */ - nff->nameandtype_index = suck_u2(cb); - - idx++; - break; - } - - case CONSTANT_String: { - forward_string *nfs = DNEW(forward_string); + case CONSTANT_String: + nfs = NEW(forward_string); nfs->next = forward_strings; forward_strings = nfs; @@ -1705,10 +1795,9 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) idx++; break; - } - case CONSTANT_NameAndType: { - forward_nameandtype *nfn = DNEW(forward_nameandtype); + case CONSTANT_NameAndType: + nfn = NEW(forward_nameandtype); nfn->next = forward_nameandtypes; forward_nameandtypes = nfn; @@ -1727,8 +1816,32 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) idx++; break; - } + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + nff = NEW(forward_fieldmethint); + + nff->next = forward_fieldmethints; + forward_fieldmethints = nff; + + nff->thisindex = idx; + /* constant type */ + nff->tag = t; + + if (!check_classbuffer_size(cb, 2 + 2)) + return false; + + /* class or interface type that contains the declaration of the + field or method */ + nff->class_index = suck_u2(cb); + + /* name and descriptor of the field or method */ + nff->nameandtype_index = suck_u2(cb); + + idx++; + break; + case CONSTANT_Integer: { constant_integer *ci = NEW(constant_integer); @@ -1782,8 +1895,11 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) cptags[idx] = CONSTANT_Long; cpinfos[idx] = cl; idx += 2; - if (idx > cpcount) - panic("Long constant exceeds constant pool"); + if (idx > cpcount) { + *exceptionptr = + new_classformaterror(c, "Invalid constant pool entry"); + return false; + } break; } @@ -1802,8 +1918,11 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) cptags[idx] = CONSTANT_Double; cpinfos[idx] = cd; idx += 2; - if (idx > cpcount) - panic("Double constant exceeds constant pool"); + if (idx > cpcount) { + *exceptionptr = + new_classformaterror(c, "Invalid constant pool entry"); + return false; + } break; } @@ -1822,12 +1941,13 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) return false; if (opt_verify && - !is_valid_utf(cb->pos + 1, cb->pos + 1 + length)) { + !is_valid_utf((char *) (cb->pos + 1), + (char *) (cb->pos + 1 + length))) { dolog("Invalid UTF-8 string (constant pool index %d)",idx); panic("Invalid UTF-8 string"); } /* insert utf-string into the utf-symboltable */ - cpinfos[idx] = utf_new_intern(cb->pos + 1, length); + cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length); /* skip bytes of the string (buffer size check above) */ skip_nbytes(cb, length); @@ -1836,7 +1956,9 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) } default: - error("Unkown constant type: %d",(int) t); + *exceptionptr = + new_classformaterror(c, "Illegal constant pool type"); + return false; } /* end switch */ } /* end while */ @@ -1859,8 +1981,8 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) if (!class_load(tc)) return false; - /* link the class later, so we cannot link the currently loaded - class */ + /* link the class later, because we cannot link the class currently + loading */ list_addfirst(&unlinkedclasses, tc); cpinfos[forward_classes->thisindex] = tc; @@ -1869,18 +1991,22 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) cpinfos[forward_classes->thisindex] = class_new(name); } + nfc = forward_classes; forward_classes = forward_classes->next; + FREE(nfc, forward_class); } while (forward_strings) { utf *text = class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8); - /* resolve utf-string */ + /* resolve utf-string */ cptags[forward_strings->thisindex] = CONSTANT_String; cpinfos[forward_strings->thisindex] = text; + nfs = forward_strings; forward_strings = forward_strings->next; + FREE(nfs, forward_string); } while (forward_nameandtypes) { @@ -1911,8 +2037,10 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType; cpinfos[forward_nameandtypes->thisindex] = cn; - + + nfn = forward_nameandtypes; forward_nameandtypes = forward_nameandtypes->next; + FREE(nfn, forward_nameandtype); } while (forward_fieldmethints) { @@ -1948,11 +2076,11 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c) break; } + nff = forward_fieldmethints; forward_fieldmethints = forward_fieldmethints->next; + FREE(nff, forward_fieldmethint); } - dump_release(dumpsize); - /* everything was ok */ return true; @@ -1978,8 +2106,6 @@ classinfo *class_load(classinfo *c) { classbuffer *cb; classinfo *r; - s8 starttime; - s8 stoptime; /* enter a monitor on the class */ @@ -1993,8 +2119,12 @@ classinfo *class_load(classinfo *c) } /* measure time */ + + if (getcompilingtime) + compilingtime_stop(); + if (getloadingtime) - starttime = getcputime(); + loadingtime_start(); /* load classdata, throw exception on error */ @@ -2028,10 +2158,12 @@ classinfo *class_load(classinfo *c) suck_stop(cb); /* measure time */ - if (getloadingtime) { - stoptime = getcputime(); - loadingtime += (stoptime - starttime); - } + + if (getloadingtime) + loadingtime_stop(); + + if (getcompilingtime) + compilingtime_start(); /* leave the monitor */ @@ -2044,9 +2176,9 @@ classinfo *class_load(classinfo *c) classinfo *class_load_intern(classbuffer *cb) { classinfo *c; + classinfo *tc; u4 i; - u4 mi, ma; -/* s4 classdata_left; */ + u4 ma, mi; char msg[MAXLOGTEXT]; /* maybe we get an exception */ /* get the classbuffer's class */ @@ -2084,13 +2216,14 @@ classinfo *class_load_intern(classbuffer *cb) if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) { *exceptionptr = - new_classformaterror(c, - "Unsupported major.minor version %d.%d", - ma, mi); + new_unsupportedclassversionerror(c, + "Unsupported major.minor version %d.%d", + ma, mi); return NULL; } + /* load the constant pool */ if (!class_loadcpool(cb, c)) return NULL; @@ -2121,7 +2254,7 @@ classinfo *class_load_intern(classbuffer *cb) if (c->flags & ACC_FINAL) { *exceptionptr = new_classformaterror(c, - "Illegal class modifiers: 0x%x", c->flags); + "Illegal class modifiers: 0x%X", c->flags); return NULL; } @@ -2133,7 +2266,7 @@ classinfo *class_load_intern(classbuffer *cb) if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) { *exceptionptr = - new_classformaterror(c, "Illegal class modifiers: 0x%x", c->flags); + new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags); return NULL; } @@ -2143,11 +2276,13 @@ classinfo *class_load_intern(classbuffer *cb) /* this class */ i = suck_u2(cb); - if (class_getconstant(c, i, CONSTANT_Class) != c) { + if (!(tc = class_getconstant(c, i, CONSTANT_Class))) + return NULL; + + if (tc != c) { utf_sprint(msg, c->name); sprintf(msg + strlen(msg), " (wrong name: "); - utf_sprint(msg + strlen(msg), - ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name); + utf_sprint(msg + strlen(msg), tc->name); sprintf(msg + strlen(msg), ")"); *exceptionptr = @@ -2158,7 +2293,8 @@ classinfo *class_load_intern(classbuffer *cb) /* retrieve superclass */ if ((i = suck_u2(cb))) { - c->super = class_getconstant(c, i, CONSTANT_Class); + if (!(c->super = class_getconstant(c, i, CONSTANT_Class))) + return NULL; /* java.lang.Object may not have a super class. */ if (c->name == utf_java_lang_Object) { @@ -2188,7 +2324,6 @@ classinfo *class_load_intern(classbuffer *cb) return NULL; } - } /* retrieve interfaces */ @@ -2202,7 +2337,8 @@ classinfo *class_load_intern(classbuffer *cb) c->interfaces = MNEW(classinfo*, c->interfacescount); for (i = 0; i < c->interfacescount; i++) { - c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class); + if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class))) + return NULL; } /* load fields */ @@ -2287,7 +2423,7 @@ classinfo *class_load_intern(classbuffer *cb) } /* Check methods */ - memset(hashtab, 0, sizeof(u2) * (hashlen + len)); + memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5)); for (i = 0; i < c->methodscount; ++i) { methodinfo *mi = c->methods + i; @@ -2296,6 +2432,13 @@ classinfo *class_load_intern(classbuffer *cb) index = ((((size_t) mi->name) + ((size_t) mi->descriptor)) >> shift) % hashlen; + /*{ JOWENN + int dbg; + for (dbg=0;dbgdata + cb->size) - cb->pos - 1); - - if (classdata_left > 0) { - /* surplus */ - dolog("There are %d extra bytes at end of classfile", classdata_left); - /* The JVM spec disallows extra bytes. */ - panic("Extra bytes at end of classfile"); + /* Pre java 1.5 version don't check this. This implementation is like + java 1.5 do it: for class file version 45.3 we don't check it, older + versions are checked. + */ + if ((ma == 45 && mi > 3) || ma > 45) { + /* check if all data has been read */ + s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1); + + if (classdata_left > 0) { + *exceptionptr = + new_classformaterror(c, "Extra bytes at the end of class file"); + return NULL; + } } #endif @@ -2365,13 +2511,8 @@ static s4 class_highestinterface(classinfo *c) s4 h; s4 i; - if (!(c->flags & ACC_INTERFACE)) { - char logtext[MAXLOGTEXT]; - sprintf(logtext, "Interface-methods count requested for non-interface: "); - utf_sprint(logtext + strlen(logtext), c->name); - error("%s",logtext); - } - + /* check for ACC_INTERFACE bit already done in class_link_intern */ + h = c->index; for (i = 0; i < c->interfacescount; i++) { s4 h2 = class_highestinterface(c->interfaces[i]); @@ -2384,33 +2525,33 @@ static s4 class_highestinterface(classinfo *c) /* class_addinterface ********************************************************** - Is needed by class_link for adding a VTBL to a class. All interfaces - implemented by ic are added as well. + Is needed by class_link for adding a VTBL to a class. All interfaces + implemented by ic are added as well. *******************************************************************************/ static void class_addinterface(classinfo *c, classinfo *ic) { s4 j, m; - s4 i = ic->index; - vftbl_t *vftbl = c->vftbl; + s4 i = ic->index; + vftbl_t *v = c->vftbl; - if (i >= vftbl->interfacetablelength) + if (i >= v->interfacetablelength) panic ("Inernal error: interfacetable overflow"); - if (vftbl->interfacetable[-i]) + if (v->interfacetable[-i]) return; if (ic->methodscount == 0) { /* fake entry needed for subtype test */ - vftbl->interfacevftbllength[i] = 1; - vftbl->interfacetable[-i] = MNEW(methodptr, 1); - vftbl->interfacetable[-i][0] = NULL; + v->interfacevftbllength[i] = 1; + v->interfacetable[-i] = MNEW(methodptr, 1); + v->interfacetable[-i][0] = NULL; } else { - vftbl->interfacevftbllength[i] = ic->methodscount; - vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); + v->interfacevftbllength[i] = ic->methodscount; + v->interfacetable[-i] = MNEW(methodptr, ic->methodscount); -#ifdef STATISTICS +#if defined(STATISTICS) if (opt_stat) count_vftbl_len += sizeof(methodptr) * (ic->methodscount + (ic->methodscount == 0)); @@ -2422,8 +2563,7 @@ static void class_addinterface(classinfo *c, classinfo *ic) for (m = 0; m < sc->methodscount; m++) { methodinfo *mi = &(sc->methods[m]); if (method_canoverwrite(mi, &(ic->methods[j]))) { - vftbl->interfacetable[-i][j] = - vftbl->table[mi->vftblindex]; + v->interfacetable[-i][j] = v->table[mi->vftblindex]; goto foundmethod; } } @@ -2553,7 +2693,6 @@ static arraydescriptor *class_link_array(classinfo *c) switch (c->name->text[1]) { case '[': /* c is an array of arrays. */ -/* comp = class_get(utf_new_intern(c->name->text + 1, namelen - 1)); */ comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1)); if (!comp) panic("Could not find component array class."); @@ -2561,7 +2700,6 @@ static arraydescriptor *class_link_array(classinfo *c) case 'L': /* c is an array of objects. */ -/* comp = class_get(utf_new_intern(c->name->text + 2, namelen - 3)); */ comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3)); if (!comp) panic("Could not find component class."); @@ -2571,8 +2709,11 @@ static arraydescriptor *class_link_array(classinfo *c) /* If the component type has not been linked, link it now */ if (comp && !comp->linked) { if (!comp->loaded) - class_load(comp); - class_link(comp); + if (!class_load(comp)) + return NULL; + + if (!class_link(comp)) + return NULL; } /* Allocate the arraydescriptor */ @@ -2680,8 +2821,6 @@ static classinfo *class_link_intern(classinfo *c); classinfo *class_link(classinfo *c) { classinfo *r; - s8 starttime; - s8 stoptime; /* enter a monitor on the class */ @@ -2695,8 +2834,12 @@ classinfo *class_link(classinfo *c) } /* measure time */ + + if (getcompilingtime) + compilingtime_stop(); + if (getloadingtime) - starttime = getcputime(); + loadingtime_start(); /* call the internal function */ r = class_link_intern(c); @@ -2706,10 +2849,12 @@ classinfo *class_link(classinfo *c) c->linked = false; /* measure time */ - if (getloadingtime) { - stoptime = getcputime(); - loadingtime += (stoptime - starttime); - } + + if (getloadingtime) + loadingtime_stop(); + + if (getcompilingtime) + compilingtime_start(); /* leave the monitor */ @@ -2724,54 +2869,61 @@ static classinfo *class_link_intern(classinfo *c) s4 supervftbllength; /* vftbllegnth of super class */ s4 vftbllength; /* vftbllength of current class */ s4 interfacetablelength; /* interface table length */ - classinfo *super = c->super; /* super class */ - classinfo *ic, *c2; /* intermediate class variables */ + classinfo *super; /* super class */ + classinfo *tc; /* temporary class variable */ vftbl_t *v; /* vftbl of current class */ s4 i; /* interface/method/field counter */ - arraydescriptor *arraydesc = NULL; /* descriptor for array classes */ + arraydescriptor *arraydesc; /* descriptor for array classes */ /* maybe the class is already linked */ if (c->linked) return c; + /* maybe the class is not loaded */ + if (!c->loaded) + if (!class_load(c)) + return NULL; + if (linkverbose) log_message_class("Linking class: ", c); /* ok, this class is somewhat linked */ c->linked = true; + arraydesc = NULL; + /* check interfaces */ for (i = 0; i < c->interfacescount; i++) { - ic = c->interfaces[i]; + tc = c->interfaces[i]; /* detect circularity */ - if (ic == c) { + if (tc == c) { *exceptionptr = new_exception_utfmessage(string_java_lang_ClassCircularityError, c->name); - return NULL; } - if (!ic->loaded) - if (!class_load(ic)) - return NULL; - - if (!ic->linked) - if (!class_link(ic)) + if (!tc->loaded) + if (!class_load(tc)) return NULL; - if (!(ic->flags & ACC_INTERFACE)) { - dolog("Specified interface is not declared as interface:"); - log_utf(ic->name); - dolog("in"); - log_utf(c->name); - panic("Specified interface is not declared as interface"); + if (!(tc->flags & ACC_INTERFACE)) { + *exceptionptr = + new_exception_message(string_java_lang_IncompatibleClassChangeError, + "Implementing class"); + return NULL; } + + if (!tc->linked) + if (!class_link(tc)) + return NULL; } - /* check super class */ + /* check super class */ + + super = c->super; if (super == NULL) { /* class java.lang.Object */ c->index = 0; @@ -2789,7 +2941,6 @@ static classinfo *class_link_intern(classinfo *c) *exceptionptr = new_exception_utfmessage(string_java_lang_ClassCircularityError, c->name); - return NULL; } @@ -2797,25 +2948,28 @@ static classinfo *class_link_intern(classinfo *c) if (!class_load(super)) return NULL; + if (super->flags & ACC_INTERFACE) { + /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */ + panic("Interface specified as super class"); + } + + /* Don't allow extending final classes */ + if (super->flags & ACC_FINAL) { + *exceptionptr = + new_exception_message(string_java_lang_VerifyError, + "Cannot inherit from final class"); + return NULL; + } + if (!super->linked) if (!class_link(super)) return NULL; - if (super->flags & ACC_INTERFACE) - panic("Interface specified as super class"); - /* handle array classes */ - /* The component class must have been linked already. */ - if (c->name->text[0] == '[') { - if ((arraydesc = class_link_array(c)) == NULL) { - panic("class_link: class_link_array"); - } - } + if (c->name->text[0] == '[') + if (!(arraydesc = class_link_array(c))) + return NULL; - /* Don't allow extending final classes */ - if (super->flags & ACC_FINAL) - panic("Trying to extend final class"); - if (c->flags & ACC_INTERFACE) c->index = interfaceindex++; else @@ -2834,26 +2988,26 @@ static classinfo *class_link_intern(classinfo *c) methodinfo *m = &(c->methods[i]); if (!(m->flags & ACC_STATIC)) { /* is instance method */ - classinfo *sc = super; - while (sc) { + tc = super; + + while (tc) { s4 j; - for (j = 0; j < sc->methodscount; j++) { - if (method_canoverwrite(m, &(sc->methods[j]))) { - if ((sc->methods[j].flags & ACC_PRIVATE) != 0) + for (j = 0; j < tc->methodscount; j++) { + if (method_canoverwrite(m, &(tc->methods[j]))) { + if (tc->methods[j].flags & ACC_PRIVATE) goto notfoundvftblindex; - if ((sc->methods[j].flags & ACC_FINAL) != 0) { - log_utf(c->name); - log_utf(sc->name); - log_utf(sc->methods[j].name); - log_utf(sc->methods[j].descriptor); - panic("Trying to overwrite final method"); + if (tc->methods[j].flags & ACC_FINAL) { + /* class a overrides final method . */ + *exceptionptr = + new_exception(string_java_lang_VerifyError); + return NULL; } - m->vftblindex = sc->methods[j].vftblindex; + m->vftblindex = tc->methods[j].vftblindex; goto foundvftblindex; } } - sc = sc->super; + tc = tc->super; } notfoundvftblindex: m->vftblindex = (vftbllength++); @@ -2871,14 +3025,14 @@ static classinfo *class_link_intern(classinfo *c) /* compute interfacetable length */ interfacetablelength = 0; - c2 = c; - while (c2) { - for (i = 0; i < c2->interfacescount; i++) { - s4 h = class_highestinterface(c2->interfaces[i]) + 1; + tc = c; + while (tc) { + for (i = 0; i < tc->interfacescount; i++) { + s4 h = class_highestinterface(tc->interfaces[i]) + 1; if (h > interfacetablelength) interfacetablelength = h; } - c2 = c2->super; + tc = tc->super; } /* allocate virtual function table */ @@ -2889,11 +3043,10 @@ static classinfo *class_link_intern(classinfo *c) v = (vftbl_t*) (((methodptr*) v) + (interfacetablelength - 1) * (interfacetablelength > 1)); c->header.vftbl = c->vftbl = v; -/* utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */ v->class = c; v->vftbllength = vftbllength; v->interfacetablelength = interfacetablelength; - v->arraydesc = arraydesc; + v->arraydesc = arraydesc; /* store interface index in vftbl */ if (c->flags & ACC_INTERFACE) @@ -2943,25 +3096,20 @@ static classinfo *class_link_intern(classinfo *c) /* add interfaces */ - for (c2 = c; c2 != NULL; c2 = c2->super) - for (i = 0; i < c2->interfacescount; i++) { - class_addinterface(c, c2->interfaces[i]); + for (tc = c; tc != NULL; tc = tc->super) { + for (i = 0; i < tc->interfacescount; i++) { + class_addinterface(c, tc->interfaces[i]); } + } /* add finalizer method (not for java.lang.Object) */ - if (super != NULL) { + if (super) { methodinfo *fi; - static utf *finame = NULL; - static utf *fidesc = NULL; - if (finame == NULL) - finame = utf_finalize; - if (fidesc == NULL) - fidesc = utf_fidesc; + fi = class_findmethod(c, utf_finalize, utf_fidesc); - fi = class_findmethod(c, finame, fidesc); - if (fi != NULL) { + if (fi) { if (!(fi->flags & ACC_STATIC)) { c->finalizer = fi; } @@ -3602,10 +3750,12 @@ static classinfo *class_init_intern(classinfo *c) int b; #endif + /* maybe the class is not already loaded */ if (!c->loaded) if (!class_load(c)) return NULL; + /* maybe the class is not already linked */ if (!c->linked) if (!class_link(c)) return NULL; @@ -3616,15 +3766,8 @@ static classinfo *class_init_intern(classinfo *c) #endif /* initialize super class */ - if (c->super) { - if (!c->super->loaded) - if (!class_load(c->super)) - return NULL; - - if (!c->super->linked) - if (!class_link(c->super)) - return NULL; + if (c->super) { if (!c->super->initialized) { if (initverbose) { char logtext[MAXLOGTEXT]; @@ -3641,15 +3784,8 @@ static classinfo *class_init_intern(classinfo *c) } /* initialize interface classes */ - for (i = 0; i < c->interfacescount; i++) { - if (!c->interfaces[i]->loaded) - if (!class_load(c->interfaces[i])) - return NULL; - - if (!c->interfaces[i]->linked) - if (!class_link(c->interfaces[i])) - return NULL; + for (i = 0; i < c->interfacescount; i++) { if (!c->interfaces[i]->initialized) { if (initverbose) { char logtext[MAXLOGTEXT]; @@ -3679,8 +3815,9 @@ static classinfo *class_init_intern(classinfo *c) return c; } - if (!(m->flags & ACC_STATIC)) - panic("Class initializer is not static!"); + /* Sun's and IBM's JVM don't care about the static flag */ +/* if (!(m->flags & ACC_STATIC)) { */ +/* panic("Class initializer is not static!"); */ if (initverbose) log_message_class("Starting static class initializer for class: ", c); @@ -3700,14 +3837,14 @@ static classinfo *class_init_intern(classinfo *c) /* we have an exception or error */ if (*exceptionptr) { + /* class is NOT initialized */ + c->initialized = false; + /* is this an exception, than wrap it */ if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) { java_objectheader *xptr; java_objectheader *cause; - /* class is NOT initialized */ - c->initialized = false; - /* get the cause */ cause = *exceptionptr; @@ -3996,9 +4133,9 @@ void class_showmethods (classinfo *c) *******************************************************************************/ -void create_primitive_classes() +static bool create_primitive_classes() { - int i; + s4 i; for (i = 0; i < PRIMITIVETYPE_COUNT; i++) { /* create primitive class */ @@ -4009,7 +4146,8 @@ void create_primitive_classes() /* prevent loader from loading primitive class */ c->loaded = true; - class_link(c); + if (!class_link(c)) + return false; primitivetype_table[i].class_primitive = c; @@ -4025,10 +4163,13 @@ void create_primitive_classes() primitivetype_table[i].arrayclass = c; c->loaded = true; if (!c->linked) - class_link(c); + if (!class_link(c)) + return false; primitivetype_table[i].arrayvftbl = c->vftbl; } } + + return true; } @@ -4288,23 +4429,20 @@ void loader_init(u1 *stackbottom) /* These classes have to be created now because the classinfo * pointers are used in the loading code. */ - class_java_lang_Object = - class_new_intern(utf_java_lang_Object); + class_java_lang_Object = class_new_intern(utf_java_lang_Object); class_load(class_java_lang_Object); class_link(class_java_lang_Object); - class_java_lang_String = - class_new_intern(utf_new_char("java/lang/String")); + class_java_lang_String = class_new(utf_new_char("java/lang/String")); class_load(class_java_lang_String); class_link(class_java_lang_String); - class_java_lang_Cloneable = - class_new_intern(utf_new_char("java/lang/Cloneable")); + class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable")); class_load(class_java_lang_Cloneable); class_link(class_java_lang_Cloneable); class_java_io_Serializable = - class_new_intern(utf_new_char("java/io/Serializable")); + class_new(utf_new_char("java/io/Serializable")); class_load(class_java_io_Serializable); class_link(class_java_io_Serializable); @@ -4324,21 +4462,13 @@ void loader_init(u1 *stackbottom) } -static void loader_compute_class_values(classinfo *c) -{ - classinfo *subs; - - c->vftbl->baseval = ++classvalue; +/* loader_compute_subclasses *************************************************** - subs = c->sub; - while (subs != NULL) { - loader_compute_class_values(subs); - subs = subs->nextsub; - } + XXX - c->vftbl->diffval = classvalue - c->vftbl->baseval; -} +*******************************************************************************/ +static void loader_compute_class_values(classinfo *c); void loader_compute_subclasses(classinfo *c) { @@ -4363,6 +4493,7 @@ void loader_compute_subclasses(classinfo *c) classvalue = 0; /* this is the java.lang.Object special case */ + if (!class_java_lang_Object) { loader_compute_class_values(c); @@ -4380,6 +4511,28 @@ void loader_compute_subclasses(classinfo *c) } +/* loader_compute_class_values ************************************************* + + XXX + +*******************************************************************************/ + +static void loader_compute_class_values(classinfo *c) +{ + classinfo *subs; + + c->vftbl->baseval = ++classvalue; + + subs = c->sub; + while (subs) { + loader_compute_class_values(subs); + subs = subs->nextsub; + } + + c->vftbl->diffval = classvalue - c->vftbl->baseval; +} + + /******************** Function: loader_close *********************************** Frees all resources