mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
286 lines
8.7 KiB
C++
286 lines
8.7 KiB
C++
// -*- C++ -*-
|
|
//
|
|
// $Id: OS_NS_dlfcn.inl 85341 2009-05-14 11:07:37Z johnnyw $
|
|
|
|
#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_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 = 0;
|
|
# 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)
|
|
//FUZZ: disable check_for_lack_ACE_OS
|
|
ACE_OSCALL_RETURN (::strerror(errno), char *, 0);
|
|
//FUZZ: enable check_for_lack_ACE_OS
|
|
# 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_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 = 0;
|
|
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;
|
|
char *value = 0;
|
|
STATUS status;
|
|
ACE_OSCALL (::symFindByName(sysSymTbl, symbolname, &value, &symtype), int, -1, status);
|
|
|
|
return status == OK ? reinterpret_cast <void*>(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
|