[mono] Add support for PINVOKE_OVERRIDE (#46442)
authorRyan Lucia <rylucia@microsoft.com>
Tue, 5 Jan 2021 21:04:00 +0000 (16:04 -0500)
committerGitHub <noreply@github.com>
Tue, 5 Jan 2021 21:04:00 +0000 (22:04 +0100)
Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>
src/mono/mono/metadata/native-library.c
src/mono/mono/metadata/native-library.h
src/mono/mono/mini/monovm.c

index 4b5d4e8..fb92e61 100644 (file)
@@ -47,11 +47,11 @@ static GHashTable *native_library_module_map;
  * This is a rare scenario and considered a worthwhile tradeoff.
  */
 static GHashTable *native_library_module_blocklist;
-#endif
 
-#if defined(ENABLE_NETCORE) && !defined(NO_GLOBALIZATION_SHIM)
+#ifndef NO_GLOBALIZATION_SHIM
 extern const void *GlobalizationResolveDllImport (const char *name);
 #endif
+#endif // ENABLE_NETCORE
 
 #ifndef DISABLE_DLLMAP
 static MonoDllMap *global_dll_map;
@@ -61,6 +61,8 @@ static GHashTable *global_module_map; // should only be accessed with the global
 
 static MonoDl *internal_module; // used when pinvoking `__Internal`
 
+static PInvokeOverrideFn pinvoke_override;
+
 // Did we initialize the temporary directory for dynamic libraries
 // FIXME: this is racy
 static gboolean bundle_save_library_initialized;
@@ -933,6 +935,26 @@ get_dllimportsearchpath_flags (MonoCustomAttrInfo *cinfo)
        return flags;
 }
 
+#ifndef NO_GLOBALIZATION_SHIM
+#ifdef HOST_WIN32
+#define GLOBALIZATION_DLL_NAME "System.Globalization.Native"
+#else
+#define GLOBALIZATION_DLL_NAME "libSystem.Globalization.Native"
+#endif
+
+static gpointer
+default_resolve_dllimport (const char *dll, const char *func)
+{
+       if (strcmp (dll, GLOBALIZATION_DLL_NAME) == 0) {
+               const void *method_impl = GlobalizationResolveDllImport (func);
+               if (method_impl)
+                       return (gpointer)method_impl;
+       }
+
+       return NULL;
+}
+#endif // NO_GLOBALIZATION_SHIM
+
 #else // ENABLE_NETCORE
 
 static MonoDl *
@@ -1263,30 +1285,8 @@ legacy_lookup_native_library (MonoImage *image, const char *scope)
 
        return module;
 }
-
 #endif // ENABLE_NETCORE
 
-#if defined(ENABLE_NETCORE) && !defined(NO_GLOBALIZATION_SHIM)
-
-#ifdef HOST_WIN32
-#define GLOBALIZATION_DLL_NAME "System.Globalization.Native"
-#else
-#define GLOBALIZATION_DLL_NAME "libSystem.Globalization.Native"
-#endif
-
-static gpointer
-default_resolve_dllimport (const char *dll, const char *func)
-{
-       if (strcmp (dll, GLOBALIZATION_DLL_NAME) == 0) {
-               const void *method_impl = GlobalizationResolveDllImport (func);
-               if (method_impl)
-                       return (gpointer)method_impl;
-       }
-
-       return NULL;
-}
-#endif
-
 gpointer
 lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_out)
 {
@@ -1367,13 +1367,19 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou
        }
 #endif
 
-#if defined(ENABLE_NETCORE) && !defined(NO_GLOBALIZATION_SHIM)
-       gpointer default_override = default_resolve_dllimport (new_scope, new_import);
-       if (default_override)
-               return default_override;
+#ifdef ENABLE_NETCORE
+#ifndef NO_GLOBALIZATION_SHIM
+       addr = default_resolve_dllimport (new_scope, new_import);
+       if (addr)
+               goto exit;
 #endif
 
-#ifdef ENABLE_NETCORE
+       if (pinvoke_override) {
+               addr = pinvoke_override (new_scope, new_import);
+               if (addr)
+                       goto exit;
+       }
+
 #ifndef HOST_WIN32
 retry_with_libcoreclr:
 #endif
@@ -1399,7 +1405,7 @@ retry_with_libcoreclr:
        module = netcore_lookup_native_library (alc, image, new_scope, flags);
 #else
        module = legacy_lookup_native_library (image, new_scope);
-#endif
+#endif // ENABLE_NETCORE
 
        if (!module) {
                mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DLLIMPORT,
@@ -1756,3 +1762,9 @@ mono_loader_save_bundled_library (int fd, uint64_t offset, uint64_t size, const
        
        g_free (buffer);
 }
+
+void
+mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn)
+{
+       pinvoke_override = override_fn;
+}
index a5b556b..94c23cd 100644 (file)
@@ -44,4 +44,9 @@ typedef struct MonoQCallFunc {
     const char     *method_name;
 } MonoQCallFunc;
 
+typedef void * (*PInvokeOverrideFn) (const char *libraryName, const char *entrypointName);
+
+void
+mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn);
+
 #endif
index 6e73a92..bbde28c 100644 (file)
@@ -8,6 +8,7 @@
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/environment.h>
 #include <mono/metadata/loader-internals.h>
+#include <mono/metadata/native-library.h>
 #include <mono/mini/mini-runtime.h>
 #include <mono/mini/mini.h>
 #include <mono/utils/mono-logger-internals.h>
@@ -181,6 +182,9 @@ parse_properties (int propertyCount, const char **propertyKeys, const char **pro
                        platform_resource_roots = parse_lookup_paths (propertyValues [i]);
                } else if (prop_len == 29 && !strncmp (propertyKeys [i], "NATIVE_DLL_SEARCH_DIRECTORIES", 29)) {
                        native_lib_paths = parse_lookup_paths (propertyValues [i]);
+               } else if (prop_len == 16 && !strncmp (propertyKeys [i], "PINVOKE_OVERRIDE", 16)) {
+                       PInvokeOverrideFn override_fn = (PInvokeOverrideFn)(uintptr_t)strtoull (propertyValues [i], NULL, 0);
+                       mono_loader_install_pinvoke_override (override_fn);
                } else if (prop_len == 30 && !strncmp (propertyKeys [i], "System.Globalization.Invariant", 30)) {
                        // TODO: Ideally we should propagate this through AppContext options
                        g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", propertyValues [i], TRUE);