0c12b69d11b6eb2f803dd88e1d4d6b9980daf6cc
[cacao.git] / src / native / native.cpp
1 /* src/native/native.cpp - native library support
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include <stdint.h>
32
33 #include <algorithm>
34 #include <functional>
35 #include <map>
36
37 #include "mm/memory.hpp"
38
39 #include "native/jni.hpp"
40 #include "native/native.hpp"
41
42 #include "threads/mutex.hpp"
43
44 #include "toolbox/logging.hpp"
45
46 #include "vm/jit/builtin.hpp"
47 #include "vm/exceptions.hpp"
48 #include "vm/global.h"
49 #include "vm/globals.hpp"
50 #include "vm/loader.hpp"
51 #include "vm/options.h"
52 #include "vm/os.hpp"
53 #include "vm/resolve.hpp"
54 #include "vm/string.hpp"
55 #include "vm/vm.hpp"
56
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/jit.hpp"
59
60 #if defined(ENABLE_JVMTI)
61 #include "native/jvmti/cacaodbg.h"
62 #endif
63
64
65 /* native_make_overloaded_function *********************************************
66
67    XXX
68
69 *******************************************************************************/
70
71 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
72 {
73         char *newname;
74         s4    namelen;
75         char *utf_ptr;
76         u2    c;
77         s4    i;
78         utf  *u;
79
80         utf_ptr = descriptor->text;
81         namelen = strlen(name->text) + strlen("__") + strlen("0");
82
83         /* calculate additional length */
84
85         while ((c = utf_nextu2(&utf_ptr)) != ')') {
86                 switch (c) {
87                 case 'Z':
88                 case 'B':
89                 case 'C':
90                 case 'S':
91                 case 'I':
92                 case 'J':
93                 case 'F':
94                 case 'D':
95                         namelen++;
96                         break;
97                 case '[':
98                         namelen += 2;
99                         break;
100                 case 'L':
101                         namelen++;
102                         while (utf_nextu2(&utf_ptr) != ';')
103                                 namelen++;
104                         namelen += 2;
105                         break;
106                 case '(':
107                         break;
108                 default:
109                         assert(0);
110                 }
111         }
112
113         /* reallocate memory */
114
115         i = strlen(name->text);
116
117         newname = MNEW(char, namelen);
118         MCOPY(newname, name->text, char, i);
119
120         utf_ptr = descriptor->text;
121
122         newname[i++] = '_';
123         newname[i++] = '_';
124
125         while ((c = utf_nextu2(&utf_ptr)) != ')') {
126                 switch (c) {
127                 case 'Z':
128                 case 'B':
129                 case 'C':
130                 case 'S':
131                 case 'J':
132                 case 'I':
133                 case 'F':
134                 case 'D':
135                         newname[i++] = c;
136                         break;
137                 case '[':
138                         newname[i++] = '_';
139                         newname[i++] = '3';
140                         break;
141                 case 'L':
142                         newname[i++] = 'L';
143                         while ((c = utf_nextu2(&utf_ptr)) != ';')
144                                 if (((c >= 'a') && (c <= 'z')) ||
145                                         ((c >= 'A') && (c <= 'Z')) ||
146                                         ((c >= '0') && (c <= '9')))
147                                         newname[i++] = c;
148                                 else
149                                         newname[i++] = '_';
150                         newname[i++] = '_';
151                         newname[i++] = '2';
152                         break;
153                 case '(':
154                         break;
155                 default:
156                         assert(0);
157                 }
158         }
159
160         /* close string */
161
162         newname[i] = '\0';
163
164         /* make a utf-string */
165
166         u = utf_new_char(newname);
167
168         /* release memory */
169
170         MFREE(newname, char, namelen);
171
172         return u;
173 }
174
175
176 /* native_insert_char **********************************************************
177
178    Inserts the passed UTF character into the native method name.  If
179    necessary it is escaped properly.
180
181 *******************************************************************************/
182
183 static s4 native_insert_char(char *name, u4 pos, u2 c)
184 {
185         s4 val;
186         s4 i;
187
188         switch (c) {
189         case '/':
190         case '.':
191                 /* replace '/' or '.' with '_' */
192                 name[pos] = '_';
193                 break;
194
195         case '_':
196                 /* escape sequence for '_' is '_1' */
197                 name[pos]   = '_';
198                 name[++pos] = '1';
199                 break;
200
201         case ';':
202                 /* escape sequence for ';' is '_2' */
203                 name[pos]   = '_';
204                 name[++pos] = '2';
205                 break;
206
207         case '[':
208                 /* escape sequence for '[' is '_1' */
209                 name[pos]   = '_';
210                 name[++pos] = '3';
211                 break;
212
213         default:
214                 if (isalnum(c))
215                         name[pos] = c;
216                 else {
217                         /* unicode character */
218                         name[pos]   = '_';
219                         name[++pos] = '0';
220
221                         for (i = 0; i < 4; ++i) {
222                                 val = c & 0x0f;
223                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
224                                 c >>= 4;
225                         }
226
227                         pos += 4;
228                 }
229                 break;
230         }
231
232         /* return the new buffer index */
233
234         return pos;
235 }
236
237
238 /* native_method_symbol ********************************************************
239
240    Generate a method-symbol string out of the class name and the
241    method name.
242
243 *******************************************************************************/
244
245 static utf *native_method_symbol(utf *classname, utf *methodname)
246 {
247         char *name;
248         s4    namelen;
249         char *utf_ptr;
250         char *utf_endptr;
251         u2    c;
252         u4    pos;
253         utf  *u;
254
255         /* Calculate length of native function name.  We multiply the
256            class and method name length by 6 as this is the maxium
257            escape-sequence that can be generated (unicode). */
258
259         namelen =
260                 strlen("Java_") +
261                 utf_get_number_of_u2s(classname) * 6 +
262                 strlen("_") +
263                 utf_get_number_of_u2s(methodname) * 6 +
264                 strlen("0");
265
266         /* allocate memory */
267
268         name = MNEW(char, namelen);
269
270         /* generate name of native functions */
271
272         strcpy(name, "Java_");
273         pos = strlen("Java_");
274
275         utf_ptr    = classname->text;
276         utf_endptr = UTF_END(classname);
277
278         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
279                 c   = *utf_ptr;
280                 pos = native_insert_char(name, pos, c);
281         }
282
283         /* seperator between class and method */
284
285         name[pos++] = '_';
286
287         utf_ptr    = methodname->text;
288         utf_endptr = UTF_END(methodname);
289
290         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
291                 c   = *utf_ptr;
292                 pos = native_insert_char(name, pos, c);
293         }
294
295         /* close string */
296
297         name[pos] = '\0';
298
299         /* check for an buffer overflow */
300
301         assert((int32_t) pos <= namelen);
302
303         /* make a utf-string */
304
305         u = utf_new_char(name);
306
307         /* release memory */
308
309         MFREE(name, char, namelen);
310
311         return u;
312 }
313
314
315 bool operator< (const NativeMethod& first, const NativeMethod& second)
316 {
317         if (first._classname < second._classname)
318                 return true;
319         else if (first._classname > second._classname)
320                 return false;
321                 
322         if (first._name < second._name)
323                 return true;
324         else if (first._name > second._name)
325                 return false;
326
327         if (first._descriptor < second._descriptor)
328                 return true;
329         else if (first._descriptor > second._descriptor)
330                 return false;
331
332         // All pointers are equal, we have found the entry.
333         return false;
334 }
335
336
337 /**
338  * Register native methods with the VM.  This is done by inserting
339  * them into the native method table.
340  *
341  * @param classname
342  * @param methods   Native methods array.
343  * @param count     Number of methods in the array.
344  */
345 void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
346 {
347         // Insert all methods passed */
348         for (size_t i = 0; i < count; i++) {
349                 if (opt_verbosejni) {
350                         printf("[Registering JNI native method ");
351                         utf_display_printable_ascii_classname(classname);
352                         printf(".%s]\n", methods[i].name);
353                 }
354
355                 // Generate the UTF8 names.
356                 utf* name      = utf_new_char(methods[i].name);
357                 utf* signature = utf_new_char(methods[i].signature);
358
359                 NativeMethod nm(classname, name, signature, methods[i].fnPtr);
360
361                 // Insert the method into the table.
362                 _methods.insert(nm);
363         }
364 }
365
366
367 /**
368  * Resolves a native method, maybe from a dynamic library.
369  *
370  * @param m Method structure of the native Java method to resolve.
371  *
372  * @return Pointer to the resolved method (symbol).
373  */
374 void* NativeMethods::resolve_method(methodinfo* m)
375 {
376         // Verbose output.
377         if (opt_verbosejni) {
378                 printf("[Dynamic-linking native method ");
379                 utf_display_printable_ascii_classname(m->clazz->name);
380                 printf(".");
381                 utf_display_printable_ascii(m->name);
382                 printf(" ... ");
383         }
384
385         /* generate method symbol string */
386
387         utf* name = native_method_symbol(m->clazz->name, m->name);
388
389         /* generate overloaded function (having the types in it's name)           */
390
391         utf* newname = native_make_overloaded_function(name, m->descriptor);
392
393         // Try to find the symbol.
394         void* symbol = NULL;
395
396 #if defined(ENABLE_DL)
397         // Get the classloader.
398         classloader_t* classloader = class_get_classloader(m->clazz);
399
400         // Resolve the native method name from the native libraries.
401         NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
402         symbol = libraries.resolve_symbol(name, classloader);
403
404         if (symbol == NULL)
405                 symbol = libraries.resolve_symbol(newname, classloader);
406
407 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
408         if (symbol == NULL) {
409                 /* We can resolve the function directly from
410                    java.lang.ClassLoader as it's a static function. */
411                 /* XXX should be done in native_init */
412
413                 methodinfo* method_findNative =
414                         class_resolveclassmethod(class_java_lang_ClassLoader,
415                                                                          utf_findNative,
416                                                                          utf_java_lang_ClassLoader_java_lang_String__J,
417                                                                          class_java_lang_ClassLoader,
418                                                                          true);
419
420                 if (method_findNative == NULL)
421                         return NULL;
422
423                 // Try the normal name.
424                 java_handle_t* s = javastring_new(name);
425                 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
426
427                 // If not found, try the mangled name.
428                 if (symbol == NULL) {
429                         s = javastring_new(newname);
430                         symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
431                 }
432         }
433 # endif
434
435         if (symbol != NULL)
436                 if (opt_verbosejni)
437                         printf("JNI ]\n");
438 #endif
439
440         // If not found already, try to find the native method symbol in
441         // the native methods registered with the VM.
442         if (symbol == NULL) {
443                 symbol = find_registered_method(m);
444
445                 if (symbol != NULL)
446                         if (opt_verbosejni)
447                                 printf("internal ]\n");
448         }
449
450 #if defined(ENABLE_JVMTI)
451         /* fire Native Method Bind event */
452         if (jvmti) jvmti_NativeMethodBind(m, f, &f);
453 #endif
454
455         // Symbol not found?  Throw an exception.
456         if (symbol == NULL) {
457                 if (opt_verbosejni)
458                         printf("failed ]\n");
459
460                 exceptions_throw_unsatisfiedlinkerror(m->name);
461         }
462
463         return symbol;
464 }
465
466
467 /**
468  * Try to find the given method in the native methods registered with
469  * the VM.
470  *
471  * @param m Method structure.
472  *
473  * @return Pointer to function if found, NULL otherwise.
474  */
475 void* NativeMethods::find_registered_method(methodinfo* m)
476 {
477         NativeMethod nm(m);
478         std::set<NativeMethod>::iterator it = _methods.find(nm);
479
480         if (it == _methods.end())
481                 return NULL;
482
483         return (*it).get_function();
484 }
485
486
487 /**
488  * Open this native library.
489  *
490  * @return File handle on success, NULL otherwise.
491  */
492 #if defined(ENABLE_DL)
493 void* NativeLibrary::open()
494 {
495         if (opt_verbosejni) {
496                 printf("[Loading native library ");
497                 utf_display_printable_ascii(_filename);
498                 printf(" ... ");
499         }
500
501         // Sanity check.
502         assert(_filename != NULL);
503
504         // Try to open the library.
505         _handle = os::dlopen(_filename->text, RTLD_LAZY);
506
507         if (_handle == NULL) {
508                 if (opt_verbosejni)
509                         printf("failed ]\n");
510
511                 if (opt_verbose) {
512                         log_start();
513                         log_print("NativeLibrary::open: os::dlopen failed: ");
514                         log_print(os::dlerror());
515                         log_finish();
516                 }
517
518                 return NULL;
519         }
520
521         if (opt_verbosejni)
522                 printf("OK ]\n");
523
524         return _handle;
525 }
526 #endif
527
528
529 /**
530  * Close this native library.
531  */
532 #if defined(ENABLE_DL)
533 void NativeLibrary::close()
534 {
535         if (opt_verbosejni) {
536                 printf("[Unloading native library ");
537 /*              utf_display_printable_ascii(filename); */
538                 printf(" ... ");
539         }
540
541         // Sanity check.
542         assert(_handle != NULL);
543
544         // Close the library.
545         int result = os::dlclose(_handle);
546
547         if (result != 0) {
548                 if (opt_verbosejni)
549                         printf("failed ]\n");
550
551                 if (opt_verbose) {
552                         log_start();
553                         log_print("NativeLibrary::close: os::dlclose failed: ");
554                         log_print(os::dlerror());
555                         log_finish();
556                 }
557         }
558
559         if (opt_verbosejni)
560                 printf("OK ]\n");
561 }
562 #endif
563
564
565 /**
566  * Load this native library and initialize it, if possible.
567  *
568  * @param env JNI environment.
569  *
570  * @return true if library loaded successfully, false otherwise.
571  */
572 bool NativeLibrary::load(JNIEnv* env)
573 {
574 #if defined(ENABLE_DL)
575         if (_filename == NULL) {
576                 exceptions_throw_nullpointerexception();
577                 return false;
578         }
579
580         // Is the library already loaded?
581         if (is_loaded())
582                 return true;
583
584         // Open the library.
585         open();
586
587         if (_handle == NULL)
588                 return false;
589
590 # if defined(ENABLE_JNI)
591         // Resolve JNI_OnLoad function.
592         void* onload = os::dlsym(_handle, "JNI_OnLoad");
593
594         if (onload != NULL) {
595                 JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
596                 JavaVM *vm;
597
598                 JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
599
600                 env->GetJavaVM(&vm);
601
602                 jint version = JNI_OnLoad(vm, NULL);
603
604                 // If the version is not 1.2 and not 1.4 the library cannot be
605                 // loaded.
606                 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
607                         os::dlclose(_handle);
608                         return false;
609                 }
610         }
611 # endif
612
613         // Insert the library name into the native library table.
614         NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
615         nativelibraries.add(*this);
616
617         return true;
618 #else
619         os::abort("NativeLibrary::load: Not available in this configuration.");
620
621         // Keep the compiler happy.
622         return false;
623 #endif
624 }
625
626
627 /**
628  * Checks if this native library is loaded.
629  *
630  * @return true if loaded, false otherwise.
631  */
632 #if defined(ENABLE_DL)
633 bool NativeLibrary::is_loaded()
634 {
635         NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
636         return libraries.is_loaded(*this);
637 }
638 #endif
639
640
641 /**
642  * Resolve the given symbol in this native library.
643  *
644  * @param symbolname Symbol name.
645  *
646  * @return Pointer to symbol if found, NULL otherwise.
647  */
648 void* NativeLibrary::resolve_symbol(utf* symbolname) const
649 {
650         return os::dlsym(_handle, symbolname->text);
651 }
652
653
654 /**
655  * Add the given native library to the native libraries table.
656  *
657  * @param library Native library to insert.
658  */
659 #if defined(ENABLE_DL)
660 void NativeLibraries::add(NativeLibrary& library)
661 {
662         // Make the container thread-safe.
663         _mutex.lock();
664
665         // XXX Check for double entries.
666         // Insert the native library.
667         _libraries.insert(std::make_pair(library.get_classloader(), library));
668
669         _mutex.unlock();
670 }
671 #endif
672
673
674 /**
675  * Checks if the given native library is loaded.
676  *
677  * @param library Native library.
678  *
679  * @return true if loaded, false otherwise.
680  */
681 bool NativeLibraries::is_loaded(NativeLibrary& library)
682 {
683         std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
684
685         // No entry for the classloader was found (the range has length
686         // zero).
687         if (its.first == its.second)
688                 return false;
689         
690         MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
691
692         // No matching entry in the range found.
693         if (it == its.second)
694                 return false;
695
696         return true;
697 }
698
699
700 /**
701  * Try to find a symbol with the given name in all loaded native
702  * libraries defined by classloader.
703  *
704  * @param symbolname  Name of the symbol to find.
705  * @param classloader Defining classloader.
706  *
707  * @return Pointer to symbol if found, NULL otherwise.
708  */
709 void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
710 {
711         std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
712
713         // No entry for the classloader was found (the range has length
714         // zero).
715         if (its.first == its.second)
716                 return NULL;
717
718         for (MAP::const_iterator it = its.first; it != its.second; it++) {
719                 const NativeLibrary& library = (*it).second;
720                 void* symbol = library.resolve_symbol(symbolname);
721
722                 if (symbol != NULL)
723                         return symbol;
724         }
725
726         return NULL;
727 }
728
729
730 /* native_new_and_init *********************************************************
731
732    Creates a new object on the heap and calls the initializer.
733    Returns the object pointer or NULL if memory is exhausted.
734                         
735 *******************************************************************************/
736
737 java_handle_t *native_new_and_init(classinfo *c)
738 {
739         methodinfo    *m;
740         java_handle_t *o;
741
742         if (c == NULL)
743                 vm_abort("native_new_and_init: c == NULL");
744
745         /* create object */
746
747         o = builtin_new(c);
748         
749         if (o == NULL)
750                 return NULL;
751
752         /* try to find the initializer */
753
754         m = class_findmethod(c, utf_init, utf_void__void);
755                                                       
756         /* ATTENTION: returning the object here is ok, since the class may
757        not have an initializer */
758
759         if (m == NULL)
760                 return o;
761
762         /* call initializer */
763
764         (void) vm_call_method(m, o);
765
766         return o;
767 }
768
769
770 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
771 {
772         methodinfo    *m;
773         java_handle_t *o;
774
775         if (c == NULL)
776                 vm_abort("native_new_and_init_string: c == NULL");
777
778         /* create object */
779
780         o = builtin_new(c);
781
782         if (o == NULL)
783                 return NULL;
784
785         /* find initializer */
786
787         m = class_findmethod(c, utf_init, utf_java_lang_String__void);
788
789         /* initializer not found */
790
791         if (m == NULL)
792                 return NULL;
793
794         /* call initializer */
795
796         (void) vm_call_method(m, o, s);
797
798         return o;
799 }
800
801
802 /*
803  * These are local overrides for various environment variables in Emacs.
804  * Please do not remove this and leave it at the end of the file, where
805  * Emacs will automagically detect them.
806  * ---------------------------------------------------------------------
807  * Local variables:
808  * mode: c++
809  * indent-tabs-mode: t
810  * c-basic-offset: 4
811  * tab-width: 4
812  * End:
813  * vim:noexpandtab:sw=4:ts=4:
814  */