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);
/* 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;
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;
}
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,
guint32 unwind_info_len;
guint8 *unwind_info;
+ mgreg_t **reg_locations;
} MonoStackFrameInfo;
/*Index into MonoThreadState::unwind_data. */