Hi,

The attached patch implements using trampolines for vtable fixups that delay assembly loading. I believe that this is the correct solution.

This patch also modifies:

1) EXE image is only fixed up when using driver.c; embedded mono.dll will not improperly tamper the image used for version initialization.

2) Use SEH with MS VC++ for reading mapped image. (GCC has no support for that:( )

3) Disallow unloading mono.dll after mscoree.dll was fixed up to prevent calling unmapped functions.

4) Remove WaitForSingleObjectEx in mono_gc_init () by modifying mono_thread_create_internal to return the thread object.

This latter also affects other platform. I would like to ask you to test it. I wasn't able to reproduce any deadlock related to this. (I only found a deadlock with socket accept on Windows that was discussed earlier on the list.) If you can reproduce a deadlock related to finalizer thread I am willing to help solving that but I need the exact locaions of deadlocked thread stack traces.

Kornél
Index: mono/mono/metadata/domain.c
===================================================================
--- mono/mono/metadata/domain.c	(revision 133502)
+++ mono/mono/metadata/domain.c	(working copy)
@@ -1256,7 +1256,7 @@
 	/* Avoid system error message boxes. */
 	SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
 
-	mono_load_coree (exe_filename);
+	mono_load_coree ();
 #endif
 
 	mono_perfcounters_init ();
@@ -1294,14 +1294,6 @@
 		 * exe_image, and close it during shutdown.
 		 */
 		get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
-#ifdef PLATFORM_WIN32
-		if (!exe_image) {
-			exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
-			if (!exe_image)
-				exe_image = mono_image_open (exe_filename, NULL);
-		}
-		mono_fixup_exe_image (exe_image);
-#endif
 	} else if (runtime_version != NULL) {
 		runtimes [0] = get_runtime_by_version (runtime_version);
 		runtimes [1] = NULL;
Index: mono/mono/metadata/assembly.c
===================================================================
--- mono/mono/metadata/assembly.c	(revision 133502)
+++ mono/mono/metadata/assembly.c	(working copy)
@@ -1520,11 +1520,6 @@
 	loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
 	mono_assemblies_unlock ();
 
-#ifdef PLATFORM_WIN32
-	if (image->is_module_handle)
-		mono_image_fixup_vtable (image);
-#endif
-
 	mono_assembly_invoke_load_hook (ass);
 
 	mono_profiler_assembly_loaded (ass, MONO_PROFILE_OK);
Index: mono/mono/metadata/coree.c
===================================================================
--- mono/mono/metadata/coree.c	(revision 133502)
+++ mono/mono/metadata/coree.c	(working copy)
@@ -35,13 +35,10 @@
 
 HMODULE coree_module_handle = NULL;
 
-static gboolean init_from_coree = FALSE;
-
-gchar*
-mono_get_module_file_name (HMODULE module_handle)
+static gunichar2*
+mono_get_module_file_name_utf16 (HMODULE module_handle)
 {
 	gunichar2* file_name;
-	gchar* file_name_utf8;
 	DWORD buffer_size;
 	DWORD size;
 
@@ -63,9 +60,19 @@
 		file_name = g_realloc (file_name, buffer_size * sizeof (gunichar2));
 	}
 
-	file_name_utf8 = g_utf16_to_utf8 (file_name, size, NULL, NULL, NULL);
-	g_free (file_name);
+	return file_name;
+}
 
+gchar*
+mono_get_module_file_name (HMODULE module_handle)
+{
+	gunichar2* file_name_utf16;
+	gchar* file_name_utf8;
+
+	file_name_utf16 = mono_get_module_file_name_utf16 (module_handle);
+	file_name_utf8 = g_utf16_to_utf8 (file_name_utf16, -1, NULL, NULL, NULL);
+	g_free (file_name_utf16);
+
 	return file_name_utf8;
 }
 
