* src/vm/hook.hpp: Added new file for hook points.
[cacao.git] / src / native / native.cpp
index a53f8415239be4fad01430d32aa759f86d4c2cff..e5e2c7c6272ec3aae80fce5c56006960ea78f5c2 100644 (file)
@@ -1,6 +1,6 @@
 /* src/native/native.cpp - native library support
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -34,7 +34,7 @@
 #include <functional>
 #include <map>
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "native/jni.hpp"
 #include "native/native.hpp"
@@ -47,6 +47,7 @@
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.hpp"
 
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
 
 /* native_make_overloaded_function *********************************************
 
@@ -391,18 +388,30 @@ void* NativeMethods::resolve_method(methodinfo* m)
        utf* newname = native_make_overloaded_function(name, m->descriptor);
 
        // Try to find the symbol.
-       void* symbol = NULL;
+       void* symbol;
+
+       // Try to find the native method symbol in the native methods registered
+       // with the VM.
+       symbol = find_registered_method(m);
+
+       if (symbol != NULL)
+               if (opt_verbosejni)
+                       printf("internal ]\n");
 
 #if defined(ENABLE_DL)
-       // Get the classloader.
-       classloader_t* classloader = class_get_classloader(m->clazz);
+       classloader_t* classloader;
+       if (symbol == NULL) {
+               // Get the classloader.
+               classloader = class_get_classloader(m->clazz);
 
-       // Resolve the native method name from the native libraries.
-       NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
-       symbol = libraries.resolve_symbol(name, classloader);
+               // Resolve the native method name from the native libraries.
+               NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
 
-       if (symbol == NULL)
-               symbol = libraries.resolve_symbol(newname, classloader);
+               symbol = libraries.resolve_symbol(name, classloader);
+
+               if (symbol == NULL)
+                       symbol = libraries.resolve_symbol(newname, classloader);
+       }
 
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        if (symbol == NULL) {
@@ -417,17 +426,16 @@ void* NativeMethods::resolve_method(methodinfo* m)
                                                                         class_java_lang_ClassLoader,
                                                                         true);
 
-               if (method_findNative == NULL)
-                       return NULL;
-
-               // Try the normal name.
-               java_handle_t* s = javastring_new(name);
-               symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
-
-               // If not found, try the mangled name.
-               if (symbol == NULL) {
-                       s = javastring_new(newname);
+               if (method_findNative != NULL) {
+                       // Try the normal name.
+                       java_handle_t* s = javastring_new(name);
                        symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+
+                       // If not found, try the mangled name.
+                       if (symbol == NULL) {
+                               s = javastring_new(newname);
+                               symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+                       }
                }
        }
 # endif
@@ -437,21 +445,6 @@ void* NativeMethods::resolve_method(methodinfo* m)
                        printf("JNI ]\n");
 #endif
 
-       // If not found already, try to find the native method symbol in
-       // the native methods registered with the VM.
-       if (symbol == NULL) {
-               symbol = find_registered_method(m);
-
-               if (symbol != NULL)
-                       if (opt_verbosejni)
-                               printf("internal ]\n");
-       }
-
-#if defined(ENABLE_JVMTI)
-       /* fire Native Method Bind event */
-       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
-#endif
-
        // Symbol not found?  Throw an exception.
        if (symbol == NULL) {
                if (opt_verbosejni)
@@ -460,6 +453,9 @@ void* NativeMethods::resolve_method(methodinfo* m)
                exceptions_throw_unsatisfiedlinkerror(m->name);
        }
 
+       // Hook point just after method resolving finished.
+       Hook::native_resolved(m, symbol, &symbol);
+
        return symbol;
 }
 
@@ -727,6 +723,110 @@ void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloade
 }
 
 
+/**
+ * Registers a new native agent by specified by it's library name
+ * and with an optional options string.
+ *
+ * @param library Name of the native agent library.
+ * @param options The options string or NULL if not specified.
+ */
+#if defined(ENABLE_JVMTI)
+void NativeAgents::register_agent_library(char* library, char* options)
+{
+       NativeAgent na(library, options);
+
+       // Insert native agent into list of agents.
+       _agents.push_back(na);
+}
+#endif
+
+
+/**
+ * Registers a new native agent by specified by a path to it's library
+ * and with an optional options string.
+ *
+ * @param path Path of the native agent library.
+ * @param options The options string or NULL if not specified.
+ */
+#if defined(ENABLE_JVMTI)
+void NativeAgents::register_agent_path(char* path, char* options)
+{
+       os::abort("NativeAgents::register_agent_library: Implement me!");
+}
+#endif
+
+
+/**
+ * Loads all registered native agents and in turn calls their exported
+ * start-up functions (Agent_OnLoad). If one of the agents reports an
+ * error during start-up, the loading is stopped.
+ *
+ * @return True if all agents were loaded successfully, false if
+ * one of them was not found or reported an error.
+ */
+#if defined(ENABLE_JVMTI)
+bool NativeAgents::load_agents()
+{
+       // Iterate over all registered agents.
+       for (std::vector<NativeAgent>::iterator it = _agents.begin(); it != _agents.end(); ++it) {
+               NativeAgent& na = *(it);
+
+               // Construct agent library name.
+               size_t len =
+                       os::strlen(NATIVE_LIBRARY_PREFIX) +
+                       os::strlen(na.get_library()) +
+                       os::strlen(NATIVE_LIBRARY_SUFFIX) +
+                       os::strlen("0");
+
+               char* p = MNEW(char, len);
+
+               os::strcpy(p, NATIVE_LIBRARY_PREFIX);
+               os::strcat(p, na.get_library());
+               os::strcat(p, NATIVE_LIBRARY_SUFFIX);
+
+               utf* u = utf_new_char(p);
+
+               MFREE(p, char, len);
+
+               // Construct new native library.
+               NativeLibrary nl(u);
+
+               // Try to open the library.
+               if (nl.open() == NULL)
+                       return false;
+
+               // Resolve Agent_OnLoad function.
+               void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
+
+               // Call Agent_OnLoad function if present.
+               if (onload != NULL) {
+                       JNIEXPORT jint (JNICALL *Agent_OnLoad) (JavaVM*, char*, void*);
+                       JavaVM* vm = VM::get_current()->get_javavm();
+
+                       Agent_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, char*, void*)) (uintptr_t) onload;
+
+                       jint result = Agent_OnLoad(vm, na.get_options(), NULL);
+
+                       // Check for error in Agent_OnLoad.
+                       if (result != 0) {
+                               nl.close();
+                               return false;
+                       }
+               }
+
+               // According to the interface spec, the library _must_ export
+               // a start-up function.
+               else {
+                       log_println("NativeAgents::load_agents: Native agent library does not export Agent_OnLoad");
+                       return false;
+               }
+       }
+
+       return true;
+}
+#endif
+
+
 /* native_new_and_init *********************************************************
 
    Creates a new object on the heap and calls the initializer.