From 2cee7211900fda7f3a19171dc6f484520dce820f Mon Sep 17 00:00:00 2001 From: Alexander Kyte Date: Tue, 18 Sep 2018 16:03:56 -0400 Subject: [runtime] Add mono_rethrow opcode --- mono/cil/cil-opcodes.xml | 1 + mono/cil/opcode.def | 1 + mono/metadata/mono-basic-block.c | 1 + mono/mini/interp/interp.c | 17 +++++++++++++++++ mono/mini/interp/mintops.def | 1 + mono/mini/interp/transform.c | 6 ++++++ mono/mini/method-to-ir.c | 20 ++++++++++++++++++++ 7 files changed, 47 insertions(+) diff --git a/mono/cil/cil-opcodes.xml b/mono/cil/cil-opcodes.xml index c779880212d..f65b16d5c89 100644 --- a/mono/cil/cil-opcodes.xml +++ b/mono/cil/cil-opcodes.xml @@ -323,4 +323,5 @@ + diff --git a/mono/cil/opcode.def b/mono/cil/opcode.def index b27d16e6217..99e7be8195a 100644 --- a/mono/cil/opcode.def +++ b/mono/cil/opcode.def @@ -323,6 +323,7 @@ OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, 0 OPDEF(CEE_MONO_GET_RGCTX_ARG, "mono_get_rgctx_arg", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x1C, NEXT) OPDEF(CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT, "mono_ldptr_profiler_allocation_count", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x1D, NEXT) OPDEF(CEE_MONO_LD_DELEGATE_METHOD_PTR, "mono_ld_delegate_method_ptr", Pop1, PushI, InlineNone, 0, 2, 0xF0, 0x1E, NEXT) +OPDEF(CEE_MONO_RETHROW, "mono_rethrow", PopRef, Push0, InlineNone, 0, 2, 0xF0, 0x1F, ERROR) #ifndef OPALIAS #define _MONO_CIL_OPALIAS_DEFINED_ #define OPALIAS(a,s,r) diff --git a/mono/metadata/mono-basic-block.c b/mono/metadata/mono-basic-block.c index b74ccd1f036..a19d445fe84 100644 --- a/mono/metadata/mono-basic-block.c +++ b/mono/metadata/mono-basic-block.c @@ -324,6 +324,7 @@ mono_opcode_has_static_branch (int opcode) case MONO_CEE_THROW: case MONO_CEE_RETHROW: case MONO_CEE_ENDFINALLY: + case MONO_CEE_MONO_RETHROW: return TRUE; } return FALSE; diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c index fdc1febec68..2941fd38580 100644 --- a/mono/mini/interp/interp.c +++ b/mono/mini/interp/interp.c @@ -5532,6 +5532,23 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, guint16 *st THROW_EX_GENERAL (*(MonoException**)(frame->locals + exvar_offset), ip - 1, TRUE); MINT_IN_BREAK; } + MINT_IN_CASE(MINT_MONO_RETHROW) { + /* + * need to clarify what this should actually do: + * + * Takes an exception from the stack and rethrows it. + * This is useful for wrappers that don't want to have to + * use CEE_THROW and lose the exception stacktrace. + */ + + --sp; + frame->ex_handler = NULL; + if (!sp->data.p) + sp->data.p = mono_get_exception_null_reference (); + + THROW_EX_GENERAL ((MonoException *)sp->data.p, ip, TRUE); + MINT_IN_BREAK; + } MINT_IN_CASE(MINT_LD_DELEGATE_METHOD_PTR) { MonoDelegate *del; diff --git a/mono/mini/interp/mintops.def b/mono/mini/interp/mintops.def index 38e51648850..ff319464aea 100644 --- a/mono/mini/interp/mintops.def +++ b/mono/mini/interp/mintops.def @@ -178,6 +178,7 @@ OPDEF(MINT_LEAVE_S_CHECK, "leave.s.check", 2, MintOpShortBranch) OPDEF(MINT_THROW, "throw", 1, MintOpNoArgs) OPDEF(MINT_RETHROW, "rethrow", 2, MintOpUShortInt) OPDEF(MINT_ENDFINALLY, "endfinally", 2, MintOpNoArgs) +OPDEF(MINT_MONO_RETHROW, "mono_rethrow", 1, MintOpNoArgs) OPDEF(MINT_CHECKPOINT, "checkpoint", 1, MintOpNoArgs) OPDEF(MINT_SAFEPOINT, "safepoint", 1, MintOpNoArgs) diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c index 66c5b880aeb..6e90e63a23f 100644 --- a/mono/mini/interp/transform.c +++ b/mono/mini/interp/transform.c @@ -4321,6 +4321,12 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig case MONO_CUSTOM_PREFIX: ++td->ip; switch (*td->ip) { + case CEE_MONO_RETHROW: + CHECK_STACK (td, 1); + SIMPLE_OP (td, MINT_MONO_RETHROW); + td->sp = td->stack; + break; + case CEE_MONO_LD_DELEGATE_METHOD_PTR: --td->sp; td->ip += 1; diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 9b3cdc54ab7..0b8734b4755 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -11739,6 +11739,26 @@ mono_ldptr: start_new_bblock = 1; break; } + case MONO_CEE_MONO_RETHROW: { + if (sp [-1]->type != STACK_OBJ) + UNVERIFIED; + + MONO_INST_NEW (cfg, ins, OP_RETHROW); + --sp; + ins->sreg1 = sp [0]->dreg; + cfg->cbb->out_of_line = TRUE; + MONO_ADD_INS (cfg->cbb, ins); + MONO_INST_NEW (cfg, ins, OP_NOT_REACHED); + MONO_ADD_INS (cfg->cbb, ins); + sp = stack_start; + + link_bblock (cfg, cfg->cbb, end_bblock); + start_new_bblock = 1; + /* This can complicate code generation for llvm since the return value might not be defined */ + if (COMPILE_LLVM (cfg)) + INLINE_FAILURE ("mono_rethrow"); + break; + } case MONO_CEE_SIZEOF: { guint32 val; int ialign; -- cgit v1.2.3 From cd1a48ef265b0ed7b619784c51ba3edfc0769a1c Mon Sep 17 00:00:00 2001 From: Alexander Kyte Date: Sat, 1 Sep 2018 16:00:08 -0400 Subject: [runtime] Fix stored exception throws On cooperative suspend, the wrapper frames capture the exception in a MonoError, which then must be thrown. The problem with treating it as a CIL THROW opcode is that every time you THROW, you completely reset the stacktrace's collectin of saved frames. The RETHROW opcode will force the JIT to rely on an in-flight exception, that in our case has been taken our of the in-flight context. By relying on the new MONO_RETHROW, we will take an explicit exception and put it back in-flight without clearing the stored stacktrace. --- mono/metadata/marshal-ilgen.c | 5 ++++- mono/mini/aot-runtime.c | 4 ++++ mono/mini/mini-exceptions.c | 6 ++++++ mono/mini/mini.h | 1 + mono/mini/tramp-amd64.c | 4 ++-- mono/mini/tramp-arm.c | 4 ++-- mono/mini/tramp-arm64.c | 4 ++-- mono/mini/tramp-ppc.c | 2 +- mono/mini/tramp-s390x.c | 4 ++-- mono/mini/tramp-x86.c | 4 ++-- 10 files changed, 26 insertions(+), 12 deletions(-) diff --git a/mono/metadata/marshal-ilgen.c b/mono/metadata/marshal-ilgen.c index 200f38d9c2e..02687517584 100644 --- a/mono/metadata/marshal-ilgen.c +++ b/mono/metadata/marshal-ilgen.c @@ -1172,7 +1172,10 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoin /* Throw the exception returned by the checkpoint function, if any */ mono_mb_emit_byte (mb, CEE_DUP); pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE); - mono_mb_emit_byte (mb, CEE_THROW); + + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_RETHROW); + mono_mb_patch_branch (mb, pos_noex); mono_mb_emit_byte (mb, CEE_POP); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 3c31eae4a2d..03f83638ffd 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -5315,6 +5315,8 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou target = (gpointer)mono_exception_from_token; } else if (!strcmp (ji->data.name, "mono_throw_exception")) { target = (gpointer)mono_get_throw_exception (); + } else if (!strcmp (ji->data.name, "mono_rethrow_exception")) { + target = (gpointer)mono_get_rethrow_exception (); } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) { MonoTrampolineType tramp_type2 = (MonoTrampolineType)atoi (ji->data.name + strlen ("trampoline_func_")); target = (gpointer)mono_get_trampoline_func (tramp_type2); @@ -5333,6 +5335,8 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou target = (gpointer)mini_get_dbg_callbacks ()->breakpoint_from_context; } else if (!strcmp (ji->data.name, "throw_exception_addr")) { target = mono_get_throw_exception_addr (); + } else if (!strcmp (ji->data.name, "rethrow_exception_addr")) { + target = mono_get_rethrow_exception_addr (); } else if (strstr (ji->data.name, "generic_trampoline_")) { target = mono_aot_get_trampoline (ji->data.name); } else if (aot_jit_icall_hash && g_hash_table_lookup (aot_jit_icall_hash, ji->data.name)) { diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 6297bacf704..f32b69b3d96 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -318,6 +318,12 @@ mono_get_throw_exception_addr (void) return &throw_exception_func; } +gpointer +mono_get_rethrow_exception_addr (void) +{ + return &rethrow_exception_func; +} + static gboolean is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip) { diff --git a/mono/mini/mini.h b/mono/mini/mini.h index c186c1f74f9..a994909d06a 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2466,6 +2466,7 @@ gpointer mono_get_restore_context (void); gpointer mono_get_throw_exception_by_name (void); gpointer mono_get_throw_corlib_exception (void); gpointer mono_get_throw_exception_addr (void); +gpointer mono_get_rethrow_exception_addr (void); ICALL_EXPORT MonoArray *ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info); diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index 49492754b44..c90c4e73f4e 100644 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -520,9 +520,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr"); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); } else { - amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_throw_exception_addr ()); + amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_rethrow_exception_addr ()); } amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, sizeof(gpointer)); amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, sizeof(mgreg_t)); diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c index 129f2d35a20..d6b72d378fe 100644 --- a/mono/mini/tramp-arm.c +++ b/mono/mini/tramp-arm.c @@ -416,11 +416,11 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr"); + code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); } else { ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); ARM_B (code, 0); - *(gpointer*)code = mono_get_throw_exception_addr (); + *(gpointer*)code = mono_get_rethrow_exception_addr (); code += 4; } ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 0); diff --git a/mono/mini/tramp-arm64.c b/mono/mini/tramp-arm64.c index 1456a09a428..1bf6e7cd79a 100644 --- a/mono/mini/tramp-arm64.c +++ b/mono/mini/tramp-arm64.c @@ -303,9 +303,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr"); + code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); } else { - code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_get_throw_exception_addr ()); + code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_get_rethrow_exception_addr ()); } arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0); /* lr contains the return address, the trampoline will use it as the throw site */ diff --git a/mono/mini/tramp-ppc.c b/mono/mini/tramp-ppc.c index 840ceaaf221..abbf65a82e3 100644 --- a/mono/mini/tramp-ppc.c +++ b/mono/mini/tramp-ppc.c @@ -424,7 +424,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf if (aot) { g_error ("Not implemented"); } else { - ppc_load_func (code, PPC_CALL_REG, mono_get_throw_exception_addr ()); + ppc_load_func (code, PPC_CALL_REG, mono_get_rethrow_exception_addr ()); ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); ppc_mtctr (code, PPC_CALL_REG); } diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c index 5e121dc2de0..b70cae7d099 100644 --- a/mono/mini/tramp-s390x.c +++ b/mono/mini/tramp-s390x.c @@ -328,9 +328,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* * Exception case: * We have an exception we want to throw in the caller's frame, so pop - * the trampoline frame and throw from the caller. + * the trampoline frame and throw from the caller. */ - S390_SET (buf, s390_r1, (guint *)mono_get_throw_exception_addr ()); + S390_SET (buf, s390_r1, (guint *)mono_get_rethrow_exception_addr ()); s390_aghi (buf, STK_BASE, sizeof(trampStack_t)); s390_lg (buf, s390_r1, 0, s390_r1, 0); s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); diff --git a/mono/mini/tramp-x86.c b/mono/mini/tramp-x86.c index 498a8f810e1..95e2d12c1f5 100644 --- a/mono/mini/tramp-x86.c +++ b/mono/mini/tramp-x86.c @@ -343,9 +343,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr"); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); } else { - x86_mov_reg_imm (code, X86_ECX, (guint8*)mono_get_throw_exception_addr ()); + x86_mov_reg_imm (code, X86_ECX, (guint8*)mono_get_rethrow_exception_addr ()); } x86_mov_reg_membase (code, X86_ECX, X86_ECX, 0, sizeof(target_mgreg_t)); x86_jump_reg (code, X86_ECX); -- cgit v1.2.3 From 2e15fa255facafd35cf67da2234271035bb89347 Mon Sep 17 00:00:00 2001 From: Alexander Kyte Date: Wed, 12 Sep 2018 18:16:51 -0400 Subject: [runtime] Add test for icall wrapper rethrowing and exception length --- mono/tests/Makefile.am | 1 + mono/tests/exception-invokes.cs | 81 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 mono/tests/exception-invokes.cs diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index b602c5f2019..830ce60c80f 100755 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -307,6 +307,7 @@ TESTS_CS_SRC= \ exception16.cs \ exception17.cs \ exception18.cs \ + exception-invokes.cs \ exception19.cs \ exception20.cs \ typeload-unaligned.cs \ diff --git a/mono/tests/exception-invokes.cs b/mono/tests/exception-invokes.cs new file mode 100644 index 00000000000..5d7a6a59328 --- /dev/null +++ b/mono/tests/exception-invokes.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Reflection; + +class C +{ + const int StepSize = 5; + const int Iterations = 8; + + public static void Main () + { + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(HandleException); + var args = new object[] {C.Iterations * C.StepSize}; + typeof (C).GetMethod ("InvokeChain", BindingFlags.NonPublic | BindingFlags.Instance).Invoke (new C (), args); + } + + public static void HandleException (object sender, UnhandledExceptionEventArgs e) + { + var ex = e.ExceptionObject as Exception; + + int iterations = 0; + while (ex != null) { + string fullTrace = ex.StackTrace; + + string[] frames = fullTrace.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); + // Console.WriteLine("Split into {0} lines", frames.Length); + + int count = 0; + for (int i=0; i < frames.Length; i++) + { + var words = frames [i].Split((char []) null, StringSplitOptions.RemoveEmptyEntries); + if (words.Length > 1 && words [0] == "at" && words [1].StartsWith("C.InvokeChain")) + count++; + // Console.WriteLine("Line: {0} {1}", frames [i], words.Length); + } + + if (count != 0) + { + if (count > 1 && count != C.StepSize) + { + Console.WriteLine("Fail step size"); + Environment.Exit(1); + } + if (count == C.StepSize) + iterations += 1; + } + + ex = ex.InnerException; + } + + if (iterations != C.Iterations) { + Console.WriteLine ("{0} iterations", iterations); + Environment.Exit (1); + } + + // Prevents the runtime from printing the exception + Environment.Exit (0); + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + private void InvokeChain (int depth) + { + if (depth == 0) { + Base (); + } else if (depth % C.StepSize == 0) { + //Console.WriteLine ("InvokeChain {0} indirect", depth); + typeof (C).GetMethod ("InvokeChain", BindingFlags.NonPublic | BindingFlags.Instance).Invoke (this, new object[] {depth - 1}); + } else { + //Console.WriteLine ("InvokeChain {0} direct", depth); + InvokeChain (depth - 1); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void Base () + { + throw new NotImplementedException (); + } +} -- cgit v1.2.3 From 52a9b776eae9908e2a1f797b335122157914bca4 Mon Sep 17 00:00:00 2001 From: Alexander Kyte Date: Mon, 24 Sep 2018 16:55:37 -0400 Subject: [runtime] Fix off by one with stacktrace rethrow --- configure.ac | 2 +- mcs/class/referencesource/mscorlib/system/exception.cs | 2 ++ mono/metadata/marshal-ilgen.c | 5 +++++ mono/metadata/object-internals.h | 1 + mono/mini/mini-exceptions.c | 10 +++++++++- mono/mini/mini-runtime.c | 4 +++- 6 files changed, 21 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index e861846b907..00032981c7f 100644 --- a/configure.ac +++ b/configure.ac @@ -46,7 +46,7 @@ MONO_VERSION_BUILD=`echo $VERSION | cut -d . -f 3` # There is no ordering of corlib versions, no old or new, # the runtime expects an exact match. # -MONO_CORLIB_VERSION=BEAF66F4-BA36-44C5-974E-83C6F627DF8C +MONO_CORLIB_VERSION=E06DCE2D-7852-4BBA-AD9F-54D67EEF1FF9 # # Put a quoted #define in config.h. diff --git a/mcs/class/referencesource/mscorlib/system/exception.cs b/mcs/class/referencesource/mscorlib/system/exception.cs index ba3e49e67b2..ac0d1fc6ba1 100644 --- a/mcs/class/referencesource/mscorlib/system/exception.cs +++ b/mcs/class/referencesource/mscorlib/system/exception.cs @@ -978,6 +978,8 @@ namespace System { // Mono addition: Used on iPhone IntPtr[] native_trace_ips; + + int caught_in_unmanaged; #endif // See clr\src\vm\excep.h's EXCEPTION_COMPLUS definition: diff --git a/mono/metadata/marshal-ilgen.c b/mono/metadata/marshal-ilgen.c index 02687517584..7f475e26fd0 100644 --- a/mono/metadata/marshal-ilgen.c +++ b/mono/metadata/marshal-ilgen.c @@ -1173,6 +1173,11 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoin mono_mb_emit_byte (mb, CEE_DUP); pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_byte (mb, CEE_DUP); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, caught_in_unmanaged)); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, CEE_STIND_I4); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_RETHROW); diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index c260a123eaf..13c7cf1d832 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -268,6 +268,7 @@ struct _MonoException { MonoObject *serialization_manager; MonoObject *captured_traces; MonoArray *native_trace_ips; + gint32 caught_in_unmanaged; }; typedef struct { diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index f32b69b3d96..da8044c62d5 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -1923,7 +1923,11 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt if (initial_trace_ips) { int len = mono_array_length (initial_trace_ips) / TRACE_IP_ENTRY_SIZE; - for (i = 0; i < (len - 1); i++) { + // If we catch in managed/non-wrapper, we don't save the catching frame + if (!mono_ex->caught_in_unmanaged) + len -= 1; + + for (i = 0; i < len; i++) { for (int j = 0; j < TRACE_IP_ENTRY_SIZE; ++j) { gpointer p = mono_array_get (initial_trace_ips, gpointer, (i * TRACE_IP_ENTRY_SIZE) + j); trace_ips = g_list_prepend (trace_ips, p); @@ -1931,6 +1935,10 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt } } + // Reset the state because we're making it be caught somewhere + if (mono_ex->caught_in_unmanaged) + MONO_OBJECT_SETREF (mono_ex, caught_in_unmanaged, 0); + if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, error)) { mono_error_assert_ok (error); mono_ex = NULL; diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index f3f0f4b93fb..0d5f471cdc8 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -3135,8 +3135,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method); } - if (catchExcInMonoError && *exc != NULL) + if (catchExcInMonoError && *exc != NULL) { + ((MonoException *)(*exc))->caught_in_unmanaged = TRUE; mono_error_set_exception_instance (error, (MonoException*) *exc); + } return result; } -- cgit v1.2.3 From e46fa20466010a18b9b9a8130f6d8c62899780b3 Mon Sep 17 00:00:00 2001 From: Alexander Kyte Date: Tue, 2 Oct 2018 13:19:00 -0400 Subject: [crash] Fix trampoline rethrows to set caught_in_unmanaged --- mono/mini/aot-compiler.c | 4 ++++ mono/mini/aot-runtime.c | 8 ++++---- mono/mini/exceptions-amd64.c | 37 +++++++++++++++++++++++++-------- mono/mini/exceptions-arm.c | 49 +++++++++++++++++++++++++++++++------------- mono/mini/exceptions-arm64.c | 29 ++++++++++++++++++-------- mono/mini/exceptions-mips.c | 36 +++++++++++++++++++++++++++----- mono/mini/exceptions-ppc.c | 32 +++++++++++++++++++++++------ mono/mini/exceptions-s390x.c | 44 ++++++++++++++++++++++++++++++++------- mono/mini/exceptions-sparc.c | 31 ++++++++++++++++++++++++---- mono/mini/exceptions-wasm.c | 14 +++++++++++++ mono/mini/exceptions-x86.c | 36 +++++++++++++++++++++----------- mono/mini/mini-amd64.h | 2 +- mono/mini/mini-arm.h | 2 +- mono/mini/mini-arm64.h | 2 +- mono/mini/mini-exceptions.c | 16 ++++++++++++--- mono/mini/mini-ppc.h | 2 +- mono/mini/mini-x86.h | 2 +- mono/mini/mini.h | 4 +++- mono/mini/tramp-amd64.c | 4 ++-- mono/mini/tramp-arm.c | 4 ++-- mono/mini/tramp-arm64.c | 4 ++-- mono/mini/tramp-ppc.c | 2 +- mono/mini/tramp-s390x.c | 2 +- mono/mini/tramp-x86.c | 4 ++-- 24 files changed, 282 insertions(+), 88 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 37f75ee223e..19d9e66129a 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -7056,6 +7056,10 @@ emit_trampolines (MonoAotCompile *acfg) emit_trampoline (acfg, acfg->got_offset, info); mono_tramp_info_free (info); + mono_arch_get_rethrow_preserve_exception (&info, TRUE); + emit_trampoline (acfg, acfg->got_offset, info); + mono_tramp_info_free (info); + mono_arch_get_throw_corlib_exception (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); mono_tramp_info_free (info); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 03f83638ffd..ad469fb69bb 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -5315,8 +5315,8 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou target = (gpointer)mono_exception_from_token; } else if (!strcmp (ji->data.name, "mono_throw_exception")) { target = (gpointer)mono_get_throw_exception (); - } else if (!strcmp (ji->data.name, "mono_rethrow_exception")) { - target = (gpointer)mono_get_rethrow_exception (); + } else if (!strcmp (ji->data.name, "mono_rethrow_preserve_exception")) { + target = (gpointer)mono_get_rethrow_preserve_exception (); } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) { MonoTrampolineType tramp_type2 = (MonoTrampolineType)atoi (ji->data.name + strlen ("trampoline_func_")); target = (gpointer)mono_get_trampoline_func (tramp_type2); @@ -5335,8 +5335,8 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou target = (gpointer)mini_get_dbg_callbacks ()->breakpoint_from_context; } else if (!strcmp (ji->data.name, "throw_exception_addr")) { target = mono_get_throw_exception_addr (); - } else if (!strcmp (ji->data.name, "rethrow_exception_addr")) { - target = mono_get_rethrow_exception_addr (); + } else if (!strcmp (ji->data.name, "rethrow_preserve_exception_addr")) { + target = mono_get_rethrow_preserve_exception_addr (); } else if (strstr (ji->data.name, "generic_trampoline_")) { target = mono_aot_get_trampoline (ji->data.name); } else if (aot_jit_icall_hash && g_hash_table_lookup (aot_jit_icall_hash, ji->data.name)) { diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 006dab03e21..1cefe97f180 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -378,7 +378,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) void mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, guint64 dummy5, guint64 dummy6, - MonoContext *mctx, MonoObject *exc, gboolean rethrow) + MonoContext *mctx, MonoObject *exc, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -391,6 +391,8 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else if (preserve_ips) { + mono_ex->caught_in_unmanaged = TRUE; } } mono_error_assert_ok (error); @@ -418,7 +420,7 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy /* Negate the ip adjustment done in mono_amd64_throw_exception () */ mctx->gregs [AMD64_RIP] += 1; - mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, mctx, (MonoObject*)ex, FALSE); + mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, mctx, (MonoObject*)ex, FALSE, FALSE); } void @@ -443,7 +445,7 @@ mono_amd64_resume_unwind (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint6 * mono_amd64_throw_corlib_exception. */ static gpointer -get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, const char *tramp_name, gboolean aot) +get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, const char *tramp_name, gboolean aot, gboolean preserve_ips) { guint8* start; guint8 *code; @@ -486,6 +488,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g arg_offsets [0] = dummy_stack_space + 0; arg_offsets [1] = dummy_stack_space + sizeof(mgreg_t); arg_offsets [2] = dummy_stack_space + sizeof(mgreg_t) * 2; + arg_offsets [3] = dummy_stack_space + sizeof(mgreg_t) * 3; ctx_offset = dummy_stack_space + sizeof(mgreg_t) * 4; regs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, gregs); @@ -521,6 +524,9 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t)); } else { amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], rethrow, sizeof(mgreg_t)); + + /* Set arg4 == preserve_ips */ + amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], preserve_ips, sizeof(mgreg_t)); } if (aot) { @@ -562,13 +568,19 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, FALSE, FALSE, FALSE, FALSE, "throw_exception", aot); + return get_throw_trampoline (info, FALSE, FALSE, FALSE, FALSE, "throw_exception", aot, FALSE); } gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_exception", aot); + return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_exception", aot, FALSE); +} + +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_preserve_exception", aot, TRUE); } /** @@ -584,7 +596,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, FALSE, TRUE, FALSE, FALSE, "throw_corlib_exception", aot); + return get_throw_trampoline (info, FALSE, TRUE, FALSE, FALSE, "throw_corlib_exception", aot, FALSE); } #endif /* !DISABLE_JIT */ @@ -911,13 +923,13 @@ mono_amd64_get_exception_trampolines (gboolean aot) GSList *tramps = NULL; /* LLVM needs different throw trampolines */ - get_throw_trampoline (&info, FALSE, TRUE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", aot); + get_throw_trampoline (&info, FALSE, TRUE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", aot, FALSE); tramps = g_slist_prepend (tramps, info); - get_throw_trampoline (&info, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", aot); + get_throw_trampoline (&info, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", aot, FALSE); tramps = g_slist_prepend (tramps, info); - get_throw_trampoline (&info, FALSE, TRUE, TRUE, TRUE, "llvm_resume_unwind_trampoline", aot); + get_throw_trampoline (&info, FALSE, TRUE, TRUE, TRUE, "llvm_resume_unwind_trampoline", aot, FALSE); tramps = g_slist_prepend (tramps, info); return tramps; @@ -1952,6 +1964,13 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) return NULL; } +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + g_assert_not_reached (); + return NULL; +} + gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { diff --git a/mono/mini/exceptions-arm.c b/mono/mini/exceptions-arm.c index 94c6dfe3512..ed822d20608 100644 --- a/mono/mini/exceptions-arm.c +++ b/mono/mini/exceptions-arm.c @@ -144,7 +144,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) } void -mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs) +mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -167,6 +167,8 @@ mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_ if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else if (preserve_ips) { + mono_ex->caught_in_unmanaged = TRUE; } } mono_error_assert_ok (error); @@ -182,7 +184,7 @@ mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t s /* Clear thumb bit */ pc &= ~1; - mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs); + mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs, FALSE); } void @@ -212,7 +214,7 @@ mono_arm_resume_unwind (guint32 dummy1, mgreg_t pc, mgreg_t sp, mgreg_t *int_reg * */ static gpointer -get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot) +get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips) { guint8 *start; guint8 *code; @@ -241,8 +243,11 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm } /* Param area */ - ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8); - cfa_offset += 8; + int param_size = 8; + if (!resume_unwind && !corlib) + param_size += 4; // Extra arg + ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, param_size); + cfa_offset += param_size; mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, cfa_offset); /* call throw_exception (exc, ip, sp, int_regs, fp_regs) */ @@ -271,9 +276,19 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm } /* int regs */ ARM_ADD_REG_IMM8 (code, ARMREG_R3, ARMREG_SP, (cfa_offset - (MONO_ARM_NUM_SAVED_REGS * sizeof (mgreg_t)))); - /* fp regs */ - ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_SP, 8); - ARM_STR_IMM (code, ARMREG_LR, ARMREG_SP, 0); + if (resume_unwind || corlib) { + /* fp regs */ + ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_SP, 8); + ARM_STR_IMM (code, ARMREG_LR, ARMREG_SP, 0); + } else { + /* preserve_ips */ + ARM_MOV_REG_IMM8 (code, ARMREG_R5, preserve_ips); + ARM_STR_IMM (code, ARMREG_R5, ARMREG_SP, 4); + + /* fp regs */ + ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_SP, 8); + ARM_STR_IMM (code, ARMREG_LR, ARMREG_SP, 0); + } if (aot) { const char *icall_name; @@ -323,7 +338,7 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (132, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot); + return get_throw_trampoline (132, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE); } /** @@ -337,7 +352,13 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot); + return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot, FALSE); +} + +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_preserve_exception", info, aot, TRUE); } /** @@ -353,7 +374,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot); + return get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE); } GSList* @@ -363,13 +384,13 @@ mono_arm_get_exception_trampolines (gboolean aot) GSList *tramps = NULL; /* LLVM uses the normal trampolines, but with a different name */ - get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot); + get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot, FALSE); tramps = g_slist_prepend (tramps, info); - get_throw_trampoline (168, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot); + get_throw_trampoline (168, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot, FALSE); tramps = g_slist_prepend (tramps, info); - get_throw_trampoline (168, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot); + get_throw_trampoline (168, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot, FALSE); tramps = g_slist_prepend (tramps, info); return tramps; diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c index 04e301b030d..15ebd08283d 100644 --- a/mono/mini/exceptions-arm64.c +++ b/mono/mini/exceptions-arm64.c @@ -161,7 +161,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) } static gpointer -get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot) +get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips) { guint8 *start, *code; MonoJumpInfo *ji = NULL; @@ -223,6 +223,11 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm arm_movzx (code, ARMREG_R4, corlib ? 1 : 0, 0); /* Arg 6 = rethrow */ arm_movzx (code, ARMREG_R5, rethrow ? 1 : 0, 0); + if (!resume_unwind) { + /* Arg 7 = preserve_ips */ + arm_movzx (code, ARMREG_R6, preserve_ips ? 1 : 0, 0); + } + /* Call the function */ if (aot) { const char *icall_name; @@ -260,19 +265,25 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (256, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot); + return get_throw_trampoline (256, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE); } gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot); + return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot, FALSE); +} + +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_preserve_exception", info, aot, TRUE); } gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot); + return get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE); } GSList* @@ -282,13 +293,13 @@ mono_arm_get_exception_trampolines (gboolean aot) GSList *tramps = NULL; /* LLVM uses the normal trampolines, but with a different name */ - get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot); + get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot, FALSE); tramps = g_slist_prepend (tramps, info); - get_throw_trampoline (256, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot); + get_throw_trampoline (256, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot, FALSE); tramps = g_slist_prepend (tramps, info); - get_throw_trampoline (256, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot); + get_throw_trampoline (256, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot, FALSE); tramps = g_slist_prepend (tramps, info); return tramps; @@ -372,7 +383,7 @@ mono_arch_exceptions_init (void) * FP_REGS points to the 8 callee saved fp regs. */ void -mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow) +mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -403,6 +414,8 @@ mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble * if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else if (preserve_ips) { + mono_ex->caught_in_unmanaged = TRUE; } } mono_error_assert_ok (error); diff --git a/mono/mini/exceptions-mips.c b/mono/mini/exceptions-mips.c index 9efa0894fb1..195d9b3e20d 100644 --- a/mono/mini/exceptions-mips.c +++ b/mono/mini/exceptions-mips.c @@ -177,7 +177,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) } static void -throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow) +throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -203,6 +203,8 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } if (preserve_ips) { + mono_ex->catch_in_unmanaged = TRUE; } } mono_error_assert_ok (error); @@ -227,7 +229,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean * */ static gpointer -mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboolean rethrow) +mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboolean rethrow, gboolean preserve_ips) { guint8 *code; int alloc_size, pos, i; @@ -312,7 +314,31 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) if (inited) return start; - mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE); + mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE, FALSE); + inited = 1; + return start; +} + +/** + * mono_arch_get_rethrow_preserve_exception: + * \returns a function pointer which can be used to rethrow + * exceptions while avoiding modification of saved trace_ips. + * The returned function has the following + * signature: void (*func) (MonoException *exc); + */ +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + static guint8 start [GENERIC_EXCEPTION_SIZE]; + static int inited = 0; + + g_assert (!aot); + if (info) + *info = NULL; + + if (inited) + return start; + mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE, TRUE); inited = 1; return start; } @@ -341,7 +367,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) if (inited) return start; - mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, FALSE); + mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, FALSE, FALSE); inited = 1; return start; } @@ -379,7 +405,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) if (inited) return start; - mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE); + mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE, FALSE); inited = 1; return start; } diff --git a/mono/mini/exceptions-ppc.c b/mono/mini/exceptions-ppc.c index 3483ba835d8..89125df5d05 100644 --- a/mono/mini/exceptions-ppc.c +++ b/mono/mini/exceptions-ppc.c @@ -322,7 +322,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) } void -mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow) +mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -343,6 +343,8 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else if (preserve_ips) { + mono_ex->catch_in_unmanaged = TRUE } } mono_error_assert_ok (error); @@ -362,7 +364,7 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, * */ static gpointer -mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, gboolean rethrow, gboolean aot) +mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, gboolean rethrow, gboolean aot, gboolean preserve_ips) { guint8 *start, *code; int alloc_size, pos; @@ -424,6 +426,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli pos -= sizeof (gpointer) * MONO_MAX_IREGS; ppc_addi (code, ppc_r6, ppc_sp, pos); ppc_li (code, ppc_r8, rethrow); + ppc_li (code, ppc_r9, preserve_ips); if (aot) { // This can be called from runtime code, which can't guarantee that @@ -449,11 +452,28 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); if (info) - *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops); + *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_preserve_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops); return start; } +/** + * mono_arch_get_rethrow_preserve_exception: + * \returns a function pointer which can be used to rethrow + * exceptions and completely preserve trace_ips. + * The returned function has the following + * signature: void (*func) (MonoException *exc); + */ +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + int size = MONO_PPC_32_64_CASE (132, 224) + PPC_FTNPTR_SIZE; + + if (aot) + size += 64; + return mono_arch_get_throw_exception_generic (size, info, FALSE, TRUE, aot, TRUE); +} + /** * mono_arch_get_rethrow_exception: * \returns a function pointer which can be used to rethrow @@ -467,7 +487,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) if (aot) size += 64; - return mono_arch_get_throw_exception_generic (size, info, FALSE, TRUE, aot); + return mono_arch_get_throw_exception_generic (size, info, FALSE, TRUE, aot, FALSE); } /** @@ -489,7 +509,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) if (aot) size += 64; - return mono_arch_get_throw_exception_generic (size, info, FALSE, FALSE, aot); + return mono_arch_get_throw_exception_generic (size, info, FALSE, FALSE, aot, FALSE); } /** @@ -506,7 +526,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) if (aot) size += 64; - return mono_arch_get_throw_exception_generic (size, info, TRUE, FALSE, aot); + return mono_arch_get_throw_exception_generic (size, info, TRUE, FALSE, aot, FALSE); } /* diff --git a/mono/mini/exceptions-s390x.c b/mono/mini/exceptions-s390x.c index 23fecb60d2e..38b30c792ec 100644 --- a/mono/mini/exceptions-s390x.c +++ b/mono/mini/exceptions-s390x.c @@ -27,7 +27,8 @@ #define S390_THROWSTACK_ACCPRM S390_MINIMAL_STACK_SIZE #define S390_THROWSTACK_FPCPRM (S390_THROWSTACK_ACCPRM+sizeof(gpointer)) -#define S390_THROWSTACK_RETHROW (S390_THROWSTACK_FPCPRM+sizeof(gulong)) +#define S390_THROWSTACK_PRESERVE_IPS (S390_THROWSTACK_FPCPRM+sizeof(gulong)) +#define S390_THROWSTACK_RETHROW (S390_THROWSTACK_PRESERVE_IPS+sizeof(gboolean)) #define S390_THROWSTACK_INTREGS (S390_THROWSTACK_RETHROW+sizeof(gboolean)) #define S390_THROWSTACK_FLTREGS (S390_THROWSTACK_INTREGS+(16*sizeof(gulong))) #define S390_THROWSTACK_ACCREGS (S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble))) @@ -72,7 +73,7 @@ static void throw_exception (MonoObject *, unsigned long, unsigned long, gulong *, gdouble *, gint32 *, guint, gboolean); static gpointer mono_arch_get_throw_exception_generic (int, MonoTrampInfo **, - int, gboolean, gboolean); + int, gboolean, gboolean, gboolean); static void handle_signal_exception (gpointer); /*========================= End of Prototypes ======================*/ @@ -240,7 +241,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) static void throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, gulong *int_regs, gdouble *fp_regs, gint32 *acc_regs, - guint fpc, gboolean rethrow) + guint fpc, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -269,6 +270,8 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else if (preserve_ips) { + mono_ex->catch_in_unmanaged = TRUE } } mono_error_assert_ok (error); @@ -295,7 +298,7 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, static gpointer mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, - int corlib, gboolean rethrow, gboolean aot) + int corlib, gboolean rethrow, gboolean aot, gboolean preserve_ips) { guint8 *code, *start; int alloc_size, pos, i; @@ -358,6 +361,8 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, S390_SET (code, s390_r1, (guint8 *)throw_exception); s390_lghi (code, s390_r7, rethrow); s390_stg (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW); + s390_lghi (code, s390_r7, preserve_ips); + s390_stg (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_PRESERVE_IPS); s390_basr (code, s390_r14, s390_r1); /* we should never reach this breakpoint */ s390_break (code); @@ -369,6 +374,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, if (info) *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" + : (preserve_ips ? "rethrow_preserve_exception" : "throw_exception"), start, code - start, ji, unwind_ops); @@ -396,7 +402,31 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) if (info) *info = NULL; - return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot)); + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot, FALSE)); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - arch_get_rethrow_preserve_exception */ +/* */ +/* Function - Return a function pointer which can be used to */ +/* raise exceptions. This preserves the stored ips. */ +/* The returned function has the */ +/* following signature: */ +/* void (*func) (MonoException *exc); */ +/* */ +/*------------------------------------------------------------------*/ + +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + g_assert (!aot); + if (info) + *info = NULL; + + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot, TRUE)); } /*========================= End of Function ========================*/ @@ -419,7 +449,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) if (info) *info = NULL; - return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot)); + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot, FALSE)); } /*========================= End of Function ========================*/ @@ -442,7 +472,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) if (info) *info = NULL; - return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot)); + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot, FALSE)); } /*========================= End of Function ========================*/ diff --git a/mono/mini/exceptions-sparc.c b/mono/mini/exceptions-sparc.c index fbf7f73392f..4ce3906a648 100644 --- a/mono/mini/exceptions-sparc.c +++ b/mono/mini/exceptions-sparc.c @@ -167,7 +167,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) } static void -throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow) +throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -187,6 +187,8 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow) if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else (preserve_ips) { + mono_ex->catch_in_unmanaged = NULL; } } mono_error_assert_ok (error); @@ -197,7 +199,7 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow) } static gpointer -get_throw_exception (gboolean rethrow) +get_throw_exception (gboolean rethrow, gboolean preserve_ips) { guint32 *start, *code; @@ -210,6 +212,7 @@ get_throw_exception (gboolean rethrow) sparc_mov_reg_reg (code, sparc_fp, sparc_o1); sparc_mov_reg_reg (code, sparc_i7, sparc_o2); sparc_set (code, rethrow, sparc_o3); + sparc_set (code, preserve_ips, sparc_o3); sparc_set (code, throw_exception, sparc_o7); sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite); sparc_nop (code); @@ -243,7 +246,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) inited = 1; - start = get_throw_exception (FALSE); + start = get_throw_exception (FALSE, FALSE); return start; } @@ -263,7 +266,27 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) inited = 1; - start = get_throw_exception (TRUE); + start = get_throw_exception (TRUE, FALSE); + + return start; +} + +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + static guint32* start; + static int inited = 0; + + g_assert (!aot); + if (info) + *info = NULL; + + if (inited) + return start; + + inited = 1; + + start = get_throw_exception (TRUE, TRUE); return start; } diff --git a/mono/mini/exceptions-wasm.c b/mono/mini/exceptions-wasm.c index 07abc7a10ee..c6d70a04e33 100644 --- a/mono/mini/exceptions-wasm.c +++ b/mono/mini/exceptions-wasm.c @@ -24,6 +24,12 @@ wasm_rethrow_exception (void) g_error ("wasm_rethrow_exception"); } +static void +wasm_rethrow_preserve_exception (void) +{ + g_error ("wasm_rethrow_preserve_exception"); +} + static void wasm_throw_corlib_exception (void) { @@ -80,6 +86,14 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) return (gpointer)wasm_rethrow_exception; } +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + if (info) + *info = mono_tramp_info_create ("rethrow_preserve_exception", (guint8*)wasm_rethrow_preserve_exception, 1, NULL, NULL); + return (gpointer)wasm_rethrow_exception; +} + gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index b2ffd3ff78d..4e2c88f2b12 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -453,7 +453,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) */ void mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, - mgreg_t eip, gboolean rethrow) + mgreg_t eip, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; @@ -478,6 +478,8 @@ mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; + } else if (preserve_ips) { + mono_ex->caught_in_unmanaged = TRUE; } } mono_error_assert_ok (error); @@ -506,7 +508,7 @@ mono_x86_throw_corlib_exception (mgreg_t *regs, guint32 ex_token_index, /* Negate the ip adjustment done in mono_x86_throw_exception () */ eip += 1; - mono_x86_throw_exception (regs, (MonoObject*)ex, eip, FALSE); + mono_x86_throw_exception (regs, (MonoObject*)ex, eip, FALSE, FALSE); } static void @@ -537,7 +539,7 @@ mono_x86_resume_unwind (mgreg_t *regs, MonoObject *exc, * which doesn't push the arguments. */ static guint8* -get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, MonoTrampInfo **info, gboolean aot) +get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips) { guint8 *start, *code, *labels [16]; int i, stack_size, stack_offset, arg_offsets [5], regs_offset; @@ -575,7 +577,8 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea arg_offsets [1] = 4; arg_offsets [2] = 8; arg_offsets [3] = 12; - regs_offset = 16; + arg_offsets [4] = 16; + regs_offset = 20; /* Save registers */ for (i = 0; i < X86_NREG; ++i) @@ -651,6 +654,9 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea x86_mov_membase_reg (code, X86_ESP, arg_offsets [3], X86_EAX, 4); } else { x86_mov_membase_imm (code, X86_ESP, arg_offsets [3], rethrow, 4); + + /* Set arg4 == preserve_ips */ + x86_mov_membase_imm (code, X86_ESP, arg_offsets [4], preserve_ips, 4); } /* Make the call */ if (aot) { @@ -697,13 +703,19 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline ("throw_exception", FALSE, FALSE, FALSE, FALSE, FALSE, info, aot); + return get_throw_trampoline ("throw_exception", FALSE, FALSE, FALSE, FALSE, FALSE, info, aot, FALSE); } gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline ("rethrow_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot); + return get_throw_trampoline ("rethrow_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot, FALSE); +} + +gpointer +mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot) +{ + return get_throw_trampoline ("rethrow_preserve_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot, TRUE); } /** @@ -718,7 +730,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline ("throw_corlib_exception", FALSE, FALSE, TRUE, FALSE, FALSE, info, aot); + return get_throw_trampoline ("throw_corlib_exception", FALSE, FALSE, TRUE, FALSE, FALSE, info, aot, FALSE); } void @@ -755,23 +767,23 @@ mono_arch_exceptions_init (void) } /* LLVM needs different throw trampolines */ - tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE); + tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE, FALSE); mono_register_jit_icall (tramp, "llvm_throw_exception_trampoline", NULL, TRUE); mono_tramp_info_register (tinfo, NULL); - tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE); + tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE, FALSE); mono_register_jit_icall (tramp, "llvm_rethrow_exception_trampoline", NULL, TRUE); mono_tramp_info_register (tinfo, NULL); - tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE); + tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE, FALSE); mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE); mono_tramp_info_register (tinfo, NULL); - tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE); + tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE, FALSE); mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE); mono_tramp_info_register (tinfo, NULL); - tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE); + tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE, FALSE); mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE); mono_tramp_info_register (tinfo, NULL); diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 42c9360a54e..71e276f6216 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -501,7 +501,7 @@ mono_amd64_patch (unsigned char* code, gpointer target); void mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, guint64 dummy5, guint64 dummy6, - MonoContext *mctx, MonoObject *exc, gboolean rethrow); + MonoContext *mctx, MonoObject *exc, gboolean rethrow, gboolean preserve_ips); void mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h index 344659c43a2..e851d6d11b5 100644 --- a/mono/mini/mini-arm.h +++ b/mono/mini/mini-arm.h @@ -397,7 +397,7 @@ typedef struct MonoCompileArch { #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf) void -mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs); +mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs, gboolean preserve_ips); void mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs); diff --git a/mono/mini/mini-arm64.h b/mono/mini/mini-arm64.h index 36fba6467eb..f1c7c2e52a4 100644 --- a/mono/mini/mini-arm64.h +++ b/mono/mini/mini-arm64.h @@ -258,7 +258,7 @@ guint8* mono_arm_emit_aotconst (gpointer ji, guint8 *code, guint8 *code_start, i void mono_arm_patch (guint8 *code, guint8 *target, int relocation); -void mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow); +void mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow, gboolean preserve_ips); void mono_arm_gsharedvt_init (void); diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index da8044c62d5..40df4b3e09a 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -114,7 +114,7 @@ typedef struct #define TRACE_IP_ENTRY_SIZE (sizeof (ExceptionTraceIp) / sizeof (gpointer)) static gpointer restore_context_func, call_filter_func; -static gpointer throw_exception_func, rethrow_exception_func; +static gpointer throw_exception_func, rethrow_exception_func, rethrow_preserve_exception_func; static gpointer throw_corlib_exception_func; static MonoFtnPtrEHCallback ftnptr_eh_callback; @@ -216,6 +216,7 @@ mono_exceptions_init (void) call_filter_func = mono_aot_get_trampoline ("call_filter"); throw_exception_func = mono_aot_get_trampoline ("throw_exception"); rethrow_exception_func = mono_aot_get_trampoline ("rethrow_exception"); + rethrow_preserve_exception_func = mono_aot_get_trampoline ("rethrow_preserve_exception"); } else { MonoTrampInfo *info; @@ -227,6 +228,8 @@ mono_exceptions_init (void) mono_tramp_info_register (info, NULL); rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE); mono_tramp_info_register (info, NULL); + rethrow_preserve_exception_func = mono_arch_get_rethrow_preserve_exception (&info, FALSE); + mono_tramp_info_register (info, NULL); } mono_arch_exceptions_init (); @@ -268,6 +271,13 @@ mono_get_rethrow_exception (void) return rethrow_exception_func; } +gpointer +mono_get_rethrow_preserve_exception (void) +{ + g_assert (rethrow_preserve_exception_func); + return rethrow_preserve_exception_func; +} + gpointer mono_get_call_filter (void) { @@ -319,9 +329,9 @@ mono_get_throw_exception_addr (void) } gpointer -mono_get_rethrow_exception_addr (void) +mono_get_rethrow_preserve_exception_addr (void) { - return &rethrow_exception_func; + return &rethrow_preserve_exception_func; } static gboolean diff --git a/mono/mini/mini-ppc.h b/mono/mini/mini-ppc.h index 8308387e8c9..47de3b525c8 100644 --- a/mono/mini/mini-ppc.h +++ b/mono/mini/mini-ppc.h @@ -384,7 +384,7 @@ void mono_ppc_patch (guchar *code, const guchar *target); void -mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow); +mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow, gboolean preserve_ips); #ifdef __mono_ppc64__ #define MONO_PPC_32_64_CASE(c32,c64) c64 diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index 33e2528553f..23d20b0f1a5 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -330,7 +330,7 @@ mono_x86_get_this_arg_offset (MonoMethodSignature *sig); void mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, - mgreg_t eip, gboolean rethrow); + mgreg_t eip, gboolean rethrow, gboolean preserve_ips); void mono_x86_throw_corlib_exception (mgreg_t *regs, guint32 ex_token_index, diff --git a/mono/mini/mini.h b/mono/mini/mini.h index a994909d06a..1b8f52f49fb 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2350,6 +2350,7 @@ gpointer mono_arch_get_call_filter (MonoTrampInfo **info, gboolean gpointer mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot); gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot); gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot); +gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot); gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot); gpointer mono_arch_get_throw_pending_exception (MonoTrampInfo **info, gboolean aot); gboolean mono_arch_handle_exception (void *sigctx, gpointer obj); @@ -2461,12 +2462,13 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, gpointer mono_get_throw_exception (void); gpointer mono_get_rethrow_exception (void); +gpointer mono_get_rethrow_preserve_exception (void); gpointer mono_get_call_filter (void); gpointer mono_get_restore_context (void); gpointer mono_get_throw_exception_by_name (void); gpointer mono_get_throw_corlib_exception (void); gpointer mono_get_throw_exception_addr (void); -gpointer mono_get_rethrow_exception_addr (void); +gpointer mono_get_rethrow_preserve_exception_addr (void); ICALL_EXPORT MonoArray *ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info); diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index c90c4e73f4e..002a4f7ed81 100644 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -520,9 +520,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr"); } else { - amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_rethrow_exception_addr ()); + amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_rethrow_preserve_exception_addr ()); } amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, sizeof(gpointer)); amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, sizeof(mgreg_t)); diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c index d6b72d378fe..fa53a53a924 100644 --- a/mono/mini/tramp-arm.c +++ b/mono/mini/tramp-arm.c @@ -416,11 +416,11 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); + code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr"); } else { ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); ARM_B (code, 0); - *(gpointer*)code = mono_get_rethrow_exception_addr (); + *(gpointer*)code = mono_get_rethrow_preserve_exception_addr (); code += 4; } ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 0); diff --git a/mono/mini/tramp-arm64.c b/mono/mini/tramp-arm64.c index 1bf6e7cd79a..d4c9606e9ad 100644 --- a/mono/mini/tramp-arm64.c +++ b/mono/mini/tramp-arm64.c @@ -303,9 +303,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); + code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr"); } else { - code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_get_rethrow_exception_addr ()); + code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_get_rethrow_preserve_exception_addr ()); } arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0); /* lr contains the return address, the trampoline will use it as the throw site */ diff --git a/mono/mini/tramp-ppc.c b/mono/mini/tramp-ppc.c index abbf65a82e3..a12e04fc636 100644 --- a/mono/mini/tramp-ppc.c +++ b/mono/mini/tramp-ppc.c @@ -424,7 +424,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf if (aot) { g_error ("Not implemented"); } else { - ppc_load_func (code, PPC_CALL_REG, mono_get_rethrow_exception_addr ()); + ppc_load_func (code, PPC_CALL_REG, mono_get_rethrow_preserve_exception_addr ()); ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); ppc_mtctr (code, PPC_CALL_REG); } diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c index b70cae7d099..166b63c1b65 100644 --- a/mono/mini/tramp-s390x.c +++ b/mono/mini/tramp-s390x.c @@ -330,7 +330,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf * We have an exception we want to throw in the caller's frame, so pop * the trampoline frame and throw from the caller. */ - S390_SET (buf, s390_r1, (guint *)mono_get_rethrow_exception_addr ()); + S390_SET (buf, s390_r1, (guint *)mono_get_rethrow_preserve_exception_addr ()); s390_aghi (buf, STK_BASE, sizeof(trampStack_t)); s390_lg (buf, s390_r1, 0, s390_r1, 0); s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); diff --git a/mono/mini/tramp-x86.c b/mono/mini/tramp-x86.c index 95e2d12c1f5..7a87ba67e31 100644 --- a/mono/mini/tramp-x86.c +++ b/mono/mini/tramp-x86.c @@ -343,9 +343,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf */ if (aot) { /* Not really a jit icall */ - code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_exception_addr"); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr"); } else { - x86_mov_reg_imm (code, X86_ECX, (guint8*)mono_get_rethrow_exception_addr ()); + x86_mov_reg_imm (code, X86_ECX, (guint8*)mono_get_rethrow_preserve_exception_addr ()); } x86_mov_reg_membase (code, X86_ECX, X86_ECX, 0, sizeof(target_mgreg_t)); x86_jump_reg (code, X86_ECX); -- cgit v1.2.3