@@ -87,7 +94,6 @@
 		if (mono_get_root_domain ()) {
 			image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), TRUE, NULL);
 		} else {
-			init_from_coree = TRUE;
 			mono_runtime_load (file_name, NULL);
 			error = (gchar*) mono_check_corlib_version ();
 			if (error) {
@@ -106,20 +112,12 @@
 			}
 		}
 
-		if (!image) {
-			g_free (file_name);
+		g_free (file_name);
+
+		if (!image)
 			return FALSE;
-		}
 
-		/*
-		 * FIXME: Find a better way to call mono_image_fixup_vtable. Only
-		 * loader trampolines should be used and assembly loading should
-		 * probably be delayed until the first call to an exported function.
-		 */
-		if (image->tables [MONO_TABLE_ASSEMBLY].rows && ((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva)
-			assembly = mono_assembly_open (file_name, NULL);
-
-		g_free (file_name);
+		mono_image_fixup_vtable (image);
 		break;
 	case DLL_PROCESS_DETACH:
 		if (lpReserved != NULL)
@@ -153,7 +151,6 @@
 	int i;
 
 	file_name = mono_get_module_file_name (NULL);
-	init_from_coree = TRUE;
 	domain = mono_runtime_load (file_name, NULL);
 
 	error = (gchar*) mono_check_corlib_version ();
@@ -198,6 +195,7 @@
 		argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
 	LocalFree (argvw);
 
+	mono_image_fixup_vtable (image);
 	mono_runtime_run_main (method, argc, argv, NULL);
 	mono_thread_manage ();
 
@@ -429,34 +427,41 @@
 	if (DosHeader == NULL)
 		goto CloseMap;
 
-	if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
-		goto InvalidImageFormat;
+#ifdef _MSC_VER
+	__try
+	{
+#endif
+		if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
+			goto InvalidImageFormat;
 
-	NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
-	if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
-		goto InvalidImageFormat;
+		NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
+		if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
+			goto InvalidImageFormat;
 
 #ifdef _WIN64
-	NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
-	if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
-	{
-		if (FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) ||
-			NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
-			!NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
-				goto InvalidImageFormat;
+		NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
+		if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+		{
+			if (FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) ||
+				NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
+				!NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
+					goto InvalidImageFormat;
 
-		goto ValidImage;
-	}
+			goto ValidImage;
+		}
 #endif
 
-	if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC ||
-		NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
-		!NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
+		if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC ||
+			NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
+			!NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
+				goto InvalidImageFormat;
+#ifdef _MSC_VER
+	}
+	__except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
 	{
-InvalidImageFormat:
-		SetLastError(STATUS_INVALID_IMAGE_FORMAT);
-		goto UnmapView;
+		goto InvalidImageFormat;
 	}
+#endif
 
 ValidImage:
 	UnmapViewOfFile(DosHeader);
@@ -467,7 +472,9 @@
 	CloseHandle(FileHandle);
 	return ModuleHandle;
 
-UnmapView:
+InvalidImageFormat:
+	SetLastError(STATUS_INVALID_IMAGE_FORMAT);
+
 	UnmapViewOfFile(DosHeader);
 CloseMap:
 	CloseHandle(MapHandle);
@@ -504,7 +511,6 @@
 
 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
 
-static HMODULE ExportFixupModuleHandle = NULL;
 static DWORD ExportFixupRvas[EXPORT_FIXUP_COUNT];
 
 /* Fixup exported functions of mscoree.dll to our implementations. */
@@ -544,8 +550,8 @@
 #endif
 #endif
 
-	if (ExportFixupModuleHandle != NULL)
-		return ModuleHandle == ExportFixupModuleHandle ? S_OK : E_FAIL;
+	if (coree_module_handle != NULL)
+		return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
 
 	DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
 	if (DosHeader == NULL)
@@ -650,7 +656,7 @@
 					return E_UNEXPECTED;
 #endif
 
-				ExportFixupModuleHandle = ModuleHandle;
+				coree_module_handle = ModuleHandle;
 				return S_OK;
 			}
 			ExportFixupRva++;
@@ -821,7 +827,7 @@
 	return S_OK;
 }
 
