{
CPalThread *pThread = InternalGetCurrentThread();
- CONTEXT *contextRecord;
- EXCEPTION_RECORD *exceptionRecord;
- AllocateExceptionRecords(&exceptionRecord, &contextRecord);
+ CONTEXT *contextRecord = pContext;
+ g_hardware_exception_context_locvar_offset = (int)((char*)&contextRecord - (char*)__builtin_frame_address(0));
- *contextRecord = *pContext;
- *exceptionRecord = *pExRecord;
-
- contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
+ pContext->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
bool continueExecution;
-
{
- // The exception object takes ownership of the exceptionRecord and contextRecord
- PAL_SEHException exception(exceptionRecord, contextRecord);
+ PAL_SEHException exception(pExRecord, pContext, true);
TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress);
if (continueExecution)
{
// Make a copy of the exception records so that we can free them before restoring the context
- *pContext = *contextRecord;
- *pExRecord = *exceptionRecord;
+ *pContext = *exception.ExceptionPointers.ContextRecord;
+ *pExRecord = *exception.ExceptionPointers.ExceptionRecord;
}
// The exception records are destroyed by the PAL_SEHException destructor now.
#ifndef HOST_WINDOWS
-extern int g_common_signal_handler_context_locvar_offset;
+// Frame pointer relative offset of a local containing a pointer to the windows style context of a location
+// where a hardware exception occured.
+int g_hardware_exception_context_locvar_offset = 0;
BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers)
{
DWORD64 curPc = CONTEXTGetPC(context);
-#ifndef __APPLE__
- // Check if the PC is the return address from the SEHProcessException in the common_signal_handler.
- // If that's the case, extract its local variable containing the windows style context of the hardware
+ // Check if the PC is the return address from the SEHProcessException.
+ // If that's the case, extract its local variable containing a pointer to the windows style context of the hardware
// exception and return that. This skips the hardware signal handler trampoline that the libunwind
- // cannot cross on some systems.
+ // cannot cross on some systems. On macOS, it skips a similar trampoline we create in HijackFaultingThread.
if ((void*)curPc == g_SEHProcessExceptionReturnAddress)
{
- CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset);
- memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT));
+ CONTEXT* exceptionContext = *(CONTEXT**)(CONTEXTGetFP(context) + g_hardware_exception_context_locvar_offset);
+ memcpy_s(context, sizeof(CONTEXT), exceptionContext, sizeof(CONTEXT));
return TRUE;
}
-#endif
if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0)
{
#if !HAVE_MACH_EXCEPTIONS
-// Offset of the local variable containing pointer to windows style context in the common_signal_handler function.
-// This offset is relative to the frame pointer.
-int g_common_signal_handler_context_locvar_offset = 0;
-
// TOP of special stack for handling stack overflow
volatile void* g_stackOverflowHandlerStack = NULL;
#if !HAVE_MACH_EXCEPTIONS
sigset_t signal_set;
CONTEXT signalContextRecord;
+ CONTEXT* signalContextRecordPtr = &signalContextRecord;
EXCEPTION_RECORD exceptionRecord;
native_context_t *ucontext;
ucontext = (native_context_t *)sigcontext;
- g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0));
+ g_hardware_exception_context_locvar_offset = (int)((char*)&signalContextRecordPtr - (char*)__builtin_frame_address(0));
if (code == (SIGSEGV | StackOverflowFlag))
{
}
+// Offset of the local variable containing pointer to windows style context in the common_signal_handler / PAL_DispatchException function.
+// This offset is relative to the frame pointer.
+extern int g_hardware_exception_context_locvar_offset;
+
+
#endif /* _PAL_SEH_HPP_ */
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+public class Program
+{
+ private interface IFoo
+ {
+ bool IsValid { get; }
+ }
+
+ private class Foo : IFoo
+ {
+ public bool IsValid { get; set; }
+ }
+
+ public static int Main(string[] args)
+ {
+ bool warmup = new Foo().IsValid;
+ CatchIgnore(() =>
+ CatchRethrow(() =>
+ {
+ IFoo[] foos = {new Foo(), null};
+ foreach (var foo in foos)
+ {
+ bool check = foo.IsValid;
+ }
+ }));
+
+ return 100;
+ }
+
+ public static void CatchRethrow(Action action)
+ {
+ try
+ {
+ action.Invoke();
+ }
+ catch (Exception e)
+ {
+ Console.Out.WriteLine("catch");
+ Console.Out.Flush();
+ throw new Exception("catch", e);
+ }
+ }
+
+ public static void CatchIgnore(Action action)
+ {
+ try
+ {
+ action.Invoke();
+ }
+ catch (Exception)
+ {
+ Console.Out.WriteLine("ignore");
+ Console.Out.Flush();
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <CLRTestPriority>1</CLRTestPriority>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="test62058.cs" />
+ </ItemGroup>
+</Project>