* roottypes.cs: Rename from tree.cs.
[mono.git] / mono / mini / exceptions-arm.c
index 73ee578a8a562fe2be1b40f2dbbf16ed505791cb..7191c3f2fcd8210da70516ec9975bc9eb7b8fba1 100644 (file)
@@ -94,8 +94,8 @@ typedef struct ucontext {
  * Returns a pointer to a method which restores a previously saved sigcontext.
  * The first argument in r0 is the pointer to the context.
  */
-static gpointer
-arch_get_restore_context (void)
+gpointer
+mono_arch_get_restore_context (void)
 {
        guint8 *code;
        static guint8 start [128];
@@ -126,8 +126,8 @@ arch_get_restore_context (void)
  * 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 [320];
        static int inited = 0;
@@ -168,7 +168,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gulong *
        gboolean rethrow = eip & 1;
 
        if (!restore_context)
-               restore_context = arch_get_restore_context ();
+               restore_context = mono_arch_get_restore_context ();
 
        eip &= ~1; /* clear the optional rethrow bit */
        /* adjust eip so that it point into the call instruction */
@@ -187,7 +187,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gulong *
                if (!rethrow)
                        mono_ex->stack_trace = NULL;
        }
-       arch_handle_exception (&ctx, exc, FALSE);
+       mono_handle_exception (&ctx, exc, (gpointer)(eip + 4), FALSE);
        restore_context (&ctx);
        g_assert_not_reached ();
 }
@@ -220,7 +220,7 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int by_name, gbo
                code = mono_arm_emit_load_imm (code, ARMREG_R1, GPOINTER_TO_UINT ("System"));
                code = mono_arm_emit_load_imm (code, ARMREG_IP, GPOINTER_TO_UINT (mono_exception_from_name));
                ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
-               ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
+               ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_IP);
        }
 
        /* call throw_exception (exc, ip, sp, int_regs, fp_regs) */
@@ -241,7 +241,7 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int by_name, gbo
 
        code = mono_arm_emit_load_imm (code, ARMREG_IP, GPOINTER_TO_UINT (throw_exception));
        ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
-       ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
+       ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_IP);
        /* we should never reach this breakpoint */
        ARM_DBRK (code);
        g_assert ((code - start) < size);
@@ -352,13 +352,8 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
                         MonoContext *ctx, MonoContext *new_ctx, char **trace, MonoLMF **lmf,
                         int *native_offset, gboolean *managed)
 {
-       return NULL;
-}
-#if 0
        MonoJitInfo *ji;
        gpointer ip = MONO_CONTEXT_GET_IP (ctx);
-       unsigned long *ptr;
-       char *p;
 
        /* 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)))
@@ -366,121 +361,84 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
        else
                ji = mono_jit_info_table_find (domain, ip);
 
-       if (trace)
-               *trace = NULL;
-
-       if (native_offset)
-               *native_offset = -1;
-
        if (managed)
                *managed = FALSE;
 
        if (ji != NULL) {
-               char *source_location, *tmpaddr, *fname;
-               gint32 address, iloffset;
-               int offset, i;
-               gulong *ctx_regs;
+               int offset;
 
                *new_ctx = *ctx;
-               setup_context (new_ctx);
-
-               if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
-                       /* remove any unused lmf */
-                       *lmf = (*lmf)->previous_lmf;
-               }
-
-               address = (char *)ip - (char *)ji->code_start;
-
-               if (native_offset)
-                       *native_offset = address;
 
                if (managed)
                        if (!ji->method->wrapper_type)
                                *managed = TRUE;
 