-static void
+void
 mono_set_act_ctx (const char* file_name)
 {
 	typedef HANDLE (WINAPI* CREATEACTCTXW_PROC) (PCACTCTXW pActCtx);
@@ -883,19 +889,18 @@
 }
 
 void
-mono_load_coree (const char* exe_file_name)
+mono_load_coree ()
 {
 	HMODULE module_handle;
+	HMODULE pinned_module_handle;
 	gunichar2* file_name;
+	gunichar2* mono_file_name;
 	UINT required_size;
 	UINT size;
 
 	if (coree_module_handle)
 		return;
 
-	if (!init_from_coree && exe_file_name)
-		mono_set_act_ctx (exe_file_name);
-
 	/* ntdll.dll loads mscoree.dll from the system32 directory. */
 	required_size = GetSystemDirectory (NULL, 0);
 	file_name = g_new (gunichar2, required_size + 12);
@@ -905,22 +910,46 @@
 		file_name [size++] = L'\\';
 	memcpy (&file_name [size], L"mscoree.dll", 12 * sizeof (gunichar2));
 
-	module_handle = LoadLibrary (file_name);
+	/* Modifying exports is safe only when the DLL was not loaded yet. */
+	if (GetModuleHandle (file_name) || !(module_handle = LoadLibraryEx (file_name, NULL, DONT_RESOLVE_DLL_REFERENCES))) {
+		g_free (file_name);
+		return;
+	}
+
 	g_free (file_name);
 
-	if (module_handle && !SUCCEEDED (MonoFixupCorEE (module_handle))) {
-		FreeLibrary (module_handle);
-		module_handle = NULL;
-	}
+	if (!SUCCEEDED (MonoFixupCorEE (module_handle)))
+		goto free_module;
 
-	coree_module_handle = module_handle;
+	mono_file_name = mono_get_module_file_name_utf16 ((HMODULE) &__ImageBase);
+	if (!mono_file_name)
+		goto unset_coree_module;
+
+	/* Add reference to avoid module unload. */
+	if (!LoadLibrary(mono_file_name))
+		goto free_mono_file_name;
+
+	g_free (mono_file_name);
+	return;
+
+free_mono_file_name:
+	g_free (mono_file_name);
+unset_coree_module:
+	coree_module_handle = NULL;
+free_module:
+	FreeLibrary (module_handle);
 }
 
 void
 mono_fixup_exe_image (MonoImage* image)
 {
-	if (!init_from_coree && image && image->is_module_handle)
-		MonoFixupExe ((HMODULE) image->raw_data);
+	if (!image || !image->is_module_handle || ((MonoCLIImageInfo *) image->image_info)->cli_header.coff.coff_attributes & COFF_ATTRIBUTE_LIBRARY_IMAGE)
+		return;
+
+	if (!SUCCEEDED (MonoFixupExe ((HMODULE) image->raw_data)))
+		return;
+
+	mono_image_fixup_vtable (image);
 }
 
 #endif /* PLATFORM_WIN32 */
Index: mono/mono/metadata/coree.h
===================================================================
--- mono/mono/metadata/coree.h	(revision 133502)
+++ mono/mono/metadata/coree.h	(working copy)
@@ -17,8 +17,12 @@
 #include <mono/io-layer/io-layer.h>
 #include "image.h"
 
+#ifndef STATUS_SUCCESS
 #define STATUS_SUCCESS 0x00000000L
+#endif
+#ifndef STATUS_INVALID_IMAGE_FORMAT
 #define STATUS_INVALID_IMAGE_FORMAT 0xC000007BL
+#endif
 
 STDAPI MonoFixupCorEE(HMODULE ModuleHandle);
 
@@ -34,10 +38,11 @@
 STDAPI MonoFixupExe(HMODULE ModuleHandle) MONO_INTERNAL;
 
 gchar* mono_get_module_file_name (HMODULE module_handle) MONO_INTERNAL;
