370db3fa00216688d20ba3bd2a9ddc94080f23d5
[cacao.git] / src / vm / loader.c
1 /* src/vm/loader.c - class loader functions
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Andreas Krall
30             Roman Obermaiser
31             Mark Probst
32             Edwin Steiner
33             Christian Thalinger
34
35    $Id: loader.c 3513 2005-10-28 11:30:19Z twisti $
36
37 */
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <sys/stat.h>
43
44 #include "config.h"
45 #include "mm/memory.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_Throwable.h"
48
49 #if defined(USE_THREADS)
50 # if defined(NATIVE_THREADS)
51 #  include "threads/native/threads.h"
52 # else
53 #  include "threads/green/threads.h"
54 #  include "threads/green/locks.h"
55 # endif
56 #endif
57
58 #include "toolbox/logging.h"
59 #include "toolbox/util.h"
60 #include "vm/exceptions.h"
61 #include "vm/builtin.h"
62 #include "vm/global.h"
63 #include "vm/linker.h"
64 #include "vm/loader.h"
65 #include "vm/options.h"
66 #include "vm/statistics.h"
67 #include "vm/stringlocal.h"
68 #include "vm/tables.h"
69 #include "vm/classcache.h"
70
71 #if defined(USE_ZLIB)
72 # include "vm/unzip.h"
73 #endif
74
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen.inc.h"
77
78 /******************************************************************************/
79 /* DEBUG HELPERS                                                              */
80 /******************************************************************************/
81
82 /*#define LOADER_VERBOSE*/
83
84 #ifndef NDEBUG
85 #define LOADER_DEBUG
86 #endif
87
88 #ifdef LOADER_DEBUG
89 #define LOADER_ASSERT(cond)  assert(cond)
90 #else
91 #define LOADER_ASSERT(cond)
92 #endif
93
94 #undef JOWENN_DEBUG
95 #undef JOWENN_DEBUG1
96 #undef JOWENN_DEBUG2
97
98 #ifdef LOADER_VERBOSE
99 static int loader_recursion = 0;
100 #define LOADER_INDENT(str)   do { int i; for(i=0;i<loader_recursion*4;++i) {str[i]=' ';} str[i]=0;} while (0)
101 #define LOADER_INC()  loader_recursion++
102 #define LOADER_DEC()  loader_recursion--
103 #else
104 #define LOADER_INC()
105 #define LOADER_DEC()
106 #endif
107
108
109 /********************************************************************
110    list of classpath entries (either filesystem directories or 
111    ZIP/JAR archives
112 ********************************************************************/
113
114 classpath_info *classpath_entries = NULL;
115
116
117 /* loader_init *****************************************************************
118
119    Initializes all lists and loads all classes required for the system
120    or the compiler.
121
122 *******************************************************************************/
123  
124 bool loader_init(u1 *stackbottom)
125 {
126 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
127         classpath_info *cpi;
128
129         /* Initialize the monitor pointer for zip/jar file locking. */
130
131         for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
132                 if (cpi->type == CLASSPATH_ARCHIVE)
133                         initObjectLock(&cpi->header);
134         }
135 #endif
136
137         /* load some important classes */
138
139         if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
140                 return false;
141
142         if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
143                 return false;
144
145         if (!(class_java_lang_Cloneable =
146                   load_class_bootstrap(utf_java_lang_Cloneable)))
147                 return false;
148
149         if (!(class_java_io_Serializable =
150                   load_class_bootstrap(utf_java_io_Serializable)))
151                 return false;
152
153
154         /* load classes for wrapping primitive types */
155
156         if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
157                 return false;
158
159         if (!(class_java_lang_Boolean =
160                   load_class_bootstrap(utf_java_lang_Boolean)))
161                 return false;
162
163         if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
164                 return false;
165
166         if (!(class_java_lang_Character =
167                   load_class_bootstrap(utf_java_lang_Character)))
168                 return false;
169
170         if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
171                 return false;
172
173         if (!(class_java_lang_Integer =
174                   load_class_bootstrap(utf_java_lang_Integer)))
175                 return false;
176
177         if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
178                 return false;
179
180         if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
181                 return false;
182
183         if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
184                 return false;
185
186
187         /* load some other important classes */
188
189         if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
190                 return false;
191
192         if (!(class_java_lang_ClassLoader =
193                   load_class_bootstrap(utf_java_lang_ClassLoader)))
194                 return false;
195
196         if (!(class_java_lang_SecurityManager =
197                   load_class_bootstrap(utf_java_lang_SecurityManager)))
198                 return false;
199
200         if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
201                 return false;
202
203         if (!(class_java_lang_Thread =
204                   load_class_bootstrap(utf_new_char("java/lang/Thread"))))
205                 return false;
206
207         if (!(class_java_lang_ThreadGroup =
208                   load_class_bootstrap(utf_java_lang_ThreadGroup)))
209                 return false;
210
211         if (!(class_java_lang_VMThread =
212                   load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
213                 return false;
214
215
216         /* some classes which may be used more often */
217
218         if (!(class_java_lang_StackTraceElement =
219                   load_class_bootstrap(utf_java_lang_StackTraceElement)))
220                 return false;
221
222         if (!(class_java_lang_reflect_Constructor =
223                   load_class_bootstrap(utf_java_lang_reflect_Constructor)))
224                 return false;
225
226         if (!(class_java_lang_reflect_Field =
227                   load_class_bootstrap(utf_java_lang_reflect_Field)))
228                 return false;
229
230         if (!(class_java_lang_reflect_Method =
231                   load_class_bootstrap(utf_java_lang_reflect_Method)))
232                 return false;
233
234         if (!(class_java_security_PrivilegedAction =
235                   load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
236                 return false;
237
238         if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
239                 return false;
240
241         if (!(arrayclass_java_lang_Object =
242                   load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
243                 return false;
244
245 #if defined(USE_THREADS)
246         if (stackbottom != 0)
247                 initLocks();
248 #endif
249
250         return true;
251 }
252
253
254 /************* functions for reading classdata *********************************
255
256     getting classdata in blocks of variable size
257     (8,16,32,64-bit integer or float)
258
259 *******************************************************************************/
260
261 /* check_classbuffer_size ******************************************************
262
263    assert that at least <len> bytes are left to read
264    <len> is limited to the range of non-negative s4 values
265
266 *******************************************************************************/
267
268 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
269 {
270         if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
271                 *exceptionptr =
272                         new_classformaterror((cb)->class, "Truncated class file");
273
274                 return false;
275         }
276
277         return true;
278 }
279
280
281 /* suck_nbytes *****************************************************************
282
283    transfer block of classfile data into a buffer
284
285 *******************************************************************************/
286
287 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
288 {
289         memcpy(buffer, cb->pos + 1, len);
290         cb->pos += len;
291 }
292
293
294 /* skip_nbytes ****************************************************************
295
296    skip block of classfile data
297
298 *******************************************************************************/
299
300 inline void skip_nbytes(classbuffer *cb, s4 len)
301 {
302         cb->pos += len;
303 }
304
305
306 inline u1 suck_u1(classbuffer *cb)
307 {
308         return *++(cb->pos);
309 }
310
311
312 inline u2 suck_u2(classbuffer *cb)
313 {
314         u1 a = suck_u1(cb);
315         u1 b = suck_u1(cb);
316         return ((u2) a << 8) + (u2) b;
317 }
318
319
320 inline u4 suck_u4(classbuffer *cb)
321 {
322         u1 a = suck_u1(cb);
323         u1 b = suck_u1(cb);
324         u1 c = suck_u1(cb);
325         u1 d = suck_u1(cb);
326         return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
327 }
328
329
330 /* get u8 from classfile data */
331 static u8 suck_u8(classbuffer *cb)
332 {
333 #if U8_AVAILABLE
334         u8 lo, hi;
335         hi = suck_u4(cb);
336         lo = suck_u4(cb);
337         return (hi << 32) + lo;
338 #else
339         u8 v;
340         v.high = suck_u4(cb);
341         v.low = suck_u4(cb);
342         return v;
343 #endif
344 }
345
346
347 /* get float from classfile data */
348 static float suck_float(classbuffer *cb)
349 {
350         float f;
351
352 #if !WORDS_BIGENDIAN 
353         u1 buffer[4];
354         u2 i;
355
356         for (i = 0; i < 4; i++)
357                 buffer[3 - i] = suck_u1(cb);
358
359         memcpy((u1*) (&f), buffer, 4);
360 #else
361         suck_nbytes((u1*) (&f), cb, 4);
362 #endif
363
364         if (sizeof(float) != 4) {
365                 *exceptionptr = new_internalerror("Incompatible float-format");
366
367                 /* XXX should we exit in such a case? */
368                 throw_exception_exit();
369         }
370         
371         return f;
372 }
373
374
375 /* get double from classfile data */
376 static double suck_double(classbuffer *cb)
377 {
378         double d;
379
380 #if !WORDS_BIGENDIAN 
381         u1 buffer[8];
382         u2 i;   
383
384 #if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
385         /*
386          * On little endian ARM processors when using FPA, word order
387          * of doubles is still big endian. So take that into account
388          * here. When using VFP, word order of doubles follows byte
389          * order. (michi 2005/07/24)
390          */
391         for (i = 0; i < 4; i++)
392                 buffer[3 - i] = suck_u1(cb);
393         for (i = 0; i < 4; i++)
394                 buffer[7 - i] = suck_u1(cb);
395 #else
396         for (i = 0; i < 8; i++)
397                 buffer[7 - i] = suck_u1(cb);
398 #endif /* defined(__ARM__) && ... */
399
400         memcpy((u1*) (&d), buffer, 8);
401 #else 
402         suck_nbytes((u1*) (&d), cb, 8);
403 #endif
404
405         if (sizeof(double) != 8) {
406                 *exceptionptr = new_internalerror("Incompatible double-format");
407
408                 /* XXX should we exit in such a case? */
409                 throw_exception_exit();
410         }
411         
412         return d;
413 }
414
415
416 /************************** function suck_init *********************************
417
418         called once at startup, sets the searchpath for the classfiles
419
420 *******************************************************************************/
421
422 void suck_init(char *classpath)
423 {
424         char           *start;
425         char           *end;
426         char           *filename;
427         s4              filenamelen;
428         bool            is_zip;
429         classpath_info *cpi;
430         classpath_info *lastcpi;
431         char           *cwd;
432         s4              cwdlen;
433
434         /* search for last classpath entry (only if there already some) */
435
436         if ((lastcpi = classpath_entries)) {
437                 while (lastcpi->next)
438                         lastcpi = lastcpi->next;
439         }
440
441         for (start = classpath; (*start) != '\0';) {
442
443                 /* search for ':' delimiter to get the end of the current entry */
444                 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
445
446                 if (start != end) {
447                         is_zip = false;
448                         filenamelen = end - start;
449
450                         if (filenamelen > 3) {
451                                 if (strncasecmp(end - 3, "zip", 3) == 0 ||
452                                         strncasecmp(end - 3, "jar", 3) == 0) {
453                                         is_zip = true;
454                                 }
455                         }
456
457                         /* save classpath entries as absolute pathnames */
458
459                         cwd = NULL;
460                         cwdlen = 0;
461
462                         if (*start != '/') {                      /* XXX fix me for win32 */
463                                 cwd = _Jv_getcwd();
464                                 cwdlen = strlen(cwd) + strlen("/");
465                         }
466
467                         /* allocate memory for filename and fill it */
468
469                         filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
470                                                         strlen("0"));
471
472                         if (cwd) {
473                                 strcpy(filename, cwd);
474                                 strcat(filename, "/");
475                                 strncat(filename, start, filenamelen);
476
477                                 /* add cwd length to file length */
478                                 filenamelen += cwdlen;
479
480                         } else {
481                                 strncpy(filename, start, filenamelen);
482                                 filename[filenamelen] = '\0';
483                         }
484
485                         cpi = NULL;
486
487                         if (is_zip) {
488 #if defined(USE_ZLIB)
489                                 unzFile uf = unzOpen(filename);
490
491                                 if (uf) {
492                                         cpi = NEW(classpath_info);
493                                         cpi->type = CLASSPATH_ARCHIVE;
494                                         cpi->uf = uf;
495                                         cpi->next = NULL;
496                                         cpi->path = filename;
497                                         cpi->pathlen = filenamelen;
498
499                                         /* SUN compatible -verbose:class output */
500
501                                         if (opt_verboseclass)
502                                                 printf("[Opened %s]\n", filename);
503                                 }
504
505 #else
506                                 throw_cacao_exception_exit(string_java_lang_InternalError,
507                                                                                    "zip/jar files not supported");
508 #endif
509                                 
510                         } else {
511                                 cpi = NEW(classpath_info);
512                                 cpi->type = CLASSPATH_PATH;
513                                 cpi->next = NULL;
514
515                                 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
516                                         filename[filenamelen] = '/';
517                                         filename[filenamelen + 1] = '\0';
518                                         filenamelen++;
519                                 }
520
521                                 cpi->path = filename;
522                                 cpi->pathlen = filenamelen;
523                         }
524
525                         /* attach current classpath entry */
526
527                         if (cpi) {
528                                 if (!classpath_entries)
529                                         classpath_entries = cpi;
530                                 else
531                                         lastcpi->next = cpi;
532
533                                 lastcpi = cpi;
534                         }
535                 }
536
537                 /* goto next classpath entry, skip ':' delimiter */
538
539                 if ((*end) == ':') {
540                         start = end + 1;
541
542                 } else {
543                         start = end;
544                 }
545         }
546 }
547
548
549 /* loader_load_all_classes *****************************************************
550
551    Loads all classes specified in the BOOTCLASSPATH.
552
553 *******************************************************************************/
554
555 void loader_load_all_classes(void)
556 {
557         classpath_info *cpi;
558         classinfo      *c;
559
560         for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
561 #if defined(USE_ZLIB)
562                 if (cpi->type == CLASSPATH_ARCHIVE) {
563                         cacao_entry_s *ce;
564                         unz_s *s;
565
566                         s = (unz_s *) cpi->uf;
567                         ce = s->cacao_dir_list;
568                                 
569                         while (ce) {
570                                 /* skip all entries in META-INF and .properties, .png files */
571
572                                 if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
573                                         !strstr(ce->name->text, ".properties") &&
574                                         !strstr(ce->name->text, ".png"))
575                                         c = load_class_bootstrap(ce->name);
576
577                                 ce = ce->next;
578                         }
579
580                 } else {
581 #endif
582 #if defined(USE_ZLIB)
583                 }
584 #endif
585         }
586 }
587
588
589 /* suck_start ******************************************************************
590
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.
595         
596 *******************************************************************************/
597
598 classbuffer *suck_start(classinfo *c)
599 {
600         classpath_info *cpi;
601         char           *filename;
602         s4             filenamelen;
603         char *path;
604         FILE *classfile;
605         bool found;
606         s4 len;
607         struct stat buffer;
608         classbuffer *cb;
609
610         /* initialize return value */
611
612         found = false;
613         cb = NULL;
614
615         filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
616         filename = MNEW(char, filenamelen);
617
618         utf_sprint(filename, c->name);
619         strcat(filename, ".class");
620
621         /* walk through all classpath entries */
622
623         for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
624 #if defined(USE_ZLIB)
625                 if (cpi->type == CLASSPATH_ARCHIVE) {
626
627 #if defined(USE_THREADS)
628                         /* enter a monitor on zip/jar archives */
629
630                         builtin_monitorenter((java_objectheader *) cpi);
631 #endif
632
633                         if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
634                                 unz_file_info file_info;
635
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);
640                                                 cb->class = c;
641                                                 cb->size  = file_info.uncompressed_size;
642                                                 cb->data  = MNEW(u1, cb->size);
643                                                 cb->pos   = cb->data - 1;
644                                                 cb->path  = cpi->path;
645
646                                                 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
647
648                                                 if (len != cb->size) {
649                                                         suck_stop(cb);
650                                                         log_text("Error while unzipping");
651
652                                                 } else {
653                                                         found = true;
654                                                 }
655
656                                         } else {
657                                                 log_text("Error while opening file in archive");
658                                         }
659
660                                 } else {
661                                         log_text("Error while retrieving fileinfo");
662                                 }
663                         }
664                         unzCloseCurrentFile(cpi->uf);
665
666 #if defined(USE_THREADS)
667                         /* leave the monitor */
668
669                         builtin_monitorexit((java_objectheader *) cpi);
670 #endif
671
672                 } else {
673 #endif /* defined(USE_ZLIB) */
674                         
675                         path = MNEW(char, cpi->pathlen + filenamelen);
676                         strcpy(path, cpi->path);
677                         strcat(path, filename);
678
679                         classfile = fopen(path, "r");
680
681                         if (classfile) {                                   /* file exists */
682                                 if (!stat(path, &buffer)) {            /* read classfile data */
683                                         cb = NEW(classbuffer);
684                                         cb->class = c;
685                                         cb->size  = buffer.st_size;
686                                         cb->data  = MNEW(u1, cb->size);
687                                         cb->pos   = cb->data - 1;
688                                         cb->path  = cpi->path;
689
690                                         /* read class data */
691                                         len = fread(cb->data, 1, cb->size, classfile);
692
693                                         if (len != buffer.st_size) {
694                                                 suck_stop(cb);
695 /*                                              if (ferror(classfile)) { */
696 /*                                              } */
697
698                                         } else {
699                                                 found = true;
700                                         }
701                                 }
702                         }
703
704                         MFREE(path, char, cpi->pathlen + filenamelen);
705 #if defined(USE_ZLIB)
706                 }
707 #endif
708         }
709
710         if (opt_verbose)
711                 if (!found) {
712                         dolog("Warning: Can not open class file '%s'", filename);
713
714                         if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
715                                 static int i = 0;
716                                 i++;
717                                 if (i == 3)
718                                         assert(0);
719                         }
720                 }
721
722         MFREE(filename, char, filenamelen);
723
724         return cb;
725 }
726
727
728 /************************** function suck_stop *********************************
729
730         frees memory for buffer with classfile data.
731         Caution: this function may only be called if buffer has been allocated
732                  by suck_start with reading a file
733         
734 *******************************************************************************/
735
736 void suck_stop(classbuffer *cb)
737 {
738         /* free memory */
739
740         MFREE(cb->data, u1, cb->size);
741         FREE(cb, classbuffer);
742 }
743
744
745 /******************************************************************************/
746 /******************* Some support functions ***********************************/
747 /******************************************************************************/
748
749 void fprintflags (FILE *fp, u2 f)
750 {
751    if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
752    if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
753    if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
754    if ( f & ACC_STATIC )       fprintf (fp," STATIC");
755    if ( f & ACC_FINAL )        fprintf (fp," FINAL");
756    if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
757    if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
758    if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
759    if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
760    if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
761    if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
762 }
763
764
765 /********** internal function: printflags  (only for debugging) ***************/
766
767 void printflags(u2 f)
768 {
769         fprintflags(stdout,f);
770 }
771
772
773 /********************** Function: skipattributebody ****************************
774
775         skips an attribute after the 16 bit reference to attribute_name has already
776         been read
777         
778 *******************************************************************************/
779
780 static bool skipattributebody(classbuffer *cb)
781 {
782         u4 len;
783
784         if (!check_classbuffer_size(cb, 4))
785                 return false;
786
787         len = suck_u4(cb);
788
789         if (!check_classbuffer_size(cb, len))
790                 return false;
791
792         skip_nbytes(cb, len);
793
794         return true;
795 }
796
797
798 /************************* Function: skipattributes ****************************
799
800         skips num attribute structures
801         
802 *******************************************************************************/
803
804 static bool skipattributes(classbuffer *cb, u4 num)
805 {
806         u4 i;
807         u4 len;
808
809         for (i = 0; i < num; i++) {
810                 if (!check_classbuffer_size(cb, 2 + 4))
811                         return false;
812
813                 suck_u2(cb);
814                 len = suck_u4(cb);
815
816                 if (!check_classbuffer_size(cb, len))
817                         return false;
818
819                 skip_nbytes(cb, len);
820         }
821
822         return true;
823 }
824
825
826 /* load_constantpool ***********************************************************
827
828    Loads the constantpool of a class, the entries are transformed into
829    a simpler format by resolving references (a detailed overview of
830    the compact structures can be found in global.h).
831
832 *******************************************************************************/
833
834 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
835 {
836
837         /* The following structures are used to save information which cannot be 
838            processed during the first pass. After the complete constantpool has 
839            been traversed the references can be resolved. 
840            (only in specific order)                                                */
841         
842         /* CONSTANT_Class entries */
843         typedef struct forward_class {
844                 struct forward_class *next;
845                 u2 thisindex;
846                 u2 name_index;
847         } forward_class;
848
849         /* CONSTANT_String */
850         typedef struct forward_string {
851                 struct forward_string *next;
852                 u2 thisindex;
853                 u2 string_index;
854         } forward_string;
855
856         /* CONSTANT_NameAndType */
857         typedef struct forward_nameandtype {
858                 struct forward_nameandtype *next;
859                 u2 thisindex;
860                 u2 name_index;
861                 u2 sig_index;
862         } forward_nameandtype;
863
864         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
865         typedef struct forward_fieldmethint {
866                 struct forward_fieldmethint *next;
867                 u2 thisindex;
868                 u1 tag;
869                 u2 class_index;
870                 u2 nameandtype_index;
871         } forward_fieldmethint;
872
873
874         classinfo *c;
875         u4 idx;
876
877         forward_class *forward_classes = NULL;
878         forward_string *forward_strings = NULL;
879         forward_nameandtype *forward_nameandtypes = NULL;
880         forward_fieldmethint *forward_fieldmethints = NULL;
881
882         forward_class *nfc;
883         forward_string *nfs;
884         forward_nameandtype *nfn;
885         forward_fieldmethint *nff;
886
887         u4 cpcount;
888         u1 *cptags;
889         voidptr *cpinfos;
890
891         c = cb->class;
892
893         /* number of entries in the constant_pool table plus one */
894         if (!check_classbuffer_size(cb, 2))
895                 return false;
896
897         cpcount = c->cpcount = suck_u2(cb);
898
899         /* allocate memory */
900         cptags  = c->cptags  = MNEW(u1, cpcount);
901         cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
902
903         if (cpcount < 1) {
904                 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
905                 return false;
906         }
907         
908 #if defined(STATISTICS)
909         if (opt_stat)
910                 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
911 #endif
912         
913         /* initialize constantpool */
914         for (idx = 0; idx < cpcount; idx++) {
915                 cptags[idx] = CONSTANT_UNUSED;
916                 cpinfos[idx] = NULL;
917         }
918
919                         
920         /******* first pass *******/
921         /* entries which cannot be resolved now are written into 
922            temporary structures and traversed again later        */
923                    
924         idx = 1;
925         while (idx < cpcount) {
926                 u4 t;
927
928                 /* get constant type */
929                 if (!check_classbuffer_size(cb, 1))
930                         return false;
931
932                 t = suck_u1(cb);
933
934                 switch (t) {
935                 case CONSTANT_Class:
936                         nfc = DNEW(forward_class);
937
938                         nfc->next = forward_classes;
939                         forward_classes = nfc;
940
941                         nfc->thisindex = idx;
942                         /* reference to CONSTANT_NameAndType */
943                         if (!check_classbuffer_size(cb, 2))
944                                 return false;
945
946                         nfc->name_index = suck_u2(cb);
947
948                         idx++;
949                         break;
950                         
951                 case CONSTANT_String:
952                         nfs = DNEW(forward_string);
953                                 
954                         nfs->next = forward_strings;
955                         forward_strings = nfs;
956                                 
957                         nfs->thisindex = idx;
958
959                         /* reference to CONSTANT_Utf8_info with string characters */
960                         if (!check_classbuffer_size(cb, 2))
961                                 return false;
962
963                         nfs->string_index = suck_u2(cb);
964                                 
965                         idx++;
966                         break;
967
968                 case CONSTANT_NameAndType:
969                         nfn = DNEW(forward_nameandtype);
970                                 
971                         nfn->next = forward_nameandtypes;
972                         forward_nameandtypes = nfn;
973                                 
974                         nfn->thisindex = idx;
975
976                         if (!check_classbuffer_size(cb, 2 + 2))
977                                 return false;
978
979                         /* reference to CONSTANT_Utf8_info containing simple name */
980                         nfn->name_index = suck_u2(cb);
981
982                         /* reference to CONSTANT_Utf8_info containing field or method
983                            descriptor */
984                         nfn->sig_index = suck_u2(cb);
985                                 
986                         idx++;
987                         break;
988
989                 case CONSTANT_Fieldref:
990                 case CONSTANT_Methodref:
991                 case CONSTANT_InterfaceMethodref:
992                         nff = DNEW(forward_fieldmethint);
993                         
994                         nff->next = forward_fieldmethints;
995                         forward_fieldmethints = nff;
996
997                         nff->thisindex = idx;
998                         /* constant type */
999                         nff->tag = t;
1000
1001                         if (!check_classbuffer_size(cb, 2 + 2))
1002                                 return false;
1003
1004                         /* class or interface type that contains the declaration of the
1005                            field or method */
1006                         nff->class_index = suck_u2(cb);
1007
1008                         /* name and descriptor of the field or method */
1009                         nff->nameandtype_index = suck_u2(cb);
1010
1011                         idx++;
1012                         break;
1013                                 
1014                 case CONSTANT_Integer: {
1015                         constant_integer *ci = NEW(constant_integer);
1016
1017 #if defined(STATISTICS)
1018                         if (opt_stat)
1019                                 count_const_pool_len += sizeof(constant_integer);
1020 #endif
1021
1022                         if (!check_classbuffer_size(cb, 4))
1023                                 return false;
1024
1025                         ci->value = suck_s4(cb);
1026                         cptags[idx] = CONSTANT_Integer;
1027                         cpinfos[idx] = ci;
1028
1029                         idx++;
1030                         break;
1031                 }
1032                                 
1033                 case CONSTANT_Float: {
1034                         constant_float *cf = NEW(constant_float);
1035
1036 #if defined(STATISTICS)
1037                         if (opt_stat)
1038                                 count_const_pool_len += sizeof(constant_float);
1039 #endif
1040
1041                         if (!check_classbuffer_size(cb, 4))
1042                                 return false;
1043
1044                         cf->value = suck_float(cb);
1045                         cptags[idx] = CONSTANT_Float;
1046                         cpinfos[idx] = cf;
1047
1048                         idx++;
1049                         break;
1050                 }
1051                                 
1052                 case CONSTANT_Long: {
1053                         constant_long *cl = NEW(constant_long);
1054                                         
1055 #if defined(STATISTICS)
1056                         if (opt_stat)
1057                                 count_const_pool_len += sizeof(constant_long);
1058 #endif
1059
1060                         if (!check_classbuffer_size(cb, 8))
1061                                 return false;
1062
1063                         cl->value = suck_s8(cb);
1064                         cptags[idx] = CONSTANT_Long;
1065                         cpinfos[idx] = cl;
1066                         idx += 2;
1067                         if (idx > cpcount) {
1068                                 *exceptionptr =
1069                                         new_classformaterror(c, "Invalid constant pool entry");
1070                                 return false;
1071                         }
1072                         break;
1073                 }
1074                         
1075                 case CONSTANT_Double: {
1076                         constant_double *cd = NEW(constant_double);
1077                                 
1078 #if defined(STATISTICS)
1079                         if (opt_stat)
1080                                 count_const_pool_len += sizeof(constant_double);
1081 #endif
1082
1083                         if (!check_classbuffer_size(cb, 8))
1084                                 return false;
1085
1086                         cd->value = suck_double(cb);
1087                         cptags[idx] = CONSTANT_Double;
1088                         cpinfos[idx] = cd;
1089                         idx += 2;
1090                         if (idx > cpcount) {
1091                                 *exceptionptr =
1092                                         new_classformaterror(c, "Invalid constant pool entry");
1093                                 return false;
1094                         }
1095                         break;
1096                 }
1097                                 
1098                 case CONSTANT_Utf8: { 
1099                         u4 length;
1100
1101                         /* number of bytes in the bytes array (not string-length) */
1102                         if (!check_classbuffer_size(cb, 2))
1103                                 return false;
1104
1105                         length = suck_u2(cb);
1106                         cptags[idx] = CONSTANT_Utf8;
1107
1108                         /* validate the string */
1109                         if (!check_classbuffer_size(cb, length))
1110                                 return false;
1111
1112                         if (opt_verify &&
1113                                 !is_valid_utf((char *) (cb->pos + 1),
1114                                                           (char *) (cb->pos + 1 + length))) {
1115                                 *exceptionptr = new_classformaterror(c,"Invalid UTF-8 string");
1116                                 return false;
1117                         }
1118                         /* insert utf-string into the utf-symboltable */
1119                         cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1120
1121                         /* skip bytes of the string (buffer size check above) */
1122                         skip_nbytes(cb, length);
1123                         idx++;
1124                         break;
1125                 }
1126                                                                                 
1127                 default:
1128                         *exceptionptr =
1129                                 new_classformaterror(c, "Illegal constant pool type");
1130                         return false;
1131                 }  /* end switch */
1132         } /* end while */
1133
1134
1135         /* resolve entries in temporary structures */
1136
1137         while (forward_classes) {
1138                 utf *name =
1139                         class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1140                 if (!name)
1141                         return false;
1142
1143                 if (opt_verify && !is_valid_name_utf(name)) {
1144                         *exceptionptr = 
1145                                 new_classformaterror(c, "Class reference with invalid name");
1146                         return false;
1147                 }
1148
1149                 /* add all class references to the descriptor_pool */
1150
1151                 if (!descriptor_pool_add_class(descpool, name))
1152                         return false;
1153
1154                 cptags[forward_classes->thisindex] = CONSTANT_Class;
1155
1156                 if (opt_eager) {
1157                         classinfo *tc;
1158
1159                         if (!(tc = load_class_bootstrap(name)))
1160                                 return false;
1161
1162                         /* link the class later, because we cannot link the class currently
1163                            loading */
1164                         list_addfirst(&unlinkedclasses, tc);
1165                 }
1166
1167                 /* the classref is created later */
1168                 cpinfos[forward_classes->thisindex] = name;
1169
1170                 nfc = forward_classes;
1171                 forward_classes = forward_classes->next;
1172         }
1173
1174         while (forward_strings) {
1175                 utf *text =
1176                         class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1177                 if (!text)
1178                         return false;
1179
1180                 /* resolve utf-string */
1181                 cptags[forward_strings->thisindex] = CONSTANT_String;
1182                 cpinfos[forward_strings->thisindex] = text;
1183                 
1184                 nfs = forward_strings;
1185                 forward_strings = forward_strings->next;
1186         }
1187
1188         while (forward_nameandtypes) {
1189                 constant_nameandtype *cn = NEW(constant_nameandtype);   
1190
1191 #if defined(STATISTICS)
1192                 if (opt_stat)
1193                         count_const_pool_len += sizeof(constant_nameandtype);
1194 #endif
1195
1196                 /* resolve simple name and descriptor */
1197                 cn->name = class_getconstant(c,
1198                                                                          forward_nameandtypes->name_index,
1199                                                                          CONSTANT_Utf8);
1200                 if (!cn->name)
1201                         return false;
1202
1203                 cn->descriptor = class_getconstant(c,
1204                                                                                    forward_nameandtypes->sig_index,
1205                                                                                    CONSTANT_Utf8);
1206                 if (!cn->descriptor)
1207                         return false;
1208
1209                 if (opt_verify) {
1210                         /* check name */
1211                         if (!is_valid_name_utf(cn->name)) {
1212                                 *exceptionptr =
1213                                         new_classformaterror(c,
1214                                                                                  "Illegal Field name \"%s\"",
1215                                                                                  cn->name->text);
1216
1217                                 return false;
1218                         }
1219
1220                         /* disallow referencing <clinit> among others */
1221                         if (cn->name->text[0] == '<' && cn->name != utf_init) {
1222                                 *exceptionptr =
1223                                         new_classformaterror(c,"Illegal reference to special method");
1224                                 return false;
1225                         }
1226                 }
1227
1228                 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1229                 cpinfos[forward_nameandtypes->thisindex] = cn;
1230
1231                 nfn = forward_nameandtypes;
1232                 forward_nameandtypes = forward_nameandtypes->next;
1233         }
1234
1235         while (forward_fieldmethints) {
1236                 constant_nameandtype *nat;
1237                 constant_FMIref *fmi = NEW(constant_FMIref);
1238
1239 #if defined(STATISTICS)
1240                 if (opt_stat)
1241                         count_const_pool_len += sizeof(constant_FMIref);
1242 #endif
1243                 /* resolve simple name and descriptor */
1244
1245                 nat = class_getconstant(c,
1246                                                                 forward_fieldmethints->nameandtype_index,
1247                                                                 CONSTANT_NameAndType);
1248                 if (!nat)
1249                         return false;
1250
1251                 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
1252
1253                 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
1254                         return false;
1255
1256                 /* the classref is created later */
1257
1258                 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
1259                 fmi->name = nat->name;
1260                 fmi->descriptor = nat->descriptor;
1261
1262                 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1263                 cpinfos[forward_fieldmethints->thisindex] = fmi;
1264         
1265                 nff = forward_fieldmethints;
1266                 forward_fieldmethints = forward_fieldmethints->next;
1267         }
1268
1269         /* everything was ok */
1270
1271         return true;
1272 }
1273
1274
1275 /* load_field ******************************************************************
1276
1277    Load everything about a class field from the class file and fill a
1278    'fieldinfo' structure. For static fields, space in the data segment
1279    is allocated.
1280
1281 *******************************************************************************/
1282
1283 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
1284
1285 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
1286 {
1287         classinfo *c;
1288         u4 attrnum, i;
1289         u4 jtype;
1290         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
1291         utf *u;
1292
1293         c = cb->class;
1294
1295         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1296                 return false;
1297
1298         f->flags = suck_u2(cb);
1299
1300         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1301                 return false;
1302
1303         f->name = u;
1304
1305         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1306                 return false;
1307
1308         f->descriptor = u;
1309         f->parseddesc = NULL;
1310
1311         if (!descriptor_pool_add(descpool, u, NULL))
1312                 return false;
1313
1314         /* descriptor_pool_add accepts method descriptors, so we have to check */
1315         /* against them here before the call of desc_to_type below.            */
1316         if (u->text[0] == '(') {
1317                 *exceptionptr = new_classformaterror(c,"Method descriptor used for field");
1318                 return false;
1319         }
1320
1321         if (opt_verify) {
1322                 /* check name */
1323                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1324                         *exceptionptr = new_classformaterror(c,
1325                                                                                                  "Illegal Field name \"%s\"",
1326                                                                                                  f->name->text);
1327                         return false;
1328                 }
1329
1330                 /* check flag consistency */
1331                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1332
1333                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1334                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1335                         *exceptionptr =
1336                                 new_classformaterror(c,
1337                                                                          "Illegal field modifiers: 0x%X",
1338                                                                          f->flags);
1339                         return false;
1340                 }
1341
1342                 if (c->flags & ACC_INTERFACE) {
1343                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1344                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1345                                 f->flags & ACC_TRANSIENT) {
1346                                 *exceptionptr =
1347                                         new_classformaterror(c,
1348                                                                                  "Illegal field modifiers: 0x%X",
1349                                                                                  f->flags);
1350                                 return false;
1351                         }
1352                 }
1353         }
1354                 
1355         f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
1356         f->offset = 0;                             /* offset from start of object */
1357         f->class = c;
1358         f->xta = NULL;
1359         
1360         switch (f->type) {
1361         case TYPE_INT:     f->value.i = 0; break;
1362         case TYPE_FLOAT:   f->value.f = 0.0; break;
1363         case TYPE_DOUBLE:  f->value.d = 0.0; break;
1364         case TYPE_ADDRESS: f->value.a = NULL; break;
1365         case TYPE_LONG:
1366 #if U8_AVAILABLE
1367                 f->value.l = 0; break;
1368 #else
1369                 f->value.l.low = 0; f->value.l.high = 0; break;
1370 #endif
1371         }
1372
1373         /* read attributes */
1374         if (!check_classbuffer_size(cb, 2))
1375                 return false;
1376
1377         attrnum = suck_u2(cb);
1378         for (i = 0; i < attrnum; i++) {
1379                 if (!check_classbuffer_size(cb, 2))
1380                         return false;
1381
1382                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1383                         return false;
1384
1385                 if (u == utf_ConstantValue) {
1386                         if (!check_classbuffer_size(cb, 4 + 2))
1387                                 return false;
1388
1389                         /* check attribute length */
1390                         if (suck_u4(cb) != 2) {
1391                                 *exceptionptr =
1392                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1393                                 return false;
1394                         }
1395                         
1396                         /* constant value attribute */
1397                         if (pindex != field_load_NOVALUE) {
1398                                 *exceptionptr =
1399                                         new_classformaterror(c,
1400                                                                                  "Multiple ConstantValue attributes");
1401                                 return false;
1402                         }
1403                         
1404                         /* index of value in constantpool */            
1405                         pindex = suck_u2(cb);
1406                 
1407                         /* initialize field with value from constantpool */             
1408                         switch (jtype) {
1409                         case TYPE_INT: {
1410                                 constant_integer *ci; 
1411
1412                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1413                                         return false;
1414
1415                                 f->value.i = ci->value;
1416                         }
1417                         break;
1418                                         
1419                         case TYPE_LONG: {
1420                                 constant_long *cl; 
1421
1422                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1423                                         return false;
1424
1425                                 f->value.l = cl->value;
1426                         }
1427                         break;
1428
1429                         case TYPE_FLOAT: {
1430                                 constant_float *cf;
1431
1432                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1433                                         return false;
1434
1435                                 f->value.f = cf->value;
1436                         }
1437                         break;
1438                                                                                         
1439                         case TYPE_DOUBLE: {
1440                                 constant_double *cd;
1441
1442                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1443                                         return false;
1444
1445                                 f->value.d = cd->value;
1446                         }
1447                         break;
1448                                                 
1449                         case TYPE_ADDRESS:
1450                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1451                                         return false;
1452
1453                                 /* create javastring from compressed utf8-string */
1454                                 f->value.a = literalstring_new(u);
1455                                 break;
1456         
1457                         default: 
1458                                 log_text("Invalid Constant - Type");
1459                         }
1460
1461                 } else {
1462                         /* unknown attribute */
1463                         if (!skipattributebody(cb))
1464                                 return false;
1465                 }
1466         }
1467
1468         /* everything was ok */
1469
1470         return true;
1471 }
1472
1473
1474 /* load_method *****************************************************************
1475
1476    Loads a method from the class file and fills an existing
1477    'methodinfo' structure. For native methods, the function pointer
1478    field is set to the real function pointer, for JavaVM methods a
1479    pointer to the compiler is used preliminarily.
1480         
1481 *******************************************************************************/
1482
1483 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1484 {
1485         classinfo *c;
1486         int argcount;
1487         s4 i, j;
1488         u4 attrnum;
1489         u4 codeattrnum;
1490         utf *u;
1491
1492         c = cb->class;
1493
1494 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1495         initObjectLock(&m->header);
1496 #endif
1497
1498 #ifdef STATISTICS
1499         if (opt_stat)
1500                 count_all_methods++;
1501 #endif
1502
1503         m->thrownexceptionscount = 0;
1504         m->linenumbercount = 0;
1505         m->linenumbers = 0;
1506         m->class = c;
1507         m->nativelyoverloaded = false;
1508         
1509         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1510                 return false;
1511
1512         m->flags = suck_u2(cb);
1513
1514         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1515                 return false;
1516
1517         m->name = u;
1518
1519         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1520                 return false;
1521
1522         m->descriptor = u;
1523         m->parseddesc = NULL;
1524
1525         if (!descriptor_pool_add(descpool, u, &argcount))
1526                 return false;
1527
1528         if (opt_verify) {
1529                 if (!is_valid_name_utf(m->name)) {
1530                         *exceptionptr = new_classformaterror(c,"Method with invalid name");
1531                         return false;
1532                 }
1533
1534                 if (m->name->text[0] == '<' &&
1535                         m->name != utf_init && m->name != utf_clinit) {
1536                         *exceptionptr = new_classformaterror(c,"Method with invalid special name");
1537                         return false;
1538                 }
1539         }
1540         
1541         if (!(m->flags & ACC_STATIC))
1542                 argcount++; /* count the 'this' argument */
1543
1544         if (opt_verify) {
1545                 if (argcount > 255) {
1546                         *exceptionptr =
1547                                 new_classformaterror(c, "Too many arguments in signature");
1548                         return false;
1549                 }
1550
1551                 /* check flag consistency */
1552                 if (m->name != utf_clinit) {
1553                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1554
1555                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1556                                 *exceptionptr =
1557                                         new_classformaterror(c,
1558                                                                                  "Illegal method modifiers: 0x%X",
1559                                                                                  m->flags);
1560                                 return false;
1561                         }
1562
1563                         if (m->flags & ACC_ABSTRACT) {
1564                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1565                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1566                                         *exceptionptr =
1567                                                 new_classformaterror(c,
1568                                                                                          "Illegal method modifiers: 0x%X",
1569                                                                                          m->flags);
1570                                         return false;
1571                                 }
1572                         }
1573
1574                         if (c->flags & ACC_INTERFACE) {
1575                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1576                                         *exceptionptr =
1577                                                 new_classformaterror(c,
1578                                                                                          "Illegal method modifiers: 0x%X",
1579                                                                                          m->flags);
1580                                         return false;
1581                                 }
1582                         }
1583
1584                         if (m->name == utf_init) {
1585                                 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1586                                                                 ACC_NATIVE | ACC_ABSTRACT)) {
1587                                         *exceptionptr = new_classformaterror(c,
1588                                                         "Instance initialization method has invalid flags set");
1589                                         return false;
1590                                 }
1591                         }
1592                 }
1593         }
1594                 
1595         m->jcode = NULL;
1596         m->basicblockcount = 0;
1597         m->basicblocks = NULL;
1598         m->basicblockindex = NULL;
1599         m->instructioncount = 0;
1600         m->instructions = NULL;
1601         m->stackcount = 0;
1602         m->stack = NULL;
1603         m->exceptiontable = NULL;
1604         m->stubroutine = NULL;
1605         m->mcode = NULL;
1606         m->entrypoint = NULL;
1607         m->methodUsed = NOTUSED;    
1608         m->monoPoly = MONO;    
1609         m->subRedefs = 0;
1610         m->subRedefsUsed = 0;
1611
1612         m->xta = NULL;
1613
1614         if (!check_classbuffer_size(cb, 2))
1615                 return false;
1616         
1617         attrnum = suck_u2(cb);
1618         for (i = 0; i < attrnum; i++) {
1619                 utf *aname;
1620
1621                 if (!check_classbuffer_size(cb, 2))
1622                         return false;
1623
1624                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1625                         return false;
1626
1627                 if (aname == utf_Code) {
1628                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1629                                         *exceptionptr =
1630                                                 new_classformaterror(c,
1631                                                                                          "Code attribute in native or abstract methods");
1632
1633                                         return false;
1634                         }
1635                         
1636                         if (m->jcode) {
1637                                 *exceptionptr =
1638                                         new_classformaterror(c, "Multiple Code attributes");
1639
1640                                 return false;
1641                         }
1642
1643                         if (!check_classbuffer_size(cb, 4 + 2 + 2))
1644                                 return false;
1645
1646                         suck_u4(cb);
1647                         m->maxstack = suck_u2(cb);
1648                         m->maxlocals = suck_u2(cb);
1649
1650                         if (m->maxlocals < argcount) {
1651                                 *exceptionptr =
1652                                         new_classformaterror(c, "Arguments can't fit into locals");
1653
1654                                 return false;
1655                         }
1656                         
1657                         if (!check_classbuffer_size(cb, 4))
1658                                 return false;
1659
1660                         m->jcodelength = suck_u4(cb);
1661
1662                         if (m->jcodelength == 0) {
1663                                 *exceptionptr =
1664                                         new_classformaterror(c, "Code of a method has length 0");
1665
1666                                 return false;
1667                         }
1668                         
1669                         if (m->jcodelength > 65535) {
1670                                 *exceptionptr =
1671                                         new_classformaterror(c,
1672                                                                                  "Code of a method longer than 65535 bytes");
1673
1674                                 return false;
1675                         }
1676
1677                         if (!check_classbuffer_size(cb, m->jcodelength))
1678                                 return false;
1679
1680                         m->jcode = MNEW(u1, m->jcodelength);
1681                         suck_nbytes(m->jcode, cb, m->jcodelength);
1682
1683                         if (!check_classbuffer_size(cb, 2))
1684                                 return false;
1685
1686                         m->exceptiontablelength = suck_u2(cb);
1687                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1688                                 return false;
1689
1690                         m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1691
1692 #if defined(STATISTICS)
1693                         if (opt_stat) {
1694                                 count_vmcode_len += m->jcodelength + 18;
1695                                 count_extable_len +=
1696                                         m->exceptiontablelength * sizeof(exceptiontable);
1697                         }
1698 #endif
1699
1700                         for (j = 0; j < m->exceptiontablelength; j++) {
1701                                 u4 idx;
1702                                 m->exceptiontable[j].startpc = suck_u2(cb);
1703                                 m->exceptiontable[j].endpc = suck_u2(cb);
1704                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1705
1706                                 idx = suck_u2(cb);
1707                                 if (!idx) {
1708                                         m->exceptiontable[j].catchtype.any = NULL;
1709
1710                                 } else {
1711                                         /* the classref is created later */
1712                                         if (!(m->exceptiontable[j].catchtype.any =
1713                                                   (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1714                                                 return false;
1715                                 }
1716                         }
1717
1718                         if (!check_classbuffer_size(cb, 2))
1719                                 return false;
1720
1721                         codeattrnum = suck_u2(cb);
1722
1723                         for (; codeattrnum > 0; codeattrnum--) {
1724                                 utf *caname;
1725
1726                                 if (!check_classbuffer_size(cb, 2))
1727                                         return false;
1728
1729                                 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1730                                         return false;
1731
1732                                 if (caname == utf_LineNumberTable) {
1733                                         u2 lncid;
1734
1735                                         if (!check_classbuffer_size(cb, 4 + 2))
1736                                                 return false;
1737
1738                                         suck_u4(cb);
1739                                         m->linenumbercount = suck_u2(cb);
1740
1741                                         if (!check_classbuffer_size(cb,
1742                                                                                                 (2 + 2) * m->linenumbercount))
1743                                                 return false;
1744
1745                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1746                                         
1747                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1748                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1749                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1750                                         }
1751                                         codeattrnum--;
1752
1753                                         if (!skipattributes(cb, codeattrnum))
1754                                                 return false;
1755                                         
1756                                         break;
1757
1758                                 } else {
1759                                         if (!skipattributebody(cb))
1760                                                 return false;
1761                                 }
1762                         }
1763
1764                 } else if (aname == utf_Exceptions) {
1765                         s4 j;
1766
1767                         if (m->thrownexceptions) {
1768                                 *exceptionptr =
1769                                         new_classformaterror(c, "Multiple Exceptions attributes");
1770                                 return false;
1771                         }
1772
1773                         if (!check_classbuffer_size(cb, 4 + 2))
1774                                 return false;
1775
1776                         suck_u4(cb); /* length */
1777                         m->thrownexceptionscount = suck_u2(cb);
1778
1779                         if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1780                                 return false;
1781
1782                         m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1783
1784                         for (j = 0; j < m->thrownexceptionscount; j++) {
1785                                 /* the classref is created later */
1786                                 if (!((m->thrownexceptions)[j].any =
1787                                           (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1788                                         return false;
1789                         }
1790                                 
1791                 } else {
1792                         if (!skipattributebody(cb))
1793                                 return false;
1794                 }
1795         }
1796
1797         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1798                 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1799
1800                 return false;
1801         }
1802
1803         /* everything was ok */
1804
1805         return true;
1806 }
1807
1808
1809 /* load_attribute **************************************************************
1810
1811    Read attributes from classfile.
1812         
1813 *******************************************************************************/
1814
1815 static bool load_attributes(classbuffer *cb, u4 num)
1816 {
1817         classinfo *c;
1818         utf       *aname;
1819         u4 i, j;
1820
1821         c = cb->class;
1822
1823         for (i = 0; i < num; i++) {
1824                 /* retrieve attribute name */
1825                 if (!check_classbuffer_size(cb, 2))
1826                         return false;
1827
1828                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1829                         return false;
1830
1831                 if (aname == utf_InnerClasses) {
1832                         /* innerclasses attribute */
1833                         if (c->innerclass) {
1834                                 *exceptionptr =
1835                                         new_classformaterror(c, "Multiple InnerClasses attributes");
1836                                 return false;
1837                         }
1838                                 
1839                         if (!check_classbuffer_size(cb, 4 + 2))
1840                                 return false;
1841
1842                         /* skip attribute length */
1843                         suck_u4(cb);
1844
1845                         /* number of records */
1846                         c->innerclasscount = suck_u2(cb);
1847
1848                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1849                                 return false;
1850
1851                         /* allocate memory for innerclass structure */
1852                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1853
1854                         for (j = 0; j < c->innerclasscount; j++) {
1855                                 /* The innerclass structure contains a class with an encoded
1856                                    name, its defining scope, its simple name and a bitmask of
1857                                    the access flags. If an inner class is not a member, its
1858                                    outer_class is NULL, if a class is anonymous, its name is
1859                                    NULL. */
1860                                                                 
1861                                 innerclassinfo *info = c->innerclass + j;
1862
1863                                 info->inner_class.ref =
1864                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1865                                 info->outer_class.ref =
1866                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1867                                 info->name =
1868                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1869                                 info->flags = suck_u2(cb);
1870                         }
1871
1872                 } else if (aname == utf_SourceFile) {
1873                         if (!check_classbuffer_size(cb, 4 + 2))
1874                                 return false;
1875
1876                         if (suck_u4(cb) != 2) {
1877                                 *exceptionptr =
1878                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1879                                 return false;
1880                         }
1881
1882                         if (c->sourcefile) {
1883                                 *exceptionptr =
1884                                         new_classformaterror(c, "Multiple SourceFile attributes");
1885                                 return false;
1886                         }
1887
1888                         if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1889                                 return false;
1890
1891                 } else {
1892                         /* unknown attribute */
1893                         if (!skipattributebody(cb))
1894                                 return false;
1895                 }
1896         }
1897
1898         return true;
1899 }
1900
1901
1902 /* load_class_from_sysloader ***************************************************
1903
1904    Load the class with the given name using the system class loader
1905
1906    IN:
1907        name.............the classname
1908
1909    RETURN VALUE:
1910        the loaded class, or
1911            NULL if an exception has been thrown
1912
1913 *******************************************************************************/
1914
1915 classinfo *load_class_from_sysloader(utf *name)
1916 {
1917         methodinfo        *m;
1918         java_objectheader *cl;
1919         classinfo         *r;
1920
1921 #ifdef LOADER_VERBOSE
1922         char logtext[MAXLOGTEXT];
1923         LOADER_INDENT(logtext);
1924         sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1925         utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1926         log_text(logtext);
1927 #endif
1928
1929         LOADER_ASSERT(class_java_lang_Object);
1930         LOADER_ASSERT(class_java_lang_ClassLoader);
1931         LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1932         
1933         m = class_resolveclassmethod(class_java_lang_ClassLoader,
1934                                                                  utf_getSystemClassLoader,
1935                                                                  utf_void__java_lang_ClassLoader,
1936                                                                  class_java_lang_Object,
1937                                                                  false);
1938
1939         if (!m)
1940                 return false;
1941
1942         cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1943         if (!cl)
1944                 return false;
1945
1946         LOADER_INC();
1947         r = load_class_from_classloader(name, cl);
1948         LOADER_DEC();
1949
1950         return r;
1951 }
1952
1953 /* load_class_from_classloader *************************************************
1954
1955    Load the class with the given name using the given user-defined class loader.
1956
1957    IN:
1958        name.............the classname
1959            cl...............user-defined class loader
1960            
1961    RETURN VALUE:
1962        the loaded class, or
1963            NULL if an exception has been thrown
1964
1965 *******************************************************************************/
1966
1967 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1968 {
1969         classinfo *r;
1970
1971 #ifdef LOADER_VERBOSE
1972         char logtext[MAXLOGTEXT];
1973         LOADER_INDENT(logtext);
1974         strcat(logtext,"load_class_from_classloader(");
1975         utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1976         if (!cl) strcat(logtext,"<bootstrap>");
1977         else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1978         else strcat(logtext,"<unknown class>");
1979         strcat(logtext,")");
1980         log_text(logtext);
1981 #endif
1982
1983         LOADER_ASSERT(name);
1984
1985         /* lookup if this class has already been loaded */
1986
1987         r = classcache_lookup(cl, name);
1988
1989 #ifdef LOADER_VERBOSE
1990         if (r)
1991                 dolog("        cached -> %p",(void*)r);
1992 #endif
1993
1994         if (r)
1995                 return r;
1996
1997         /* if other class loader than bootstrap, call it */
1998
1999         if (cl) {
2000                 methodinfo *lc;
2001                 char       *text;
2002                 s4          namelen;
2003
2004                 text = name->text;
2005                 namelen = name->blength;
2006
2007                 /* handle array classes */
2008                 if (text[0] == '[') {
2009                         classinfo *comp;
2010                         utf       *u;
2011
2012                         switch (text[1]) {
2013                         case 'L':
2014                                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2015                                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2016                                         *exceptionptr = new_noclassdeffounderror(name);
2017                                         return false;
2018                                 }
2019
2020                                 u = utf_new(text + 2, namelen - 3);
2021
2022                                 if (!(comp = load_class_from_classloader(u, cl)))
2023                                         return false;
2024
2025                                 /* create the array class */
2026                                 return class_array_of(comp, false);
2027
2028                         case '[':
2029                                 /* load the component class */
2030
2031                                 u = utf_new(text + 1, namelen - 1);
2032
2033                                 if (!(comp = load_class_from_classloader(u, cl)))
2034                                         return false;
2035
2036                                 /* create the array class */
2037                                 return class_array_of(comp, false);
2038
2039                         default:
2040                                 /* primitive array classes are loaded by the bootstrap loader */
2041                                 return load_class_bootstrap(name);
2042                         }
2043                 }
2044                 
2045                 LOADER_ASSERT(class_java_lang_Object);
2046
2047                 lc = class_resolveclassmethod(cl->vftbl->class,
2048                                                                           utf_loadClass,
2049                                                                           utf_java_lang_String__java_lang_Class,
2050                                                                           class_java_lang_Object,
2051                                                                           true);
2052
2053                 if (!lc)
2054                         return false; /* exception */
2055
2056                 LOADER_INC();
2057                 r = (classinfo *) asm_calljavafunction(lc,
2058                                                                                            cl,
2059                                                                                            javastring_new_slash_to_dot(name),
2060                                                                                            NULL, NULL);
2061                 LOADER_DEC();
2062
2063                 if (r) {
2064                         /* Store this class in the loaded class cache. If another
2065                            class with the same (initloader,name) pair has been
2066                            stored earlier it will be returned by classcache_store
2067                            In this case classcache_store may not free the class
2068                            because it has already been exposed to Java code which
2069                            may have kept references to that class. */
2070
2071                     classinfo *c = classcache_store(cl,r,false);
2072
2073                         if (c == NULL) {
2074                                 /* exception, free the loaded class */
2075                                 r->loaded = false;
2076                                 class_free(r);
2077                         }
2078
2079                         r = c;
2080                 }
2081                 else {
2082                         /* loadClass has thrown an exception */
2083                         /* we must convert ClassNotFoundException into NoClassDefFoundException */
2084                         /* XXX maybe we should have a flag that avoids this conversion */
2085                         /* for calling load_class_from_classloader from Class.forName  */
2086                         /* Currently we do a double conversion in these cases          */
2087                         classnotfoundexception_to_noclassdeffounderror();
2088                 }
2089
2090                 /* SUN compatible -verbose:class output */
2091
2092                 if (opt_verboseclass && (r != NULL) && (r->classloader == cl)) {
2093                         printf("[Loaded ");
2094                         utf_display_classname(name);
2095                         printf("]\n");
2096                 }
2097
2098                 return r;
2099         } 
2100
2101         LOADER_INC();
2102         r = load_class_bootstrap(name);
2103         LOADER_DEC();
2104
2105         return r;
2106 }
2107
2108
2109 /* load_class_bootstrap ********************************************************
2110         
2111    Load the class with the given name using the bootstrap class loader.
2112
2113    IN:
2114        name.............the classname
2115
2116    RETURN VALUE:
2117        loaded classinfo, or
2118            NULL if an exception has been thrown
2119
2120    SYNCHRONIZATION:
2121        load_class_bootstrap is synchronized. It can be treated as an
2122            atomic operation.
2123
2124 *******************************************************************************/
2125
2126 classinfo *load_class_bootstrap(utf *name)
2127 {
2128         classbuffer *cb;
2129         classinfo   *c;
2130         classinfo   *r;
2131 #ifdef LOADER_VERBOSE
2132         char logtext[MAXLOGTEXT];
2133 #endif
2134
2135         /* for debugging */
2136
2137         LOADER_ASSERT(name);
2138         LOADER_INC();
2139
2140         /* lookup if this class has already been loaded */
2141
2142         if ((r = classcache_lookup(NULL, name)))
2143                 goto success;
2144
2145 #ifdef LOADER_VERBOSE
2146         LOADER_INDENT(logtext);
2147         strcat(logtext,"load_class_bootstrap(");
2148         utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
2149         log_text(logtext);
2150 #endif
2151
2152         /* create the classinfo */
2153
2154         c = class_create_classinfo(name);
2155         
2156         /* handle array classes */
2157
2158         if (name->text[0] == '[') {
2159                 c = load_newly_created_array(c, NULL);
2160                 if (c == NULL)
2161                         goto return_exception;
2162                 LOADER_ASSERT(c->loaded);
2163                 r = c;
2164                 goto success;
2165         }
2166
2167 #if defined(STATISTICS)
2168         /* measure time */
2169
2170         if (getcompilingtime)
2171                 compilingtime_stop();
2172
2173         if (getloadingtime)
2174                 loadingtime_start();
2175 #endif
2176
2177         /* load classdata, throw exception on error */
2178
2179         if ((cb = suck_start(c)) == NULL) {
2180                 /* this normally means, the classpath was not set properly */
2181
2182                 if (name == utf_java_lang_Object)
2183                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2184                                                                            "java/lang/Object");
2185
2186                 *exceptionptr =
2187                         new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2188                                                                          name);
2189                 goto return_exception;
2190         }
2191         
2192         /* load the class from the buffer */
2193
2194         r = load_class_from_classbuffer(cb);
2195
2196         if (!r) {
2197                 /* the class could not be loaded, free the classinfo struct */
2198
2199                 class_free(c);
2200
2201         } else {
2202                 /* Store this class in the loaded class cache this step also
2203                 checks the loading constraints. If the class has been loaded
2204                 before, the earlier loaded class is returned. */
2205
2206                 classinfo *res = classcache_store(NULL, c, true);
2207
2208                 if (!res) {
2209                         /* exception */
2210                         class_free(c);
2211                 }
2212
2213                 r = res;
2214         }
2215
2216         /* SUN compatible -verbose:class output */
2217
2218         if (opt_verboseclass && r) {
2219                 printf("[Loaded ");
2220                 utf_display_classname(name);
2221                 printf(" from %s]\n", cb->path);
2222         }
2223
2224         /* free memory */
2225
2226         suck_stop(cb);
2227
2228 #if defined(STATISTICS)
2229         /* measure time */
2230
2231         if (getloadingtime)
2232                 loadingtime_stop();
2233
2234         if (getcompilingtime)
2235                 compilingtime_start();
2236 #endif
2237
2238         if (!r)
2239                 goto return_exception;
2240
2241 success:
2242         LOADER_DEC();
2243
2244         return r;
2245
2246 return_exception:
2247         LOADER_DEC();
2248
2249         return NULL;
2250 }
2251
2252
2253 /* load_class_from_classbuffer *************************************************
2254         
2255    Loads everything interesting about a class from the class file. The
2256    'classinfo' structure must have been allocated previously.
2257
2258    The super class and the interfaces implemented by this class need
2259    not be loaded. The link is set later by the function 'class_link'.
2260
2261    The loaded class is removed from the list 'unloadedclasses' and
2262    added to the list 'unlinkedclasses'.
2263         
2264    SYNCHRONIZATION:
2265        This function is NOT synchronized!
2266    
2267 *******************************************************************************/
2268
2269 classinfo *load_class_from_classbuffer(classbuffer *cb)
2270 {
2271         classinfo *c;
2272         utf *name;
2273         utf *supername;
2274         u4 i,j;
2275         u4 ma, mi;
2276         s4 dumpsize;
2277         descriptor_pool *descpool;
2278 #if defined(STATISTICS)
2279         u4 classrefsize;
2280         u4 descsize;
2281 #endif
2282 #ifdef LOADER_VERBOSE
2283         char logtext[MAXLOGTEXT];
2284 #endif
2285
2286         /* get the classbuffer's class */
2287
2288         c = cb->class;
2289
2290         /* maybe the class is already loaded */
2291
2292         if (c->loaded)
2293                 return c;
2294
2295 #ifdef LOADER_VERBOSE
2296         LOADER_INDENT(logtext);
2297         strcat(logtext,"load_class_from_classbuffer(");
2298         utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2299         log_text(logtext);
2300         LOADER_INC();
2301 #endif
2302
2303 #if defined(STATISTICS)
2304         if (opt_stat)
2305                 count_class_loads++;
2306 #endif
2307
2308         /* output for debugging purposes */
2309
2310         if (loadverbose)
2311                 log_message_class("Loading class: ", c);
2312         
2313         /* mark start of dump memory area */
2314
2315         dumpsize = dump_size();
2316
2317         /* class is somewhat loaded */
2318
2319         c->loaded = true;
2320
2321         if (!check_classbuffer_size(cb, 4 + 2 + 2))
2322                 goto return_exception;
2323
2324         /* check signature */
2325
2326         if (suck_u4(cb) != MAGIC) {
2327                 *exceptionptr = new_classformaterror(c, "Bad magic number");
2328
2329                 goto return_exception;
2330         }
2331
2332         /* check version */
2333
2334         mi = suck_u2(cb);
2335         ma = suck_u2(cb);
2336
2337         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2338                 *exceptionptr =
2339                         new_unsupportedclassversionerror(c,
2340                                                                                          "Unsupported major.minor version %d.%d",
2341                                                                                          ma, mi);
2342
2343                 goto return_exception;
2344         }
2345
2346         /* create a new descriptor pool */
2347
2348         descpool = descriptor_pool_new(c);
2349
2350         /* load the constant pool */
2351
2352         if (!load_constantpool(cb, descpool))
2353                 goto return_exception;
2354
2355         /*JOWENN*/
2356         c->erroneous_state = 0;
2357         c->initializing_thread = 0;     
2358         /*JOWENN*/
2359         c->classUsed = NOTUSED; /* not used initially CO-RT */
2360         c->impldBy = NULL;
2361
2362         /* ACC flags */
2363
2364         if (!check_classbuffer_size(cb, 2))
2365                 goto return_exception;
2366
2367         c->flags = suck_u2(cb);
2368
2369         /* check ACC flags consistency */
2370
2371         if (c->flags & ACC_INTERFACE) {
2372                 if (!(c->flags & ACC_ABSTRACT)) {
2373                         /* We work around this because interfaces in JDK 1.1 are
2374                          * not declared abstract. */
2375
2376                         c->flags |= ACC_ABSTRACT;
2377                 }
2378
2379                 if (c->flags & ACC_FINAL) {
2380                         *exceptionptr =
2381                                 new_classformaterror(c,
2382                                                                          "Illegal class modifiers: 0x%X", c->flags);
2383
2384                         goto return_exception;
2385                 }
2386
2387                 if (c->flags & ACC_SUPER) {
2388                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2389                 }
2390         }
2391
2392         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2393                 *exceptionptr =
2394                         new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2395
2396                 goto return_exception;
2397         }
2398
2399         if (!check_classbuffer_size(cb, 2 + 2))
2400                 goto return_exception;
2401
2402         /* this class */
2403
2404         i = suck_u2(cb);
2405         if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2406                 goto return_exception;
2407
2408         if (c->name == utf_not_named_yet) {
2409                 /* we finally have a name for this class */
2410                 c->name = name;
2411                 class_set_packagename(c);
2412
2413         } else if (name != c->name) {
2414                 char *msg;
2415                 s4    msglen;
2416
2417                 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
2418                         utf_strlen(name) + strlen(")") + strlen("0");
2419
2420                 msg = MNEW(char, msglen);
2421
2422                 utf_sprint(msg, c->name);
2423                 strcat(msg, " (wrong name: ");
2424                 utf_strcat(msg, name);
2425                 strcat(msg, ")");
2426
2427                 *exceptionptr =
2428                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2429
2430                 MFREE(msg, char, msglen);
2431
2432                 goto return_exception;
2433         }
2434         
2435         /* retrieve superclass */
2436
2437         c->super.any = NULL;
2438         if ((i = suck_u2(cb))) {
2439                 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2440                         goto return_exception;
2441
2442                 /* java.lang.Object may not have a super class. */
2443
2444                 if (c->name == utf_java_lang_Object) {
2445                         *exceptionptr =
2446                                 new_exception_message(string_java_lang_ClassFormatError,
2447                                                                           "java.lang.Object with superclass");
2448
2449                         goto return_exception;
2450                 }
2451
2452                 /* Interfaces must have java.lang.Object as super class. */
2453
2454                 if ((c->flags & ACC_INTERFACE) &&
2455                         supername != utf_java_lang_Object) {
2456                         *exceptionptr =
2457                                 new_exception_message(string_java_lang_ClassFormatError,
2458                                                                           "Interfaces must have java.lang.Object as superclass");
2459
2460                         goto return_exception;
2461                 }
2462
2463         } else {
2464                 supername = NULL;
2465
2466                 /* This is only allowed for java.lang.Object. */
2467
2468                 if (c->name != utf_java_lang_Object) {
2469                         *exceptionptr = new_classformaterror(c, "Bad superclass index");
2470
2471                         goto return_exception;
2472                 }
2473         }
2474                          
2475         /* retrieve interfaces */
2476
2477         if (!check_classbuffer_size(cb, 2))
2478                 goto return_exception;
2479
2480         c->interfacescount = suck_u2(cb);
2481
2482         if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2483                 goto return_exception;
2484
2485         c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2486         for (i = 0; i < c->interfacescount; i++) {
2487                 /* the classrefs are created later */
2488                 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2489                         goto return_exception;
2490         }
2491
2492         /* load fields */
2493         if (!check_classbuffer_size(cb, 2))
2494                 goto return_exception;
2495
2496         c->fieldscount = suck_u2(cb);
2497         c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
2498 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
2499         for (i = 0; i < c->fieldscount; i++) {
2500                 if (!load_field(cb, &(c->fields[i]),descpool))
2501                         goto return_exception;
2502         }
2503
2504         /* load methods */
2505         if (!check_classbuffer_size(cb, 2))
2506                 goto return_exception;
2507
2508         c->methodscount = suck_u2(cb);
2509 /*      c->methods = GCNEW(methodinfo, c->methodscount); */
2510         c->methods = MNEW(methodinfo, c->methodscount);
2511         for (i = 0; i < c->methodscount; i++) {
2512                 if (!load_method(cb, &(c->methods[i]),descpool))
2513                         goto return_exception;
2514         }
2515
2516         /* create the class reference table */
2517
2518         c->classrefs =
2519                 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2520
2521         /* allocate space for the parsed descriptors */
2522
2523         descriptor_pool_alloc_parsed_descriptors(descpool);
2524         c->parseddescs =
2525                 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2526
2527 #if defined(STATISTICS)
2528         if (opt_stat) {
2529                 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2530                 count_classref_len += classrefsize;
2531                 count_parsed_desc_len += descsize;
2532         }
2533 #endif
2534
2535         /* put the classrefs in the constant pool */
2536         for (i = 0; i < c->cpcount; i++) {
2537                 if (c->cptags[i] == CONSTANT_Class) {
2538                         utf *name = (utf *) c->cpinfos[i];
2539                         c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2540                 }
2541         }
2542
2543         /* set the super class reference */
2544
2545         if (supername) {
2546                 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2547                 if (!c->super.ref)
2548                         goto return_exception;
2549         }
2550
2551         /* set the super interfaces references */
2552
2553         for (i = 0; i < c->interfacescount; i++) {
2554                 c->interfaces[i].ref =
2555                         descriptor_pool_lookup_classref(descpool,
2556                                                                                         (utf *) c->interfaces[i].any);
2557                 if (!c->interfaces[i].ref)
2558                         goto return_exception;
2559         }
2560
2561         /* parse field descriptors */
2562
2563         for (i = 0; i < c->fieldscount; i++) {
2564                 c->fields[i].parseddesc =
2565                         descriptor_pool_parse_field_descriptor(descpool,
2566                                                                                                    c->fields[i].descriptor);
2567                 if (!c->fields[i].parseddesc)
2568                         goto return_exception;
2569         }
2570
2571         /* parse method descriptors */
2572
2573         for (i = 0; i < c->methodscount; i++) {
2574                 methodinfo *m = &c->methods[i];
2575                 m->parseddesc =
2576                         descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2577                                                                                                         m->flags, class_get_self_classref(m->class));
2578                 if (!m->parseddesc)
2579                         goto return_exception;
2580
2581                 for (j = 0; j < m->exceptiontablelength; j++) {
2582                         if (!m->exceptiontable[j].catchtype.any)
2583                                 continue;
2584                         if ((m->exceptiontable[j].catchtype.ref =
2585                                  descriptor_pool_lookup_classref(descpool,
2586                                                 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2587                                 goto return_exception;
2588                 }
2589
2590                 for (j = 0; j < m->thrownexceptionscount; j++) {
2591                         if (!m->thrownexceptions[j].any)
2592                                 continue;
2593                         if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2594                                                 (utf *) m->thrownexceptions[j].any)) == NULL)
2595                                 goto return_exception;
2596                 }
2597         }
2598
2599         /* parse the loaded descriptors */
2600
2601         for (i = 0; i < c->cpcount; i++) {
2602                 constant_FMIref *fmi;
2603                 s4               index;
2604                 
2605                 switch (c->cptags[i]) {
2606                 case CONSTANT_Fieldref:
2607                         fmi = (constant_FMIref *) c->cpinfos[i];
2608                         fmi->parseddesc.fd =
2609                                 descriptor_pool_parse_field_descriptor(descpool,
2610                                                                                                            fmi->descriptor);
2611                         if (!fmi->parseddesc.fd)
2612                                 goto return_exception;
2613                         index = (int) (size_t) fmi->classref;
2614                         fmi->classref =
2615                                 (constant_classref *) class_getconstant(c, index,
2616                                                                                                                 CONSTANT_Class);
2617                         if (!fmi->classref)
2618                                 goto return_exception;
2619                         break;
2620                 case CONSTANT_Methodref:
2621                 case CONSTANT_InterfaceMethodref:
2622                         fmi = (constant_FMIref *) c->cpinfos[i];
2623                         index = (int) (size_t) fmi->classref;
2624                         fmi->classref =
2625                                 (constant_classref *) class_getconstant(c, index,
2626                                                                                                                 CONSTANT_Class);
2627                         if (!fmi->classref)
2628                                 goto return_exception;
2629                         fmi->parseddesc.md =
2630                                 descriptor_pool_parse_method_descriptor(descpool,
2631                                                                                                                 fmi->descriptor,
2632                                                                                                                 ACC_UNDEF,
2633                                                                                                                 fmi->classref);
2634                         if (!fmi->parseddesc.md)
2635                                 goto return_exception;
2636                         break;
2637                 }
2638         }
2639
2640         /* Check if all fields and methods can be uniquely
2641          * identified by (name,descriptor). */
2642
2643         if (opt_verify) {
2644                 /* We use a hash table here to avoid making the
2645                  * average case quadratic in # of methods, fields.
2646                  */
2647                 static int shift = 0;
2648                 u2 *hashtab;
2649                 u2 *next; /* for chaining colliding hash entries */
2650                 size_t len;
2651                 size_t hashlen;
2652                 u2 index;
2653                 u2 old;
2654
2655                 /* Allocate hashtable */
2656                 len = c->methodscount;
2657                 if (len < c->fieldscount) len = c->fieldscount;
2658                 hashlen = 5 * len;
2659                 hashtab = MNEW(u2,(hashlen + len));
2660                 next = hashtab + hashlen;
2661
2662                 /* Determine bitshift (to get good hash values) */
2663                 if (!shift) {
2664                         len = sizeof(utf);
2665                         while (len) {
2666                                 len >>= 1;
2667                                 shift++;
2668                         }
2669                 }
2670
2671                 /* Check fields */
2672                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2673
2674                 for (i = 0; i < c->fieldscount; ++i) {
2675                         fieldinfo *fi = c->fields + i;
2676
2677                         /* It's ok if we lose bits here */
2678                         index = ((((size_t) fi->name) +
2679                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2680
2681                         if ((old = hashtab[index])) {
2682                                 old--;
2683                                 next[i] = old;
2684                                 do {
2685                                         if (c->fields[old].name == fi->name &&
2686                                                 c->fields[old].descriptor == fi->descriptor) {
2687                                                 *exceptionptr =
2688                                                         new_classformaterror(c,
2689                                                                                                  "Repetitive field name/signature");
2690
2691                                                 goto return_exception;
2692                                         }
2693                                 } while ((old = next[old]));
2694                         }
2695                         hashtab[index] = i + 1;
2696                 }
2697                 
2698                 /* Check methods */
2699                 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2700
2701                 for (i = 0; i < c->methodscount; ++i) {
2702                         methodinfo *mi = c->methods + i;
2703
2704                         /* It's ok if we lose bits here */
2705                         index = ((((size_t) mi->name) +
2706                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2707
2708                         /*{ JOWENN
2709                                 int dbg;
2710                                 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2711                                         printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2712                                 }
2713                         }*/
2714
2715                         if ((old = hashtab[index])) {
2716                                 old--;
2717                                 next[i] = old;
2718                                 do {
2719                                         if (c->methods[old].name == mi->name &&
2720                                                 c->methods[old].descriptor == mi->descriptor) {
2721                                                 *exceptionptr =
2722                                                         new_classformaterror(c,
2723                                                                                                  "Repetitive method name/signature");
2724
2725                                                 goto return_exception;
2726                                         }
2727                                 } while ((old = next[old]));
2728                         }
2729                         hashtab[index] = i + 1;
2730                 }
2731                 
2732                 MFREE(hashtab, u2, (hashlen + len));
2733         }
2734
2735 #if defined(STATISTICS)
2736         if (opt_stat) {
2737                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2738                 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2739                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2740         }
2741 #endif
2742
2743         /* load attribute structures */
2744
2745         if (!check_classbuffer_size(cb, 2))
2746                 goto return_exception;
2747
2748         if (!load_attributes(cb, suck_u2(cb)))
2749                 goto return_exception;
2750
2751 #if 0
2752         /* Pre java 1.5 version don't check this. This implementation is like
2753            java 1.5 do it: for class file version 45.3 we don't check it, older
2754            versions are checked.
2755          */
2756         if ((ma == 45 && mi > 3) || ma > 45) {
2757                 /* check if all data has been read */
2758                 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2759
2760                 if (classdata_left > 0) {
2761                         *exceptionptr =
2762                                 new_classformaterror(c, "Extra bytes at the end of class file");
2763                         goto return_exception;
2764                 }
2765         }
2766 #endif
2767
2768         /* release dump area */
2769
2770         dump_release(dumpsize);
2771         
2772         if (loadverbose)
2773                 log_message_class("Loading done class: ", c);
2774
2775         LOADER_DEC();
2776         return c;
2777
2778 return_exception:
2779         /* release dump area */
2780
2781         dump_release(dumpsize);
2782
2783         /* an exception has been thrown */
2784
2785         LOADER_DEC();
2786         return NULL;
2787 }
2788
2789
2790 /* load_newly_created_array ****************************************************
2791
2792    Load a newly created array class.
2793
2794         RETURN VALUE:
2795             c....................the array class C has been loaded
2796                 other classinfo......the array class was found in the class cache, 
2797                                      C has been freed
2798             NULL.................an exception has been thrown
2799
2800         Note:
2801                 This is an internal function. Do not use it unless you know exactly
2802                 what you are doing!
2803
2804                 Use one of the load_class_... functions for general array class loading.
2805
2806 *******************************************************************************/
2807
2808 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2809 {
2810         classinfo         *comp = NULL;
2811         methodinfo        *clone;
2812         methoddesc        *clonedesc;
2813         constant_classref *classrefs;
2814         char              *text;
2815         s4                 namelen;
2816         utf               *u;
2817
2818 #ifdef LOADER_VERBOSE
2819         char logtext[MAXLOGTEXT];
2820         LOADER_INDENT(logtext);
2821         strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2822         sprintf(logtext+strlen(logtext),") loader=%p",loader);
2823         log_text(logtext);
2824 #endif
2825
2826         text = c->name->text;
2827         namelen = c->name->blength;
2828
2829         /* Check array class name */
2830
2831         if (namelen < 2 || text[0] != '[') {
2832                 *exceptionptr = new_noclassdeffounderror(c->name);
2833                 return NULL;
2834         }
2835
2836         /* Check the element type */
2837
2838         switch (text[1]) {
2839         case '[':
2840                 /* c is an array of arrays. We have to create the component class. */
2841
2842                 u = utf_new_intern(text + 1, namelen - 1);
2843                 LOADER_INC();
2844                 if (!(comp = load_class_from_classloader(u, loader))) {
2845                         LOADER_DEC();
2846                         return NULL;
2847                 }
2848                 LOADER_DEC();
2849                 LOADER_ASSERT(comp->loaded);
2850                 if (opt_eager)
2851                         if (!link_class(c))
2852                                 return NULL;
2853
2854                 /* the array's flags are that of the component class */
2855                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2856                 c->classloader = comp->classloader;
2857                 break;
2858
2859         case 'L':
2860                 /* c is an array of objects. */
2861
2862                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2863                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2864                         *exceptionptr = new_noclassdeffounderror(c->name);
2865                         return NULL;
2866                 }
2867
2868                 u = utf_new_intern(text + 2, namelen - 3);
2869
2870                 LOADER_INC();
2871                 if (!(comp = load_class_from_classloader(u, loader))) {
2872                         LOADER_DEC();
2873                         return NULL;
2874                 }
2875                 LOADER_DEC();
2876                 LOADER_ASSERT(comp->loaded);
2877                 if (opt_eager)
2878                         if (!link_class(c))
2879                                 return NULL;
2880
2881                 /* the array's flags are that of the component class */
2882                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2883                 c->classloader = comp->classloader;
2884                 break;
2885
2886         default:
2887                 /* c is an array of a primitive type */
2888
2889                 /* check for cases like `[II' */
2890                 if (namelen > 2) {
2891                         *exceptionptr = new_noclassdeffounderror(c->name);
2892                         return NULL;
2893                 }
2894
2895                 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2896                 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2897                 c->classloader = NULL;
2898         }
2899
2900         LOADER_ASSERT(class_java_lang_Object);
2901         LOADER_ASSERT(class_java_lang_Cloneable);
2902         LOADER_ASSERT(class_java_io_Serializable);
2903
2904         /* setup the array class */
2905
2906         c->super.cls = class_java_lang_Object;
2907
2908     c->interfacescount = 2;
2909     c->interfaces = MNEW(classref_or_classinfo, 2);
2910
2911         if (opt_eager) {
2912                 classinfo *tc;
2913
2914                 tc = class_java_lang_Cloneable;
2915                 LOADER_ASSERT(tc->loaded);
2916                 list_addfirst(&unlinkedclasses, tc);
2917                 c->interfaces[0].cls = tc;
2918
2919                 tc = class_java_io_Serializable;
2920                 LOADER_ASSERT(tc->loaded);
2921                 list_addfirst(&unlinkedclasses, tc);
2922                 c->interfaces[1].cls = tc;
2923
2924         } else {
2925                 c->interfaces[0].cls = class_java_lang_Cloneable;
2926                 c->interfaces[1].cls = class_java_io_Serializable;
2927         }
2928
2929         c->methodscount = 1;
2930         c->methods = MNEW(methodinfo, c->methodscount);
2931
2932         classrefs = MNEW(constant_classref, 2);
2933         CLASSREF_INIT(classrefs[0], c, c->name);
2934         CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2935
2936         /* create descriptor for clone method */
2937         /* we need one paramslot which is reserved for the 'this' parameter */
2938         clonedesc = NEW(methoddesc);
2939         clonedesc->returntype.type = TYPE_ADDRESS;
2940         clonedesc->returntype.classref = classrefs + 1;
2941         clonedesc->returntype.arraydim = 0;
2942         /* initialize params to "empty", add real params below in
2943            descriptor_params_from_paramtypes */
2944         clonedesc->paramcount = 0;
2945         clonedesc->paramslots = 0;
2946         clonedesc->paramtypes[0].classref = classrefs + 0;
2947
2948         /* create methodinfo */
2949
2950         clone = c->methods;
2951         MSET(clone, 0, methodinfo, 1);
2952
2953 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2954         initObjectLock(&clone->header);
2955 #endif
2956
2957         /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter 
2958            related) */
2959         clone->flags = ACC_PUBLIC | ACC_NATIVE;
2960         clone->name = utf_clone;
2961         clone->descriptor = utf_void__java_lang_Object;
2962         clone->parseddesc = clonedesc;
2963         clone->class = c;
2964         clone->monoPoly = MONO;
2965
2966         /* parse the descriptor to get the register allocation */
2967
2968         if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2969                 return false;
2970
2971         clone->entrypoint =
2972                 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2973
2974         /* XXX: field: length? */
2975
2976         /* array classes are not loaded from class files */
2977
2978         c->loaded = true;
2979         c->parseddescs = (u1 *) clonedesc;
2980         c->parseddescsize = sizeof(methodinfo);
2981         c->classrefs = classrefs;
2982         c->classrefcount = 1;
2983
2984         /* insert class into the loaded class cache */
2985         /* XXX free classinfo if NULL returned? */
2986
2987         return classcache_store(loader,c,true);
2988 }
2989
2990
2991 /* loader_close ****************************************************************
2992
2993    Frees all resources.
2994         
2995 *******************************************************************************/
2996
2997 void loader_close(void)
2998 {
2999         /* empty */
3000 }
3001
3002
3003 /*
3004  * These are local overrides for various environment variables in Emacs.
3005  * Please do not remove this and leave it at the end of the file, where
3006  * Emacs will automagically detect them.
3007  * ---------------------------------------------------------------------
3008  * Local variables:
3009  * mode: c
3010  * indent-tabs-mode: t
3011  * c-basic-offset: 4
3012  * tab-width: 4
3013  * End:
3014  */