1 /*------------------------------------------------------------------*/
3 /* Name - exceptions-s390.c */
5 /* Function - Exception support for S/390. */
7 /* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
9 /* Date - January, 2004 */
11 /* Derivation - From exceptions-x86 & exceptions-ppc */
12 /* Paolo Molaro (lupus@ximian.com) */
13 /* Dietmar Maurer (dietmar@ximian.com) */
15 /* Copyright - 2001 Ximian, Inc. */
17 /*------------------------------------------------------------------*/
19 /*------------------------------------------------------------------*/
21 /*------------------------------------------------------------------*/
23 #define MONO_CONTEXT_SET_IP(ctx,ip) \
25 (ctx)->uc_mcontext.gregs[14] = (unsigned long)ip; \
26 (ctx)->uc_mcontext.psw.addr = (unsigned long)ip; \
29 #define MONO_CONTEXT_SET_BP(ctx,bp) \
31 (ctx)->uc_mcontext.gregs[15] = (unsigned long)bp; \
32 (ctx)->uc_stack.ss_sp = (unsigned long)bp; \
35 #define MONO_CONTEXT_GET_IP(ctx) context_get_ip ((ctx))
36 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[15]))
38 #define S390_CALLFILTER_INTREGS S390_MINIMAL_STACK_SIZE
39 #define S390_CALLFILTER_FLTREGS S390_CALLFILTER_INTREGS+(16*sizeof(gulong))
40 #define S390_CALLFILTER_ACCREGS S390_CALLFILTER_FLTREGS+(16*sizeof(gdouble))
41 #define S390_CALLFILTER_SIZE (S390_CALLFILTER_ACCREGS+(16*sizeof(gulong)))
43 #define S390_THROWSTACK_ACCPRM S390_MINIMAL_STACK_SIZE
44 #define S390_THROWSTACK_FPCPRM S390_THROWSTACK_ACCPRM+sizeof(gpointer)
45 #define S390_THROWSTACK_RETHROW S390_THROWSTACK_FPCPRM+sizeof(gulong)
46 #define S390_THROWSTACK_INTREGS S390_THROWSTACK_RETHROW+sizeof(gboolean)
47 #define S390_THROWSTACK_FLTREGS S390_THROWSTACK_INTREGS+(16*sizeof(gulong))
48 #define S390_THROWSTACK_ACCREGS S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble))
49 #define S390_THROWSTACK_SIZE (S390_THROWSTACK_ACCREGS+(16*sizeof(gulong)))
51 /*========================= End of Defines =========================*/
53 /*------------------------------------------------------------------*/
55 /*------------------------------------------------------------------*/
63 #include <mono/arch/s390/s390-codegen.h>
64 #include <mono/metadata/appdomain.h>
65 #include <mono/metadata/tabledefs.h>
66 #include <mono/metadata/threads.h>
67 #include <mono/metadata/debug-helpers.h>
68 #include <mono/metadata/exception.h>
69 #include <mono/metadata/mono-debug.h>
72 #include "mini-s390.h"
74 /*========================= End of Includes ========================*/
76 /*------------------------------------------------------------------*/
78 /*------------------------------------------------------------------*/
88 /*========================= End of Typedefs ========================*/
90 /*------------------------------------------------------------------*/
91 /* P r o t o t y p e s */
92 /*------------------------------------------------------------------*/
94 gboolean mono_arch_handle_exception (void *ctx,
98 /*========================= End of Prototypes ======================*/
100 /*------------------------------------------------------------------*/
101 /* G l o b a l V a r i a b l e s */
102 /*------------------------------------------------------------------*/
104 /*====================== End of Global Variables ===================*/
106 /*------------------------------------------------------------------*/
108 /* Name - context_get_ip */
110 /* Function - Extract the current instruction address from the */
113 /*------------------------------------------------------------------*/
115 static inline gpointer
116 context_get_ip (MonoContext *ctx)
120 ip = (gpointer) ((gint32) (ctx->uc_mcontext.psw.addr) & 0x7fffffff);
124 /*========================= End of Function ========================*/
126 /*------------------------------------------------------------------*/
128 /* Name - mono_arch_has_unwind_info */
130 /* Function - Tests if a function has a DWARF exception table */
131 /* that is able to restore all caller saved registers*/
133 /*------------------------------------------------------------------*/
136 mono_arch_has_unwind_info (gconstpointer addr)
141 /*========================= End of Function ========================*/
143 /*------------------------------------------------------------------*/
145 /* Name - arch_get_call_filter */
147 /* Function - Return a pointer to a method which calls an */
148 /* exception filter. We also use this function to */
149 /* call finally handlers (we pass NULL as @exc */
150 /* object in this case). */
152 /*------------------------------------------------------------------*/
155 arch_get_call_filter (void)
157 static guint8 start [512];
158 static int inited = 0;
160 int alloc_size, pos, i;
166 /* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */
169 s390_stm (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
170 s390_lr (code, s390_r14, STK_BASE);
171 alloc_size = S390_ALIGN(S390_CALLFILTER_SIZE, S390_STACK_ALIGNMENT);
172 s390_ahi (code, STK_BASE, -alloc_size);
173 s390_st (code, s390_r14, 0, STK_BASE, 0);
175 /*------------------------------------------------------*/
176 /* save general registers on stack */
177 /*------------------------------------------------------*/
178 s390_stm (code, s390_r0, s390_r13, STK_BASE, S390_CALLFILTER_INTREGS);
180 /*------------------------------------------------------*/
181 /* save floating point registers on stack */
182 /*------------------------------------------------------*/
183 // pos = S390_CALLFILTER_FLTREGS;
184 // for (i = 0; i < 16; ++i) {
185 // s390_std (code, i, 0, STK_BASE, pos);
186 // pos += sizeof (gdouble);
189 /*------------------------------------------------------*/
190 /* save access registers on stack */
191 /*------------------------------------------------------*/
192 // s390_stam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS);
194 /*------------------------------------------------------*/
196 /*------------------------------------------------------*/
197 s390_lr (code, s390_r13, s390_r2);
199 /*------------------------------------------------------*/
200 /* Get A(Handler Entry Point) */
201 /*------------------------------------------------------*/
202 s390_lr (code, s390_r0, s390_r3);
204 /*------------------------------------------------------*/
205 /* Set parameter register with Exception */
206 /*------------------------------------------------------*/
207 s390_lr (code, s390_r2, s390_r4);
209 /*------------------------------------------------------*/
210 /* Load all registers with values from the context */
211 /*------------------------------------------------------*/
212 s390_lm (code, s390_r3, s390_r12, s390_r13, G_STRUCT_OFFSET(MonoContext, uc_mcontext.gregs[3]));
213 pos = G_STRUCT_OFFSET(MonoContext, uc_mcontext.fpregs.fprs[0]);
214 for (i = 0; i < 16; ++i) {
215 s390_ld (code, i, 0, s390_r13, pos);
216 pos += sizeof(gdouble);
219 /*------------------------------------------------------*/
220 /* Point at the copied stack frame and call the filter */
221 /*------------------------------------------------------*/
222 s390_lr (code, s390_r1, s390_r0);
223 s390_basr (code, s390_r14, s390_r1);
225 /*------------------------------------------------------*/
226 /* Save return value */
227 /*------------------------------------------------------*/
228 s390_lr (code, s390_r14, s390_r2);
230 /*------------------------------------------------------*/
231 /* Restore all the regs from the stack */
232 /*------------------------------------------------------*/
233 s390_lm (code, s390_r0, s390_r13, STK_BASE, S390_CALLFILTER_INTREGS);
234 // pos = S390_CALLFILTER_FLTREGS;
235 // for (i = 0; i < 16; ++i) {
236 // s390_ld (code, i, 0, STK_BASE, pos);
237 // pos += sizeof (gdouble);
240 s390_lr (code, s390_r2, s390_r14);
241 // s390_lam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS);
242 s390_ahi (code, s390_r15, alloc_size);
243 s390_lm (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
244 s390_br (code, s390_r14);
246 g_assert ((code - start) < sizeof(start));
250 /*========================= End of Function ========================*/
252 /*------------------------------------------------------------------*/
254 /* Name - throw_exception. */
256 /* Function - Raise an exception based on the parameters passed.*/
258 /*------------------------------------------------------------------*/
261 throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
262 gulong *int_regs, gdouble *fp_regs, gulong *acc_regs,
263 guint fpc, gboolean rethrow)
268 memset(&ctx, 0, sizeof(ctx));
272 /* adjust eip so that it point into the call instruction */
275 for (iReg = 0; iReg < 16; iReg++) {
276 ctx.uc_mcontext.gregs[iReg] = int_regs[iReg];
277 ctx.uc_mcontext.fpregs.fprs[iReg].d = fp_regs[iReg];
278 ctx.uc_mcontext.aregs[iReg] = acc_regs[iReg];
281 ctx.uc_mcontext.fpregs.fpc = fpc;
283 MONO_CONTEXT_SET_BP (&ctx, sp);
284 MONO_CONTEXT_SET_IP (&ctx, ip);
286 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
287 MonoException *mono_ex = (MonoException*)exc;
289 mono_ex->stack_trace = NULL;
291 mono_arch_handle_exception (&ctx, exc, FALSE);
294 g_assert_not_reached ();
297 /*========================= End of Function ========================*/
299 /*------------------------------------------------------------------*/
301 /* Name - get_throw_exception_generic */
303 /* Function - Return a function pointer which can be used to */
304 /* raise exceptions. The returned function has the */
305 /* following signature: */
306 /* void (*func) (MonoException *exc); or, */
307 /* void (*func) (char *exc_name); */
309 /*------------------------------------------------------------------*/
312 get_throw_exception_generic (guint8 *start, int size,
313 int by_name, gboolean rethrow)
316 int alloc_size, pos, i, offset;
320 s390_stm (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
321 alloc_size = S390_ALIGN(S390_THROWSTACK_SIZE, S390_STACK_ALIGNMENT);
322 s390_lr (code, s390_r14, STK_BASE);
323 s390_ahi (code, STK_BASE, -alloc_size);
324 s390_st (code, s390_r14, 0, STK_BASE, 0);
326 s390_lr (code, s390_r4, s390_r2);
327 s390_bras (code, s390_r13, 6);
328 s390_word (code, mono_defaults.corlib);
329 s390_word (code, "System");
330 s390_l (code, s390_r2, 0, s390_r13, 0);
331 s390_l (code, s390_r3, 0, s390_r13, 4);
332 offset = (guint32) S390_RELATIVE(mono_exception_from_name, code);
333 s390_brasl(code, s390_r14, offset);
335 /*------------------------------------------------------*/
336 /* save the general registers on the stack */
337 /*------------------------------------------------------*/
338 s390_stm (code, s390_r0, s390_r13, STK_BASE, S390_THROWSTACK_INTREGS);
340 s390_lr (code, s390_r1, STK_BASE);
341 s390_ahi (code, s390_r1, alloc_size);
342 /*------------------------------------------------------*/
343 /* save the return address in the parameter register */
344 /*------------------------------------------------------*/
345 s390_l (code, s390_r3, 0, s390_r1, S390_RET_ADDR_OFFSET);
347 /*------------------------------------------------------*/
348 /* save the floating point registers */
349 /*------------------------------------------------------*/
350 pos = S390_THROWSTACK_FLTREGS;
351 for (i = 0; i < 16; ++i) {
352 s390_std (code, i, 0,STK_BASE, pos);
353 pos += sizeof (gdouble);
355 /*------------------------------------------------------*/
356 /* save the access registers */
357 /*------------------------------------------------------*/
358 s390_stam (code, s390_r0, s390_r15, STK_BASE, S390_THROWSTACK_ACCREGS);
360 /*------------------------------------------------------*/
361 /* call throw_exception (exc, ip, sp, gr, fr, ar) */
362 /* exc is already in place in r2 */
363 /*------------------------------------------------------*/
364 s390_lr (code, s390_r4, s390_r1); /* caller sp */
365 /*------------------------------------------------------*/
366 /* pointer to the saved int regs */
367 /*------------------------------------------------------*/
368 s390_la (code, s390_r5, 0, STK_BASE, S390_THROWSTACK_INTREGS);
369 s390_la (code, s390_r6, 0, STK_BASE, S390_THROWSTACK_FLTREGS);
370 s390_la (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCREGS);
371 s390_st (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCPRM);
372 s390_stfpc(code, STK_BASE, S390_THROWSTACK_FPCPRM);
373 s390_lhi (code, s390_r7, rethrow);
374 s390_st (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW);
375 offset = (guint32) S390_RELATIVE(throw_exception, code);
376 s390_brasl(code, s390_r14, offset);
377 /* we should never reach this breakpoint */
379 g_assert ((code - start) < size);
383 /*========================= End of Function ========================*/
385 /*------------------------------------------------------------------*/
387 /* Name - arch_get_throw_exception */
389 /* Function - Return a function pointer which can be used to */
390 /* raise exceptions. The returned function has the */
391 /* following signature: */
392 /* void (*func) (MonoException *exc); */
394 /*------------------------------------------------------------------*/
397 mono_arch_get_throw_exception (void)
399 static guint8 start [384];
400 static int inited = 0;
404 get_throw_exception_generic (start, sizeof (start), FALSE, FALSE);
409 /*========================= End of Function ========================*/
411 /*------------------------------------------------------------------*/
413 /* Name - arch_get_rethrow_exception */
415 /* Function - Return a function pointer which can be used to */
416 /* raise exceptions. The returned function has the */
417 /* following signature: */
418 /* void (*func) (MonoException *exc); */
420 /*------------------------------------------------------------------*/
423 mono_arch_get_rethrow_exception (void)
425 static guint8 start [384];
426 static int inited = 0;
430 get_throw_exception_generic (start, sizeof (start), FALSE, TRUE);
435 /*========================= End of Function ========================*/
437 /*------------------------------------------------------------------*/
439 /* Name - arch_get_throw_exception_by_name */
441 /* Function - Return a function pointer which can be used to */
442 /* raise corlib exceptions. The return function has */
443 /* the following signature: */
444 /* void (*func) (char *exc_name); */
446 /*------------------------------------------------------------------*/
449 mono_arch_get_throw_exception_by_name (void)
451 static guint8 start [384];
452 static int inited = 0;
456 get_throw_exception_generic (start, sizeof (start), TRUE, FALSE);
461 /*========================= End of Function ========================*/
463 /*------------------------------------------------------------------*/
465 /* Name - glist_to_array */
467 /* Function - Convert a list to a mono array. */
469 /*------------------------------------------------------------------*/
472 glist_to_array (GList *list)
474 MonoDomain *domain = mono_domain_get ();
481 len = g_list_length (list);
482 res = mono_array_new (domain, mono_defaults.int_class, len);
484 for (i = 0; list; list = list->next, i++)
485 mono_array_set (res, gpointer, i, list->data);
490 /*========================= End of Function ========================*/
492 /*------------------------------------------------------------------*/
494 /* Name - mono_arch_find_jit_info */
496 /* Function - This function is used to gather informatoin from */
497 /* @ctx. It returns the MonoJitInfo of the corres- */
498 /* ponding function, unwinds one stack frame and */
499 /* stores the resulting context into @new_ctx. It */
500 /* also stores a string describing the stack location*/
501 /* into @trace (if not NULL), and modifies the @lmf */
502 /* if necessary. @native_offset returns the IP off- */
503 /* set from the start of the function or -1 if that */
504 /* informatoin is not available. */
506 /*------------------------------------------------------------------*/
509 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
510 MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx,
511 MonoContext *new_ctx, char **trace, MonoLMF **lmf,
512 int *native_offset, gboolean *managed)
515 gpointer ip = MONO_CONTEXT_GET_IP (ctx);
516 MonoS390StackFrame *sframe;
519 (ip >= prev_ji->code_start &&
520 ((guint8 *) ip <= ((guint8 *) prev_ji->code_start) + prev_ji->code_size)))
523 ji = mono_jit_info_table_find (domain, ip);
535 char *source_location, *tmpaddr, *fname;
536 gint32 address, iloffset;
540 if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
541 /* remove any unused lmf */
542 *lmf = (*lmf)->previous_lmf;
545 address = (char *)ip - (char *)ji->code_start;
548 *native_offset = address;
551 if (!ji->method->wrapper_type)
555 source_location = mono_debug_source_location_from_address (ji->method, address, NULL, domain);
556 iloffset = mono_debug_il_offset_from_address (ji->method, address, domain);
559 tmpaddr = g_strdup_printf ("<0x%08x>", address);
561 tmpaddr = g_strdup_printf ("[0x%08x]", iloffset);
563 fname = mono_method_full_name (ji->method, TRUE);
566 *trace = g_strdup_printf ("in %s (at %s) %s", tmpaddr, source_location, fname);
568 *trace = g_strdup_printf ("in %s %s", tmpaddr, fname);
571 g_free (source_location);
574 sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_BP (ctx);
575 MONO_CONTEXT_SET_BP (new_ctx, sframe->prev);
576 sframe = (MonoS390StackFrame *) sframe->prev;
577 MONO_CONTEXT_SET_IP (new_ctx, sframe->return_address);
578 memcpy (&new_ctx->uc_mcontext.gregs[6], sframe->regs, (8*sizeof(gint32)));
589 *trace = g_strdup_printf ("in (unmanaged) %s", mono_method_full_name ((*lmf)->method, TRUE));
591 if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
594 memset (res, 0, sizeof (MonoJitInfo));
595 res->method = (*lmf)->method;
598 memcpy(new_ctx->uc_mcontext.gregs, (*lmf)->gregs, sizeof((*lmf)->gregs));
599 memcpy(new_ctx->uc_mcontext.fpregs.fprs, (*lmf)->fregs, sizeof((*lmf)->fregs));
601 MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
602 MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
603 *lmf = (*lmf)->previous_lmf;
612 /*========================= End of Function ========================*/
614 /*------------------------------------------------------------------*/
616 /* Name - ves_icall_get_trace */
620 /*------------------------------------------------------------------*/
623 ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
625 MonoDomain *domain = mono_domain_get ();
627 MonoArray *ta = exc->trace_ips;
631 return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
634 len = mono_array_length (ta);
636 res = mono_array_new (domain, mono_defaults.stack_frame_class,
637 len > skip ? len - skip : 0);
639 for (i = skip; i < len; i++) {
641 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
642 gpointer ip = mono_array_get (ta, gpointer, i);
644 ji = mono_jit_info_table_find (domain, ip);
646 mono_array_set (res, gpointer, i, sf);
650 sf->method = mono_method_get_object (domain, ji->method, NULL);
651 sf->native_offset = (char *)ip - (char *)ji->code_start;
653 sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
655 if (need_file_info) {
658 filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
660 sf->filename = filename? mono_string_new (domain, filename): NULL;
666 mono_array_set (res, gpointer, i, sf);
672 /*========================= End of Function ========================*/
674 /*------------------------------------------------------------------*/
676 /* Name - mono_jit_walk_stack */
680 /*------------------------------------------------------------------*/
683 mono_jit_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data) {
684 MonoDomain *domain = mono_domain_get ();
685 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
686 MonoLMF *lmf = jit_tls->lmf;
687 MonoJitInfo *ji, rji;
688 gint native_offset, il_offset;
690 MonoContext ctx, new_ctx;
692 MONO_CONTEXT_SET_IP (&ctx, __builtin_return_address (0));
693 MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (1));
695 while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) {
697 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL,
698 &ctx, &new_ctx, NULL, &lmf,
699 &native_offset, &managed);
702 if (ji == (gpointer)-1)
705 il_offset = do_il_offset ? mono_debug_il_offset_from_address (ji->method, native_offset, domain): -1;
707 if (func (ji->method, native_offset, il_offset, managed, user_data))
714 /*========================= End of Function ========================*/
716 /*------------------------------------------------------------------*/
718 /* Name - ves_icall_get_frame_info */
722 /*------------------------------------------------------------------*/
725 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
726 MonoReflectionMethod **method,
727 gint32 *iloffset, gint32 *native_offset,
728 MonoString **file, gint32 *line, gint32 *column)
730 MonoDomain *domain = mono_domain_get ();
731 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
732 MonoLMF *lmf = jit_tls->lmf;
733 MonoJitInfo *ji, rji;
734 MonoContext ctx, new_ctx;
736 MONO_CONTEXT_SET_IP (&ctx, ves_icall_get_frame_info);
737 MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (0));
742 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL,
743 &ctx, &new_ctx, NULL, &lmf,
744 native_offset, NULL);
748 if (!ji || ji == (gpointer)-1 ||
749 MONO_CONTEXT_GET_BP (&ctx) >= jit_tls->end_of_stack)
752 /*---------------------------------------------------*/
753 /* skip all wrappers ?? */
754 /*---------------------------------------------------*/
755 if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
756 ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
757 ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
758 ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
759 ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
766 *method = mono_method_get_object (domain, ji->method, NULL);
767 *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset, domain);
769 if (need_file_info) {
772 filename = mono_debug_source_location_from_address (ji->method, *native_offset, line, domain);
774 *file = filename? mono_string_new (domain, filename): NULL;
783 /*========================= End of Function ========================*/
785 /*------------------------------------------------------------------*/
787 /* Name - mono_arch_handle_exception */
789 /* Function - Handle an exception raised by the JIT code. */
791 /* Parameters - ctx - Saved processor state */
792 /* obj - The exception object */
793 /* test_only - Only test if the exception is caught, */
794 /* but don't call handlers */
796 /*------------------------------------------------------------------*/
799 mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only)
801 MonoContext *ctx = uc;
802 MonoDomain *domain = mono_domain_get ();
803 MonoJitInfo *ji, rji;
804 static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL;
805 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
806 MonoLMF *lmf = jit_tls->lmf;
807 GList *trace_ips = NULL;
808 GString *traceStr = NULL;
809 MonoException *mono_ex;
810 MonoString *initialStackTrace = NULL;
813 g_assert (ctx != NULL);
814 memset(&rji, 0, sizeof(rji));
816 MonoException *ex = mono_get_exception_null_reference ();
817 ex->message = mono_string_new (domain,
818 "Object reference not set to an instance of an object");
819 obj = (MonoObject *)ex;
822 if (mono_object_isinst (obj, mono_defaults.exception_class)) {
823 mono_ex = (MonoException*)obj;
824 initialStackTrace = mono_ex->stack_trace;
831 call_filter = arch_get_call_filter ();
833 g_assert (jit_tls->end_of_stack);
834 g_assert (jit_tls->abort_func);
837 MonoContext ctx_cp = *ctx;
838 if (mono_jit_trace_calls != NULL)
839 g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
840 if (!mono_arch_handle_exception (&ctx_cp, obj, TRUE)) {
841 if (mono_break_on_exc)
843 mono_unhandled_exception (obj);
847 memset (&rji, 0, sizeof(rji));
852 gboolean needTrace = FALSE;
854 if (test_only && (frameCount < 1000)) {
857 traceStr = g_string_new ("");
860 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx,
861 test_only ? &trace : NULL, &lmf, NULL, NULL);
863 g_warning ("Exception inside function without unwind info");
864 g_assert_not_reached ();
867 if (ji != (gpointer)-1) {
871 (ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) &&
873 if (!initialStackTrace && (frameCount < 1000)) {
874 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
875 g_string_append (traceStr, trace);
876 g_string_append_c (traceStr, '\n');
880 if (ji->num_clauses) {
883 g_assert (ji->clauses);
885 for (i = 0; i < ji->num_clauses; i++) {
886 MonoJitExceptionInfo *ei = &ji->clauses [i];
887 gboolean filtered = FALSE;
890 if (ei->try_start < MONO_CONTEXT_GET_IP (ctx) &&
891 MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) {
893 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) ||
894 (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) {
895 g_assert (ji->exvar_offset);
896 *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj;
897 if (!initialStackTrace &&
899 mono_ex->stack_trace = mono_string_new (domain, traceStr->str);
903 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
904 filtered = call_filter (ctx, ei->data.filter, obj);
906 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) &&
907 (mono_object_isinst (obj, ei->data.catch_class)) ||
911 trace_ips = g_list_reverse (trace_ips);
912 mono_ex->trace_ips = glist_to_array (trace_ips);
914 g_list_free (trace_ips);
917 g_string_free (traceStr, TRUE);
922 if (mono_jit_trace_calls != NULL)
923 g_print ("EXCEPTION: catch found at clause %d of %s - caught at %p with sp %p\n",
924 i, mono_method_full_name (ji->method, TRUE),
926 MONO_CONTEXT_GET_BP(ctx));
927 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
931 g_string_free (traceStr, TRUE);
935 if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
936 MONO_CONTEXT_GET_IP (ctx) < ei->try_end &&
937 (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
938 if (mono_jit_trace_calls != NULL)
939 g_print ("EXCEPTION: finally clause %d of %s handled at: %p using sp: %p\n",
940 i, mono_method_full_name (ji->method, TRUE),
942 MONO_CONTEXT_GET_BP(ctx));
943 call_filter (ctx, ei->handler_start, NULL);
955 if ((ji == (gpointer)-1) ||
956 (MONO_CONTEXT_GET_BP (ctx) >= jit_tls->end_of_stack)) {
959 jit_tls->abort_func (obj);
960 g_assert_not_reached ();
963 trace_ips = g_list_reverse (trace_ips);
964 mono_ex->trace_ips = glist_to_array (trace_ips);
966 g_list_free (trace_ips);
968 g_string_free (traceStr, TRUE);
974 g_assert_not_reached ();
977 /*========================= End of Function ========================*/
979 /*------------------------------------------------------------------*/
981 /* Name - mono_arch_ip_from_context */
983 /* Function - Return the instruction pointer from the context. */
985 /* Parameters - sigctx - Saved processor state */
987 /*------------------------------------------------------------------*/
990 mono_arch_ip_from_context (void *sigctx)
992 return context_get_ip (sigctx);
996 /*========================= End of Function ========================*/
998 /*------------------------------------------------------------------*/
1000 /* Name - mono_arch_is_int_overflow */
1002 /* Function - Inspect the code that raised the SIGFPE signal */
1003 /* to see if the DivideByZero or Arithmetic exception*/
1004 /* should be raised. */
1006 /*------------------------------------------------------------------*/
1009 mono_arch_is_int_overflow (void *uc, void *info)
1014 gboolean arithExc = TRUE;
1018 ctx = (MonoContext *) uc;
1019 code = (guint8 *) ((siginfo_t *)info)->si_addr;
1020 /*----------------------------------------------------------*/
1021 /* Divide operations are the only ones that will give the */
1022 /* divide by zero exception so just check for these ops. */
1023 /*----------------------------------------------------------*/
1025 case 0x1d : /* Divide Register */
1026 regNo = code[1] & 0x0f;
1027 if (ctx->uc_mcontext.gregs[regNo] == 0)
1030 case 0x5d : /* Divide */
1031 regNo = (code[2] & 0xf0 >> 8);
1032 offset = *((guint16 *) code+2) & 0x0fff;
1033 operand = ctx->uc_mcontext.gregs[regNo] + offset;
1037 case 0xb9 : /* Divide logical Register? */
1038 if (code[1] == 0x97) {
1039 regNo = (code[2] & 0xf0 >> 8);
1040 if (ctx->uc_mcontext.gregs[regNo] == 0)
1044 case 0xe3 : /* Divide logical? */
1045 if (code[1] == 0x97) {
1046 regNo = (code[2] & 0xf0 >> 8);
1047 offset = *((guint32 *) code+1) & 0x000fffff;
1048 operand = ctx->uc_mcontext.gregs[regNo] + offset;
1059 /*========================= End of Function ========================*/