Skip to content

Commit

Permalink
Fix handling of hardware exceptions in native code on Unix (#69685)
Browse files Browse the repository at this point in the history
This change fixes handling of hardware exceptions like sigsegv or
division by zero that happen in native code out of our runtime helpers
and that is enclosed in the PAL_TRY / PAL_EXCEPT or PAL_FINALLY.
The current implementation was working only for the DAC code. There is a
new need to use it in SuperPMI to ensure that a log is written even in case
an access violation occured in JIT.
It still requires the shared library that wants to use it to be compiled
with FEATURE_ENABLE_HARDWARE_EXCEPTIONS, so nothing has changed for
coreclr or JIT. It also requires the PAL of that shared library to be
initialized with PAL_INITIALIZE_REGISTER_SIGNALS on Linux. On macOS,
this is not needed.
  • Loading branch information
janvorli committed May 24, 2022
1 parent a014478 commit 326e719
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/coreclr/pal/inc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -4524,6 +4524,7 @@ struct PAL_SEHException
ExceptionPointers.ContextRecord = ex.ExceptionPointers.ContextRecord;
TargetFrameSp = ex.TargetFrameSp;
RecordsOnStack = ex.RecordsOnStack;
IsExternal = ex.IsExternal;
ManagedToNativeExceptionCallback = ex.ManagedToNativeExceptionCallback;
ManagedToNativeExceptionCallbackContext = ex.ManagedToNativeExceptionCallbackContext;

Expand All @@ -4545,6 +4546,9 @@ struct PAL_SEHException
// Target frame stack pointer set before the 2nd pass.
SIZE_T TargetFrameSp;
bool RecordsOnStack;
// The exception is a hardware exception coming from a native code out of
// the well known runtime helpers
bool IsExternal;

void(*ManagedToNativeExceptionCallback)(void* context);
void* ManagedToNativeExceptionCallbackContext;
Expand All @@ -4555,6 +4559,7 @@ struct PAL_SEHException
ExceptionPointers.ContextRecord = pContextRecord;
TargetFrameSp = NoTargetFrameSp;
RecordsOnStack = onStack;
IsExternal = false;
ManagedToNativeExceptionCallback = NULL;
ManagedToNativeExceptionCallbackContext = NULL;
}
Expand Down Expand Up @@ -4593,6 +4598,7 @@ struct PAL_SEHException
ExceptionPointers.ContextRecord = NULL;
TargetFrameSp = NoTargetFrameSp;
RecordsOnStack = false;
IsExternal = false;
ManagedToNativeExceptionCallback = NULL;
ManagedToNativeExceptionCallbackContext = NULL;
}
Expand Down Expand Up @@ -4899,6 +4905,7 @@ class NativeExceptionHolderFactory
{ \
try \
{ \
HardwareExceptionHolder \
tryBlock(__param); \
} \
catch (...) \
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/pal/src/exception/seh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ SEHProcessException(PAL_SEHException* exception)
if (CatchHardwareExceptionHolder::IsEnabled())
{
EnsureExceptionRecordsOnHeap(exception);
exception->IsExternal = true;
PAL_ThrowExceptionFromContext(exception->GetContextRecord(), exception);
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4569,7 +4569,13 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT
// This is the first time we see the managed exception, set its context to the managed frame that has caused
// the exception to be thrown
*ex.GetContextRecord() = *frameContext;
ex.GetExceptionRecord()->ExceptionAddress = (VOID*)controlPc;

// Move the exception address to the first managed frame on the stack except for the hardware exceptions
// stemming from from a native code out of the well known runtime helpers
if (!ex.IsExternal)
{
ex.GetExceptionRecord()->ExceptionAddress = (VOID*)controlPc;
}
}

ex.GetExceptionRecord()->ExceptionFlags = 0;
Expand Down

0 comments on commit 326e719

Please sign in to comment.