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_INTREGS S390_THROWSTACK_FPCPRM+sizeof(gulong)
46 #define S390_THROWSTACK_FLTREGS S390_THROWSTACK_INTREGS+(16*sizeof(gulong))
47 #define S390_THROWSTACK_ACCREGS S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble))
48 #define S390_THROWSTACK_SIZE (S390_THROWSTACK_ACCREGS+(16*sizeof(gulong)))
50 /*========================= End of Defines =========================*/
52 /*------------------------------------------------------------------*/
54 /*------------------------------------------------------------------*/
62 #include <mono/arch/s390/s390-codegen.h>
63 #include <mono/metadata/appdomain.h>
64 #include <mono/metadata/tabledefs.h>
65 #include <mono/metadata/threads.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/exception.h>
68 #include <mono/metadata/mono-debug.h>
71 #include "mini-s390.h"
73 /*========================= End of Includes ========================*/
75 /*------------------------------------------------------------------*/
77 /*------------------------------------------------------------------*/
87 /*========================= End of Typedefs ========================*/
89 /*------------------------------------------------------------------*/
90 /* P r o t o t y p e s */
91 /*------------------------------------------------------------------*/
93 gboolean
mono_arch_handle_exception (void *ctx
,
97 /*========================= End of Prototypes ======================*/
99 /*------------------------------------------------------------------*/
100 /* G l o b a l V a r i a b l e s */
101 /*------------------------------------------------------------------*/
103 /*====================== End of Global Variables ===================*/
105 /*------------------------------------------------------------------*/
107 /* Name - context_get_ip */
109 /* Function - Extract the current instruction address from the */
112 /*------------------------------------------------------------------*/
114 static inline gpointer
115 context_get_ip (MonoContext
*ctx
)
119 ip
= (gpointer
) ((gint32
) (ctx
->uc_mcontext
.psw
.addr
) & 0x7fffffff);
123 /*========================= End of Function ========================*/
125 /*------------------------------------------------------------------*/
127 /* Name - mono_arch_has_unwind_info */
129 /* Function - Tests if a function has a DWARF exception table */
130 /* that is able to restore all caller saved registers*/
132 /*------------------------------------------------------------------*/
135 mono_arch_has_unwind_info (gconstpointer addr
)
140 /*========================= End of Function ========================*/
142 /*------------------------------------------------------------------*/
144 /* Name - arch_get_call_filter */
146 /* Function - Return a pointer to a method which calls an */
147 /* exception filter. We also use this function to */
148 /* call finally handlers (we pass NULL as @exc */
149 /* object in this case). */
151 /*------------------------------------------------------------------*/
154 arch_get_call_filter (void)
156 static guint8 start
[512];
157 static int inited
= 0;
159 int alloc_size
, pos
, i
;
165 /* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */
168 s390_stm (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
169 s390_lr (code
, s390_r14
, STK_BASE
);
170 alloc_size
= S390_ALIGN(S390_CALLFILTER_SIZE
, S390_STACK_ALIGNMENT
);
171 s390_ahi (code
, STK_BASE
, -alloc_size
);
172 s390_st (code
, s390_r14
, 0, STK_BASE
, 0);
174 /*------------------------------------------------------*/
175 /* save general registers on stack */
176 /*------------------------------------------------------*/
177 s390_stm (code
, s390_r0
, s390_r13
, STK_BASE
, S390_CALLFILTER_INTREGS
);
179 /*------------------------------------------------------*/
180 /* save floating point registers on stack */
181 /*------------------------------------------------------*/
182 // pos = S390_CALLFILTER_FLTREGS;
183 // for (i = 0; i < 16; ++i) {
184 // s390_std (code, i, 0, STK_BASE, pos);
185 // pos += sizeof (gdouble);
188 /*------------------------------------------------------*/
189 /* save access registers on stack */
190 /*------------------------------------------------------*/
191 // s390_stam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS);
193 /*------------------------------------------------------*/
195 /*------------------------------------------------------*/
196 s390_lr (code
, s390_r13
, s390_r2
);
198 /*------------------------------------------------------*/
199 /* Get A(Handler Entry Point) */
200 /*------------------------------------------------------*/
201 s390_lr (code
, s390_r0
, s390_r3
);
203 /*------------------------------------------------------*/
204 /* Set parameter register with Exception */
205 /*------------------------------------------------------*/
206 s390_lr (code
, s390_r2
, s390_r4
);
208 /*------------------------------------------------------*/
209 /* Load all registers with values from the context */
210 /*------------------------------------------------------*/
211 s390_lm (code
, s390_r3
, s390_r12
, s390_r13
, G_STRUCT_OFFSET(MonoContext
, uc_mcontext
.gregs
[3]));
212 pos
= G_STRUCT_OFFSET(MonoContext
, uc_mcontext
.fpregs
.fprs
[0]);
213 for (i
= 0; i
< 16; ++i
) {
214 s390_ld (code
, i
, 0, s390_r13
, pos
);
215 pos
+= sizeof(gdouble
);
218 /*------------------------------------------------------*/
219 /* Point at the copied stack frame and call the filter */
220 /*------------------------------------------------------*/
221 s390_lr (code
, s390_r1
, s390_r0
);
222 s390_basr (code
, s390_r14
, s390_r1
);
224 /*------------------------------------------------------*/
225 /* Save return value */
226 /*------------------------------------------------------*/
227 s390_lr (code
, s390_r14
, s390_r2
);
229 /*------------------------------------------------------*/
230 /* Restore all the regs from the stack */
231 /*------------------------------------------------------*/
232 s390_lm (code
, s390_r0
, s390_r13
, STK_BASE
, S390_CALLFILTER_INTREGS
);
233 // pos = S390_CALLFILTER_FLTREGS;
234 // for (i = 0; i < 16; ++i) {
235 // s390_ld (code, i, 0, STK_BASE, pos);
236 // pos += sizeof (gdouble);
239 s390_lr (code
, s390_r2
, s390_r14
);
240 // s390_lam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS);
241 s390_ahi (code
, s390_r15
, alloc_size
);
242 s390_lm (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
243 s390_br (code
, s390_r14
);
245 g_assert ((code
- start
) < sizeof(start
));
249 /*========================= End of Function ========================*/
251 /*------------------------------------------------------------------*/
253 /* Name - throw_exception. */
255 /* Function - Raise an exception based on the parameters passed.*/
257 /*------------------------------------------------------------------*/
260 throw_exception (MonoObject
*exc
, unsigned long ip
, unsigned long sp
,
261 gulong
*int_regs
, gdouble
*fp_regs
, gulong
*acc_regs
, guint fpc
)
263 static void (*restore_context
) (MonoContext
*);
267 memset(&ctx
, 0, sizeof(ctx
));
271 /* adjust eip so that it point into the call instruction */
274 for (iReg
= 0; iReg
< 16; iReg
++) {
275 ctx
.uc_mcontext
.gregs
[iReg
] = int_regs
[iReg
];
276 ctx
.uc_mcontext
.fpregs
.fprs
[iReg
].d
= fp_regs
[iReg
];
277 ctx
.uc_mcontext
.aregs
[iReg
] = acc_regs
[iReg
];
280 ctx
.uc_mcontext
.fpregs
.fpc
= fpc
;
282 MONO_CONTEXT_SET_BP (&ctx
, sp
);
283 MONO_CONTEXT_SET_IP (&ctx
, ip
);
285 if (mono_object_isinst (exc
, mono_defaults
.exception_class
)) {
286 MonoException
*mono_ex
= (MonoException
*)exc
;
287 mono_ex
->stack_trace
= NULL
;
289 mono_arch_handle_exception (&ctx
, exc
, FALSE
);
292 g_assert_not_reached ();
295 /*========================= End of Function ========================*/
297 /*------------------------------------------------------------------*/
299 /* Name - arch_get_throw_exception_generic */
301 /* Function - Return a function pointer which can be used to */
302 /* raise exceptions. The returned function has the */
303 /* following signature: */
304 /* void (*func) (MonoException *exc); or, */
305 /* void (*func) (char *exc_name); */
307 /*------------------------------------------------------------------*/
310 mono_arch_get_throw_exception_generic (guint8
*start
, int size
, int by_name
)
313 int alloc_size
, pos
, i
, offset
;
317 s390_stm (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
318 alloc_size
= S390_ALIGN(S390_THROWSTACK_SIZE
, S390_STACK_ALIGNMENT
);
319 s390_lr (code
, s390_r14
, STK_BASE
);
320 s390_ahi (code
, STK_BASE
, -alloc_size
);
321 s390_st (code
, s390_r14
, 0, STK_BASE
, 0);
323 s390_lr (code
, s390_r4
, s390_r2
);
324 s390_bras (code
, s390_r13
, 6);
325 s390_word (code
, mono_defaults
.corlib
);
326 s390_word (code
, "System");
327 s390_l (code
, s390_r2
, 0, s390_r13
, 0);
328 s390_l (code
, s390_r3
, 0, s390_r13
, 4);
329 offset
= (guint32
) S390_RELATIVE(mono_exception_from_name
, code
);
330 s390_brasl(code
, s390_r14
, offset
);
332 /*------------------------------------------------------*/
333 /* save the general registers on the stack */
334 /*------------------------------------------------------*/
335 s390_stm (code
, s390_r0
, s390_r13
, STK_BASE
, S390_THROWSTACK_INTREGS
);
337 s390_lr (code
, s390_r1
, STK_BASE
);
338 s390_ahi (code
, s390_r1
, alloc_size
);
339 /*------------------------------------------------------*/
340 /* save the return address in the parameter register */
341 /*------------------------------------------------------*/
342 s390_l (code
, s390_r3
, 0, s390_r1
, S390_RET_ADDR_OFFSET
);
344 /*------------------------------------------------------*/
345 /* save the floating point registers */
346 /*------------------------------------------------------*/
347 pos
= S390_THROWSTACK_FLTREGS
;
348 for (i
= 0; i
< 16; ++i
) {
349 s390_std (code
, i
, 0,STK_BASE
, pos
);
350 pos
+= sizeof (gdouble
);
352 /*------------------------------------------------------*/
353 /* save the access registers */
354 /*------------------------------------------------------*/
355 s390_stam (code
, s390_r0
, s390_r15
, STK_BASE
, S390_THROWSTACK_ACCREGS
);
357 /*------------------------------------------------------*/
358 /* call throw_exception (exc, ip, sp, gr, fr, ar) */
359 /* exc is already in place in r2 */
360 /*------------------------------------------------------*/
361 s390_lr (code
, s390_r4
, s390_r1
); /* caller sp */
362 /*------------------------------------------------------*/
363 /* pointer to the saved int regs */
364 /*------------------------------------------------------*/
365 s390_la (code
, s390_r5
, 0, STK_BASE
, S390_THROWSTACK_INTREGS
);
366 s390_la (code
, s390_r6
, 0, STK_BASE
, S390_THROWSTACK_FLTREGS
);
367 s390_la (code
, s390_r7
, 0, STK_BASE
, S390_THROWSTACK_ACCREGS
);
368 s390_st (code
, s390_r7
, 0, STK_BASE
, S390_THROWSTACK_ACCPRM
);
369 s390_stfpc(code
, STK_BASE
, S390_THROWSTACK_FPCPRM
);
370 offset
= (guint32
) S390_RELATIVE(throw_exception
, code
);
371 s390_brasl(code
, s390_r14
, offset
);
372 /* we should never reach this breakpoint */
374 g_assert ((code
- start
) < size
);
378 /*========================= End of Function ========================*/
380 /*------------------------------------------------------------------*/
382 /* Name - arch_get_throw_exception */
384 /* Function - Return a function pointer which can be used to */
385 /* raise exceptions. The returned function has the */
386 /* following signature: */
387 /* void (*func) (MonoException *exc); */
389 /*------------------------------------------------------------------*/
392 mono_arch_get_throw_exception (void)
394 static guint8 start
[256];
395 static int inited
= 0;
399 mono_arch_get_throw_exception_generic (start
, sizeof (start
), FALSE
);
404 /*========================= End of Function ========================*/
406 /*------------------------------------------------------------------*/
408 /* Name - arch_get_throw_exception_by_name */
410 /* Function - Return a function pointer which can be used to */
411 /* raise corlib exceptions. The return function has */
412 /* the following signature: */
413 /* void (*func) (char *exc_name); */
415 /*------------------------------------------------------------------*/
418 mono_arch_get_throw_exception_by_name (void)
420 static guint8 start
[160];
421 static int inited
= 0;
425 mono_arch_get_throw_exception_generic (start
, sizeof (start
), TRUE
);
430 /*========================= End of Function ========================*/
432 /*------------------------------------------------------------------*/
434 /* Name - glist_to_array */
436 /* Function - Convert a list to a mono array. */
438 /*------------------------------------------------------------------*/
441 glist_to_array (GList
*list
)
443 MonoDomain
*domain
= mono_domain_get ();
450 len
= g_list_length (list
);
451 res
= mono_array_new (domain
, mono_defaults
.int_class
, len
);
453 for (i
= 0; list
; list
= list
->next
, i
++)
454 mono_array_set (res
, gpointer
, i
, list
->data
);
459 /*========================= End of Function ========================*/
461 /*------------------------------------------------------------------*/
463 /* Name - mono_arch_find_jit_info */
465 /* Function - This function is used to gather informatoin from */
466 /* @ctx. It returns the MonoJitInfo of the corres- */
467 /* ponding function, unwinds one stack frame and */
468 /* stores the resulting context into @new_ctx. It */
469 /* also stores a string describing the stack location*/
470 /* into @trace (if not NULL), and modifies the @lmf */
471 /* if necessary. @native_offset returns the IP off- */
472 /* set from the start of the function or -1 if that */
473 /* informatoin is not available. */
475 /*------------------------------------------------------------------*/
478 mono_arch_find_jit_info (MonoDomain
*domain
, MonoJitTlsData
*jit_tls
,
479 MonoJitInfo
*res
, MonoJitInfo
*prev_ji
, MonoContext
*ctx
,
480 MonoContext
*new_ctx
, char **trace
, MonoLMF
**lmf
,
481 int *native_offset
, gboolean
*managed
)
484 gpointer ip
= MONO_CONTEXT_GET_IP (ctx
);
487 MonoS390StackFrame
*sframe
;
490 (ip
> prev_ji
->code_start
&&
491 ((guint8
*) ip
< ((guint8
*) prev_ji
->code_start
) + prev_ji
->code_size
)))
494 ji
= mono_jit_info_table_find (domain
, ip
);
506 char *source_location
, *tmpaddr
, *fname
;
507 gint32 address
, iloffset
;
512 if (*lmf
&& (MONO_CONTEXT_GET_BP (ctx
) >= (gpointer
)(*lmf
)->ebp
)) {
513 /* remove any unused lmf */
514 *lmf
= (*lmf
)->previous_lmf
;
517 address
= (char *)ip
- (char *)ji
->code_start
;
520 *native_offset
= address
;
523 if (!ji
->method
->wrapper_type
)
527 source_location
= mono_debug_source_location_from_address (ji
->method
, address
, NULL
, domain
);
528 iloffset
= mono_debug_il_offset_from_address (ji
->method
, address
, domain
);
531 tmpaddr
= g_strdup_printf ("<0x%08x>", address
);
533 tmpaddr
= g_strdup_printf ("[0x%08x]", iloffset
);
535 fname
= mono_method_full_name (ji
->method
, TRUE
);
538 *trace
= g_strdup_printf ("in %s (at %s) %s", tmpaddr
, source_location
, fname
);
540 *trace
= g_strdup_printf ("in %s %s", tmpaddr
, fname
);
543 g_free (source_location
);
546 sframe
= (MonoS390StackFrame
*) MONO_CONTEXT_GET_BP (ctx
);
547 MONO_CONTEXT_SET_BP (new_ctx
, sframe
->prev
);
548 sframe
= (MonoS390StackFrame
*) sframe
->prev
;
549 MONO_CONTEXT_SET_IP (new_ctx
, sframe
->return_address
);
550 memcpy (&new_ctx
->uc_mcontext
.gregs
[6], sframe
->regs
, (8*sizeof(gint32
)));
561 *trace
= g_strdup_printf ("in (unmanaged) %s", mono_method_full_name ((*lmf
)->method
, TRUE
));
563 if ((ji
= mono_jit_info_table_find (domain
, (gpointer
)(*lmf
)->eip
))) {
566 memset (res
, 0, sizeof (MonoJitInfo
));
567 res
->method
= (*lmf
)->method
;
570 memcpy(new_ctx
->uc_mcontext
.gregs
, (*lmf
)->gregs
, sizeof((*lmf
)->gregs
));
571 memcpy(new_ctx
->uc_mcontext
.fpregs
.fprs
, (*lmf
)->fregs
, sizeof((*lmf
)->fregs
));
573 MONO_CONTEXT_SET_BP (new_ctx
, (*lmf
)->ebp
);
574 MONO_CONTEXT_SET_IP (new_ctx
, (*lmf
)->eip
);
575 *lmf
= (*lmf
)->previous_lmf
;
584 /*========================= End of Function ========================*/
586 /*------------------------------------------------------------------*/
588 /* Name - ves_icall_get_trace */
592 /*------------------------------------------------------------------*/
595 ves_icall_get_trace (MonoException
*exc
, gint32 skip
, MonoBoolean need_file_info
)
597 MonoDomain
*domain
= mono_domain_get ();
599 MonoArray
*ta
= exc
->trace_ips
;
603 return mono_array_new (domain
, mono_defaults
.stack_frame_class
, 0);
606 len
= mono_array_length (ta
);
608 res
= mono_array_new (domain
, mono_defaults
.stack_frame_class
,
609 len
> skip
? len
- skip
: 0);
611 for (i
= skip
; i
< len
; i
++) {
613 MonoStackFrame
*sf
= (MonoStackFrame
*)mono_object_new (domain
, mono_defaults
.stack_frame_class
);
614 gpointer ip
= mono_array_get (ta
, gpointer
, i
);
616 ji
= mono_jit_info_table_find (domain
, ip
);
618 mono_array_set (res
, gpointer
, i
, sf
);
622 sf
->method
= mono_method_get_object (domain
, ji
->method
, NULL
);
623 sf
->native_offset
= (char *)ip
- (char *)ji
->code_start
;
625 sf
->il_offset
= mono_debug_il_offset_from_address (ji
->method
, sf
->native_offset
, domain
);
627 if (need_file_info
) {
630 filename
= mono_debug_source_location_from_address (ji
->method
, sf
->native_offset
, &sf
->line
, domain
);
632 sf
->filename
= filename
? mono_string_new (domain
, filename
): NULL
;
638 mono_array_set (res
, gpointer
, i
, sf
);
644 /*========================= End of Function ========================*/
646 /*------------------------------------------------------------------*/
648 /* Name - mono_jit_walk_stack */
652 /*------------------------------------------------------------------*/
655 mono_jit_walk_stack (MonoStackWalk func
, gboolean do_il_offset
, gpointer user_data
) {
656 MonoDomain
*domain
= mono_domain_get ();
657 MonoJitTlsData
*jit_tls
= TlsGetValue (mono_jit_tls_id
);
658 MonoLMF
*lmf
= jit_tls
->lmf
;
659 MonoJitInfo
*ji
, rji
;
660 gint native_offset
, il_offset
;
662 MonoContext ctx
, new_ctx
;
664 MONO_CONTEXT_SET_IP (&ctx
, __builtin_return_address (0));
665 MONO_CONTEXT_SET_BP (&ctx
, __builtin_frame_address (1));
667 while (MONO_CONTEXT_GET_BP (&ctx
) < jit_tls
->end_of_stack
) {
669 ji
= mono_arch_find_jit_info (domain
, jit_tls
, &rji
, NULL
,
670 &ctx
, &new_ctx
, NULL
, &lmf
,
671 &native_offset
, &managed
);
674 if (ji
== (gpointer
)-1)
677 il_offset
= do_il_offset
? mono_debug_il_offset_from_address (ji
->method
, native_offset
, domain
): -1;
679 if (func (ji
->method
, native_offset
, il_offset
, managed
, user_data
))
686 /*========================= End of Function ========================*/
688 /*------------------------------------------------------------------*/
690 /* Name - ves_icall_get_frame_info */
694 /*------------------------------------------------------------------*/
697 ves_icall_get_frame_info (gint32 skip
, MonoBoolean need_file_info
,
698 MonoReflectionMethod
**method
,
699 gint32
*iloffset
, gint32
*native_offset
,
700 MonoString
**file
, gint32
*line
, gint32
*column
)
702 MonoDomain
*domain
= mono_domain_get ();
703 MonoJitTlsData
*jit_tls
= TlsGetValue (mono_jit_tls_id
);
704 MonoLMF
*lmf
= jit_tls
->lmf
;
705 MonoJitInfo
*ji
, rji
;
706 MonoContext ctx
, new_ctx
;
708 MONO_CONTEXT_SET_IP (&ctx
, ves_icall_get_frame_info
);
709 MONO_CONTEXT_SET_BP (&ctx
, __builtin_frame_address (0));
714 ji
= mono_arch_find_jit_info (domain
, jit_tls
, &rji
, NULL
,
715 &ctx
, &new_ctx
, NULL
, &lmf
,
716 native_offset
, NULL
);
720 if (!ji
|| ji
== (gpointer
)-1 || MONO_CONTEXT_GET_BP (&ctx
) >= jit_tls
->end_of_stack
)
723 /* skip all wrappers ??*/
724 if (ji
->method
->wrapper_type
== MONO_WRAPPER_RUNTIME_INVOKE
||
725 ji
->method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
||
726 ji
->method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE
)
733 *method
= mono_method_get_object (domain
, ji
->method
, NULL
);
734 *iloffset
= mono_debug_il_offset_from_address (ji
->method
, *native_offset
, domain
);
736 if (need_file_info
) {
739 filename
= mono_debug_source_location_from_address (ji
->method
, *native_offset
, line
, domain
);
741 *file
= filename
? mono_string_new (domain
, filename
): NULL
;
750 /*========================= End of Function ========================*/
752 /*------------------------------------------------------------------*/
754 /* Name - mono_arch_handle_exception */
756 /* Function - Handle an exception raised by the JIT code. */
758 /* Parameters - ctx - Saved processor state */
759 /* obj - The exception object */
760 /* test_only - Only test if the exception is caught, */
761 /* but don't call handlers */
763 /*------------------------------------------------------------------*/
766 mono_arch_handle_exception (void *uc
, gpointer obj
, gboolean test_only
)
768 MonoContext
*ctx
= uc
;
769 MonoDomain
*domain
= mono_domain_get ();
770 MonoJitInfo
*ji
, rji
;
771 static int (*call_filter
) (MonoContext
*, gpointer
, gpointer
) = NULL
;
772 MonoJitTlsData
*jit_tls
= TlsGetValue (mono_jit_tls_id
);
773 MonoLMF
*lmf
= jit_tls
->lmf
;
774 GList
*trace_ips
= NULL
;
775 GString
*traceStr
= NULL
;
776 MonoException
*mono_ex
;
777 MonoString
*initialStackTrace
= NULL
;
780 g_assert (ctx
!= NULL
);
781 memset(&rji
, 0, sizeof(rji
));
783 MonoException
*ex
= mono_get_exception_null_reference ();
784 ex
->message
= mono_string_new (domain
,
785 "Object reference not set to an instance of an object");
786 obj
= (MonoObject
*)ex
;
789 if (mono_object_isinst (obj
, mono_defaults
.exception_class
)) {
790 mono_ex
= (MonoException
*)obj
;
791 mono_ex
->stack_trace
= NULL
;
798 call_filter
= arch_get_call_filter ();
800 g_assert (jit_tls
->end_of_stack
);
801 g_assert (jit_tls
->abort_func
);
804 MonoContext ctx_cp
= *ctx
;
805 if (mono_jit_trace_calls
!= NULL
)
806 g_print ("EXCEPTION handling: %s\n", mono_object_class (obj
)->name
);
807 if (!mono_arch_handle_exception (&ctx_cp
, obj
, TRUE
)) {
808 if (mono_break_on_exc
)
810 mono_unhandled_exception (obj
);
814 memset (&rji
, 0, sizeof(rji
));
819 gboolean needTrace
= FALSE
;
821 if (test_only
&& (frameCount
< 1000)) {
824 traceStr
= g_string_new ("");
827 ji
= mono_arch_find_jit_info (domain
, jit_tls
, &rji
, &rji
, ctx
, &new_ctx
,
828 test_only
? &trace
: NULL
, &lmf
, NULL
, NULL
);
830 g_warning ("Exception inside function without unwind info");
831 g_assert_not_reached ();
834 if (ji
!= (gpointer
)-1) {
838 (ji
->method
->wrapper_type
!= MONO_WRAPPER_RUNTIME_INVOKE
) &&
840 if (!initialStackTrace
&& (frameCount
< 1000)) {
841 trace_ips
= g_list_prepend (trace_ips
, MONO_CONTEXT_GET_IP (ctx
));
842 g_string_append (traceStr
, trace
);
843 g_string_append_c (traceStr
, '\n');
847 if (ji
->num_clauses
) {
850 g_assert (ji
->clauses
);
852 for (i
= 0; i
< ji
->num_clauses
; i
++) {
853 MonoJitExceptionInfo
*ei
= &ji
->clauses
[i
];
854 gboolean filtered
= FALSE
;
856 if (ei
->try_start
< MONO_CONTEXT_GET_IP (ctx
) &&
857 MONO_CONTEXT_GET_IP (ctx
) <= ei
->try_end
) {
859 if ((ei
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) ||
860 (ei
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)) {
861 g_assert (ji
->exvar_offset
);
862 *((gpointer
*)((char *)MONO_CONTEXT_GET_BP (ctx
) + ji
->exvar_offset
)) = obj
;
863 if (!initialStackTrace
&&
865 mono_ex
->stack_trace
= mono_string_new (domain
, traceStr
->str
);
869 if (ei
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
870 filtered
= call_filter (ctx
, ei
->data
.filter
, obj
);
872 if ((ei
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) &&
873 (mono_object_isinst (obj
, mono_class_get (ji
->method
->klass
->image
, ei
->data
.token
))) ||
877 trace_ips
= g_list_reverse (trace_ips
);
878 mono_ex
->trace_ips
= glist_to_array (trace_ips
);
880 g_list_free (trace_ips
);
883 g_string_free (traceStr
, TRUE
);
888 if (mono_jit_trace_calls
!= NULL
)
889 g_print ("EXCEPTION: catch found at clause %d of %s - caught at %p with sp %p\n",
890 i
, mono_method_full_name (ji
->method
, TRUE
),
892 MONO_CONTEXT_GET_BP(ctx
));
893 MONO_CONTEXT_SET_IP (ctx
, ei
->handler_start
);
897 g_string_free (traceStr
, TRUE
);
901 if (!test_only
&& ei
->try_start
<= MONO_CONTEXT_GET_IP (ctx
) &&
902 MONO_CONTEXT_GET_IP (ctx
) < ei
->try_end
&&
903 (ei
->flags
& MONO_EXCEPTION_CLAUSE_FINALLY
)) {
904 if (mono_jit_trace_calls
!= NULL
)
905 g_print ("EXCEPTION: finally clause %d of %s handled at: %p using sp: %p\n",
906 i
, mono_method_full_name (ji
->method
, TRUE
),
908 MONO_CONTEXT_GET_BP(ctx
));
909 call_filter (ctx
, ei
->handler_start
, NULL
);
921 if ((ji
== (gpointer
)-1) ||
922 (MONO_CONTEXT_GET_BP (ctx
) >= jit_tls
->end_of_stack
)) {
925 jit_tls
->abort_func (obj
);
926 g_assert_not_reached ();
929 trace_ips
= g_list_reverse (trace_ips
);
930 mono_ex
->trace_ips
= glist_to_array (trace_ips
);
932 g_list_free (trace_ips
);
934 g_string_free (traceStr
, TRUE
);
940 g_assert_not_reached ();
943 /*========================= End of Function ========================*/
945 /*------------------------------------------------------------------*/
947 /* Name - mono_arch_ip_from_context */
949 /* Function - Return the instruction pointer from the context. */
951 /* Parameters - sigctx - Saved processor state */
953 /*------------------------------------------------------------------*/
956 mono_arch_ip_from_context (void *sigctx
)
958 return context_get_ip (sigctx
);