3c5e7b4c68641e94c972b261bddedd5d55decd3c
[cacao.git] / src / native / native.cpp
1 /* src/native/native.cpp - native library support
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
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;
395
396         // Try to find the native method symbol in the native methods registered
397         // with the VM.
398         symbol = find_registered_method(m);
399
400         if (symbol != NULL)
401                 if (opt_verbosejni)
402                         printf("internal ]\n");
403
404 #if defined(ENABLE_DL)
405         classloader_t* classloader;
406         if (symbol == NULL) {
407                 // Get the classloader.
408                 classloader = class_get_classloader(m->clazz);
409
410                 // Resolve the native method name from the native libraries.
411                 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
412
413                 symbol = libraries.resolve_symbol(name, classloader);
414
415                 if (symbol == NULL)
416                         symbol = libraries.resolve_symbol(newname, classloader);
417         }
418
419 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
420         if (symbol == NULL) {
421                 /* We can resolve the function directly from
422                    java.lang.ClassLoader as it's a static function. */
423                 /* XXX should be done in native_init */
424
425                 methodinfo* method_findNative =
426                         class_resolveclassmethod(class_java_lang_ClassLoader,
427                                                                          utf_findNative,
428                                                                          utf_java_lang_ClassLoader_java_lang_String__J,
429                                                                          class_java_lang_ClassLoader,
430                                                                          true);
431
432                 if (method_findNative != NULL) {
433                         // Try the normal name.
434                         java_handle_t* s = javastring_new(name);
435                         symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
436
437                         // If not found, try the mangled name.
438                         if (symbol == NULL) {
439                                 s = javastring_new(newname);
440                                 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
441                         }
442                 }
443         }
444 # endif
445
446         if (symbol != NULL)
447                 if (opt_verbosejni)
448                         printf("JNI ]\n");
449 #endif
450
451 #if defined(ENABLE_JVMTI)
452         /* fire Native Method Bind event */
453         if (jvmti) jvmti_NativeMethodBind(m, f, &f);
454 #endif
455
456         // Symbol not found?  Throw an exception.
457         if (symbol == NULL) {
458                 if (opt_verbosejni)
459                         printf("failed ]\n");
460
461                 exceptions_throw_unsatisfiedlinkerror(m->name);
462         }
463
464         return symbol;
465 }
466
467
468 /**
469  * Try to find the given method in the native methods registered with
470  * the VM.
471  *
472  * @param m Method structure.
473  *
474  * @return Pointer to function if found, NULL otherwise.
475  */
476 void* NativeMethods::find_registered_method(methodinfo* m)
477 {
478         NativeMethod nm(m);
479         std::set<NativeMethod>::iterator it = _methods.find(nm);
480
481         if (it == _methods.end())
482                 return NULL;
483
484         return (*it).get_function();
485 }
486
487
488 /**
489  * Open this native library.
490  *
491  * @return File handle on success, NULL otherwise.
492  */
493 #if defined(ENABLE_DL)
494 void* NativeLibrary::open()
495 {
496         if (opt_verbosejni) {
497                 printf("[Loading native library ");
498                 utf_display_printable_ascii(_filename);
499                 printf(" ... ");
500         }
501
502         // Sanity check.
503         assert(_filename != NULL);
504
505         // Try to open the library.
506         _handle = os::dlopen(_filename->text, RTLD_LAZY);
507
508         if (_handle == NULL) {
509                 if (opt_verbosejni)
510                         printf("failed ]\n");
511
512                 if (opt_verbose) {
513                         log_start();
514                         log_print("NativeLibrary::open: os::dlopen failed: ");
515                         log_print(os::dlerror());
516                         log_finish();
517                 }
518
519                 return NULL;
520         }
521
522         if (opt_verbosejni)
523                 printf("OK ]\n");
524
525         return _handle;
526 }
527 #endif
528
529
530 /**
531  * Close this native library.
532  */
533 #if defined(ENABLE_DL)
534 void NativeLibrary::close()
535 {
536         if (opt_verbosejni) {
537                 printf("[Unloading native library ");
538 /*              utf_display_printable_ascii(filename); */
539                 printf(" ... ");
540         }
541
542         // Sanity check.
543         assert(_handle != NULL);
544
545         // Close the library.
546         int result = os::dlclose(_handle);
547
548         if (result != 0) {
549                 if (opt_verbosejni)
550                         printf("failed ]\n");
551
552                 if (opt_verbose) {
553                         log_start();
554                         log_print("NativeLibrary::close: os::dlclose failed: ");
555                         log_print(os::dlerror());
556                         log_finish();
557                 }
558         }
559
560         if (opt_verbosejni)
561                 printf("OK ]\n");
562 }
563 #endif
564
565
566 /**
567  * Load this native library and initialize it, if possible.
568  *
569  * @param env JNI environment.
570  *
571  * @return true if library loaded successfully, false otherwise.
572  */
573 bool NativeLibrary::load(JNIEnv* env)
574 {
575 #if defined(ENABLE_DL)
576         if (_filename == NULL) {
577                 exceptions_throw_nullpointerexception();
578                 return false;
579         }
580
581         // Is the library already loaded?
582         if (is_loaded())
583                 return true;
584
585         // Open the library.
586         open();
587
588         if (_handle == NULL)
589                 return false;
590
591 # if defined(ENABLE_JNI)
592         // Resolve JNI_OnLoad function.
593         void* onload = os::dlsym(_handle, "JNI_OnLoad");
594
595         if (onload != NULL) {
596                 JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
597                 JavaVM *vm;
598
599                 JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
600
601                 env->GetJavaVM(&vm);
602
603                 jint version = JNI_OnLoad(vm, NULL);
604
605                 // If the version is not 1.2 and not 1.4 the library cannot be
606                 // loaded.
607                 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
608                         os::dlclose(_handle);
609                         return false;
610                 }
611         }
612 # endif
613
614         // Insert the library name into the native library table.
615         NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
616         nativelibraries.add(*this);
617
618         return true;
619 #else
620         os::abort("NativeLibrary::load: Not available in this configuration.");
621
622         // Keep the compiler happy.
623         return false;
624 #endif
625 }
626
627
628 /**
629  * Checks if this native library is loaded.
630  *
631  * @return true if loaded, false otherwise.
632  */
633 #if defined(ENABLE_DL)
634 bool NativeLibrary::is_loaded()
635 {
636         NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
637         return libraries.is_loaded(*this);
638 }
639 #endif
640
641
642 /**
643  * Resolve the given symbol in this native library.
644  *
645  * @param symbolname Symbol name.
646  *
647  * @return Pointer to symbol if found, NULL otherwise.
648  */
649 void* NativeLibrary::resolve_symbol(utf* symbolname) const
650 {
651         return os::dlsym(_handle, symbolname->text);
652 }
653
654
655 /**
656  * Add the given native library to the native libraries table.
657  *
658  * @param library Native library to insert.
659  */
660 #if defined(ENABLE_DL)
661 void NativeLibraries::add(NativeLibrary& library)
662 {
663         // Make the container thread-safe.
664         _mutex.lock();
665
666         // XXX Check for double entries.
667         // Insert the native library.
668         _libraries.insert(std::make_pair(library.get_classloader(), library));
669
670         _mutex.unlock();
671 }
672 #endif
673
674
675 /**
676  * Checks if the given native library is loaded.
677  *
678  * @param library Native library.
679  *
680  * @return true if loaded, false otherwise.
681  */
682 bool NativeLibraries::is_loaded(NativeLibrary& library)
683 {
684         std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
685
686         // No entry for the classloader was found (the range has length
687         // zero).
688         if (its.first == its.second)
689                 return false;
690         
691         MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
692
693         // No matching entry in the range found.
694         if (it == its.second)
695                 return false;
696
697         return true;
698 }
699
700
701 /**
702  * Try to find a symbol with the given name in all loaded native
703  * libraries defined by classloader.
704  *
705  * @param symbolname  Name of the symbol to find.
706  * @param classloader Defining classloader.
707  *
708  * @return Pointer to symbol if found, NULL otherwise.
709  */
710 void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
711 {
712         std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
713
714         // No entry for the classloader was found (the range has length
715         // zero).
716         if (its.first == its.second)
717                 return NULL;
718
719         for (MAP::const_iterator it = its.first; it != its.second; it++) {
720                 const NativeLibrary& library = (*it).second;
721                 void* symbol = library.resolve_symbol(symbolname);
722
723                 if (symbol != NULL)
724                         return symbol;
725         }
726
727         return NULL;
728 }
729
730
731 /* native_new_and_init *********************************************************
732
733    Creates a new object on the heap and calls the initializer.
734    Returns the object pointer or NULL if memory is exhausted.
735                         
736 *******************************************************************************/
737
738 java_handle_t *native_new_and_init(classinfo *c)
739 {
740         methodinfo    *m;
741         java_handle_t *o;
742
743         if (c == NULL)
744                 vm_abort("native_new_and_init: c == NULL");
745
746         /* create object */
747
748         o = builtin_new(c);
749         
750         if (o == NULL)
751                 return NULL;
752
753         /* try to find the initializer */
754
755         m = class_findmethod(c, utf_init, utf_void__void);
756                                                       
757         /* ATTENTION: returning the object here is ok, since the class may
758        not have an initializer */
759
760         if (m == NULL)
761                 return o;
762
763         /* call initializer */
764
765         (void) vm_call_method(m, o);
766
767         return o;
768 }
769
770
771 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
772 {
773         methodinfo    *m;
774         java_handle_t *o;
775
776         if (c == NULL)
777                 vm_abort("native_new_and_init_string: c == NULL");
778
779         /* create object */
780
781         o = builtin_new(c);
782
783         if (o == NULL)
784                 return NULL;
785
786         /* find initializer */
787
788         m = class_findmethod(c, utf_init, utf_java_lang_String__void);
789
790         /* initializer not found */
791
792         if (m == NULL)
793                 return NULL;
794
795         /* call initializer */
796
797         (void) vm_call_method(m, o, s);
798
799         return o;
800 }
801
802
803 /*
804  * These are local overrides for various environment variables in Emacs.
805  * Please do not remove this and leave it at the end of the file, where
806  * Emacs will automagically detect them.
807  * ---------------------------------------------------------------------
808  * Local variables:
809  * mode: c++
810  * indent-tabs-mode: t
811  * c-basic-offset: 4
812  * tab-width: 4
813  * End:
814  * vim:noexpandtab:sw=4:ts=4:
815  */