[mono-config] use right type for result of strlen
[mono.git] / mono / mini / mini-posix.c
1 /*
2  * mini-posix.c: POSIX signal handling support for Mono.
3  *
4  * Authors:
5  *   Mono Team (mono-list@lists.ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc.
8  * Copyright 2003-2008 Ximian, Inc.
9  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10  *
11  * See LICENSE for licensing information.
12  */
13 #include <config.h>
14 #include <signal.h>
15 #ifdef HAVE_ALLOCA_H
16 #include <alloca.h>
17 #endif
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #include <math.h>
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25 #ifdef HAVE_SYS_SYSCALL_H
26 #include <sys/syscall.h>
27 #endif
28 #include <errno.h>
29
30
31 #include <mono/metadata/assembly.h>
32 #include <mono/metadata/loader.h>
33 #include <mono/metadata/tabledefs.h>
34 #include <mono/metadata/class.h>
35 #include <mono/metadata/object.h>
36 #include <mono/metadata/tokentype.h>
37 #include <mono/metadata/tabledefs.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/appdomain.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/io-layer/io-layer.h>
42 #include "mono/metadata/profiler.h"
43 #include <mono/metadata/profiler-private.h>
44 #include <mono/metadata/mono-config.h>
45 #include <mono/metadata/environment.h>
46 #include <mono/metadata/mono-debug.h>
47 #include <mono/metadata/gc-internal.h>
48 #include <mono/metadata/threads-types.h>
49 #include <mono/metadata/verify.h>
50 #include <mono/metadata/verify-internals.h>
51 #include <mono/metadata/mempool-internals.h>
52 #include <mono/metadata/attach.h>
53 #include <mono/utils/mono-math.h>
54 #include <mono/utils/mono-compiler.h>
55 #include <mono/utils/mono-counters.h>
56 #include <mono/utils/mono-logger-internal.h>
57 #include <mono/utils/mono-mmap.h>
58 #include <mono/utils/dtrace.h>
59 #include <mono/utils/mono-signal-handler.h>
60 #include <mono/utils/mono-threads.h>
61
62 #include "mini.h"
63 #include <string.h>
64 #include <ctype.h>
65 #include "trace.h"
66 #include "version.h"
67 #include "debugger-agent.h"
68
69 #include "jit-icalls.h"
70
71 #if defined(__native_client__) || defined(HOST_WATCHOS)
72
73 void
74 mono_runtime_setup_stat_profiler (void)
75 {
76         printf("WARNING: mono_runtime_setup_stat_profiler() called!\n");
77 }
78
79
80 void
81 mono_runtime_shutdown_stat_profiler (void)
82 {
83 }
84
85
86 gboolean
87 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
88 {
89         return FALSE;
90 }
91
92 #ifndef PLATFORM_MACOSX
93 void
94 mono_runtime_install_handlers (void)
95 {
96 }
97 #endif
98
99 void
100 mono_runtime_shutdown_handlers (void)
101 {
102 }
103
104 void
105 mono_runtime_cleanup_handlers (void)
106 {
107 }
108
109 #if !defined(PLATFORM_MACOSX)
110 pid_t
111 mono_runtime_syscall_fork (void)
112 {
113         g_assert_not_reached();
114         return 0;
115 }
116
117 void
118 mono_gdb_render_native_backtraces (pid_t crashed_pid)
119 {
120 }
121 #endif
122
123 #else
124
125 static GHashTable *mono_saved_signal_handlers = NULL;
126
127 static gpointer
128 get_saved_signal_handler (int signo)
129 {
130         if (mono_saved_signal_handlers)
131                 /* The hash is only modified during startup, so no need for locking */
132                 return g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo));
133         return NULL;
134 }
135
136 static void
137 save_old_signal_handler (int signo, struct sigaction *old_action)
138 {
139         struct sigaction *handler_to_save = g_malloc (sizeof (struct sigaction));
140
141         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_CONFIG,
142                                 "Saving old signal handler for signal %d.", signo);
143
144         if (! (old_action->sa_flags & SA_SIGINFO)) {
145                 handler_to_save->sa_handler = old_action->sa_handler;
146         } else {
147 #ifdef MONO_ARCH_USE_SIGACTION
148                 handler_to_save->sa_sigaction = old_action->sa_sigaction;
149 #endif /* MONO_ARCH_USE_SIGACTION */
150         }
151         handler_to_save->sa_mask = old_action->sa_mask;
152         handler_to_save->sa_flags = old_action->sa_flags;
153         
154         if (!mono_saved_signal_handlers)
155                 mono_saved_signal_handlers = g_hash_table_new (NULL, NULL);
156         g_hash_table_insert (mono_saved_signal_handlers, GINT_TO_POINTER (signo), handler_to_save);
157 }
158
159 static void
160 free_saved_sig_handler_func (gpointer key, gpointer value, gpointer user_data)
161 {
162         g_free (value);
163 }
164
165 static void
166 free_saved_signal_handlers (void)
167 {
168         if (mono_saved_signal_handlers) {
169                 g_hash_table_foreach (mono_saved_signal_handlers, free_saved_sig_handler_func, NULL);
170                 g_hash_table_destroy (mono_saved_signal_handlers);
171                 mono_saved_signal_handlers = NULL;
172         }
173 }
174
175 /*
176  * mono_chain_signal:
177  *
178  *   Call the original signal handler for the signal given by the arguments, which
179  * should be the same as for a signal handler. Returns TRUE if the original handler
180  * was called, false otherwise.
181  */
182 gboolean
183 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
184 {
185         int signal = MONO_SIG_HANDLER_GET_SIGNO ();
186         struct sigaction *saved_handler = get_saved_signal_handler (signal);
187
188         if (saved_handler && saved_handler->sa_handler) {
189                 if (!(saved_handler->sa_flags & SA_SIGINFO)) {
190                         saved_handler->sa_handler (signal);
191                 } else {
192 #ifdef MONO_ARCH_USE_SIGACTION
193                         saved_handler->sa_sigaction (MONO_SIG_HANDLER_PARAMS);
194 #endif /* MONO_ARCH_USE_SIGACTION */
195                 }
196                 return TRUE;
197         }
198         return FALSE;
199 }
200
201 MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
202 {
203         MonoJitInfo *ji = NULL;
204         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
205         MONO_SIG_HANDLER_GET_CONTEXT;
206
207         if (mono_thread_internal_current ())
208                 ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
209         if (!ji) {
210         if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
211                         return;
212                 mono_handle_native_sigsegv (SIGABRT, ctx, info);
213         }
214 }
215
216 #if defined(__i386__) || defined(__x86_64__)
217 #define FULL_STAT_PROFILER_BACKTRACE 1
218 #define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
219 #define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
220 #if MONO_ARCH_STACK_GROWS_UP
221 #define IS_BEFORE_ON_STACK <
222 #define IS_AFTER_ON_STACK >
223 #else
224 #define IS_BEFORE_ON_STACK >
225 #define IS_AFTER_ON_STACK <
226 #endif
227 #else
228 #define FULL_STAT_PROFILER_BACKTRACE 0
229 #endif
230
231 #ifdef SIGPROF
232
233 static int profiling_signal_in_use;
234
235 #if defined(__ia64__) || defined(__sparc__) || defined(sparc)
236
237 MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
238 {
239         if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
240                 return;
241
242         NOT_IMPLEMENTED;
243 }
244
245 #else
246
247 static void
248 per_thread_profiler_hit (void *ctx)
249 {
250         int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
251         MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
252
253         if (call_chain_depth == 0) {
254                 mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
255         } else {
256                 MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
257                 int current_frame_index = 1;
258                 MonoContext mono_context;
259                 guchar *ips [call_chain_depth + 1];
260
261                 mono_sigctx_to_monoctx (ctx, &mono_context);
262                 ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
263                 
264                 if (jit_tls != NULL) {
265                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
266 #if FULL_STAT_PROFILER_BACKTRACE
267                         guchar *current_frame;
268                         guchar *stack_bottom;
269                         guchar *stack_top;
270                         
271                         stack_bottom = jit_tls->end_of_stack;
272                         stack_top = MONO_CONTEXT_GET_SP (&mono_context);
273                         current_frame = MONO_CONTEXT_GET_BP (&mono_context);
274                         
275                         while ((current_frame_index <= call_chain_depth) &&
276                                         (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
277                                         ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
278                                 ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
279                                 current_frame_index ++;
280                                 stack_top = current_frame;
281                                 current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
282                         }
283 #else
284                                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
285 #endif
286                         }
287                         
288                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
289 #if GLIBC_PROFILER_BACKTRACE
290                                 current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
291 #else
292                                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
293 #endif
294                         }
295
296                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
297                                 MonoDomain *domain = mono_domain_get ();
298                                 if (domain != NULL) {
299                                         MonoLMF *lmf = NULL;
300                                         MonoJitInfo *ji;
301                                         MonoJitInfo res;
302                                         MonoContext new_mono_context;
303                                         int native_offset;
304                                         ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
305                                                         &new_mono_context, NULL, &lmf, &native_offset, NULL);
306                                         while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
307                                                 ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
308                                                 current_frame_index ++;
309                                                 mono_context = new_mono_context;
310                                                 ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
311                                                                 &new_mono_context, NULL, &lmf, &native_offset, NULL);
312                                         }
313                                 }
314                         }
315                 }
316                 
317                 mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
318         }
319 }
320
321 MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
322 {
323         MonoThreadInfo *info;
324         int old_errno = errno;
325         int hp_save_index;
326         MONO_SIG_HANDLER_GET_CONTEXT;
327
328         if (mono_thread_info_get_small_id () == -1)
329                 return; //an non-attached thread got the signal
330
331         if (!mono_domain_get () || !mono_native_tls_get_value (mono_jit_tls_id))
332                 return; //thread in the process of dettaching
333
334         hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
335
336         /* If we can't consume a profiling request it means we're the initiator. */
337         if (!(mono_threads_consume_async_jobs () & MONO_SERVICE_REQUEST_SAMPLE)) {
338                 FOREACH_THREAD_SAFE (info) {
339                         if (mono_thread_info_get_tid (info) == mono_native_thread_id_get ())
340                                 continue;
341
342                         mono_threads_add_async_job (info, MONO_SERVICE_REQUEST_SAMPLE);
343                         mono_threads_pthread_kill (info, profiling_signal_in_use);
344                 } END_FOREACH_THREAD_SAFE;
345         }
346
347         mono_thread_info_set_is_async_context (TRUE);
348         per_thread_profiler_hit (ctx);
349         mono_thread_info_set_is_async_context (FALSE);
350
351         mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
352         errno = old_errno;
353
354         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
355 }
356
357 #endif
358 #endif
359
360 MONO_SIG_HANDLER_FUNC (static, sigquit_signal_handler)
361 {
362         gboolean res;
363
364         /* We use this signal to start the attach agent too */
365         res = mono_attach_start ();
366         if (res)
367                 return;
368
369         mono_threads_request_thread_dump ();
370
371         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
372 }
373
374 MONO_SIG_HANDLER_FUNC (static, sigusr2_signal_handler)
375 {
376         gboolean enabled = mono_trace_is_enabled ();
377
378         mono_trace_enable (!enabled);
379
380         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
381 }
382
383 static void
384 add_signal_handler (int signo, gpointer handler)
385 {
386         struct sigaction sa;
387         struct sigaction previous_sa;
388
389 #ifdef MONO_ARCH_USE_SIGACTION
390         sa.sa_sigaction = handler;
391         sigemptyset (&sa.sa_mask);
392         sa.sa_flags = SA_SIGINFO;
393 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
394
395 /*Apple likes to deliver SIGBUS for *0 */
396 #ifdef PLATFORM_MACOSX
397         if (signo == SIGSEGV || signo == SIGBUS) {
398 #else
399         if (signo == SIGSEGV) {
400 #endif
401                 sa.sa_flags |= SA_ONSTACK;
402
403                 /* 
404                  * libgc will crash when trying to do stack marking for threads which are on
405                  * an altstack, so delay the suspend signal after the signal handler has
406                  * executed.
407                  */
408                 if (mono_gc_get_suspend_signal () != -1)
409                         sigaddset (&sa.sa_mask, mono_gc_get_suspend_signal ());
410         }
411 #endif
412         if (signo == SIGSEGV) {
413                 /* 
414                  * Delay abort signals while handling SIGSEGVs since they could go unnoticed.
415                  */
416                 sigset_t block_mask;
417      
418                 sigemptyset (&block_mask);
419         }
420 #else
421         sa.sa_handler = handler;
422         sigemptyset (&sa.sa_mask);
423         sa.sa_flags = 0;
424 #endif
425         g_assert (sigaction (signo, &sa, &previous_sa) != -1);
426
427         /* if there was already a handler in place for this signal, store it */
428         if (! (previous_sa.sa_flags & SA_SIGINFO) &&
429                         (SIG_DFL == previous_sa.sa_handler)) { 
430                 /* it there is no sa_sigaction function and the sa_handler is default, we can safely ignore this */
431         } else {
432                 if (mono_do_signal_chaining)
433                         save_old_signal_handler (signo, &previous_sa);
434         }
435 }
436
437 static void
438 remove_signal_handler (int signo)
439 {
440         struct sigaction sa;
441         struct sigaction *saved_action = get_saved_signal_handler (signo);
442
443         if (!saved_action) {
444                 sa.sa_handler = SIG_DFL;
445                 sigemptyset (&sa.sa_mask);
446                 sa.sa_flags = 0;
447
448                 sigaction (signo, &sa, NULL);
449         } else {
450                 g_assert (sigaction (signo, saved_action, NULL) != -1);
451         }
452 }
453
454 void
455 mono_runtime_posix_install_handlers (void)
456 {
457
458         sigset_t signal_set;
459
460         if (mini_get_debug_options ()->handle_sigint)
461                 add_signal_handler (SIGINT, mono_sigint_signal_handler);
462
463         add_signal_handler (SIGFPE, mono_sigfpe_signal_handler);
464         add_signal_handler (SIGQUIT, sigquit_signal_handler);
465         add_signal_handler (SIGILL, mono_sigill_signal_handler);
466         add_signal_handler (SIGBUS, mono_sigsegv_signal_handler);
467         if (mono_jit_trace_calls != NULL)
468                 add_signal_handler (SIGUSR2, sigusr2_signal_handler);
469
470         /* it seems to have become a common bug for some programs that run as parents
471          * of many processes to block signal delivery for real time signals.
472          * We try to detect and work around their breakage here.
473          */
474         sigemptyset (&signal_set);
475         if (mono_gc_get_suspend_signal () != -1)
476                 sigaddset (&signal_set, mono_gc_get_suspend_signal ());
477         if (mono_gc_get_restart_signal () != -1)
478                 sigaddset (&signal_set, mono_gc_get_restart_signal ());
479         sigaddset (&signal_set, SIGCHLD);
480         sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
481
482         signal (SIGPIPE, SIG_IGN);
483
484         add_signal_handler (SIGABRT, sigabrt_signal_handler);
485
486         /* catch SIGSEGV */
487         add_signal_handler (SIGSEGV, mono_sigsegv_signal_handler);
488 }
489
490 #ifndef PLATFORM_MACOSX
491 void
492 mono_runtime_install_handlers (void)
493 {
494         mono_runtime_posix_install_handlers ();
495 }
496 #endif
497
498 void
499 mono_runtime_cleanup_handlers (void)
500 {
501         if (mini_get_debug_options ()->handle_sigint)
502                 remove_signal_handler (SIGINT);
503
504         remove_signal_handler (SIGFPE);
505         remove_signal_handler (SIGQUIT);
506         remove_signal_handler (SIGILL);
507         remove_signal_handler (SIGBUS);
508         if (mono_jit_trace_calls != NULL)
509                 remove_signal_handler (SIGUSR2);
510
511         remove_signal_handler (SIGABRT);
512
513         remove_signal_handler (SIGSEGV);
514
515         free_saved_signal_handlers ();
516 }
517
518 #ifdef HAVE_LINUX_RTC_H
519 #include <linux/rtc.h>
520 #include <sys/ioctl.h>
521 #include <fcntl.h>
522 static int rtc_fd = -1;
523
524 static int
525 enable_rtc_timer (gboolean enable)
526 {
527         int flags;
528         flags = fcntl (rtc_fd, F_GETFL);
529         if (flags < 0) {
530                 perror ("getflags");
531                 return 0;
532         }
533         if (enable)
534                 flags |= FASYNC;
535         else
536                 flags &= ~FASYNC;
537         if (fcntl (rtc_fd, F_SETFL, flags) == -1) {
538                 perror ("setflags");
539                 return 0;
540         }
541         return 1;
542 }
543 #endif
544
545 void
546 mono_runtime_shutdown_stat_profiler (void)
547 {
548 #ifdef HAVE_LINUX_RTC_H
549         if (rtc_fd >= 0)
550                 enable_rtc_timer (FALSE);
551 #endif
552 }
553
554 #ifdef ITIMER_PROF
555 static int
556 get_itimer_mode (void)
557 {
558         switch (mono_profiler_get_sampling_mode ()) {
559         case MONO_PROFILER_STAT_MODE_PROCESS: return ITIMER_PROF;
560         case MONO_PROFILER_STAT_MODE_REAL: return ITIMER_REAL;
561         }
562         g_assert_not_reached ();
563         return 0;
564 }
565
566 static int
567 get_itimer_signal (void)
568 {
569         switch (mono_profiler_get_sampling_mode ()) {
570         case MONO_PROFILER_STAT_MODE_PROCESS: return SIGPROF;
571         case MONO_PROFILER_STAT_MODE_REAL: return SIGALRM;
572         }
573         g_assert_not_reached ();
574         return 0;
575 }
576 #endif
577
578 void
579 mono_runtime_setup_stat_profiler (void)
580 {
581 #ifdef ITIMER_PROF
582         struct itimerval itval;
583         static int inited = 0;
584 #ifdef HAVE_LINUX_RTC_H
585         const char *rtc_freq;
586         if (!inited && (rtc_freq = g_getenv ("MONO_RTC"))) {
587                 int freq = 0;
588                 inited = 1;
589                 if (*rtc_freq)
590                         freq = atoi (rtc_freq);
591                 if (!freq)
592                         freq = 1024;
593                 rtc_fd = open ("/dev/rtc", O_RDONLY);
594                 if (rtc_fd == -1) {
595                         perror ("open /dev/rtc");
596                         return;
597                 }
598                 profiling_signal_in_use = SIGPROF;
599                 add_signal_handler (profiling_signal_in_use, sigprof_signal_handler);
600                 if (ioctl (rtc_fd, RTC_IRQP_SET, freq) == -1) {
601                         perror ("set rtc freq");
602                         return;
603                 }
604                 if (ioctl (rtc_fd, RTC_PIE_ON, 0) == -1) {
605                         perror ("start rtc");
606                         return;
607                 }
608                 if (fcntl (rtc_fd, F_SETSIG, SIGPROF) == -1) {
609                         perror ("setsig");
610                         return;
611                 }
612                 if (fcntl (rtc_fd, F_SETOWN, getpid ()) == -1) {
613                         perror ("setown");
614                         return;
615                 }
616                 enable_rtc_timer (TRUE);
617                 return;
618         }
619         if (rtc_fd >= 0)
620                 return;
621 #endif
622
623         itval.it_interval.tv_usec = (1000000 / mono_profiler_get_sampling_rate ()) - 1;
624         itval.it_interval.tv_sec = 0;
625         itval.it_value = itval.it_interval;
626         if (inited)
627                 return;
628         inited = 1;
629         profiling_signal_in_use = get_itimer_signal ();
630         add_signal_handler (profiling_signal_in_use, sigprof_signal_handler);
631         setitimer (get_itimer_mode (), &itval, NULL);
632 #endif
633 }
634
635 #if !defined(PLATFORM_MACOSX)
636 pid_t
637 mono_runtime_syscall_fork ()
638 {
639 #if defined(PLATFORM_ANDROID)
640         /* SYS_fork is defined to be __NR_fork which is not defined in some ndk versions */
641         g_assert_not_reached ();
642         return 0;
643 #elif defined(SYS_fork)
644         return (pid_t) syscall (SYS_fork);
645 #else
646         g_assert_not_reached ();
647         return 0;
648 #endif
649 }
650
651 void
652 mono_gdb_render_native_backtraces (pid_t crashed_pid)
653 {
654         const char *argv [9];
655         char template [] = "/tmp/mono-lldb-commands.XXXXXX";
656         char buf1 [128];
657         FILE *commands;
658         gboolean using_lldb = FALSE;
659
660         argv [0] = g_find_program_in_path ("gdb");
661         if (argv [0] == NULL) {
662                 argv [0] = g_find_program_in_path ("lldb");
663                 using_lldb = TRUE;
664         }
665
666         if (argv [0] == NULL)
667                 return;
668
669         if (using_lldb) {
670                 if (mkstemp (template) == -1)
671                         return;
672
673                 commands = fopen (template, "w");
674
675                 fprintf (commands, "process attach --pid %ld\n", (long) crashed_pid);
676                 fprintf (commands, "thread list\n");
677                 fprintf (commands, "thread backtrace all\n");
678                 fprintf (commands, "detach\n");
679                 fprintf (commands, "quit\n");
680
681                 fflush (commands);
682                 fclose (commands);
683
684                 argv [1] = "--source";
685                 argv [2] = template;
686                 argv [3] = 0;
687         } else {
688                 argv [1] = "-ex";
689                 sprintf (buf1, "attach %ld", (long) crashed_pid);
690                 argv [2] = buf1;
691                 argv [3] = "--ex";
692                 argv [4] = "info threads";
693                 argv [5] = "--ex";
694                 argv [6] = "thread apply all bt";
695                 argv [7] = "--batch";
696                 argv [8] = 0;
697         }
698
699         execv (argv [0], (char**)argv);
700
701         if (using_lldb)
702                 unlink (template);
703 }
704 #endif
705 #endif /* __native_client__ */
706
707 #if !defined (__MACH__)
708
709 gboolean
710 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
711 {
712         g_error ("Posix systems don't support mono_thread_state_init_from_handle");
713         return FALSE;
714 }
715
716 #endif