endif
if ARM64
-arch_sources += mach-support-arm.c
+arch_sources += mach-support-arm64.c
endif
else
#include "utils/mono-sigcontext.h"
#include "mach-support.h"
+//For reg numbers
+#include <mono/arch/amd64/amd64-codegen.h>
+
/* Known offsets used for TLS storage*/
/* All OSX versions up to 10.8 */
*arch_state = ctx->__ss;
}
+void
+mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+{
+ x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state;
+ context->gregs [AMD64_RAX] = arch_state->__rax;
+ context->gregs [AMD64_RBX] = arch_state->__rbx;
+ context->gregs [AMD64_RCX] = arch_state->__rcx;
+ context->gregs [AMD64_RDX] = arch_state->__rdx;
+ context->gregs [AMD64_RDI] = arch_state->__rdi;
+ context->gregs [AMD64_RBP] = arch_state->__rbp;
+ context->gregs [AMD64_RSP] = arch_state->__rsp;
+ context->gregs [AMD64_R8] = arch_state->__r8;
+ context->gregs [AMD64_R9] = arch_state->__r9;
+ context->gregs [AMD64_R10] = arch_state->__r10;
+ context->gregs [AMD64_R11] = arch_state->__r11;
+ context->gregs [AMD64_R12] = arch_state->__r12;
+ context->gregs [AMD64_R13] = arch_state->__r13;
+ context->gregs [AMD64_R14] = arch_state->__r14;
+ context->gregs [AMD64_R15] = arch_state->__r15;
+ context->gregs [AMD64_RIP] = arch_state->__rip;
+}
+
int
mono_mach_arch_get_thread_state_size ()
{
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, 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 (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
+}
+
+void
+mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+{
+ int i;
+ arm_thread_state_t *arch_state = (x86_thread_state64_t *) state;
+ for (i = 0; i < 13; ++i)
+ context->regs [i] = arch_state->__r [i];
+ context->regs [ARMREG_R13] = arch_state->__sp;
+ context->regs [ARMREG_R14] = arch_state->__lr;
+ context->regs [ARMREG_R15] = arch_state->__pc;
+ context->pc = arch_state->__pc;
+ context->cpsr = arch_state->__cpsr;
}
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
#if defined(HOST_WATCHOS)
g_error ("thread_get_state() is not supported by this platform");
#else
-#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, (thread_state_t) arch_state, count);
-#endif
return ret;
#endif
}
{
#if defined(HOST_WATCHOS)
g_error ("thread_set_state() is not supported by this platform");
-#else
-#ifdef TARGET_ARM64
- return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE, state, count);
#else
return thread_set_state (thread, ARM_THREAD_STATE, state, count);
#endif
-#endif
}
void *
--- /dev/null
+/*
+ * mach-support-arm.c: mach support for ARM
+ *
+ * Authors:
+ * Geoff Norton (gnorton@novell.com)
+ * Rodrigo Kumpera (kumpera@gmail.com)
+ *
+ * (C) 2010 Novell, Inc.
+ * (C) 2011 Xamarin, Inc.
+ */
+
+#include <config.h>
+
+#if defined(__MACH__)
+#include <stdint.h>
+#include <glib.h>
+#include <pthread.h>
+#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 */
+ arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+
+ return (void *) arch_state->ts_64.__pc;
+}
+
+void *
+mono_mach_arch_get_sp (thread_state_t state)
+{
+ arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+
+ return (void *) arch_state->ts_64.__sp;
+}
+
+int
+mono_mach_arch_get_mcontext_size ()
+{
+ return sizeof (struct __darwin_mcontext64);
+}
+
+void
+mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+{
+ 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;
+}
+
+void
+mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+{
+ 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;
+}
+
+void
+mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+{
+ int i;
+ arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+ for (i = 0; i < 29; ++i)
+ context->regs [i] = arch_state->uts.ts_64.__x [i];
+
+ context->regs [ARMREG_R29] = arch_state->uts.ts_64.__fp;
+ context->regs [ARMREG_R30] = arch_state->uts.ts_64.__lr;
+ context->regs [ARMREG_R31] = arch_state->uts.ts_64.__sp;
+ context->pc = arch_state->uts.ts_64.__pc;
+}
+
+int
+mono_mach_arch_get_thread_state_size ()
+{
+ return sizeof (arm_unified_thread_state_t);
+}
+
+kern_return_t
+mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+{
+ 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);
+ 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)
+{
+ return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE, state, count);
+}
+
+void *
+mono_mach_get_tls_address_from_thread (pthread_t thread, pthread_key_t key)
+{
+ /* 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 + tls_vector_offset);
+ g_assert (tls_vector_offset != -1);
+
+ 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;
+ }
+ }
+
+ tls_vector_offset = -1;
+ g_warning ("could not discover the mach TLS offset");
+ok:
+ pthread_setspecific (key, old_value);
+}
+
+#endif
g_assert_not_reached ();
}
+void
+mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+{
+ g_assert_not_reached ();
+}
int
mono_mach_arch_get_thread_state_size ()
*arch_state = ctx->__ss;
}
+void
+mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+{
+ x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state;
+ context->eax = arch_state->__eax;
+ context->ebx = arch_state->__ebx;
+ context->ecx = arch_state->__ecx;
+ context->edx = arch_state->__edx;
+ context->ebp = arch_state->__ebp;
+ context->esp = arch_state->__esp;
+ context->esi = arch_state->__edi;
+ context->edi = arch_state->__esi;
+ context->eip = arch_state->__eip;
+}
+
+
int
mono_mach_arch_get_thread_state_size ()
{
#include <glib.h>
#include <pthread.h>
#include "mono/utils/mono-compiler.h"
+#include "mono/utils/mono-context.h"
#include <mach/task.h>
#include <mach/mach_port.h>
#include <mach/mach_init.h>
int mono_mach_arch_get_mcontext_size (void);
void mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context);
void mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state);
+void mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context);
int mono_mach_arch_get_thread_state_size (void);
kern_return_t mono_mach_get_threads (thread_act_array_t *threads, guint32 *count);
#if defined (HOST_APPLETVOS)
#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
- fprintf (stderr, "MONO_CONTEXT_GET_CURRENT: Not implemented"); \
- g_error ("MONO_CONTEXT_GET_CURRENT: Not implemented"); \
+ arm_unified_thread_state_t thread_state; \
+ int state_flavor = ARM_UNIFIED_THREAD_STATE; \
+ unsigned state_count = ARM_UNIFIED_THREAD_STATE_COUNT; \
+ thread_port_t self = mach_thread_self (); \
+ kern_return_t ret = thread_get_state (self, state_flavor, (thread_state_t) &thread_state, &state_count); \
+ g_assert (ret == 0); \
+ mono_mach_arch_thread_state_to_mono_context (&thread_state, &ctx); \
+ mach_port_deallocate (current_task (), self); \
} while (0);
#else