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