+#ifdef MONO_ARCH_HAVE_FIND_JIT_INFO_EXT
+
+/*
+ * mono_find_jit_info_ext:
+ *
+ * A version of mono_find_jit_info which returns all data in the StackFrameInfo
+ * structure.
+ */
+gboolean
+mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
+ MonoJitInfo *prev_ji, MonoContext *ctx,
+ MonoContext *new_ctx, char **trace, MonoLMF **lmf,
+ StackFrameInfo *frame)
+{
+ gboolean err;
+ gpointer ip = MONO_CONTEXT_GET_IP (ctx);
+ MonoJitInfo *ji;
+ MonoDomain *target_domain;
+
+ if (trace)
+ *trace = NULL;
+
+ /* Avoid costly table lookup during stack overflow */
+ if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
+ ji = prev_ji;
+ else
+ ji = mini_jit_info_table_find (domain, ip, &target_domain);
+
+ if (!target_domain)
+ target_domain = domain;
+
+ err = mono_arch_find_jit_info_ext (target_domain, jit_tls, ji, ctx, new_ctx, lmf, frame);
+ if (!err)
+ return FALSE;
+
+ frame->native_offset = -1;
+ frame->domain = target_domain;
+
+ ji = frame->ji;
+
+ if (ji && (frame->managed || ji->method->wrapper_type)) {
+ const char *real_ip, *start;
+
+ start = (const char *)ji->code_start;
+ if (!frame->managed)
+ /* ctx->ip points into native code */
+ real_ip = (const char*)MONO_CONTEXT_GET_IP (new_ctx);
+ else
+ real_ip = (const char*)ip;
+
+ if ((real_ip >= start) && (real_ip <= start + ji->code_size))
+ frame->native_offset = real_ip - start;
+ else
+ frame->native_offset = -1;
+
+ if (trace)
+ *trace = mono_debug_print_stack_frame (ji->method, frame->native_offset, domain);
+ } else {
+ if (trace && frame->method) {
+ char *fname = mono_method_full_name (frame->method, TRUE);
+ *trace = g_strdup_printf ("in (unmanaged) %s", fname);
+ g_free (fname);
+ }
+ }
+
+ return TRUE;
+}
+
+#endif /* MONO_ARCH_HAVE_FIND_JIT_INFO_EXT */
+
+static gpointer
+get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
+{
+ MonoGenericJitInfo *gi;
+ gpointer info;
+
+ if (!ji->has_generic_jit_info)
+ return NULL;
+ gi = mono_jit_info_get_generic_jit_info (ji);
+ if (!gi->has_this)
+ return NULL;
+
+ if (gi->this_in_reg)
+ info = mono_arch_context_get_int_reg (ctx, gi->this_reg);
+ else
+ info = *(gpointer*)(gpointer)((char*)mono_arch_context_get_int_reg (ctx, gi->this_reg) +
+ gi->this_offset);
+ if (mono_method_get_context (ji->method)->method_inst) {
+ return info;
+ } else if ((ji->method->flags & METHOD_ATTRIBUTE_STATIC) || ji->method->klass->valuetype) {
+ return info;
+ } else {
+ /* Avoid returning a managed object */
+ MonoObject *this_obj = info;
+
+ return this_obj->vtable->klass;
+ }
+}
+
+static MonoGenericContext
+get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
+{
+ MonoGenericContext context = { NULL, NULL };
+ MonoClass *class, *method_container_class;
+
+ g_assert (generic_info);
+
+ g_assert (ji->method->is_inflated);
+ if (mono_method_get_context (ji->method)->method_inst) {
+ MonoMethodRuntimeGenericContext *mrgctx = generic_info;
+
+ class = mrgctx->class_vtable->klass;
+ context.method_inst = mrgctx->method_inst;
+ g_assert (context.method_inst);
+ } else if ((ji->method->flags & METHOD_ATTRIBUTE_STATIC) || ji->method->klass->valuetype) {
+ MonoVTable *vtable = generic_info;
+
+ class = vtable->klass;
+ } else {
+ class = generic_info;
+ }
+
+ g_assert (!ji->method->klass->generic_container);
+ if (ji->method->klass->generic_class)
+ method_container_class = ji->method->klass->generic_class->container_class;
+ else
+ method_container_class = ji->method->klass;
+
+ /* class might refer to a subclass of ji->method's class */
+ while (class->generic_class && class->generic_class->container_class != method_container_class) {
+ class = class->parent;
+ g_assert (class);
+ }
+
+ if (class->generic_class || class->generic_container)
+ context.class_inst = mini_class_get_context (class)->class_inst;
+
+ if (class->generic_class)
+ g_assert (mono_class_has_parent_and_ignore_generics (class->generic_class->container_class, method_container_class));
+ else
+ g_assert (mono_class_has_parent_and_ignore_generics (class, method_container_class));
+
+ return context;
+}
+
+static MonoMethod*
+get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
+{
+ MonoGenericContext context;
+ MonoMethod *method;
+
+ if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
+ return ji->method;
+ context = get_generic_context_from_stack_frame (ji, generic_info);
+
+ method = mono_method_get_declaring_generic_method (ji->method);
+ method = mono_class_inflate_generic_method (method, &context);
+
+ return method;
+}