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 2181 2005-04-01 16:53:33Z edwin $
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))
275 /* load classes for wrapping primitive types */
277 if (!load_class_bootstrap(class_java_lang_Void))
280 if (!load_class_bootstrap(class_java_lang_Boolean))
283 if (!load_class_bootstrap(class_java_lang_Byte))
286 if (!load_class_bootstrap(class_java_lang_Character))
289 if (!load_class_bootstrap(class_java_lang_Short))
292 if (!load_class_bootstrap(class_java_lang_Integer))
295 if (!load_class_bootstrap(class_java_lang_Long))
298 if (!load_class_bootstrap(class_java_lang_Float))
301 if (!load_class_bootstrap(class_java_lang_Double))
305 #if defined(USE_THREADS)
306 if (stackbottom != 0)
314 /************* functions for reading classdata *********************************
316 getting classdata in blocks of variable size
317 (8,16,32,64-bit integer or float)
319 *******************************************************************************/
321 /* check_classbuffer_size ******************************************************
323 assert that at least <len> bytes are left to read
324 <len> is limited to the range of non-negative s4 values
326 *******************************************************************************/
328 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
330 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
332 new_classformaterror((cb)->class, "Truncated class file");
341 /* suck_nbytes *****************************************************************
343 transfer block of classfile data into a buffer
345 *******************************************************************************/
347 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
349 memcpy(buffer, cb->pos + 1, len);
354 /* skip_nbytes ****************************************************************
356 skip block of classfile data
358 *******************************************************************************/
360 inline void skip_nbytes(classbuffer *cb, s4 len)
366 inline u1 suck_u1(classbuffer *cb)
372 inline u2 suck_u2(classbuffer *cb)
376 return ((u2) a << 8) + (u2) b;
380 inline u4 suck_u4(classbuffer *cb)
386 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
390 /* get u8 from classfile data */
391 static u8 suck_u8(classbuffer *cb)
397 return (hi << 32) + lo;
400 v.high = suck_u4(cb);
407 /* get float from classfile data */
408 static float suck_float(classbuffer *cb)
416 for (i = 0; i < 4; i++)
417 buffer[3 - i] = suck_u1(cb);
419 memcpy((u1*) (&f), buffer, 4);
421 suck_nbytes((u1*) (&f), cb, 4);
424 if (sizeof(float) != 4) {
425 *exceptionptr = new_exception_message(string_java_lang_InternalError,
426 "Incompatible float-format");
428 /* XXX should we exit in such a case? */
429 throw_exception_exit();
436 /* get double from classfile data */
437 static double suck_double(classbuffer *cb)
445 for (i = 0; i < 8; i++)
446 buffer[7 - i] = suck_u1(cb);
448 memcpy((u1*) (&d), buffer, 8);
450 suck_nbytes((u1*) (&d), cb, 8);
453 if (sizeof(double) != 8) {
454 *exceptionptr = new_exception_message(string_java_lang_InternalError,
455 "Incompatible double-format");
457 /* XXX should we exit in such a case? */
458 throw_exception_exit();
465 /************************** function suck_init *********************************
467 called once at startup, sets the searchpath for the classfiles
469 *******************************************************************************/
471 void suck_init(char *classpath)
479 classpath_info *lastcpi;
483 /* search for last classpath entry (only if there already some) */
485 if ((lastcpi = classpath_entries)) {
486 while (lastcpi->next)
487 lastcpi = lastcpi->next;
490 for (start = classpath; (*start) != '\0';) {
492 /* search for ':' delimiter to get the end of the current entry */
493 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
497 filenamelen = end - start;
499 if (filenamelen > 3) {
500 if (strncasecmp(end - 3, "zip", 3) == 0 ||
501 strncasecmp(end - 3, "jar", 3) == 0) {
506 /* save classpath entries as absolute pathnames */
511 if (*start != '/') { /* XXX fix me for win32 */
513 cwdlen = strlen(cwd) + strlen("/");
516 /* allocate memory for filename and fill it */
518 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
522 strcpy(filename, cwd);
523 strcat(filename, "/");
524 strncat(filename, start, filenamelen);
526 /* add cwd length to file length */
527 filenamelen += cwdlen;
530 strncpy(filename, start, filenamelen);
531 filename[filenamelen] = '\0';
537 #if defined(USE_ZLIB)
538 unzFile uf = unzOpen(filename);
541 cpi = NEW(classpath_info);
542 cpi->type = CLASSPATH_ARCHIVE;
545 cpi->path = filename;
546 cpi->pathlen = filenamelen;
550 throw_cacao_exception_exit(string_java_lang_InternalError,
551 "zip/jar files not supported");
555 cpi = NEW(classpath_info);
556 cpi->type = CLASSPATH_PATH;
559 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
560 filename[filenamelen] = '/';
561 filename[filenamelen + 1] = '\0';
565 cpi->path = filename;
566 cpi->pathlen = filenamelen;
569 /* attach current classpath entry */
572 if (!classpath_entries)
573 classpath_entries = cpi;
581 /* goto next classpath entry, skip ':' delimiter */
593 void create_all_classes()
597 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
598 #if defined(USE_ZLIB)
599 if (cpi->type == CLASSPATH_ARCHIVE) {
603 s = (unz_s *) cpi->uf;
604 ce = s->cacao_dir_list;
607 (void) class_new(ce->name);
613 #if defined(USE_ZLIB)
620 /* suck_start ******************************************************************
622 Returns true if classbuffer is already loaded or a file for the
623 specified class has succussfully been read in. All directories of
624 the searchpath are used to find the classfile (<classname>.class).
625 Returns false if no classfile is found and writes an error message.
627 *******************************************************************************/
629 classbuffer *suck_start(classinfo *c)
641 /* initialize return value */
646 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
647 filename = MNEW(char, filenamelen);
649 utf_sprint(filename, c->name);
650 strcat(filename, ".class");
652 /* walk through all classpath entries */
654 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
655 #if defined(USE_ZLIB)
656 if (cpi->type == CLASSPATH_ARCHIVE) {
658 #if defined(USE_THREADS)
659 /* enter a monitor on zip/jar archives */
661 builtin_monitorenter((java_objectheader *) cpi);
664 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
665 unz_file_info file_info;
667 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
668 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
669 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
670 cb = NEW(classbuffer);
672 cb->size = file_info.uncompressed_size;
673 cb->data = MNEW(u1, cb->size);
674 cb->pos = cb->data - 1;
676 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
678 if (len != cb->size) {
680 log_text("Error while unzipping");
687 log_text("Error while opening file in archive");
691 log_text("Error while retrieving fileinfo");
694 unzCloseCurrentFile(cpi->uf);
696 #if defined(USE_THREADS)
697 /* leave the monitor */
699 builtin_monitorexit((java_objectheader *) cpi);
703 #endif /* defined(USE_ZLIB) */
705 path = MNEW(char, cpi->pathlen + filenamelen);
706 strcpy(path, cpi->path);
707 strcat(path, filename);
709 classfile = fopen(path, "r");
711 if (classfile) { /* file exists */
712 if (!stat(path, &buffer)) { /* read classfile data */
713 cb = NEW(classbuffer);
715 cb->size = buffer.st_size;
716 cb->data = MNEW(u1, cb->size);
717 cb->pos = cb->data - 1;
719 /* read class data */
720 len = fread(cb->data, 1, cb->size, classfile);
722 if (len != buffer.st_size) {
724 /* if (ferror(classfile)) { */
733 MFREE(path, char, cpi->pathlen + filenamelen);
734 #if defined(USE_ZLIB)
741 dolog("Warning: Can not open class file '%s'", filename);
743 MFREE(filename, char, filenamelen);
749 /************************** function suck_stop *********************************
751 frees memory for buffer with classfile data.
752 Caution: this function may only be called if buffer has been allocated
753 by suck_start with reading a file
755 *******************************************************************************/
757 void suck_stop(classbuffer *cb)
761 MFREE(cb->data, u1, cb->size);
762 FREE(cb, classbuffer);
766 /******************************************************************************/
767 /******************* Some support functions ***********************************/
768 /******************************************************************************/
770 void fprintflags (FILE *fp, u2 f)
772 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
773 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
774 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
775 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
776 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
777 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
778 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
779 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
780 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
781 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
782 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
786 /********** internal function: printflags (only for debugging) ***************/
788 void printflags(u2 f)
790 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
791 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
792 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
793 if ( f & ACC_STATIC ) printf (" STATIC");
794 if ( f & ACC_FINAL ) printf (" FINAL");
795 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
796 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
797 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
798 if ( f & ACC_NATIVE ) printf (" NATIVE");
799 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
800 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
804 /********************** Function: skipattributebody ****************************
806 skips an attribute after the 16 bit reference to attribute_name has already
809 *******************************************************************************/
811 static bool skipattributebody(classbuffer *cb)
815 if (!check_classbuffer_size(cb, 4))
820 if (!check_classbuffer_size(cb, len))
823 skip_nbytes(cb, len);
829 /************************* Function: skipattributes ****************************
831 skips num attribute structures
833 *******************************************************************************/
835 static bool skipattributes(classbuffer *cb, u4 num)
840 for (i = 0; i < num; i++) {
841 if (!check_classbuffer_size(cb, 2 + 4))
847 if (!check_classbuffer_size(cb, len))
850 skip_nbytes(cb, len);
857 /******************** function:: class_getconstant *****************************
859 retrieves the value at position 'pos' of the constantpool of a class
860 if the type of the value is other than 'ctype' the system is stopped
862 *******************************************************************************/
864 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
866 /* check index and type of constantpool entry */
867 /* (pos == 0 is caught by type comparison) */
868 if (pos >= c->cpcount || c->cptags[pos] != ctype) {
869 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
873 return c->cpinfos[pos];
877 /******************** function: innerclass_getconstant ************************
879 like class_getconstant, but if cptags is ZERO null is returned
881 *******************************************************************************/
883 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
885 /* invalid position in constantpool */
886 if (pos >= c->cpcount) {
887 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
891 /* constantpool entry of type 0 */
895 /* check type of constantpool entry */
896 if (c->cptags[pos] != ctype) {
897 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
901 return c->cpinfos[pos];
905 /********************* Function: class_constanttype ****************************
907 Determines the type of a class entry in the ConstantPool
909 *******************************************************************************/
911 u4 class_constanttype(classinfo *c, u4 pos)
913 if (pos <= 0 || pos >= c->cpcount) {
914 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
918 return c->cptags[pos];
922 /* load_constantpool ***********************************************************
924 Loads the constantpool of a class, the entries are transformed into
925 a simpler format by resolving references (a detailed overview of
926 the compact structures can be found in global.h).
928 *******************************************************************************/
930 static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
933 /* The following structures are used to save information which cannot be
934 processed during the first pass. After the complete constantpool has
935 been traversed the references can be resolved.
936 (only in specific order) */
938 /* CONSTANT_Class entries */
939 typedef struct forward_class {
940 struct forward_class *next;
945 /* CONSTANT_String */
946 typedef struct forward_string {
947 struct forward_string *next;
952 /* CONSTANT_NameAndType */
953 typedef struct forward_nameandtype {
954 struct forward_nameandtype *next;
958 } forward_nameandtype;
960 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
961 typedef struct forward_fieldmethint {
962 struct forward_fieldmethint *next;
966 u2 nameandtype_index;
967 } forward_fieldmethint;
973 forward_class *forward_classes = NULL;
974 forward_string *forward_strings = NULL;
975 forward_nameandtype *forward_nameandtypes = NULL;
976 forward_fieldmethint *forward_fieldmethints = NULL;
980 forward_nameandtype *nfn;
981 forward_fieldmethint *nff;
989 /* number of entries in the constant_pool table plus one */
990 if (!check_classbuffer_size(cb, 2))
993 cpcount = c->cpcount = suck_u2(cb);
995 /* allocate memory */
996 cptags = c->cptags = MNEW(u1, cpcount);
997 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1000 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
1004 #if defined(STATISTICS)
1006 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1009 /* initialize constantpool */
1010 for (idx = 0; idx < cpcount; idx++) {
1011 cptags[idx] = CONSTANT_UNUSED;
1012 cpinfos[idx] = NULL;
1016 /******* first pass *******/
1017 /* entries which cannot be resolved now are written into
1018 temporary structures and traversed again later */
1021 while (idx < cpcount) {
1024 /* get constant type */
1025 if (!check_classbuffer_size(cb, 1))
1031 case CONSTANT_Class:
1032 nfc = NEW(forward_class);
1034 nfc->next = forward_classes;
1035 forward_classes = nfc;
1037 nfc->thisindex = idx;
1038 /* reference to CONSTANT_NameAndType */
1039 if (!check_classbuffer_size(cb, 2))
1042 nfc->name_index = suck_u2(cb);
1047 case CONSTANT_String:
1048 nfs = NEW(forward_string);
1050 nfs->next = forward_strings;
1051 forward_strings = nfs;
1053 nfs->thisindex = idx;
1055 /* reference to CONSTANT_Utf8_info with string characters */
1056 if (!check_classbuffer_size(cb, 2))
1059 nfs->string_index = suck_u2(cb);
1064 case CONSTANT_NameAndType:
1065 nfn = NEW(forward_nameandtype);
1067 nfn->next = forward_nameandtypes;
1068 forward_nameandtypes = nfn;
1070 nfn->thisindex = idx;
1072 if (!check_classbuffer_size(cb, 2 + 2))
1075 /* reference to CONSTANT_Utf8_info containing simple name */
1076 nfn->name_index = suck_u2(cb);
1078 /* reference to CONSTANT_Utf8_info containing field or method
1080 nfn->sig_index = suck_u2(cb);
1085 case CONSTANT_Fieldref:
1086 case CONSTANT_Methodref:
1087 case CONSTANT_InterfaceMethodref:
1088 nff = NEW(forward_fieldmethint);
1090 nff->next = forward_fieldmethints;
1091 forward_fieldmethints = nff;
1093 nff->thisindex = idx;
1097 if (!check_classbuffer_size(cb, 2 + 2))
1100 /* class or interface type that contains the declaration of the
1102 nff->class_index = suck_u2(cb);
1104 /* name and descriptor of the field or method */
1105 nff->nameandtype_index = suck_u2(cb);
1110 case CONSTANT_Integer: {
1111 constant_integer *ci = NEW(constant_integer);
1113 #if defined(STATISTICS)
1115 count_const_pool_len += sizeof(constant_integer);
1118 if (!check_classbuffer_size(cb, 4))
1121 ci->value = suck_s4(cb);
1122 cptags[idx] = CONSTANT_Integer;
1129 case CONSTANT_Float: {
1130 constant_float *cf = NEW(constant_float);
1132 #if defined(STATISTICS)
1134 count_const_pool_len += sizeof(constant_float);
1137 if (!check_classbuffer_size(cb, 4))
1140 cf->value = suck_float(cb);
1141 cptags[idx] = CONSTANT_Float;
1148 case CONSTANT_Long: {
1149 constant_long *cl = NEW(constant_long);
1151 #if defined(STATISTICS)
1153 count_const_pool_len += sizeof(constant_long);
1156 if (!check_classbuffer_size(cb, 8))
1159 cl->value = suck_s8(cb);
1160 cptags[idx] = CONSTANT_Long;
1163 if (idx > cpcount) {
1165 new_classformaterror(c, "Invalid constant pool entry");
1171 case CONSTANT_Double: {
1172 constant_double *cd = NEW(constant_double);
1174 #if defined(STATISTICS)
1176 count_const_pool_len += sizeof(constant_double);
1179 if (!check_classbuffer_size(cb, 8))
1182 cd->value = suck_double(cb);
1183 cptags[idx] = CONSTANT_Double;
1186 if (idx > cpcount) {
1188 new_classformaterror(c, "Invalid constant pool entry");
1194 case CONSTANT_Utf8: {
1197 /* number of bytes in the bytes array (not string-length) */
1198 if (!check_classbuffer_size(cb, 2))
1201 length = suck_u2(cb);
1202 cptags[idx] = CONSTANT_Utf8;
1204 /* validate the string */
1205 if (!check_classbuffer_size(cb, length))
1209 !is_valid_utf((char *) (cb->pos + 1),
1210 (char *) (cb->pos + 1 + length))) {
1211 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1212 panic("Invalid UTF-8 string");
1214 /* insert utf-string into the utf-symboltable */
1215 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1217 /* skip bytes of the string (buffer size check above) */
1218 skip_nbytes(cb, length);
1225 new_classformaterror(c, "Illegal constant pool type");
1230 /* add all class references to the descriptor_pool */
1231 for (nfc=forward_classes; nfc; nfc=nfc->next) {
1232 utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
1233 if (!descriptor_pool_add_class(descpool,name))
1236 /* add all descriptors in NameAndTypes to the descriptor_pool */
1237 for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
1238 utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
1239 if (!descriptor_pool_add(descpool,desc))
1243 /* resolve entries in temporary structures */
1245 while (forward_classes) {
1247 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1249 if (opt_verify && !is_valid_name_utf(name))
1250 panic("Class reference with invalid name");
1252 cptags[forward_classes->thisindex] = CONSTANT_Class;
1253 /* retrieve class from class-table */
1256 tc = class_new_intern(name);
1258 if (!load_class_from_classloader(tc, c->classloader))
1261 /* link the class later, because we cannot link the class currently
1263 list_addfirst(&unlinkedclasses, tc);
1265 cpinfos[forward_classes->thisindex] = tc;
1268 cpinfos[forward_classes->thisindex] = class_new(name);
1271 nfc = forward_classes;
1272 forward_classes = forward_classes->next;
1273 FREE(nfc, forward_class);
1276 while (forward_strings) {
1278 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1280 /* resolve utf-string */
1281 cptags[forward_strings->thisindex] = CONSTANT_String;
1282 cpinfos[forward_strings->thisindex] = text;
1284 nfs = forward_strings;
1285 forward_strings = forward_strings->next;
1286 FREE(nfs, forward_string);
1289 while (forward_nameandtypes) {
1290 constant_nameandtype *cn = NEW(constant_nameandtype);
1292 #if defined(STATISTICS)
1294 count_const_pool_len += sizeof(constant_nameandtype);
1297 /* resolve simple name and descriptor */
1298 cn->name = class_getconstant(c,
1299 forward_nameandtypes->name_index,
1302 cn->descriptor = class_getconstant(c,
1303 forward_nameandtypes->sig_index,
1308 if (!is_valid_name_utf(cn->name)) {
1310 new_classformaterror(c,
1311 "Illegal Field name \"%s\"",
1317 /* disallow referencing <clinit> among others */
1318 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1320 new_exception_utfmessage(string_java_lang_InternalError,
1326 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1327 cpinfos[forward_nameandtypes->thisindex] = cn;
1329 nfn = forward_nameandtypes;
1330 forward_nameandtypes = forward_nameandtypes->next;
1331 FREE(nfn, forward_nameandtype);
1334 while (forward_fieldmethints) {
1335 constant_nameandtype *nat;
1336 constant_FMIref *fmi = NEW(constant_FMIref);
1338 #if defined(STATISTICS)
1340 count_const_pool_len += sizeof(constant_FMIref);
1342 /* resolve simple name and descriptor */
1343 nat = class_getconstant(c,
1344 forward_fieldmethints->nameandtype_index,
1345 CONSTANT_NameAndType);
1347 fmi->class = class_getconstant(c,
1348 forward_fieldmethints->class_index,
1350 fmi->name = nat->name;
1351 fmi->descriptor = nat->descriptor;
1353 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1354 cpinfos[forward_fieldmethints->thisindex] = fmi;
1356 switch (forward_fieldmethints->tag) {
1357 case CONSTANT_Fieldref: /* check validity of descriptor */
1358 checkfielddescriptor(fmi->descriptor->text,
1359 utf_end(fmi->descriptor));
1361 case CONSTANT_InterfaceMethodref:
1362 case CONSTANT_Methodref: /* check validity of descriptor */
1363 checkmethoddescriptor(c, fmi->descriptor);
1367 nff = forward_fieldmethints;
1368 forward_fieldmethints = forward_fieldmethints->next;
1369 FREE(nff, forward_fieldmethint);
1372 /* everything was ok */
1378 /* load_field ******************************************************************
1380 Load everything about a class field from the class file and fill a
1381 'fieldinfo' structure. For static fields, space in the data segment
1384 *******************************************************************************/
1386 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1388 static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
1393 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1398 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1401 f->flags = suck_u2(cb);
1403 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1407 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1410 f->parseddesc = NULL;
1411 if (!descriptor_pool_add(descpool,u))
1416 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1417 *exceptionptr = new_classformaterror(c,
1418 "Illegal Field name \"%s\"",
1423 /* check flag consistency */
1424 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1426 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1427 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1429 new_classformaterror(c,
1430 "Illegal field modifiers: 0x%X",
1435 if (c->flags & ACC_INTERFACE) {
1436 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1437 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1438 f->flags & ACC_TRANSIENT) {
1440 new_classformaterror(c,
1441 "Illegal field modifiers: 0x%X",
1447 /* check descriptor */
1448 checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
1451 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1452 f->offset = 0; /* offset from start of object */
1457 case TYPE_INT: f->value.i = 0; break;
1458 case TYPE_FLOAT: f->value.f = 0.0; break;
1459 case TYPE_DOUBLE: f->value.d = 0.0; break;
1460 case TYPE_ADDRESS: f->value.a = NULL; break;
1463 f->value.l = 0; break;
1465 f->value.l.low = 0; f->value.l.high = 0; break;
1469 /* read attributes */
1470 if (!check_classbuffer_size(cb, 2))
1473 attrnum = suck_u2(cb);
1474 for (i = 0; i < attrnum; i++) {
1475 if (!check_classbuffer_size(cb, 2))
1478 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1481 if (u == utf_ConstantValue) {
1482 if (!check_classbuffer_size(cb, 4 + 2))
1485 /* check attribute length */
1486 if (suck_u4(cb) != 2) {
1488 new_classformaterror(c, "Wrong size for VALUE attribute");
1492 /* constant value attribute */
1493 if (pindex != field_load_NOVALUE) {
1495 new_classformaterror(c,
1496 "Multiple ConstantValue attributes");
1500 /* index of value in constantpool */
1501 pindex = suck_u2(cb);
1503 /* initialize field with value from constantpool */
1506 constant_integer *ci;
1508 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1511 f->value.i = ci->value;
1518 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1521 f->value.l = cl->value;
1528 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1531 f->value.f = cf->value;
1536 constant_double *cd;
1538 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1541 f->value.d = cd->value;
1546 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1549 /* create javastring from compressed utf8-string */
1550 f->value.a = literalstring_new(u);
1554 log_text("Invalid Constant - Type");
1558 /* unknown attribute */
1559 if (!skipattributebody(cb))
1564 /* everything was ok */
1570 /* load_method *****************************************************************
1572 Loads a method from the class file and fills an existing
1573 'methodinfo' structure. For native methods, the function pointer
1574 field is set to the real function pointer, for JavaVM methods a
1575 pointer to the compiler is used preliminarily.
1577 *******************************************************************************/
1579 static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
1590 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1591 initObjectLock(&m->header);
1596 count_all_methods++;
1599 m->thrownexceptionscount = 0;
1600 m->linenumbercount = 0;
1603 m->nativelyoverloaded = false;
1605 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1608 m->flags = suck_u2(cb);
1610 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1614 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1617 m->parseddesc = NULL;
1618 if (!descriptor_pool_add(descpool,u))
1622 if (!is_valid_name_utf(m->name))
1623 panic("Method with invalid name");
1625 if (m->name->text[0] == '<'
1626 && m->name != utf_init && m->name != utf_clinit)
1627 panic("Method with invalid special name");
1630 argcount = checkmethoddescriptor(c, m->descriptor);
1632 if (!(m->flags & ACC_STATIC))
1633 argcount++; /* count the 'this' argument */
1636 if (argcount > 255) {
1638 new_classformaterror(c, "Too many arguments in signature");
1642 /* check flag consistency */
1643 if (m->name != utf_clinit) {
1644 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1646 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1648 new_classformaterror(c,
1649 "Illegal method modifiers: 0x%X",
1654 if (m->flags & ACC_ABSTRACT) {
1655 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1656 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1658 new_classformaterror(c,
1659 "Illegal method modifiers: 0x%X",
1665 if (c->flags & ACC_INTERFACE) {
1666 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1668 new_classformaterror(c,
1669 "Illegal method modifiers: 0x%X",
1675 if (m->name == utf_init) {
1676 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1677 ACC_NATIVE | ACC_ABSTRACT))
1678 panic("Instance initialization method has invalid flags set");
1684 m->basicblockcount = 0;
1685 m->basicblocks = NULL;
1686 m->basicblockindex = NULL;
1687 m->instructioncount = 0;
1688 m->instructions = NULL;
1691 m->exceptiontable = NULL;
1692 m->stubroutine = NULL;
1694 m->entrypoint = NULL;
1695 m->methodUsed = NOTUSED;
1698 m->subRedefsUsed = 0;
1702 if (!check_classbuffer_size(cb, 2))
1705 attrnum = suck_u2(cb);
1706 for (i = 0; i < attrnum; i++) {
1709 if (!check_classbuffer_size(cb, 2))
1712 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1715 if (aname == utf_Code) {
1716 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1718 new_classformaterror(c,
1719 "Code attribute in native or abstract methods");
1726 new_classformaterror(c, "Multiple Code attributes");
1731 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1735 m->maxstack = suck_u2(cb);
1736 m->maxlocals = suck_u2(cb);
1738 if (m->maxlocals < argcount) {
1740 new_classformaterror(c, "Arguments can't fit into locals");
1745 if (!check_classbuffer_size(cb, 4))
1748 m->jcodelength = suck_u4(cb);
1750 if (m->jcodelength == 0) {
1752 new_classformaterror(c, "Code of a method has length 0");
1757 if (m->jcodelength > 65535) {
1759 new_classformaterror(c,
1760 "Code of a method longer than 65535 bytes");
1765 if (!check_classbuffer_size(cb, m->jcodelength))
1768 m->jcode = MNEW(u1, m->jcodelength);
1769 suck_nbytes(m->jcode, cb, m->jcodelength);
1771 if (!check_classbuffer_size(cb, 2))
1774 m->exceptiontablelength = suck_u2(cb);
1775 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1778 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1780 #if defined(STATISTICS)
1782 count_vmcode_len += m->jcodelength + 18;
1783 count_extable_len += 8 * m->exceptiontablelength;
1787 for (j = 0; j < m->exceptiontablelength; j++) {
1789 m->exceptiontable[j].startpc = suck_u2(cb);
1790 m->exceptiontable[j].endpc = suck_u2(cb);
1791 m->exceptiontable[j].handlerpc = suck_u2(cb);
1795 m->exceptiontable[j].catchtype = NULL;
1798 if (!(m->exceptiontable[j].catchtype =
1799 class_getconstant(c, idx, CONSTANT_Class)))
1804 if (!check_classbuffer_size(cb, 2))
1807 codeattrnum = suck_u2(cb);
1809 for (; codeattrnum > 0; codeattrnum--) {
1812 if (!check_classbuffer_size(cb, 2))
1815 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1818 if (caname == utf_LineNumberTable) {
1821 if (!check_classbuffer_size(cb, 4 + 2))
1825 m->linenumbercount = suck_u2(cb);
1827 if (!check_classbuffer_size(cb,
1828 (2 + 2) * m->linenumbercount))
1831 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1833 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1834 m->linenumbers[lncid].start_pc = suck_u2(cb);
1835 m->linenumbers[lncid].line_number = suck_u2(cb);
1839 if (!skipattributes(cb, codeattrnum))
1845 if (!skipattributebody(cb))
1850 } else if (aname == utf_Exceptions) {
1853 if (m->thrownexceptions) {
1855 new_classformaterror(c, "Multiple Exceptions attributes");
1859 if (!check_classbuffer_size(cb, 4 + 2))
1862 suck_u4(cb); /* length */
1863 m->thrownexceptionscount = suck_u2(cb);
1865 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1868 m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1870 for (j = 0; j < m->thrownexceptionscount; j++) {
1871 if (!((m->thrownexceptions)[j] =
1872 class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1877 if (!skipattributebody(cb))
1882 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1883 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1888 /* everything was ok */
1894 /* load_attribute **************************************************************
1896 Read attributes from classfile.
1898 *******************************************************************************/
1900 static bool load_attributes(classbuffer *cb, u4 num)
1908 for (i = 0; i < num; i++) {
1909 /* retrieve attribute name */
1910 if (!check_classbuffer_size(cb, 2))
1913 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1916 if (aname == utf_InnerClasses) {
1917 /* innerclasses attribute */
1918 if (c->innerclass) {
1920 new_classformaterror(c, "Multiple InnerClasses attributes");
1924 if (!check_classbuffer_size(cb, 4 + 2))
1927 /* skip attribute length */
1930 /* number of records */
1931 c->innerclasscount = suck_u2(cb);
1933 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1936 /* allocate memory for innerclass structure */
1937 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1939 for (j = 0; j < c->innerclasscount; j++) {
1940 /* The innerclass structure contains a class with an encoded
1941 name, its defining scope, its simple name and a bitmask of
1942 the access flags. If an inner class is not a member, its
1943 outer_class is NULL, if a class is anonymous, its name is
1946 innerclassinfo *info = c->innerclass + j;
1949 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1951 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1953 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1954 info->flags = suck_u2(cb);
1957 } else if (aname == utf_SourceFile) {
1958 if (!check_classbuffer_size(cb, 4 + 2))
1961 if (suck_u4(cb) != 2) {
1963 new_classformaterror(c, "Wrong size for VALUE attribute");
1967 if (c->sourcefile) {
1969 new_classformaterror(c, "Multiple SourceFile attributes");
1973 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1977 /* unknown attribute */
1978 if (!skipattributebody(cb))
1987 /* load_class_from_classloader *************************************************
1991 *******************************************************************************/
1993 classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
1997 /* if other class loader than bootstrap, call it */
2002 lc = class_resolveclassmethod(cl->vftbl->class,
2004 utf_java_lang_String__java_lang_Class,
2005 class_java_lang_Object,
2011 r = (classinfo *) asm_calljavafunction(lc,
2013 javastring_new(c->name),
2019 return load_class_bootstrap(c);
2024 /* load_class_bootstrap ********************************************************
2028 *******************************************************************************/
2030 classinfo *load_class_bootstrap(classinfo *c)
2035 #if defined(USE_THREADS)
2036 /* enter a monitor on the class */
2038 builtin_monitorenter((java_objectheader *) c);
2041 /* maybe the class is already loaded */
2044 #if defined(USE_THREADS)
2045 builtin_monitorexit((java_objectheader *) c);
2051 #if defined(STATISTICS)
2054 if (getcompilingtime)
2055 compilingtime_stop();
2058 loadingtime_start();
2061 /* load classdata, throw exception on error */
2063 if ((cb = suck_start(c)) == NULL) {
2064 /* this means, the classpath was not set properly */
2065 if (c->name == utf_java_lang_Object)
2066 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2067 "java/lang/Object");
2070 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2073 #if defined(USE_THREADS)
2074 builtin_monitorexit((java_objectheader *) c);
2080 /* load the class from the buffer */
2082 r = load_class_from_classbuffer(cb);
2084 /* if return value is NULL, we had a problem and the class is not loaded */
2088 /* now free the allocated memory, otherwise we could ran into a DOS */
2095 #if defined(STATISTICS)
2101 if (getcompilingtime)
2102 compilingtime_start();
2105 #if defined(USE_THREADS)
2106 /* leave the monitor */
2108 builtin_monitorexit((java_objectheader *) c);
2115 /* load_class_from_classbuffer *************************************************
2117 Loads everything interesting about a class from the class file. The
2118 'classinfo' structure must have been allocated previously.
2120 The super class and the interfaces implemented by this class need
2121 not be loaded. The link is set later by the function 'class_link'.
2123 The loaded class is removed from the list 'unloadedclasses' and
2124 added to the list 'unlinkedclasses'.
2126 *******************************************************************************/
2128 classinfo *load_class_from_classbuffer(classbuffer *cb)
2135 descriptor_pool *descpool;
2136 char msg[MAXLOGTEXT]; /* maybe we get an exception */
2137 #if defined(STATISTICS)
2142 /* get the classbuffer's class */
2145 /* maybe the class is already loaded */
2149 #if defined(STATISTICS)
2151 count_class_loads++;
2154 /* output for debugging purposes */
2156 log_message_class("Loading class: ", c);
2158 /* mark start of dump memory area */
2159 dumpsize = dump_size();
2161 /* class is somewhat loaded */
2164 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2165 goto return_exception;
2167 /* check signature */
2168 if (suck_u4(cb) != MAGIC) {
2169 *exceptionptr = new_classformaterror(c, "Bad magic number");
2171 goto return_exception;
2178 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2180 new_unsupportedclassversionerror(c,
2181 "Unsupported major.minor version %d.%d",
2184 goto return_exception;
2187 /* create a new descriptor pool */
2188 descpool = descriptor_pool_new(c);
2190 /* load the constant pool */
2191 if (!load_constantpool(cb,descpool))
2192 goto return_exception;
2195 c->erroneous_state = 0;
2196 c->initializing_thread = 0;
2198 c->classUsed = NOTUSED; /* not used initially CO-RT */
2202 if (!check_classbuffer_size(cb, 2))
2203 goto return_exception;
2205 c->flags = suck_u2(cb);
2206 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2208 /* check ACC flags consistency */
2209 if (c->flags & ACC_INTERFACE) {
2210 if (!(c->flags & ACC_ABSTRACT)) {
2211 /* We work around this because interfaces in JDK 1.1 are
2212 * not declared abstract. */
2214 c->flags |= ACC_ABSTRACT;
2215 /* panic("Interface class not declared abstract"); */
2218 if (c->flags & ACC_FINAL) {
2220 new_classformaterror(c,
2221 "Illegal class modifiers: 0x%X", c->flags);
2223 goto return_exception;
2226 if (c->flags & ACC_SUPER) {
2227 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2231 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2233 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2235 goto return_exception;
2238 if (!check_classbuffer_size(cb, 2 + 2))
2239 goto return_exception;
2243 if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
2244 goto return_exception;
2247 utf_sprint(msg, c->name);
2248 sprintf(msg + strlen(msg), " (wrong name: ");
2249 utf_sprint(msg + strlen(msg), tc->name);
2250 sprintf(msg + strlen(msg), ")");
2253 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2255 goto return_exception;
2258 /* retrieve superclass */
2259 if ((i = suck_u2(cb))) {
2260 if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
2261 goto return_exception;
2263 /* java.lang.Object may not have a super class. */
2264 if (c->name == utf_java_lang_Object) {
2266 new_exception_message(string_java_lang_ClassFormatError,
2267 "java.lang.Object with superclass");
2269 goto return_exception;
2272 /* Interfaces must have java.lang.Object as super class. */
2273 if ((c->flags & ACC_INTERFACE) &&
2274 c->super->name != utf_java_lang_Object) {
2276 new_exception_message(string_java_lang_ClassFormatError,
2277 "Interfaces must have java.lang.Object as superclass");
2279 goto return_exception;
2285 /* This is only allowed for java.lang.Object. */
2286 if (c->name != utf_java_lang_Object) {
2287 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2289 goto return_exception;
2293 /* retrieve interfaces */
2294 if (!check_classbuffer_size(cb, 2))
2295 goto return_exception;
2297 c->interfacescount = suck_u2(cb);
2299 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2300 goto return_exception;
2302 c->interfaces = MNEW(classinfo*, c->interfacescount);
2303 for (i = 0; i < c->interfacescount; i++) {
2304 if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2305 goto return_exception;
2309 if (!check_classbuffer_size(cb, 2))
2310 goto return_exception;
2312 c->fieldscount = suck_u2(cb);
2313 c->fields = GCNEW(fieldinfo, c->fieldscount);
2314 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2315 for (i = 0; i < c->fieldscount; i++) {
2316 if (!load_field(cb, &(c->fields[i]),descpool))
2317 goto return_exception;
2321 if (!check_classbuffer_size(cb, 2))
2322 goto return_exception;
2324 c->methodscount = suck_u2(cb);
2325 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2326 c->methods = MNEW(methodinfo, c->methodscount);
2327 for (i = 0; i < c->methodscount; i++) {
2328 if (!load_method(cb, &(c->methods[i]),descpool))
2329 goto return_exception;
2332 /* create the class reference table */
2333 c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
2335 /* allocate space for the parsed descriptors */
2336 descriptor_pool_alloc_parsed_descriptors(descpool);
2337 c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
2339 #if defined(STATISTICS)
2341 descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
2342 count_classref_len += classrefsize;
2343 count_parsed_desc_len += descsize;
2347 /* parse the loaded descriptors */
2348 for (i=0; i<c->cpcount; ++i) {
2349 constant_FMIref *fmi;
2351 switch (c->cptags[i]) {
2352 case CONSTANT_Class:
2353 /* XXX set classref */
2355 case CONSTANT_Fieldref:
2356 fmi = (constant_FMIref *)c->cpinfos[i];
2357 fmi->parseddesc.fd =
2358 descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor);
2359 if (!fmi->parseddesc.fd)
2360 goto return_exception;
2361 fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
2363 case CONSTANT_Methodref:
2364 case CONSTANT_InterfaceMethodref:
2365 fmi = (constant_FMIref *)c->cpinfos[i];
2366 fmi->parseddesc.md =
2367 descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor);
2368 if (!fmi->parseddesc.md)
2369 goto return_exception;
2370 fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
2374 for (i = 0; i < c->fieldscount; i++) {
2375 c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor);
2376 if (!c->fields[i].parseddesc)
2377 goto return_exception;
2379 for (i = 0; i < c->methodscount; i++) {
2380 c->methods[i].parseddesc = descriptor_pool_parse_method_descriptor(descpool,c->methods[i].descriptor);
2381 if (!c->methods[i].parseddesc)
2382 goto return_exception;
2385 /* Check if all fields and methods can be uniquely
2386 * identified by (name,descriptor). */
2388 /* We use a hash table here to avoid making the
2389 * average case quadratic in # of methods, fields.
2391 static int shift = 0;
2393 u2 *next; /* for chaining colliding hash entries */
2399 /* Allocate hashtable */
2400 len = c->methodscount;
2401 if (len < c->fieldscount) len = c->fieldscount;
2403 hashtab = MNEW(u2,(hashlen + len));
2404 next = hashtab + hashlen;
2406 /* Determine bitshift (to get good hash values) */
2416 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2418 for (i = 0; i < c->fieldscount; ++i) {
2419 fieldinfo *fi = c->fields + i;
2421 /* It's ok if we lose bits here */
2422 index = ((((size_t) fi->name) +
2423 ((size_t) fi->descriptor)) >> shift) % hashlen;
2425 if ((old = hashtab[index])) {
2429 if (c->fields[old].name == fi->name &&
2430 c->fields[old].descriptor == fi->descriptor) {
2432 new_classformaterror(c,
2433 "Repetitive field name/signature");
2435 goto return_exception;
2437 } while ((old = next[old]));
2439 hashtab[index] = i + 1;
2443 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2445 for (i = 0; i < c->methodscount; ++i) {
2446 methodinfo *mi = c->methods + i;
2448 /* It's ok if we lose bits here */
2449 index = ((((size_t) mi->name) +
2450 ((size_t) mi->descriptor)) >> shift) % hashlen;
2454 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2455 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2459 if ((old = hashtab[index])) {
2463 if (c->methods[old].name == mi->name &&
2464 c->methods[old].descriptor == mi->descriptor) {
2466 new_classformaterror(c,
2467 "Repetitive method name/signature");
2469 goto return_exception;
2471 } while ((old = next[old]));
2473 hashtab[index] = i + 1;
2476 MFREE(hashtab, u2, (hashlen + len));
2479 #if defined(STATISTICS)
2481 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2482 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2483 count_class_infos += sizeof(methodinfo) * c->methodscount;
2487 /* load attribute structures */
2488 if (!check_classbuffer_size(cb, 2))
2489 goto return_exception;
2491 if (!load_attributes(cb, suck_u2(cb)))
2492 goto return_exception;
2495 /* Pre java 1.5 version don't check this. This implementation is like
2496 java 1.5 do it: for class file version 45.3 we don't check it, older
2497 versions are checked.
2499 if ((ma == 45 && mi > 3) || ma > 45) {
2500 /* check if all data has been read */
2501 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2503 if (classdata_left > 0) {
2505 new_classformaterror(c, "Extra bytes at the end of class file");
2506 goto return_exception;
2511 /* release dump area */
2512 dump_release(dumpsize);
2515 log_message_class("Loading done class: ", c);
2520 /* release dump area */
2521 dump_release(dumpsize);
2523 /* an exception has been thrown */
2529 /******************* Function: class_new_array *********************************
2531 This function is called by class_new to setup an array class.
2533 *******************************************************************************/
2535 void class_new_array(classinfo *c)
2537 classinfo *comp = NULL;
2539 methoddesc *clonedesc;
2540 constant_classref *classrefs;
2543 /* Check array class name */
2544 namelen = c->name->blength;
2545 if (namelen < 2 || c->name->text[0] != '[')
2546 panic("Invalid array class name");
2548 /* Check the component type */
2549 switch (c->name->text[1]) {
2551 /* c is an array of arrays. We have to create the component class. */
2553 comp = class_new_intern(utf_new_intern(c->name->text + 1,
2555 load_class_from_classloader(comp, c->classloader);
2556 list_addfirst(&unlinkedclasses, comp);
2559 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2564 /* c is an array of objects. */
2565 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2566 panic("Invalid array class name");
2569 comp = class_new_intern(utf_new_intern(c->name->text + 2,
2571 load_class_from_classloader(comp, c->classloader);
2572 list_addfirst(&unlinkedclasses, comp);
2575 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2580 /* Setup the array class */
2581 c->super = class_java_lang_Object;
2582 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2584 c->interfacescount = 2;
2585 c->interfaces = MNEW(classinfo*, 2);
2590 tc = class_java_lang_Cloneable;
2591 load_class_bootstrap(tc);
2592 list_addfirst(&unlinkedclasses, tc);
2593 c->interfaces[0] = tc;
2595 tc = class_java_io_Serializable;
2596 load_class_bootstrap(tc);
2597 list_addfirst(&unlinkedclasses, tc);
2598 c->interfaces[1] = tc;
2601 c->interfaces[0] = class_java_lang_Cloneable;
2602 c->interfaces[1] = class_java_io_Serializable;
2605 c->methodscount = 1;
2606 c->methods = MNEW(methodinfo, c->methodscount);
2608 classrefs = MNEW(constant_classref,1);
2609 CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
2611 clonedesc = NEW(methoddesc);
2612 clonedesc->returntype.type = TYPE_ADDRESS;
2613 clonedesc->returntype.classref = classrefs;
2614 clonedesc->returntype.arraydim = 0;
2615 clonedesc->paramcount = 0;
2616 clonedesc->paramslots = 0;
2619 MSET(clone, 0, methodinfo, 1);
2620 clone->flags = ACC_PUBLIC;
2621 clone->name = utf_new_char("clone");
2622 clone->descriptor = utf_void__java_lang_Object;
2623 clone->parseddesc = clonedesc;
2625 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2626 clone->monoPoly = MONO;
2628 /* XXX: field: length? */
2630 /* array classes are not loaded from class files */
2632 c->parseddescs = (u1*) clonedesc;
2633 c->parseddescsize = sizeof(methodinfo);
2634 c->classrefs = classrefs;
2635 c->classrefcount = 1;
2637 /* XXX insert class into the loaded class cache */
2641 /************************* Function: class_findfield ***************************
2643 Searches a 'classinfo' structure for a field having the given name and
2646 *******************************************************************************/
2648 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2652 for (i = 0; i < c->fieldscount; i++) {
2653 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2654 return &(c->fields[i]);
2657 panic("Can not find field given in CONSTANT_Fieldref");
2659 /* keep compiler happy */
2664 /****************** Function: class_resolvefield_int ***************************
2666 This is an internally used helper function. Do not use this directly.
2668 Tries to resolve a field having the given name and type.
2669 If the field cannot be resolved, NULL is returned.
2671 *******************************************************************************/
2673 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2678 /* search for field in class c */
2680 for (i = 0; i < c->fieldscount; i++) {
2681 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2682 return &(c->fields[i]);
2686 /* try superinterfaces recursively */
2688 for (i = 0; i < c->interfacescount; i++) {
2689 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2694 /* try superclass */
2697 return class_resolvefield_int(c->super, name, desc);
2705 /********************* Function: class_resolvefield ***************************
2707 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2709 If the field cannot be resolved the return value is NULL. If EXCEPT is
2710 true *exceptionptr is set, too.
2712 *******************************************************************************/
2714 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2715 classinfo *referer, bool except)
2719 /* XXX resolve class c */
2720 /* XXX check access from REFERER to C */
2722 fi = class_resolvefield_int(c, name, desc);
2727 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2733 /* XXX check access rights */
2739 /* class_findmethod ************************************************************
2741 Searches a 'classinfo' structure for a method having the given name
2742 and descriptor. If descriptor is NULL, it is ignored.
2744 *******************************************************************************/
2746 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2751 for (i = 0; i < c->methodscount; i++) {
2752 m = &(c->methods[i]);
2754 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2762 /*********************** Function: class_fetchmethod **************************
2764 like class_findmethod, but aborts with an error if the method is not found
2766 *******************************************************************************/
2768 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2772 mi = class_findmethod(c, name, desc);
2775 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2776 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2777 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2778 panic("Method not found");
2785 /************************* Function: class_findmethod_approx ******************
2787 like class_findmethod but ignores the return value when comparing the
2790 *******************************************************************************/
2792 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2796 for (i = 0; i < c->methodscount; i++) {
2797 if (c->methods[i].name == name) {
2798 utf *meth_descr = c->methods[i].descriptor;
2802 return &(c->methods[i]);
2804 if (desc->blength <= meth_descr->blength) {
2805 /* current position in utf text */
2806 char *desc_utf_ptr = desc->text;
2807 char *meth_utf_ptr = meth_descr->text;
2808 /* points behind utf strings */
2809 char *desc_end = utf_end(desc);
2810 char *meth_end = utf_end(meth_descr);
2813 /* compare argument types */
2814 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2816 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2817 break; /* no match */
2820 return &(c->methods[i]); /* all parameter types equal */
2830 /***************** Function: class_resolvemethod_approx ***********************
2832 Searches a class and every super class for a method (without paying
2833 attention to the return value)
2835 *******************************************************************************/
2837 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2840 /* search for method (ignore returntype) */
2841 methodinfo *m = class_findmethod_approx(c, name, desc);
2844 /* search superclass */
2852 /* class_resolvemethod *********************************************************
2854 Searches a class and it's super classes for a method.
2856 *******************************************************************************/
2858 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2863 m = class_findmethod(c, name, desc);
2875 /* class_resolveinterfacemethod_intern *****************************************
2877 Internally used helper function. Do not use this directly.
2879 *******************************************************************************/
2881 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2882 utf *name, utf *desc)
2887 m = class_findmethod(c, name, desc);
2892 /* try the superinterfaces */
2894 for (i = 0; i < c->interfacescount; i++) {
2895 m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2904 /* class_resolveinterfacemethod ************************************************
2906 Resolves a reference from REFERER to a method with NAME and DESC in
2909 If the method cannot be resolved the return value is NULL. If
2910 EXCEPT is true *exceptionptr is set, too.
2912 *******************************************************************************/
2914 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2915 classinfo *referer, bool except)
2919 /* XXX resolve class c */
2920 /* XXX check access from REFERER to C */
2922 if (!(c->flags & ACC_INTERFACE)) {
2925 new_exception(string_java_lang_IncompatibleClassChangeError);
2930 mi = class_resolveinterfacemethod_intern(c, name, desc);
2935 /* try class java.lang.Object */
2936 mi = class_findmethod(class_java_lang_Object, name, desc);
2943 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2949 /* class_resolveclassmethod ****************************************************
2951 Resolves a reference from REFERER to a method with NAME and DESC in
2954 If the method cannot be resolved the return value is NULL. If EXCEPT is
2955 true *exceptionptr is set, too.
2957 *******************************************************************************/
2959 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2960 classinfo *referer, bool except)
2968 /* XXX resolve class c */
2969 /* XXX check access from REFERER to C */
2971 /* if (c->flags & ACC_INTERFACE) { */
2973 /* *exceptionptr = */
2974 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
2978 /* try class c and its superclasses */
2983 mi = class_findmethod(cls, name, desc);
2991 /* try the superinterfaces */
2993 for (i = 0; i < c->interfacescount; i++) {
2994 mi = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
3001 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
3002 utf_strlen(desc) + strlen("0");
3004 msg = MNEW(char, msglen);
3006 utf_sprint(msg, c->name);
3008 utf_sprint(msg + strlen(msg), name);
3009 utf_sprint(msg + strlen(msg), desc);
3012 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3014 MFREE(msg, char, msglen);
3020 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3022 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3027 /* XXX check access rights */
3033 /************************* Function: class_issubclass **************************
3035 Checks if sub is a descendant of super.
3037 *******************************************************************************/
3039 bool class_issubclass(classinfo *sub, classinfo *super)
3042 if (!sub) return false;
3043 if (sub == super) return true;
3049 /****************** Initialization function for classes ******************
3051 In Java, every class can have a static initialization function. This
3052 function has to be called BEFORE calling other methods or accessing static
3055 *******************************************************************************/
3057 static classinfo *class_init_intern(classinfo *c);
3059 classinfo *class_init(classinfo *c)
3063 if (!makeinitializations)
3066 #if defined(USE_THREADS)
3067 /* enter a monitor on the class */
3069 builtin_monitorenter((java_objectheader *) c);
3072 /* maybe the class is already initalized or the current thread, which can
3073 pass the monitor, is currently initalizing this class */
3075 /* JOWENN: In future we need an additinal flag: initializationfailed,
3076 since further access to the class should cause a NoClassDefFound,
3077 if the static initializer failed once
3080 if (c->initialized || c->initializing) {
3081 #if defined(USE_THREADS)
3082 builtin_monitorexit((java_objectheader *) c);
3088 /* this initalizing run begins NOW */
3089 c->initializing = true;
3091 /* call the internal function */
3092 r = class_init_intern(c);
3094 /* if return value is not NULL everything was ok and the class is
3097 c->initialized = true;
3099 /* this initalizing run is done */
3100 c->initializing = false;
3102 #if defined(USE_THREADS)
3103 /* leave the monitor */
3105 builtin_monitorexit((java_objectheader *) c);
3112 /* this function MUST NOT be called directly, because of thread <clinit>
3115 static classinfo *class_init_intern(classinfo *c)
3119 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3123 /* maybe the class is not already loaded */
3125 if (!load_class_bootstrap(c))
3128 /* maybe the class is not already linked */
3133 #if defined(STATISTICS)
3135 count_class_inits++;
3138 /* initialize super class */
3141 if (!c->super->initialized) {
3143 char logtext[MAXLOGTEXT];
3144 sprintf(logtext, "Initialize super class ");
3145 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3146 sprintf(logtext + strlen(logtext), " from ");
3147 utf_sprint_classname(logtext + strlen(logtext), c->name);
3151 if (!class_init(c->super))
3156 /* initialize interface classes */
3158 for (i = 0; i < c->interfacescount; i++) {
3159 if (!c->interfaces[i]->initialized) {
3161 char logtext[MAXLOGTEXT];
3162 sprintf(logtext, "Initialize interface class ");
3163 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3164 sprintf(logtext + strlen(logtext), " from ");
3165 utf_sprint_classname(logtext + strlen(logtext), c->name);
3169 if (!class_init(c->interfaces[i]))
3174 m = class_findmethod(c, utf_clinit, utf_void__void);
3178 char logtext[MAXLOGTEXT];
3179 sprintf(logtext, "Class ");
3180 utf_sprint_classname(logtext + strlen(logtext), c->name);
3181 sprintf(logtext + strlen(logtext), " has no static class initializer");
3188 /* Sun's and IBM's JVM don't care about the static flag */
3189 /* if (!(m->flags & ACC_STATIC)) { */
3190 /* panic("Class initializer is not static!"); */
3193 log_message_class("Starting static class initializer for class: ", c);
3195 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3200 /* now call the initializer */
3201 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3203 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3204 assert(blockInts == 0);
3208 /* we have an exception or error */
3209 if (*exceptionptr) {
3210 /* class is NOT initialized */
3211 c->initialized = false;
3213 /* is this an exception, than wrap it */
3214 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3215 java_objectheader *xptr;
3216 java_objectheader *cause;
3219 cause = *exceptionptr;
3221 /* clear exception, because we are calling jit code again */
3222 *exceptionptr = NULL;
3224 /* wrap the exception */
3226 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3227 (java_lang_Throwable *) cause);
3229 /* XXX should we exit here? */
3233 /* set new exception */
3234 *exceptionptr = xptr;
3241 log_message_class("Finished static class initializer for class: ", c);
3247 void class_showconstanti(classinfo *c, int ii)
3253 printf ("#%d: ", (int) i);
3255 switch (c->cptags [i]) {
3256 case CONSTANT_Class:
3257 printf("Classreference -> ");
3258 utf_display(((classinfo*)e)->name);
3261 case CONSTANT_Fieldref:
3262 printf("Fieldref -> "); goto displayFMIi;
3263 case CONSTANT_Methodref:
3264 printf("Methodref -> "); goto displayFMIi;
3265 case CONSTANT_InterfaceMethodref:
3266 printf("InterfaceMethod -> "); goto displayFMIi;
3269 constant_FMIref *fmi = e;
3270 utf_display(fmi->class->name);
3272 utf_display(fmi->name);
3274 utf_display(fmi->descriptor);
3278 case CONSTANT_String:
3279 printf("String -> ");
3282 case CONSTANT_Integer:
3283 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3285 case CONSTANT_Float:
3286 printf("Float -> %f", ((constant_float*)e)->value);
3288 case CONSTANT_Double:
3289 printf("Double -> %f", ((constant_double*)e)->value);
3293 u8 v = ((constant_long*)e)->value;
3295 printf("Long -> %ld", (long int) v);
3297 printf("Long -> HI: %ld, LO: %ld\n",
3298 (long int) v.high, (long int) v.low);
3302 case CONSTANT_NameAndType:
3304 constant_nameandtype *cnt = e;
3305 printf("NameAndType: ");
3306 utf_display(cnt->name);
3308 utf_display(cnt->descriptor);
3316 panic("Invalid type of ConstantPool-Entry");
3323 void class_showconstantpool (classinfo *c)
3328 printf ("---- dump of constant pool ----\n");
3330 for (i=0; i<c->cpcount; i++) {
3331 printf ("#%d: ", (int) i);
3333 e = c -> cpinfos [i];
3336 switch (c -> cptags [i]) {
3337 case CONSTANT_Class:
3338 printf ("Classreference -> ");
3339 utf_display ( ((classinfo*)e) -> name );
3342 case CONSTANT_Fieldref:
3343 printf ("Fieldref -> "); goto displayFMI;
3344 case CONSTANT_Methodref:
3345 printf ("Methodref -> "); goto displayFMI;
3346 case CONSTANT_InterfaceMethodref:
3347 printf ("InterfaceMethod -> "); goto displayFMI;
3350 constant_FMIref *fmi = e;
3351 utf_display ( fmi->class->name );
3353 utf_display ( fmi->name);
3355 utf_display ( fmi->descriptor );
3359 case CONSTANT_String:
3360 printf ("String -> ");
3363 case CONSTANT_Integer:
3364 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3366 case CONSTANT_Float:
3367 printf ("Float -> %f", ((constant_float*)e) -> value);
3369 case CONSTANT_Double:
3370 printf ("Double -> %f", ((constant_double*)e) -> value);
3374 u8 v = ((constant_long*)e) -> value;
3376 printf ("Long -> %ld", (long int) v);
3378 printf ("Long -> HI: %ld, LO: %ld\n",
3379 (long int) v.high, (long int) v.low);
3383 case CONSTANT_NameAndType:
3385 constant_nameandtype *cnt = e;
3386 printf ("NameAndType: ");
3387 utf_display (cnt->name);
3389 utf_display (cnt->descriptor);
3393 printf ("Utf8 -> ");
3397 panic ("Invalid type of ConstantPool-Entry");
3407 /********** Function: class_showmethods (debugging only) *************/
3409 void class_showmethods (classinfo *c)
3413 printf ("--------- Fields and Methods ----------------\n");
3414 printf ("Flags: "); printflags (c->flags); printf ("\n");
3416 printf ("This: "); utf_display (c->name); printf ("\n");
3418 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3420 printf ("Index: %d\n", c->index);
3422 printf ("interfaces:\n");
3423 for (i=0; i < c-> interfacescount; i++) {
3425 utf_display (c -> interfaces[i] -> name);
3426 printf (" (%d)\n", c->interfaces[i] -> index);
3429 printf ("fields:\n");
3430 for (i=0; i < c -> fieldscount; i++) {
3431 field_display (&(c -> fields[i]));
3434 printf ("methods:\n");
3435 for (i=0; i < c -> methodscount; i++) {
3436 methodinfo *m = &(c->methods[i]);
3437 if ( !(m->flags & ACC_STATIC))
3438 printf ("vftblindex: %d ", m->vftblindex);
3440 method_display ( m );
3444 printf ("Virtual function table:\n");
3445 for (i=0; i<c->vftbl->vftbllength; i++) {
3446 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3452 /******************************************************************************/
3453 /******************* General functions for the class loader *******************/
3454 /******************************************************************************/
3456 /**************** function: class_primitive_from_sig ***************************
3458 return the primitive class indicated by the given signature character
3460 If the descriptor does not indicate a valid primitive type the
3461 return value is NULL.
3463 ********************************************************************************/
3465 classinfo *class_primitive_from_sig(char sig)
3468 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3469 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3470 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3471 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3472 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3473 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3474 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3475 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3476 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3481 /****************** function: class_from_descriptor ****************************
3483 return the class indicated by the given descriptor
3485 utf_ptr....first character of descriptor
3486 end_ptr....first character after the end of the string
3487 next.......if non-NULL, *next is set to the first character after
3488 the descriptor. (Undefined if an error occurs.)
3490 mode.......a combination (binary or) of the following flags:
3492 (Flags marked with * are the default settings.)
3494 What to do if a reference type descriptor is parsed successfully:
3496 CLASSLOAD_SKIP...skip it and return something != NULL
3497 * CLASSLOAD_NEW....get classinfo * via class_new
3498 CLASSLOAD_LOAD...get classinfo * via loader_load
3500 How to handle primitive types:
3502 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3503 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3505 How to handle "V" descriptors:
3507 * CLASSLOAD_VOID.....handle it like other primitive types
3508 CLASSLOAD_NOVOID...treat it as an error
3510 How to deal with extra characters after the end of the
3513 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3514 CLASSLOAD_CHECKEND.....treat them as an error
3516 How to deal with errors:
3518 * CLASSLOAD_PANIC....abort execution with an error message
3519 CLASSLOAD_NOPANIC..return NULL on error
3521 *******************************************************************************/
3523 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3524 char **next, int mode)
3526 char *start = utf_ptr;
3530 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3532 if (mode & CLASSLOAD_CHECKEND)
3533 error |= (utf_ptr != end_ptr);
3536 if (next) *next = utf_ptr;
3540 if (mode & CLASSLOAD_NOVOID)
3551 return (mode & CLASSLOAD_NULLPRIMITIVE)
3553 : class_primitive_from_sig(*start);
3560 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3561 name = utf_new(start, utf_ptr - start);
3565 tc = class_new_intern(name);
3566 load_class_from_classloader(tc, NULL);
3567 list_addfirst(&unlinkedclasses, tc);
3572 return (mode & CLASSLOAD_LOAD)
3573 ? load_class_from_classloader(class_new(name), NULL) : class_new(name); /* XXX handle errors */
3578 /* An error occurred */
3579 if (mode & CLASSLOAD_NOPANIC)
3582 log_plain("Invalid descriptor at beginning of '");
3583 log_plain_utf(utf_new(start, end_ptr - start));
3587 panic("Invalid descriptor");
3589 /* keep compiler happy */
3594 /******************* function: type_from_descriptor ****************************
3596 return the basic type indicated by the given descriptor
3598 This function parses a descriptor and returns its basic type as
3599 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3601 cls...if non-NULL the referenced variable is set to the classinfo *
3602 returned by class_from_descriptor.
3604 For documentation of the arguments utf_ptr, end_ptr, next and mode
3605 see class_from_descriptor. The only difference is that
3606 type_from_descriptor always uses CLASSLOAD_PANIC.
3608 ********************************************************************************/
3610 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3611 char **next, int mode)
3614 if (!cls) cls = &mycls;
3615 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3632 return TYPE_ADDRESS;
3636 /******************** Function: loader_close ***********************************
3640 *******************************************************************************/
3647 for (slot = 0; slot < class_hash.size; slot++) {
3648 c = class_hash.ptr[slot];
3659 * These are local overrides for various environment variables in Emacs.
3660 * Please do not remove this and leave it at the end of the file, where
3661 * Emacs will automagically detect them.
3662 * ---------------------------------------------------------------------
3665 * indent-tabs-mode: t