| // natSharedLibLoader.cc - Implementation of SharedLibHelper native methods. |
| |
| /* Copyright (C) 2001, 2003, 2004, 2005, 2006 Free Software Foundation |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| #include <config.h> |
| #include <platform.h> |
| |
| #include <gcj/cni.h> |
| #include <jvm.h> |
| #include <execution.h> |
| |
| #include <gnu/gcj/runtime/SharedLibHelper.h> |
| #include <java/io/IOException.h> |
| #include <java/lang/UnsupportedOperationException.h> |
| #include <java/lang/UnknownError.h> |
| |
| #include <java/lang/VMClassLoader.h> |
| |
| // If we're using the Boehm GC, then we need this include to override dlopen. |
| #ifdef HAVE_BOEHM_GC |
| // Set GC_DEBUG before including gc.h! |
| #ifdef LIBGCJ_GC_DEBUG |
| # define GC_DEBUG |
| #endif |
| #include <gc.h> |
| #endif /* HAVE_BOEHM_GC */ |
| |
| #ifdef HAVE_DLOPEN |
| #include <dlfcn.h> |
| |
| /* Only used during dlopen, while having a lock on Class.class. */ |
| static java::lang::ClassLoader *curLoader; |
| static gnu::gcj::runtime::SharedLibHelper *curHelper; |
| |
| typedef void (*ClassHookFunc) (jclass); |
| typedef void (*CoreHookFunc) (_Jv_core_chain *); |
| |
| void |
| _Jv_sharedlib_register_hook (jclass cls) |
| { |
| cls->protectionDomain = curHelper->domain; |
| cls->loader = curLoader; |
| if (! cls->engine) |
| cls->engine = &_Jv_soleCompiledEngine; |
| curHelper->registerClass(cls->getName(), cls); |
| } |
| |
| static void |
| core_hook (_Jv_core_chain *chain) |
| { |
| chain->next = (_Jv_core_chain *) curHelper->core_chain; |
| curHelper->core_chain = (gnu::gcj::RawData *) chain; |
| } |
| |
| struct SharedLibDummy |
| { |
| ClassHookFunc saved; |
| CoreHookFunc saved_core; |
| SharedLibDummy() |
| { |
| saved = _Jv_RegisterClassHook; |
| saved_core = _Jv_RegisterCoreHook; |
| } |
| ~SharedLibDummy() |
| { |
| _Jv_RegisterClassHook = saved; |
| _Jv_RegisterCoreHook = saved_core; |
| curLoader = NULL; |
| } |
| }; |
| #endif |
| |
| void |
| gnu::gcj::runtime::SharedLibHelper::init(void) |
| { |
| #ifdef HAVE_DLOPEN |
| char *lname = (char *) __builtin_alloca (JvGetStringUTFLength (baseName) |
| + 1); |
| jsize total = JvGetStringUTFRegion (baseName, 0, baseName->length(), lname); |
| lname[total] = '\0'; |
| |
| if (flags==0) |
| flags = RTLD_GLOBAL | RTLD_LAZY; |
| JvSynchronize dummy1(&java::lang::Class::class$); |
| SharedLibDummy dummy2; |
| curLoader = ((void*)loader == java::lang::VMClassLoader::bootLoader |
| ? NULL : loader); |
| curHelper = this; |
| _Jv_RegisterClassHook = _Jv_sharedlib_register_hook; |
| _Jv_RegisterCoreHook = core_hook; |
| void *h = dlopen(lname, flags); |
| if (h == NULL) |
| { |
| const char *msg = dlerror(); |
| throw new java::lang::UnknownError(JvNewStringLatin1(msg)); |
| } |
| handler = (gnu::gcj::RawData*) h; |
| #else |
| const char *msg |
| = "shared library class loading is not supported on this platform"; |
| throw new java::lang::UnsupportedOperationException(JvNewStringLatin1(msg)); |
| #endif |
| } |
| |
| jboolean |
| gnu::gcj::runtime::SharedLibHelper::hasResource (jstring name) |
| { |
| #ifdef HAVE_DLOPEN |
| _Jv_core_chain *node = _Jv_FindCore ((_Jv_core_chain *) core_chain, name); |
| return node != NULL; |
| #else |
| return false; |
| #endif |
| } |
| |
| gnu::gcj::Core * |
| gnu::gcj::runtime::SharedLibHelper::findCore (jstring name) |
| { |
| #ifdef HAVE_DLOPEN |
| extern gnu::gcj::Core *_Jv_create_core (_Jv_core_chain *node, jstring name); |
| ensureInit(); |
| return _Jv_create_core ((_Jv_core_chain *) core_chain, name); |
| #else |
| return NULL; |
| #endif |
| } |
| |
| void |
| gnu::gcj::runtime::SharedLibHelper::finalize() |
| { |
| _Jv_FreeCoreChain ((_Jv_core_chain *) core_chain); |
| #ifdef HAVE_DLOPEN |
| if (handler) |
| dlclose (handler); |
| #endif |
| } |
| |
| void |
| gnu::gcj::runtime::SharedLibHelper::ensureSupersLinked(jclass k) |
| { |
| _Jv_Linker::wait_for_state (k, JV_STATE_LOADING); |
| } |