diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2c97801f9..c4d02902a 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2011-08-16 Corinna Vinschen + + * autoload.cc (GetModuleHandleExW): Define. + * dlfcn.cc: Throughout mark exported symbols as extern "C". + (dlopen): Unignore flags argument. Define ret to NULL. Fix typo in + comment. Support Glibc flags RTLD_NOLOAD and RTLD_NODELETE. + * include/dlfcn.h: Clean up comments. + (RTLD_NODELETE): Define. + (RTLD_NOLOAD): Define. + (RTLD_DEEPBIND): Define. + 2011-08-15 Corinna Vinschen * pipe.cc (pipe): Just call _pipe with O_BINARY mode. Move code to diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 63355b42b..f8a7a0cbb 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -390,6 +390,7 @@ LoadDLLfunc (GetNetworkParams, 8, iphlpapi) LoadDLLfunc (GetUdpTable, 12, iphlpapi) LoadDLLfuncEx (AttachConsole, 4, kernel32, 1) +LoadDLLfuncEx (GetModuleHandleExW, 12, kernel32, 1) LoadDLLfuncEx (GetNamedPipeClientProcessId, 8, kernel32, 1) LoadDLLfunc (LocaleNameToLCID, 8, kernel32) diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index ff1be8d86..91ffc9a6c 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -67,10 +67,10 @@ get_full_path_of_dll (const char* str, path_conv &real_filename) return false; } -void * -dlopen (const char *name, int) +extern "C" void * +dlopen (const char *name, int flags) { - void *ret; + void *ret = NULL; if (name == NULL) { @@ -82,16 +82,14 @@ dlopen (const char *name, int) { /* handle for the named library */ path_conv pc; - if (!get_full_path_of_dll (name, pc)) - ret = NULL; - else + if (get_full_path_of_dll (name, pc)) { tmp_pathbuf tp; wchar_t *path = tp.w_get (); pc.get_wide_win32_path (path); /* Check if the last path component contains a dot. If so, - leave the filename alone. Otherwise add a traiing dot + leave the filename alone. Otherwise add a trailing dot to override LoadLibrary's automatic adding of a ".dll" suffix. */ wchar_t *last_bs = wcsrchr (path, L'\\'); if (last_bs && !wcschr (last_bs, L'.')) @@ -113,7 +111,23 @@ dlopen (const char *name, int) struct per_process_cxx_malloc *tmp_malloc; tmp_malloc = __cygwin_user_data.cxx_malloc; - ret = (void *) LoadLibraryW (path); + if (!(flags & RTLD_NOLOAD) + || (ret = GetModuleHandleW (path)) != NULL) + { + ret = (void *) LoadLibraryW (path); + if (ret && (flags & RTLD_NODELETE) + && !GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_PIN, path, + (HMODULE *) &ret)) + { + /* Windows 2000 is missing the GetModuleHandleEx call, so we + just use a trick. Call LoadLibrary 10 times more if the + RTLD_NODELETE flag has been specified. That makes it + unlikely (but not impossible) that dlclose will actually + free the library. */ + for (int i = 0; i < 10; ++i) + LoadLibraryW (path); + } + } /* Restore original cxx_malloc pointer. */ __cygwin_user_data.cxx_malloc = tmp_malloc; @@ -130,7 +144,7 @@ dlopen (const char *name, int) return ret; } -void * +extern "C" void * dlsym (void *handle, const char *name) { void *ret = NULL; @@ -176,7 +190,7 @@ dlsym (void *handle, const char *name) return ret; } -int +extern "C" int dlclose (void *handle) { int ret; @@ -191,7 +205,7 @@ dlclose (void *handle) return ret; } -char * +extern "C" char * dlerror () { char *res; diff --git a/winsup/cygwin/include/dlfcn.h b/winsup/cygwin/include/dlfcn.h index 56a7fb4cb..9ffbdb388 100644 --- a/winsup/cygwin/include/dlfcn.h +++ b/winsup/cygwin/include/dlfcn.h @@ -1,6 +1,6 @@ /* dlfcn.h - Copyright 1998, 1999, 2000, 2001, 2010 Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -31,10 +31,18 @@ extern void dlfork (int); #define RTLD_DEFAULT NULL /* valid values for mode argument to dlopen */ -#define RTLD_LOCAL 0 /* symbols in this dlopen'ed obj are not visible to other dlopen'ed objs */ -#define RTLD_LAZY 1 /* lazy function call binding */ -#define RTLD_NOW 2 /* immediate function call binding */ -#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other dlopen'ed objs */ +#define RTLD_LOCAL 0 /* Symbols in this dlopen'ed obj are not */ + /* visible to other dlopen'ed objs. */ +#define RTLD_LAZY 1 /* Lazy function call binding. */ +#define RTLD_NOW 2 /* Immediate function call binding. */ +#define RTLD_GLOBAL 4 /* Symbols in this dlopen'ed obj are visible */ + /* to other dlopen'ed objs. */ +/* Non-standard GLIBC extensions */ +#define RTLD_NODELETE 8 /* Don't unload lib in dlcose. */ +#define RTLD_NOLOAD 16 /* Don't load lib, just return handle if lib */ + /* is already loaded, NULL otherwise. */ +#define RTLD_DEEPBIND 32 /* Place lookup scope so that this lib is */ + /* preferred over global scope. */ #ifdef __cplusplus }