Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 prevent compiler from optimizing away a variable
#if defined(__llvm__)
__attribute__((noinline, optnone))
#else
__attribute__((noinline, optimize("O0")))
#endif
static void DoNotOptimize(const void* p)
{
// This function takes the address of a variable to ensure
// it's preserved and available in crash dumps
(void)p;
}

/*++
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
DoNotOptimize(&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 prevent compiler from optimizing away a variable
__attribute__((noinline,NOOPT_ATTRIBUTE))
static void DoNotOptimize(const void* p)
{
// This function takes the address of a variable to ensure
// it's preserved and available in crash dumps
(void)p;
}

/*++
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
DoNotOptimize(&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
DoNotOptimize(&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