-void mono_load_coree (const char* file_name) MONO_INTERNAL;
+void mono_set_act_ctx (const char* file_name) MONO_INTERNAL;
+void mono_load_coree () MONO_INTERNAL;
 void mono_fixup_exe_image (MonoImage* image) MONO_INTERNAL;
 
-/* Declared in image.c. */
+/* Defined in image.c. */
 MonoImage* mono_image_open_from_module_handle (HMODULE module_handle, char* fname, gboolean has_entry_point, MonoImageOpenStatus* status) MONO_INTERNAL;
 
 #endif /* PLATFORM_WIN32 */
Index: mono/mono/metadata/object.c
===================================================================
--- mono/mono/metadata/object.c	(revision 133502)
+++ mono/mono/metadata/object.c	(working copy)
@@ -463,10 +463,18 @@
 	return NULL;
 }
 
+static gpointer
+default_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32 token, guint16 type)
+{
+	g_assert_not_reached ();
+	return NULL;
+}
+
 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
 static MonoJumpTrampoline arch_create_jump_trampoline = default_jump_trampoline;
 static MonoRemotingTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
 static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
+static MonoVTFixupTrampoline arch_create_vtfixup_trampoline = default_vtfixup_trampoline;
 static MonoImtThunkBuilder imt_thunk_builder = NULL;
 #define ARCH_USE_IMT (imt_thunk_builder != NULL)
 #if (MONO_IMT_SIZE > 32)
@@ -498,6 +506,12 @@
 }
 
 void
+mono_install_vtfixup_trampoline (MonoVTFixupTrampoline func) 
+{
+	arch_create_vtfixup_trampoline = func? func: default_vtfixup_trampoline;
+}
+
+void
 mono_install_imt_thunk_builder (MonoImtThunkBuilder func) {
 	imt_thunk_builder = func;
 }
@@ -545,6 +559,12 @@
 	return arch_create_delegate_trampoline (klass);
 }
 
+gpointer
+mono_runtime_create_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32 token, guint16 type)
+{
+	return arch_create_vtfixup_trampoline (slot, image, token, type);
+}
+
 static MonoFreeMethodFunc default_mono_free_method = NULL;
 
 /**
Index: mono/mono/metadata/class-internals.h
===================================================================
--- mono/mono/metadata/class-internals.h	(revision 133502)
+++ mono/mono/metadata/class-internals.h	(working copy)
@@ -778,6 +778,7 @@
 typedef gpointer (*MonoJumpTrampoline)       (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper);
 typedef gpointer (*MonoRemotingTrampoline)       (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target);
 typedef gpointer (*MonoDelegateTrampoline)       (MonoClass *klass);
+typedef gpointer (*MonoVTFixupTrampoline)       (gpointer slot, MonoImage *image, guint32 token, guint16 type);
 
 typedef gpointer (*MonoLookupDynamicToken) (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
 
@@ -864,6 +865,9 @@
 void
 mono_install_delegate_trampoline (MonoDelegateTrampoline func) MONO_INTERNAL;
 
+void
+mono_install_vtfixup_trampoline (MonoVTFixupTrampoline func) MONO_INTERNAL;
+
 gpointer
 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context) MONO_INTERNAL;
 
@@ -879,6 +883,9 @@
 gpointer
 mono_runtime_create_delegate_trampoline (MonoClass *klass) MONO_INTERNAL;
 
+gpointer
+mono_runtime_create_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32 token, guint16 type) MONO_INTERNAL;
+
 void
 mono_install_get_cached_class_info (MonoGetCachedClassInfo func) MONO_INTERNAL;
 
Index: mono/mono/metadata/gc.c
===================================================================
--- mono/mono/metadata/gc.c	(revision 133502)
+++ mono/mono/metadata/gc.c	(working copy)
@@ -73,7 +73,6 @@
 #ifndef HAVE_NULL_GC
 static HANDLE pending_done_event;
 static HANDLE shutdown_event;
-static HANDLE thread_started_event;
 #endif
 
 static void
@@ -992,10 +991,6 @@
 static guint32
 finalizer_thread (gpointer unused)
 {
-	gc_thread = mono_thread_current ();
-
-	SetEvent (thread_started_event);
-
 	while (!finished) {
 		/* Wait to be notified that there's at least one
 		 * finaliser to run
@@ -1057,26 +1052,14 @@
 	finalizer_event = CreateEvent (NULL, FALSE, FALSE, NULL);
 	pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
 	shutdown_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-	thread_started_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-	if (finalizer_event == NULL || pending_done_event == NULL || shutdown_event == NULL || thread_started_event == NULL) {
+	if (finalizer_event == NULL || pending_done_event == NULL || shutdown_event == NULL) {
 		g_assert_not_reached ();
 	}
 #if USE_POSIX_SEM
 	sem_init (&finalizer_sem, 0, 0);
 #endif
 
-	mono_thread_create (mono_domain_get (), finalizer_thread, NULL);
-
-	/*
-	 * Wait until the finalizer thread sets gc_thread since its value is needed
-	 * by mono_thread_attach ()
-	 *
-	 * FIXME: Eliminate this as to avoid some deadlocks on windows. 
-	 * Waiting for a new thread should result in a deadlock when the runtime is
-	 * initialized from _CorDllMain that is called while the OS loader lock is
-	 * held by LoadLibrary.
-	 */
-	WaitForSingleObjectEx (thread_started_event, INFINITE, FALSE);
+	gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE);
 }
 
 void
