2 * exceptions-mips.c: exception support for MIPS
5 * Mark Mason (mason@broadcom.com)
7 * Based on exceptions-ppc.c by:
8 * Dietmar Maurer (dietmar@ximian.com)
9 * Paolo Molaro (lupus@ximian.com)
12 * (C) 2001 Ximian, Inc.
21 #include <mono/arch/mips/mips-codegen.h>
22 #include <mono/metadata/appdomain.h>
23 #include <mono/metadata/tabledefs.h>
24 #include <mono/metadata/threads.h>
25 #include <mono/metadata/debug-helpers.h>
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/mono-debug.h>
30 #include "mini-mips.h"
32 #define GENERIC_EXCEPTION_SIZE 256
34 #ifdef CUSTOM_EXCEPTION_HANDLING
35 static gboolean arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only);
40 #define restore_regs_from_context(ctx_reg,ip_reg,tmp_reg) do { \
43 #define restore_regs_from_context(ctx_reg,pc,tmp_reg) do { \
45 ppc_lwz (code, pc, G_STRUCT_OFFSET (MonoContext, sc_pc), ctx_reg); \
46 ppc_lmw (code, ppc_r13, ctx_reg, G_STRUCT_OFFSET (MonoContext, sc_regs)); \
47 for (reg = 0; reg < MONO_SAVED_FREGS; ++reg) { \
48 ppc_lfd (code, (14 + reg), G_STRUCT_OFFSET(MonoLMF, sc_fpregs) + reg * sizeof (gdouble), ctx_reg); \
54 #define setup_context(ctx) do { \
55 memset ((ctx), 0, sizeof(*(ctx))); \
59 * mono_arch_get_restore_context:
61 * Returns a pointer to a method which restores a previously saved MonoContext.
62 * The first argument in a0 is the pointer to the MonoContext.
65 mono_arch_get_restore_context (void)
69 static guint8 start [128];
70 static int inited = 0;
77 for (i = 0; i < MONO_SAVED_GREGS; ++i) {
78 if (MONO_ARCH_CALLEE_SAVED_REGS & (1 << i)) {
79 mips_lw (code, i, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[i]));
83 /* restore also the sp, fp and ra */
84 mips_lw (code, mips_sp, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_sp]));
85 mips_lw (code, mips_fp, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_fp]));
86 mips_lw (code, mips_ra, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_ra]));
88 /* Get the address to return to */
89 mips_lw (code, mips_t9, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_pc));
91 /* jump to the saved IP */
92 mips_jr (code, mips_t9);
96 mips_break (code, 0xff);
98 g_assert ((code - start) < sizeof(start));
99 mono_arch_flush_icache (start, code - start);
104 * mono_arch_get_call_filter:
106 * Returns a pointer to a method which calls an exception filter. We
107 * also use this function to call finally handlers (we pass NULL as
108 * @exc object in this case).
110 * This function is invoked as
111 * call_handler (MonoContext *ctx, handler)
113 * Where 'handler' is a function to be invoked as:
117 mono_arch_get_call_filter (void)
119 static guint8 start [320];
120 static int inited = 0;
133 g_assert ((alloc_size & (MIPS_STACK_ALIGNMENT-1)) == 0);
135 mips_addiu (code, mips_sp, mips_sp, -alloc_size);
136 mips_sw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
138 /* Save global registers on stack (s0 - s7) */
139 mips_sw (code, mips_s0, mips_sp, offset); offset += 4;
140 mips_sw (code, mips_s1, mips_sp, offset); offset += 4;
141 mips_sw (code, mips_s2, mips_sp, offset); offset += 4;
142 mips_sw (code, mips_s3, mips_sp, offset); offset += 4;
143 mips_sw (code, mips_s4, mips_sp, offset); offset += 4;
144 mips_sw (code, mips_s5, mips_sp, offset); offset += 4;
145 mips_sw (code, mips_s6, mips_sp, offset); offset += 4;
146 mips_sw (code, mips_s7, mips_sp, offset); offset += 4;
147 mips_sw (code, mips_fp, mips_sp, offset); offset += 4;
149 /* Restore global registers (s0-s7) */
150 mips_lw (code, mips_s0, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s0]));
151 mips_lw (code, mips_s1, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s1]));
152 mips_lw (code, mips_s2, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s2]));
153 mips_lw (code, mips_s3, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s3]));
154 mips_lw (code, mips_s4, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s4]));
155 mips_lw (code, mips_s5, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s5]));
156 mips_lw (code, mips_s6, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s6]));
157 mips_lw (code, mips_s7, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s7]));
158 mips_lw (code, mips_fp, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_fp]));
160 /* a1 is the handler to call */
161 mips_move (code, mips_t9, mips_a1);
163 /* jump to the saved IP */
164 mips_jalr (code, mips_t9, mips_ra);
167 /* restore all regs from the stack */
169 mips_lw (code, mips_s0, mips_sp, offset); offset += 4;
170 mips_lw (code, mips_s1, mips_sp, offset); offset += 4;
171 mips_lw (code, mips_s2, mips_sp, offset); offset += 4;
172 mips_lw (code, mips_s3, mips_sp, offset); offset += 4;
173 mips_lw (code, mips_s4, mips_sp, offset); offset += 4;
174 mips_lw (code, mips_s5, mips_sp, offset); offset += 4;
175 mips_lw (code, mips_s6, mips_sp, offset); offset += 4;
176 mips_lw (code, mips_s7, mips_sp, offset); offset += 4;
177 mips_lw (code, mips_fp, mips_sp, offset); offset += 4;
180 mips_lw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
181 mips_addiu (code, mips_sp, mips_sp, alloc_size);
182 mips_jr (code, mips_ra);
185 g_assert ((code - start) < sizeof(start));
186 mono_arch_flush_icache (start, code - start);
191 throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow)
193 static void (*restore_context) (MonoContext *);
197 printf("throw_exception: exc=%p eip=%x esp=%x rethrow=%d\n",
198 exc, (unsigned int) eip, (unsigned int) esp, rethrow);
201 if (!restore_context)
202 restore_context = mono_arch_get_restore_context ();
204 /* adjust eip so that it point into the call instruction */
207 setup_context (&ctx);
209 /*printf ("stack in throw: %p\n", esp);*/
210 memcpy (&ctx.sc_regs, (void *)(esp + MIPS_STACK_PARAM_OFFSET),
211 sizeof (gulong) * MONO_SAVED_GREGS);
213 memcpy (&ctx.sc_fpregs, fp_regs, sizeof (float) * MONO_SAVED_FREGS);
215 memset (&ctx.sc_fpregs, 0, sizeof (float) * MONO_SAVED_FREGS);
217 MONO_CONTEXT_SET_IP (&ctx, eip);
219 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
220 MonoException *mono_ex = (MonoException*)exc;
222 mono_ex->stack_trace = NULL;
224 #ifdef CUSTOM_EXCEPTION_HANDLING
225 arch_handle_exception (&ctx, exc, FALSE);
227 mono_handle_exception (&ctx, exc, (void *)eip, FALSE);
229 restore_context (&ctx);
231 g_assert_not_reached ();
235 * arch_get_throw_exception_generic:
237 * Returns a function pointer which can be used to raise
238 * exceptions. The returned function has the following
239 * signature: void (*func) (MonoException *exc); or
240 * void (*func) (char *exc_name);
244 mono_arch_get_throw_exception_generic (guint8 *start, int size, int by_name, gboolean rethrow)
247 int alloc_size, pos, i;
251 //printf("mono_arch_get_throw_exception_generic: code=%p\n", code);
254 /* XXX - save all the FP regs on the stack ? */
256 pos += MONO_MAX_IREGS * sizeof(guint32);
258 alloc_size = MIPS_MINIMAL_STACK_SIZE + pos + 64;
259 // align to MIPS_STACK_ALIGNMENT bytes
260 alloc_size += MIPS_STACK_ALIGNMENT - 1;
261 alloc_size &= ~(MIPS_STACK_ALIGNMENT - 1);
263 g_assert ((alloc_size & (MIPS_STACK_ALIGNMENT-1)) == 0);
264 mips_addiu (code, mips_sp, mips_sp, -alloc_size);
265 mips_sw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
267 /* Save all the regs on the stack */
268 for (i = 0; i < MONO_MAX_IREGS; i++) {
270 mips_sw (code, i, mips_sp, i*sizeof(guint32) + MIPS_STACK_PARAM_OFFSET);
272 mips_addiu (code, mips_at, mips_sp, alloc_size);
273 mips_sw (code, mips_at, mips_sp, i*sizeof(guint32) + MIPS_STACK_PARAM_OFFSET);
278 mips_move (code, mips_a2, mips_a0);
279 mips_load (code, mips_a0, mono_defaults.corlib);
280 mips_load (code, mips_a1, "System");
281 mips_load (code, mips_t9, mono_exception_from_name);
282 mips_jalr (code, mips_t9, mips_ra);
284 mips_move (code, mips_a0, mips_v0);
286 /* call throw_exception (exc, ip, sp, rethrow) */
288 /* exc is already in place in a0 */
292 mips_lw (code, mips_a1, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
294 mips_move (code, mips_a1, mips_ra);
296 /* current sp & rethrow */
297 mips_move (code, mips_a2, mips_sp);
298 mips_addiu (code, mips_a3, mips_zero, rethrow);
300 mips_load (code, mips_t9, throw_exception);
301 mips_jr (code, mips_t9);
303 /* we should never reach this breakpoint */
304 mips_break (code, 0xfe);
306 g_assert ((code - start) < size);
307 mono_arch_flush_icache (start, code - start);
312 * mono_arch_get_rethrow_exception:
314 * Returns a function pointer which can be used to rethrow
315 * exceptions. The returned function has the following
316 * signature: void (*func) (MonoException *exc);
320 mono_arch_get_rethrow_exception (void)
322 static guint8 start [GENERIC_EXCEPTION_SIZE];
323 static int inited = 0;
327 mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE);
333 * arch_get_throw_exception:
335 * Returns a function pointer which can be used to raise
336 * exceptions. The returned function has the following
337 * signature: void (*func) (MonoException *exc);
338 * For example to raise an arithmetic exception you can use:
340 * x86_push_imm (code, mono_get_exception_arithmetic ());
341 * x86_call_code (code, arch_get_throw_exception ());
345 mono_arch_get_throw_exception (void)
347 static guint8 start [GENERIC_EXCEPTION_SIZE];
348 static int inited = 0;
352 mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, FALSE);
358 * arch_get_throw_exception_by_name:
360 * Returns a function pointer which can be used to raise
361 * corlib exceptions. The returned function has the following
362 * signature: void (*func) (char *exc_name);
363 * For example to raise an arithmetic exception you can use:
365 * x86_push_imm (code, "ArithmeticException");
366 * x86_call_code (code, arch_get_throw_exception_by_name ());
370 mono_arch_get_throw_exception_by_name (void)
372 static guint8 start [GENERIC_EXCEPTION_SIZE];
373 static int inited = 0;
377 mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE);
383 glist_to_array (GList *list, MonoClass *eclass)
385 MonoDomain *domain = mono_domain_get ();
392 len = g_list_length (list);
393 res = mono_array_new (domain, eclass, len);
395 for (i = 0; list; list = list->next, i++)
396 mono_array_set (res, gpointer, i, list->data);
401 /* mono_arch_find_jit_info:
403 * This function is used to gather information from @ctx. It returns the
404 * MonoJitInfo of the corresponding function, unwinds one stack frame and
405 * stores the resulting context into @new_ctx. It also stores a string
406 * describing the stack location into @trace (if not NULL), and modifies
407 * the @lmf if necessary. @native_offset return the IP offset from the
408 * start of the function or -1 if that info is not available.
411 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
412 MonoJitInfo *res, MonoJitInfo *prev_ji,
413 MonoContext *ctx, MonoContext *new_ctx,
414 char **trace, MonoLMF **lmf,
415 int *native_offset, gboolean *managed)
418 gpointer ip = MONO_CONTEXT_GET_IP (ctx);
421 /* Avoid costly table lookup during stack overflow */
422 if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
425 ji = mono_jit_info_table_find (domain, ip);
442 setup_context (new_ctx);
444 if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
445 /* remove any unused lmf */
446 *lmf = (*lmf)->previous_lmf;
449 address = (char *)ip - (char *)ji->code_start;
452 *native_offset = address;
455 if (!ji->method->wrapper_type)
459 *trace = mono_debug_print_stack_frame (ji->method, offset, domain);
461 /* Compute the previous stack frame */
462 sp = (guint32)(MONO_CONTEXT_GET_BP (ctx)) - (short)(*(guint32 *)(ji->code_start));
464 /* Sanity check the frame */
465 if (!sp || (sp == 0xffffffff)
466 || (sp & 0x07) || (sp < 64*1024))
468 MONO_CONTEXT_SET_BP (new_ctx, sp);
470 if (ji->method->save_lmf && 0) {
471 memcpy (&new_ctx->sc_fpregs, (char*)sp - sizeof (float) * MONO_SAVED_FREGS, sizeof (float) * MONO_SAVED_FREGS);
472 memcpy (&new_ctx->sc_regs, (char*)sp - sizeof (float) * MONO_SAVED_FREGS - sizeof (gulong) * MONO_SAVED_GREGS, sizeof (gulong) * MONO_SAVED_GREGS);
473 } else if (ji->used_regs) {
474 /* keep updated with emit_prolog in mini-mips.c */
476 /* FIXME handle floating point args */
477 for (i = 0; i < MONO_MAX_IREGS; i++) {
478 new_ctx->sc_regs [i] = 0;
480 new_ctx->sc_regs [mips_fp] = sp;
481 new_ctx->sc_regs [mips_sp] = sp;
482 new_ctx->sc_regs [mips_ra] = *(guint32 *)(sp-4);
484 /* we substract 8, so that the IP points into the call instruction */
485 MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_regs[mips_ra] - 8);
491 setup_context (new_ctx);
497 char *fname = mono_method_full_name ((*lmf)->method, TRUE);
498 *trace = g_strdup_printf ("in (unmanaged) %s", fname);
502 if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
504 memset (res, 0, sizeof (MonoJitInfo));
505 res->method = (*lmf)->method;
509 memcpy (&new_ctx->sc_regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS);
510 memcpy (&new_ctx->sc_fpregs, (*lmf)->fregs, sizeof (float) * MONO_SAVED_FREGS);
512 MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
513 MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
514 *lmf = (*lmf)->previous_lmf;
516 return ji ? ji : res;
522 #ifdef CUSTOM_STACK_WALK
525 mono_jit_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data) {
526 MonoDomain *domain = mono_domain_get ();
527 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
528 MonoLMF *lmf = jit_tls->lmf;
529 MonoJitInfo *ji, rji;
530 gint native_offset, il_offset;
532 MonoMipsStackFrame *sframe;
534 MonoContext ctx, new_ctx;
536 setup_context (&ctx);
537 setup_context (&new_ctx);
539 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_jit_walk_stack);
540 MONO_INIT_CONTEXT_FROM_FUNC (&new_ctx, mono_jit_walk_stack);
542 while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) {
544 ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed);
547 if (ji == (gpointer)-1)
551 MonoDebugSourceLocation *source;
553 source = mono_debug_lookup_source_location (ji->method, native_offset, domain);
554 il_offset = source ? source->il_offset : -1;
555 mono_debug_free_source_location (source);
559 if (func (ji->method, native_offset, il_offset, managed, user_data))
563 setup_context (&ctx);
569 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
570 MonoReflectionMethod **method,
571 gint32 *iloffset, gint32 *native_offset,
572 MonoString **file, gint32 *line, gint32 *column)
574 MonoDomain *domain = mono_domain_get ();
575 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
576 MonoLMF *lmf = jit_tls->lmf;
577 MonoJitInfo *ji, rji;
578 MonoContext ctx, new_ctx;
579 MonoMipsStackFrame *sframe;
580 MonoDebugSourceLocation *location;
584 __asm__ volatile("lwz %0,0(r1)" : "=r" (sframe));
586 __asm__ volatile("lwz %0,0(1)" : "=r" (sframe));
589 MONO_CONTEXT_SET_BP (&ctx, sframe->sp);
590 sframe = (MonoMipsStackFrame*)sframe->sp;
591 MONO_CONTEXT_SET_IP (&ctx, sframe->ra);
592 /*MONO_CONTEXT_SET_IP (&ctx, ves_icall_get_frame_info);
593 MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (0));*/
598 ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL);
602 if (!ji || ji == (gpointer)-1 || MONO_CONTEXT_GET_BP (&ctx) >= jit_tls->end_of_stack)
605 /* skip all wrappers ??*/
606 if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
607 ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
608 ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
609 ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
610 ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
617 *method = mono_method_get_object (domain, ji->method, NULL);
619 location = mono_debug_lookup_source_location (ji->method, *native_offset, domain);
621 *iloffset = location->il_offset;
625 if (need_file_info) {
627 *file = mono_string_new (domain, location->source_file);
628 *line = location->row;
629 *column = location->column;
636 mono_debug_free_source_location (location);
641 #endif /* CUSTOM_STACK_WALK */
644 mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
647 struct sigcontext *ctx = (struct sigcontext *)sigctx;
649 mctx->sc_pc = ctx->sc_pc;
650 for (i = 0; i < 32; ++i) {
651 mctx->sc_regs[i] = ctx->sc_regs[i];
652 mctx->sc_fpregs[i] = ctx->sc_fpregs[i];
657 mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
660 struct sigcontext *ctx = (struct sigcontext *)sigctx;
662 ctx->sc_pc = mctx->sc_pc;
663 for (i = 0; i < 32; ++i) {
664 ctx->sc_regs[i] = mctx->sc_regs[i];
665 ctx->sc_fpregs[i] = mctx->sc_fpregs[i];
670 mono_arch_ip_from_context (void *sigctx)
672 struct ucontext *uc = sigctx;
673 return (gpointer)(guint32)uc->uc_mcontext.pc;
677 * This is the function called from the signal handler
680 mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
685 mono_arch_sigctx_to_monoctx (ctx, &mctx);
686 #ifdef CUSTOM_EXCEPTION_HANDLING
687 result = arch_handle_exception (&mctx, obj, test_only);
689 mono_handle_exception (&mctx, obj, (gpointer)mctx.sc_pc, test_only);
693 /* restore the context so that returning from the signal handler
694 * will invoke the catch clause
696 mono_arch_monoctx_to_sigctx (&mctx, ctx);
701 #ifdef CUSTOM_EXCEPTION_HANDLING
703 * arch_handle_exception:
704 * @ctx: saved processor state
705 * @obj: the exception object
706 * @test_only: only test if the exception is caught, but dont call handlers
711 arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only)
713 MonoDomain *domain = mono_domain_get ();
714 MonoJitInfo *ji, rji;
715 static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL;
716 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
717 MonoLMF *lmf = jit_tls->lmf;
718 GList *trace_ips = NULL;
719 MonoException *mono_ex;
720 MonoArray *initial_trace_ips = NULL;
722 gboolean has_dynamic_methods = FALSE;
724 g_assert (ctx != NULL);
726 MonoException *ex = mono_get_exception_null_reference ();
727 ex->message = mono_string_new (domain,
728 "Object reference not set to an instance of an object");
729 obj = (MonoObject *)ex;
732 if (mono_object_isinst (obj, mono_defaults.exception_class)) {
733 mono_ex = (MonoException*)obj;
734 initial_trace_ips = mono_ex->trace_ips;
741 call_filter = mono_arch_get_call_filter ();
743 g_assert (jit_tls->end_of_stack);
744 g_assert (jit_tls->abort_func);
747 MonoContext ctx_cp = *ctx;
748 setup_context (&ctx_cp);
749 if (mono_jit_trace_calls != NULL)
750 g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
751 if (!arch_handle_exception (&ctx_cp, obj, TRUE)) {
752 if (mono_break_on_exc)
754 mono_unhandled_exception (obj);
758 memset (&rji, 0, sizeof (rji));
763 setup_context (&new_ctx);
764 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx,
765 NULL, &lmf, NULL, NULL);
767 g_warning ("Exception inside function without unwind info");
768 g_assert_not_reached ();
771 if (ji != (gpointer)-1) {
774 if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
776 * Avoid overwriting the stack trace if the exception is
777 * rethrown. Also avoid giant stack traces during a stack
780 if (!initial_trace_ips && (frame_count < 1000)) {
781 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
786 if (ji->method->dynamic)
787 has_dynamic_methods = TRUE;
789 if (ji->num_clauses) {
792 g_assert (ji->clauses);
794 for (i = 0; i < ji->num_clauses; i++) {
795 MonoJitExceptionInfo *ei = &ji->clauses [i];
796 gboolean filtered = FALSE;
798 if (ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
799 MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) {
802 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) {
803 /* store the exception object int cfg->excvar */
804 g_assert (ei->exvar_offset);
805 /* need to use the frame pointer (mips_fp): methods with clauses always have mips_fp */
806 *((gpointer *)(void*)((char *)(ctx->sc_regs [mips_fp]) + ei->exvar_offset)) = obj;
809 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
810 filtered = call_filter (ctx, ei->data.filter, mono_ex);
812 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE &&
813 mono_object_isinst (obj, ei->data.catch_class)) || filtered) {
815 if (mono_ex && !initial_trace_ips) {
816 trace_ips = g_list_reverse (trace_ips);
817 mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class);
818 if (has_dynamic_methods)
819 /* These methods could go away anytime, so compute the stack trace now */
820 mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex);
822 g_list_free (trace_ips);
825 if (mono_jit_trace_calls != NULL)
826 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
827 /*printf ("stack for catch: %p\n", MONO_CONTEXT_GET_BP (ctx));*/
828 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
832 if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
833 MONO_CONTEXT_GET_IP (ctx) < ei->try_end &&
834 (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
835 if (mono_jit_trace_calls != NULL)
836 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
837 call_filter (ctx, ei->handler_start, NULL);
848 if ((ji == (gpointer)-1) || MONO_CONTEXT_GET_BP (ctx) >= jit_tls->end_of_stack) {
851 jit_tls->abort_func (obj);
852 g_assert_not_reached ();
854 if (mono_ex && !initial_trace_ips) {
855 trace_ips = g_list_reverse (trace_ips);
856 mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class);
857 if (has_dynamic_methods)
858 /* These methods could go away anytime, so compute the stack trace now */
859 mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex);
861 g_list_free (trace_ips);
867 g_assert_not_reached ();
869 #endif /* CUSTOM_EXCEPTION_HANDLING */
872 mono_arch_has_unwind_info (gconstpointer addr)