-               if (trace) {
-                       source_location = mono_debug_source_location_from_address (ji->method, address, NULL, domain);
-                       iloffset = mono_debug_il_offset_from_address (ji->method, address, domain);
-
-                       if (iloffset < 0)
-                               tmpaddr = g_strdup_printf ("<0x%05x>", address);
-                       else
-                               tmpaddr = g_strdup_printf ("[0x%05x]", iloffset);
-               
-                       fname = mono_method_full_name (ji->method, TRUE);
-
-                       if (source_location)
-                               *trace = g_strdup_printf ("in %s (at %s) %s", tmpaddr, source_location, fname);
-                       else
-                               *trace = g_strdup_printf ("in %s %s", tmpaddr, fname);
-
-                       g_free (fname);
-                       g_free (source_location);
-                       g_free (tmpaddr);
-               }
-#if ARM_PORT
-               sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_BP (ctx);
-               MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
-#endif
+               /*
+                * Some managed methods like pinvoke wrappers might have save_lmf set.
+                * In this case, register save/restore code is not generated by the 
+                * JIT, so we have to restore callee saved registers from the lmf.
+                */
                if (ji->method->save_lmf) {
-#if ARM_PORT
-                       memcpy (&new_ctx->fregs, (char*)sframe->sp - sizeof (double) * MONO_SAVED_FREGS, sizeof (double) * MONO_SAVED_FREGS);
-                       memcpy (&new_ctx->regs, (char*)sframe->sp - sizeof (double) * MONO_SAVED_FREGS - sizeof (gulong) * MONO_SAVED_GREGS, sizeof (gulong) * MONO_SAVED_GREGS);
-#endif
-               } else if (ji->used_regs) {
-#if ARM_PORT
-                       /* keep updated with emit_prolog in mini-ppc.c */
-                       offset = 0;
-                       /* FIXME handle floating point args 
-                       for (i = 31; i >= 14; --i) {
-                               if (ji->used_fregs & (1 << i)) {
-                                       offset += sizeof (double);
-                                       new_ctx->fregs [i - 14] = *(gulong*)((char*)sframe->sp - offset);
-                               }
-                       }*/
-                       for (i = 31; i >= 13; --i) {
+                       /* 
+                        * We only need to do this if the exception was raised in managed
+                        * code, since otherwise the lmf was already popped of the stack.
+                        */
+                       if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
+                               memcpy (&new_ctx->regs [0], &(*lmf)->iregs [4], sizeof (gulong) * MONO_SAVED_GREGS);
+                       }
+                       new_ctx->esp = (*lmf)->iregs [13];
+                       new_ctx->eip = (*lmf)->iregs [14];
+                       new_ctx->ebp = new_ctx->esp;
+               } else {
+                       int i;
+                       char* sp;
+                       offset = ji->used_regs >> 16;
+                       offset <<= 2;
+                       /* the saved regs are at sp + offset */
+                       /* restore caller saved registers */
+                       sp = (char*)ctx->ebp;
+                       sp += offset;
+                       for (i = 4; i < 16; ++i) {
                                if (ji->used_regs & (1 << i)) {
-                                       offset += sizeof (gulong);
-                                       new_ctx->regs [i - 13] = *(gulong*)((char*)sframe->sp - offset);
+                                       new_ctx->regs [i - 4] = *(gulong*)sp;
+                                       sp += sizeof (gulong);
                                }
                        }
+                       /* IP and LR */
+                       new_ctx->esp = *(gulong*)sp;
+                       sp += sizeof (gulong);
+                       new_ctx->eip = *(gulong*)sp;
+                       sp += sizeof (gulong);
+                       new_ctx->ebp = new_ctx->esp;
+               }
+
+               if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
+                       /* remove any unused lmf */
+                       *lmf = (*lmf)->previous_lmf;
                }
-               /* the calling IP is in the parent frame */
-               sframe = (MonoPPCStackFrame*)sframe->sp;
-               /* we substract 4, so that the IP points into the call instruction */
-               MONO_CONTEXT_SET_IP (new_ctx, sframe->lr - 4);
-#endif
+
+               /* we substract 1, so that the IP points into the call instruction */
+               new_ctx->eip--;
 
                return ji;
        } else if (*lmf) {
                
                *new_ctx = *ctx;
-               setup_context (new_ctx);
 
                if (!(*lmf)->method)
                        return (gpointer)-1;
 
-               if (trace) {
-                       char *fname = mono_method_full_name ((*lmf)->method, TRUE);
-                       *trace = g_strdup_printf ("in (unmanaged) %s", fname);
-                       g_free (fname);
-               }
-               
                if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
                } else {
                        memset (res, 0, sizeof (MonoJitInfo));
                        res->method = (*lmf)->method;
                }
 
-#if ARM_PORT
-               /*sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_BP (ctx);
-               MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
-               MONO_CONTEXT_SET_IP (new_ctx, sframe->lr);*/
-               MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
-               MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
-               memcpy (&new_ctx->regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS);
-               memcpy (&new_ctx->fregs, (*lmf)->fregs, sizeof (double) * MONO_SAVED_FREGS);
-#endif
+               memcpy (&new_ctx->regs [0], &(*lmf)->iregs [4], sizeof (gulong) * MONO_SAVED_GREGS);
+               new_ctx->esp = (*lmf)->iregs [13];
+               new_ctx->eip = (*lmf)->iregs [14];
+               new_ctx->ebp = new_ctx->esp;
+
                *lmf = (*lmf)->previous_lmf;
 
                return ji ? ji : res;
