added checkaccess parameter to resolve_class* functions
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native 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             Roman Obermaisser
29             Andreas Krall
30
31    Changes: Christian Thalinger
32
33    $Id: native.c 2788 2005-06-22 16:08:51Z edwin $
34
35 */
36
37
38 #include <assert.h>
39
40 #if !defined(STATIC_CLASSPATH)
41 # include "libltdl/ltdl.h"
42 #endif
43
44 #include "config.h"
45 #include "types.h"
46 #include "cacao/cacao.h"
47 #include "mm/memory.h"
48 #include "native/jni.h"
49 #include "native/native.h"
50 #include "native/include/java_lang_Throwable.h"
51 #include "toolbox/logging.h"
52 #include "vm/builtin.h"
53 #include "vm/exceptions.h"
54 #include "vm/global.h"
55 #include "vm/loader.h"
56 #include "vm/options.h"
57 #include "vm/resolve.h"
58 #include "vm/stringlocal.h"
59 #include "vm/tables.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/jit.h"
62
63
64 /* include table of native functions ******************************************/
65
66 #include "native/include/java_lang_Cloneable.h"
67 #include "native/include/java_util_Properties.h"
68 #include "native/include/java_io_InputStream.h"
69 #include "native/include/java_io_PrintStream.h"
70
71 #include "native/include/gnu_classpath_VMStackWalker.h"
72 #include "native/include/gnu_classpath_VMSystemProperties.h"
73 #include "native/include/java_lang_Class.h"
74 #include "native/include/java_lang_Object.h"
75 #include "native/include/java_lang_VMClass.h"
76 #include "native/include/java_lang_VMClassLoader.h"
77 #include "native/include/java_lang_VMObject.h"
78 #include "native/include/java_lang_VMRuntime.h"
79 #include "native/include/java_lang_VMString.h"
80 #include "native/include/java_lang_VMSystem.h"
81 #include "native/include/java_lang_VMThread.h"
82 #include "native/include/java_lang_VMThrowable.h"
83 #include "native/include/java_lang_reflect_Constructor.h"
84 #include "native/include/java_lang_reflect_Field.h"
85 #include "native/include/java_lang_reflect_Proxy.h"
86 #include "native/include/java_lang_reflect_Method.h"
87 #include "native/include/java_security_VMAccessController.h"
88
89 #if defined(STATIC_CLASSPATH)
90
91 /* these are required to prevent compiler warnings */
92
93 #include "native/include/java_net_DatagramPacket.h"
94 #include "native/include/java_net_InetAddress.h"
95 #include "native/include/java_net_SocketImpl.h"
96
97 #include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
98 #include "native/include/gnu_java_net_PlainSocketImpl.h"
99 #include "native/include/gnu_java_nio_PipeImpl.h"
100 #include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
101 #include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
102 #include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
103 #include "native/include/java_lang_VMProcess.h"
104 #include "native/include/java_nio_MappedByteBufferImpl.h"
105 #include "native/include/java_nio_channels_spi_SelectorProvider.h"
106
107 /* now include the native table */
108
109 #include "native/nativetable.inc"
110
111 #else /* defined(STATIC_CLASSPATH) */
112
113 /* Ensure that symbols for functions implemented within CACAO are used and    */
114 /* exported to dlopen.                                                        */
115
116 static functionptr dummynativetable[] = {
117         (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
118
119         (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
120
121         (functionptr) Java_java_lang_VMClass_isInstance,
122         (functionptr) Java_java_lang_VMClass_isAssignableFrom,
123         (functionptr) Java_java_lang_VMClass_isInterface,
124         (functionptr) Java_java_lang_VMClass_isPrimitive,
125         (functionptr) Java_java_lang_VMClass_getName,
126         (functionptr) Java_java_lang_VMClass_getSuperclass,
127         (functionptr) Java_java_lang_VMClass_getInterfaces,
128         (functionptr) Java_java_lang_VMClass_getComponentType,
129         (functionptr) Java_java_lang_VMClass_getModifiers,
130         (functionptr) Java_java_lang_VMClass_getDeclaringClass,
131         (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
132         (functionptr) Java_java_lang_VMClass_getDeclaredFields,
133         (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
134         (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
135         (functionptr) Java_java_lang_VMClass_getClassLoader,
136         (functionptr) Java_java_lang_VMClass_forName,
137         (functionptr) Java_java_lang_VMClass_isArray,
138         (functionptr) Java_java_lang_VMClass_initialize,
139         (functionptr) Java_java_lang_VMClass_loadArrayClass,
140         (functionptr) Java_java_lang_VMClass_throwException,
141
142         (functionptr) Java_java_lang_VMClassLoader_defineClass,
143         (functionptr) Java_java_lang_VMClassLoader_resolveClass,
144         (functionptr) Java_java_lang_VMClassLoader_loadClass,
145         (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
146         (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
147
148         (functionptr) Java_java_lang_VMObject_getClass,
149         (functionptr) Java_java_lang_VMObject_clone,
150         (functionptr) Java_java_lang_VMObject_notify,
151         (functionptr) Java_java_lang_VMObject_notifyAll,
152         (functionptr) Java_java_lang_VMObject_wait,
153
154         (functionptr) Java_java_lang_VMRuntime_availableProcessors,
155         (functionptr) Java_java_lang_VMRuntime_freeMemory,
156         (functionptr) Java_java_lang_VMRuntime_totalMemory,
157         (functionptr) Java_java_lang_VMRuntime_maxMemory,
158         (functionptr) Java_java_lang_VMRuntime_gc,
159         (functionptr) Java_java_lang_VMRuntime_runFinalization,
160         (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
161         (functionptr) Java_java_lang_VMRuntime_traceInstructions,
162         (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
163         (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
164         (functionptr) Java_java_lang_VMRuntime_exit,
165         (functionptr) Java_java_lang_VMRuntime_nativeLoad,
166         (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
167
168         (functionptr) Java_java_lang_VMString_intern,
169
170         (functionptr) Java_java_lang_VMSystem_arraycopy,
171         (functionptr) Java_java_lang_VMSystem_identityHashCode,
172
173         (functionptr) Java_java_lang_VMThread_start,
174         (functionptr) Java_java_lang_VMThread_interrupt,
175         (functionptr) Java_java_lang_VMThread_isInterrupted,
176         (functionptr) Java_java_lang_VMThread_suspend,
177         (functionptr) Java_java_lang_VMThread_resume,
178         (functionptr) Java_java_lang_VMThread_nativeSetPriority,
179         (functionptr) Java_java_lang_VMThread_nativeStop,
180         (functionptr) Java_java_lang_VMThread_currentThread,
181         (functionptr) Java_java_lang_VMThread_yield,
182         (functionptr) Java_java_lang_VMThread_interrupted,
183         (functionptr) Java_java_lang_VMThread_holdsLock,
184
185         (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
186         (functionptr) Java_java_lang_VMThrowable_getStackTrace,
187
188         (functionptr) Java_java_lang_reflect_Constructor_getModifiers,
189         (functionptr) Java_java_lang_reflect_Constructor_constructNative,
190
191         (functionptr) Java_java_lang_reflect_Field_getModifiers,
192         (functionptr) Java_java_lang_reflect_Field_getType,
193         (functionptr) Java_java_lang_reflect_Field_get,
194         (functionptr) Java_java_lang_reflect_Field_getBoolean,
195         (functionptr) Java_java_lang_reflect_Field_getByte,
196         (functionptr) Java_java_lang_reflect_Field_getChar,
197         (functionptr) Java_java_lang_reflect_Field_getShort,
198         (functionptr) Java_java_lang_reflect_Field_getInt,
199         (functionptr) Java_java_lang_reflect_Field_getLong,
200         (functionptr) Java_java_lang_reflect_Field_getFloat,
201         (functionptr) Java_java_lang_reflect_Field_getDouble,
202         (functionptr) Java_java_lang_reflect_Field_set,
203         (functionptr) Java_java_lang_reflect_Field_setBoolean,
204         (functionptr) Java_java_lang_reflect_Field_setByte,
205         (functionptr) Java_java_lang_reflect_Field_setChar,
206         (functionptr) Java_java_lang_reflect_Field_setShort,
207         (functionptr) Java_java_lang_reflect_Field_setInt,
208         (functionptr) Java_java_lang_reflect_Field_setLong,
209         (functionptr) Java_java_lang_reflect_Field_setFloat,
210         (functionptr) Java_java_lang_reflect_Field_setDouble,
211
212         (functionptr) Java_java_lang_reflect_Proxy_getProxyClass0,
213         (functionptr) Java_java_lang_reflect_Proxy_getProxyData0,
214         (functionptr) Java_java_lang_reflect_Proxy_generateProxyClass0,
215
216         (functionptr) Java_java_lang_reflect_Method_getModifiers,
217         (functionptr) Java_java_lang_reflect_Method_getReturnType,
218         (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
219         (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
220         (functionptr) Java_java_lang_reflect_Method_invokeNative,
221
222         (functionptr) Java_java_security_VMAccessController_getStack,
223 };
224
225 #endif /* defined(STATIC_CLASSPATH) */
226
227
228 /************* use classinfo structure as java.lang.Class object **************/
229
230 void use_class_as_object(classinfo *c) 
231 {
232         if (!c->classvftbl) {
233                 /* is the class loaded */
234                 if (!c->loaded) {
235 /*                      if (!class_load(c)) */
236 /*                              throw_exception_exit(); */
237                         log_text("use_class_as_object: class_load should not happen");
238                         assert(0);
239                 }
240
241                 /* is the class linked */
242                 if (!c->linked)
243                         if (!link_class(c))
244                                 throw_exception_exit();
245
246                 assert(class_java_lang_Class);
247
248                 c->header.vftbl = class_java_lang_Class->vftbl;
249                 c->classvftbl = true;
250         }
251 }
252
253
254 /************************** tables for methods ********************************/
255
256 #undef JOWENN_DEBUG
257 #undef JOWENN_DEBUG1
258
259 #ifdef STATIC_CLASSPATH
260 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
261
262 /* table for fast string comparison */
263 static nativecompref nativecomptable[NATIVETABLESIZE];
264
265 /* string comparsion table initialized */
266 static bool nativecompdone = false;
267 #endif
268
269
270 /* XXX don't define this in a header file!!! */
271
272 static struct nativeCall nativeCalls[] =
273 {
274 #include "nativecalls.inc"
275 };
276
277 #define NATIVECALLSSIZE    (sizeof(nativeCalls) / sizeof(struct nativeCall))
278
279 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
280
281
282 /* global variables ***********************************************************/
283
284 static hashtable library_hash;
285 static lt_dlhandle mainhandle;
286
287
288 /* native_loadclasses **********************************************************
289
290    Load classes required for native methods.
291
292 *******************************************************************************/
293
294 bool native_init(void)
295 {
296 #if !defined(STATIC_CLASSPATH)
297         void *p;
298
299         /* We need to access the dummy native table, not only to remove a warning */
300         /* but to be sure that the table is not optimized away (gcc does this     */
301         /* since 3.4).                                                            */
302
303         p = &dummynativetable;
304
305         /* initialize libltdl */
306
307         if (lt_dlinit()) {
308                 /* XXX how can we throw an exception here? */
309                 log_text(lt_dlerror());
310
311                 return false;
312         }
313
314         /* get the handle for the main program */
315
316         if (!(mainhandle = lt_dlopen(NULL)))
317                 return false;
318
319         /* initialize library hashtable, 10 entries should be enough */
320
321         init_hashtable(&library_hash, 10);
322
323 #endif
324
325         /* everything's ok */
326
327         return true;
328 }
329
330
331 /* native_library_hash_add *****************************************************
332
333    Adds an entry to the native library hashtable.
334
335 *******************************************************************************/
336
337 #if !defined(STATIC_CLASSPATH)
338 void native_library_hash_add(utf *filename, java_objectheader *loader,
339                                                          lt_dlhandle handle)
340 {
341         library_hash_loader_entry *le;
342         library_hash_name_entry   *ne;      /* library name                       */
343         u4   key;                           /* hashkey                            */
344         u4   slot;                          /* slot in hashtable                  */
345
346         /* normally addresses are aligned to 4, 8 or 16 bytes */
347
348         key = ((u4) (ptrint) loader) >> 4;         /* align to 16-byte boundaries */
349         slot = key & (library_hash.size - 1);
350         le = library_hash.ptr[slot];
351
352         /* search external hash chain for the entry */
353
354         while (le) {
355                 if (le->loader == loader)
356                         break;
357
358                 le = le->hashlink;                  /* next element in external chain */
359         }
360
361         /* no loader found? create a new entry */
362
363         if (!le) {
364                 le = NEW(library_hash_loader_entry);
365
366                 le->loader = loader;
367                 le->namelink = NULL;
368
369                 /* insert entry into hashtable */
370
371                 le->hashlink = (library_hash_loader_entry *) library_hash.ptr[slot];
372                 library_hash.ptr[slot] = le;
373
374                 /* update number of hashtable-entries */
375
376                 library_hash.entries++;
377         }
378
379
380         /* search for library name */
381
382         ne = le->namelink;
383
384         while (ne) {
385                 if (ne->name == filename)
386                         return;
387
388                 ne = ne->hashlink;                  /* next element in external chain */
389         }
390
391         /* not found? add the library name to the classloader */
392
393         ne = NEW(library_hash_name_entry);
394
395         ne->name = filename;
396         ne->handle = handle;
397
398         /* insert entry into external chain */
399
400         ne->hashlink = le->namelink;
401         le->namelink = ne;
402 }
403 #endif /* !defined(STATIC_CLASSPATH) */
404
405
406 /* native_findfunction *********************************************************
407
408    Looks up a method (must have the same class name, method name,
409    descriptor and 'static'ness) and returns a function pointer to it.
410    Returns: function pointer or NULL (if there is no such method)
411
412    Remark: For faster operation, the names/descriptors are converted
413    from C strings to Unicode the first time this function is called.
414
415 *******************************************************************************/
416
417 #if defined(STATIC_CLASSPATH)
418 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
419                                                                 bool isstatic)
420 {
421         int i;
422         /* entry of table for fast string comparison */
423         struct nativecompref *n;
424         /* for warning message if no function is found */
425         char *buffer;                   
426         int buffer_len;
427
428         isstatic = isstatic ? true : false;
429         
430         if (!nativecompdone) {
431                 for (i = 0; i < NATIVETABLESIZE; i++) {
432                         nativecomptable[i].classname  = 
433                                 utf_new_char(nativetable[i].classname);
434                         nativecomptable[i].methodname = 
435                                 utf_new_char(nativetable[i].methodname);
436                         nativecomptable[i].descriptor = 
437                                 utf_new_char(nativetable[i].descriptor);
438                         nativecomptable[i].isstatic   = 
439                                 nativetable[i].isstatic;
440                         nativecomptable[i].func       = 
441                                 nativetable[i].func;
442                 }
443                 nativecompdone = true;
444         }
445
446         for (i = 0; i < NATIVETABLESIZE; i++) {
447                 n = &(nativecomptable[i]);
448
449                 if (cname == n->classname && mname == n->methodname &&
450                     desc == n->descriptor && isstatic == n->isstatic)
451                         return n->func;
452         }
453
454                 
455         /* no function was found, display warning */
456
457         buffer_len = 
458                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
459
460         buffer = MNEW(char, buffer_len);
461
462         strcpy(buffer, "warning: native function ");
463         utf_sprint(buffer + strlen(buffer), mname);
464         strcpy(buffer + strlen(buffer), ": ");
465         utf_sprint(buffer + strlen(buffer), desc);
466         strcpy(buffer + strlen(buffer), " not found in class ");
467         utf_sprint(buffer + strlen(buffer), cname);
468
469         log_text(buffer);       
470
471         MFREE(buffer, char, buffer_len);
472
473         /* keep compiler happy */
474
475         return NULL;
476 }
477 #endif /* defined(STATIC_CLASSPATH) */
478
479
480 /* native_make_overloaded_function *********************************************
481
482    XXX
483
484 *******************************************************************************/
485
486 #if !defined(STATIC_CLASSPATH)
487 static char *native_make_overloaded_function(char *name, utf *desc)
488 {
489         char *newname;
490         s4    namelen;
491         char *utf_ptr;
492         u2    c;
493         s4    i;
494
495         utf_ptr = desc->text;
496         namelen = strlen("__");
497
498         /* calculate additional length */
499
500         while ((c = utf_nextu2(&utf_ptr)) != ')') {
501                 switch (c) {
502                 case 'Z':
503                 case 'B':
504                 case 'C':
505                 case 'S':
506                 case 'I':
507                 case 'J':
508                 case 'F':
509                 case 'D':
510                         namelen++;
511                         break;
512                 case '[':
513                         namelen += 2;
514                         break;
515                 case 'L':
516                         namelen++;
517                         while (utf_nextu2(&utf_ptr) != ';')
518                                 namelen++;
519                         namelen += 2;
520                         break;
521                 case '(':
522                         break;
523                 default:
524                         assert(0);
525                 }
526         }
527
528
529         /* reallocate memory */
530
531         i = strlen(name);
532
533         newname = DMNEW(char, namelen);
534         MCOPY(newname, name, char, i);
535
536         utf_ptr = desc->text;
537
538         newname[i++] = '_';
539         newname[i++] = '_';
540
541         while ((c = utf_nextu2(&utf_ptr)) != ')') {
542                 switch (c) {
543                 case 'Z':
544                 case 'B':
545                 case 'C':
546                 case 'S':
547                 case 'J':
548                 case 'I':
549                 case 'F':
550                 case 'D':
551                         newname[i++] = c;
552                         break;
553                 case '[':
554                         newname[i++] = '_';
555                         newname[i++] = '3';
556                         break;
557                 case 'L':
558                         newname[i++] = 'L';
559                         while ((c = utf_nextu2(&utf_ptr)) != ';')
560                                 if (((c >= 'a') && (c <= 'z')) ||
561                                         ((c >= 'A') && (c <= 'Z')) ||
562                                         ((c >= '0') && (c <= '9')))
563                                         newname[i++] = c;
564                                 else
565                                         newname[i++] = '_';
566                         newname[i++] = '_';
567                         newname[i++] = '2';
568                         break;
569                 case '(':
570                         break;
571                 default:
572                         assert(0);
573                 }
574         }
575
576         /* close string */
577
578         newname[i] = '\0';
579
580         return newname;
581 }
582
583
584 /* native_resolve_function *****************************************************
585
586    Resolves a native function, maybe from a dynamic library.
587
588 *******************************************************************************/
589
590 functionptr native_resolve_function(methodinfo *m)
591 {
592         lt_ptr                     sym;
593         char                      *name;
594         char                      *newname;
595         s4                         namelen;
596         char                      *utf_ptr;
597         char                      *utf_endptr;
598         s4                         dumpsize;
599         library_hash_loader_entry *le;
600         library_hash_name_entry   *ne;
601         u4                         key;     /* hashkey                            */
602         u4                         slot;    /* slot in hashtable                  */
603         u4                         i;
604
605
606         /* calculate length of native function name */
607
608         namelen = strlen("Java_") + utf_strlen(m->class->name) + strlen("_") +
609                 utf_strlen(m->name) + strlen("0");
610
611         /* check for underscores in class name */
612
613         utf_ptr = m->class->name->text;
614         utf_endptr = UTF_END(m->class->name);
615
616         while (utf_ptr < utf_endptr)
617                 if (utf_nextu2(&utf_ptr) == '_')
618                         namelen++;
619
620         /* check for underscores in method name */
621
622         utf_ptr = m->name->text;
623         utf_endptr = UTF_END(m->name);
624
625         while (utf_ptr < utf_endptr)
626                 if (utf_nextu2(&utf_ptr) == '_')
627                         namelen++;
628
629         /* allocate memory */
630
631         dumpsize = dump_size();
632
633         name = DMNEW(char, namelen);
634
635
636         /* generate name of native functions */
637
638         strcpy(name, "Java_");
639         i = strlen("Java_");
640
641         utf_ptr = m->class->name->text;
642         utf_endptr = UTF_END(m->class->name);
643
644         for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
645                 name[i] = *utf_ptr;
646
647                 /* escape sequence for '_' is '_1' */
648
649                 if (name[i] == '_')
650                         name[++i] = '1';
651
652                 /* replace '/' with '_' */
653
654                 if (name[i] == '/')
655                         name[i] = '_';
656         }
657
658         /* seperator between class and method */
659
660         name[i++] = '_';
661
662         utf_ptr = m->name->text;
663         utf_endptr = UTF_END(m->name);
664
665         for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
666                 name[i] = *utf_ptr;
667
668                 /* escape sequence for '_' is '_1' */
669
670                 if (name[i] == '_')
671                         name[++i] = '1';
672         }
673
674         /* close string */
675
676         name[i] = '\0';
677
678
679         /* try to find the native function symbol in the main program */
680
681         if (!(sym = lt_dlsym(mainhandle, name))) {
682                 /* we didn't find the symbol yet, try to resolve an overloaded        */
683                 /* function (having the types in it's name)                           */
684
685                 newname = native_make_overloaded_function(name, m->descriptor);
686
687                 /* try to find the overloaded symbol */
688
689                 sym = lt_dlsym(mainhandle, newname);
690         }
691
692         /* if symbol not found, check the library hash entries of the classloader */
693         /* of the methods's class                                                 */
694
695         if (!sym) {
696                 /* normally addresses are aligned to 4, 8 or 16 bytes */
697
698                 key = ((u4) (ptrint) m->class->classloader) >> 4; /* align to 16-byte */
699                 slot = key & (library_hash.size - 1);
700                 le = library_hash.ptr[slot];
701
702                 /* iterate through loaders in this hash slot */
703
704                 while (le && !sym) {
705                         /* iterate through names in this loader */
706
707                         ne = le->namelink;
708                         
709                         while (ne && !sym) {
710                                 sym = lt_dlsym(ne->handle, name);
711
712                                 if (!sym)
713                                         sym = lt_dlsym(ne->handle, newname);
714
715                                 ne = ne->hashlink;
716                         }
717
718                         le = le->hashlink;
719                 }
720         }
721
722         /* no symbol found? throw exception */
723
724         if (!sym) {
725                 *exceptionptr =
726                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
727                                                                          m->name);
728                 log_text(lt_dlerror());
729         }
730
731         /* release memory */
732
733         dump_release(dumpsize);
734
735         return (functionptr) (ptrint) sym;
736 }
737 #endif /* !defined(STATIC_CLASSPATH) */
738
739
740 /****************** function class_findfield_approx ****************************
741         
742         searches in 'classinfo'-structure for a field with the
743         specified name
744
745 *******************************************************************************/
746  
747 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
748 {
749         s4 i;
750
751         for (i = 0; i < c->fieldscount; i++) {
752                 /* compare field names */
753                 if ((c->fields[i].name == name))
754                         return &(c->fields[i]);
755         }
756
757         /* field was not found, raise exception */      
758         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
759
760         return NULL;
761 }
762
763
764 s4 class_findfield_index_approx(classinfo *c, utf *name)
765 {
766         s4 i;
767
768         for (i = 0; i < c->fieldscount; i++) {
769                 /* compare field names */
770                 if ((c->fields[i].name == name))
771                         return i;
772         }
773
774         /* field was not found, raise exception */      
775         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
776
777         return -1;
778 }
779
780
781 /* native_new_and_init *********************************************************
782
783    Creates a new object on the heap and calls the initializer.
784    Returns the object pointer or NULL if memory is exhausted.
785                         
786 *******************************************************************************/
787
788 java_objectheader *native_new_and_init(classinfo *c)
789 {
790         methodinfo *m;
791         java_objectheader *o;
792
793         if (!c)
794                 return *exceptionptr;
795
796         /* create object */
797
798         o = builtin_new(c);
799         
800         if (!o)
801                 return NULL;
802
803         /* find initializer */
804
805         m = class_findmethod(c, utf_init, utf_void__void);
806                                                       
807         /* initializer not found */
808
809         if (!m)
810                 return o;
811
812         /* call initializer */
813
814         asm_calljavafunction(m, o, NULL, NULL, NULL);
815
816         return o;
817 }
818
819
820 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
821 {
822         methodinfo *m;
823         java_objectheader *o;
824
825         if (!c)
826                 return *exceptionptr;
827
828         /* create object */
829
830         o = builtin_new(c);
831
832         if (!o)
833                 return NULL;
834
835         /* find initializer */
836
837         m = class_resolveclassmethod(c,
838                                                                  utf_init,
839                                                                  utf_java_lang_String__void,
840                                                                  NULL,
841                                                                  true);
842
843         /* initializer not found */
844
845         if (!m)
846                 return NULL;
847
848         /* call initializer */
849
850         asm_calljavafunction(m, o, s, NULL, NULL);
851
852         return o;
853 }
854
855
856 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
857 {
858         methodinfo *m;
859         java_objectheader *o;
860
861         if (!c)
862                 return *exceptionptr;
863
864         /* create object */
865
866         o = builtin_new(c);
867         
868         if (!o)
869                 return NULL;
870
871         /* find initializer */
872
873         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
874
875         /* initializer not found  */
876
877         if (!m)
878                 return NULL;
879
880         /* call initializer */
881
882         asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
883
884         return o;
885 }
886
887
888 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
889 {
890         methodinfo *m;
891         java_objectheader *o;
892
893         if (!c)
894                 return *exceptionptr;
895
896         /* create object */
897
898         o = builtin_new(c);
899         
900         if (!o)
901                 return NULL;
902
903         /* find initializer */
904
905         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
906                                                       
907         /* initializer not found */
908
909         if (!m)
910                 return NULL;
911
912         /* call initializer */
913
914         asm_calljavafunction(m, o, t, NULL, NULL);
915
916         return o;
917 }
918
919
920 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
921 {
922     *dest = src;
923 #if 0
924     /* XXX this kind of copying does not work (in the general
925      * case). The interface tables would have to be copied, too. I
926      * don't see why we should make a copy anyway. -Edwin
927      */
928         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
929         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
930         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
931 #endif
932 }
933
934
935 /******************************************************************************************                                                                                                             
936
937         creates method signature (excluding return type) from array of 
938         class-objects representing the parameters of the method 
939
940 *******************************************************************************************/
941
942
943 utf *create_methodsig(java_objectarray* types, char *retType)
944 {
945     char *buffer;       /* buffer for building the desciptor */
946     char *pos;          /* current position in buffer */
947     utf *result;        /* the method signature */
948     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
949     u4 i, j;
950  
951     if (!types) return NULL;
952
953     /* determine required buffer-size */    
954     for (i = 0; i < types->header.size; i++) {
955                 classinfo *c = (classinfo *) types->data[i];
956                 buffer_size  = buffer_size + c->name->blength + 2;
957     }
958
959     if (retType) buffer_size += strlen(retType);
960
961     /* allocate buffer */
962     buffer = MNEW(char, buffer_size);
963     pos    = buffer;
964     
965     /* method-desciptor starts with parenthesis */
966     *pos++ = '(';
967
968     for (i = 0; i < types->header.size; i++) {
969                 char ch;           
970
971                 /* current argument */
972             classinfo *c = (classinfo *) types->data[i];
973
974             /* current position in utf-text */
975             char *utf_ptr = c->name->text; 
976             
977             /* determine type of argument */
978             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
979                 /* arrayclass */
980                 for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) {
981                                 *pos++ = *utf_ptr; /* copy text */
982                         }
983
984             } else {            
985                         /* check for primitive types */
986                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
987                                 char *utf_pos   = utf_ptr - 1;
988                                 char *primitive = primitivetype_table[j].wrapname;
989
990                                 /* compare text */
991                                 while (utf_pos < UTF_END(c->name)) {
992                                         if (*utf_pos++ != *primitive++) goto nomatch;
993                                 }
994
995                                 /* primitive type found */
996                                 *pos++ = primitivetype_table[j].typesig;
997                                 goto next_type;
998
999                         nomatch:
1000                                 ;
1001                         }
1002
1003                         /* no primitive type and no arrayclass, so must be object */
1004                         *pos++ = 'L';
1005
1006                         /* copy text */
1007                         for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) {
1008                                 *pos++ = *utf_ptr;
1009                         }
1010
1011                         *pos++ = ';';
1012
1013                 next_type:
1014                         ;
1015                 }  
1016     }       
1017
1018     *pos++ = ')';
1019
1020     if (retType) {
1021                 for (i = 0; i < strlen(retType); i++) {
1022                         *pos++ = retType[i];
1023                 }
1024     }
1025
1026     /* create utf-string */
1027     result = utf_new(buffer, (pos - buffer));
1028     MFREE(buffer, char, buffer_size);
1029
1030     return result;
1031 }
1032
1033
1034 /* get_parametertypes **********************************************************
1035
1036    Use the descriptor of a method to generate a java/lang/Class array
1037    which contains the classes of the parametertypes of the method.
1038
1039 *******************************************************************************/
1040
1041 java_objectarray *get_parametertypes(methodinfo *m) 
1042 {
1043         methoddesc       *md;
1044         typedesc         *paramtypes;
1045         s4                paramcount;
1046     java_objectarray *result;
1047         s4                i;
1048
1049         md = m->parseddesc;
1050
1051         /* is the descriptor fully parsed? */
1052
1053         if (!m->parseddesc->params)
1054                 if (!descriptor_params_from_paramtypes(md, m->flags))
1055                         return NULL;
1056
1057         paramtypes = md->paramtypes;
1058         paramcount = md->paramcount;
1059
1060         /* skip `this' pointer */
1061
1062         if (!(m->flags & ACC_STATIC)) {
1063                 paramtypes++;
1064                 paramcount--;
1065         }
1066
1067         /* create class-array */
1068
1069         result = builtin_anewarray(paramcount, class_java_lang_Class);
1070
1071     /* get classes */
1072
1073         for (i = 0; i < paramcount; i++) {
1074                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false,
1075                                                                                  (classinfo **) &result->data[i]))
1076                         return NULL;
1077
1078                 use_class_as_object((classinfo *) result->data[i]);
1079         }
1080
1081         return result;
1082 }
1083
1084
1085 /* get_exceptiontypes **********************************************************
1086
1087    get the exceptions which can be thrown by a method
1088
1089 *******************************************************************************/
1090
1091 java_objectarray* get_exceptiontypes(methodinfo *m)
1092 {
1093     u2 excount;
1094     u2 i;
1095     java_objectarray *result;
1096         classinfo *cls;
1097
1098         excount = m->thrownexceptionscount;
1099
1100     /* create class-array */
1101         assert(class_java_lang_Class);
1102
1103     result = builtin_anewarray(excount, class_java_lang_Class);
1104
1105     for (i = 0; i < excount; i++) {
1106                 if (!resolve_classref_or_classinfo(NULL,m->thrownexceptions[i],resolveEager,true,false,&cls))
1107                         return NULL; /* exception */
1108                 use_class_as_object(cls);
1109                 result->data[i] = (java_objectheader *)cls;
1110     }
1111
1112     return result;
1113 }
1114
1115
1116 /******************************************************************************************
1117
1118         get the returntype class of a method
1119
1120 *******************************************************************************************/
1121
1122 classinfo *get_returntype(methodinfo *m) 
1123 {
1124         classinfo *cls;
1125
1126         if (!resolve_class_from_typedesc(&(m->parseddesc->returntype),true,false,&cls))
1127                 return NULL; /* exception */
1128
1129         use_class_as_object(cls);
1130         return cls;
1131 }
1132
1133
1134 /*****************************************************************************/
1135 /*****************************************************************************/
1136
1137
1138 /*--------------------------------------------------------*/
1139 void printNativeCall(nativeCall nc) {
1140   int i,j;
1141
1142   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1143   for (i=0; i<nc.methCnt; i++) {  
1144       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1145
1146     for (j=0; j<nc.callCnt[i]; j++) {  
1147         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1148         nc.methods[i].methodCalls[j].classname, 
1149         nc.methods[i].methodCalls[j].methodname, 
1150         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1151       }
1152     }
1153   printf("-+++++--------------------\n");fflush(stdout);
1154 }
1155
1156 /*--------------------------------------------------------*/
1157 void printCompNativeCall(nativeCompCall nc) {
1158   int i,j;
1159   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1160   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1161   utf_display(nc.classname); fflush(stdout);
1162   
1163   for (i=0; i<nc.methCnt; i++) {  
1164     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1165     utf_display(nc.methods[i].methodname); fflush(stdout);
1166     utf_display(nc.methods[i].descriptor);fflush(stdout);
1167     printf("\n");fflush(stdout);
1168
1169     for (j=0; j<nc.callCnt[i]; j++) {  
1170       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1171         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1172         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1173         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1174         printf("\n");fflush(stdout);
1175       }
1176     }
1177 printf("---------------------\n");fflush(stdout);
1178 }
1179
1180
1181 /*--------------------------------------------------------*/
1182 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1183 {
1184     int i = 0;
1185     int j = 0;
1186     int cnt = 0;
1187     classMeth mc;
1188     mc.i_class = i;
1189     mc.j_method = j;
1190     mc.methCnt = cnt;
1191
1192     return mc;
1193 }
1194
1195 /*--------------------------------------------------------*/
1196 nativeCall* findNativeClassCalls(char *aclassname ) {
1197 int i;
1198
1199 for (i=0;i<NATIVECALLSSIZE; i++) {
1200    /* convert table to utf later to speed up search */ 
1201    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1202         return &nativeCalls[i];
1203    }
1204
1205 return NULL;
1206 }
1207 /*--------------------------------------------------------*/
1208 /*--------------------------------------------------------*/
1209 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1210   int i,j;
1211
1212
1213   ncc->classname = utf_new_char(nc.classname); 
1214   ncc->methCnt = nc.methCnt;
1215   
1216   for (i=0; i<nc.methCnt; i++) {  
1217     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1218     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1219     ncc->callCnt[i] = nc.callCnt[i];
1220
1221     for (j=0; j<nc.callCnt[i]; j++) {  
1222
1223         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1224
1225         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1226           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1227           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1228           }
1229         else {
1230           ncc->methods[i].methodCalls[j].methodname = NULL;
1231           ncc->methods[i].methodCalls[j].descriptor = NULL;
1232           }
1233       }
1234     }
1235 }
1236
1237
1238
1239 /*--------------------------------------------------------*/
1240
1241 bool natcall2utf(bool natcallcompdone) {
1242 int i;
1243
1244 if (natcallcompdone) 
1245         return true;
1246
1247 for (i=0;i<NATIVECALLSSIZE; i++) {
1248    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1249    }
1250
1251 return true;
1252 }
1253
1254 /*
1255  * These are local overrides for various environment variables in Emacs.
1256  * Please do not remove this and leave it at the end of the file, where
1257  * Emacs will automagically detect them.
1258  * ---------------------------------------------------------------------
1259  * Local variables:
1260  * mode: c
1261  * indent-tabs-mode: t
1262  * c-basic-offset: 4
1263  * tab-width: 4
1264  * End:
1265  */