X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-x86.c;h=39412d20cd35ec58603aacfd1a6cfe42ae53ecc6;hb=2621a9329557531206012c6a860e75048655bd15;hp=4a35c4b75ca3cfc8af533e4f37c1d087171431a2;hpb=6c06cfbe2e74125fde73028ded7a9a02fbdbf53f;p=mono.git diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index 4a35c4b75ca..39412d20cd3 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -18,53 +18,13 @@ #include #include #include +#include #include #include "mini.h" #include "mini-x86.h" #ifdef PLATFORM_WIN32 - -#include - -/* use SIG* defines if possible */ -#ifdef HAVE_SIGNAL_H -#include -#endif - -/* sigcontext surrogate */ -struct sigcontext { - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - unsigned int ebp; - unsigned int esp; - unsigned int esi; - unsigned int edi; - unsigned int eip; -}; - - -typedef void (* MonoW32ExceptionHandler) (int); -void win32_seh_init(void); -void win32_seh_cleanup(void); -void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler); - -#ifndef SIGFPE -#define SIGFPE 4 -#endif - -#ifndef SIGILL -#define SIGILL 8 -#endif - -#ifndef SIGSEGV -#define SIGSEGV 11 -#endif - -LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep); - static MonoW32ExceptionHandler fpe_handler; static MonoW32ExceptionHandler ill_handler; static MonoW32ExceptionHandler segv_handler; @@ -164,37 +124,6 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) #endif /* PLATFORM_WIN32 */ -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) -# define SC_EAX sc_eax -# define SC_EBX sc_ebx -# define SC_ECX sc_ecx -# define SC_EDX sc_edx -# define SC_EBP sc_ebp -# define SC_EIP sc_eip -# define SC_ESP sc_esp -# define SC_EDI sc_edi -# define SC_ESI sc_esi -#else -# define SC_EAX eax -# define SC_EBX ebx -# define SC_ECX ecx -# define SC_EDX edx -# define SC_EBP ebp -# define SC_EIP eip -# define SC_ESP esp -# define SC_EDI edi -# define SC_ESI esi -#endif - -gboolean mono_arch_handle_exception (struct sigcontext *ctx, gpointer obj, gboolean test_only); - -typedef struct sigcontext MonoContext; - -#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->SC_EIP = (long)ip; } while (0); -#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->SC_EBP = (long)bp; } while (0); - -#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->SC_EIP)) -#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->SC_EBP)) #ifdef MONO_USE_EXC_TABLES @@ -461,12 +390,12 @@ x86_unwind_native_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, struct sig #endif /* - * arch_get_restore_context: + * mono_arch_get_restore_context: * * Returns a pointer to a method which restores a previously saved sigcontext. */ -static gpointer -arch_get_restore_context (void) +gpointer +mono_arch_get_restore_context (void) { static guint8 *start = NULL; guint8 *code; @@ -502,14 +431,14 @@ arch_get_restore_context (void) } /* - * arch_get_call_filter: + * mono_arch_get_call_filter: * * Returns a pointer to a method which calls an exception filter. We * also use this function to call finally handlers (we pass NULL as * @exc object in this case). */ -static gpointer -arch_get_call_filter (void) +gpointer +mono_arch_get_call_filter (void) { static guint8 start [64]; static int inited = 0; @@ -568,7 +497,7 @@ throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsign struct sigcontext ctx; if (!restore_context) - restore_context = arch_get_restore_context (); + restore_context = mono_arch_get_restore_context (); /* adjust eip so that it point into the call instruction */ eip -= 1; @@ -591,7 +520,7 @@ throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsign } /** - * arch_get_throw_exception: + * mono_arch_get_throw_exception: * * Returns a function pointer which can be used to raise * exceptions. The returned function has the following @@ -634,7 +563,7 @@ mono_arch_get_throw_exception (void) } /** - * arch_get_throw_exception_by_name: + * mono_arch_get_throw_exception_by_name: * * Returns a function pointer which can be used to raise * corlib exceptions. The returned function has the following @@ -670,25 +599,6 @@ mono_arch_get_throw_exception_by_name (void) g_assert ((code - start) < 32); return start; -} - -static MonoArray * -glist_to_array (GList *list) -{ - MonoDomain *domain = mono_domain_get (); - MonoArray *res; - int len, i; - - if (!list) - return NULL; - - len = g_list_length (list); - res = mono_array_new (domain, mono_defaults.int_class, len); - - for (i = 0; list; list = list->next, i++) - mono_array_set (res, gpointer, i, list->data); - - return res; } /* mono_arch_find_jit_info: @@ -700,15 +610,19 @@ glist_to_array (GList *list) * the @lmf if necessary. @native_offset return the IP offset from the * start of the function or -1 if that info is not available. */ -static MonoJitInfo * -mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoContext *ctx, +MonoJitInfo * +mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset, gboolean *managed) { MonoJitInfo *ji; gpointer ip = MONO_CONTEXT_GET_IP (ctx); - ji = mono_jit_info_table_find (domain, ip); + /* Avoid costly table lookup during stack overflow */ + if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size))) + ji = prev_ji; + else + ji = mono_jit_info_table_find (domain, ip); if (trace) *trace = NULL; @@ -841,292 +755,14 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf return NULL; } -MonoArray * -ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info) -{ - MonoDomain *domain = mono_domain_get (); - MonoArray *res; - MonoArray *ta = exc->trace_ips; - int i, len; - - if (ta == NULL) { - /* Exception is not thrown yet */ - return mono_array_new (domain, mono_defaults.stack_frame_class, 0); - } - - len = mono_array_length (ta); - - res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0); - - for (i = skip; i < len; i++) { - MonoJitInfo *ji; - MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class); - gpointer ip = mono_array_get (ta, gpointer, i); - - ji = mono_jit_info_table_find (domain, ip); - if (ji == NULL) { - /* Unmanaged frame */ - mono_array_set (res, gpointer, i, sf); - continue; - } - - g_assert (ji != NULL); - - sf->method = mono_method_get_object (domain, ji->method, NULL); - sf->native_offset = (char *)ip - (char *)ji->code_start; - - sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain); - - if (need_file_info) { - gchar *filename; - - filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain); - - sf->filename = filename? mono_string_new (domain, filename): NULL; - sf->column = 0; - - g_free (filename); - } - - mono_array_set (res, gpointer, i, sf); - } - - return res; -} - -void -mono_jit_walk_stack (MonoStackWalk func, gpointer user_data) { - MonoDomain *domain = mono_domain_get (); - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); - MonoLMF *lmf = jit_tls->lmf; - MonoJitInfo *ji, rji; - gint native_offset, il_offset; - gboolean managed; - - MonoContext ctx, new_ctx; - - MONO_CONTEXT_SET_IP (&ctx, __builtin_return_address (0)); - MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (1)); - - while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) { - - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed); - g_assert (ji); - - if (ji == (gpointer)-1) - return; - - il_offset = mono_debug_il_offset_from_address (ji->method, native_offset, domain); - - if (func (ji->method, native_offset, il_offset, managed, user_data)) - return; - - ctx = new_ctx; - } -} - -MonoBoolean -ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, - MonoReflectionMethod **method, - gint32 *iloffset, gint32 *native_offset, - MonoString **file, gint32 *line, gint32 *column) -{ - MonoDomain *domain = mono_domain_get (); - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); - MonoLMF *lmf = jit_tls->lmf; - MonoJitInfo *ji, rji; - MonoContext ctx, new_ctx; - - MONO_CONTEXT_SET_IP (&ctx, ves_icall_get_frame_info); - MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (0)); - - skip++; - - do { - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL); - - ctx = new_ctx; - - if (!ji || ji == (gpointer)-1 || MONO_CONTEXT_GET_BP (&ctx) >= jit_tls->end_of_stack) - return FALSE; - - /* skip all wrappers ??*/ - if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE || - ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK || - ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) - continue; - - skip--; - - } while (skip >= 0); - - *method = mono_method_get_object (domain, ji->method, NULL); - *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset, domain); - - if (need_file_info) { - gchar *filename; - - filename = mono_debug_source_location_from_address (ji->method, *native_offset, line, domain); - - *file = filename? mono_string_new (domain, filename): NULL; - *column = 0; - - g_free (filename); - } - - return TRUE; -} - /** - * arch_handle_exception: + * mono_arch_handle_exception: + * * @ctx: saved processor state * @obj: the exception object - * @test_only: only test if the exception is caught, but dont call handlers - * - * */ gboolean -mono_arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only) +mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { - MonoDomain *domain = mono_domain_get (); - MonoJitInfo *ji, rji; - static int (*call_filter) (MonoContext *, gpointer) = NULL; - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); - MonoLMF *lmf = jit_tls->lmf; - GList *trace_ips = NULL; - MonoException *mono_ex; - - g_assert (ctx != NULL); - if (!obj) { - MonoException *ex = mono_get_exception_null_reference (); - ex->message = mono_string_new (domain, - "Object reference not set to an instance of an object"); - obj = (MonoObject *)ex; - } - - if (mono_object_isinst (obj, mono_defaults.exception_class)) { - mono_ex = (MonoException*)obj; - mono_ex->stack_trace = NULL; - } else { - mono_ex = NULL; - } - - if (!call_filter) - call_filter = arch_get_call_filter (); - - g_assert (jit_tls->end_of_stack); - g_assert (jit_tls->abort_func); - - if (!test_only) { - MonoContext ctx_cp = *ctx; - if (mono_jit_trace_calls != NULL) - g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name); - if (!mono_arch_handle_exception (&ctx_cp, obj, TRUE)) { - if (mono_break_on_exc) - G_BREAKPOINT (); - mono_unhandled_exception (obj); - } - } - - while (1) { - MonoContext new_ctx; - char *trace = NULL; - - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, ctx, &new_ctx, - test_only ? &trace : NULL, &lmf, NULL, NULL); - if (!ji) { - g_warning ("Exception inside function without unwind info"); - g_assert_not_reached (); - } - - if (ji != (gpointer)-1) { - - if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) { - char *tmp, *strace; - - trace_ips = g_list_append (trace_ips, MONO_CONTEXT_GET_IP (ctx)); - - if (!mono_ex->stack_trace) - strace = g_strdup (""); - else - strace = mono_string_to_utf8 (mono_ex->stack_trace); - - tmp = g_strdup_printf ("%s%s\n", strace, trace); - g_free (strace); - - mono_ex->stack_trace = mono_string_new (domain, tmp); - - g_free (tmp); - } - - if (ji->num_clauses) { - int i; - - g_assert (ji->clauses); - - for (i = 0; i < ji->num_clauses; i++) { - MonoJitExceptionInfo *ei = &ji->clauses [i]; - - if (ei->try_start <= MONO_CONTEXT_GET_IP (ctx) && - MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) { - /* catch block */ - - if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) { - /* store the exception object int cfg->excvar */ - g_assert (ji->exvar_offset); - *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj; - } - - if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && - mono_object_isinst (obj, mono_class_get (ji->method->klass->image, ei->data.token))) || - ((ei->flags == MONO_EXCEPTION_CLAUSE_FILTER && - call_filter (ctx, ei->data.filter)))) { - if (test_only) { - if (mono_ex) - mono_ex->trace_ips = glist_to_array (trace_ips); - g_list_free (trace_ips); - g_free (trace); - return TRUE; - } - if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method)) - g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE)); - MONO_CONTEXT_SET_IP (ctx, ei->handler_start); - jit_tls->lmf = lmf; - g_free (trace); - return 0; - } - if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) && - MONO_CONTEXT_GET_IP (ctx) < ei->try_end && - (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) { - if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method)) - g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE)); - call_filter (ctx, ei->handler_start); - } - - } - } - } - } - - g_free (trace); - - *ctx = new_ctx; - - if ((ji == (gpointer)-1) || MONO_CONTEXT_GET_BP (ctx) >= jit_tls->end_of_stack) { - if (!test_only) { - jit_tls->lmf = lmf; - jit_tls->abort_func (obj); - g_assert_not_reached (); - } else { - if (mono_ex) - mono_ex->trace_ips = glist_to_array (trace_ips); - g_list_free (trace_ips); - return FALSE; - } - } - } - - g_assert_not_reached (); + return mono_handle_exception (sigctx, obj, test_only); } - -