Test case for bug#325444.
[mono.git] / mono / mini / tramp-amd64.c
index ba788ca001c7d0b2fea3ab67b0528dda470e6114..0d606cc5f8dfb2190706ec05554b6ca150e2f7a1 100644 (file)
@@ -13,6 +13,7 @@
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/tabledefs.h>
+#include <mono/metadata/mono-debug-debugger.h>
 #include <mono/arch/amd64/amd64-codegen.h>
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
@@ -69,7 +70,7 @@ mono_arch_patch_callsite (guint8 *code, guint8 *addr)
                else {
                        g_assert ((((guint64)(addr)) >> 32) == 0);
                        g_assert ((((guint64)(code)) >> 32) == 0);
-                       InterlockedExchange ((guint32*)(code - 4), ((gint64)addr - (gint64)code));
+                       InterlockedExchange ((gint32*)(code - 4), ((gint64)addr - (gint64)code));
                }
        }
        else if ((code [-7] == 0x41) && (code [-6] == 0xff) && (code [-5] == 0x15)) {
@@ -79,6 +80,23 @@ mono_arch_patch_callsite (guint8 *code, guint8 *addr)
        }
 }
 
+void
+mono_arch_patch_plt_entry (guint8 *code, guint8 *addr)
+{
+       gint32 disp;
+       gpointer *plt_jump_table_entry;
+
+       /* A PLT entry: jmp *<DISP>(%rip) */
+       g_assert (code [0] == 0xff);
+       g_assert (code [1] == 0x25);
+
+       disp = *(gint32*)(code + 2);
+
+       plt_jump_table_entry = (gpointer*)(code + 6 + disp);
+
+       InterlockedExchangePointer (plt_jump_table_entry, addr);
+}
+
 void
 mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
 {
@@ -106,8 +124,9 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
                buf [2] = 0x90;
                buf [3] = 0x66;
                buf [4] = 0x90;
-       } else if ((code [0] == 0x49) && (code [1] == 0xff)) {
+       } else if ((code [0] == 0x41) && (code [1] == 0xff)) {
                /* call <REG> */
+               /* happens on machines without MAP_32BIT like freebsd */
                /* amd64_set_reg_template is 10 bytes long */
                guint8* buf = code - 10;
 
@@ -137,35 +156,9 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
 }
 
 void
-mono_arch_patch_delegate_trampoline (guint8 *code, guint8 *tramp, gssize *regs, guint8 *addr)
+mono_arch_nullify_plt_entry (guint8 *code)
 {
-       guint8 rex = 0;
-       guint32 reg;
-       guint32 disp;
-
-       if ((code [-3] == 0xff) && (amd64_modrm_reg (code [-2]) == 0x2) && (amd64_modrm_mod (code [-2]) == 0x1)) {
-               /* call *[reg+disp8] */
-               if (IS_REX (code [-4]))
-                       rex = code [-4];
-               reg = amd64_modrm_rm (code [-2]);
-               disp = *(guint8*)(code - 1);
-               //printf ("B: [%%r%d+0x%x]\n", reg, disp);
-       }
-       else {
-               int i;
-
-               for (i = -16; i < 0; ++i)
-                       printf ("%d ", code [i]);
-               printf ("\n");
-               g_assert_not_reached ();
-       }
-
-       reg += amd64_rex_b (rex);
-
-       /* R11 is clobbered by the trampoline code */
-       g_assert (reg != AMD64_R11);
-
-       *(gpointer*)(((guint64)(regs [reg])) + disp) = addr;
+       mono_arch_patch_plt_entry (code, nullified_class_init_trampoline);
 }
 
 guchar*
@@ -281,6 +274,8 @@ mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
                tramp = (guint8*)mono_class_init_trampoline;
        else if (tramp_type == MONO_TRAMPOLINE_AOT)
                tramp = (guint8*)mono_aot_trampoline;
+       else if (tramp_type == MONO_TRAMPOLINE_AOT_PLT)
+               tramp = (guint8*)mono_aot_plt_trampoline;
        else if (tramp_type == MONO_TRAMPOLINE_DELEGATE)
                tramp = (guint8*)mono_delegate_trampoline;
        else
@@ -355,23 +350,17 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
        g_assert ((code - buf) <= TRAMPOLINE_SIZE);
 
        mono_domain_lock (domain);
-       /* 
-        * FIXME: Changing the size to code - buf causes strange crashes during
-        * mcs bootstrap.
-        */
-       real_code = mono_code_manager_reserve (domain->code_mp, TRAMPOLINE_SIZE);
+       real_code = mono_code_manager_reserve (domain->code_mp, code - buf);
        size = code - buf;
        mono_domain_unlock (domain);
 
        memcpy (real_code, buf, size);
 
        /* Fix up jump */
-       g_assert ((((gint64)tramp) >> 32) == 0);
        code = (guint8*)real_code + jump_offset;
+       g_assert (amd64_is_imm32 (((gint64)tramp - (gint64)code)));
        amd64_jump_disp (code, tramp - code);
 
-       mono_jit_stats.method_trampolines++;
-
        if (code_len)
                *code_len = size;
 
@@ -397,16 +386,12 @@ mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
  * This method is only called when running in the Mono Debugger.
  */
 gpointer
-mono_debugger_create_notification_function (gpointer *notification_address)
+mono_debugger_create_notification_function (void)
 {
-       guint8 *ptr, *buf;
-
-       ptr = buf = mono_global_codeman_reserve (16);
+       guint8 *buf, *code;
 
+       code = buf = mono_global_codeman_reserve (2);
        x86_breakpoint (buf);
-       if (notification_address)
-               *notification_address = buf;
        x86_ret (buf);
-
-       return ptr;
+       return code;
 }