Print a normal stack trace on a hard stack overflow.
authorZoltan Varga <vargaz@gmail.com>
Thu, 3 Feb 2011 22:03:42 +0000 (23:03 +0100)
committerZoltan Varga <vargaz@gmail.com>
Thu, 3 Feb 2011 22:03:42 +0000 (23:03 +0100)
mono/mini/mini-exceptions.c
mono/mini/mini.c
mono/mini/mini.h

index 5576d41441835a1a14431232acb5600e1156c0a0..2f4bce7a5ccd2cc4bcde819b6b677ed1aab1f2dc 100644 (file)
@@ -2003,6 +2003,74 @@ mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx,
        return FALSE;
 }
 
+typedef struct {
+       FILE *stream;
+       MonoMethod *omethod;
+       int count;
+} PrintOverflowUserData;
+
+static gboolean
+print_overflow_stack_frame (MonoMethod *method, gint32 native_offset, gint32 il_offset, gboolean managed, gpointer data)
+{
+       PrintOverflowUserData *user_data = data;
+       FILE *stream = user_data->stream;
+       gchar *location;
+
+       if (method) {
+               if (user_data->count == 0) {
+                       /* The first frame is in its prolog, so a line number cannot be computed */
+                       user_data->count ++;
+                       return FALSE;
+               }
+
+               /* If this is a one method overflow, skip the other instances */
+               if (method == user_data->omethod)
+                       return FALSE;
+
+               location = mono_debug_print_stack_frame (method, native_offset, mono_domain_get ());
+               fprintf (stream, "  %s\n", location);
+               g_free (location);
+
+               if (user_data->count == 1) {
+                       fprintf (stream, "  <...>\n");
+                       user_data->omethod = method;
+               } else {
+                       user_data->omethod = NULL;
+               }
+
+               user_data->count ++;
+       } else
+               fprintf (stream, "  at <unknown> <0x%05x>\n", native_offset);
+
+       return FALSE;
+}
+
+void
+mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
+{
+       const char *method;
+       /* we don't do much now, but we can warn the user with a useful message */
+       fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), fault_addr);
+       if (ji && ji->method) {
+               PrintOverflowUserData ud;
+               MonoContext mctx;
+
+               mono_arch_sigctx_to_monoctx (ctx, &mctx);
+                       
+               method = mono_method_full_name (ji->method, TRUE);
+               fprintf (stderr, "Stacktrace:\n");
+
+               memset (&ud, 0, sizeof (ud));
+               ud.stream = stderr;
+
+               mono_jit_walk_stack_from_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
+       } else {
+               method = "Unmanaged";
+               fprintf (stderr, "  at %s\n", method);
+       }
+       _exit (1);
+}
+
 static gboolean
 print_stack_frame (MonoMethod *method, gint32 native_offset, gint32 il_offset, gboolean managed, gpointer data)
 {
index b2d6192cf05d7b80c8e94935e7eee8bb2a79e417..fa4151b8d3228d094b2cf946d714eecb6123b85b 100644 (file)
@@ -5824,20 +5824,14 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
        }
 #endif
 
-       /* The hard-guard page has been hit: there is not much we can do anymore
-        * Print a hopefully clear message and abort.
-        */
        if (jit_tls->stack_size && 
                ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
-               const char *method;
-               /* we don't do much now, but we can warn the user with a useful message */
-               fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), (gpointer)info->si_addr);
-               if (ji && ji->method)
-                       method = mono_method_full_name (ji->method, TRUE);
-               else
-                       method = "Unmanaged";
-               fprintf (stderr, "At %s\n", method);
-               _exit (1);
+               /*
+                * The hard-guard page has been hit: there is not much we can do anymore
+                * Print a hopefully clear message and abort.
+                */
+               mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
+               g_assert_not_reached ();
        } else {
                /* The original handler might not like that it is executed on an altstack... */
                if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
index 8bbac35a743cf2cc35338cb195da636068801a93..64d055ac30f8919ef21f39fee09287b781f1cf86 100644 (file)
@@ -2048,6 +2048,7 @@ gpointer  mono_arch_get_throw_pending_exception (MonoTrampInfo **info, gboolean
 gboolean mono_arch_handle_exception             (void *sigctx, gpointer obj, gboolean test_only) MONO_INTERNAL;
 void     mono_arch_handle_altstack_exception    (void *sigctx, gpointer fault_addr, gboolean stack_ovf) MONO_INTERNAL;
 gboolean mono_handle_soft_stack_ovf             (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
+void     mono_handle_hard_stack_ovf             (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
 gpointer mono_arch_ip_from_context              (void *sigctx) MONO_INTERNAL;
 void     mono_arch_sigctx_to_monoctx            (void *sigctx, MonoContext *ctx) MONO_INTERNAL;
 void     mono_arch_monoctx_to_sigctx            (MonoContext *mctx, void *ctx) MONO_INTERNAL;