* configure.ac: New switch for disabling -O2 (--disable-optimizations).
[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/hook.hpp"
51 #include "vm/loader.hpp"
52 #include "vm/options.h"
53 #include "vm/os.hpp"
54 #include "vm/resolve.hpp"
55 #include "vm/string.hpp"
56 #include "vm/vm.hpp"
57
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.hpp"
60
61
62 /* native_make_overloaded_function *********************************************
63
64    XXX
65
66 *******************************************************************************/
67
68 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
69 {
70         char *newname;
71         s4    namelen;
72         char *utf_ptr;
73         u2    c;
74         s4    i;
75         utf  *u;
76
77         utf_ptr = descriptor->text;
78         namelen = strlen(name->text) + strlen("__") + strlen("0");
79
80         /* calculate additional length */
81
82         while ((c = utf_nextu2(&utf_ptr)) != ')') {
83                 switch (c) {
84                 case 'Z':
85                 case 'B':
86                 case 'C':
87                 case 'S':
88                 case 'I':
89                 case 'J':
90                 case 'F':
91                 case 'D':
92                         namelen++;
93                         break;
94                 case '[':
95                         namelen += 2;
96                         break;
97                 case 'L':
98                         namelen++;
99                         while (utf_nextu2(&utf_ptr) != ';')
100                                 namelen++;
101                         namelen += 2;
102                         break;
103                 case '(':
104                         break;
105                 default:
106                         assert(0);
107                 }
108         }
109
110         /* reallocate memory */
111
112         i = strlen(name->text);
113
114         newname = MNEW(char, namelen);
115         MCOPY(newname, name->text, char, i);
116
117         utf_ptr = descriptor->text;
118
119         newname[i++] = '_';
120         newname[i++] = '_';
121
122         while ((c = utf_nextu2(&utf_ptr)) != ')') {
123                 switch (c) {
124                 case 'Z':
125                 case 'B':
126                 case 'C':
127                 case 'S':
128                 case 'J':
129                 case 'I':
130                 case 'F':
131                 case 'D':
132                         newname[i++] = c;
133                         break;
134                 case '[':
135                         newname[i++] = '_';
136                         newname[i++] = '3';
137                         break;
138                 case 'L':
139                         newname[i++] = 'L';
140                         while ((c = utf_nextu2(&utf_ptr)) != ';')
141                                 if (((c >= 'a') && (c <= 'z')) ||
142                                         ((c >= 'A') && (c <= 'Z')) ||
143                                         ((c >= '0') && (c <= '9')))
144                                         newname[i++] = c;
145                                 else
146                                         newname[i++] = '_';
147                         newname[i++] = '_';
148                         newname[i++] = '2';
149                         break;
150                 case '(':
151                         break;
152                 default:
153                         assert(0);
154                 }
155         }
156
157         /* close string */
158
159         newname[i] = '\0';
160
161         /* make a utf-string */
162
163         u = utf_new_char(newname);
164
165         /* release memory */
166
167         MFREE(newname, char, namelen);
168
169         return u;
170 }
171
172
173 /* native_insert_char **********************************************************
174
175    Inserts the passed UTF character into the native method name.  If
176    necessary it is escaped properly.
177
178 *******************************************************************************/
179
180 static s4 native_insert_char(char *name, u4 pos, u2 c)
181 {
182         s4 val;
183         s4 i;
184
185         switch (c) {
186         case '/':
187         case '.':
188                 /* replace '/' or '.' with '_' */
189                 name[pos] = '_';
190                 break;
191
192         case '_':
193                 /* escape sequence for '_' is '_1' */
194                 name[pos]   = '_';
195                 name[++pos] = '1';
196                 break;
197
198         case ';':
199                 /* escape sequence for ';' is '_2' */
200                 name[pos]   = '_';
201                 name[++pos] = '2';
202                 break;
203
204         case '[':
205                 /* escape sequence for '[' is '_1' */
206                 name[pos]   = '_';
207                 name[++pos] = '3';
208                 break;
209
210         default:
211                 if (isalnum(c))
212                         name[pos] = c;
213                 else {
214                         /* unicode character */
215                         name[pos]   = '_';
216                         name[++pos] = '0';
217
218                         for (i = 0; i < 4; ++i) {
219                                 val = c & 0x0f;
220                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
221                                 c >>= 4;
222                         }
223
224                         pos += 4;
225                 }
226                 break;
227         }
228
229         /* return the new buffer index */
230
231         return pos;
232 }
233
234
235 /* native_method_symbol ********************************************************
236
237    Generate a method-symbol string out of the class name and the
238    method name.
239
240 *******************************************************************************/
241
242 static utf *native_method_symbol(utf *classname, utf *methodname)
243 {
244         char *name;
245         s4    namelen;
246         char *utf_ptr;
247         char *utf_endptr;
248         u2    c;
249         u4    pos;
250         utf  *u;
251
252         /* Calculate length of native function name.  We multiply the
253            class and method name length by 6 as this is the maxium
254            escape-sequence that can be generated (unicode). */
255
256         namelen =
257                 strlen("Java_") +
258                 utf_get_number_of_u2s(classname) * 6 +
259                 strlen("_") +
260                 utf_get_number_of_u2s(methodname) * 6 +
261                 strlen("0");
262
263         /* allocate memory */
264
265         name = MNEW(char, namelen);
266
267         /* generate name of native functions */
268
269         strcpy(name, "Java_");
270         pos = strlen("Java_");
271
272         utf_ptr    = classname->text;
273         utf_endptr = UTF_END(classname);
274
275         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
276                 c   = *utf_ptr;
277                 pos = native_insert_char(name, pos, c);
278         }
279
280         /* seperator between class and method */
281
282         name[pos++] = '_';
283
284         utf_ptr    = methodname->text;
285         utf_endptr = UTF_END(methodname);
286
287         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
288                 c   = *utf_ptr;
289                 pos = native_insert_char(name, pos, c);
290         }
291
292         /* close string */
293
294         name[pos] = '\0';
295
296         /* check for an buffer overflow */
297
298         assert((int32_t) pos <= namelen);
299
300         /* make a utf-string */
301
302         u = utf_new_char(name);
303
304         /* release memory */
305
306         MFREE(name, char, namelen);
307
308         return u;
309 }
310
311
312 bool operator< (const NativeMethod& first, const NativeMethod& second)
313 {
314         if (first._classname < second._classname)
315                 return true;
316         else if (first._classname > second._classname)
317                 return false;
318                 
319         if (first._name < second._name)
320                 return true;
321         else if (first._name > second._name)
322                 return false;
323
324         if (first._descriptor < second._descriptor)
325                 return true;
326         else if (first._descriptor > second._descriptor)
327                 return false;
328
329         // All pointers are equal, we have found the entry.
330         return false;
331 }
332
333
334 /**
335  * Register native methods with the VM.  This is done by inserting
336  * them into the native method table.
337  *
338  * @param classname
339  * @param methods   Native methods array.
340  * @param count     Number of methods in the array.
341  */
342 void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
343 {
344         // Insert all methods passed */
345         for (size_t i = 0; i < count; i++) {
346                 if (opt_verbosejni) {
347                         printf("[Registering JNI native method ");
348                         utf_display_printable_ascii_classname(classname);
349                         printf(".%s]\n", methods[i].name);
350                 }
351
352                 // Generate the UTF8 names.
353                 utf* name      = utf_new_char(methods[i].name);
354                 utf* signature = utf_new_char(methods[i].signature);
355
356                 NativeMethod nm(classname, name, signature, methods[i].fnPtr);
357
358                 // Insert the method into the table.
359                 _methods.insert(nm);
360         }
361 }
362
363
364 /**
365  * Resolves a native method, maybe from a dynamic library.
366  *
367  * @param m Method structure of the native Java method to resolve.
368  *
369  * @return Pointer to the resolved method (symbol).
370  */
371 void* NativeMethods::resolve_method(methodinfo* m)
372 {
373         // Verbose output.
374         if (opt_verbosejni) {
375                 printf("[Dynamic-linking native method ");
376                 utf_display_printable_ascii_classname(m->clazz->name);
377                 printf(".");
378                 utf_display_printable_ascii(m->name);
379                 printf(" ... ");
380         }
381
382         /* generate method symbol string */
383
384         utf* name = native_method_symbol(m->clazz->name, m->name);
385
386         /* generate overloaded function (having the types in it's name)           */
387
388         utf* newname = native_make_overloaded_function(name, m->descriptor);
389
390         // Try to find the symbol.
391         void* symbol;
392
393         // Try to find the native method symbol in the native methods registered
394         // with the VM.
395         symbol = find_registered_method(m);
396
397         if (symbol != NULL)
398                 if (opt_verbosejni)
399                         printf("internal ]\n");
400
401 #if defined(ENABLE_DL)
402         classloader_t* classloader;
403         if (symbol == NULL) {
404                 // Get the classloader.
405                 classloader = class_get_classloader(m->clazz);
406
407                 // Resolve the native method name from the native libraries.
408                 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
409
410                 symbol = libraries.resolve_symbol(name, classloader);
411
412                 if (symbol == NULL)
413                         symbol = libraries.resolve_symbol(newname, classloader);
414         }
415
416 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
417         if (symbol == NULL) {
418                 /* We can resolve the function directly from
419                    java.lang.ClassLoader as it's a static function. */
420                 /* XXX should be done in native_init */
421
422                 methodinfo* method_findNative =
423                         class_resolveclassmethod(class_java_lang_ClassLoader,
424                                                                          utf_findNative,
425                                                                          utf_java_lang_ClassLoader_java_lang_String__J,
426                                                                          class_java_lang_ClassLoader,
427                                                                          true);
428
429                 if (method_findNative != NULL) {
430                         // Try the normal name.
431                         java_handle_t* s = javastring_new(name);
432                         symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
433
434                         // If not found, try the mangled name.
435                         if (symbol == NULL) {
436                                 s = javastring_new(newname);
437                                 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
438                         }
439                 }
440         }
441 # endif
442
443         if (symbol != NULL)
444                 if (opt_verbosejni)
445                         printf("JNI ]\n");
446 #endif
447
448         // Symbol not found?  Throw an exception.
449         if (symbol == NULL) {
450                 if (opt_verbosejni)
451                         printf("failed ]\n");
452
453                 exceptions_throw_unsatisfiedlinkerror(m->name);
454         }
455
456         // Hook point just after method resolving finished.
457         Hook::native_resolved(m, symbol, &symbol);
458
459         return symbol;
460 }
461
462
463 /**
464  * Try to find the given method in the native methods registered with
465  * the VM.
466  *
467  * @param m Method structure.
468  *
469  * @return Pointer to function if found, NULL otherwise.
470  */
471 void* NativeMethods::find_registered_method(methodinfo* m)
472 {
473         NativeMethod nm(m);
474         std::set<NativeMethod>::iterator it = _methods.find(nm);
475
476         if (it == _methods.end())
477                 return NULL;
478
479         return (*it).get_function();
480 }
481
482
483 /**
484  * Open this native library.
485  *
486  * @return File handle on success, NULL otherwise.
487  */
488 #if defined(ENABLE_DL)
489 void* NativeLibrary::open()
490 {
491         if (opt_verbosejni) {
492                 printf("[Loading native library ");
493                 utf_display_printable_ascii(_filename);
494                 printf(" ... ");
495         }
496
497         // Sanity check.
498         assert(_filename != NULL);
499
500         // Try to open the library.
501         _handle = os::dlopen(_filename->text, RTLD_LAZY);
502
503         if (_handle == NULL) {
504                 if (opt_verbosejni)
505                         printf("failed ]\n");
506
507                 if (opt_PrintWarnings)
508                         log_println("NativeLibrary::open: os::dlopen failed: %s", os::dlerror());
509
510                 return NULL;
511         }
512
513         if (opt_verbosejni)
514                 printf("OK ]\n");
515
516         return _handle;
517 }
518 #endif
519
520
521 /**
522  * Close this native library.
523  */
524 #if defined(ENABLE_DL)
525 void NativeLibrary::close()
526 {
527         if (opt_verbosejni) {
528                 printf("[Unloading native library ");
529 /*              utf_display_printable_ascii(filename); */
530                 printf(" ... ");
531         }
532
533         // Sanity check.
534         assert(_handle != NULL);
535
536         // Close the library.
537         int result = os::dlclose(_handle);
538
539         if (result != 0) {
540                 if (opt_verbosejni)
541                         printf("failed ]\n");
542
543                 if (opt_PrintWarnings)
544                         log_println("NativeLibrary::close: os::dlclose failed: %s", os::dlerror());
545         }
546
547         if (opt_verbosejni)
548                 printf("OK ]\n");
549 }
550 #endif
551
552
553 /**
554  * Load this native library and initialize it, if possible.
555  *
556  * @param env JNI environment.
557  *
558  * @return true if library loaded successfully, false otherwise.
559  */
560 bool NativeLibrary::load(JNIEnv* env)
561 {
562 #if defined(ENABLE_DL)
563         if (_filename == NULL) {
564                 exceptions_throw_nullpointerexception();
565                 return false;
566         }
567
568         // Is the library already loaded?
569         if (is_loaded())
570                 return true;
571
572         // Open the library.
573         open();
574
575         if (_handle == NULL)
576                 return false;
577
578 # if defined(ENABLE_JNI)
579         // Resolve JNI_OnLoad function.
580         void* onload = os::dlsym(_handle, "JNI_OnLoad");
581
582         if (onload != NULL) {
583                 JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
584                 JavaVM *vm;
585
586                 JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
587
588                 env->GetJavaVM(&vm);
589
590                 jint version = JNI_OnLoad(vm, NULL);
591
592                 // If the version is not 1.2 and not 1.4 the library cannot be
593                 // loaded.
594                 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
595                         os::dlclose(_handle);
596                         return false;
597                 }
598         }
599 # endif
600
601         // Insert the library name into the native library table.
602         NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
603         nativelibraries.add(*this);
604
605         return true;
606 #else
607         os::abort("NativeLibrary::load: Not available in this configuration.");
608
609         // Keep the compiler happy.
610         return false;
611 #endif
612 }
613
614
615 /**
616  * Checks if this native library is loaded.
617  *
618  * @return true if loaded, false otherwise.
619  */
620 #if defined(ENABLE_DL)
621 bool NativeLibrary::is_loaded()
622 {
623         NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
624         return libraries.is_loaded(*this);
625 }
626 #endif
627
628
629 /**
630  * Resolve the given symbol in this native library.
631  *
632  * @param symbolname Symbol name.
633  *
634  * @return Pointer to symbol if found, NULL otherwise.
635  */
636 void* NativeLibrary::resolve_symbol(utf* symbolname) const
637 {
638         return os::dlsym(_handle, symbolname->text);
639 }
640
641
642 /**
643  * Add the given native library to the native libraries table.
644  *
645  * @param library Native library to insert.
646  */
647 #if defined(ENABLE_DL)
648 void NativeLibraries::add(NativeLibrary& library)
649 {
650         // Make the container thread-safe.
651         _mutex.lock();
652
653         // XXX Check for double entries.
654         // Insert the native library.
655         _libraries.insert(std::make_pair(library.get_classloader(), library));
656
657         _mutex.unlock();
658 }
659 #endif
660
661
662 /**
663  * Checks if the given native library is loaded.
664  *
665  * @param library Native library.
666  *
667  * @return true if loaded, false otherwise.
668  */
669 bool NativeLibraries::is_loaded(NativeLibrary& library)
670 {
671         std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
672
673         // No entry for the classloader was found (the range has length
674         // zero).
675         if (its.first == its.second)
676                 return false;
677         
678         MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
679
680         // No matching entry in the range found.
681         if (it == its.second)
682                 return false;
683
684         return true;
685 }
686
687
688 /**
689  * Try to find a symbol with the given name in all loaded native
690  * libraries defined by classloader.
691  *
692  * @param symbolname  Name of the symbol to find.
693  * @param classloader Defining classloader.
694  *
695  * @return Pointer to symbol if found, NULL otherwise.
696  */
697 void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
698 {
699         std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
700
701         // No entry for the classloader was found (the range has length
702         // zero).
703         if (its.first == its.second)
704                 return NULL;
705
706         for (MAP::const_iterator it = its.first; it != its.second; it++) {
707                 const NativeLibrary& library = (*it).second;
708                 void* symbol = library.resolve_symbol(symbolname);
709
710                 if (symbol != NULL)
711                         return symbol;
712         }
713
714         return NULL;
715 }
716
717
718 /**
719  * Registers a new native agent by specified by it's library name
720  * and with an optional options string.
721  *
722  * @param library Name of the native agent library.
723  * @param options The options string or NULL if not specified.
724  */
725 #if defined(ENABLE_JVMTI)
726 void NativeAgents::register_agent_library(char* library, char* options)
727 {
728         NativeAgent na(library, options);
729
730         // Insert native agent into list of agents.
731         _agents.push_back(na);
732 }
733 #endif
734
735
736 /**
737  * Registers a new native agent by specified by a path to it's library
738  * and with an optional options string.
739  *
740  * @param path Path of the native agent library.
741  * @param options The options string or NULL if not specified.
742  */
743 #if defined(ENABLE_JVMTI)
744 void NativeAgents::register_agent_path(char* path, char* options)
745 {
746         os::abort("NativeAgents::register_agent_library: Implement me!");
747 }
748 #endif
749
750
751 /**
752  * Loads all registered native agents and in turn calls their exported
753  * start-up functions (Agent_OnLoad). If one of the agents reports an
754  * error during start-up, the loading is stopped.
755  *
756  * @return True if all agents were loaded successfully, false if
757  * one of them was not found or reported an error.
758  */
759 #if defined(ENABLE_JVMTI)
760 bool NativeAgents::load_agents()
761 {
762         // Iterate over all registered agents.
763         for (std::vector<NativeAgent>::iterator it = _agents.begin(); it != _agents.end(); ++it) {
764                 NativeAgent& na = *(it);
765
766                 // Construct agent library name.
767                 size_t len =
768                         os::strlen(NATIVE_LIBRARY_PREFIX) +
769                         os::strlen(na.get_library()) +
770                         os::strlen(NATIVE_LIBRARY_SUFFIX) +
771                         os::strlen("0");
772
773                 char* p = MNEW(char, len);
774
775                 os::strcpy(p, NATIVE_LIBRARY_PREFIX);
776                 os::strcat(p, na.get_library());
777                 os::strcat(p, NATIVE_LIBRARY_SUFFIX);
778
779                 utf* u = utf_new_char(p);
780
781                 MFREE(p, char, len);
782
783                 // Construct new native library.
784                 NativeLibrary nl(u);
785
786                 // Try to open the library.
787                 if (nl.open() == NULL)
788                         return false;
789
790                 // Resolve Agent_OnLoad function.
791                 void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
792
793                 // Call Agent_OnLoad function if present.
794                 if (onload != NULL) {
795                         JNIEXPORT jint (JNICALL *Agent_OnLoad) (JavaVM*, char*, void*);
796                         JavaVM* vm = VM::get_current()->get_javavm();
797
798                         Agent_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, char*, void*)) (uintptr_t) onload;
799
800                         jint result = Agent_OnLoad(vm, na.get_options(), NULL);
801
802                         // Check for error in Agent_OnLoad.
803                         if (result != 0) {
804                                 nl.close();
805                                 return false;
806                         }
807                 }
808
809                 // According to the interface spec, the library _must_ export
810                 // a start-up function.
811                 else {
812                         log_println("NativeAgents::load_agents: Native agent library does not export Agent_OnLoad");
813                         return false;
814                 }
815         }
816
817         return true;
818 }
819 #endif
820
821
822 /* native_new_and_init *********************************************************
823
824    Creates a new object on the heap and calls the initializer.
825    Returns the object pointer or NULL if memory is exhausted.
826                         
827 *******************************************************************************/
828
829 java_handle_t *native_new_and_init(classinfo *c)
830 {
831         methodinfo    *m;
832         java_handle_t *o;
833
834         if (c == NULL)
835                 vm_abort("native_new_and_init: c == NULL");
836
837         /* create object */
838
839         o = builtin_new(c);
840         
841         if (o == NULL)
842                 return NULL;
843
844         /* try to find the initializer */
845
846         m = class_findmethod(c, utf_init, utf_void__void);
847                                                       
848         /* ATTENTION: returning the object here is ok, since the class may
849        not have an initializer */
850
851         if (m == NULL)
852                 return o;
853
854         /* call initializer */
855
856         (void) vm_call_method(m, o);
857
858         return o;
859 }
860
861
862 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
863 {
864         methodinfo    *m;
865         java_handle_t *o;
866
867         if (c == NULL)
868                 vm_abort("native_new_and_init_string: c == NULL");
869
870         /* create object */
871
872         o = builtin_new(c);
873
874         if (o == NULL)
875                 return NULL;
876
877         /* find initializer */
878
879         m = class_findmethod(c, utf_init, utf_java_lang_String__void);
880
881         /* initializer not found */
882
883         if (m == NULL)
884                 return NULL;
885
886         /* call initializer */
887
888         (void) vm_call_method(m, o, s);
889
890         return o;
891 }
892
893
894 /*
895  * These are local overrides for various environment variables in Emacs.
896  * Please do not remove this and leave it at the end of the file, where
897  * Emacs will automagically detect them.
898  * ---------------------------------------------------------------------
899  * Local variables:
900  * mode: c++
901  * indent-tabs-mode: t
902  * c-basic-offset: 4
903  * tab-width: 4
904  * End:
905  * vim:noexpandtab:sw=4:ts=4:
906  */