Add an unwind option to enable collection of register save locations during stack...
authorZoltan Varga <vargaz@gmail.com>
Fri, 25 Mar 2011 18:34:40 +0000 (19:34 +0100)
committerZoltan Varga <vargaz@gmail.com>
Fri, 25 Mar 2011 18:55:58 +0000 (19:55 +0100)
mono/mini/mini-exceptions.c
mono/utils/mono-stack-unwinding.h

index 99490c30b46f581e50db5c25fd548dbd3fb2cf58..db91eb612ce10043b2663c4aeba7d5fc3a8317c7 100644 (file)
@@ -729,10 +729,13 @@ mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_da
 static void
 mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data)
 {
-       gint il_offset;
+       gint il_offset, i;
        MonoContext ctx, new_ctx;
        StackFrameInfo frame;
        gboolean res;
+       mgreg_t *reg_locations [MONO_MAX_IREGS];
+       mgreg_t *new_reg_locations [MONO_MAX_IREGS];
+       gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS;
 
        g_assert (start_ctx);
        g_assert (domain);
@@ -741,10 +744,11 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
        /* g_assert (lmf); */
 
        memcpy (&ctx, start_ctx, sizeof (MonoContext));
+       memset (reg_locations, 0, sizeof (reg_locations));
 
        while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
                frame.lmf = lmf;
-               res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame);
+               res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
                if (!res)
                        return;
 
@@ -765,8 +769,17 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
                        frame.actual_method = frame.method;
                }
 
+               if (get_reg_locations)
+                       frame.reg_locations = reg_locations;
+
                if (func (&frame, &ctx, user_data))
                        return;
+
+               if (get_reg_locations) {
+                       for (i = 0; i < MONO_MAX_IREGS; ++i)
+                               if (new_reg_locations [i])
+                                       reg_locations [i] = new_reg_locations [i];
+               }
                
                ctx = new_ctx;
        }
index b747f2d428f6892c006460ed8dccce2d3d6b1127..ffeb17408b5627ee1f5b193f2d3fe33ac6030b75 100644 (file)
@@ -22,6 +22,12 @@ typedef enum {
        MONO_UNWIND_NONE = 0x0,
        MONO_UNWIND_LOOKUP_IL_OFFSET = 0x1,
        MONO_UNWIND_LOOKUP_ACTUAL_METHOD = 0x2,
+       /*
+        * Store the locations where caller-saved registers are saved on the stack in
+        * frame->reg_locations. The pointer is only valid during the call to the unwind
+        * callback.
+        */
+       MONO_UNWIND_REG_LOCATIONS = 0x4,
        MONO_UNWIND_DEFAULT = MONO_UNWIND_LOOKUP_ACTUAL_METHOD,
        MONO_UNWIND_SIGNAL_SAFE = MONO_UNWIND_NONE,
        MONO_UNWIND_LOOKUP_ALL = MONO_UNWIND_LOOKUP_IL_OFFSET | MONO_UNWIND_LOOKUP_ACTUAL_METHOD,
@@ -58,6 +64,7 @@ typedef struct {
        guint32 unwind_info_len;
        guint8 *unwind_info;
 
+       mgreg_t **reg_locations;
 } MonoStackFrameInfo;
 
 /*Index into MonoThreadState::unwind_data. */