[mono] Thread DllImportSearchPath flags down to LoadLibraryEx (#41229)
authorRyan Lucia <rylucia@microsoft.com>
Mon, 24 Aug 2020 14:40:44 +0000 (10:40 -0400)
committerGitHub <noreply@github.com>
Mon, 24 Aug 2020 14:40:44 +0000 (10:40 -0400)
This mostly completes support for the attribute. Our algorithm differs a bit from CoreCLR right now, so we don't support the legacy behavior flag since it makes less since in the context of our algorithm, but this should be good enough for most cases.

src/mono/mono/metadata/native-library.c
src/mono/mono/utils/mono-dl-posix.c
src/mono/mono/utils/mono-dl-wasm.c
src/mono/mono/utils/mono-dl-windows.c
src/mono/mono/utils/mono-dl.c
src/mono/mono/utils/mono-dl.h

index 10ac830..f53b8d0 100644 (file)
@@ -28,8 +28,10 @@ typedef enum
        DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES = 0x1000,
        DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY = 0x2, // search the assembly directory first regardless of platform, not passed on to LoadLibraryEx
 } DllImportSearchPath;
-//static const int DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK = DLLIMPORTSEARCHPATH_USE_DLL_DIRECTORY_FOR_DEPENDENCIES | DLLIMPORTSEARCHPATH_APPLICATION_DIRECTORY |
-//                                                             DLLIMPORTSEARCHPATH_USER_DIRECTORIES | DLLIMPORTSEARCHPATH_SYSTEM32 | DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES;
+#ifdef HOST_WIN32
+static const int DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK = DLLIMPORTSEARCHPATH_USE_DLL_DIRECTORY_FOR_DEPENDENCIES | DLLIMPORTSEARCHPATH_APPLICATION_DIRECTORY |
+                                                             DLLIMPORTSEARCHPATH_USER_DIRECTORIES | DLLIMPORTSEARCHPATH_SYSTEM32 | DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES;
+#endif
 
 // This lock may be taken within an ALC lock, and should never be the other way around.
 static MonoCoopMutex native_library_module_lock;
@@ -490,18 +492,28 @@ netcore_check_blocklist (MonoDl *module)
        return g_hash_table_contains (native_library_module_blocklist, module);
 }
 
+static int
+convert_dllimport_flags (int flags)
+{
+#ifdef HOST_WIN32
+       return flags & DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK;
+#else
+       // DllImportSearchPath is Windows-only, other than DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY
+       return 0;
+#endif
+}
+
 static MonoDl *
-netcore_probe_for_module_variations (const char *mdirname, const char *file_name)
+netcore_probe_for_module_variations (const char *mdirname, const char *file_name, int raw_flags)
 {
        void *iter = NULL;
        char *full_name;
        MonoDl *module = NULL;
 
-       // This does not actually mirror CoreCLR's algorithm; if that becomes a problem, potentially use theirs
        // FIXME: this appears to search *.dylib twice for some reason
        while ((full_name = mono_dl_build_path (mdirname, file_name, &iter)) && module == NULL) {
                char *error_msg;
-               module = mono_dl_open (full_name, MONO_DL_LAZY, &error_msg);
+               module = mono_dl_open_full (full_name, MONO_DL_LAZY, raw_flags, &error_msg);
                if (!module) {
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s': '%s'.", full_name, error_msg);
                        g_free (error_msg);
@@ -517,19 +529,23 @@ static MonoDl *
 netcore_probe_for_module (MonoImage *image, const char *file_name, int flags)
 {
        MonoDl *module = NULL;
+       int lflags = convert_dllimport_flags (flags);
+
+       // TODO: this algorithm doesn't quite match CoreCLR, so respecting DLLIMPORTSEARCHPATH_LEGACY_BEHAVIOR makes little sense
+       // If the difference becomes a problem, overhaul this algorithm to match theirs exactly
 
        // Try without any path additions
-       module = netcore_probe_for_module_variations (NULL, file_name);
+       module = netcore_probe_for_module_variations (NULL, file_name, lflags);
 
        // Check the NATIVE_DLL_SEARCH_DIRECTORIES
        for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i)
-               module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name);
+               module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name, lflags);
 
        // Check the assembly directory if the search flag is set and the image exists
        if (flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY && image != NULL && module == NULL) {
                char *mdirname = g_path_get_dirname (image->filename);
                if (mdirname)
-                       module = netcore_probe_for_module_variations (mdirname, file_name);
+                       module = netcore_probe_for_module_variations (mdirname, file_name, lflags);
                g_free (mdirname);
        }
 
index a6c767c..7b19cd5 100644 (file)
@@ -130,21 +130,21 @@ mono_dl_lookup_symbol (MonoDl *module, const char *name)
 }
 
 int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
 {
-       int lflags = 0;
+       int lflags = native_flags;
 
 #ifdef ENABLE_NETCORE
        // Specifying both will default to LOCAL
-       if (flags & MONO_DL_GLOBAL && !(flags & MONO_DL_LOCAL))
+       if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL))
                lflags |= RTLD_GLOBAL;
        else 
                lflags |= RTLD_LOCAL;
 #else
