void mono_arch_exceptions_init (void) { guint8 *tramp; GSList *tramps, *l; if (mono_aot_only) { tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_trampoline"); mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE); tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_abs_trampoline"); mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE); tramp = mono_aot_get_trampoline ("llvm_resume_unwind_trampoline"); mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE); } else { tramps = mono_arm_get_exception_trampolines (FALSE); for (l = tramps; l; l = l->next) { MonoTrampInfo *info = l->data; mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE); mono_save_trampoline_xdebug_info (info); mono_tramp_info_free (info); } g_slist_free (tramps); } }
void mono_arch_exceptions_init (void) { GSList *tramps, *l; gpointer tramp; if (mono_aot_only) { throw_pending_exception = mono_aot_get_trampoline ("throw_pending_exception"); tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_trampoline"); mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE); tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_abs_trampoline"); mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE); tramp = mono_aot_get_trampoline ("llvm_resume_unwind_trampoline"); mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE); } else { /* Call this to avoid initialization races */ throw_pending_exception = mono_arch_get_throw_pending_exception (NULL, FALSE); tramps = mono_amd64_get_exception_trampolines (FALSE); for (l = tramps; l; l = l->next) { MonoTrampInfo *info = l->data; mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE); mono_save_trampoline_xdebug_info (info); mono_tramp_info_free (info); } g_slist_free (tramps); } }
/* * get_throw_exception: * * Generate a call to mono_x86_throw_exception/ * mono_x86_throw_corlib_exception. * If LLVM is true, generate code which assumes the caller is LLVM generated code, * which doesn't push the arguments. */ static guint8* get_throw_exception (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib) { guint8 *start, *code; GSList *unwind_ops = NULL; int i, stack_size, stack_offset, arg_offsets [5], regs_offset; start = code = mono_global_codeman_reserve (128); stack_size = 128; /* * On apple, the stack is misaligned by the pushing of the return address. */ if (!llvm && corlib) /* On OSX, we don't generate alignment code to save space */ stack_size += 4; else stack_size += MONO_ARCH_FRAME_ALIGNMENT - 4; /* * The stack looks like this: * <pc offset> (only if corlib is TRUE) * <exception object>/<type token> * <return addr> <- esp (unaligned on apple) */ mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4); mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4); /* Alloc frame */ x86_alu_reg_imm (code, X86_SUB, X86_ESP, stack_size); mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, stack_size + 4); arg_offsets [0] = 0; arg_offsets [1] = 4; arg_offsets [2] = 8; arg_offsets [3] = 12; regs_offset = 16; /* Save registers */ for (i = 0; i < X86_NREG; ++i) if (i != X86_ESP) x86_mov_membase_reg (code, X86_ESP, regs_offset + (i * 4), i, 4); /* Calculate the offset between the current sp and the sp of the caller */ if (llvm) { /* LLVM doesn't push the arguments */ stack_offset = stack_size + 4; } else { if (corlib) { /* Two arguments */ stack_offset = stack_size + 4 + 8; #ifdef __APPLE__ /* We don't generate stack alignment code on osx to save space */ #endif } else { /* One argument */ stack_offset = stack_size + 4 + 4; #ifdef __APPLE__ /* Pop the alignment added by OP_THROW too */ stack_offset += MONO_ARCH_FRAME_ALIGNMENT - 4; #endif } } /* Save ESP */ x86_lea_membase (code, X86_EAX, X86_ESP, stack_offset); x86_mov_membase_reg (code, X86_ESP, regs_offset + (X86_ESP * 4), X86_EAX, 4); /* Set arg1 == regs */ x86_lea_membase (code, X86_EAX, X86_ESP, regs_offset); x86_mov_membase_reg (code, X86_ESP, arg_offsets [0], X86_EAX, 4); /* Set arg2 == exc */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 4, 4); x86_mov_membase_reg (code, X86_ESP, arg_offsets [1], X86_EAX, 4); /* Set arg3 == eip */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size, 4); x86_mov_membase_reg (code, X86_ESP, arg_offsets [2], X86_EAX, 4); if (corlib) { /* Set arg4 == offset */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 8, 4); x86_mov_membase_reg (code, X86_ESP, arg_offsets [3], X86_EAX, 4); } else { /* Set arg4 == rethrow */ x86_mov_membase_imm (code, X86_ESP, arg_offsets [3], rethrow, 4); } /* Make the call */ x86_call_code (code, corlib ? (gpointer)mono_x86_throw_corlib_exception : (gpointer)mono_x86_throw_exception); x86_breakpoint (code); g_assert ((code - start) < 128); mono_save_trampoline_xdebug_info (corlib ? "llvm_throw_corlib_exception_trampoline" : "llvm_throw_exception_trampoline", start, code - start, unwind_ops); return start; }