X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-amd64.c;h=7611b48d46250eddfdea141450036dbe6c82e752;hb=f233a1c472f36dd1d84e3d01de04eca9958262ea;hp=5d890aa2a285f28fdfe652e84538d713d04b20e3;hpb=3980eb0b28ecb8380c6f923fb09fca8287200b66;p=mono.git diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index 5d890aa2a28..7611b48d462 100644 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -18,9 +18,7 @@ #include #include -#ifdef HAVE_VALGRIND_MEMCHECK_H -#include -#endif +#include #include "mini.h" #include "mini-amd64.h" @@ -62,6 +60,67 @@ mono_arch_get_unbox_trampoline (MonoGenericSharingContext *gsctx, MonoMethod *m, return start; } +/* + * mono_arch_get_static_rgctx_trampoline: + * + * Create a trampoline which sets RGCTX_REG to MRGCTX, then jumps to ADDR. + */ +gpointer +mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr) +{ + guint8 *code, *start; + int buf_len; + + MonoDomain *domain = mono_domain_get (); + +#ifdef MONO_ARCH_NOMAP32BIT + buf_len = 32; +#else + /* AOTed code could still have a non-32 bit address */ + if ((((guint64)addr) >> 32) == 0) + buf_len = 16; + else + buf_len = 30; +#endif + + start = code = mono_domain_code_reserve (domain, buf_len); + + amd64_mov_reg_imm (code, MONO_ARCH_RGCTX_REG, mrgctx); + amd64_jump_code (code, addr); + g_assert ((code - start) < buf_len); + + mono_arch_flush_icache (start, code - start); + + return start; +} + +gpointer +mono_arch_get_llvm_imt_trampoline (MonoDomain *domain, MonoMethod *m, int vt_offset) +{ + guint8 *code, *start; + int buf_len; + int this_reg; + + buf_len = 32; + + start = code = mono_domain_code_reserve (domain, buf_len); + + this_reg = mono_arch_get_this_arg_reg (mono_method_signature (m), NULL, NULL); + + /* Set imt arg */ + amd64_mov_reg_imm (code, MONO_ARCH_IMT_REG, m); + /* Load vtable address */ + amd64_mov_reg_membase (code, AMD64_RAX, this_reg, 0, 8); + amd64_jump_membase (code, AMD64_RAX, vt_offset); + amd64_ret (code); + + g_assert ((code - start) < buf_len); + + mono_arch_flush_icache (start, code - start); + + return start; +} + /* * mono_arch_patch_callsite: * @@ -81,12 +140,11 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) if (code [-5] != 0xe8) { if (can_write) { InterlockedExchangePointer ((gpointer*)(orig_code - 11), addr); -#ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_DISCARD_TRANSLATIONS (orig_code - 11, sizeof (gpointer)); -#endif } } else { if ((((guint64)(addr)) >> 32) != 0) { +#ifdef MONO_ARCH_NOMAP32BIT /* Print some diagnostics */ MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), (char*)orig_code); if (ji) @@ -96,13 +154,24 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) if (ji) fprintf (stderr, "Callee: %s\n", mono_method_full_name (ji->method, TRUE)); g_assert_not_reached (); +#else + /* + * This might happen when calling AOTed code. Create a thunk. + */ + guint8 *thunk_start, *thunk_code; + + thunk_start = thunk_code = mono_domain_code_reserve (mono_domain_get (), 32); + amd64_jump_membase (thunk_code, AMD64_RIP, 0); + *(guint64*)thunk_code = (guint64)addr; + addr = thunk_start; + g_assert ((((guint64)(addr)) >> 32) == 0); + mono_arch_flush_icache (thunk_start, thunk_code - thunk_start); +#endif } g_assert ((((guint64)(orig_code)) >> 32) == 0); if (can_write) { InterlockedExchange ((gint32*)(orig_code - 4), ((gint64)addr - (gint64)orig_code)); -#ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_DISCARD_TRANSLATIONS (orig_code - 5, 4); -#endif } } } @@ -111,15 +180,13 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) gpointer *got_entry = (gpointer*)((guint8*)orig_code + (*(guint32*)(orig_code - 4))); if (can_write) { InterlockedExchangePointer (got_entry, addr); -#ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_DISCARD_TRANSLATIONS (orig_code - 5, sizeof (gpointer)); -#endif } } } void -mono_arch_patch_plt_entry (guint8 *code, guint8 *addr) +mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) { gint32 disp; gpointer *plt_jump_table_entry; @@ -136,10 +203,19 @@ mono_arch_patch_plt_entry (guint8 *code, guint8 *addr) } void -mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs) +mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs) { guint8 buf [16]; - gboolean can_write = mono_breakpoint_clean_code (NULL, code, 7, buf, sizeof (buf)); + MonoJitInfo *ji = NULL; + gboolean can_write; + + if (mono_use_llvm) { + /* code - 7 might be before the start of the method */ + /* FIXME: Avoid this expensive call somehow */ + ji = mono_jit_info_table_find (mono_domain_get (), (char*)code); + } + + can_write = mono_breakpoint_clean_code (ji ? ji->code_start : NULL, code, 7, buf, sizeof (buf)); if (!can_write) return; @@ -151,17 +227,17 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs) * really careful about the ordering of the cases. Longer sequences * come first. */ - if ((code [-4] == 0x41) && (code [-3] == 0xff) && (code [-2] == 0x15)) { + if ((buf [0] == 0x41) && (buf [1] == 0xff) && (buf [2] == 0x15)) { gpointer *vtable_slot; /* call *(%rip) */ - vtable_slot = mono_arch_get_vcall_slot_addr (code + 3, (gpointer*)regs); + vtable_slot = mono_get_vcall_slot_addr (code + 3, regs); g_assert (vtable_slot); *vtable_slot = nullified_class_init_trampoline; - } else if (code [-2] == 0xe8) { + } else if (buf [2] == 0xe8) { /* call */ - guint8 *buf = code - 2; + //guint8 *buf = code - 2; /* * It would be better to replace the call with nops, but that doesn't seem @@ -176,45 +252,32 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs) buf [4] = 0x90; */ - mono_arch_patch_callsite (NULL, code - 2 + 5, nullified_class_init_trampoline); - } else if ((code [0] == 0x41) && (code [1] == 0xff)) { - /* call */ - /* happens on machines without MAP_32BIT like freebsd */ - /* amd64_set_reg_template is 10 bytes long */ - guint8* buf = code - 10; + mono_arch_patch_callsite (code - 2, code - 2 + 5, nullified_class_init_trampoline); + } else if ((buf [5] == 0xff) && x86_modrm_mod (buf [6]) == 3 && x86_modrm_reg (buf [6]) == 2) { + /* call * */ + /* Generated by the LLVM JIT or on platforms without MAP_32BIT set */ + guint8* buf = code; - /* FIXME: Make this thread safe */ - /* Padding code suggested by the AMD64 Opt Manual */ - buf [0] = 0x66; - buf [1] = 0x66; - buf [2] = 0x66; - buf [3] = 0x90; - buf [4] = 0x66; - buf [5] = 0x66; - buf [6] = 0x66; - buf [7] = 0x90; - buf [8] = 0x66; - buf [9] = 0x66; - buf [10] = 0x90; - buf [11] = 0x66; - buf [12] = 0x90; - } else if (code [0] == 0x90 || code [0] == 0xeb || code [0] == 0x66) { + /* FIXME: Not thread safe */ + buf [1] = 0x90; + buf [2] = 0x90; + } else if (buf [4] == 0x90 || buf [5] == 0xeb || buf [6] == 0x66) { /* Already changed by another thread */ ; } else { - printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3], - code [4], code [5], code [6]); + printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", buf [0], buf [1], buf [2], buf [3], + buf [4], buf [5], buf [6]); g_assert_not_reached (); } } void -mono_arch_nullify_plt_entry (guint8 *code) +mono_arch_nullify_plt_entry (guint8 *code, mgreg_t *regs) { if (mono_aot_only && !nullified_class_init_trampoline) nullified_class_init_trampoline = mono_aot_get_named_code ("nullified_class_init_trampoline"); - mono_arch_patch_plt_entry (code, nullified_class_init_trampoline); + mono_arch_patch_plt_entry (code, NULL, regs, nullified_class_init_trampoline); } guchar* @@ -398,7 +461,7 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c amd64_mov_membase_imm (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), 0, 8); } /* Save callee saved regs */ -#ifdef PLATFORM_WIN32 +#ifdef TARGET_WIN32 amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rdi), AMD64_RDI, 8); amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsi), AMD64_RSI, 8); #endif @@ -599,7 +662,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline_full (guint32 slot, guint32 *code_s mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); index = MONO_RGCTX_SLOT_INDEX (slot); if (mrgctx) - index += sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer); + index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer); for (depth = 0; ; ++depth) { int size = mono_class_rgctx_get_array_size (depth, mrgctx); @@ -630,7 +693,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline_full (guint32 slot, guint32 *code_s for (i = 0; i < depth; ++i) { /* load ptr to next array */ if (mrgctx && i == 0) - amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, sizeof (MonoMethodRuntimeGenericContext), 8); + amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 8); else amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, 0, 8); /* is the ptr null? */ @@ -785,10 +848,10 @@ mono_arch_create_monitor_enter_trampoline_full (guint32 *code_size, MonoJumpInfo jump_sync_null = code; amd64_branch8 (code, X86_CC_Z, -1, 1); - /* load MonoThread* into RDX */ + /* load MonoInternalThread* into RDX */ code = mono_amd64_emit_tls_get (code, AMD64_RDX, mono_thread_get_tls_offset ()); /* load TID into RDX */ - amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, G_STRUCT_OFFSET (MonoThread, tid), 8); + amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, G_STRUCT_OFFSET (MonoInternalThread, tid), 8); /* is synchronization->owner null? */ amd64_alu_membase_imm_size (code, X86_CMP, AMD64_RCX, owner_offset, 0, 8); @@ -905,10 +968,10 @@ mono_arch_create_monitor_exit_trampoline_full (guint32 *code_size, MonoJumpInfo /* next case: synchronization is not null */ x86_patch (jump_next, code); - /* load MonoThread* into RDX */ + /* load MonoInternalThread* into RDX */ code = mono_amd64_emit_tls_get (code, AMD64_RDX, mono_thread_get_tls_offset ()); /* load TID into RDX */ - amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, G_STRUCT_OFFSET (MonoThread, tid), 8); + amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, G_STRUCT_OFFSET (MonoInternalThread, tid), 8); /* is synchronization->owner == TID */ amd64_alu_membase_reg_size (code, X86_CMP, AMD64_RCX, owner_offset, AMD64_RDX, 8); /* if yes, jump to next case */