From: Rodrigo Kumpera Date: Tue, 27 Jan 2015 22:58:19 +0000 (-0500) Subject: [utils] Cleanup the dynamic loading code and split the platform specific code into... X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=8b10cef3442563ce07523ccab151826d057de2d2;p=mono.git [utils] Cleanup the dynamic loading code and split the platform specific code into multiple files. This makes the actual code much simpler to read and work with as we can clearly see what's done on each target. --- diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index 20d89c5ea7c..286ef7dae21 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -22,6 +22,9 @@ monoutils_sources = \ mono-counters.c \ mono-compiler.h \ mono-dl.c \ + mono-dl-windows.c \ + mono-dl-darwin.c \ + mono-dl-posix.c \ mono-dl.h \ mono-internal-hash.c \ mono-internal-hash.h \ diff --git a/mono/utils/mono-dl-darwin.c b/mono/utils/mono-dl-darwin.c new file mode 100644 index 00000000000..b1cd30f9045 --- /dev/null +++ b/mono/utils/mono-dl-darwin.c @@ -0,0 +1,53 @@ +/* + * mono-dl.c: Interface to the dynamic linker + * + * Author: + * Mono Team (http://www.mono-project.com) + * + * Copyright 2001-2004 Ximian, Inc. + * Copyright 2004-2009 Novell, Inc. + */ +#include + +#if defined (TARGET_MACH) + +#include "mono/utils/mono-dl.h" +#include "mono/utils/mono-embed.h" +#include "mono/utils/mono-path.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +const char * +mono_dl_get_so_prefix (void) +{ + return "lib"; +} +const char ** +mono_dl_get_so_suffixes (void) +{ + static const char *suffixes[] = { + ".dylib", + ".so", + ".bundle", + "", + }; + return suffixes; +} + +int +mono_dl_get_executable_path (char *buf, int buflen) +{ + uint32_t bsize = buflen; + if (_NSGetExecutablePath (buf, &bsize) == 0) + return strlen (buf); + return -1; +} + +#endif diff --git a/mono/utils/mono-dl-posix.c b/mono/utils/mono-dl-posix.c new file mode 100644 index 00000000000..d6da89da213 --- /dev/null +++ b/mono/utils/mono-dl-posix.c @@ -0,0 +1,93 @@ +/* + * mono-dl.c: Interface to the dynamic linker + * + * Author: + * Mono Team (http://www.mono-project.com) + * + * Copyright 2001-2004 Ximian, Inc. + * Copyright 2004-2009 Novell, Inc. + */ +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#if defined(_POSIX_VERSION) + +#include "mono/utils/mono-dl.h" +#include "mono/utils/mono-embed.h" +#include "mono/utils/mono-path.h" + +#include +#include +#include +#include +#include +#include + +#if !defined (TARGET_MACH) +const char * +mono_dl_get_so_prefix (void) +{ + return "lib"; +} +const char ** +mono_dl_get_so_suffixes (void) +{ + static const char *suffixes[] = { + ".so", + "", + }; + return suffixes; +} + +int +mono_dl_get_executable_path (char *buf, int buflen) +{ + return readlink ("/proc/self/exe", buf, buflen - 1; +} +#endif + +void * +mono_dl_open_file (const char *file, int flags) +{ +#ifdef PLATFORM_ANDROID + /* Bionic doesn't support NULL filenames */ + if (!name) + return NULL; +#endif + return dlopen (file, flags); +} + +void +mono_dl_close_handle (MonoDl *module) +{ + dlclose (module->handle); +} + +void* +mono_dl_lookup_symbol (MonoDl *module, const char *name) +{ + return dlsym (module->handle, name); +} + +int +mono_dl_convert_flags (int flags) +{ + int lflags = flags & MONO_DL_LOCAL? 0: RTLD_GLOBAL; + + if (flags & MONO_DL_LAZY) + lflags |= RTLD_LAZY; + else + lflags |= RTLD_NOW; + return lflags; +} + +char* +mono_dl_current_error_string (void) +{ + return g_strdup (dlerror ()); +} + +#endif diff --git a/mono/utils/mono-dl-windows.c b/mono/utils/mono-dl-windows.c new file mode 100644 index 00000000000..5dabce44835 --- /dev/null +++ b/mono/utils/mono-dl-windows.c @@ -0,0 +1,162 @@ +/* + * mono-dl.c: Interface to the dynamic linker + * + * Author: + * Mono Team (http://www.mono-project.com) + * + * Copyright 2001-2004 Ximian, Inc. + * Copyright 2004-2009 Novell, Inc. + */ +#include + +#if defined(HOST_WIN32) + +#include "mono/utils/mono-dl.h" +#include "mono/utils/mono-embed.h" +#include "mono/utils/mono-path.h" + +#include +#include +#include +#include +#include + +#include +#include + + +const char* +mono_dl_get_so_prefix (void) +{ + return ""; +} + +const char** +mono_dl_get_so_suffixes (void) +{ + static const char *suffixes[] = { + ".dll", + "", + }; + return suffixes; +} + +void* +mono_dl_open_file (const char *file, int flags) +{ + gpointer hModule = NULL; + if (file) { + gunichar2* file_utf16 = g_utf8_to_utf16 (file, strlen (file), NULL, NULL, NULL); + guint last_sem = SetErrorMode (SEM_FAILCRITICALERRORS); + guint32 last_error = 0; + + hModule = LoadLibrary (file_utf16); + if (!hModule) + last_error = GetLastError (); + + SetErrorMode (last_sem); + g_free (file_utf16); + + if (!hModule) + SetLastError (last_error); + } else { + hModule = GetModuleHandle (NULL); + } + return hModule; +} + +void +mono_dl_close_handle (MonoDl *module) +{ + if (!module->main_module) + FreeLibrary (module->handle); +} + +void* +mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name) +{ + HMODULE *modules; + DWORD buffer_size = sizeof (HMODULE) * 1024; + DWORD needed, i; + gpointer proc = NULL; + + /* get the symbol directly from the specified module */ + if (!module->main_module) + return GetProcAddress (module->handle, symbol_name); + + /* get the symbol from the main module */ + proc = GetProcAddress (module->handle, symbol_name); + if (proc != NULL) + return proc; + + /* get the symbol from the loaded DLLs */ + modules = (HMODULE *) g_malloc (buffer_size); + if (modules == NULL) + return NULL; + + if (!EnumProcessModules (GetCurrentProcess (), modules, + buffer_size, &needed)) { + g_free (modules); + return NULL; + } + + /* check whether the supplied buffer was too small, realloc, retry */ + if (needed > buffer_size) { + g_free (modules); + + buffer_size = needed; + modules = (HMODULE *) g_malloc (buffer_size); + + if (modules == NULL) + return NULL; + + if (!EnumProcessModules (GetCurrentProcess (), modules, + buffer_size, &needed)) { + g_free (modules); + return NULL; + } + } + + for (i = 0; i < needed / sizeof (HANDLE); i++) { + proc = GetProcAddress (modules [i], symbol_name); + if (proc != NULL) { + g_free (modules); + return proc; + } + } + + g_free (modules); + return NULL; +} + +int +mono_dl_convert_flags (int flags) +{ + return 0; +} + +char* +mono_dl_current_error_string (void) +{ + char* ret = NULL; + wchar_t* buf = NULL; + DWORD code = GetLastError (); + + if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL)) + { + ret = g_utf16_to_utf8 (buf, wcslen(buf), NULL, NULL, NULL); + LocalFree (buf); + } else { + g_assert_not_reached (); + } + return ret; +} + +int +mono_dl_get_executable_path (char *buf, int buflen) +{ + return -1; //TODO +} + +#endif diff --git a/mono/utils/mono-dl.c b/mono/utils/mono-dl.c index c13c68a0421..64b93996174 100644 --- a/mono/utils/mono-dl.c +++ b/mono/utils/mono-dl.c @@ -18,200 +18,14 @@ #include #include -#ifdef TARGET_WIN32 -#define SOPREFIX "" -static const char suffixes [][5] = { - ".dll" -}; -#elif defined(__APPLE__) -#define SOPREFIX "lib" -static const char suffixes [][8] = { - ".dylib", - ".so", - ".bundle" -}; -#else -#define SOPREFIX "lib" -static const char suffixes [][4] = { - ".so" -}; -#endif - -#ifdef TARGET_WIN32 - -#include -#include - -#define SO_HANDLE_TYPE HMODULE -#define LL_SO_OPEN(file,flags) w32_load_module ((file), (flags)) -#define LL_SO_CLOSE(module) do { if (!(module)->main_module) FreeLibrary ((module)->handle); } while (0) -#define LL_SO_SYMBOL(module, name) w32_find_symbol ((module), (name)) -#define LL_SO_TRFLAGS(flags) 0 -#define LL_SO_ERROR() w32_dlerror () - -#elif defined (HAVE_DL_LOADER) - -#include -#include - -#ifdef __MACH__ -#include -#endif - - -#ifndef RTLD_LAZY -#define RTLD_LAZY 1 -#endif /* RTLD_LAZY */ - -#define SO_HANDLE_TYPE void* -#define LL_SO_OPEN(file,flags) dlopen ((file), (flags)) -#define LL_SO_CLOSE(module) dlclose ((module)->handle) -#define LL_SO_SYMBOL(module, name) dlsym ((module)->handle, (name)) -#define LL_SO_TRFLAGS(flags) convert_flags ((flags)) -#define LL_SO_ERROR() g_strdup (dlerror ()) - -static int -convert_flags (int flags) -{ - int lflags = flags & MONO_DL_LOCAL? 0: RTLD_GLOBAL; - - if (flags & MONO_DL_LAZY) - lflags |= RTLD_LAZY; - else - lflags |= RTLD_NOW; - return lflags; -} - -#else -/* no dynamic loader supported */ -#define SO_HANDLE_TYPE void* -#define LL_SO_OPEN(file,flags) NULL -#define LL_SO_CLOSE(module) -#define LL_SO_SYMBOL(module, name) NULL -#define LL_SO_TRFLAGS(flags) (flags) -#define LL_SO_ERROR() g_strdup ("No support for dynamic loader") - -#endif - -static GSList *fallback_handlers; - struct MonoDlFallbackHandler { MonoDlFallbackLoad load_func; MonoDlFallbackSymbol symbol_func; MonoDlFallbackClose close_func; void *user_data; }; - -struct _MonoDl { - SO_HANDLE_TYPE handle; - int main_module; - - /* If not NULL, use the methods in MonoDlFallbackHandler instead of the LL_* methods */ - MonoDlFallbackHandler *dl_fallback; -}; - -#ifdef TARGET_WIN32 - -static char* -w32_dlerror (void) -{ - char* ret = NULL; - wchar_t* buf = NULL; - DWORD code = GetLastError (); - if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL)) - { - ret = g_utf16_to_utf8 (buf, wcslen(buf), NULL, NULL, NULL); - LocalFree (buf); - } else { - g_assert_not_reached (); - } - return ret; -} - -static gpointer -w32_find_symbol (MonoDl *module, const gchar *symbol_name) -{ - HMODULE *modules; - DWORD buffer_size = sizeof (HMODULE) * 1024; - DWORD needed, i; - gpointer proc = NULL; - - /* get the symbol directly from the specified module */ - if (!module->main_module) - return GetProcAddress (module->handle, symbol_name); - - /* get the symbol from the main module */ - proc = GetProcAddress (module->handle, symbol_name); - if (proc != NULL) - return proc; - - /* get the symbol from the loaded DLLs */ - modules = (HMODULE *) g_malloc (buffer_size); - if (modules == NULL) - return NULL; - - if (!EnumProcessModules (GetCurrentProcess (), modules, - buffer_size, &needed)) { - g_free (modules); - return NULL; - } - - /* check whether the supplied buffer was too small, realloc, retry */ - if (needed > buffer_size) { - g_free (modules); - - buffer_size = needed; - modules = (HMODULE *) g_malloc (buffer_size); - - if (modules == NULL) - return NULL; - - if (!EnumProcessModules (GetCurrentProcess (), modules, - buffer_size, &needed)) { - g_free (modules); - return NULL; - } - } - - for (i = 0; i < needed / sizeof (HANDLE); i++) { - proc = GetProcAddress (modules [i], symbol_name); - if (proc != NULL) { - g_free (modules); - return proc; - } - } - - g_free (modules); - return NULL; -} - - -static gpointer -w32_load_module (const char* file, int flags) -{ - gpointer hModule = NULL; - if (file) { - gunichar2* file_utf16 = g_utf8_to_utf16 (file, strlen (file), NULL, NULL, NULL); - guint last_sem = SetErrorMode (SEM_FAILCRITICALERRORS); - guint32 last_error = 0; - - hModule = LoadLibrary (file_utf16); - if (!hModule) - last_error = GetLastError (); - - SetErrorMode (last_sem); - g_free (file_utf16); - - if (!hModule) - SetLastError (last_error); - } else { - hModule = GetModuleHandle (NULL); - } - return hModule; -} -#endif +static GSList *fallback_handlers; /* * read a value string from line with any of the following formats: @@ -320,7 +134,7 @@ mono_dl_open (const char *name, int flags, char **error_msg) MonoDl *module; void *lib; MonoDlFallbackHandler *dl_fallback = NULL; - int lflags = LL_SO_TRFLAGS (flags); + int lflags = mono_dl_convert_flags (flags); if (error_msg) *error_msg = NULL; @@ -333,15 +147,8 @@ mono_dl_open (const char *name, int flags, char **error_msg) } module->main_module = name == NULL? TRUE: FALSE; -#ifdef PLATFORM_ANDROID - /* Bionic doesn't support NULL filenames */ - if (!name) - lib = NULL; - else - lib = LL_SO_OPEN (name, lflags); -#else - lib = LL_SO_OPEN (name, lflags); -#endif + lib = mono_dl_open_file (name, lflags); + if (!lib) { GSList *node; for (node = fallback_handlers; node != NULL; node = node->next){ @@ -378,12 +185,12 @@ mono_dl_open (const char *name, int flags, char **error_msg) llname = get_dl_name_from_libtool (lname); g_free (lname); if (llname) { - lib = LL_SO_OPEN (llname, lflags); + lib = mono_dl_open_file (llname, lflags); g_free (llname); } if (!lib) { if (error_msg) { - *error_msg = LL_SO_ERROR (); + *error_msg = mono_dl_current_error_string (); } free (module); return NULL; @@ -419,11 +226,11 @@ mono_dl_symbol (MonoDl *module, const char *name, void **symbol) char *usname = malloc (strlen (name) + 2); *usname = '_'; strcpy (usname + 1, name); - sym = LL_SO_SYMBOL (module, usname); + sym = mono_dl_lookup_symbol (module, usname); free (usname); } #else - sym = LL_SO_SYMBOL (module, name); + sym = mono_dl_lookup_symbol (module, name); #endif } @@ -434,7 +241,7 @@ mono_dl_symbol (MonoDl *module, const char *name, void **symbol) } if (symbol) *symbol = NULL; - return (module->dl_fallback != NULL) ? err : LL_SO_ERROR (); + return (module->dl_fallback != NULL) ? err : mono_dl_current_error_string (); } /** @@ -454,7 +261,7 @@ mono_dl_close (MonoDl *module) if (dl_fallback->close_func != NULL) dl_fallback->close_func (module->handle, dl_fallback->user_data); } else - LL_SO_CLOSE (module); + mono_dl_close_handle (module); free (module); } @@ -504,16 +311,16 @@ mono_dl_build_path (const char *directory, const char *name, void **iter) suffixlen = 0; } else { idx--; - if (idx >= G_N_ELEMENTS (suffixes)) + if (mono_dl_get_so_suffixes () [idx] == '\0') return NULL; first_call = FALSE; - suffix = suffixes [idx]; + suffix = mono_dl_get_so_suffixes () [idx]; suffixlen = strlen (suffix); } - prlen = strlen (SOPREFIX); - if (prlen && strncmp (name, SOPREFIX, prlen) != 0) - prefix = SOPREFIX; + prlen = strlen (mono_dl_get_so_prefix ()); + if (prlen && strncmp (name, mono_dl_get_so_prefix (), prlen) != 0) + prefix = mono_dl_get_so_prefix (); else prefix = ""; @@ -563,9 +370,6 @@ mono_dl_fallback_unregister (MonoDlFallbackHandler *handler) g_free (handler); } - -#if defined (HAVE_DL_LOADER) - static MonoDl* try_load (const char *lib_name, char *dir, int flags, char **err) { @@ -590,17 +394,10 @@ mono_dl_open_runtime_lib (const char* lib_name, int flags, char **error_msg) MonoDl *runtime_lib = NULL; char buf [4096]; int binl; - binl = readlink ("/proc/self/exe", buf, sizeof (buf)-1); *error_msg = NULL; -#ifdef __MACH__ - if (binl == -1) { - uint32_t bsize = sizeof (buf); - if (_NSGetExecutablePath (buf, &bsize) == 0) { - binl = strlen (buf); - } - } -#endif + binl = mono_dl_get_executable_path (buf, sizeof (buf)); + if (binl != -1) { char *base; char *resolvedname, *name; @@ -632,13 +429,3 @@ mono_dl_open_runtime_lib (const char* lib_name, int flags, char **error_msg) return runtime_lib; } - -#else - -MonoDl* -mono_dl_open_runtime_lib (const char* lib_name, int flags, char **error_msg) -{ - return NULL; -} - -#endif diff --git a/mono/utils/mono-dl.h b/mono/utils/mono-dl.h index 205916b6d4b..4b972ef62f0 100644 --- a/mono/utils/mono-dl.h +++ b/mono/utils/mono-dl.h @@ -16,7 +16,14 @@ #define MONO_SOLIB_EXT ".so" #endif -typedef struct _MonoDl MonoDl; +typedef struct { + void *handle; + int main_module; + + /* If not NULL, use the methods in MonoDlFallbackHandler instead of the LL_* methods */ + MonoDlFallbackHandler *dl_fallback; +} MonoDl; + MonoDl* mono_dl_open (const char *name, int flags, char **error_msg) MONO_LLVM_INTERNAL; char* mono_dl_symbol (MonoDl *module, const char *name, void **symbol) MONO_LLVM_INTERNAL; @@ -26,5 +33,16 @@ char* mono_dl_build_path (const char *directory, const char *name, void ** MonoDl* mono_dl_open_runtime_lib (const char *lib_name, int flags, char **error_msg) MONO_INTERNAL; + +//Platform API for mono_dl +const char* mono_dl_get_so_prefix (void) MONO_INTERNAL; +const char** mono_dl_get_so_suffixes (void) MONO_INTERNAL; +void* mono_dl_open_file (const char *file, int flags) MONO_INTERNAL; +void mono_dl_close_handle (MonoDl *module) MONO_INTERNAL; +void* mono_dl_lookup_symbol (MonoDl *module, const char *name) MONO_INTERNAL; +int mono_dl_convert_flags (int flags) MONO_INTERNAL; +char* mono_dl_current_error_string (void) MONO_INTERNAL; +int mono_dl_get_executable_path (char *buf, int buflen) MONO_INTERNAL; + #endif /* __MONO_UTILS_DL_H__ */