Index: mono/mono/metadata/image.c
===================================================================
--- mono/mono/metadata/image.c	(revision 133502)
+++ mono/mono/metadata/image.c	(working copy)
@@ -566,10 +566,6 @@
 			if (image->modules [idx - 1]) {
 				mono_image_addref (image->modules [idx - 1]);
 				image->modules [idx - 1]->assembly = image->assembly;
-#ifdef PLATFORM_WIN32
-				if (image->modules [idx - 1]->is_module_handle)
-					mono_image_fixup_vtable (image->modules [idx - 1]);
-#endif
 				/* g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly); */
 			}
 			g_free (module_ref);
@@ -1277,7 +1273,6 @@
 void
 mono_image_fixup_vtable (MonoImage *image)
 {
-#ifdef PLATFORM_WIN32
 	MonoCLIImageInfo *iinfo;
 	MonoPEDirEntry *de;
 	MonoVTableFixup *vtfixup;
@@ -1286,7 +1281,10 @@
 	guint16 slot_type;
 	int slot_count;
 
-	g_assert (image->is_module_handle);
+#ifdef PLATFORM_WIN32
+	if (!image->is_module_handle)
+#endif
+		g_assert_not_reached();
 
 	iinfo = image->image_info;
 	de = &iinfo->cli_cli_header.ch_vtable_fixups;
@@ -1295,7 +1293,7 @@
 	vtfixup = (MonoVTableFixup*) mono_image_rva_map (image, de->rva);
 	if (!vtfixup)
 		return;
-	
+
 	count = de->size / sizeof (MonoVTableFixup);
 	while (count--) {
 		if (!vtfixup->rva || !vtfixup->count)
@@ -1305,24 +1303,26 @@
 		g_assert (slot);
 		slot_type = vtfixup->type;
 		slot_count = vtfixup->count;
-		if (slot_type & VTFIXUP_TYPE_32BIT)
+
+		switch (slot_type & (VTFIXUP_TYPE_32BIT | VTFIXUP_TYPE_64BIT)) {
+		case VTFIXUP_TYPE_32BIT:
 			while (slot_count--) {
-				*((guint32*) slot) = (guint32) mono_marshal_get_vtfixup_ftnptr (image, *((guint32*) slot), slot_type);
+				*((guint32*) slot) = (guint32) mono_runtime_create_vtfixup_trampoline (slot, image, *((guint32*) slot), slot_type);
 				slot = ((guint32*) slot) + 1;
 			}
-		else if (slot_type & VTFIXUP_TYPE_64BIT)
+			break;
+		case VTFIXUP_TYPE_64BIT:
 			while (slot_count--) {
-				*((guint64*) slot) = (guint64) mono_marshal_get_vtfixup_ftnptr (image, *((guint64*) slot), slot_type);
-				slot = ((guint32*) slot) + 1;
+				*((guint64*) slot) = (guint64) mono_runtime_create_vtfixup_trampoline (slot, image, *((guint64*) slot), slot_type);
+				slot = ((guint64*) slot) + 1;
 			}
-		else
+			break;
+		default:
 			g_assert_not_reached();
+		}
 
 		vtfixup++;
 	}
-#else
-	g_assert_not_reached();
-#endif
 }
 
 static void
