1 /* src/vm/loader.c - class loader functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
35 $Id: loader.c 2148 2005-03-30 16:49:40Z twisti $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "native/include/java_lang_Throwable.h"
50 #if defined(USE_THREADS)
51 # if defined(NATIVE_THREADS)
52 # include "threads/native/threads.h"
54 # include "threads/green/threads.h"
55 # include "threads/green/locks.h"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
61 #include "vm/exceptions.h"
62 #include "vm/builtin.h"
63 #include "vm/global.h"
64 #include "vm/linker.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/statistics.h"
68 #include "vm/stringlocal.h"
69 #include "vm/tables.h"
72 # include "vm/unzip.h"
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen.inc.h"
84 /********************************************************************
85 list of classpath entries (either filesystem directories or
87 ********************************************************************/
89 classpath_info *classpath_entries = NULL;
92 /******************* function: checkfielddescriptor ****************************
94 checks whether a field-descriptor is valid and aborts otherwise
95 all referenced classes are inserted into the list of unloaded classes
97 *******************************************************************************/
99 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
101 class_from_descriptor(utf_ptr,end_pos,NULL,
103 | CLASSLOAD_NULLPRIMITIVE
105 | CLASSLOAD_CHECKEND);
107 /* XXX use the following if -noverify */
109 char *tstart; /* pointer to start of classname */
111 char *start = utf_ptr;
113 switch (*utf_ptr++) {
127 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
128 panic ("Ill formed descriptor");
132 panic ("Ill formed descriptor");
135 /* exceeding characters */
136 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
141 /******************* function checkmethoddescriptor ****************************
143 checks whether a method-descriptor is valid and aborts otherwise.
144 All referenced classes are inserted into the list of unloaded classes.
146 The number of arguments is returned. A long or double argument is counted
149 *******************************************************************************/
151 static int checkmethoddescriptor(classinfo *c, utf *descriptor)
153 char *utf_ptr; /* current position in utf text */
154 char *end_pos; /* points behind utf string */
155 s4 argcount = 0; /* number of arguments */
157 utf_ptr = descriptor->text;
158 end_pos = utf_end(descriptor);
160 /* method descriptor must start with parenthesis */
161 if (utf_ptr == end_pos || *utf_ptr++ != '(')
162 panic ("Missing '(' in method descriptor");
164 /* check arguments */
165 while (utf_ptr != end_pos && *utf_ptr != ')') {
166 /* We cannot count the this argument here because
167 * we don't know if the method is static. */
168 if (*utf_ptr == 'J' || *utf_ptr == 'D')
172 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
174 | CLASSLOAD_NULLPRIMITIVE
178 if (utf_ptr == end_pos)
179 panic("Missing ')' in method descriptor");
181 utf_ptr++; /* skip ')' */
183 class_from_descriptor(utf_ptr,
187 CLASSLOAD_NULLPRIMITIVE |
190 if (argcount > 255) {
192 new_classformaterror(c, "Too many arguments in signature");
199 /* XXX use the following if -noverify */
201 /* check arguments */
202 while ((c = *utf_ptr++) != ')') {
219 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
220 panic ("Ill formed method descriptor");
224 panic ("Ill formed methodtype-descriptor");
228 /* check returntype */
230 /* returntype void */
231 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
234 /* treat as field-descriptor */
235 checkfielddescriptor (utf_ptr,end_pos);
240 /* loader_init *****************************************************************
242 Initializes all lists and loads all classes required for the system
245 *******************************************************************************/
247 bool loader_init(u1 *stackbottom)
251 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
252 /* Initialize the monitor pointer for zip/jar file locking. */
254 for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
255 if (cpi->type == CLASSPATH_ARCHIVE)
256 initObjectLock(&cpi->header);
260 /* load some important classes */
262 if (!load_class_bootstrap(class_java_lang_Object))
265 if (!load_class_bootstrap(class_java_lang_String))
268 if (!load_class_bootstrap(class_java_lang_Cloneable))
271 if (!load_class_bootstrap(class_java_io_Serializable))
274 #if defined(USE_THREADS)
275 if (stackbottom != 0)
283 /************* functions for reading classdata *********************************
285 getting classdata in blocks of variable size
286 (8,16,32,64-bit integer or float)
288 *******************************************************************************/
290 /* check_classbuffer_size ******************************************************
292 assert that at least <len> bytes are left to read
293 <len> is limited to the range of non-negative s4 values
295 *******************************************************************************/
297 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
299 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
301 new_classformaterror((cb)->class, "Truncated class file");
310 /* suck_nbytes *****************************************************************
312 transfer block of classfile data into a buffer
314 *******************************************************************************/
316 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
318 memcpy(buffer, cb->pos + 1, len);
323 /* skip_nbytes ****************************************************************
325 skip block of classfile data
327 *******************************************************************************/
329 inline void skip_nbytes(classbuffer *cb, s4 len)
335 inline u1 suck_u1(classbuffer *cb)
341 inline u2 suck_u2(classbuffer *cb)
345 return ((u2) a << 8) + (u2) b;
349 inline u4 suck_u4(classbuffer *cb)
355 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
359 /* get u8 from classfile data */
360 static u8 suck_u8(classbuffer *cb)
366 return (hi << 32) + lo;
369 v.high = suck_u4(cb);
376 /* get float from classfile data */
377 static float suck_float(classbuffer *cb)
385 for (i = 0; i < 4; i++)
386 buffer[3 - i] = suck_u1(cb);
388 memcpy((u1*) (&f), buffer, 4);
390 suck_nbytes((u1*) (&f), cb, 4);
393 if (sizeof(float) != 4) {
394 *exceptionptr = new_exception_message(string_java_lang_InternalError,
395 "Incompatible float-format");
397 /* XXX should we exit in such a case? */
398 throw_exception_exit();
405 /* get double from classfile data */
406 static double suck_double(classbuffer *cb)
414 for (i = 0; i < 8; i++)
415 buffer[7 - i] = suck_u1(cb);
417 memcpy((u1*) (&d), buffer, 8);
419 suck_nbytes((u1*) (&d), cb, 8);
422 if (sizeof(double) != 8) {
423 *exceptionptr = new_exception_message(string_java_lang_InternalError,
424 "Incompatible double-format");
426 /* XXX should we exit in such a case? */
427 throw_exception_exit();
434 /************************** function suck_init *********************************
436 called once at startup, sets the searchpath for the classfiles
438 *******************************************************************************/
440 void suck_init(char *classpath)
448 classpath_info *lastcpi;
452 /* search for last classpath entry (only if there already some) */
454 if ((lastcpi = classpath_entries)) {
455 while (lastcpi->next)
456 lastcpi = lastcpi->next;
459 for (start = classpath; (*start) != '\0';) {
461 /* search for ':' delimiter to get the end of the current entry */
462 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
466 filenamelen = end - start;
468 if (filenamelen > 3) {
469 if (strncasecmp(end - 3, "zip", 3) == 0 ||
470 strncasecmp(end - 3, "jar", 3) == 0) {
475 /* save classpath entries as absolute pathnames */
480 if (*start != '/') { /* XXX fix me for win32 */
482 cwdlen = strlen(cwd) + strlen("/");
485 /* allocate memory for filename and fill it */
487 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
491 strcpy(filename, cwd);
492 strcat(filename, "/");
493 strncat(filename, start, filenamelen);
495 /* add cwd length to file length */
496 filenamelen += cwdlen;
499 strncpy(filename, start, filenamelen);
500 filename[filenamelen] = '\0';
506 #if defined(USE_ZLIB)
507 unzFile uf = unzOpen(filename);
510 cpi = NEW(classpath_info);
511 cpi->type = CLASSPATH_ARCHIVE;
514 cpi->path = filename;
515 cpi->pathlen = filenamelen;
519 throw_cacao_exception_exit(string_java_lang_InternalError,
520 "zip/jar files not supported");
524 cpi = NEW(classpath_info);
525 cpi->type = CLASSPATH_PATH;
528 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
529 filename[filenamelen] = '/';
530 filename[filenamelen + 1] = '\0';
534 cpi->path = filename;
535 cpi->pathlen = filenamelen;
538 /* attach current classpath entry */
541 if (!classpath_entries)
542 classpath_entries = cpi;
550 /* goto next classpath entry, skip ':' delimiter */
562 void create_all_classes()
566 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
567 #if defined(USE_ZLIB)
568 if (cpi->type == CLASSPATH_ARCHIVE) {
572 s = (unz_s *) cpi->uf;
573 ce = s->cacao_dir_list;
576 (void) class_new(ce->name);
582 #if defined(USE_ZLIB)
589 /* suck_start ******************************************************************
591 Returns true if classbuffer is already loaded or a file for the
592 specified class has succussfully been read in. All directories of
593 the searchpath are used to find the classfile (<classname>.class).
594 Returns false if no classfile is found and writes an error message.
596 *******************************************************************************/
598 classbuffer *suck_start(classinfo *c)
610 /* initialize return value */
615 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
616 filename = MNEW(char, filenamelen);
618 utf_sprint(filename, c->name);
619 strcat(filename, ".class");
621 /* walk through all classpath entries */
623 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
624 #if defined(USE_ZLIB)
625 if (cpi->type == CLASSPATH_ARCHIVE) {
627 #if defined(USE_THREADS)
628 /* enter a monitor on zip/jar archives */
630 builtin_monitorenter((java_objectheader *) cpi);
633 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
634 unz_file_info file_info;
636 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
637 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
638 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
639 cb = NEW(classbuffer);
641 cb->size = file_info.uncompressed_size;
642 cb->data = MNEW(u1, cb->size);
643 cb->pos = cb->data - 1;
645 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
647 if (len != cb->size) {
649 log_text("Error while unzipping");
656 log_text("Error while opening file in archive");
660 log_text("Error while retrieving fileinfo");
663 unzCloseCurrentFile(cpi->uf);
665 #if defined(USE_THREADS)
666 /* leave the monitor */
668 builtin_monitorexit((java_objectheader *) cpi);
672 #endif /* defined(USE_ZLIB) */
674 path = MNEW(char, cpi->pathlen + filenamelen);
675 strcpy(path, cpi->path);
676 strcat(path, filename);
678 classfile = fopen(path, "r");
680 if (classfile) { /* file exists */
681 if (!stat(path, &buffer)) { /* read classfile data */
682 cb = NEW(classbuffer);
684 cb->size = buffer.st_size;
685 cb->data = MNEW(u1, cb->size);
686 cb->pos = cb->data - 1;
688 /* read class data */
689 len = fread(cb->data, 1, cb->size, classfile);
691 if (len != buffer.st_size) {
693 /* if (ferror(classfile)) { */
702 MFREE(path, char, cpi->pathlen + filenamelen);
703 #if defined(USE_ZLIB)
710 dolog("Warning: Can not open class file '%s'", filename);
712 MFREE(filename, char, filenamelen);
718 /************************** function suck_stop *********************************
720 frees memory for buffer with classfile data.
721 Caution: this function may only be called if buffer has been allocated
722 by suck_start with reading a file
724 *******************************************************************************/
726 void suck_stop(classbuffer *cb)
730 MFREE(cb->data, u1, cb->size);
731 FREE(cb, classbuffer);
735 /******************************************************************************/
736 /******************* Some support functions ***********************************/
737 /******************************************************************************/
739 void fprintflags (FILE *fp, u2 f)
741 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
742 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
743 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
744 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
745 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
746 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
747 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
748 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
749 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
750 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
751 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
755 /********** internal function: printflags (only for debugging) ***************/
757 void printflags(u2 f)
759 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
760 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
761 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
762 if ( f & ACC_STATIC ) printf (" STATIC");
763 if ( f & ACC_FINAL ) printf (" FINAL");
764 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
765 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
766 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
767 if ( f & ACC_NATIVE ) printf (" NATIVE");
768 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
769 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
773 /********************** Function: skipattributebody ****************************
775 skips an attribute after the 16 bit reference to attribute_name has already
778 *******************************************************************************/
780 static bool skipattributebody(classbuffer *cb)
784 if (!check_classbuffer_size(cb, 4))
789 if (!check_classbuffer_size(cb, len))
792 skip_nbytes(cb, len);
798 /************************* Function: skipattributes ****************************
800 skips num attribute structures
802 *******************************************************************************/
804 static bool skipattributes(classbuffer *cb, u4 num)
809 for (i = 0; i < num; i++) {
810 if (!check_classbuffer_size(cb, 2 + 4))
816 if (!check_classbuffer_size(cb, len))
819 skip_nbytes(cb, len);
826 /******************** function:: class_getconstant *****************************
828 retrieves the value at position 'pos' of the constantpool of a class
829 if the type of the value is other than 'ctype' the system is stopped
831 *******************************************************************************/
833 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
835 /* check index and type of constantpool entry */
836 /* (pos == 0 is caught by type comparison) */
837 if (pos >= c->cpcount || c->cptags[pos] != ctype) {
838 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
842 return c->cpinfos[pos];
846 /******************** function: innerclass_getconstant ************************
848 like class_getconstant, but if cptags is ZERO null is returned
850 *******************************************************************************/
852 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
854 /* invalid position in constantpool */
855 if (pos >= c->cpcount) {
856 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
860 /* constantpool entry of type 0 */
864 /* check type of constantpool entry */
865 if (c->cptags[pos] != ctype) {
866 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
870 return c->cpinfos[pos];
874 /********************* Function: class_constanttype ****************************
876 Determines the type of a class entry in the ConstantPool
878 *******************************************************************************/
880 u4 class_constanttype(classinfo *c, u4 pos)
882 if (pos <= 0 || pos >= c->cpcount) {
883 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
887 return c->cptags[pos];
891 /* load_constantpool ***********************************************************
893 Loads the constantpool of a class, the entries are transformed into
894 a simpler format by resolving references (a detailed overview of
895 the compact structures can be found in global.h).
897 *******************************************************************************/
899 static bool load_constantpool(classbuffer *cb)
902 /* The following structures are used to save information which cannot be
903 processed during the first pass. After the complete constantpool has
904 been traversed the references can be resolved.
905 (only in specific order) */
907 /* CONSTANT_Class entries */
908 typedef struct forward_class {
909 struct forward_class *next;
914 /* CONSTANT_String */
915 typedef struct forward_string {
916 struct forward_string *next;
921 /* CONSTANT_NameAndType */
922 typedef struct forward_nameandtype {
923 struct forward_nameandtype *next;
927 } forward_nameandtype;
929 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
930 typedef struct forward_fieldmethint {
931 struct forward_fieldmethint *next;
935 u2 nameandtype_index;
936 } forward_fieldmethint;
942 forward_class *forward_classes = NULL;
943 forward_string *forward_strings = NULL;
944 forward_nameandtype *forward_nameandtypes = NULL;
945 forward_fieldmethint *forward_fieldmethints = NULL;
949 forward_nameandtype *nfn;
950 forward_fieldmethint *nff;
958 /* number of entries in the constant_pool table plus one */
959 if (!check_classbuffer_size(cb, 2))
962 cpcount = c->cpcount = suck_u2(cb);
964 /* allocate memory */
965 cptags = c->cptags = MNEW(u1, cpcount);
966 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
969 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
973 #if defined(STATISTICS)
975 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
978 /* initialize constantpool */
979 for (idx = 0; idx < cpcount; idx++) {
980 cptags[idx] = CONSTANT_UNUSED;
985 /******* first pass *******/
986 /* entries which cannot be resolved now are written into
987 temporary structures and traversed again later */
990 while (idx < cpcount) {
993 /* get constant type */
994 if (!check_classbuffer_size(cb, 1))
1000 case CONSTANT_Class:
1001 nfc = NEW(forward_class);
1003 nfc->next = forward_classes;
1004 forward_classes = nfc;
1006 nfc->thisindex = idx;
1007 /* reference to CONSTANT_NameAndType */
1008 if (!check_classbuffer_size(cb, 2))
1011 nfc->name_index = suck_u2(cb);
1016 case CONSTANT_String:
1017 nfs = NEW(forward_string);
1019 nfs->next = forward_strings;
1020 forward_strings = nfs;
1022 nfs->thisindex = idx;
1024 /* reference to CONSTANT_Utf8_info with string characters */
1025 if (!check_classbuffer_size(cb, 2))
1028 nfs->string_index = suck_u2(cb);
1033 case CONSTANT_NameAndType:
1034 nfn = NEW(forward_nameandtype);
1036 nfn->next = forward_nameandtypes;
1037 forward_nameandtypes = nfn;
1039 nfn->thisindex = idx;
1041 if (!check_classbuffer_size(cb, 2 + 2))
1044 /* reference to CONSTANT_Utf8_info containing simple name */
1045 nfn->name_index = suck_u2(cb);
1047 /* reference to CONSTANT_Utf8_info containing field or method
1049 nfn->sig_index = suck_u2(cb);
1054 case CONSTANT_Fieldref:
1055 case CONSTANT_Methodref:
1056 case CONSTANT_InterfaceMethodref:
1057 nff = NEW(forward_fieldmethint);
1059 nff->next = forward_fieldmethints;
1060 forward_fieldmethints = nff;
1062 nff->thisindex = idx;
1066 if (!check_classbuffer_size(cb, 2 + 2))
1069 /* class or interface type that contains the declaration of the
1071 nff->class_index = suck_u2(cb);
1073 /* name and descriptor of the field or method */
1074 nff->nameandtype_index = suck_u2(cb);
1079 case CONSTANT_Integer: {
1080 constant_integer *ci = NEW(constant_integer);
1082 #if defined(STATISTICS)
1084 count_const_pool_len += sizeof(constant_integer);
1087 if (!check_classbuffer_size(cb, 4))
1090 ci->value = suck_s4(cb);
1091 cptags[idx] = CONSTANT_Integer;
1098 case CONSTANT_Float: {
1099 constant_float *cf = NEW(constant_float);
1101 #if defined(STATISTICS)
1103 count_const_pool_len += sizeof(constant_float);
1106 if (!check_classbuffer_size(cb, 4))
1109 cf->value = suck_float(cb);
1110 cptags[idx] = CONSTANT_Float;
1117 case CONSTANT_Long: {
1118 constant_long *cl = NEW(constant_long);
1120 #if defined(STATISTICS)
1122 count_const_pool_len += sizeof(constant_long);
1125 if (!check_classbuffer_size(cb, 8))
1128 cl->value = suck_s8(cb);
1129 cptags[idx] = CONSTANT_Long;
1132 if (idx > cpcount) {
1134 new_classformaterror(c, "Invalid constant pool entry");
1140 case CONSTANT_Double: {
1141 constant_double *cd = NEW(constant_double);
1143 #if defined(STATISTICS)
1145 count_const_pool_len += sizeof(constant_double);
1148 if (!check_classbuffer_size(cb, 8))
1151 cd->value = suck_double(cb);
1152 cptags[idx] = CONSTANT_Double;
1155 if (idx > cpcount) {
1157 new_classformaterror(c, "Invalid constant pool entry");
1163 case CONSTANT_Utf8: {
1166 /* number of bytes in the bytes array (not string-length) */
1167 if (!check_classbuffer_size(cb, 2))
1170 length = suck_u2(cb);
1171 cptags[idx] = CONSTANT_Utf8;
1173 /* validate the string */
1174 if (!check_classbuffer_size(cb, length))
1178 !is_valid_utf((char *) (cb->pos + 1),
1179 (char *) (cb->pos + 1 + length))) {
1180 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1181 panic("Invalid UTF-8 string");
1183 /* insert utf-string into the utf-symboltable */
1184 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1186 /* skip bytes of the string (buffer size check above) */
1187 skip_nbytes(cb, length);
1194 new_classformaterror(c, "Illegal constant pool type");
1200 /* resolve entries in temporary structures */
1202 while (forward_classes) {
1204 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1206 if (opt_verify && !is_valid_name_utf(name))
1207 panic("Class reference with invalid name");
1209 cptags[forward_classes->thisindex] = CONSTANT_Class;
1210 /* retrieve class from class-table */
1213 tc = class_new_intern(name);
1215 if (!load_class_from_classloader(tc, c->classloader))
1218 /* link the class later, because we cannot link the class currently
1220 list_addfirst(&unlinkedclasses, tc);
1222 cpinfos[forward_classes->thisindex] = tc;
1225 cpinfos[forward_classes->thisindex] = class_new(name);
1228 nfc = forward_classes;
1229 forward_classes = forward_classes->next;
1230 FREE(nfc, forward_class);
1233 while (forward_strings) {
1235 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1237 /* resolve utf-string */
1238 cptags[forward_strings->thisindex] = CONSTANT_String;
1239 cpinfos[forward_strings->thisindex] = text;
1241 nfs = forward_strings;
1242 forward_strings = forward_strings->next;
1243 FREE(nfs, forward_string);
1246 while (forward_nameandtypes) {
1247 constant_nameandtype *cn = NEW(constant_nameandtype);
1249 #if defined(STATISTICS)
1251 count_const_pool_len += sizeof(constant_nameandtype);
1254 /* resolve simple name and descriptor */
1255 cn->name = class_getconstant(c,
1256 forward_nameandtypes->name_index,
1259 cn->descriptor = class_getconstant(c,
1260 forward_nameandtypes->sig_index,
1265 if (!is_valid_name_utf(cn->name)) {
1267 new_classformaterror(c,
1268 "Illegal Field name \"%s\"",
1274 /* disallow referencing <clinit> among others */
1275 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1277 new_exception_utfmessage(string_java_lang_InternalError,
1283 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1284 cpinfos[forward_nameandtypes->thisindex] = cn;
1286 nfn = forward_nameandtypes;
1287 forward_nameandtypes = forward_nameandtypes->next;
1288 FREE(nfn, forward_nameandtype);
1291 while (forward_fieldmethints) {
1292 constant_nameandtype *nat;
1293 constant_FMIref *fmi = NEW(constant_FMIref);
1295 #if defined(STATISTICS)
1297 count_const_pool_len += sizeof(constant_FMIref);
1299 /* resolve simple name and descriptor */
1300 nat = class_getconstant(c,
1301 forward_fieldmethints->nameandtype_index,
1302 CONSTANT_NameAndType);
1304 fmi->class = class_getconstant(c,
1305 forward_fieldmethints->class_index,
1307 fmi->name = nat->name;
1308 fmi->descriptor = nat->descriptor;
1310 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1311 cpinfos[forward_fieldmethints->thisindex] = fmi;
1313 switch (forward_fieldmethints->tag) {
1314 case CONSTANT_Fieldref: /* check validity of descriptor */
1315 checkfielddescriptor(fmi->descriptor->text,
1316 utf_end(fmi->descriptor));
1318 case CONSTANT_InterfaceMethodref:
1319 case CONSTANT_Methodref: /* check validity of descriptor */
1320 checkmethoddescriptor(c, fmi->descriptor);
1324 nff = forward_fieldmethints;
1325 forward_fieldmethints = forward_fieldmethints->next;
1326 FREE(nff, forward_fieldmethint);
1329 /* everything was ok */
1335 /* load_field ******************************************************************
1337 Load everything about a class field from the class file and fill a
1338 'fieldinfo' structure. For static fields, space in the data segment
1341 *******************************************************************************/
1343 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1345 static bool load_field(classbuffer *cb, fieldinfo *f)
1350 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1355 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1358 f->flags = suck_u2(cb);
1360 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1364 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1370 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1371 *exceptionptr = new_classformaterror(c,
1372 "Illegal Field name \"%s\"",
1377 /* check flag consistency */
1378 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1380 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1381 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1383 new_classformaterror(c,
1384 "Illegal field modifiers: 0x%X",
1389 if (c->flags & ACC_INTERFACE) {
1390 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1391 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1392 f->flags & ACC_TRANSIENT) {
1394 new_classformaterror(c,
1395 "Illegal field modifiers: 0x%X",
1401 /* check descriptor */
1402 checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
1405 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1406 f->offset = 0; /* offset from start of object */
1411 case TYPE_INT: f->value.i = 0; break;
1412 case TYPE_FLOAT: f->value.f = 0.0; break;
1413 case TYPE_DOUBLE: f->value.d = 0.0; break;
1414 case TYPE_ADDRESS: f->value.a = NULL; break;
1417 f->value.l = 0; break;
1419 f->value.l.low = 0; f->value.l.high = 0; break;
1423 /* read attributes */
1424 if (!check_classbuffer_size(cb, 2))
1427 attrnum = suck_u2(cb);
1428 for (i = 0; i < attrnum; i++) {
1429 if (!check_classbuffer_size(cb, 2))
1432 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1435 if (u == utf_ConstantValue) {
1436 if (!check_classbuffer_size(cb, 4 + 2))
1439 /* check attribute length */
1440 if (suck_u4(cb) != 2) {
1442 new_classformaterror(c, "Wrong size for VALUE attribute");
1446 /* constant value attribute */
1447 if (pindex != field_load_NOVALUE) {
1449 new_classformaterror(c,
1450 "Multiple ConstantValue attributes");
1454 /* index of value in constantpool */
1455 pindex = suck_u2(cb);
1457 /* initialize field with value from constantpool */
1460 constant_integer *ci;
1462 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1465 f->value.i = ci->value;
1472 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1475 f->value.l = cl->value;
1482 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1485 f->value.f = cf->value;
1490 constant_double *cd;
1492 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1495 f->value.d = cd->value;
1500 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1503 /* create javastring from compressed utf8-string */
1504 f->value.a = literalstring_new(u);
1508 log_text("Invalid Constant - Type");
1512 /* unknown attribute */
1513 if (!skipattributebody(cb))
1518 /* everything was ok */
1524 /* load_method *****************************************************************
1526 Loads a method from the class file and fills an existing
1527 'methodinfo' structure. For native methods, the function pointer
1528 field is set to the real function pointer, for JavaVM methods a
1529 pointer to the compiler is used preliminarily.
1531 *******************************************************************************/
1533 static bool load_method(classbuffer *cb, methodinfo *m)
1544 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1545 initObjectLock(&m->header);
1550 count_all_methods++;
1553 m->thrownexceptionscount = 0;
1554 m->linenumbercount = 0;
1557 m->nativelyoverloaded = false;
1559 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1562 m->flags = suck_u2(cb);
1564 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1568 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1573 if (!is_valid_name_utf(m->name))
1574 panic("Method with invalid name");
1576 if (m->name->text[0] == '<'
1577 && m->name != utf_init && m->name != utf_clinit)
1578 panic("Method with invalid special name");
1581 argcount = checkmethoddescriptor(c, m->descriptor);
1583 if (!(m->flags & ACC_STATIC))
1584 argcount++; /* count the 'this' argument */
1587 if (argcount > 255) {
1589 new_classformaterror(c, "Too many arguments in signature");
1593 /* check flag consistency */
1594 if (m->name != utf_clinit) {
1595 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1597 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1599 new_classformaterror(c,
1600 "Illegal method modifiers: 0x%X",
1605 if (m->flags & ACC_ABSTRACT) {
1606 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1607 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1609 new_classformaterror(c,
1610 "Illegal method modifiers: 0x%X",
1616 if (c->flags & ACC_INTERFACE) {
1617 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1619 new_classformaterror(c,
1620 "Illegal method modifiers: 0x%X",
1626 if (m->name == utf_init) {
1627 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1628 ACC_NATIVE | ACC_ABSTRACT))
1629 panic("Instance initialization method has invalid flags set");
1635 m->basicblockcount = 0;
1636 m->basicblocks = NULL;
1637 m->basicblockindex = NULL;
1638 m->instructioncount = 0;
1639 m->instructions = NULL;
1642 m->exceptiontable = NULL;
1643 m->stubroutine = NULL;
1645 m->entrypoint = NULL;
1646 m->methodUsed = NOTUSED;
1649 m->subRedefsUsed = 0;
1653 if (!check_classbuffer_size(cb, 2))
1656 attrnum = suck_u2(cb);
1657 for (i = 0; i < attrnum; i++) {
1660 if (!check_classbuffer_size(cb, 2))
1663 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1666 if (aname == utf_Code) {
1667 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1669 new_classformaterror(c,
1670 "Code attribute in native or abstract methods");
1677 new_classformaterror(c, "Multiple Code attributes");
1682 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1686 m->maxstack = suck_u2(cb);
1687 m->maxlocals = suck_u2(cb);
1689 if (m->maxlocals < argcount) {
1691 new_classformaterror(c, "Arguments can't fit into locals");
1696 if (!check_classbuffer_size(cb, 4))
1699 m->jcodelength = suck_u4(cb);
1701 if (m->jcodelength == 0) {
1703 new_classformaterror(c, "Code of a method has length 0");
1708 if (m->jcodelength > 65535) {
1710 new_classformaterror(c,
1711 "Code of a method longer than 65535 bytes");
1716 if (!check_classbuffer_size(cb, m->jcodelength))
1719 m->jcode = MNEW(u1, m->jcodelength);
1720 suck_nbytes(m->jcode, cb, m->jcodelength);
1722 if (!check_classbuffer_size(cb, 2))
1725 m->exceptiontablelength = suck_u2(cb);
1726 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1729 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1731 #if defined(STATISTICS)
1733 count_vmcode_len += m->jcodelength + 18;
1734 count_extable_len += 8 * m->exceptiontablelength;
1738 for (j = 0; j < m->exceptiontablelength; j++) {
1740 m->exceptiontable[j].startpc = suck_u2(cb);
1741 m->exceptiontable[j].endpc = suck_u2(cb);
1742 m->exceptiontable[j].handlerpc = suck_u2(cb);
1746 m->exceptiontable[j].catchtype = NULL;
1749 if (!(m->exceptiontable[j].catchtype =
1750 class_getconstant(c, idx, CONSTANT_Class)))
1755 if (!check_classbuffer_size(cb, 2))
1758 codeattrnum = suck_u2(cb);
1760 for (; codeattrnum > 0; codeattrnum--) {
1763 if (!check_classbuffer_size(cb, 2))
1766 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1769 if (caname == utf_LineNumberTable) {
1772 if (!check_classbuffer_size(cb, 4 + 2))
1776 m->linenumbercount = suck_u2(cb);
1778 if (!check_classbuffer_size(cb,
1779 (2 + 2) * m->linenumbercount))
1782 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1784 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1785 m->linenumbers[lncid].start_pc = suck_u2(cb);
1786 m->linenumbers[lncid].line_number = suck_u2(cb);
1790 if (!skipattributes(cb, codeattrnum))
1796 if (!skipattributebody(cb))
1801 } else if (aname == utf_Exceptions) {
1804 if (m->thrownexceptions) {
1806 new_classformaterror(c, "Multiple Exceptions attributes");
1810 if (!check_classbuffer_size(cb, 4 + 2))
1813 suck_u4(cb); /* length */
1814 m->thrownexceptionscount = suck_u2(cb);
1816 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1819 m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1821 for (j = 0; j < m->thrownexceptionscount; j++) {
1822 if (!((m->thrownexceptions)[j] =
1823 class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1828 if (!skipattributebody(cb))
1833 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1834 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1839 /* everything was ok */
1845 /* load_attribute **************************************************************
1847 Read attributes from classfile.
1849 *******************************************************************************/
1851 static bool load_attributes(classbuffer *cb, u4 num)
1859 for (i = 0; i < num; i++) {
1860 /* retrieve attribute name */
1861 if (!check_classbuffer_size(cb, 2))
1864 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1867 if (aname == utf_InnerClasses) {
1868 /* innerclasses attribute */
1869 if (c->innerclass) {
1871 new_classformaterror(c, "Multiple InnerClasses attributes");
1875 if (!check_classbuffer_size(cb, 4 + 2))
1878 /* skip attribute length */
1881 /* number of records */
1882 c->innerclasscount = suck_u2(cb);
1884 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1887 /* allocate memory for innerclass structure */
1888 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1890 for (j = 0; j < c->innerclasscount; j++) {
1891 /* The innerclass structure contains a class with an encoded
1892 name, its defining scope, its simple name and a bitmask of
1893 the access flags. If an inner class is not a member, its
1894 outer_class is NULL, if a class is anonymous, its name is
1897 innerclassinfo *info = c->innerclass + j;
1900 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1902 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1904 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1905 info->flags = suck_u2(cb);
1908 } else if (aname == utf_SourceFile) {
1909 if (!check_classbuffer_size(cb, 4 + 2))
1912 if (suck_u4(cb) != 2) {
1914 new_classformaterror(c, "Wrong size for VALUE attribute");
1918 if (c->sourcefile) {
1920 new_classformaterror(c, "Multiple SourceFile attributes");
1924 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1928 /* unknown attribute */
1929 if (!skipattributebody(cb))
1938 /***************** Function: print_arraydescriptor ****************************
1940 Debugging helper for displaying an arraydescriptor
1942 *******************************************************************************/
1944 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
1947 fprintf(file, "<NULL>");
1952 if (desc->componentvftbl) {
1953 if (desc->componentvftbl->class)
1954 utf_fprint(file, desc->componentvftbl->class->name);
1956 fprintf(file, "<no classinfo>");
1962 if (desc->elementvftbl) {
1963 if (desc->elementvftbl->class)
1964 utf_fprint(file, desc->elementvftbl->class->name);
1966 fprintf(file, "<no classinfo>");
1970 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
1971 desc->dataoffset, desc->componentsize);
1975 /* load_class_from_classloader *************************************************
1979 *******************************************************************************/
1981 classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
1985 /* if other class loader than bootstrap, call it */
1990 lc = class_resolveclassmethod(cl->vftbl->class,
1992 utf_java_lang_String__java_lang_Class,
1993 class_java_lang_Object,
1999 r = (classinfo *) asm_calljavafunction(lc,
2001 javastring_new(c->name),
2007 return load_class_bootstrap(c);
2012 /* load_class_bootstrap ********************************************************
2016 *******************************************************************************/
2018 classinfo *load_class_bootstrap(classinfo *c)
2023 #if defined(USE_THREADS)
2024 /* enter a monitor on the class */
2026 builtin_monitorenter((java_objectheader *) c);
2029 /* maybe the class is already loaded */
2032 #if defined(USE_THREADS)
2033 builtin_monitorexit((java_objectheader *) c);
2039 #if defined(STATISTICS)
2042 if (getcompilingtime)
2043 compilingtime_stop();
2046 loadingtime_start();
2049 /* load classdata, throw exception on error */
2051 if ((cb = suck_start(c)) == NULL) {
2052 /* this means, the classpath was not set properly */
2053 if (c->name == utf_java_lang_Object)
2054 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2055 "java/lang/Object");
2058 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2061 #if defined(USE_THREADS)
2062 builtin_monitorexit((java_objectheader *) c);
2068 /* load the class from the buffer */
2070 r = load_class_from_classbuffer(cb);
2072 /* if return value is NULL, we had a problem and the class is not loaded */
2076 /* now free the allocated memory, otherwise we could ran into a DOS */
2083 #if defined(STATISTICS)
2089 if (getcompilingtime)
2090 compilingtime_start();
2093 #if defined(USE_THREADS)
2094 /* leave the monitor */
2096 builtin_monitorexit((java_objectheader *) c);
2103 /* load_class_from_classbuffer *************************************************
2105 Loads everything interesting about a class from the class file. The
2106 'classinfo' structure must have been allocated previously.
2108 The super class and the interfaces implemented by this class need
2109 not be loaded. The link is set later by the function 'class_link'.
2111 The loaded class is removed from the list 'unloadedclasses' and
2112 added to the list 'unlinkedclasses'.
2114 *******************************************************************************/
2116 classinfo *load_class_from_classbuffer(classbuffer *cb)
2122 char msg[MAXLOGTEXT]; /* maybe we get an exception */
2124 /* get the classbuffer's class */
2127 /* maybe the class is already loaded */
2131 #if defined(STATISTICS)
2133 count_class_loads++;
2136 /* output for debugging purposes */
2138 log_message_class("Loading class: ", c);
2140 /* class is somewhat loaded */
2143 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2146 /* check signature */
2147 if (suck_u4(cb) != MAGIC) {
2148 *exceptionptr = new_classformaterror(c, "Bad magic number");
2157 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2159 new_unsupportedclassversionerror(c,
2160 "Unsupported major.minor version %d.%d",
2166 /* load the constant pool */
2167 if (!load_constantpool(cb))
2171 c->erroneous_state = 0;
2172 c->initializing_thread = 0;
2174 c->classUsed = NOTUSED; /* not used initially CO-RT */
2178 if (!check_classbuffer_size(cb, 2))
2181 c->flags = suck_u2(cb);
2182 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2184 /* check ACC flags consistency */
2185 if (c->flags & ACC_INTERFACE) {
2186 if (!(c->flags & ACC_ABSTRACT)) {
2187 /* We work around this because interfaces in JDK 1.1 are
2188 * not declared abstract. */
2190 c->flags |= ACC_ABSTRACT;
2191 /* panic("Interface class not declared abstract"); */
2194 if (c->flags & ACC_FINAL) {
2196 new_classformaterror(c,
2197 "Illegal class modifiers: 0x%X", c->flags);
2202 if (c->flags & ACC_SUPER) {
2203 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2207 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2209 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2214 if (!check_classbuffer_size(cb, 2 + 2))
2219 if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
2223 utf_sprint(msg, c->name);
2224 sprintf(msg + strlen(msg), " (wrong name: ");
2225 utf_sprint(msg + strlen(msg), tc->name);
2226 sprintf(msg + strlen(msg), ")");
2229 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2234 /* retrieve superclass */
2235 if ((i = suck_u2(cb))) {
2236 if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
2239 /* java.lang.Object may not have a super class. */
2240 if (c->name == utf_java_lang_Object) {
2242 new_exception_message(string_java_lang_ClassFormatError,
2243 "java.lang.Object with superclass");
2248 /* Interfaces must have java.lang.Object as super class. */
2249 if ((c->flags & ACC_INTERFACE) &&
2250 c->super->name != utf_java_lang_Object) {
2252 new_exception_message(string_java_lang_ClassFormatError,
2253 "Interfaces must have java.lang.Object as superclass");
2261 /* This is only allowed for java.lang.Object. */
2262 if (c->name != utf_java_lang_Object) {
2263 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2269 /* retrieve interfaces */
2270 if (!check_classbuffer_size(cb, 2))
2273 c->interfacescount = suck_u2(cb);
2275 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2278 c->interfaces = MNEW(classinfo*, c->interfacescount);
2279 for (i = 0; i < c->interfacescount; i++) {
2280 if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2285 if (!check_classbuffer_size(cb, 2))
2288 c->fieldscount = suck_u2(cb);
2289 c->fields = GCNEW(fieldinfo, c->fieldscount);
2290 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2291 for (i = 0; i < c->fieldscount; i++) {
2292 if (!load_field(cb, &(c->fields[i])))
2297 if (!check_classbuffer_size(cb, 2))
2300 c->methodscount = suck_u2(cb);
2301 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2302 c->methods = MNEW(methodinfo, c->methodscount);
2303 for (i = 0; i < c->methodscount; i++) {
2304 if (!load_method(cb, &(c->methods[i])))
2308 /* Check if all fields and methods can be uniquely
2309 * identified by (name,descriptor). */
2311 /* We use a hash table here to avoid making the
2312 * average case quadratic in # of methods, fields.
2314 static int shift = 0;
2316 u2 *next; /* for chaining colliding hash entries */
2322 /* Allocate hashtable */
2323 len = c->methodscount;
2324 if (len < c->fieldscount) len = c->fieldscount;
2326 hashtab = MNEW(u2,(hashlen + len));
2327 next = hashtab + hashlen;
2329 /* Determine bitshift (to get good hash values) */
2339 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2341 for (i = 0; i < c->fieldscount; ++i) {
2342 fieldinfo *fi = c->fields + i;
2344 /* It's ok if we lose bits here */
2345 index = ((((size_t) fi->name) +
2346 ((size_t) fi->descriptor)) >> shift) % hashlen;
2348 if ((old = hashtab[index])) {
2352 if (c->fields[old].name == fi->name &&
2353 c->fields[old].descriptor == fi->descriptor) {
2355 new_classformaterror(c,
2356 "Repetitive field name/signature");
2360 } while ((old = next[old]));
2362 hashtab[index] = i + 1;
2366 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2368 for (i = 0; i < c->methodscount; ++i) {
2369 methodinfo *mi = c->methods + i;
2371 /* It's ok if we lose bits here */
2372 index = ((((size_t) mi->name) +
2373 ((size_t) mi->descriptor)) >> shift) % hashlen;
2377 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2378 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2382 if ((old = hashtab[index])) {
2386 if (c->methods[old].name == mi->name &&
2387 c->methods[old].descriptor == mi->descriptor) {
2389 new_classformaterror(c,
2390 "Repetitive method name/signature");
2394 } while ((old = next[old]));
2396 hashtab[index] = i + 1;
2399 MFREE(hashtab, u2, (hashlen + len));
2402 #if defined(STATISTICS)
2404 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2405 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2406 count_class_infos += sizeof(methodinfo) * c->methodscount;
2410 /* load attribute structures */
2411 if (!check_classbuffer_size(cb, 2))
2414 if (!load_attributes(cb, suck_u2(cb)))
2418 /* Pre java 1.5 version don't check this. This implementation is like
2419 java 1.5 do it: for class file version 45.3 we don't check it, older
2420 versions are checked.
2422 if ((ma == 45 && mi > 3) || ma > 45) {
2423 /* check if all data has been read */
2424 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2426 if (classdata_left > 0) {
2428 new_classformaterror(c, "Extra bytes at the end of class file");
2435 log_message_class("Loading done class: ", c);
2442 /******************* Function: class_new_array *********************************
2444 This function is called by class_new to setup an array class.
2446 *******************************************************************************/
2448 void class_new_array(classinfo *c)
2450 classinfo *comp = NULL;
2454 /* Check array class name */
2455 namelen = c->name->blength;
2456 if (namelen < 2 || c->name->text[0] != '[')
2457 panic("Invalid array class name");
2459 /* Check the component type */
2460 switch (c->name->text[1]) {
2462 /* c is an array of arrays. We have to create the component class. */
2464 comp = class_new_intern(utf_new_intern(c->name->text + 1,
2466 load_class_from_classloader(comp, c->classloader);
2467 list_addfirst(&unlinkedclasses, comp);
2470 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2475 /* c is an array of objects. */
2476 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2477 panic("Invalid array class name");
2480 comp = class_new_intern(utf_new_intern(c->name->text + 2,
2482 load_class_from_classloader(comp, c->classloader);
2483 list_addfirst(&unlinkedclasses, comp);
2486 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2491 /* Setup the array class */
2492 c->super = class_java_lang_Object;
2493 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2495 c->interfacescount = 2;
2496 c->interfaces = MNEW(classinfo*, 2);
2501 tc = class_java_lang_Cloneable;
2502 load_class_bootstrap(tc);
2503 list_addfirst(&unlinkedclasses, tc);
2504 c->interfaces[0] = tc;
2506 tc = class_java_io_Serializable;
2507 load_class_bootstrap(tc);
2508 list_addfirst(&unlinkedclasses, tc);
2509 c->interfaces[1] = tc;
2512 c->interfaces[0] = class_java_lang_Cloneable;
2513 c->interfaces[1] = class_java_io_Serializable;
2516 c->methodscount = 1;
2517 c->methods = MNEW(methodinfo, c->methodscount);
2520 MSET(clone, 0, methodinfo, 1);
2521 clone->flags = ACC_PUBLIC;
2522 clone->name = utf_new_char("clone");
2523 clone->descriptor = utf_void__java_lang_Object;
2525 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2526 clone->monoPoly = MONO;
2528 /* XXX: field: length? */
2530 /* array classes are not loaded from class files */
2535 /************************* Function: class_findfield ***************************
2537 Searches a 'classinfo' structure for a field having the given name and
2540 *******************************************************************************/
2542 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2546 for (i = 0; i < c->fieldscount; i++) {
2547 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2548 return &(c->fields[i]);
2551 panic("Can not find field given in CONSTANT_Fieldref");
2553 /* keep compiler happy */
2558 /****************** Function: class_resolvefield_int ***************************
2560 This is an internally used helper function. Do not use this directly.
2562 Tries to resolve a field having the given name and type.
2563 If the field cannot be resolved, NULL is returned.
2565 *******************************************************************************/
2567 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2572 /* search for field in class c */
2574 for (i = 0; i < c->fieldscount; i++) {
2575 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2576 return &(c->fields[i]);
2580 /* try superinterfaces recursively */
2582 for (i = 0; i < c->interfacescount; i++) {
2583 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2588 /* try superclass */
2591 return class_resolvefield_int(c->super, name, desc);
2599 /********************* Function: class_resolvefield ***************************
2601 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2603 If the field cannot be resolved the return value is NULL. If EXCEPT is
2604 true *exceptionptr is set, too.
2606 *******************************************************************************/
2608 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2609 classinfo *referer, bool except)
2613 /* XXX resolve class c */
2614 /* XXX check access from REFERER to C */
2616 fi = class_resolvefield_int(c, name, desc);
2621 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2627 /* XXX check access rights */
2633 /* class_findmethod ************************************************************
2635 Searches a 'classinfo' structure for a method having the given name
2636 and descriptor. If descriptor is NULL, it is ignored.
2638 *******************************************************************************/
2640 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2645 for (i = 0; i < c->methodscount; i++) {
2646 m = &(c->methods[i]);
2648 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2656 /*********************** Function: class_fetchmethod **************************
2658 like class_findmethod, but aborts with an error if the method is not found
2660 *******************************************************************************/
2662 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2666 mi = class_findmethod(c, name, desc);
2669 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2670 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2671 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2672 panic("Method not found");
2679 /************************* Function: class_findmethod_approx ******************
2681 like class_findmethod but ignores the return value when comparing the
2684 *******************************************************************************/
2686 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2690 for (i = 0; i < c->methodscount; i++) {
2691 if (c->methods[i].name == name) {
2692 utf *meth_descr = c->methods[i].descriptor;
2696 return &(c->methods[i]);
2698 if (desc->blength <= meth_descr->blength) {
2699 /* current position in utf text */
2700 char *desc_utf_ptr = desc->text;
2701 char *meth_utf_ptr = meth_descr->text;
2702 /* points behind utf strings */
2703 char *desc_end = utf_end(desc);
2704 char *meth_end = utf_end(meth_descr);
2707 /* compare argument types */
2708 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2710 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2711 break; /* no match */
2714 return &(c->methods[i]); /* all parameter types equal */
2724 /***************** Function: class_resolvemethod_approx ***********************
2726 Searches a class and every super class for a method (without paying
2727 attention to the return value)
2729 *******************************************************************************/
2731 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2734 /* search for method (ignore returntype) */
2735 methodinfo *m = class_findmethod_approx(c, name, desc);
2738 /* search superclass */
2746 /* class_resolvemethod *********************************************************
2748 Searches a class and it's super classes for a method.
2750 *******************************************************************************/
2752 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2757 m = class_findmethod(c, name, desc);
2769 /* class_resolveinterfacemethod_intern *****************************************
2771 Internally used helper function. Do not use this directly.
2773 *******************************************************************************/
2775 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2776 utf *name, utf *desc)
2781 m = class_findmethod(c, name, desc);
2786 /* try the superinterfaces */
2788 for (i = 0; i < c->interfacescount; i++) {
2789 m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2798 /* class_resolveinterfacemethod ************************************************
2800 Resolves a reference from REFERER to a method with NAME and DESC in
2803 If the method cannot be resolved the return value is NULL. If
2804 EXCEPT is true *exceptionptr is set, too.
2806 *******************************************************************************/
2808 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2809 classinfo *referer, bool except)
2813 /* XXX resolve class c */
2814 /* XXX check access from REFERER to C */
2816 if (!(c->flags & ACC_INTERFACE)) {
2819 new_exception(string_java_lang_IncompatibleClassChangeError);
2824 mi = class_resolveinterfacemethod_intern(c, name, desc);
2829 /* try class java.lang.Object */
2830 mi = class_findmethod(class_java_lang_Object, name, desc);
2837 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2843 /* class_resolveclassmethod ****************************************************
2845 Resolves a reference from REFERER to a method with NAME and DESC in
2848 If the method cannot be resolved the return value is NULL. If EXCEPT is
2849 true *exceptionptr is set, too.
2851 *******************************************************************************/
2853 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2854 classinfo *referer, bool except)
2862 /* XXX resolve class c */
2863 /* XXX check access from REFERER to C */
2865 /* if (c->flags & ACC_INTERFACE) { */
2867 /* *exceptionptr = */
2868 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
2872 /* try class c and its superclasses */
2877 mi = class_findmethod(cls, name, desc);
2885 /* try the superinterfaces */
2887 for (i = 0; i < c->interfacescount; i++) {
2888 mi = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2895 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
2896 utf_strlen(desc) + strlen("0");
2898 msg = MNEW(char, msglen);
2900 utf_sprint(msg, c->name);
2902 utf_sprint(msg + strlen(msg), name);
2903 utf_sprint(msg + strlen(msg), desc);
2906 new_exception_message(string_java_lang_NoSuchMethodError, msg);
2908 MFREE(msg, char, msglen);
2914 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
2916 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
2921 /* XXX check access rights */
2927 /************************* Function: class_issubclass **************************
2929 Checks if sub is a descendant of super.
2931 *******************************************************************************/
2933 bool class_issubclass(classinfo *sub, classinfo *super)
2936 if (!sub) return false;
2937 if (sub == super) return true;
2943 /****************** Initialization function for classes ******************
2945 In Java, every class can have a static initialization function. This
2946 function has to be called BEFORE calling other methods or accessing static
2949 *******************************************************************************/
2951 static classinfo *class_init_intern(classinfo *c);
2953 classinfo *class_init(classinfo *c)
2957 if (!makeinitializations)
2960 #if defined(USE_THREADS)
2961 /* enter a monitor on the class */
2963 builtin_monitorenter((java_objectheader *) c);
2966 /* maybe the class is already initalized or the current thread, which can
2967 pass the monitor, is currently initalizing this class */
2969 /* JOWENN: In future we need an additinal flag: initializationfailed,
2970 since further access to the class should cause a NoClassDefFound,
2971 if the static initializer failed once
2974 if (c->initialized || c->initializing) {
2975 #if defined(USE_THREADS)
2976 builtin_monitorexit((java_objectheader *) c);
2982 /* this initalizing run begins NOW */
2983 c->initializing = true;
2985 /* call the internal function */
2986 r = class_init_intern(c);
2988 /* if return value is not NULL everything was ok and the class is
2991 c->initialized = true;
2993 /* this initalizing run is done */
2994 c->initializing = false;
2996 #if defined(USE_THREADS)
2997 /* leave the monitor */
2999 builtin_monitorexit((java_objectheader *) c);
3006 /* this function MUST NOT be called directly, because of thread <clinit>
3009 static classinfo *class_init_intern(classinfo *c)
3013 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3017 /* maybe the class is not already loaded */
3019 if (!load_class_bootstrap(c))
3022 /* maybe the class is not already linked */
3027 #if defined(STATISTICS)
3029 count_class_inits++;
3032 /* initialize super class */
3035 if (!c->super->initialized) {
3037 char logtext[MAXLOGTEXT];
3038 sprintf(logtext, "Initialize super class ");
3039 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3040 sprintf(logtext + strlen(logtext), " from ");
3041 utf_sprint_classname(logtext + strlen(logtext), c->name);
3045 if (!class_init(c->super))
3050 /* initialize interface classes */
3052 for (i = 0; i < c->interfacescount; i++) {
3053 if (!c->interfaces[i]->initialized) {
3055 char logtext[MAXLOGTEXT];
3056 sprintf(logtext, "Initialize interface class ");
3057 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3058 sprintf(logtext + strlen(logtext), " from ");
3059 utf_sprint_classname(logtext + strlen(logtext), c->name);
3063 if (!class_init(c->interfaces[i]))
3068 m = class_findmethod(c, utf_clinit, utf_void__void);
3072 char logtext[MAXLOGTEXT];
3073 sprintf(logtext, "Class ");
3074 utf_sprint_classname(logtext + strlen(logtext), c->name);
3075 sprintf(logtext + strlen(logtext), " has no static class initializer");
3082 /* Sun's and IBM's JVM don't care about the static flag */
3083 /* if (!(m->flags & ACC_STATIC)) { */
3084 /* panic("Class initializer is not static!"); */
3087 log_message_class("Starting static class initializer for class: ", c);
3089 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3094 /* now call the initializer */
3095 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3097 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3098 assert(blockInts == 0);
3102 /* we have an exception or error */
3103 if (*exceptionptr) {
3104 /* class is NOT initialized */
3105 c->initialized = false;
3107 /* is this an exception, than wrap it */
3108 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3109 java_objectheader *xptr;
3110 java_objectheader *cause;
3113 cause = *exceptionptr;
3115 /* clear exception, because we are calling jit code again */
3116 *exceptionptr = NULL;
3118 /* wrap the exception */
3120 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3121 (java_lang_Throwable *) cause);
3123 /* XXX should we exit here? */
3127 /* set new exception */
3128 *exceptionptr = xptr;
3135 log_message_class("Finished static class initializer for class: ", c);
3141 void class_showconstanti(classinfo *c, int ii)
3147 printf ("#%d: ", (int) i);
3149 switch (c->cptags [i]) {
3150 case CONSTANT_Class:
3151 printf("Classreference -> ");
3152 utf_display(((classinfo*)e)->name);
3155 case CONSTANT_Fieldref:
3156 printf("Fieldref -> "); goto displayFMIi;
3157 case CONSTANT_Methodref:
3158 printf("Methodref -> "); goto displayFMIi;
3159 case CONSTANT_InterfaceMethodref:
3160 printf("InterfaceMethod -> "); goto displayFMIi;
3163 constant_FMIref *fmi = e;
3164 utf_display(fmi->class->name);
3166 utf_display(fmi->name);
3168 utf_display(fmi->descriptor);
3172 case CONSTANT_String:
3173 printf("String -> ");
3176 case CONSTANT_Integer:
3177 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3179 case CONSTANT_Float:
3180 printf("Float -> %f", ((constant_float*)e)->value);
3182 case CONSTANT_Double:
3183 printf("Double -> %f", ((constant_double*)e)->value);
3187 u8 v = ((constant_long*)e)->value;
3189 printf("Long -> %ld", (long int) v);
3191 printf("Long -> HI: %ld, LO: %ld\n",
3192 (long int) v.high, (long int) v.low);
3196 case CONSTANT_NameAndType:
3198 constant_nameandtype *cnt = e;
3199 printf("NameAndType: ");
3200 utf_display(cnt->name);
3202 utf_display(cnt->descriptor);
3210 panic("Invalid type of ConstantPool-Entry");
3217 void class_showconstantpool (classinfo *c)
3222 printf ("---- dump of constant pool ----\n");
3224 for (i=0; i<c->cpcount; i++) {
3225 printf ("#%d: ", (int) i);
3227 e = c -> cpinfos [i];
3230 switch (c -> cptags [i]) {
3231 case CONSTANT_Class:
3232 printf ("Classreference -> ");
3233 utf_display ( ((classinfo*)e) -> name );
3236 case CONSTANT_Fieldref:
3237 printf ("Fieldref -> "); goto displayFMI;
3238 case CONSTANT_Methodref:
3239 printf ("Methodref -> "); goto displayFMI;
3240 case CONSTANT_InterfaceMethodref:
3241 printf ("InterfaceMethod -> "); goto displayFMI;
3244 constant_FMIref *fmi = e;
3245 utf_display ( fmi->class->name );
3247 utf_display ( fmi->name);
3249 utf_display ( fmi->descriptor );
3253 case CONSTANT_String:
3254 printf ("String -> ");
3257 case CONSTANT_Integer:
3258 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3260 case CONSTANT_Float:
3261 printf ("Float -> %f", ((constant_float*)e) -> value);
3263 case CONSTANT_Double:
3264 printf ("Double -> %f", ((constant_double*)e) -> value);
3268 u8 v = ((constant_long*)e) -> value;
3270 printf ("Long -> %ld", (long int) v);
3272 printf ("Long -> HI: %ld, LO: %ld\n",
3273 (long int) v.high, (long int) v.low);
3277 case CONSTANT_NameAndType:
3279 constant_nameandtype *cnt = e;
3280 printf ("NameAndType: ");
3281 utf_display (cnt->name);
3283 utf_display (cnt->descriptor);
3287 printf ("Utf8 -> ");
3291 panic ("Invalid type of ConstantPool-Entry");
3301 /********** Function: class_showmethods (debugging only) *************/
3303 void class_showmethods (classinfo *c)
3307 printf ("--------- Fields and Methods ----------------\n");
3308 printf ("Flags: "); printflags (c->flags); printf ("\n");
3310 printf ("This: "); utf_display (c->name); printf ("\n");
3312 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3314 printf ("Index: %d\n", c->index);
3316 printf ("interfaces:\n");
3317 for (i=0; i < c-> interfacescount; i++) {
3319 utf_display (c -> interfaces[i] -> name);
3320 printf (" (%d)\n", c->interfaces[i] -> index);
3323 printf ("fields:\n");
3324 for (i=0; i < c -> fieldscount; i++) {
3325 field_display (&(c -> fields[i]));
3328 printf ("methods:\n");
3329 for (i=0; i < c -> methodscount; i++) {
3330 methodinfo *m = &(c->methods[i]);
3331 if ( !(m->flags & ACC_STATIC))
3332 printf ("vftblindex: %d ", m->vftblindex);
3334 method_display ( m );
3338 printf ("Virtual function table:\n");
3339 for (i=0; i<c->vftbl->vftbllength; i++) {
3340 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3346 /******************************************************************************/
3347 /******************* General functions for the class loader *******************/
3348 /******************************************************************************/
3350 /**************** function: class_primitive_from_sig ***************************
3352 return the primitive class indicated by the given signature character
3354 If the descriptor does not indicate a valid primitive type the
3355 return value is NULL.
3357 ********************************************************************************/
3359 classinfo *class_primitive_from_sig(char sig)
3362 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3363 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3364 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3365 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3366 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3367 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3368 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3369 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3370 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3375 /****************** function: class_from_descriptor ****************************
3377 return the class indicated by the given descriptor
3379 utf_ptr....first character of descriptor
3380 end_ptr....first character after the end of the string
3381 next.......if non-NULL, *next is set to the first character after
3382 the descriptor. (Undefined if an error occurs.)
3384 mode.......a combination (binary or) of the following flags:
3386 (Flags marked with * are the default settings.)
3388 What to do if a reference type descriptor is parsed successfully:
3390 CLASSLOAD_SKIP...skip it and return something != NULL
3391 * CLASSLOAD_NEW....get classinfo * via class_new
3392 CLASSLOAD_LOAD...get classinfo * via loader_load
3394 How to handle primitive types:
3396 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3397 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3399 How to handle "V" descriptors:
3401 * CLASSLOAD_VOID.....handle it like other primitive types
3402 CLASSLOAD_NOVOID...treat it as an error
3404 How to deal with extra characters after the end of the
3407 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3408 CLASSLOAD_CHECKEND.....treat them as an error
3410 How to deal with errors:
3412 * CLASSLOAD_PANIC....abort execution with an error message
3413 CLASSLOAD_NOPANIC..return NULL on error
3415 *******************************************************************************/
3417 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3418 char **next, int mode)
3420 char *start = utf_ptr;
3424 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3426 if (mode & CLASSLOAD_CHECKEND)
3427 error |= (utf_ptr != end_ptr);
3430 if (next) *next = utf_ptr;
3434 if (mode & CLASSLOAD_NOVOID)
3445 return (mode & CLASSLOAD_NULLPRIMITIVE)
3447 : class_primitive_from_sig(*start);
3454 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3455 name = utf_new(start, utf_ptr - start);
3459 tc = class_new_intern(name);
3460 load_class_from_classloader(tc, NULL);
3461 list_addfirst(&unlinkedclasses, tc);
3466 return (mode & CLASSLOAD_LOAD)
3467 ? load_class_from_classloader(class_new(name), NULL) : class_new(name); /* XXX handle errors */
3472 /* An error occurred */
3473 if (mode & CLASSLOAD_NOPANIC)
3476 log_plain("Invalid descriptor at beginning of '");
3477 log_plain_utf(utf_new(start, end_ptr - start));
3481 panic("Invalid descriptor");
3483 /* keep compiler happy */
3488 /******************* function: type_from_descriptor ****************************
3490 return the basic type indicated by the given descriptor
3492 This function parses a descriptor and returns its basic type as
3493 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3495 cls...if non-NULL the referenced variable is set to the classinfo *
3496 returned by class_from_descriptor.
3498 For documentation of the arguments utf_ptr, end_ptr, next and mode
3499 see class_from_descriptor. The only difference is that
3500 type_from_descriptor always uses CLASSLOAD_PANIC.
3502 ********************************************************************************/
3504 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3505 char **next, int mode)
3508 if (!cls) cls = &mycls;
3509 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3526 return TYPE_ADDRESS;
3530 /******************** Function: loader_close ***********************************
3534 *******************************************************************************/
3541 for (slot = 0; slot < class_hash.size; slot++) {
3542 c = class_hash.ptr[slot];
3553 * These are local overrides for various environment variables in Emacs.
3554 * Please do not remove this and leave it at the end of the file, where
3555 * Emacs will automagically detect them.
3556 * ---------------------------------------------------------------------
3559 * indent-tabs-mode: t