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