@@ -1850,10 +1850,6 @@
 		}
 
 		image->files [fileidx - 1] = res;
-#ifdef PLATFORM_WIN32
-		if (res->is_module_handle)
-			mono_image_fixup_vtable (res);
-#endif
 	}
 	mono_loader_unlock ();
 	g_free (name);
Index: mono/mono/metadata/threads.c
===================================================================
--- mono/mono/metadata/threads.c	(revision 133502)
+++ mono/mono/metadata/threads.c	(working copy)
@@ -701,7 +701,7 @@
 	return res;
 }
 
-void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread)
+MonoThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread)
 {
 	MonoThread *thread;
 	HANDLE thread_handle;
@@ -726,7 +726,7 @@
 	mono_threads_lock ();
 	if (shutting_down) {
 		mono_threads_unlock ();
-		return;
+		return NULL;
 	}
 	if (threads_starting_up == NULL) {
 		MONO_GC_REGISTER_ROOT (threads_starting_up);
@@ -749,7 +749,7 @@
 		mono_threads_unlock ();
 		g_free (start_info);
 		mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
-		return;
+		return NULL;
 	}
 
 	thread->handle=thread_handle;
@@ -766,6 +766,8 @@
 
 	if (handle_store (thread))
 		ResumeThread (thread_handle);
+
+	return thread;
 }
 
 void
Index: mono/mono/metadata/marshal.c
===================================================================
--- mono/mono/metadata/marshal.c	(revision 133502)
+++ mono/mono/metadata/marshal.c	(working copy)
@@ -8267,6 +8267,9 @@
 		return mono_compile_method (method);
 	}
 
+	if (!(type & VTFIXUP_TYPE_CALL_MOST_DERIVED))
+		return mono_compile_method (method);
+
 	sig = mono_method_signature (method);
 	mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_MANAGED);
 
@@ -8274,10 +8277,7 @@
 	for (i = 0; i < param_count; i++)
 		mono_mb_emit_ldarg (mb, i);
 
-	if (type & VTFIXUP_TYPE_CALL_MOST_DERIVED)
-		mono_mb_emit_op (mb, CEE_CALLVIRT, method);
-	else
-		mono_mb_emit_op (mb, CEE_CALL, method);
+	mono_mb_emit_op (mb, CEE_CALLVIRT, method);
 	mono_mb_emit_byte (mb, CEE_RET);
 
 	mb->dynamic = 1;
Index: mono/mono/metadata/threads-types.h
===================================================================
--- mono/mono/metadata/threads-types.h	(revision 133502)
+++ mono/mono/metadata/threads-types.h	(working copy)
@@ -53,7 +53,7 @@
 							 guint32 stacksize, WapiThreadStart start,
 							 gpointer param, guint32 create, gsize *tid) MONO_INTERNAL;
 
-void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread) MONO_INTERNAL;
+MonoThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread) MONO_INTERNAL;
 
 HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this_obj, MonoObject *start) MONO_INTERNAL;
 void ves_icall_System_Threading_Thread_Thread_init(MonoThread *this_obj) MONO_INTERNAL;
