- MonoContext *ctx = uc;
- MonoDomain *domain = mono_domain_get ();
- MonoJitInfo *ji, rji;
- static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL;
- MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
- MonoLMF *lmf = jit_tls->lmf;
- GList *trace_ips = NULL;
- GString *traceStr = NULL;
- MonoException *mono_ex;
- MonoString *initialStackTrace = NULL;
- int frameCount = 0;
-
- g_assert (ctx != NULL);
- memset(&rji, 0, sizeof(rji));
- 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);
- }
- }
-
- memset (&rji, 0, sizeof(rji));
-
- while (1) {
- MonoContext new_ctx;
- char *trace = NULL;
- gboolean needTrace = FALSE;
-
- if (test_only && (frameCount < 1000)) {
- needTrace = TRUE;
- if (!traceStr)
- traceStr = g_string_new ("");
- }
-
- ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &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) {
- frameCount++;
-
- if ((test_only) &&
- (ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) &&
- (mono_ex)) {
- if (!initialStackTrace && (frameCount < 1000)) {
- trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
- g_string_append (traceStr, trace);
- g_string_append_c (traceStr, '\n');
- }
- }
-
- if (ji->num_clauses) {
- int i;
-
- g_assert (ji->clauses);
-
- for (i = 0; i < ji->num_clauses; i++) {
- MonoJitExceptionInfo *ei = &ji->clauses [i];
- gboolean filtered = FALSE;
-
- 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)) {
- g_assert (ji->exvar_offset);
- *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj;
- if (!initialStackTrace &&
- traceStr) {
- mono_ex->stack_trace = mono_string_new (domain, traceStr->str);
- }
- }
-
- if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
- filtered = call_filter (ctx, ei->data.filter, obj);
-
- if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) &&
- (mono_object_isinst (obj, ei->data.catch_class)) ||
- (filtered)) {
- if (test_only) {
- if (mono_ex) {
- trace_ips = g_list_reverse (trace_ips);
- mono_ex->trace_ips = glist_to_array (trace_ips);
- }
- g_list_free (trace_ips);
- g_free (trace);
- if (traceStr)
- g_string_free (traceStr, TRUE);
-
- return TRUE;
- }
-
- if (mono_jit_trace_calls != NULL)
- g_print ("EXCEPTION: catch found at clause %d of %s - caught at %p with sp %p\n",
- i, mono_method_full_name (ji->method, TRUE),
- ei->handler_start,
- MONO_CONTEXT_GET_BP(ctx));
- MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
- jit_tls->lmf = lmf;
- g_free (trace);
- if (traceStr)
- g_string_free (traceStr, TRUE);
- return FALSE;
- }
-
- 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)
- g_print ("EXCEPTION: finally clause %d of %s handled at: %p using sp: %p\n",
- i, mono_method_full_name (ji->method, TRUE),
- ei->handler_start,
- MONO_CONTEXT_GET_BP(ctx));
- call_filter (ctx, ei->handler_start, NULL);
- }
-
- }
- }
+ MonoContext *ctx;
+ guint8 *code;
+ guint32 *operand;
+ gboolean arithExc = TRUE;
+ gint regNo,
+ offset;
+
+ ctx = (MonoContext *) uc;
+ code = (guint8 *) ((siginfo_t *)info)->si_addr;
+ /*----------------------------------------------------------*/
+ /* Divide operations are the only ones that will give the */
+ /* divide by zero exception so just check for these ops. */
+ /*----------------------------------------------------------*/
+ switch (code[0]) {
+ case 0x1d : /* Divide Register */
+ regNo = code[1] & 0x0f;
+ if (ctx->uc_mcontext.gregs[regNo] == 0)
+ arithExc = FALSE;
+ break;
+ case 0x5d : /* Divide */
+ regNo = (code[2] & 0xf0 >> 8);
+ offset = *((guint16 *) code+2) & 0x0fff;
+ operand = (guint32*)(ctx->uc_mcontext.gregs[regNo] + offset);
+ if (*operand == 0)
+ arithExc = FALSE;
+ break;
+ case 0xb9 : /* Divide logical Register? */
+ if (code[1] == 0x97) {
+ regNo = (code[2] & 0xf0 >> 8);
+ if (ctx->uc_mcontext.gregs[regNo] == 0)
+ arithExc = FALSE;