From 0b96691cc6c229dfa7a13c1bd515c179ea809506 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 17 Apr 2015 16:49:05 -0400 Subject: [PATCH] [jit] Allow the storage of trampolines in the jit info tables. Currently, this is only used by mono_print_method_from_ip (). --- mono/metadata/domain-internals.h | 8 ++++- mono/metadata/jit-info.c | 11 +++++-- mono/metadata/sgen-stw.c | 2 +- mono/mini/mini-exceptions.c | 16 ++++++---- mono/mini/mini-runtime.c | 51 +++++++++++++++++++++++++------- mono/mini/mini.h | 1 + 6 files changed, 70 insertions(+), 19 deletions(-) diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 317db53276f..a5fc96dec61 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -210,6 +210,7 @@ struct _MonoJitInfo { MonoMethod *method; MonoImage *image; gpointer aot_info; + gpointer tramp_info; } d; struct _MonoJitInfo *next_jit_code_hash; gpointer code_start; @@ -230,6 +231,11 @@ struct _MonoJitInfo { gboolean async:1; gboolean dbg_step_through:1; gboolean dbg_non_user_code:1; + /* + * Whenever this jit info refers to a trampoline. + * d.tramp_info contains additional data in this case. + */ + gboolean is_trampoline:1; /* FIXME: Embed this after the structure later*/ gpointer gc_info; /* Currently only used by SGen */ @@ -685,7 +691,7 @@ void mono_reflection_cleanup_domain (MonoDomain *domain); void mono_assembly_cleanup_domain_bindings (guint32 domain_id); -MonoJitInfo* mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot); +MonoJitInfo* mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot, gboolean allow_trampolines); void mono_enable_debug_domain_unload (gboolean enable); diff --git a/mono/metadata/jit-info.c b/mono/metadata/jit-info.c index cc0b76622fb..0698d6c1b9e 100644 --- a/mono/metadata/jit-info.c +++ b/mono/metadata/jit-info.c @@ -266,12 +266,13 @@ jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint * * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe. * In this case, only those AOT methods will be found whose jit info is already loaded. + * If ALLOW_TRAMPOLINES is TRUE, this can return a MonoJitInfo which represents a trampoline (ji->is_trampoline is true). * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe. * In this case, the returned MonoJitInfo might not have metadata information, in particular, * mono_jit_info_get_method () could fail. */ MonoJitInfo* -mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot) +mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot, gboolean allow_trampolines) { MonoJitInfoTable *table; MonoJitInfo *ji, *module_ji; @@ -292,6 +293,8 @@ mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_ ji = jit_info_table_find (table, hp, (gint8*)addr); if (hp) mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); + if (ji && ji->is_trampoline && !allow_trampolines) + return NULL; if (ji) return ji; @@ -304,6 +307,9 @@ mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_ if (hp) mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); } + + if (ji && ji->is_trampoline && !allow_trampolines) + return NULL; return ji; } @@ -311,7 +317,7 @@ mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_ MonoJitInfo* mono_jit_info_table_find (MonoDomain *domain, char *addr) { - return mono_jit_info_table_find_internal (domain, addr, TRUE); + return mono_jit_info_table_find_internal (domain, addr, TRUE, FALSE); } static G_GNUC_UNUSED void @@ -817,6 +823,7 @@ MonoMethod* mono_jit_info_get_method (MonoJitInfo* ji) { g_assert (!ji->async); + g_assert (!ji->is_trampoline); return ji->d.method; } diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index 9078f6bb07a..c16d380d5a7 100644 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -104,7 +104,7 @@ is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip) * missing methods (#13951). To work around this, we disable the AOT fallback. For this to work, the JIT needs * to register the jit info for all GC critical methods after they are JITted/loaded. */ - ji = mono_jit_info_table_find_internal (domain, ip, FALSE); + ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE); if (!ji) return FALSE; diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index e96392764f0..d457487ce93 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -1169,14 +1169,14 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex } /* - * mini_jit_info_table_find: + * mini_jit_info_table_find_ext: * * Same as mono_jit_info_table_find, but search all the domains of the current thread * if ADDR is not found in DOMAIN. The domain where the method was found is stored into * OUT_DOMAIN if it is not NULL. */ MonoJitInfo* -mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain) +mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain) { MonoJitInfo *ji; MonoInternalThread *t = mono_thread_internal_current (); @@ -1185,7 +1185,7 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai if (out_domain) *out_domain = NULL; - ji = mono_jit_info_table_find (domain, addr); + ji = mono_jit_info_table_find_internal (domain, addr, TRUE, allow_trampolines); if (ji) { if (out_domain) *out_domain = domain; @@ -1194,7 +1194,7 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai /* maybe it is shared code, so we also search in the root domain */ if (domain != mono_get_root_domain ()) { - ji = mono_jit_info_table_find (mono_get_root_domain (), addr); + ji = mono_jit_info_table_find_internal (mono_get_root_domain (), addr, TRUE, allow_trampolines); if (ji) { if (out_domain) *out_domain = mono_get_root_domain (); @@ -1208,7 +1208,7 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai refs = (t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL; for (; refs && *refs; refs++) { if (*refs != domain && *refs != mono_get_root_domain ()) { - ji = mono_jit_info_table_find ((MonoDomain*) *refs, addr); + ji = mono_jit_info_table_find_internal ((MonoDomain*) *refs, addr, TRUE, allow_trampolines); if (ji) { if (out_domain) *out_domain = (MonoDomain*) *refs; @@ -1220,6 +1220,12 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai return NULL; } +MonoJitInfo* +mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain) +{ + return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain); +} + /* * wrap_non_exception_throws: * diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 0f70d05a90d..841ee66b2a7 100755 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -226,29 +226,28 @@ mono_print_method_from_ip (void *ip) FindTrampUserData user_data; MonoGenericSharingContext*gsctx; const char *shared_type; - GSList *l; - ji = mini_jit_info_table_find (domain, ip, &target_domain); + ji = mini_jit_info_table_find_ext (domain, ip, TRUE, &target_domain); + if (ji && ji->is_trampoline) { + MonoTrampInfo *tinfo = ji->d.tramp_info; + + printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name); + return; + } + if (!ji) { user_data.ip = ip; user_data.method = NULL; mono_domain_lock (domain); g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data); mono_domain_unlock (domain); + if (user_data.method) { char *mname = mono_method_full_name (user_data.method, TRUE); printf ("IP %p is a JIT trampoline for %s\n", ip, mname); g_free (mname); return; } - for (l = tramp_infos; l; l = l->next) { - MonoTrampInfo *tinfo = l->data; - - if ((guint8*)ip >= tinfo->code && (guint8*)ip <= tinfo->code + tinfo->code_size) { - printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name); - return; - } - } g_print ("No method at %p\n", ip); fflush (stdout); @@ -471,6 +470,20 @@ mono_tramp_info_free (MonoTrampInfo *info) g_free (info); } +static void +register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info) +{ + MonoJitInfo *ji; + + ji = mono_domain_alloc0 (domain, mono_jit_info_size (0, 0, 0)); + mono_jit_info_init (ji, NULL, info->code, info->code_size, 0, 0, 0); + ji->d.tramp_info = info; + ji->is_trampoline = TRUE; + // FIXME: Unwind info + + mono_jit_info_table_add (domain, ji); +} + /* * mono_tramp_info_register: * @@ -497,6 +510,9 @@ mono_tramp_info_register (MonoTrampInfo *info) mono_save_trampoline_xdebug_info (info); + if (mono_get_root_domain ()) + register_trampoline_jit_info (mono_get_root_domain (), copy); + if (mono_jit_map_is_enabled ()) mono_emit_jit_tramp (info->code, info->code_size, info->name); @@ -516,6 +532,19 @@ mono_tramp_info_cleanup (void) g_slist_free (tramp_infos); } +/* Register trampolines created before the root domain was created in the jit info tables */ +static void +register_trampolines (MonoDomain *domain) +{ + GSList *l; + + for (l = tramp_infos; l; l = l->next) { + MonoTrampInfo *info = l->data; + + register_trampoline_jit_info (domain, info); + } +} + G_GNUC_UNUSED static void break_count (void) { @@ -3141,6 +3170,8 @@ mini_init (const char *filename, const char *runtime_version) mono_tasklets_init (); #endif + register_trampolines (domain); + if (mono_compile_aot) /* * Avoid running managed code when AOT compiling, since the platform diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 1b97399f855..11b446709a9 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2640,6 +2640,7 @@ void mono_setup_altstack (MonoJitTlsData *tls); void mono_free_altstack (MonoJitTlsData *tls); gpointer mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp); MonoJitInfo* mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain); +MonoJitInfo* mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain); void mono_resume_unwind (MonoContext *ctx) MONO_LLVM_INTERNAL; MonoJitInfo * mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset, gboolean *managed); -- 2.25.1