Index: mono/mono/mini/mini.c
===================================================================
--- mono/mono/mini/mini.c	(revision 133502)
+++ mono/mono/mini/mini.c	(working copy)
@@ -4772,6 +4772,7 @@
 	mono_install_jump_trampoline (mono_create_jump_trampoline);
 	mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
 	mono_install_delegate_trampoline (mono_create_delegate_trampoline);
+	mono_install_vtfixup_trampoline (mono_create_vtfixup_trampoline);
 	mono_install_create_domain_hook (mini_create_jit_domain_info);
 	mono_install_free_domain_hook (mini_free_jit_domain_info);
 #endif
Index: mono/mono/mini/mini.h
===================================================================
--- mono/mono/mini/mini.h	(revision 133502)
+++ mono/mono/mini/mini.h	(working copy)
@@ -794,6 +794,7 @@
 	MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
 	MONO_TRAMPOLINE_MONITOR_ENTER,
 	MONO_TRAMPOLINE_MONITOR_EXIT,
+	MONO_TRAMPOLINE_VTFIXUP,
 #ifdef ENABLE_LLVM
 	MONO_TRAMPOLINE_LLVM_VCALL,
 #endif
@@ -1434,6 +1435,7 @@
 gpointer          mono_create_monitor_enter_trampoline (void) MONO_INTERNAL;
 gpointer          mono_create_monitor_exit_trampoline (void) MONO_INTERNAL;
 gpointer          mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) MONO_INTERNAL;
+gpointer          mono_create_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32 token, guint16 type) MONO_INTERNAL;
 gpointer          mono_create_llvm_vcall_trampoline (MonoMethod *method) MONO_INTERNAL;
 MonoVTable*       mono_find_class_init_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
 MonoClass*        mono_find_delegate_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
Index: mono/mono/mini/mini-trampolines.c
===================================================================
--- mono/mono/mini/mini-trampolines.c	(revision 133502)
+++ mono/mono/mini/mini-trampolines.c	(working copy)
@@ -6,6 +6,7 @@
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/tabledefs.h>
+#include <mono/metadata/cil-coff.h>
 #include <mono/utils/mono-counters.h>
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
@@ -758,6 +759,52 @@
 	mono_monitor_exit (obj);
 }
 
