From: Vlad Brezae Date: Thu, 19 Nov 2015 19:48:07 +0000 (+0200) Subject: [arm] Rework tls detection on android in order to be more strict X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=62682da5e12af5f494ec81bffd77a40cb0438220;p=mono.git [arm] Rework tls detection on android in order to be more strict Unify the tls implementation across platform using a TlsImplementation structure which maps a potential pthread_getspecific implementation to the corresponding fastpaths. Some implementations might require an additional check of the kuser_get_tls kernel helper. --- diff --git a/mono/mini/mini-arm-tls.h b/mono/mini/mini-arm-tls.h index 30b2494dfc7..a61d699cf17 100644 --- a/mono/mini/mini-arm-tls.h +++ b/mono/mini/mini-arm-tls.h @@ -16,4 +16,65 @@ void mono_fallback_set_tls_key (int, int); void mono_fast_get_tls_key_end (void); void mono_fast_set_tls_key_end (void); + +/* Structure that maps a possible tls implementation to the corresponding thunks */ +typedef struct { + guint32 *expected_code; + int expected_code_length; + gboolean check_kernel_helper; + gpointer get_tls_thunk; + gpointer get_tls_thunk_end; + gpointer set_tls_thunk; + gpointer set_tls_thunk_end; +} MonoTlsImplementation; + + +static MonoTlsImplementation known_tls_implementations [] = { +#if defined(HAVE_KW_THREAD) && defined(__linux__) + { NULL, 0, TRUE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end } +#elif defined(TARGET_IOS) + { (guint32[]) {0x1f70ee1d, 0x0103f021, 0x0020f851, 0xbf004770}, 16, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end } +#elif defined(TARGET_ANDROID) + { (guint32[]) {0xe2403003, 0xe353003c, 0xe92d4010, 0xe1a04000, 0x9a000001, 0xe3a00000, 0xe8bd8010, 0xe3e00a0f, 0xe240101f, 0xe12fff31, 0xe7900104, 0xe8bd8010}, 48, TRUE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 1.5 */ + { (guint32[]) {0xe2402003, 0xe1a03000, 0xe352003c, 0x8a000002, 0xee1d0f70, 0xe7900103, 0xe12fff1e}, 28, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 4.2 */ + { (guint32[]) {0xe2403007, 0xe3530084, 0x8a000002, 0xee1d1f70, 0xe7910100, 0xe12fff1e, 0xe3a00000, 0xe12fff1e}, 32, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 4.4 */ + { (guint32[]) {0x2b8c1fc3, 0xee1dd804, 0xf8511f70, 0x47700020, 0x47702000}, 20, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end} /* 5.0 */ +#endif +}; + +static gboolean +known_kernel_helper (void) +{ +#ifdef __linux__ + const guint32* kuser_get_tls = (void*)0xffff0fe0; /* linux kernel user helper on arm */ + guint32 expected [] = {0xee1d0f70, 0xe12fff1e}; + + /* Expecting mrc + bx lr in the kuser_get_tls kernel helper */ + return memcmp (kuser_get_tls, expected, 8) == 0; +#else + g_error ("Trying to check linux kernel helper on non linux platform"); + return FALSE; +#endif +} + +static MonoTlsImplementation +mono_arm_get_tls_implementation (void) +{ + /* Discard thumb bit */ + guint32* pthread_getspecific_addr = (guint32*) ((guint32)pthread_getspecific & 0xfffffffe); + int i; + + if (!mini_get_debug_options ()->arm_use_fallback_tls) { + for (i = 0; i < sizeof (known_tls_implementations) / sizeof (MonoTlsImplementation); i++) { + if (memcmp (pthread_getspecific_addr, known_tls_implementations [i].expected_code, known_tls_implementations [i].expected_code_length) == 0) { + if ((known_tls_implementations [i].check_kernel_helper && known_kernel_helper ()) || + !known_tls_implementations [i].check_kernel_helper) + return known_tls_implementations [i]; + } + } + } + + g_warning ("No fast tls on device. Using fallbacks.\n"); + return (MonoTlsImplementation) { NULL, 0, FALSE, mono_fallback_get_tls_key, NULL, mono_fallback_set_tls_key, NULL }; +} #endif diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 2798808809f..a030c4950d1 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -645,30 +645,6 @@ emit_restore_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset) #endif /* #ifndef DISABLE_JIT */ -#ifndef MONO_CROSS_COMPILE -static gboolean -mono_arm_have_fast_tls (void) -{ - if (mini_get_debug_options ()->arm_use_fallback_tls) - return FALSE; -#if (defined(HAVE_KW_THREAD) && defined(__linux__)) \ - || defined(TARGET_ANDROID) - guint32* kuser_get_tls = (void*)0xffff0fe0; - guint32 expected [] = {0xee1d0f70, 0xe12fff1e}; - - /* Expecting mrc + bx lr in the kuser_get_tls kernel helper */ - return memcmp (kuser_get_tls, expected, 8) == 0; -#elif defined(TARGET_IOS) - guint32 expected [] = {0x1f70ee1d, 0x0103f021, 0x0020f851, 0xbf004770}; - /* Discard thumb bit */ - guint32* pthread_getspecific_addr = (guint32*) ((guint32)pthread_getspecific & 0xfffffffe); - return memcmp ((void*)pthread_getspecific_addr, expected, 16) == 0; -#else - return FALSE; -#endif -} -#endif - /* * mono_arm_have_tls_get: * @@ -5986,15 +5962,17 @@ mono_arch_register_lowlevel_calls (void) #ifndef MONO_CROSS_COMPILE if (mono_arm_have_tls_get ()) { - if (mono_arm_have_fast_tls ()) { - mono_register_jit_icall (mono_fast_get_tls_key, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE); - mono_register_jit_icall (mono_fast_set_tls_key, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE); + MonoTlsImplementation tls_imp = mono_arm_get_tls_implementation (); + + mono_register_jit_icall (tls_imp.get_tls_thunk, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE); + mono_register_jit_icall (tls_imp.set_tls_thunk, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE); + if (tls_imp.get_tls_thunk_end) { mono_tramp_info_register ( mono_tramp_info_create ( "mono_get_tls_key", - (guint8*)mono_fast_get_tls_key, - (guint8*)mono_fast_get_tls_key_end - (guint8*)mono_fast_get_tls_key, + (guint8*)tls_imp.get_tls_thunk, + (guint8*)tls_imp.get_tls_thunk_end - (guint8*)tls_imp.get_tls_thunk, NULL, mono_arch_get_cie_program () ), @@ -6003,17 +5981,13 @@ mono_arch_register_lowlevel_calls (void) mono_tramp_info_register ( mono_tramp_info_create ( "mono_set_tls_key", - (guint8*)mono_fast_set_tls_key, - (guint8*)mono_fast_set_tls_key_end - (guint8*)mono_fast_set_tls_key, + (guint8*)tls_imp.set_tls_thunk, + (guint8*)tls_imp.set_tls_thunk_end - (guint8*)tls_imp.set_tls_thunk, NULL, mono_arch_get_cie_program () ), NULL ); - } else { - g_warning ("No fast tls on device. Using fallbacks."); - mono_register_jit_icall (mono_fallback_get_tls_key, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE); - mono_register_jit_icall (mono_fallback_set_tls_key, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE); } } #endif