1 /* src/native/native.c - table of native functions
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
41 #include "mm/memory.h"
43 #include "native/jni.h"
44 #include "native/native.h"
46 #include "native/vm/nativevm.h"
48 #include "threads/lock-common.h"
50 #include "toolbox/avl.h"
51 #include "toolbox/hashtable.h"
52 #include "toolbox/logging.h"
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/stringlocal.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/jit.h"
63 #include "vmcore/loader.h"
64 #include "vmcore/options.h"
65 #include "vm/resolve.h"
67 #if defined(ENABLE_JVMTI)
68 #include "native/jvmti/cacaodbg.h"
72 /* global variables ***********************************************************/
74 static avl_tree_t *tree_native_methods;
76 #if defined(ENABLE_LTDL)
77 static hashtable *hashtable_library;
81 /* prototypes *****************************************************************/
83 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
86 /* native_init *****************************************************************
88 Initializes the native subsystem.
90 *******************************************************************************/
92 bool native_init(void)
94 #if defined(ENABLE_LTDL)
95 /* initialize libltdl */
98 vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
100 /* initialize library hashtable, 10 entries should be enough */
102 hashtable_library = NEW(hashtable);
104 hashtable_create(hashtable_library, 10);
107 /* initialize the native methods table */
109 tree_native_methods = avl_create(&native_tree_native_methods_comparator);
111 /* everything's ok */
117 /* native_tree_native_methods_comparator ***************************************
119 Comparison function for AVL tree of native methods.
122 treenode....node in the tree
123 node........node to compare with tree-node
128 *******************************************************************************/
130 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
132 const native_methods_node_t *treenmn;
133 const native_methods_node_t *nmn;
138 /* these are for walking the tree */
140 if (treenmn->classname < nmn->classname)
142 else if (treenmn->classname > nmn->classname)
145 if (treenmn->name < nmn->name)
147 else if (treenmn->name > nmn->name)
150 if (treenmn->descriptor < nmn->descriptor)
152 else if (treenmn->descriptor > nmn->descriptor)
155 /* all pointers are equal, we have found the entry */
161 /* native_make_overloaded_function *********************************************
165 *******************************************************************************/
167 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
179 dumpsize = dump_size();
181 utf_ptr = descriptor->text;
182 namelen = strlen(name->text) + strlen("__") + strlen("0");
184 /* calculate additional length */
186 while ((c = utf_nextu2(&utf_ptr)) != ')') {
203 while (utf_nextu2(&utf_ptr) != ';')
214 /* reallocate memory */
216 i = strlen(name->text);
218 newname = DMNEW(char, namelen);
219 MCOPY(newname, name->text, char, i);
221 utf_ptr = descriptor->text;
226 while ((c = utf_nextu2(&utf_ptr)) != ')') {
244 while ((c = utf_nextu2(&utf_ptr)) != ';')
245 if (((c >= 'a') && (c <= 'z')) ||
246 ((c >= 'A') && (c <= 'Z')) ||
247 ((c >= '0') && (c <= '9')))
265 /* make a utf-string */
267 u = utf_new_char(newname);
271 dump_release(dumpsize);
277 /* native_insert_char **********************************************************
279 Inserts the passed UTF character into the native method name. If
280 necessary it is escaped properly.
282 *******************************************************************************/
284 static s4 native_insert_char(char *name, u4 pos, u2 c)
292 /* replace '/' or '.' with '_' */
297 /* escape sequence for '_' is '_1' */
303 /* escape sequence for ';' is '_2' */
309 /* escape sequence for '[' is '_1' */
318 /* unicode character */
322 for (i = 0; i < 4; ++i) {
324 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
333 /* return the new buffer index */
339 /* native_method_symbol ********************************************************
341 Generate a method-symbol string out of the class name and the
344 *******************************************************************************/
346 static utf *native_method_symbol(utf *classname, utf *methodname)
359 dumpsize = dump_size();
361 /* Calculate length of native function name. We multiply the
362 class and method name length by 6 as this is the maxium
363 escape-sequence that can be generated (unicode). */
367 utf_get_number_of_u2s(classname) * 6 +
369 utf_get_number_of_u2s(methodname) * 6 +
372 /* allocate memory */
374 name = DMNEW(char, namelen);
376 /* generate name of native functions */
378 strcpy(name, "Java_");
379 pos = strlen("Java_");
381 utf_ptr = classname->text;
382 utf_endptr = UTF_END(classname);
384 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
386 pos = native_insert_char(name, pos, c);
389 /* seperator between class and method */
393 utf_ptr = methodname->text;
394 utf_endptr = UTF_END(methodname);
396 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
398 pos = native_insert_char(name, pos, c);
405 /* check for an buffer overflow */
407 assert(pos <= namelen);
409 /* make a utf-string */
411 u = utf_new_char(name);
415 dump_release(dumpsize);
421 /* native_method_register ******************************************************
423 Register a native method in the native method table.
425 *******************************************************************************/
427 void native_method_register(utf *classname, const JNINativeMethod *methods,
430 native_methods_node_t *nmn;
435 /* insert all methods passed */
437 for (i = 0; i < count; i++) {
438 if (opt_verbosejni) {
439 printf("[Registering JNI native method ");
440 utf_display_printable_ascii_classname(classname);
441 printf(".%s]\n", methods[i].name);
444 /* generate the utf8 names */
446 name = utf_new_char(methods[i].name);
447 descriptor = utf_new_char(methods[i].signature);
449 /* allocate a new tree node */
451 nmn = NEW(native_methods_node_t);
453 nmn->classname = classname;
455 nmn->descriptor = descriptor;
456 nmn->function = (functionptr) (ptrint) methods[i].fnPtr;
458 /* insert the method into the tree */
460 avl_insert(tree_native_methods, nmn);
465 /* native_method_find **********************************************************
467 Find a native method in the native method table.
469 *******************************************************************************/
471 static functionptr native_method_find(methodinfo *m)
473 native_methods_node_t tmpnmn;
474 native_methods_node_t *nmn;
476 /* fill the temporary structure used for searching the tree */
478 tmpnmn.classname = m->class->name;
479 tmpnmn.name = m->name;
480 tmpnmn.descriptor = m->descriptor;
482 /* find the entry in the AVL-tree */
484 nmn = avl_find(tree_native_methods, &tmpnmn);
489 return nmn->function;
493 /* native_method_resolve *******************************************************
495 Resolves a native method, maybe from a dynamic library.
498 m ... methodinfo of the native Java method to resolve
501 pointer to the resolved method (symbol)
503 *******************************************************************************/
505 functionptr native_method_resolve(methodinfo *m)
510 #if defined(ENABLE_LTDL)
512 hashtable_library_loader_entry *le;
513 hashtable_library_name_entry *ne;
514 u4 key; /* hashkey */
515 u4 slot; /* slot in hashtable */
517 #if defined(WITH_CLASSPATH_SUN)
518 methodinfo *method_findNative;
524 if (opt_verbosejni) {
525 printf("[Dynamic-linking native method ");
526 utf_display_printable_ascii_classname(m->class->name);
528 utf_display_printable_ascii(m->name);
532 /* generate method symbol string */
534 name = native_method_symbol(m->class->name, m->name);
536 /* generate overloaded function (having the types in it's name) */
538 newname = native_make_overloaded_function(name, m->descriptor);
540 /* check the library hash entries of the classloader of the
545 #if defined(ENABLE_LTDL)
546 /* Get the classloader. */
548 cl = class_get_classloader(m->class);
550 /* normally addresses are aligned to 4, 8 or 16 bytes */
552 key = ((u4) (ptrint) cl) >> 4; /* align to 16-byte */
553 slot = key & (hashtable_library->size - 1);
554 le = hashtable_library->ptr[slot];
556 /* iterate through loaders in this hash slot */
558 while ((le != NULL) && (f == NULL)) {
559 /* iterate through names in this loader */
563 while ((ne != NULL) && (f == NULL)) {
564 f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
567 f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
575 # if defined(WITH_CLASSPATH_SUN)
577 /* We can resolve the function directly from
578 java.lang.ClassLoader as it's a static function. */
579 /* XXX should be done in native_init */
582 class_resolveclassmethod(class_java_lang_ClassLoader,
584 utf_java_lang_ClassLoader_java_lang_String__J,
585 class_java_lang_ClassLoader,
588 if (method_findNative == NULL)
591 /* try the normal name */
593 s = javastring_new(name);
595 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
598 /* if not found, try the mangled name */
601 s = javastring_new(newname);
603 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
614 /* If not found, try to find the native function symbol in the
618 f = native_method_find(m);
622 printf("internal ]\n");
625 #if defined(ENABLE_JVMTI)
626 /* fire Native Method Bind event */
627 if (jvmti) jvmti_NativeMethodBind(m, f, &f);
630 /* no symbol found? throw exception */
634 printf("failed ]\n");
636 exceptions_throw_unsatisfiedlinkerror(m->name);
643 /* native_library_open *********************************************************
645 Open a native library with the given utf8 name.
647 *******************************************************************************/
649 #if defined(ENABLE_LTDL)
650 lt_dlhandle native_library_open(utf *filename)
654 if (opt_verbosejni) {
655 printf("[Loading native library ");
656 utf_display_printable_ascii(filename);
660 /* try to open the library */
662 handle = lt_dlopen(filename->text);
664 if (handle == NULL) {
667 log_print("native_library_load: lt_dlopen failed: ");
668 log_print(lt_dlerror());
680 /* native_library_add **********************************************************
682 Adds an entry to the native library hashtable.
684 *******************************************************************************/
686 #if defined(ENABLE_LTDL)
687 void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
689 hashtable_library_loader_entry *le;
690 hashtable_library_name_entry *ne; /* library name */
691 u4 key; /* hashkey */
692 u4 slot; /* slot in hashtable */
694 LOCK_MONITOR_ENTER(hashtable_library->header);
696 /* normally addresses are aligned to 4, 8 or 16 bytes */
698 key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
699 slot = key & (hashtable_library->size - 1);
700 le = hashtable_library->ptr[slot];
702 /* search external hash chain for the entry */
705 if (le->loader == loader)
708 le = le->hashlink; /* next element in external chain */
711 /* no loader found? create a new entry */
714 le = NEW(hashtable_library_loader_entry);
719 /* insert entry into hashtable */
722 (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
723 hashtable_library->ptr[slot] = le;
725 /* update number of hashtable-entries */
727 hashtable_library->entries++;
731 /* search for library name */
736 if (ne->name == filename) {
737 LOCK_MONITOR_EXIT(hashtable_library->header);
742 ne = ne->hashlink; /* next element in external chain */
745 /* not found? add the library name to the classloader */
747 ne = NEW(hashtable_library_name_entry);
752 /* insert entry into external chain */
754 ne->hashlink = le->namelink;
757 LOCK_MONITOR_EXIT(hashtable_library->header);
762 /* native_library_find *********************************************************
764 Find an entry in the native library hashtable.
766 *******************************************************************************/
768 #if defined(ENABLE_LTDL)
769 hashtable_library_name_entry *native_library_find(utf *filename,
772 hashtable_library_loader_entry *le;
773 hashtable_library_name_entry *ne; /* library name */
774 u4 key; /* hashkey */
775 u4 slot; /* slot in hashtable */
777 /* normally addresses are aligned to 4, 8 or 16 bytes */
779 key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
780 slot = key & (hashtable_library->size - 1);
781 le = hashtable_library->ptr[slot];
783 /* search external hash chain for the entry */
786 if (le->loader == loader)
789 le = le->hashlink; /* next element in external chain */
792 /* no loader found? return NULL */
797 /* search for library name */
802 if (ne->name == filename)
805 ne = ne->hashlink; /* next element in external chain */
808 /* return entry, if no entry was found, ne is NULL */
815 /* native_new_and_init *********************************************************
817 Creates a new object on the heap and calls the initializer.
818 Returns the object pointer or NULL if memory is exhausted.
820 *******************************************************************************/
822 java_handle_t *native_new_and_init(classinfo *c)
828 vm_abort("native_new_and_init: c == NULL");
837 /* try to find the initializer */
839 m = class_findmethod(c, utf_init, utf_void__void);
841 /* ATTENTION: returning the object here is ok, since the class may
842 not have an initializer */
847 /* call initializer */
849 (void) vm_call_method(m, o);
855 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
861 vm_abort("native_new_and_init_string: c == NULL");
870 /* find initializer */
872 m = class_findmethod(c, utf_init, utf_java_lang_String__void);
874 /* initializer not found */
879 /* call initializer */
881 (void) vm_call_method(m, o, s);
888 * These are local overrides for various environment variables in Emacs.
889 * Please do not remove this and leave it at the end of the file, where
890 * Emacs will automagically detect them.
891 * ---------------------------------------------------------------------
894 * indent-tabs-mode: t
898 * vim:noexpandtab:sw=4:ts=4: