Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
RestoreSignalHandler(code, &g_previousSIGSEGV);
}

PalCreateCrashDumpIfEnabled(code, siginfo);
PalCreateCrashDumpIfEnabled(code, siginfo, context);
}

// Handler for the SIGFPE signal
Expand All @@ -581,7 +581,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
RestoreSignalHandler(code, &g_previousSIGFPE);
}

PalCreateCrashDumpIfEnabled(code, siginfo);
PalCreateCrashDumpIfEnabled(code, siginfo, context);
}

// Initialize hardware exception handling
Expand Down
23 changes: 20 additions & 3 deletions src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,19 @@ CreateCrashDump(

#endif // !defined(HOST_MACCATALYST) && !defined(HOST_IOS) && !defined(HOST_TVOS)

// Helper function to ensure context is not optimized away
#if defined(__llvm__)
__attribute__((noinline, optnone))
#else
__attribute__((noinline, optimize("O0")))
#endif
static void PreserveContextPointer(void** pContext)
{
// This function takes the address of the context pointer to ensure
// it's preserved and available in crash dumps
(void)pContext;
}

/*++
Function:
PalCreateCrashDumpIfEnabled
Expand All @@ -355,13 +368,17 @@ CreateCrashDump(
Parameters:
signal - POSIX signal number or 0
siginfo - signal info or nullptr
context - signal context or nullptr
exceptionRecord - address of exception record or nullptr

(no return value)
--*/
void
PalCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* exceptionRecord)
PalCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* context, void* exceptionRecord)
{
// Preserve context pointer to prevent optimization
PreserveContextPointer(&context);

#if !defined(HOST_MACCATALYST) && !defined(HOST_IOS) && !defined(HOST_TVOS)
// If enabled, launch the create minidump utility and wait until it completes
if (g_argvCreateDump[0] != nullptr)
Expand Down Expand Up @@ -454,13 +471,13 @@ PalCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* exceptionRecor
void
PalCreateCrashDumpIfEnabled()
{
PalCreateCrashDumpIfEnabled(SIGABRT, nullptr, nullptr);
PalCreateCrashDumpIfEnabled(SIGABRT, nullptr, nullptr, nullptr);
}

void
PalCreateCrashDumpIfEnabled(void* pExceptionRecord)
{
PalCreateCrashDumpIfEnabled(SIGABRT, nullptr, pExceptionRecord);
PalCreateCrashDumpIfEnabled(SIGABRT, nullptr, nullptr, pExceptionRecord);
}

/*++
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/PalCreateDump.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@

extern bool PalCreateDumpInitialize();
extern void PalCreateCrashDumpIfEnabled();
extern void PalCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo = nullptr, void* exceptionRecord = nullptr);
extern void PalCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo = nullptr, void* context = nullptr, void* exceptionRecord = nullptr);
extern void PalCreateCrashDumpIfEnabled(void* pExceptionRecord);
14 changes: 7 additions & 7 deletions src/coreclr/pal/src/exception/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t
if (signalRestarts)
{
// This signal mustn't be ignored because it will be restarted.
PROCAbort(code, siginfo);
PROCAbort(code, siginfo, context);
}
return;
}
Expand All @@ -433,7 +433,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t
// Shutdown and create the core dump before we restore the signal to the default handler.
PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

PROCCreateCrashDumpIfEnabled(code, siginfo, true);
PROCCreateCrashDumpIfEnabled(code, siginfo, context, true);

// Restore the original and restart h/w exception.
restore_signal(code, action);
Expand All @@ -444,7 +444,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t
{
// We can't invoke the original handler because returning from the
// handler doesn't restart the exception.
PROCAbort(code, siginfo);
PROCAbort(code, siginfo, context);
}
}
else if (IsSaSigInfo(action))
Expand All @@ -462,7 +462,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t

PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

PROCCreateCrashDumpIfEnabled(code, siginfo, true);
PROCCreateCrashDumpIfEnabled(code, siginfo, context, true);
}

/*++
Expand Down Expand Up @@ -655,7 +655,7 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
{
#if defined(TARGET_TVOS)
(void)!write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1);
PROCAbort(SIGSEGV, siginfo);
PROCAbort(SIGSEGV, siginfo, context);
#else // TARGET_TVOS
size_t handlerStackTop = __sync_val_compare_and_swap((size_t*)&g_stackOverflowHandlerStack, (size_t)g_stackOverflowHandlerStack, 0);
if (handlerStackTop == 0)
Expand All @@ -682,7 +682,7 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)

if (SwitchStackAndExecuteHandler(code | StackOverflowFlag, siginfo, context, (size_t)handlerStackTop))
{
PROCAbort(SIGSEGV, siginfo);
PROCAbort(SIGSEGV, siginfo, context);
}
(void)!write(STDERR_FILENO, StackOverflowHandlerReturnedMessage, sizeof(StackOverflowHandlerReturnedMessage) - 1);
#endif // TARGET_TVOS
Expand Down Expand Up @@ -851,7 +851,7 @@ static void sigterm_handler(int code, siginfo_t *siginfo, void *context)
DWORD val = 0;
if (enableDumpOnSigTerm.IsSet() && enableDumpOnSigTerm.TryAsInteger(10, val) && val == 1)
{
PROCCreateCrashDumpIfEnabled(code, siginfo, false);
PROCCreateCrashDumpIfEnabled(code, siginfo, context, false);
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/pal/src/include/pal/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,15 @@ BOOL PROCAbortInitialize();
Parameters:
signal - POSIX signal number
siginfo - POSIX signal info
context - signal context or nullptr

Does not return
--*/
#if !defined(HOST_ARM) // PAL_NORETURN produces broken unwinding information for this method
// making crash dumps impossible to analyze
PAL_NORETURN
#endif
VOID PROCAbort(int signal = SIGABRT, siginfo_t* siginfo = nullptr);
VOID PROCAbort(int signal = SIGABRT, siginfo_t* siginfo = nullptr, void* context = nullptr);

/*++
Function:
Expand All @@ -182,11 +183,12 @@ VOID PROCNotifyProcessShutdown(bool isExecutingOnAltStack = false);
Parameters:
signal - POSIX signal number
siginfo - POSIX signal info or nullptr
context - signal context or nullptr
serialize - allow only one thread to generate core dump

(no return value)
--*/
VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize);
VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* context, bool serialize);

#ifdef __cplusplus
}
Expand Down
25 changes: 21 additions & 4 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,15 @@ PAL_GenerateCoreDump(
return result;
}

// Helper function to ensure context is not optimized away
__attribute__((noinline,NOOPT_ATTRIBUTE))
static void PreserveContextPointer(void** pContext)
{
// This function takes the address of the context pointer to ensure
// it's preserved and available in crash dumps
(void)pContext;
}

/*++
Function:
PROCCreateCrashDumpIfEnabled
Expand All @@ -2716,23 +2725,30 @@ PAL_GenerateCoreDump(
Parameters:
signal - POSIX signal number
siginfo - POSIX signal info or nullptr
context - signal context or nullptr
serialize - allow only one thread to generate core dump

(no return value)
--*/
#ifdef HOST_ANDROID
#include <minipal/log.h>
VOID
PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize)
PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* context, bool serialize)
{
// Preserve context pointer to prevent optimization
PreserveContextPointer(&context);

// TODO: Dump all managed threads callstacks into logcat and/or file?
// TODO: Dump stress log into logcat and/or file when enabled?
minipal_log_write_fatal("Aborting process.\n");
}
#else
VOID
PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize)
PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* context, bool serialize)
{
// Preserve context pointer to prevent optimization
PreserveContextPointer(&context);

// If enabled, launch the create minidump utility and wait until it completes
if (!g_argvCreateDump.empty())
{
Expand Down Expand Up @@ -2809,19 +2825,20 @@ PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize)

Parameters:
signal - POSIX signal number
context - signal context or nullptr

Does not return
--*/
#if !defined(HOST_ARM)
PAL_NORETURN
#endif
VOID
PROCAbort(int signal, siginfo_t* siginfo)
PROCAbort(int signal, siginfo_t* siginfo, void* context)
{
// Do any shutdown cleanup before aborting or creating a core dump
PROCNotifyProcessShutdown();

PROCCreateCrashDumpIfEnabled(signal, siginfo, true);
PROCCreateCrashDumpIfEnabled(signal, siginfo, context, true);

// Restore all signals; the SIGABORT handler to prevent recursion and
// the others to prevent multiple core dumps from being generated.
Expand Down
Loading