-       lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
+       lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
 #endif
 
-       if (flags & MONO_DL_LAZY)
+       if (mono_flags & MONO_DL_LAZY)
                lflags |= RTLD_LAZY;
        else
                lflags |= RTLD_NOW;
index cd1ce22..21cdbad 100644 (file)
@@ -55,23 +55,23 @@ mono_dl_current_error_string (void)
        return g_strdup ("");
 }
 
-
+// Copied from mono-dl-posix.c
 int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
 {
-       int lflags = 0;
+       int lflags = native_flags;
 
 #ifdef ENABLE_NETCORE
        // Specifying both will default to LOCAL
-       if (flags & MONO_DL_LOCAL)
-               lflags |= RTLD_LOCAL;
-       else if (flags & MONO_DL_GLOBAL)
+       if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL))
                lflags |= RTLD_GLOBAL;
+       else 
+               lflags |= RTLD_LOCAL;
 #else
-       lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
+       lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
 #endif
 
-       if (flags & MONO_DL_LAZY)
+       if (mono_flags & MONO_DL_LAZY)
                lflags |= RTLD_LAZY;
        else
                lflags |= RTLD_NOW;
index 88c4911..966d71a 100644 (file)
@@ -57,7 +57,7 @@ mono_dl_open_file (const char *file, int flags)
                guint32 last_error = 0;
 
 #if HAVE_API_SUPPORT_WIN32_LOAD_LIBRARY
-               hModule = LoadLibraryW (file_utf16);
+               hModule = LoadLibraryExW (file_utf16, NULL, flags);
 #elif HAVE_API_SUPPORT_WIN32_LOAD_PACKAGED_LIBRARY
                hModule = LoadPackagedLibrary (file_utf16, NULL);
 #else
@@ -160,9 +160,10 @@ mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name)
 }
 
 int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
 {
-       return 0;
+       // Mono flags are not applicable on Windows
+       return native_flags;
 }
 
 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
index 32fc1da..ab47127 100644 (file)
@@ -221,10 +221,16 @@ mono_dl_open_self (char **error_msg)
 MonoDl*
 mono_dl_open (const char *name, int flags, char **error_msg)
 {
+       return mono_dl_open_full (name, flags, 0, error_msg);
+}
+
+MonoDl *
+mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **error_msg)
+{
        MonoDl *module;
        void *lib;
        MonoDlFallbackHandler *dl_fallback = NULL;
-       int lflags = mono_dl_convert_flags (flags);
+       int lflags = mono_dl_convert_flags (mono_flags, native_flags);
        char *found_name;
 
        if (error_msg)
index 6efee6f..0f6132e 100644 (file)
@@ -43,7 +43,11 @@ 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);
 
-MonoDl*     mono_dl_open_self (char **error_msg);
+MonoDl *
+mono_dl_open_self (char **error_msg);
+// This converts the MONO_DL_* enum to native flags, combines it with the other flags passed, and resolves some inconsistencies
+MonoDl *
+mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **error_msg);
 
 
 //Platform API for mono_dl
@@ -52,7 +56,7 @@ const char** mono_dl_get_so_suffixes (void);
 void* mono_dl_open_file (const char *file, int flags);
 void mono_dl_close_handle (MonoDl *module);
 void* mono_dl_lookup_symbol (MonoDl *module, const char *name);
-int mono_dl_convert_flags (int flags);
+int mono_dl_convert_flags (int mono_flags, int native_flags);
 char* mono_dl_current_error_string (void);
 int mono_dl_get_executable_path (char *buf, int buflen);
 const char* mono_dl_get_system_dir (void);