+void
+mono_jit_walk_stack_from_ctx_in_thread (MonoJitStackWalk func, MonoDomain *domain, MonoContext *start_ctx, gboolean do_il_offset, MonoInternalThread *thread, MonoLMF *lmf, gpointer user_data)
+{
+ MonoJitTlsData *jit_tls = thread->jit_data;
+ gint il_offset;
+ MonoContext ctx, new_ctx;
+ StackFrameInfo frame;
+#ifndef MONO_ARCH_HAVE_FIND_JIT_INFO_EXT
+ gint native_offset;
+ gboolean managed;
+ MonoJitInfo *ji, rji;
+#else
+ gboolean res;
+#endif
+
+ MONO_ARCH_CONTEXT_DEF
+
+ mono_arch_flush_register_windows ();
+
+ if (start_ctx) {
+ memcpy (&ctx, start_ctx, sizeof (MonoContext));
+ } else {
+#ifdef MONO_INIT_CONTEXT_FROM_CURRENT
+ MONO_INIT_CONTEXT_FROM_CURRENT (&ctx);
+#else
+ MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_jit_walk_stack_from_ctx);
+#endif
+ g_assert (thread == mono_thread_internal_current ());
+ }
+
+ while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
+ frame.lmf = lmf;
+#ifdef MONO_ARCH_HAVE_FIND_JIT_INFO_EXT
+ res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, &frame);
+ if (!res)
+ return;
+#else
+ ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed);
+ g_assert (ji);
+ frame.type = FRAME_TYPE_MANAGED;
+ frame.ji = ji;
+ frame.managed = managed;
+ frame.native_offset = native_offset;
+
+ if (ji == (gpointer)-1)
+ return;
+#endif
+
+ if (do_il_offset && frame.ji) {
+ MonoDebugSourceLocation *source;
+
+ source = mono_debug_lookup_source_location (frame.ji->method, frame.native_offset, domain);
+ il_offset = source ? source->il_offset : -1;
+ mono_debug_free_source_location (source);
+ } else
+ il_offset = -1;
+
+ frame.il_offset = il_offset;
+
+ if (func (&frame, &ctx, user_data))
+ return;
+
+ ctx = new_ctx;
+ }
+}
+
+