added resolve_*_eager functions
[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 3460 2005-10-20 09:34:16Z edwin $
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 += 8 * m->exceptiontablelength;
1696                         }
1697 #endif
1698
1699                         for (j = 0; j < m->exceptiontablelength; j++) {
1700                                 u4 idx;
1701                                 m->exceptiontable[j].startpc = suck_u2(cb);
1702                                 m->exceptiontable[j].endpc = suck_u2(cb);
1703                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1704
1705                                 idx = suck_u2(cb);
1706                                 if (!idx) {
1707                                         m->exceptiontable[j].catchtype.any = NULL;
1708
1709                                 } else {
1710                                         /* the classref is created later */
1711                                         if (!(m->exceptiontable[j].catchtype.any =
1712                                                   (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1713                                                 return false;
1714                                 }
1715                         }
1716
1717                         if (!check_classbuffer_size(cb, 2))
1718                                 return false;
1719
1720                         codeattrnum = suck_u2(cb);
1721
1722                         for (; codeattrnum > 0; codeattrnum--) {
1723                                 utf *caname;
1724
1725                                 if (!check_classbuffer_size(cb, 2))
1726                                         return false;
1727
1728                                 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1729                                         return false;
1730
1731                                 if (caname == utf_LineNumberTable) {
1732                                         u2 lncid;
1733
1734                                         if (!check_classbuffer_size(cb, 4 + 2))
1735                                                 return false;
1736
1737                                         suck_u4(cb);
1738                                         m->linenumbercount = suck_u2(cb);
1739
1740                                         if (!check_classbuffer_size(cb,
1741                                                                                                 (2 + 2) * m->linenumbercount))
1742                                                 return false;
1743
1744                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1745                                         
1746                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1747                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1748                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1749                                         }
1750                                         codeattrnum--;
1751
1752                                         if (!skipattributes(cb, codeattrnum))
1753                                                 return false;
1754                                         
1755                                         break;
1756
1757                                 } else {
1758                                         if (!skipattributebody(cb))
1759                                                 return false;
1760                                 }
1761                         }
1762
1763                 } else if (aname == utf_Exceptions) {
1764                         s4 j;
1765
1766                         if (m->thrownexceptions) {
1767                                 *exceptionptr =
1768                                         new_classformaterror(c, "Multiple Exceptions attributes");
1769                                 return false;
1770                         }
1771
1772                         if (!check_classbuffer_size(cb, 4 + 2))
1773                                 return false;
1774
1775                         suck_u4(cb); /* length */
1776                         m->thrownexceptionscount = suck_u2(cb);
1777
1778                         if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1779                                 return false;
1780
1781                         m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1782
1783                         for (j = 0; j < m->thrownexceptionscount; j++) {
1784                                 /* the classref is created later */
1785                                 if (!((m->thrownexceptions)[j].any =
1786                                           (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1787                                         return false;
1788                         }
1789                                 
1790                 } else {
1791                         if (!skipattributebody(cb))
1792                                 return false;
1793                 }
1794         }
1795
1796         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1797                 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1798
1799                 return false;
1800         }
1801
1802         /* everything was ok */
1803
1804         return true;
1805 }
1806
1807
1808 /* load_attribute **************************************************************
1809
1810    Read attributes from classfile.
1811         
1812 *******************************************************************************/
1813
1814 static bool load_attributes(classbuffer *cb, u4 num)
1815 {
1816         classinfo *c;
1817         utf       *aname;
1818         u4 i, j;
1819
1820         c = cb->class;
1821
1822         for (i = 0; i < num; i++) {
1823                 /* retrieve attribute name */
1824                 if (!check_classbuffer_size(cb, 2))
1825                         return false;
1826
1827                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1828                         return false;
1829
1830                 if (aname == utf_InnerClasses) {
1831                         /* innerclasses attribute */
1832                         if (c->innerclass) {
1833                                 *exceptionptr =
1834                                         new_classformaterror(c, "Multiple InnerClasses attributes");
1835                                 return false;
1836                         }
1837                                 
1838                         if (!check_classbuffer_size(cb, 4 + 2))
1839                                 return false;
1840
1841                         /* skip attribute length */
1842                         suck_u4(cb);
1843
1844                         /* number of records */
1845                         c->innerclasscount = suck_u2(cb);
1846
1847                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1848                                 return false;
1849
1850                         /* allocate memory for innerclass structure */
1851                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1852
1853                         for (j = 0; j < c->innerclasscount; j++) {
1854                                 /* The innerclass structure contains a class with an encoded
1855                                    name, its defining scope, its simple name and a bitmask of
1856                                    the access flags. If an inner class is not a member, its
1857                                    outer_class is NULL, if a class is anonymous, its name is
1858                                    NULL. */
1859                                                                 
1860                                 innerclassinfo *info = c->innerclass + j;
1861
1862                                 info->inner_class.ref =
1863                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1864                                 info->outer_class.ref =
1865                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1866                                 info->name =
1867                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1868                                 info->flags = suck_u2(cb);
1869                         }
1870
1871                 } else if (aname == utf_SourceFile) {
1872                         if (!check_classbuffer_size(cb, 4 + 2))
1873                                 return false;
1874
1875                         if (suck_u4(cb) != 2) {
1876                                 *exceptionptr =
1877                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1878                                 return false;
1879                         }
1880
1881                         if (c->sourcefile) {
1882                                 *exceptionptr =
1883                                         new_classformaterror(c, "Multiple SourceFile attributes");
1884                                 return false;
1885                         }
1886
1887                         if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1888                                 return false;
1889
1890                 } else {
1891                         /* unknown attribute */
1892                         if (!skipattributebody(cb))
1893                                 return false;
1894                 }
1895         }
1896
1897         return true;
1898 }
1899
1900
1901 /* load_class_from_sysloader ***************************************************
1902
1903    Load the class with the given name using the system class loader
1904
1905    IN:
1906        name.............the classname
1907
1908    RETURN VALUE:
1909        the loaded class, or
1910            NULL if an exception has been thrown
1911
1912 *******************************************************************************/
1913
1914 classinfo *load_class_from_sysloader(utf *name)
1915 {
1916         methodinfo        *m;
1917         java_objectheader *cl;
1918         classinfo         *r;
1919
1920 #ifdef LOADER_VERBOSE
1921         char logtext[MAXLOGTEXT];
1922         LOADER_INDENT(logtext);
1923         sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1924         utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1925         log_text(logtext);
1926 #endif
1927
1928         LOADER_ASSERT(class_java_lang_Object);
1929         LOADER_ASSERT(class_java_lang_ClassLoader);
1930         LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1931         
1932         m = class_resolveclassmethod(class_java_lang_ClassLoader,
1933                                                                  utf_getSystemClassLoader,
1934                                                                  utf_void__java_lang_ClassLoader,
1935                                                                  class_java_lang_Object,
1936                                                                  false);
1937
1938         if (!m)
1939                 return false;
1940
1941         cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1942         if (!cl)
1943                 return false;
1944
1945         LOADER_INC();
1946         r = load_class_from_classloader(name, cl);
1947         LOADER_DEC();
1948
1949         return r;
1950 }
1951
1952 /* load_class_from_classloader *************************************************
1953
1954    Load the class with the given name using the given user-defined class loader.
1955
1956    IN:
1957        name.............the classname
1958            cl...............user-defined class loader
1959            
1960    RETURN VALUE:
1961        the loaded class, or
1962            NULL if an exception has been thrown
1963
1964 *******************************************************************************/
1965
1966 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1967 {
1968         classinfo *r;
1969
1970 #ifdef LOADER_VERBOSE
1971         char logtext[MAXLOGTEXT];
1972         LOADER_INDENT(logtext);
1973         strcat(logtext,"load_class_from_classloader(");
1974         utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1975         if (!cl) strcat(logtext,"<bootstrap>");
1976         else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1977         else strcat(logtext,"<unknown class>");
1978         strcat(logtext,")");
1979         log_text(logtext);
1980 #endif
1981
1982         LOADER_ASSERT(name);
1983
1984         /* lookup if this class has already been loaded */
1985
1986         r = classcache_lookup(cl, name);
1987
1988 #ifdef LOADER_VERBOSE
1989         if (r)
1990                 dolog("        cached -> %p",(void*)r);
1991 #endif
1992
1993         if (r)
1994                 return r;
1995
1996         /* if other class loader than bootstrap, call it */
1997
1998         if (cl) {
1999                 methodinfo *lc;
2000                 char       *text;
2001                 s4          namelen;
2002
2003                 text = name->text;
2004                 namelen = name->blength;
2005
2006                 /* handle array classes */
2007                 if (text[0] == '[') {
2008                         classinfo *comp;
2009                         utf       *u;
2010
2011                         switch (text[1]) {
2012                         case 'L':
2013                                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2014                                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2015                                         *exceptionptr = new_noclassdeffounderror(name);
2016                                         return false;
2017                                 }
2018
2019                                 u = utf_new(text + 2, namelen - 3);
2020
2021                                 if (!(comp = load_class_from_classloader(u, cl)))
2022                                         return false;
2023
2024                                 /* create the array class */
2025                                 return class_array_of(comp, false);
2026
2027                         case '[':
2028                                 /* load the component class */
2029
2030                                 u = utf_new(text + 1, namelen - 1);
2031
2032                                 if (!(comp = load_class_from_classloader(u, cl)))
2033                                         return false;
2034
2035                                 /* create the array class */
2036                                 return class_array_of(comp, false);
2037
2038                         default:
2039                                 /* primitive array classes are loaded by the bootstrap loader */
2040                                 return load_class_bootstrap(name);
2041                         }
2042                 }
2043                 
2044                 LOADER_ASSERT(class_java_lang_Object);
2045
2046                 lc = class_resolveclassmethod(cl->vftbl->class,
2047                                                                           utf_loadClass,
2048                                                                           utf_java_lang_String__java_lang_Class,
2049                                                                           class_java_lang_Object,
2050                                                                           true);
2051
2052                 if (!lc)
2053                         return false; /* exception */
2054
2055                 LOADER_INC();
2056                 r = (classinfo *) asm_calljavafunction(lc,
2057                                                                                            cl,
2058                                                                                            javastring_new_slash_to_dot(name),
2059                                                                                            NULL, NULL);
2060                 LOADER_DEC();
2061
2062                 if (r) {
2063                         /* Store this class in the loaded class cache. If another
2064                            class with the same (initloader,name) pair has been
2065                            stored earlier it will be returned by classcache_store
2066                            In this case classcache_store may not free the class
2067                            because it has already been exposed to Java code which
2068                            may have kept references to that class. */
2069
2070                     classinfo *c = classcache_store(cl,r,false);
2071
2072                         if (c == NULL) {
2073                                 /* exception, free the loaded class */
2074                                 r->loaded = false;
2075                                 class_free(r);
2076                         }
2077
2078                         r = c;
2079                 }
2080                 else {
2081                         /* loadClass has thrown an exception */
2082                         /* we must convert ClassNotFoundException into NoClassDefFoundException */
2083                         /* XXX maybe we should have a flag that avoids this conversion */
2084                         /* for calling load_class_from_classloader from Class.forName  */
2085                         /* Currently we do a double conversion in these cases          */
2086                         classnotfoundexception_to_noclassdeffounderror();
2087                 }
2088
2089                 /* SUN compatible -verbose:class output */
2090
2091                 if (opt_verboseclass && (r != NULL) && (r->classloader == cl)) {
2092                         printf("[Loaded ");
2093                         utf_display_classname(name);
2094                         printf("]\n");
2095                 }
2096
2097                 return r;
2098         } 
2099
2100         LOADER_INC();
2101         r = load_class_bootstrap(name);
2102         LOADER_DEC();
2103
2104         return r;
2105 }
2106
2107
2108 /* load_class_bootstrap ********************************************************
2109         
2110    Load the class with the given name using the bootstrap class loader.
2111
2112    IN:
2113        name.............the classname
2114
2115    RETURN VALUE:
2116        loaded classinfo, or
2117            NULL if an exception has been thrown
2118
2119    SYNCHRONIZATION:
2120        load_class_bootstrap is synchronized. It can be treated as an
2121            atomic operation.
2122
2123 *******************************************************************************/
2124
2125 classinfo *load_class_bootstrap(utf *name)
2126 {
2127         classbuffer *cb;
2128         classinfo   *c;
2129         classinfo   *r;
2130 #ifdef LOADER_VERBOSE
2131         char logtext[MAXLOGTEXT];
2132 #endif
2133
2134         /* for debugging */
2135
2136         LOADER_ASSERT(name);
2137         LOADER_INC();
2138
2139         /* lookup if this class has already been loaded */
2140
2141         if ((r = classcache_lookup(NULL, name)))
2142                 goto success;
2143
2144 #ifdef LOADER_VERBOSE
2145         LOADER_INDENT(logtext);
2146         strcat(logtext,"load_class_bootstrap(");
2147         utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
2148         log_text(logtext);
2149 #endif
2150
2151         /* create the classinfo */
2152
2153         c = class_create_classinfo(name);
2154         
2155         /* handle array classes */
2156
2157         if (name->text[0] == '[') {
2158                 c = load_newly_created_array(c, NULL);
2159                 if (c == NULL)
2160                         goto return_exception;
2161                 LOADER_ASSERT(c->loaded);
2162                 r = c;
2163                 goto success;
2164         }
2165
2166 #if defined(STATISTICS)
2167         /* measure time */
2168
2169         if (getcompilingtime)
2170                 compilingtime_stop();
2171
2172         if (getloadingtime)
2173                 loadingtime_start();
2174 #endif
2175
2176         /* load classdata, throw exception on error */
2177
2178         if ((cb = suck_start(c)) == NULL) {
2179                 /* this normally means, the classpath was not set properly */
2180
2181                 if (name == utf_java_lang_Object)
2182                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2183                                                                            "java/lang/Object");
2184
2185                 *exceptionptr =
2186                         new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2187                                                                          name);
2188                 goto return_exception;
2189         }
2190         
2191         /* load the class from the buffer */
2192
2193         r = load_class_from_classbuffer(cb);
2194
2195         if (!r) {
2196                 /* the class could not be loaded, free the classinfo struct */
2197
2198                 class_free(c);
2199
2200         } else {
2201                 /* Store this class in the loaded class cache this step also
2202                 checks the loading constraints. If the class has been loaded
2203                 before, the earlier loaded class is returned. */
2204
2205                 classinfo *res = classcache_store(NULL, c, true);
2206
2207                 if (!res) {
2208                         /* exception */
2209                         class_free(c);
2210                 }
2211
2212                 r = res;
2213         }
2214
2215         /* SUN compatible -verbose:class output */
2216
2217         if (opt_verboseclass && r) {
2218                 printf("[Loaded ");
2219                 utf_display_classname(name);
2220                 printf(" from %s]\n", cb->path);
2221         }
2222
2223         /* free memory */
2224
2225         suck_stop(cb);
2226
2227 #if defined(STATISTICS)
2228         /* measure time */
2229
2230         if (getloadingtime)
2231                 loadingtime_stop();
2232
2233         if (getcompilingtime)
2234                 compilingtime_start();
2235 #endif
2236
2237         if (!r)
2238                 goto return_exception;
2239
2240 success:
2241         LOADER_DEC();
2242
2243         return r;
2244
2245 return_exception:
2246         LOADER_DEC();
2247
2248         return NULL;
2249 }
2250
2251
2252 /* load_class_from_classbuffer *************************************************
2253         
2254    Loads everything interesting about a class from the class file. The
2255    'classinfo' structure must have been allocated previously.
2256
2257    The super class and the interfaces implemented by this class need
2258    not be loaded. The link is set later by the function 'class_link'.
2259
2260    The loaded class is removed from the list 'unloadedclasses' and
2261    added to the list 'unlinkedclasses'.
2262         
2263    SYNCHRONIZATION:
2264        This function is NOT synchronized!
2265    
2266 *******************************************************************************/
2267
2268 classinfo *load_class_from_classbuffer(classbuffer *cb)
2269 {
2270         classinfo *c;
2271         utf *name;
2272         utf *supername;
2273         u4 i,j;
2274         u4 ma, mi;
2275         s4 dumpsize;
2276         descriptor_pool *descpool;
2277 #if defined(STATISTICS)
2278         u4 classrefsize;
2279         u4 descsize;
2280 #endif
2281 #ifdef LOADER_VERBOSE
2282         char logtext[MAXLOGTEXT];
2283 #endif
2284
2285         /* get the classbuffer's class */
2286
2287         c = cb->class;
2288
2289         /* maybe the class is already loaded */
2290
2291         if (c->loaded)
2292                 return c;
2293
2294 #ifdef LOADER_VERBOSE
2295         LOADER_INDENT(logtext);
2296         strcat(logtext,"load_class_from_classbuffer(");
2297         utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2298         log_text(logtext);
2299         LOADER_INC();
2300 #endif
2301
2302 #if defined(STATISTICS)
2303         if (opt_stat)
2304                 count_class_loads++;
2305 #endif
2306
2307         /* output for debugging purposes */
2308
2309         if (loadverbose)
2310                 log_message_class("Loading class: ", c);
2311         
2312         /* mark start of dump memory area */
2313
2314         dumpsize = dump_size();
2315
2316         /* class is somewhat loaded */
2317
2318         c->loaded = true;
2319
2320         if (!check_classbuffer_size(cb, 4 + 2 + 2))
2321                 goto return_exception;
2322
2323         /* check signature */
2324
2325         if (suck_u4(cb) != MAGIC) {
2326                 *exceptionptr = new_classformaterror(c, "Bad magic number");
2327
2328                 goto return_exception;
2329         }
2330
2331         /* check version */
2332
2333         mi = suck_u2(cb);
2334         ma = suck_u2(cb);
2335
2336         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2337                 *exceptionptr =
2338                         new_unsupportedclassversionerror(c,
2339                                                                                          "Unsupported major.minor version %d.%d",
2340                                                                                          ma, mi);
2341
2342                 goto return_exception;
2343         }
2344
2345         /* create a new descriptor pool */
2346
2347         descpool = descriptor_pool_new(c);
2348
2349         /* load the constant pool */
2350
2351         if (!load_constantpool(cb, descpool))
2352                 goto return_exception;
2353
2354         /*JOWENN*/
2355         c->erroneous_state = 0;
2356         c->initializing_thread = 0;     
2357         /*JOWENN*/
2358         c->classUsed = NOTUSED; /* not used initially CO-RT */
2359         c->impldBy = NULL;
2360
2361         /* ACC flags */
2362
2363         if (!check_classbuffer_size(cb, 2))
2364                 goto return_exception;
2365
2366         c->flags = suck_u2(cb);
2367
2368         /* check ACC flags consistency */
2369
2370         if (c->flags & ACC_INTERFACE) {
2371                 if (!(c->flags & ACC_ABSTRACT)) {
2372                         /* We work around this because interfaces in JDK 1.1 are
2373                          * not declared abstract. */
2374
2375                         c->flags |= ACC_ABSTRACT;
2376                 }
2377
2378                 if (c->flags & ACC_FINAL) {
2379                         *exceptionptr =
2380                                 new_classformaterror(c,
2381                                                                          "Illegal class modifiers: 0x%X", c->flags);
2382
2383                         goto return_exception;
2384                 }
2385
2386                 if (c->flags & ACC_SUPER) {
2387                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2388                 }
2389         }
2390
2391         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2392                 *exceptionptr =
2393                         new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2394
2395                 goto return_exception;
2396         }
2397
2398         if (!check_classbuffer_size(cb, 2 + 2))
2399                 goto return_exception;
2400
2401         /* this class */
2402
2403         i = suck_u2(cb);
2404         if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2405                 goto return_exception;
2406
2407         if (c->name == utf_not_named_yet) {
2408                 /* we finally have a name for this class */
2409                 c->name = name;
2410                 class_set_packagename(c);
2411
2412         } else if (name != c->name) {
2413                 char *msg;
2414                 s4    msglen;
2415
2416                 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
2417                         utf_strlen(name) + strlen(")") + strlen("0");
2418
2419                 msg = MNEW(char, msglen);
2420
2421                 utf_sprint(msg, c->name);
2422                 strcat(msg, " (wrong name: ");
2423                 utf_strcat(msg, name);
2424                 strcat(msg, ")");
2425
2426                 *exceptionptr =
2427                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2428
2429                 MFREE(msg, char, msglen);
2430
2431                 goto return_exception;
2432         }
2433         
2434         /* retrieve superclass */
2435
2436         c->super.any = NULL;
2437         if ((i = suck_u2(cb))) {
2438                 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2439                         goto return_exception;
2440
2441                 /* java.lang.Object may not have a super class. */
2442
2443                 if (c->name == utf_java_lang_Object) {
2444                         *exceptionptr =
2445                                 new_exception_message(string_java_lang_ClassFormatError,
2446                                                                           "java.lang.Object with superclass");
2447
2448                         goto return_exception;
2449                 }
2450
2451                 /* Interfaces must have java.lang.Object as super class. */
2452
2453                 if ((c->flags & ACC_INTERFACE) &&
2454                         supername != utf_java_lang_Object) {
2455                         *exceptionptr =
2456                                 new_exception_message(string_java_lang_ClassFormatError,
2457                                                                           "Interfaces must have java.lang.Object as superclass");
2458
2459                         goto return_exception;
2460                 }
2461
2462         } else {
2463                 supername = NULL;
2464
2465                 /* This is only allowed for java.lang.Object. */
2466
2467                 if (c->name != utf_java_lang_Object) {
2468                         *exceptionptr = new_classformaterror(c, "Bad superclass index");
2469
2470                         goto return_exception;
2471                 }
2472         }
2473                          
2474         /* retrieve interfaces */
2475
2476         if (!check_classbuffer_size(cb, 2))
2477                 goto return_exception;
2478
2479         c->interfacescount = suck_u2(cb);
2480
2481         if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2482                 goto return_exception;
2483
2484         c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2485         for (i = 0; i < c->interfacescount; i++) {
2486                 /* the classrefs are created later */
2487                 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2488                         goto return_exception;
2489         }
2490
2491         /* load fields */
2492         if (!check_classbuffer_size(cb, 2))
2493                 goto return_exception;
2494
2495         c->fieldscount = suck_u2(cb);
2496         c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
2497 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
2498         for (i = 0; i < c->fieldscount; i++) {
2499                 if (!load_field(cb, &(c->fields[i]),descpool))
2500                         goto return_exception;
2501         }
2502
2503         /* load methods */
2504         if (!check_classbuffer_size(cb, 2))
2505                 goto return_exception;
2506
2507         c->methodscount = suck_u2(cb);
2508 /*      c->methods = GCNEW(methodinfo, c->methodscount); */
2509         c->methods = MNEW(methodinfo, c->methodscount);
2510         for (i = 0; i < c->methodscount; i++) {
2511                 if (!load_method(cb, &(c->methods[i]),descpool))
2512                         goto return_exception;
2513         }
2514
2515         /* create the class reference table */
2516
2517         c->classrefs =
2518                 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2519
2520         /* allocate space for the parsed descriptors */
2521
2522         descriptor_pool_alloc_parsed_descriptors(descpool);
2523         c->parseddescs =
2524                 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2525
2526 #if defined(STATISTICS)
2527         if (opt_stat) {
2528                 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2529                 count_classref_len += classrefsize;
2530                 count_parsed_desc_len += descsize;
2531         }
2532 #endif
2533
2534         /* put the classrefs in the constant pool */
2535         for (i = 0; i < c->cpcount; i++) {
2536                 if (c->cptags[i] == CONSTANT_Class) {
2537                         utf *name = (utf *) c->cpinfos[i];
2538                         c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2539                 }
2540         }
2541
2542         /* set the super class reference */
2543
2544         if (supername) {
2545                 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2546                 if (!c->super.ref)
2547                         goto return_exception;
2548         }
2549
2550         /* set the super interfaces references */
2551
2552         for (i = 0; i < c->interfacescount; i++) {
2553                 c->interfaces[i].ref =
2554                         descriptor_pool_lookup_classref(descpool,
2555                                                                                         (utf *) c->interfaces[i].any);
2556                 if (!c->interfaces[i].ref)
2557                         goto return_exception;
2558         }
2559
2560         /* parse field descriptors */
2561
2562         for (i = 0; i < c->fieldscount; i++) {
2563                 c->fields[i].parseddesc =
2564                         descriptor_pool_parse_field_descriptor(descpool,
2565                                                                                                    c->fields[i].descriptor);
2566                 if (!c->fields[i].parseddesc)
2567                         goto return_exception;
2568         }
2569
2570         /* parse method descriptors */
2571
2572         for (i = 0; i < c->methodscount; i++) {
2573                 methodinfo *m = &c->methods[i];
2574                 m->parseddesc =
2575                         descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2576                                                                                                         m->flags, class_get_self_classref(m->class));
2577                 if (!m->parseddesc)
2578                         goto return_exception;
2579
2580                 for (j = 0; j < m->exceptiontablelength; j++) {
2581                         if (!m->exceptiontable[j].catchtype.any)
2582                                 continue;
2583                         if ((m->exceptiontable[j].catchtype.ref =
2584                                  descriptor_pool_lookup_classref(descpool,
2585                                                 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2586                                 goto return_exception;
2587                 }
2588
2589                 for (j = 0; j < m->thrownexceptionscount; j++) {
2590                         if (!m->thrownexceptions[j].any)
2591                                 continue;
2592                         if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2593                                                 (utf *) m->thrownexceptions[j].any)) == NULL)
2594                                 goto return_exception;
2595                 }
2596         }
2597
2598         /* parse the loaded descriptors */
2599
2600         for (i = 0; i < c->cpcount; i++) {
2601                 constant_FMIref *fmi;
2602                 s4               index;
2603                 
2604                 switch (c->cptags[i]) {
2605                 case CONSTANT_Fieldref:
2606                         fmi = (constant_FMIref *) c->cpinfos[i];
2607                         fmi->parseddesc.fd =
2608                                 descriptor_pool_parse_field_descriptor(descpool,
2609                                                                                                            fmi->descriptor);
2610                         if (!fmi->parseddesc.fd)
2611                                 goto return_exception;
2612                         index = (int) (size_t) fmi->classref;
2613                         fmi->classref =
2614                                 (constant_classref *) class_getconstant(c, index,
2615                                                                                                                 CONSTANT_Class);
2616                         if (!fmi->classref)
2617                                 goto return_exception;
2618                         break;
2619                 case CONSTANT_Methodref:
2620                 case CONSTANT_InterfaceMethodref:
2621                         fmi = (constant_FMIref *) c->cpinfos[i];
2622                         index = (int) (size_t) fmi->classref;
2623                         fmi->classref =
2624                                 (constant_classref *) class_getconstant(c, index,
2625                                                                                                                 CONSTANT_Class);
2626                         if (!fmi->classref)
2627                                 goto return_exception;
2628                         fmi->parseddesc.md =
2629                                 descriptor_pool_parse_method_descriptor(descpool,
2630                                                                                                                 fmi->descriptor,
2631                                                                                                                 ACC_UNDEF,
2632                                                                                                                 fmi->classref);
2633                         if (!fmi->parseddesc.md)
2634                                 goto return_exception;
2635                         break;
2636                 }
2637         }
2638
2639         /* Check if all fields and methods can be uniquely
2640          * identified by (name,descriptor). */
2641
2642         if (opt_verify) {
2643                 /* We use a hash table here to avoid making the
2644                  * average case quadratic in # of methods, fields.
2645                  */
2646                 static int shift = 0;
2647                 u2 *hashtab;
2648                 u2 *next; /* for chaining colliding hash entries */
2649                 size_t len;
2650                 size_t hashlen;
2651                 u2 index;
2652                 u2 old;
2653
2654                 /* Allocate hashtable */
2655                 len = c->methodscount;
2656                 if (len < c->fieldscount) len = c->fieldscount;
2657                 hashlen = 5 * len;
2658                 hashtab = MNEW(u2,(hashlen + len));
2659                 next = hashtab + hashlen;
2660
2661                 /* Determine bitshift (to get good hash values) */
2662                 if (!shift) {
2663                         len = sizeof(utf);
2664                         while (len) {
2665                                 len >>= 1;
2666                                 shift++;
2667                         }
2668                 }
2669
2670                 /* Check fields */
2671                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2672
2673                 for (i = 0; i < c->fieldscount; ++i) {
2674                         fieldinfo *fi = c->fields + i;
2675
2676                         /* It's ok if we lose bits here */
2677                         index = ((((size_t) fi->name) +
2678                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2679
2680                         if ((old = hashtab[index])) {
2681                                 old--;
2682                                 next[i] = old;
2683                                 do {
2684                                         if (c->fields[old].name == fi->name &&
2685                                                 c->fields[old].descriptor == fi->descriptor) {
2686                                                 *exceptionptr =
2687                                                         new_classformaterror(c,
2688                                                                                                  "Repetitive field name/signature");
2689
2690                                                 goto return_exception;
2691                                         }
2692                                 } while ((old = next[old]));
2693                         }
2694                         hashtab[index] = i + 1;
2695                 }
2696                 
2697                 /* Check methods */
2698                 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2699
2700                 for (i = 0; i < c->methodscount; ++i) {
2701                         methodinfo *mi = c->methods + i;
2702
2703                         /* It's ok if we lose bits here */
2704                         index = ((((size_t) mi->name) +
2705                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2706
2707                         /*{ JOWENN
2708                                 int dbg;
2709                                 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2710                                         printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2711                                 }
2712                         }*/
2713
2714                         if ((old = hashtab[index])) {
2715                                 old--;
2716                                 next[i] = old;
2717                                 do {
2718                                         if (c->methods[old].name == mi->name &&
2719                                                 c->methods[old].descriptor == mi->descriptor) {
2720                                                 *exceptionptr =
2721                                                         new_classformaterror(c,
2722                                                                                                  "Repetitive method name/signature");
2723
2724                                                 goto return_exception;
2725                                         }
2726                                 } while ((old = next[old]));
2727                         }
2728                         hashtab[index] = i + 1;
2729                 }
2730                 
2731                 MFREE(hashtab, u2, (hashlen + len));
2732         }
2733
2734 #if defined(STATISTICS)
2735         if (opt_stat) {
2736                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2737                 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2738                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2739         }
2740 #endif
2741
2742         /* load attribute structures */
2743
2744         if (!check_classbuffer_size(cb, 2))
2745                 goto return_exception;
2746
2747         if (!load_attributes(cb, suck_u2(cb)))
2748                 goto return_exception;
2749
2750 #if 0
2751         /* Pre java 1.5 version don't check this. This implementation is like
2752            java 1.5 do it: for class file version 45.3 we don't check it, older
2753            versions are checked.
2754          */
2755         if ((ma == 45 && mi > 3) || ma > 45) {
2756                 /* check if all data has been read */
2757                 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2758
2759                 if (classdata_left > 0) {
2760                         *exceptionptr =
2761                                 new_classformaterror(c, "Extra bytes at the end of class file");
2762                         goto return_exception;
2763                 }
2764         }
2765 #endif
2766
2767         /* release dump area */
2768
2769         dump_release(dumpsize);
2770         
2771         if (loadverbose)
2772                 log_message_class("Loading done class: ", c);
2773
2774         LOADER_DEC();
2775         return c;
2776
2777 return_exception:
2778         /* release dump area */
2779
2780         dump_release(dumpsize);
2781
2782         /* an exception has been thrown */
2783
2784         LOADER_DEC();
2785         return NULL;
2786 }
2787
2788
2789 /* load_newly_created_array ****************************************************
2790
2791    Load a newly created array class.
2792
2793         RETURN VALUE:
2794             c....................the array class C has been loaded
2795                 other classinfo......the array class was found in the class cache, 
2796                                      C has been freed
2797             NULL.................an exception has been thrown
2798
2799         Note:
2800                 This is an internal function. Do not use it unless you know exactly
2801                 what you are doing!
2802
2803                 Use one of the load_class_... functions for general array class loading.
2804
2805 *******************************************************************************/
2806
2807 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2808 {
2809         classinfo         *comp = NULL;
2810         methodinfo        *clone;
2811         methoddesc        *clonedesc;
2812         constant_classref *classrefs;
2813         char              *text;
2814         s4                 namelen;
2815         utf               *u;
2816
2817 #ifdef LOADER_VERBOSE
2818         char logtext[MAXLOGTEXT];
2819         LOADER_INDENT(logtext);
2820         strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2821         sprintf(logtext+strlen(logtext),") loader=%p",loader);
2822         log_text(logtext);
2823 #endif
2824
2825         text = c->name->text;
2826         namelen = c->name->blength;
2827
2828         /* Check array class name */
2829
2830         if (namelen < 2 || text[0] != '[') {
2831                 *exceptionptr = new_noclassdeffounderror(c->name);
2832                 return NULL;
2833         }
2834
2835         /* Check the element type */
2836
2837         switch (text[1]) {
2838         case '[':
2839                 /* c is an array of arrays. We have to create the component class. */
2840
2841                 u = utf_new_intern(text + 1, namelen - 1);
2842                 LOADER_INC();
2843                 if (!(comp = load_class_from_classloader(u, loader))) {
2844                         LOADER_DEC();
2845                         return NULL;
2846                 }
2847                 LOADER_DEC();
2848                 LOADER_ASSERT(comp->loaded);
2849                 if (opt_eager)
2850                         if (!link_class(c))
2851                                 return NULL;
2852
2853                 /* the array's flags are that of the component class */
2854                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2855                 c->classloader = comp->classloader;
2856                 break;
2857
2858         case 'L':
2859                 /* c is an array of objects. */
2860
2861                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2862                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2863                         *exceptionptr = new_noclassdeffounderror(c->name);
2864                         return NULL;
2865                 }
2866
2867                 u = utf_new_intern(text + 2, namelen - 3);
2868
2869                 LOADER_INC();
2870                 if (!(comp = load_class_from_classloader(u, loader))) {
2871                         LOADER_DEC();
2872                         return NULL;
2873                 }
2874                 LOADER_DEC();
2875                 LOADER_ASSERT(comp->loaded);
2876                 if (opt_eager)
2877                         if (!link_class(c))
2878                                 return NULL;
2879
2880                 /* the array's flags are that of the component class */
2881                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2882                 c->classloader = comp->classloader;
2883                 break;
2884
2885         default:
2886                 /* c is an array of a primitive type */
2887
2888                 /* check for cases like `[II' */
2889                 if (namelen > 2) {
2890                         *exceptionptr = new_noclassdeffounderror(c->name);
2891                         return NULL;
2892                 }
2893
2894                 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2895                 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2896                 c->classloader = NULL;
2897         }
2898
2899         LOADER_ASSERT(class_java_lang_Object);
2900         LOADER_ASSERT(class_java_lang_Cloneable);
2901         LOADER_ASSERT(class_java_io_Serializable);
2902
2903         /* setup the array class */
2904
2905         c->super.cls = class_java_lang_Object;
2906
2907     c->interfacescount = 2;
2908     c->interfaces = MNEW(classref_or_classinfo, 2);
2909
2910         if (opt_eager) {
2911                 classinfo *tc;
2912
2913                 tc = class_java_lang_Cloneable;
2914                 LOADER_ASSERT(tc->loaded);
2915                 list_addfirst(&unlinkedclasses, tc);
2916                 c->interfaces[0].cls = tc;
2917
2918                 tc = class_java_io_Serializable;
2919                 LOADER_ASSERT(tc->loaded);
2920                 list_addfirst(&unlinkedclasses, tc);
2921                 c->interfaces[1].cls = tc;
2922
2923         } else {
2924                 c->interfaces[0].cls = class_java_lang_Cloneable;
2925                 c->interfaces[1].cls = class_java_io_Serializable;
2926         }
2927
2928         c->methodscount = 1;
2929         c->methods = MNEW(methodinfo, c->methodscount);
2930
2931         classrefs = MNEW(constant_classref, 2);
2932         CLASSREF_INIT(classrefs[0], c, c->name);
2933         CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2934
2935         /* create descriptor for clone method */
2936         /* we need one paramslot which is reserved for the 'this' parameter */
2937         clonedesc = NEW(methoddesc);
2938         clonedesc->returntype.type = TYPE_ADDRESS;
2939         clonedesc->returntype.classref = classrefs + 1;
2940         clonedesc->returntype.arraydim = 0;
2941         /* initialize params to "empty", add real params below in
2942            descriptor_params_from_paramtypes */
2943         clonedesc->paramcount = 0;
2944         clonedesc->paramslots = 0;
2945         clonedesc->paramtypes[0].classref = classrefs + 0;
2946
2947         /* create methodinfo */
2948
2949         clone = c->methods;
2950         MSET(clone, 0, methodinfo, 1);
2951
2952 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2953         initObjectLock(&clone->header);
2954 #endif
2955
2956         /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter 
2957            related) */
2958         clone->flags = ACC_PUBLIC | ACC_NATIVE;
2959         clone->name = utf_clone;
2960         clone->descriptor = utf_void__java_lang_Object;
2961         clone->parseddesc = clonedesc;
2962         clone->class = c;
2963         clone->monoPoly = MONO;
2964
2965         /* parse the descriptor to get the register allocation */
2966
2967         if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2968                 return false;
2969
2970         clone->entrypoint =
2971                 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2972
2973         /* XXX: field: length? */
2974
2975         /* array classes are not loaded from class files */
2976
2977         c->loaded = true;
2978         c->parseddescs = (u1 *) clonedesc;
2979         c->parseddescsize = sizeof(methodinfo);
2980         c->classrefs = classrefs;
2981         c->classrefcount = 1;
2982
2983         /* insert class into the loaded class cache */
2984         /* XXX free classinfo if NULL returned? */
2985
2986         return classcache_store(loader,c,true);
2987 }
2988
2989
2990 /****************** Function: class_resolvefield_int ***************************
2991
2992     This is an internally used helper function. Do not use this directly.
2993
2994         Tries to resolve a field having the given name and type.
2995     If the field cannot be resolved, NULL is returned.
2996
2997 *******************************************************************************/
2998
2999 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
3000 {
3001         fieldinfo *fi;
3002         s4         i;
3003
3004         /* search for field in class c */
3005
3006         for (i = 0; i < c->fieldscount; i++) { 
3007                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
3008                         return &(c->fields[i]);
3009                 }
3010     }
3011
3012         /* try superinterfaces recursively */
3013
3014         for (i = 0; i < c->interfacescount; i++) {
3015                 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
3016                 if (fi)
3017                         return fi;
3018         }
3019
3020         /* try superclass */
3021
3022         if (c->super.cls)
3023                 return class_resolvefield_int(c->super.cls, name, desc);
3024
3025         /* not found */
3026
3027         return NULL;
3028 }
3029
3030
3031 /********************* Function: class_resolvefield ***************************
3032         
3033         Resolves a reference from REFERER to a field with NAME and DESC in class C.
3034
3035     If the field cannot be resolved the return value is NULL. If EXCEPT is
3036     true *exceptionptr is set, too.
3037
3038 *******************************************************************************/
3039
3040 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
3041                                                           classinfo *referer, bool except)
3042 {
3043         fieldinfo *fi;
3044
3045         /* XXX resolve class c */
3046         /* XXX check access from REFERER to C */
3047         
3048         fi = class_resolvefield_int(c, name, desc);
3049
3050         if (!fi) {
3051                 if (except)
3052                         *exceptionptr =
3053                                 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
3054                                                                                  name);
3055
3056                 return NULL;
3057         }
3058
3059         /* XXX check access rights */
3060
3061         return fi;
3062 }
3063
3064
3065 /* class_findmethod ************************************************************
3066         
3067    Searches a 'classinfo' structure for a method having the given name
3068    and descriptor. If descriptor is NULL, it is ignored.
3069
3070 *******************************************************************************/
3071
3072 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3073 {
3074         methodinfo *m;
3075         s4          i;
3076
3077         for (i = 0; i < c->methodscount; i++) {
3078                 m = &(c->methods[i]);
3079
3080                 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
3081                         return m;
3082         }
3083
3084         return NULL;
3085 }
3086
3087
3088 /************************* Function: class_findmethod_approx ******************
3089         
3090         like class_findmethod but ignores the return value when comparing the
3091         descriptor.
3092
3093 *******************************************************************************/
3094
3095 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3096 {
3097         s4 i;
3098
3099         for (i = 0; i < c->methodscount; i++) {
3100                 if (c->methods[i].name == name) {
3101                         utf *meth_descr = c->methods[i].descriptor;
3102                         
3103                         if (desc == NULL) 
3104                                 /* ignore type */
3105                                 return &(c->methods[i]);
3106
3107                         if (desc->blength <= meth_descr->blength) {
3108                                 /* current position in utf text   */
3109                                 char *desc_utf_ptr = desc->text;      
3110                                 char *meth_utf_ptr = meth_descr->text;                                    
3111                                 /* points behind utf strings */
3112                                 char *desc_end = UTF_END(desc);         
3113                                 char *meth_end = UTF_END(meth_descr);   
3114                                 char ch;
3115
3116                                 /* compare argument types */
3117                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3118
3119                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3120                                                 break; /* no match */
3121
3122                                         if (ch == ')')
3123                                                 return &(c->methods[i]); /* all parameter types equal */
3124                                 }
3125                         }
3126                 }
3127         }
3128
3129         return NULL;
3130 }
3131
3132
3133 /***************** Function: class_resolvemethod_approx ***********************
3134         
3135         Searches a class and every super class for a method (without paying
3136         attention to the return value)
3137
3138 *******************************************************************************/
3139
3140 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3141 {
3142         while (c) {
3143                 /* search for method (ignore returntype) */
3144                 methodinfo *m = class_findmethod_approx(c, name, desc);
3145                 /* method found */
3146                 if (m) return m;
3147                 /* search superclass */
3148                 c = c->super.cls;
3149         }
3150
3151         return NULL;
3152 }
3153
3154
3155 /* class_resolvemethod *********************************************************
3156         
3157    Searches a class and it's super classes for a method.
3158
3159    Superinterfaces are *not* searched.
3160
3161 *******************************************************************************/
3162
3163 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3164 {
3165         methodinfo *m;
3166
3167         while (c) {
3168                 m = class_findmethod(c, name, desc);
3169
3170                 if (m)
3171                         return m;
3172
3173                 c = c->super.cls;
3174         }
3175
3176         return NULL;
3177 }
3178
3179
3180 /* class_resolveinterfacemethod_intern *****************************************
3181
3182    Internally used helper function. Do not use this directly.
3183
3184 *******************************************************************************/
3185
3186 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
3187                                                                                                            utf *name, utf *desc)
3188 {
3189         methodinfo *m;
3190         s4          i;
3191         
3192         m = class_findmethod(c, name, desc);
3193
3194         if (m)
3195                 return m;
3196
3197         /* try the superinterfaces */
3198
3199         for (i = 0; i < c->interfacescount; i++) {
3200                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3201                                                                                                 name, desc);
3202
3203                 if (m)
3204                         return m;
3205         }
3206         
3207         return NULL;
3208 }
3209
3210 /* class_resolveinterfacemethod ************************************************
3211
3212    Resolves a reference from REFERER to a method with NAME and DESC in
3213    interface C.
3214
3215    If the method cannot be resolved the return value is NULL. If
3216    EXCEPT is true *exceptionptr is set, too.
3217
3218 *******************************************************************************/
3219
3220 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3221                                                                                  classinfo *referer, bool except)
3222 {
3223         methodinfo *mi;
3224
3225         /* XXX resolve class c */
3226         /* XXX check access from REFERER to C */
3227         
3228         if (!(c->flags & ACC_INTERFACE)) {
3229                 if (except)
3230                         *exceptionptr =
3231                                 new_exception(string_java_lang_IncompatibleClassChangeError);
3232
3233                 return NULL;
3234         }
3235
3236         mi = class_resolveinterfacemethod_intern(c, name, desc);
3237
3238         if (mi)
3239                 return mi;
3240
3241         /* try class java.lang.Object */
3242
3243         mi = class_findmethod(class_java_lang_Object, name, desc);
3244
3245         if (mi)
3246                 return mi;
3247
3248         if (except)
3249                 *exceptionptr =
3250                         new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3251
3252         return NULL;
3253 }
3254
3255
3256 /* class_resolveclassmethod ****************************************************
3257         
3258    Resolves a reference from REFERER to a method with NAME and DESC in
3259    class C.
3260
3261    If the method cannot be resolved the return value is NULL. If
3262    EXCEPT is true *exceptionptr is set, too.
3263
3264 *******************************************************************************/
3265
3266 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3267                                                                          classinfo *referer, bool except)
3268 {
3269         classinfo  *cls;
3270         methodinfo *mi;
3271         s4          i;
3272         char       *msg;
3273         s4          msglen;
3274
3275         /* XXX resolve class c */
3276         /* XXX check access from REFERER to C */
3277         
3278 /*      if (c->flags & ACC_INTERFACE) { */
3279 /*              if (except) */
3280 /*                      *exceptionptr = */
3281 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
3282 /*              return NULL; */
3283 /*      } */
3284
3285         /* try class c and its superclasses */
3286
3287         cls = c;
3288
3289         while (cls) {
3290                 mi = class_findmethod(cls, name, desc);
3291
3292                 if (mi)
3293                         goto found;
3294
3295                 cls = cls->super.cls;
3296         }
3297
3298         /* try the superinterfaces */
3299
3300         for (i = 0; i < c->interfacescount; i++) {
3301                 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3302                                                                                                  name, desc);
3303
3304                 if (mi)
3305                         goto found;
3306         }
3307         
3308         if (except) {
3309                 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
3310                         utf_strlen(desc) + strlen("0");
3311
3312                 msg = MNEW(char, msglen);
3313
3314                 utf_sprint(msg, c->name);
3315                 strcat(msg, ".");
3316                 utf_sprint(msg + strlen(msg), name);
3317                 utf_sprint(msg + strlen(msg), desc);
3318
3319                 *exceptionptr =
3320                         new_exception_message(string_java_lang_NoSuchMethodError, msg);
3321
3322                 MFREE(msg, char, msglen);
3323         }
3324
3325         return NULL;
3326
3327  found:
3328         if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3329                 if (except)
3330                         *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3331
3332                 return NULL;
3333         }
3334
3335         /* XXX check access rights */
3336
3337         return mi;
3338 }
3339
3340
3341 /************************* Function: class_issubclass **************************
3342
3343         Checks if sub is a descendant of super.
3344         
3345 *******************************************************************************/
3346
3347 bool class_issubclass(classinfo *sub, classinfo *super)
3348 {
3349         for (;;) {
3350                 if (!sub) return false;
3351                 if (sub == super) return true;
3352                 sub = sub->super.cls;
3353         }
3354 }
3355
3356
3357 void class_showconstanti(classinfo *c, int ii) 
3358 {
3359         u4 i = ii;
3360         voidptr e;
3361                 
3362         e = c->cpinfos [i];
3363         printf ("#%d:  ", (int) i);
3364         if (e) {
3365                 switch (c->cptags [i]) {
3366                 case CONSTANT_Class:
3367                         printf("Classreference -> ");
3368                         utf_display(((constant_classref*)e)->name);
3369                         break;
3370                                 
3371                 case CONSTANT_Fieldref:
3372                         printf("Fieldref -> "); goto displayFMIi;
3373                 case CONSTANT_Methodref:
3374                         printf("Methodref -> "); goto displayFMIi;
3375                 case CONSTANT_InterfaceMethodref:
3376                         printf("InterfaceMethod -> "); goto displayFMIi;
3377                 displayFMIi:
3378                         {
3379                                 constant_FMIref *fmi = e;
3380                                 utf_display(fmi->classref->name);
3381                                 printf(".");
3382                                 utf_display(fmi->name);
3383                                 printf(" ");
3384                                 utf_display(fmi->descriptor);
3385                         }
3386                         break;
3387
3388                 case CONSTANT_String:
3389                         printf("String -> ");
3390                         utf_display(e);
3391                         break;
3392                 case CONSTANT_Integer:
3393                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3394                         break;
3395                 case CONSTANT_Float:
3396                         printf("Float -> %f", ((constant_float*)e)->value);
3397                         break;
3398                 case CONSTANT_Double:
3399                         printf("Double -> %f", ((constant_double*)e)->value);
3400                         break;
3401                 case CONSTANT_Long:
3402                         {
3403                                 u8 v = ((constant_long*)e)->value;
3404 #if U8_AVAILABLE
3405                                 printf("Long -> %ld", (long int) v);
3406 #else
3407                                 printf("Long -> HI: %ld, LO: %ld\n", 
3408                                             (long int) v.high, (long int) v.low);
3409 #endif 
3410                         }
3411                         break;
3412                 case CONSTANT_NameAndType:
3413                         { 
3414                                 constant_nameandtype *cnt = e;
3415                                 printf("NameAndType: ");
3416                                 utf_display(cnt->name);
3417                                 printf(" ");
3418                                 utf_display(cnt->descriptor);
3419                         }
3420                         break;
3421                 case CONSTANT_Utf8:
3422                         printf("Utf8 -> ");
3423                         utf_display(e);
3424                         break;
3425                 default: 
3426                         log_text("Invalid type of ConstantPool-Entry");
3427                         assert(0);
3428                 }
3429         }
3430         printf("\n");
3431 }
3432
3433
3434 void class_showconstantpool (classinfo *c) 
3435 {
3436         u4 i;
3437         voidptr e;
3438
3439         printf ("---- dump of constant pool ----\n");
3440
3441         for (i=0; i<c->cpcount; i++) {
3442                 printf ("#%d:  ", (int) i);
3443                 
3444                 e = c -> cpinfos [i];
3445                 if (e) {
3446                         
3447                         switch (c -> cptags [i]) {
3448                         case CONSTANT_Class:
3449                                 printf ("Classreference -> ");
3450                                 utf_display ( ((constant_classref*)e) -> name );
3451                                 break;
3452                                 
3453                         case CONSTANT_Fieldref:
3454                                 printf ("Fieldref -> "); goto displayFMI;
3455                         case CONSTANT_Methodref:
3456                                 printf ("Methodref -> "); goto displayFMI;
3457                         case CONSTANT_InterfaceMethodref:
3458                                 printf ("InterfaceMethod -> "); goto displayFMI;
3459                         displayFMI:
3460                                 {
3461                                         constant_FMIref *fmi = e;
3462                                         utf_display ( fmi->classref->name );
3463                                         printf (".");
3464                                         utf_display ( fmi->name);
3465                                         printf (" ");
3466                                         utf_display ( fmi->descriptor );
3467                                 }
3468                                 break;
3469
3470                         case CONSTANT_String:
3471                                 printf ("String -> ");
3472                                 utf_display (e);
3473                                 break;
3474                         case CONSTANT_Integer:
3475                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3476                                 break;
3477                         case CONSTANT_Float:
3478                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3479                                 break;
3480                         case CONSTANT_Double:
3481                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3482                                 break;
3483                         case CONSTANT_Long:
3484                                 {
3485                                         u8 v = ((constant_long*)e) -> value;
3486 #if U8_AVAILABLE
3487                                         printf ("Long -> %ld", (long int) v);
3488 #else
3489                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3490                                                         (long int) v.high, (long int) v.low);
3491 #endif 
3492                                 }
3493                                 break;
3494                         case CONSTANT_NameAndType:
3495                                 {
3496                                         constant_nameandtype *cnt = e;
3497                                         printf ("NameAndType: ");
3498                                         utf_display (cnt->name);
3499                                         printf (" ");
3500                                         utf_display (cnt->descriptor);
3501                                 }
3502                                 break;
3503                         case CONSTANT_Utf8:
3504                                 printf ("Utf8 -> ");
3505                                 utf_display (e);
3506                                 break;
3507                         default: 
3508                                 log_text("Invalid type of ConstantPool-Entry");
3509                                 assert(0);
3510                         }
3511                 }
3512
3513                 printf ("\n");
3514         }
3515 }
3516
3517
3518
3519 /********** Function: class_showmethods   (debugging only) *************/
3520
3521 void class_showmethods (classinfo *c)
3522 {
3523         s4 i;
3524         
3525         printf ("--------- Fields and Methods ----------------\n");
3526         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3527
3528         printf ("This: "); utf_display (c->name); printf ("\n");
3529         if (c->super.cls) {
3530                 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3531                 }
3532         printf ("Index: %d\n", c->index);
3533         
3534         printf ("interfaces:\n");       
3535         for (i=0; i < c-> interfacescount; i++) {
3536                 printf ("   ");
3537                 utf_display (c -> interfaces[i].cls -> name);
3538                 printf (" (%d)\n", c->interfaces[i].cls -> index);
3539                 }
3540
3541         printf ("fields:\n");           
3542         for (i=0; i < c -> fieldscount; i++) {
3543                 field_display (&(c -> fields[i]));
3544                 }
3545
3546         printf ("methods:\n");
3547         for (i=0; i < c -> methodscount; i++) {
3548                 methodinfo *m = &(c->methods[i]);
3549                 if ( !(m->flags & ACC_STATIC)) 
3550                         printf ("vftblindex: %d   ", m->vftblindex);
3551
3552                 method_display ( m );
3553
3554                 }
3555
3556         printf ("Virtual function table:\n");
3557         for (i=0; i<c->vftbl->vftbllength; i++) {
3558                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3559                 }
3560
3561 }
3562
3563
3564 /* loader_close ****************************************************************
3565
3566    Frees all resources.
3567         
3568 *******************************************************************************/
3569
3570 void loader_close(void)
3571 {
3572         /* empty */
3573 }
3574
3575
3576 /*
3577  * These are local overrides for various environment variables in Emacs.
3578  * Please do not remove this and leave it at the end of the file, where
3579  * Emacs will automagically detect them.
3580  * ---------------------------------------------------------------------
3581  * Local variables:
3582  * mode: c
3583  * indent-tabs-mode: t
3584  * c-basic-offset: 4
3585  * tab-width: 4
3586  * End:
3587  */