@@ -488,7 +446,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
 
        return NULL;
 }
-#endif
 
 /*
  * This is the function called from the signal handler
@@ -505,7 +462,7 @@ mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
        memcpy (&mctx.regs, &uc->uc_mcontext.gregs [ARMREG_R4], sizeof (gulong) * 8);
        /* memcpy (&mctx.fregs, &uc->uc_mcontext.uc_regs->fpregs.fpregs [14], sizeof (double) * MONO_SAVED_FREGS);*/
 
-       result = arch_handle_exception (&mctx, obj, test_only);
+       result = mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only);
        /* restore the context so that returning from the signal handler will invoke
         * the catch clause 
         */
@@ -523,174 +480,6 @@ mono_arch_ip_from_context (void *sigctx)
        return (gpointer)uc->uc_mcontext.gregs [ARMREG_PC];
 }
 
-/**
- * arch_handle_exception:
- * @ctx: saved processor state
- * @obj: the exception object
- * @test_only: only test if the exception is caught, but dont call handlers
- *
- *
- */
-static gboolean
-arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only)
-{
-       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;
-       MonoException *mono_ex;
-       MonoArray *initial_trace_ips = NULL;
-       int frame_count = 0;
-       gboolean has_dynamic_methods = FALSE;
-
-       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;
-               initial_trace_ips = mono_ex->trace_ips;
-       } 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;
-               setup_context (&ctx_cp);
-               if (mono_jit_trace_calls != NULL)
-                       g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
-               if (!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;
-
-               setup_context (&new_ctx);
-               ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx, 
-                                             NULL, &lmf, NULL, NULL);
-               if (!ji) {
-                       g_warning ("Exception inside function without unwind info");
-                       g_assert_not_reached ();
-               }
-
-               if (ji != (gpointer)-1) {
-                       frame_count ++;
-                       
-                       if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
-                               /* 
-                                * Avoid overwriting the stack trace if the exception is
-                                * rethrown. Also avoid giant stack traces during a stack
-                                * overflow.
-                                */
-                               if (!initial_trace_ips && (frame_count < 1000)) {
-                                       trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
-
-                               }
-                       }
-
-                       if (ji->method->dynamic)
-                               has_dynamic_methods = TRUE;
-
-                       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)) {
-                                                       /* store the exception object int cfg->excvar */
-                                                       g_assert (ei->exvar_offset);
-                                                       /* need to use the frame pointer (ppc_r31), not r1 (regs start from register r13): methods with clauses always have r31 */
-                                                       // ARM_PORT *((gpointer *)((char *)(ctx->regs [ppc_r31-13]) + ei->exvar_offset)) = obj;
-                                               }
-
-                                               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
-                                                       filtered = call_filter (ctx, ei->data.filter, mono_ex);
-
-                                               if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
-                                                    mono_object_isinst (obj, ei->data.catch_class)) || filtered) {
-                                                       if (test_only) {
-                                                               if (mono_ex && !initial_trace_ips) {
-                                                                       trace_ips = g_list_reverse (trace_ips);
-                                                                       mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class);
-                                                                       if (has_dynamic_methods)
-                                                                               /* These methods could go away anytime, so compute the stack trace now */
-                                                                               mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex);
-                                                               }
-                                                               g_list_free (trace_ips);
-                                                               return TRUE;
-                                                       }
-                                                       if (mono_jit_trace_calls != NULL)
-                                                               g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
-                                                       /*printf ("stack for catch: %p\n", MONO_CONTEXT_GET_BP (ctx));*/
-                                                       MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
-                                                       jit_tls->lmf = lmf;
-                                                       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)
-                                                               g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
-                                                       call_filter (ctx, ei->handler_start, NULL);
-                                               }
-                                               
-                                       }
-                               }
-                       }
-               }
-
-               *ctx = new_ctx;
-               setup_context (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 && !initial_trace_ips) {
-                                       trace_ips = g_list_reverse (trace_ips);
-                                       mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class);
-                                       if (has_dynamic_methods)
-                                               /* These methods could go away anytime, so compute the stack trace now */
-                                               mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex);
-                               }
-                               g_list_free (trace_ips);
-                               return FALSE;
-                       }
-               }
-       }
-
-       g_assert_not_reached ();
-}
-
 gboolean
 mono_arch_has_unwind_info (gconstpointer addr)
 {