+static gpointer
+mono_vtfixup_trampoline (gssize *regs, guint8 *code, guint8 *slot_info, guint8* tramp)
+{
+	gpointer tramp_addr;
+	gpointer slot, slot_addr;
+	MonoImage *image;
+	guint32 token;
+	guint16 type;
+	gpointer addr;
+
+	tramp_addr = *(gpointer*) (gpointer) slot_info;
+	slot_info += sizeof (gpointer);
+	slot = *(gpointer*) (gpointer) slot_info;
+	slot_info += sizeof (gpointer);
+	image = *(gpointer*) (gpointer) slot_info;
+	slot_info += sizeof (gpointer);
+	token = *(guint32*) (gpointer) slot_info;
+	slot_info += sizeof (guint32);
+	type = *(guint16*) (gpointer) slot_info;
+
+	if (type & VTFIXUP_TYPE_64BIT)
+		slot_addr = (gpointer) *((volatile gint64*) (slot));
+	else
+		slot_addr = (gpointer) *((volatile gint32*) (slot));
+
+	if (slot_addr != tramp_addr)
+		return slot_addr;
+
+	if (!image->assembly)
+		g_assert (mono_assembly_open (image->name, NULL));
+
+	addr = mono_marshal_get_vtfixup_ftnptr (image, token, type);
+	if (type & VTFIXUP_TYPE_64BIT)
+#if SIZEOF_VOID_P == 8
+		slot_addr = InterlockedCompareExchangePointer (slot, addr, tramp_addr);
+#else
+		slot_addr = (gpointer) ves_icall_System_Threading_Interlocked_CompareExchange_Long ((gint64*) slot, (gint64) addr, (gint64) tramp_addr);
+#endif
+	else
+		slot_addr = (gpointer) InterlockedCompareExchange ((gint32*) slot, (gint32) addr, (gint32) tramp_addr);
+
+	if (slot_addr == tramp_addr)
+		return addr;
+	return slot_addr;
+}
+
 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
 
 /**
@@ -905,6 +952,8 @@
 		return mono_monitor_enter_trampoline;
 	case MONO_TRAMPOLINE_MONITOR_EXIT:
 		return mono_monitor_exit_trampoline;
+	case MONO_TRAMPOLINE_VTFIXUP:
+		return mono_vtfixup_trampoline;
 #ifdef ENABLE_LLVM
 	case MONO_TRAMPOLINE_LLVM_VCALL:
 		return mono_llvm_vcall_trampoline;
@@ -939,6 +988,7 @@
 	mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
 	mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
 	mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
+	mono_trampoline_code [MONO_TRAMPOLINE_VTFIXUP] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_VTFIXUP);
 #ifdef ENABLE_LLVM
 	mono_trampoline_code [MONO_TRAMPOLINE_LLVM_VCALL] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_LLVM_VCALL);
 #endif
@@ -1271,7 +1321,31 @@
 #endif
 	return code;
 }
- 
+
+gpointer
+mono_create_vtfixup_trampoline (gpointer slot, MonoImage *image, guint32 token, guint16 type)
+{
+	gpointer tramp;
+
+	MonoDomain *domain = mono_get_root_domain ();
+	guint8 *buf, *start;
+
+	buf = start = mono_domain_code_reserve (domain, 3 * sizeof (gpointer) + sizeof (guint32) + sizeof (guint16));
+
+	buf += sizeof (gpointer);
+	*(gpointer*) (gpointer) buf = slot;
+	buf += sizeof (gpointer);
+	*(gpointer*) (gpointer) buf = image;
+	buf += sizeof (gpointer);
+	*(guint32*) (gpointer) buf = token;
+	buf += sizeof (guint32);
+	*(guint16*) (gpointer) buf = type;
+
+	tramp = mono_create_specific_trampoline (start, MONO_TRAMPOLINE_VTFIXUP, domain, NULL);
+	*(gpointer*) (gpointer) start = tramp;
+	return tramp;
+}
+
 #ifdef ENABLE_LLVM
 /*
  * mono_create_llvm_vcall_trampoline:
Index: mono/mono/mini/driver.c
===================================================================
--- mono/mono/mini/driver.c	(revision 133502)
+++ mono/mono/mini/driver.c	(working copy)
@@ -1187,8 +1187,9 @@
 		mono_install_runtime_load (mini_init);
 		break;
 	case DLL_PROCESS_DETACH:
-		if (coree_module_handle)
-			FreeLibrary (coree_module_handle);
+		/* Should not be unloaded after mscoree.dll was fixed up. */
+		if (!reserved && coree_module_handle)
+			g_assert_not_reached ();
 		break;
 	}
 	return TRUE;
@@ -1532,6 +1533,9 @@
 
 	mono_set_defaults (mini_verbose, opt);
 	mono_setup_vtable_in_class_init = FALSE;
+#ifdef PLATFORM_WIN32
+	mono_set_act_ctx (argv [i]);
+#endif
 	domain = mini_init (argv [i], forced_version);
 
 	if (agents) {
@@ -1630,6 +1634,8 @@
 		/* Detach console when executing IMAGE_SUBSYSTEM_WINDOWS_GUI on win32 */
 		if (!enable_debugging && !mono_compile_aot && ((MonoCLIImageInfo*)(mono_assembly_get_image (assembly)->image_info))->cli_header.nt.pe_subsys_required == IMAGE_SUBSYSTEM_WINDOWS_GUI)
 			FreeConsole ();
+
+		mono_fixup_exe_image (mono_assembly_get_image (assembly));
 #endif
 
 		main_args.domain = domain;
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to