X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmach-support-arm.c;h=eb1e009bfc20c8648ef993432ee01ef1f7f25cda;hb=54be6b1d53c2510a21e7cdbf4e246403c2a92591;hp=ebead18cab8e9bad44640b271d7c307c77d6cdc0;hpb=5a35198e2fdb794d48af81d80e783644a29d7291;p=mono.git diff --git a/mono/utils/mach-support-arm.c b/mono/utils/mach-support-arm.c index ebead18cab8..eb1e009bfc2 100644 --- a/mono/utils/mach-support-arm.c +++ b/mono/utils/mach-support-arm.c @@ -16,83 +16,194 @@ #include #include #include "utils/mono-sigcontext.h" +#include "utils/mono-compiler.h" #include "mach-support.h" +/* _mcontext.h now defines __darwin_mcontext32, not __darwin_mcontext, starting with Xcode 5.1 */ +#ifdef _STRUCT_MCONTEXT32 + #define __darwin_mcontext __darwin_mcontext32 +#endif + +/* Known offsets used for TLS storage*/ + + +static const int known_tls_offsets[] = { + 0x48, /*Found on iOS 6 */ + 0xA4, + 0xA8, +}; + +#define TLS_PROBE_COUNT (sizeof (known_tls_offsets) / sizeof (int)) + +/* This is 2 slots less than the known low */ +#define TLS_PROBE_LOW_WATERMARK 0x40 +/* This is 24 slots above the know high, which is the same diff as the knowns high-low*/ +#define TLS_PROBE_HIGH_WATERMARK 0x108 + +static int tls_vector_offset; + void * mono_mach_arch_get_ip (thread_state_t state) { + /* Can't use unified_thread_state on !ARM64 since this has to compile on armv6 too */ +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + + return (void *) arch_state->ts_64.__pc; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; return (void *) arch_state->__pc; +#endif } void * mono_mach_arch_get_sp (thread_state_t state) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + + return (void *) arch_state->ts_64.__sp; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; return (void *) arch_state->__sp; +#endif } int mono_mach_arch_get_mcontext_size () { +#ifdef TARGET_ARM64 + return sizeof (struct __darwin_mcontext64); +#else return sizeof (struct __darwin_mcontext); +#endif } void -mono_mach_arch_thread_state_to_mcontext (thread_state_t state, mcontext_t context) +mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context; + + ctx->__ss = arch_state->ts_64; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context; ctx->__ss = *arch_state; +#endif } void -mono_mach_arch_mcontext_to_thread_state (mcontext_t context, thread_state_t state) +mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context; + + arch_state->ts_64 = ctx->__ss; +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context; *arch_state = ctx->__ss; +#endif } int mono_mach_arch_get_thread_state_size () { +#ifdef TARGET_ARM64 + return sizeof (arm_unified_thread_state_t); +#else return sizeof (arm_thread_state_t); +#endif } kern_return_t mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count) { +#ifdef TARGET_ARM64 + arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; + kern_return_t ret; + + *count = ARM_UNIFIED_THREAD_STATE_COUNT; + + ret = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE, (thread_state_t) arch_state, count); +#else arm_thread_state_t *arch_state = (arm_thread_state_t *) state; kern_return_t ret; *count = ARM_THREAD_STATE_COUNT; - ret = thread_get_state (thread, ARM_THREAD_STATE_COUNT, (thread_state_t) arch_state, count); - + ret = thread_get_state (thread, ARM_THREAD_STATE, (thread_state_t) arch_state, count); +#endif return ret; } kern_return_t mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count) { +#ifdef TARGET_ARM64 + return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE_COUNT, state, count); +#else return thread_set_state (thread, ARM_THREAD_STATE_COUNT, state, count); +#endif } void * -mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key) +mono_mach_get_tls_address_from_thread (pthread_t thread, pthread_key_t key) { - /* OSX stores TLS values in a hidden array inside the pthread_t structure - * They are keyed off a giant array offset 0x48 into the pointer. This value + /* Mach stores TLS values in a hidden array inside the pthread_t structure + * They are keyed off a giant array from a known offset into the pointer. This value * is baked into their pthread_getspecific implementation */ intptr_t *p = (intptr_t *) thread; - intptr_t **tsd = (intptr_t **) ((char*)p + 0x48 + (key << 2)); + intptr_t **tsd = (intptr_t **) ((char*)p + tls_vector_offset); - return (void *) *tsd; + return (void *) &tsd [key]; } + +void * +mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key) +{ + return *(void**)mono_mach_get_tls_address_from_thread (thread, key); +} + +void +mono_mach_init (pthread_key_t key) +{ + int i; + void *old_value = pthread_getspecific (key); + void *canary = (void*)0xDEADBEEFu; + + pthread_key_create (&key, NULL); + g_assert (old_value != canary); + + pthread_setspecific (key, canary); + + /*First we probe for cats*/ + for (i = 0; i < TLS_PROBE_COUNT; ++i) { + tls_vector_offset = known_tls_offsets [i]; + if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key) == canary) + goto ok; + } + + /*Fallback to scanning a large range of offsets*/ + for (i = TLS_PROBE_LOW_WATERMARK; i <= TLS_PROBE_HIGH_WATERMARK; i += 4) { + tls_vector_offset = i; + if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key) == canary) { + g_warning ("Found new TLS offset at %d", i); + goto ok; + } + } + + g_error ("could not discover the mach TLS offset"); +ok: + pthread_setspecific (key, old_value); +} + #endif