diff options
Diffstat (limited to 'ACE/ace/OS_NS_dlfcn.inl')
-rw-r--r-- | ACE/ace/OS_NS_dlfcn.inl | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/ACE/ace/OS_NS_dlfcn.inl b/ACE/ace/OS_NS_dlfcn.inl new file mode 100644 index 00000000000..6c4caeaf3e8 --- /dev/null +++ b/ACE/ace/OS_NS_dlfcn.inl @@ -0,0 +1,284 @@ +// -*- C++ -*- +// +// $Id$ + +#include "ace/OS_NS_macros.h" +#include "ace/OS_NS_errno.h" +#include "ace/OS_NS_fcntl.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Default_Constants.h" +#include "ace/os_include/os_fcntl.h" +#include "ace/os_include/os_string.h" + +#if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP) +# include "ace/OS_NS_stdio.h" +#endif + +#if defined (ACE_USES_ASM_SYMBOL_IN_DLSYM) +# include "ace/OS_Memory.h" +# include "ace/OS_NS_string.h" +#endif /* ACE_USES_ASM_SYMBOL_IN_DLSYM */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_INLINE int +ACE_OS::dlclose (ACE_SHLIB_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::dlclose"); +#if defined (ACE_LACKS_DLCLOSE) + ACE_UNUSED_ARG (handle); + return 0; +#elif defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + +# if !defined (ACE_HAS_AUTOMATIC_INIT_FINI) + // SunOS4 does not automatically call _fini()! + void *ptr; + + ACE_OSCALL (::dlsym (handle, ACE_LIB_TEXT ("_fini")), void *, 0, ptr); + + if (ptr != 0) + (*((int (*)(void)) ptr)) (); // Call _fini hook explicitly. +# endif /* ACE_HAS_AUTOMATIC_INIT_FINI */ +#if defined (_M_UNIX) + ACE_OSCALL_RETURN (::_dlclose (handle), int, -1); +#else /* _MUNIX */ + ACE_OSCALL_RETURN (::dlclose (handle), int, -1); +#endif /* _M_UNIX */ +#elif defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::FreeLibrary (handle), ace_result_), int, -1); +#elif defined (__hpux) + // HP-UX 10.x and 32-bit 11.00 do not pay attention to the ref count + // when unloading a dynamic lib. So, if the ref count is more than + // 1, do not unload the lib. This will cause a library loaded more + // than once to not be unloaded until the process runs down, but + // that's life. It's better than unloading a library that's in use. + // So far as I know, there's no way to decrement the refcnt that the + // kernel is looking at - the shl_descriptor is a copy of what the + // kernel has, not the actual struct. On 64-bit HP-UX using dlopen, + // this problem has been fixed. + struct shl_descriptor desc; + if (shl_gethandle_r (handle, &desc) == -1) + return -1; + if (desc.ref_count > 1) + return 0; +# if defined(__GNUC__) || __cplusplus >= 199707L + ACE_OSCALL_RETURN (::shl_unload (handle), int, -1); +# else + ACE_OSCALL_RETURN (::cxxshl_unload (handle), int, -1); +# endif /* aC++ vs. Hp C++ */ +#else + ACE_UNUSED_ARG (handle); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE ACE_TCHAR * +ACE_OS::dlerror (void) +{ + ACE_OS_TRACE ("ACE_OS::dlerror"); +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + const char *err; +# if defined(_M_UNIX) + ACE_OSCALL (::_dlerror (), const char *, 0, err); +# else /* _M_UNIX */ + ACE_OSCALL (::dlerror (), const char *, 0, err); +# endif /* _M_UNIX */ + if (err == 0) + return 0; +# if defined (ACE_USES_WCHAR) + const size_t BufLen = 256; + static wchar_t buf[BufLen]; + ACE_OS::strncpy (buf, ACE_TEXT_CHAR_TO_TCHAR (err), BufLen); + return buf; +# else + return const_cast <char *> (err); +# endif /* ACE_USES_WCHAR */ +# elif defined (__hpux) || defined (ACE_VXWORKS) + ACE_OSCALL_RETURN (::strerror(errno), char *, 0); +# elif defined (ACE_WIN32) + static ACE_TCHAR buf[128]; +# if defined (ACE_HAS_PHARLAP) + ACE_OS::sprintf (buf, "error code %d", GetLastError()); +# else + ACE_TEXT_FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, + 0, + ::GetLastError (), + 0, + buf, + sizeof buf / sizeof buf[0], + 0); +# endif /* ACE_HAS_PHARLAP */ + return buf; +# else + ACE_NOTSUP_RETURN (0); +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE ACE_SHLIB_HANDLE +ACE_OS::dlopen (const ACE_TCHAR *fname, + int mode) +{ + ACE_OS_TRACE ("ACE_OS::dlopen"); + +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + void *handle; +# if defined (ACE_HAS_SGIDLADD) + ACE_OSCALL + (::sgidladd (ACE_TEXT_ALWAYS_CHAR (fname), mode), void *, 0, handle); +# elif defined (_M_UNIX) + ACE_OSCALL + (::_dlopen (ACE_TEXT_ALWAYS_CHAR (fname), mode), void *, 0, handle); +# else + ACE_OSCALL + (::dlopen (ACE_TEXT_ALWAYS_CHAR (fname), mode), void *, 0, handle); +# endif /* ACE_HAS_SGIDLADD */ +# if !defined (ACE_HAS_AUTOMATIC_INIT_FINI) + if (handle != 0) + { + void *ptr; + // Some systems (e.g., SunOS4) do not automatically call _init(), so + // we'll have to call it manually. + + ACE_OSCALL (::dlsym (handle, ACE_LIB_TEXT ("_init")), void *, 0, ptr); + + if (ptr != 0 && (*((int (*)(void)) ptr)) () == -1) // Call _init hook explicitly. + { + // Close down the handle to prevent leaks. + ::dlclose (handle); + return 0; + } + } +# endif /* ACE_HAS_AUTOMATIC_INIT_FINI */ + return handle; +# elif defined (ACE_WIN32) + ACE_UNUSED_ARG (mode); + + ACE_WIN32CALL_RETURN (ACE_TEXT_LoadLibrary (fname), ACE_SHLIB_HANDLE, 0); +# elif defined (__hpux) + +# if defined(__GNUC__) || __cplusplus >= 199707L + ACE_OSCALL_RETURN (::shl_load(fname, mode, 0L), ACE_SHLIB_HANDLE, 0); +# else + ACE_OSCALL_RETURN (::cxxshl_load(fname, mode, 0L), ACE_SHLIB_HANDLE, 0); +# endif /* aC++ vs. Hp C++ */ +# elif defined (ACE_VXWORKS) && !defined (__RTP__) + MODULE* handle = 0; + // Open readonly + ACE_HANDLE filehandle = ACE_OS::open (fname, + O_RDONLY, + ACE_DEFAULT_FILE_PERMS); + + if (filehandle != ACE_INVALID_HANDLE) + { + ACE_OS::last_error(0); + ACE_OSCALL ( ::loadModule (filehandle, LOAD_GLOBAL_SYMBOLS|LOAD_COMMON_MATCH_ALL ), MODULE *, 0, handle); + int loaderror = ACE_OS::last_error(); + ACE_OS::close (filehandle); + + if ( (loaderror != 0) && (handle != 0) ) + { + // ouch something went wrong most likely unresolved externals + if (handle) + ::unldByModuleId ( handle, 0 ); + handle = 0; + } + } + else + { + // couldn't open file + handle = 0; + } + return handle; +# else + ACE_UNUSED_ARG (fname); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (0); +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE void * +ACE_OS::dlsym (ACE_SHLIB_HANDLE handle, + const ACE_TCHAR *sname) +{ + ACE_OS_TRACE ("ACE_OS::dlsym"); + +#if defined (ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE) + // Check if the handle is valid before making any calls using it. + if (handle == ACE_SHLIB_INVALID_HANDLE) + return 0; +#endif /* ACE_HAS_DLSYM_SEGFAULT_ON_INVALID_HANDLE */ + + // Get the correct OS type. +#if defined (ACE_HAS_WINCE) + // CE (at least thru Pocket PC 2003) offers GetProcAddressW, not ...A, so + // we always need a wide-char string. + const wchar_t *symbolname = 0; +# if defined (ACE_USES_WCHAR) + symbolname = sname; +# else + ACE_Ascii_To_Wide sname_xlate (sname); + symbolname = sname_xlate.wchar_rep (); +# endif /* ACE_USES_WCHAR */ +#elif defined (ACE_USES_WCHAR) + // WinCE is WCHAR always; other platforms need a char * symbol name + ACE_Wide_To_Ascii w_sname (sname); + char *symbolname = w_sname.char_rep (); +#elif defined (ACE_VXWORKS) + char *symbolname = const_cast<char *> (sname); +#else + const char *symbolname = sname; +#endif /* ACE_HAS_WINCE */ + +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + +# if defined (ACE_USES_ASM_SYMBOL_IN_DLSYM) + int l = ACE_OS::strlen (symbolname) + 2; + char *asm_symbolname = 0; + ACE_NEW_RETURN (asm_symbolname, char[l], 0); + ACE_OS::strcpy (asm_symbolname, "_") ; + ACE_OS::strcpy (asm_symbolname + 1, symbolname) ; + void *ace_result; + ACE_OSCALL (::dlsym (handle, asm_symbolname), void *, 0, ace_result); + delete [] asm_symbolname; + return ace_result; +# elif defined (_M_UNIX) + ACE_OSCALL_RETURN (::_dlsym (handle, symbolname), void *, 0); +# else + ACE_OSCALL_RETURN (::dlsym (handle, symbolname), void *, 0); +# endif /* ACE_USES_ASM_SYMBOL_IN_DLSYM */ + +# elif defined (ACE_WIN32) + + ACE_WIN32CALL_RETURN (::GetProcAddress (handle, symbolname), void *, 0); + +# elif defined (__hpux) + + void *value; + int status; + shl_t _handle = handle; + ACE_OSCALL (::shl_findsym(&_handle, symbolname, TYPE_UNDEFINED, &value), int, -1, status); + return status == 0 ? value : 0; + +# elif defined (ACE_VXWORKS) && !defined (__RTP__) + + // For now we use the VxWorks global symbol table + // which resolves the most recently loaded symbols .. which resolve mostly what we want.. + ACE_UNUSED_ARG (handle); + SYM_TYPE symtype; + void *value = 0; + STATUS status; + ACE_OSCALL (::symFindByName(sysSymTbl, symbolname, (char **)&value, &symtype), int, -1, status); + + return status == OK ? value : 0; + +# else + + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (symbolname); + ACE_NOTSUP_RETURN (0); + +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_END_VERSIONED_NAMESPACE_DECL |