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)
265 static void (*restore_context) (MonoContext *);
269 memset(&ctx, 0, sizeof(ctx));
273 /* adjust eip so that it point into the call instruction */
276 for (iReg = 0; iReg < 16; iReg++) {
277 ctx.uc_mcontext.gregs[iReg] = int_regs[iReg];
278 ctx.uc_mcontext.fpregs.fprs[iReg].d = fp_regs[iReg];
279 ctx.uc_mcontext.aregs[iReg] = acc_regs[iReg];
282 ctx.uc_mcontext.fpregs.fpc = fpc;
284 MONO_CONTEXT_SET_BP (&ctx, sp);
285 MONO_CONTEXT_SET_IP (&ctx, ip);
287 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
288 MonoException *mono_ex = (MonoException*)exc;
290 mono_ex->stack_trace = NULL;
292 mono_arch_handle_exception (&ctx, exc, FALSE);
295 g_assert_not_reached ();
298 /*========================= End of Function ========================*/
300 /*------------------------------------------------------------------*/
302 /* Name - get_throw_exception_generic */
304 /* Function - Return a function pointer which can be used to */
305 /* raise exceptions. The returned function has the */
306 /* following signature: */
307 /* void (*func) (MonoException *exc); or, */
308 /* void (*func) (char *exc_name); */
310 /*------------------------------------------------------------------*/
313 get_throw_exception_generic (guint8 *start, int size,
314 int by_name, gboolean rethrow)
317 int alloc_size, pos, i, offset;
321 s390_stm (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
322 alloc_size = S390_ALIGN(S390_THROWSTACK_SIZE, S390_STACK_ALIGNMENT);
323 s390_lr (code, s390_r14, STK_BASE);
324 s390_ahi (code, STK_BASE, -alloc_size);
325 s390_st (code, s390_r14, 0, STK_BASE, 0);
327 s390_lr (code, s390_r4, s390_r2);
328 s390_bras (code, s390_r13, 6);
329 s390_word (code, mono_defaults.corlib);
330 s390_word (code, "System");
331 s390_l (code, s390_r2, 0, s390_r13, 0);
332 s390_l (code, s390_r3, 0, s390_r13, 4);
333 offset = (guint32) S390_RELATIVE(mono_exception_from_name, code);
334 s390_brasl(code, s390_r14, offset);
336 /*------------------------------------------------------*/
337 /* save the general registers on the stack */
338 /*------------------------------------------------------*/
339 s390_stm (code, s390_r0, s390_r13, STK_BASE, S390_THROWSTACK_INTREGS);
341 s390_lr (code, s390_r1, STK_BASE);
342 s390_ahi (code, s390_r1, alloc_size);
343 /*------------------------------------------------------*/
344 /* save the return address in the parameter register */
345 /*------------------------------------------------------*/
346 s390_l (code, s390_r3, 0, s390_r1, S390_RET_ADDR_OFFSET);
348 /*------------------------------------------------------*/
349 /* save the floating point registers */
350 /*------------------------------------------------------*/
351 pos = S390_THROWSTACK_FLTREGS;
352 for (i = 0; i < 16; ++i) {
353 s390_std (code, i, 0,STK_BASE, pos);
354 pos += sizeof (gdouble);
356 /*------------------------------------------------------*/
357 /* save the access registers */
358 /*------------------------------------------------------*/
359 s390_stam (code, s390_r0, s390_r15, STK_BASE, S390_THROWSTACK_ACCREGS);
361 /*------------------------------------------------------*/
362 /* call throw_exception (exc, ip, sp, gr, fr, ar) */
363 /* exc is already in place in r2 */
364 /*------------------------------------------------------*/
365 s390_lr (code, s390_r4, s390_r1); /* caller sp */
366 /*------------------------------------------------------*/
367 /* pointer to the saved int regs */
368 /*------------------------------------------------------*/
369 s390_la (code, s390_r5, 0, STK_BASE, S390_THROWSTACK_INTREGS);
370 s390_la (code, s390_r6, 0, STK_BASE, S390_THROWSTACK_FLTREGS);
371 s390_la (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCREGS);
372 s390_st (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCPRM);
373 s390_stfpc(code, STK_BASE, S390_THROWSTACK_FPCPRM);
374 s390_lhi (code, s390_r7, rethrow);
375 s390_st (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW);
376 offset = (guint32) S390_RELATIVE(throw_exception, code);
377 s390_brasl(code, s390_r14, offset);
378 /* we should never reach this breakpoint */
380 g_assert ((code - start) < size);
384 /*========================= End of Function ========================*/
386 /*------------------------------------------------------------------*/
388 /* Name - arch_get_throw_exception */
390 /* Function - Return a function pointer which can be used to */
391 /* raise exceptions. The returned function has the */
392 /* following signature: */
393 /* void (*func) (MonoException *exc); */
395 /*------------------------------------------------------------------*/
398 mono_arch_get_throw_exception (void)
400 static guint8 start [384];
401 static int inited = 0;
405 get_throw_exception_generic (start, sizeof (start), FALSE, FALSE);
410 /*========================= End of Function ========================*/
412 /*------------------------------------------------------------------*/
414 /* Name - arch_get_rethrow_exception */
416 /* Function - Return a function pointer which can be used to */
417 /* raise exceptions. The returned function has the */
418 /* following signature: */
419 /* void (*func) (MonoException *exc); */
421 /*------------------------------------------------------------------*/
424 mono_arch_get_rethrow_exception (void)
426 static guint8 start [384];
427 static int inited = 0;
431 get_throw_exception_generic (start, sizeof (start), FALSE, TRUE);
436 /*========================= End of Function ========================*/
438 /*------------------------------------------------------------------*/
440 /* Name - arch_get_throw_exception_by_name */
442 /* Function - Return a function pointer which can be used to */
443 /* raise corlib exceptions. The return function has */
444 /* the following signature: */
445 /* void (*func) (char *exc_name); */
447 /*------------------------------------------------------------------*/
450 mono_arch_get_throw_exception_by_name (void)
452 static guint8 start [384];
453 static int inited = 0;
457 get_throw_exception_generic (start, sizeof (start), TRUE, FALSE);
462 /*========================= End of Function ========================*/
464 /*------------------------------------------------------------------*/
466 /* Name - glist_to_array */
468 /* Function - Convert a list to a mono array. */
470 /*------------------------------------------------------------------*/
473 glist_to_array (GList *list)
475 MonoDomain *domain = mono_domain_get ();
482 len = g_list_length (list);
483 res = mono_array_new (domain, mono_defaults.int_class, len);
485 for (i = 0; list; list = list->next, i++)
486 mono_array_set (res, gpointer, i, list->data);
491 /*========================= End of Function ========================*/
493 /*------------------------------------------------------------------*/
495 /* Name - mono_arch_find_jit_info */
497 /* Function - This function is used to gather informatoin from */
498 /* @ctx. It returns the MonoJitInfo of the corres- */
499 /* ponding function, unwinds one stack frame and */
500 /* stores the resulting context into @new_ctx. It */
501 /* also stores a string describing the stack location*/
502 /* into @trace (if not NULL), and modifies the @lmf */
503 /* if necessary. @native_offset returns the IP off- */
504 /* set from the start of the function or -1 if that */
505 /* informatoin is not available. */
507 /*------------------------------------------------------------------*/
510 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
511 MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx,
512 MonoContext *new_ctx, char **trace, MonoLMF **lmf,
513 int *native_offset, gboolean *managed)
516 gpointer ip = MONO_CONTEXT_GET_IP (ctx);
519 MonoS390StackFrame *sframe;
522 (ip > prev_ji->code_start &&
523 ((guint8 *) ip < ((guint8 *) prev_ji->code_start) + prev_ji->code_size)))
526 ji = mono_jit_info_table_find (domain, ip);
538 char *source_location, *tmpaddr, *fname;
539 gint32 address, iloffset;
544 if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
545 /* remove any unused lmf */
546 *lmf = (*lmf)->previous_lmf;
549 address = (char *)ip - (char *)ji->code_start;
552 *native_offset = address;
555 if (!ji->method->wrapper_type)
559 source_location = mono_debug_source_location_from_address (ji->method, address, NULL, domain);
560 iloffset = mono_debug_il_offset_from_address (ji->method, address, domain);
563 tmpaddr = g_strdup_printf ("<0x%08x>", address);
565 tmpaddr = g_strdup_printf ("[0x%08x]", iloffset);
567 fname = mono_method_full_name (ji->method, TRUE);
570 *trace = g_strdup_printf ("in %s (at %s) %s", tmpaddr, source_location, fname);
572 *trace = g_strdup_printf ("in %s %s", tmpaddr, fname);
575 g_free (source_location);
578 sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_BP (ctx);
579 MONO_CONTEXT_SET_BP (new_ctx, sframe->prev);
580 sframe = (MonoS390StackFrame *) sframe->prev;
581 MONO_CONTEXT_SET_IP (new_ctx, sframe->return_address);
582 memcpy (&new_ctx->uc_mcontext.gregs[6], sframe->regs, (8*sizeof(gint32)));
593 *trace = g_strdup_printf ("in (unmanaged) %s", mono_method_full_name ((*lmf)->method, TRUE));
595 if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
598 memset (res, 0, sizeof (MonoJitInfo));
599 res->method = (*lmf)->method;
602 memcpy(new_ctx->uc_mcontext.gregs, (*lmf)->gregs, sizeof((*lmf)->gregs));
603 memcpy(new_ctx->uc_mcontext.fpregs.fprs, (*lmf)->fregs, sizeof((*lmf)->fregs));
605 MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
606 MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
607 *lmf = (*lmf)->previous_lmf;
616 /*========================= End of Function ========================*/
618 /*------------------------------------------------------------------*/
620 /* Name - ves_icall_get_trace */
624 /*------------------------------------------------------------------*/
627 ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
629 MonoDomain *domain = mono_domain_get ();
631 MonoArray *ta = exc->trace_ips;
635 return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
638 len = mono_array_length (ta);
640 res = mono_array_new (domain, mono_defaults.stack_frame_class,
641 len > skip ? len - skip : 0);
643 for (i = skip; i < len; i++) {
645 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
646 gpointer ip = mono_array_get (ta, gpointer, i);
648 ji = mono_jit_info_table_find (domain, ip);
650 mono_array_set (res, gpointer, i, sf);
654 sf->method = mono_method_get_object (domain, ji->method, NULL);
655 sf->native_offset = (char *)ip - (char *)ji->code_start;
657 sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
659 if (need_file_info) {
662 filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
664 sf->filename = filename? mono_string_new (domain, filename): NULL;
670 mono_array_set (res, gpointer, i, sf);
676 /*========================= End of Function ========================*/
678 /*------------------------------------------------------------------*/
680 /* Name - mono_jit_walk_stack */
684 /*------------------------------------------------------------------*/
687 mono_jit_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data) {
688 MonoDomain *domain = mono_domain_get ();
689 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
690 MonoLMF *lmf = jit_tls->lmf;
691 MonoJitInfo *ji, rji;
692 gint native_offset, il_offset;
694 MonoContext ctx, new_ctx;
696 MONO_CONTEXT_SET_IP (&ctx, __builtin_return_address (0));
697 MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (1));
699 while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) {
701 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL,
702 &ctx, &new_ctx, NULL, &lmf,
703 &native_offset, &managed);
706 if (ji == (gpointer)-1)
709 il_offset = do_il_offset ? mono_debug_il_offset_from_address (ji->method, native_offset, domain): -1;
711 if (func (ji->method, native_offset, il_offset, managed, user_data))
718 /*========================= End of Function ========================*/
720 /*------------------------------------------------------------------*/
722 /* Name - ves_icall_get_frame_info */
726 /*------------------------------------------------------------------*/
729 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
730 MonoReflectionMethod **method,
731 gint32 *iloffset, gint32 *native_offset,
732 MonoString **file, gint32 *line, gint32 *column)
734 MonoDomain *domain = mono_domain_get ();
735 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
736 MonoLMF *lmf = jit_tls->lmf;
737 MonoJitInfo *ji, rji;
738 MonoContext ctx, new_ctx;
740 MONO_CONTEXT_SET_IP (&ctx, ves_icall_get_frame_info);
741 MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (0));
746 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL,
747 &ctx, &new_ctx, NULL, &lmf,
748 native_offset, NULL);
752 if (!ji || ji == (gpointer)-1 || MONO_CONTEXT_GET_BP (&ctx) >= jit_tls->end_of_stack)
755 /* skip all wrappers ??*/
756 if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
757 ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
758 ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
759 ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
760 ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
767 *method = mono_method_get_object (domain, ji->method, NULL);
768 *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset, domain);
770 if (need_file_info) {
773 filename = mono_debug_source_location_from_address (ji->method, *native_offset, line, domain);
775 *file = filename? mono_string_new (domain, filename): NULL;
784 /*========================= End of Function ========================*/
786 /*------------------------------------------------------------------*/
788 /* Name - mono_arch_handle_exception */
790 /* Function - Handle an exception raised by the JIT code. */
792 /* Parameters - ctx - Saved processor state */
793 /* obj - The exception object */
794 /* test_only - Only test if the exception is caught, */
795 /* but don't call handlers */
797 /*------------------------------------------------------------------*/
800 mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only)
802 MonoContext *ctx = uc;
803 MonoDomain *domain = mono_domain_get ();
804 MonoJitInfo *ji, rji;
805 static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL;
806 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
807 MonoLMF *lmf = jit_tls->lmf;
808 GList *trace_ips = NULL;
809 GString *traceStr = NULL;
810 MonoException *mono_ex;
811 MonoString *initialStackTrace = NULL;
814 g_assert (ctx != NULL);
815 memset(&rji, 0, sizeof(rji));
817 MonoException *ex = mono_get_exception_null_reference ();
818 ex->message = mono_string_new (domain,
819 "Object reference not set to an instance of an object");
820 obj = (MonoObject *)ex;
823 if (mono_object_isinst (obj, mono_defaults.exception_class)) {
824 mono_ex = (MonoException*)obj;
825 mono_ex->stack_trace = NULL;
832 call_filter = arch_get_call_filter ();
834 g_assert (jit_tls->end_of_stack);
835 g_assert (jit_tls->abort_func);
838 MonoContext ctx_cp = *ctx;
839 if (mono_jit_trace_calls != NULL)
840 g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
841 if (!mono_arch_handle_exception (&ctx_cp, obj, TRUE)) {
842 if (mono_break_on_exc)
844 mono_unhandled_exception (obj);
848 memset (&rji, 0, sizeof(rji));
853 gboolean needTrace = FALSE;
855 if (test_only && (frameCount < 1000)) {
858 traceStr = g_string_new ("");
861 ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx,
862 test_only ? &trace : NULL, &lmf, NULL, NULL);
864 g_warning ("Exception inside function without unwind info");
865 g_assert_not_reached ();
868 if (ji != (gpointer)-1) {
872 (ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) &&
874 if (!initialStackTrace && (frameCount < 1000)) {
875 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
876 g_string_append (traceStr, trace);
877 g_string_append_c (traceStr, '\n');
881 if (ji->num_clauses) {
884 g_assert (ji->clauses);
886 for (i = 0; i < ji->num_clauses; i++) {
887 MonoJitExceptionInfo *ei = &ji->clauses [i];
888 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);