1 /* src/native/native.c - table of native functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
6 This file is part of CACAO.
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.
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.
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
31 #if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
39 #include "mm/memory.h"
41 #include "native/jni.h"
42 #include "native/native.h"
44 #include "native/vm/nativevm.h"
46 #include "threads/lock-common.h"
48 #include "toolbox/avl.h"
49 #include "toolbox/hashtable.h"
50 #include "toolbox/logging.h"
52 #include "vm/builtin.h"
53 #include "vm/exceptions.h"
54 #include "vm/global.h"
55 #include "vm/stringlocal.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
61 #include "vmcore/loader.h"
62 #include "vmcore/options.h"
63 #include "vm/resolve.h"
65 #if defined(ENABLE_JVMTI)
66 #include "native/jvmti/cacaodbg.h"
70 /* global variables ***********************************************************/
72 static avl_tree_t *tree_native_methods;
74 #if defined(ENABLE_LTDL)
75 static hashtable *hashtable_library;
79 /* prototypes *****************************************************************/
81 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
84 /* native_init *****************************************************************
86 Initializes the native subsystem.
88 *******************************************************************************/
90 bool native_init(void)
92 #if defined(ENABLE_LTDL)
93 /* initialize libltdl */
96 vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
98 /* initialize library hashtable, 10 entries should be enough */
100 hashtable_library = NEW(hashtable);
102 hashtable_create(hashtable_library, 10);
105 /* initialize the native methods table */
107 tree_native_methods = avl_create(&native_tree_native_methods_comparator);
109 /* everything's ok */
115 /* native_tree_native_methods_comparator ***************************************
117 Comparison function for AVL tree of native methods.
120 treenode....node in the tree
121 node........node to compare with tree-node
126 *******************************************************************************/
128 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
130 const native_methods_node_t *treenmn;
131 const native_methods_node_t *nmn;
136 /* these are for walking the tree */
138 if (treenmn->classname < nmn->classname)
140 else if (treenmn->classname > nmn->classname)
143 if (treenmn->name < nmn->name)
145 else if (treenmn->name > nmn->name)
148 if (treenmn->descriptor < nmn->descriptor)
150 else if (treenmn->descriptor > nmn->descriptor)
153 /* all pointers are equal, we have found the entry */
159 /* native_make_overloaded_function *********************************************
163 *******************************************************************************/
165 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
179 utf_ptr = descriptor->text;
180 namelen = strlen(name->text) + strlen("__") + strlen("0");
182 /* calculate additional length */
184 while ((c = utf_nextu2(&utf_ptr)) != ')') {
201 while (utf_nextu2(&utf_ptr) != ';')
212 /* reallocate memory */
214 i = strlen(name->text);
216 newname = DMNEW(char, namelen);
217 MCOPY(newname, name->text, char, i);
219 utf_ptr = descriptor->text;
224 while ((c = utf_nextu2(&utf_ptr)) != ')') {
242 while ((c = utf_nextu2(&utf_ptr)) != ';')
243 if (((c >= 'a') && (c <= 'z')) ||
244 ((c >= 'A') && (c <= 'Z')) ||
245 ((c >= '0') && (c <= '9')))
263 /* make a utf-string */
265 u = utf_new_char(newname);
275 /* native_insert_char **********************************************************
277 Inserts the passed UTF character into the native method name. If
278 necessary it is escaped properly.
280 *******************************************************************************/
282 static s4 native_insert_char(char *name, u4 pos, u2 c)
290 /* replace '/' or '.' with '_' */
295 /* escape sequence for '_' is '_1' */
301 /* escape sequence for ';' is '_2' */
307 /* escape sequence for '[' is '_1' */
316 /* unicode character */
320 for (i = 0; i < 4; ++i) {
322 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
331 /* return the new buffer index */
337 /* native_method_symbol ********************************************************
339 Generate a method-symbol string out of the class name and the
342 *******************************************************************************/
344 static utf *native_method_symbol(utf *classname, utf *methodname)
359 /* Calculate length of native function name. We multiply the
360 class and method name length by 6 as this is the maxium
361 escape-sequence that can be generated (unicode). */
365 utf_get_number_of_u2s(classname) * 6 +
367 utf_get_number_of_u2s(methodname) * 6 +
370 /* allocate memory */
372 name = DMNEW(char, namelen);
374 /* generate name of native functions */
376 strcpy(name, "Java_");
377 pos = strlen("Java_");
379 utf_ptr = classname->text;
380 utf_endptr = UTF_END(classname);
382 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
384 pos = native_insert_char(name, pos, c);
387 /* seperator between class and method */
391 utf_ptr = methodname->text;
392 utf_endptr = UTF_END(methodname);
394 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
396 pos = native_insert_char(name, pos, c);
403 /* check for an buffer overflow */
405 assert(pos <= namelen);
407 /* make a utf-string */
409 u = utf_new_char(name);
419 /* native_method_register ******************************************************
421 Register a native method in the native method table.
423 *******************************************************************************/
425 void native_method_register(utf *classname, const JNINativeMethod *methods,
428 native_methods_node_t *nmn;
433 /* insert all methods passed */
435 for (i = 0; i < count; i++) {
436 if (opt_verbosejni) {
437 printf("[Registering JNI native method ");
438 utf_display_printable_ascii_classname(classname);
439 printf(".%s]\n", methods[i].name);
442 /* generate the utf8 names */
444 name = utf_new_char(methods[i].name);
445 descriptor = utf_new_char(methods[i].signature);
447 /* allocate a new tree node */
449 nmn = NEW(native_methods_node_t);
451 nmn->classname = classname;
453 nmn->descriptor = descriptor;
454 nmn->function = (functionptr) (ptrint) methods[i].fnPtr;
456 /* insert the method into the tree */
458 avl_insert(tree_native_methods, nmn);
463 /* native_method_find **********************************************************
465 Find a native method in the native method table.
467 *******************************************************************************/
469 static functionptr native_method_find(methodinfo *m)
471 native_methods_node_t tmpnmn;
472 native_methods_node_t *nmn;
474 /* fill the temporary structure used for searching the tree */
476 tmpnmn.classname = m->class->name;
477 tmpnmn.name = m->name;
478 tmpnmn.descriptor = m->descriptor;
480 /* find the entry in the AVL-tree */
482 nmn = avl_find(tree_native_methods, &tmpnmn);
487 return nmn->function;
491 /* native_method_resolve *******************************************************
493 Resolves a native method, maybe from a dynamic library.
496 m ... methodinfo of the native Java method to resolve
499 pointer to the resolved method (symbol)
501 *******************************************************************************/
503 functionptr native_method_resolve(methodinfo *m)
508 #if defined(ENABLE_LTDL)
510 hashtable_library_loader_entry *le;
511 hashtable_library_name_entry *ne;
512 u4 key; /* hashkey */
513 u4 slot; /* slot in hashtable */
515 #if defined(WITH_CLASSPATH_SUN)
516 methodinfo *method_findNative;
522 if (opt_verbosejni) {
523 printf("[Dynamic-linking native method ");
524 utf_display_printable_ascii_classname(m->class->name);
526 utf_display_printable_ascii(m->name);
530 /* generate method symbol string */
532 name = native_method_symbol(m->class->name, m->name);
534 /* generate overloaded function (having the types in it's name) */
536 newname = native_make_overloaded_function(name, m->descriptor);
538 /* check the library hash entries of the classloader of the
543 #if defined(ENABLE_LTDL)
544 /* Get the classloader. */
546 cl = class_get_classloader(m->class);
548 /* normally addresses are aligned to 4, 8 or 16 bytes */
550 key = ((u4) (ptrint) cl) >> 4; /* align to 16-byte */
551 slot = key & (hashtable_library->size - 1);
552 le = hashtable_library->ptr[slot];
554 /* iterate through loaders in this hash slot */
556 while ((le != NULL) && (f == NULL)) {
557 /* iterate through names in this loader */
561 while ((ne != NULL) && (f == NULL)) {
562 f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
565 f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
573 # if defined(WITH_CLASSPATH_SUN)
575 /* We can resolve the function directly from
576 java.lang.ClassLoader as it's a static function. */
577 /* XXX should be done in native_init */
580 class_resolveclassmethod(class_java_lang_ClassLoader,
582 utf_java_lang_ClassLoader_java_lang_String__J,
583 class_java_lang_ClassLoader,
586 if (method_findNative == NULL)
589 /* try the normal name */
591 s = javastring_new(name);
593 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
596 /* if not found, try the mangled name */
599 s = javastring_new(newname);
601 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
612 /* If not found, try to find the native function symbol in the
616 f = native_method_find(m);
620 printf("internal ]\n");
623 #if defined(ENABLE_JVMTI)
624 /* fire Native Method Bind event */
625 if (jvmti) jvmti_NativeMethodBind(m, f, &f);
628 /* no symbol found? throw exception */
632 printf("failed ]\n");
634 exceptions_throw_unsatisfiedlinkerror(m->name);
641 /* native_library_open *********************************************************
643 Open a native library with the given utf8 name.
646 filename ... filename of the library to open
649 handle of the opened library
651 *******************************************************************************/
653 #if defined(ENABLE_LTDL)
654 lt_dlhandle native_library_open(utf *filename)
658 if (opt_verbosejni) {
659 printf("[Loading native library ");
660 utf_display_printable_ascii(filename);
664 /* try to open the library */
666 handle = lt_dlopen(filename->text);
668 if (handle == NULL) {
670 printf("failed ]\n");
674 log_print("native_library_open: lt_dlopen failed: ");
675 log_print(lt_dlerror());
690 /* native_library_close ********************************************************
692 Close the native library of the given handle.
695 handle ... handle of the open library
697 *******************************************************************************/
699 #if defined(ENABLE_LTDL)
700 void native_library_close(lt_dlhandle handle)
704 if (opt_verbosejni) {
705 printf("[Unloading native library ");
706 /* utf_display_printable_ascii(filename); */
710 /* Close the library. */
712 result = lt_dlclose(handle);
717 log_print("native_library_close: lt_dlclose failed: ");
718 log_print(lt_dlerror());
726 /* native_library_add **********************************************************
728 Adds an entry to the native library hashtable.
730 *******************************************************************************/
732 #if defined(ENABLE_LTDL)
733 void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
735 hashtable_library_loader_entry *le;
736 hashtable_library_name_entry *ne; /* library name */
737 u4 key; /* hashkey */
738 u4 slot; /* slot in hashtable */
740 LOCK_MONITOR_ENTER(hashtable_library->header);
742 /* normally addresses are aligned to 4, 8 or 16 bytes */
744 key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
745 slot = key & (hashtable_library->size - 1);
746 le = hashtable_library->ptr[slot];
748 /* search external hash chain for the entry */
751 if (le->loader == loader)
754 le = le->hashlink; /* next element in external chain */
757 /* no loader found? create a new entry */
760 le = NEW(hashtable_library_loader_entry);
765 /* insert entry into hashtable */
768 (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
769 hashtable_library->ptr[slot] = le;
771 /* update number of hashtable-entries */
773 hashtable_library->entries++;
777 /* search for library name */
782 if (ne->name == filename) {
783 LOCK_MONITOR_EXIT(hashtable_library->header);
788 ne = ne->hashlink; /* next element in external chain */
791 /* not found? add the library name to the classloader */
793 ne = NEW(hashtable_library_name_entry);
798 /* insert entry into external chain */
800 ne->hashlink = le->namelink;
803 LOCK_MONITOR_EXIT(hashtable_library->header);
808 /* native_library_find *********************************************************
810 Find an entry in the native library hashtable.
812 *******************************************************************************/
814 #if defined(ENABLE_LTDL)
815 hashtable_library_name_entry *native_library_find(utf *filename,
818 hashtable_library_loader_entry *le;
819 hashtable_library_name_entry *ne; /* library name */
820 u4 key; /* hashkey */
821 u4 slot; /* slot in hashtable */
823 /* normally addresses are aligned to 4, 8 or 16 bytes */
825 key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
826 slot = key & (hashtable_library->size - 1);
827 le = hashtable_library->ptr[slot];
829 /* search external hash chain for the entry */
832 if (le->loader == loader)
835 le = le->hashlink; /* next element in external chain */
838 /* no loader found? return NULL */
843 /* search for library name */
848 if (ne->name == filename)
851 ne = ne->hashlink; /* next element in external chain */
854 /* return entry, if no entry was found, ne is NULL */
861 /* native_new_and_init *********************************************************
863 Creates a new object on the heap and calls the initializer.
864 Returns the object pointer or NULL if memory is exhausted.
866 *******************************************************************************/
868 java_handle_t *native_new_and_init(classinfo *c)
874 vm_abort("native_new_and_init: c == NULL");
883 /* try to find the initializer */
885 m = class_findmethod(c, utf_init, utf_void__void);
887 /* ATTENTION: returning the object here is ok, since the class may
888 not have an initializer */
893 /* call initializer */
895 (void) vm_call_method(m, o);
901 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
907 vm_abort("native_new_and_init_string: c == NULL");
916 /* find initializer */
918 m = class_findmethod(c, utf_init, utf_java_lang_String__void);
920 /* initializer not found */
925 /* call initializer */
927 (void) vm_call_method(m, o, s);
934 * These are local overrides for various environment variables in Emacs.
935 * Please do not remove this and leave it at the end of the file, where
936 * Emacs will automagically detect them.
937 * ---------------------------------------------------------------------
940 * indent-tabs-mode: t
944 * vim:noexpandtab:sw=4:ts=4: