+
+ /* Snow Leopard has a horrible bug: http://openradar.appspot.com/7209349
+ * This causes obscure SIGTRAP's for any application that comes across this built on
+ * Snow Leopard. This is a horrible hack to ensure that the private __CFInitialize
+ * is run on the main thread, so that we don't get SIGTRAPs later
+ */
+#if defined (__APPLE__) && (defined (__i386__) || defined (__x86_64__))
+ {
+ void *handle = dlopen ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY);
+ if (handle == NULL)
+ return;
+
+ dlclose (handle);
+ }
+#endif
+}
+
+pid_t
+mono_runtime_syscall_fork ()
+{
+ return (pid_t) fork ();
+}
+
+void
+mono_gdb_render_native_backtraces (pid_t crashed_pid)
+{
+ const char *argv [5];
+ char gdb_template [] = "/tmp/mono-gdb-commands.XXXXXX";
+
+ argv [0] = g_find_program_in_path ("gdb");
+ if (argv [0] == NULL) {
+ return;
+ }
+
+ if (mkstemp (gdb_template) != -1) {
+ FILE *gdb_commands = fopen (gdb_template, "w");
+
+ fprintf (gdb_commands, "attach %ld\n", (long) crashed_pid);
+ fprintf (gdb_commands, "info threads\n");
+ fprintf (gdb_commands, "thread apply all bt\n");
+
+ fflush (gdb_commands);
+ fclose (gdb_commands);
+
+ argv [1] = "-batch";
+ argv [2] = "-x";
+ argv [3] = gdb_template;
+ argv [4] = 0;
+
+ execv (argv [0], (char**)argv);
+
+ unlink (gdb_template);
+ }
+}
+
+gboolean
+mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle)
+{
+ kern_return_t ret;
+ mach_msg_type_number_t num_state;
+ thread_state_t state;
+ ucontext_t ctx;
+ mcontext_t mctx;
+ guint32 domain_key, jit_key;
+ MonoJitTlsData *jit_tls;
+ void *domain;
+#if defined (MONO_ARCH_ENABLE_MONO_LMF_VAR)
+ guint32 lmf_key;
+#endif
+
+ /*Zero enough state to make sure the caller doesn't confuse itself*/
+ tctx->valid = FALSE;
+ tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL;
+ tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL;
+ tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL;
+
+ state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ());
+ mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ());
+
+ ret = mono_mach_arch_get_thread_state (thread_handle, state, &num_state);
+ if (ret != KERN_SUCCESS)
+ return FALSE;
+
+ mono_mach_arch_thread_state_to_mcontext (state, mctx);
+ ctx.uc_mcontext = mctx;
+
+ mono_sigctx_to_monoctx (&ctx, &tctx->ctx);
+
+ domain_key = mono_domain_get_tls_key ();
+ jit_key = mono_get_jit_tls_key ();
+
+ jit_tls = mono_mach_arch_get_tls_value_from_thread (thread_id, jit_key);
+ domain = mono_mach_arch_get_tls_value_from_thread (thread_id, domain_key);
+
+ /*Thread already started to cleanup, can no longer capture unwind state*/
+ if (!jit_tls || !domain)
+ return FALSE;
+
+#if defined (MONO_ARCH_ENABLE_MONO_LMF_VAR)
+ lmf_key = mono_get_lmf_tls_offset ();
+ tctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_mach_arch_get_tls_value_from_thread (thread_id, lmf_key);;
+#else
+ tctx->unwind_data [MONO_UNWIND_DATA_LMF] = jit_tls ? jit_tls->lmf : NULL;
+#endif
+
+ tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain;
+ tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls;
+ tctx->valid = TRUE;
+
+ return TRUE;