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
2 changes: 1 addition & 1 deletion src/coreclr/clrfeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ if(NOT DEFINED FEATURE_SINGLE_FILE_DIAGNOSTICS)
endif(NOT DEFINED FEATURE_SINGLE_FILE_DIAGNOSTICS)

if(NOT DEFINED FEATURE_INPROC_CRASHREPORT)
if(CLR_CMAKE_TARGET_ANDROID)
if(CLR_CMAKE_TARGET_ANDROID OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS OR CLR_CMAKE_TARGET_MACCATALYST)
set(FEATURE_INPROC_CRASHREPORT 1)
else()
set(FEATURE_INPROC_CRASHREPORT 0)
Expand Down
61 changes: 58 additions & 3 deletions src/coreclr/debug/crashreport/inproccrashreporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include <ucontext.h>
#include <minipal/getexepath.h>
#include <minipal/thread.h>
#ifdef __APPLE__
#include <mach/mach.h>
#include <sys/sysctl.h>
#endif

// Include the .NET version string instead of linking because it is "static".
#if __has_include("_version.c")
Expand All @@ -26,6 +30,27 @@
static char sccsid[] = "@(#)Version N/A";
#endif

#ifdef __APPLE__
// Query a sysctl by name into a caller-supplied buffer. Called from Initialize, NOT from the
// signal handler -- sysctl/sysctlbyname is not on POSIX's async-signal-safe list, so the
// queried values are cached for use during crash reporting (mirrors the m_hostName /
// gethostname pattern).
static void CacheSysctlString(const char* sysctlName, char* buffer, size_t bufferSize)
{
buffer[0] = '\0';
size_t size = bufferSize;
if (sysctlbyname(sysctlName, buffer, &size, nullptr, 0) == 0 && size > 0)
{
size_t terminatorIndex = (size < bufferSize) ? size : bufferSize - 1;
buffer[terminatorIndex] = '\0';
}
else
{
buffer[0] = '\0';
}
}
#endif // __APPLE__

class ThreadEnumerationContext
{
public:
Expand Down Expand Up @@ -276,6 +301,17 @@ InProcCrashReporter::CreateReport(

m_jsonWriter.OpenObject("parameters");
m_jsonWriter.WriteSignedDecimalAsString("signal", static_cast<int64_t>(signal));
#ifdef __APPLE__
if (m_osVersion[0] != '\0')
{
m_jsonWriter.WriteString("OSVersion", m_osVersion);
}
if (m_systemModel[0] != '\0')
{
m_jsonWriter.WriteString("SystemModel", m_systemModel);
}
m_jsonWriter.WriteString("SystemManufacturer", "apple");
#endif
m_jsonWriter.CloseObject(); // parameters

m_jsonWriter.CloseObject(); // root
Expand Down Expand Up @@ -349,6 +385,13 @@ InProcCrashReporter::Initialize(
{
m_hostName[0] = '\0';
}

#ifdef __APPLE__
// Cache sysctl values at Initialize because sysctl/sysctlbyname is not on POSIX's
// async-signal-safe list; CreateReport reads these from the signal-handler path.
CacheSysctlString("kern.osproductversion", m_osVersion, sizeof(m_osVersion));
CacheSysctlString("hw.model", m_systemModel, sizeof(m_systemModel));
#endif
}

void
Expand Down Expand Up @@ -667,7 +710,11 @@ CrashReportHelpers::GetInstructionPointer(
}

ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
#if defined(__x86_64__)
#if defined(__APPLE__) && defined(__x86_64__)
return static_cast<uint64_t>(ucontext->uc_mcontext->__ss.__rip);
#elif defined(__APPLE__) && defined(__aarch64__)
return reinterpret_cast<uint64_t>(arm_thread_state64_get_pc_fptr(ucontext->uc_mcontext->__ss));
#elif defined(__x86_64__)
Comment thread
mdh1418 marked this conversation as resolved.
return static_cast<uint64_t>(ucontext->uc_mcontext.gregs[REG_RIP]);
#elif defined(__aarch64__)
return static_cast<uint64_t>(ucontext->uc_mcontext.pc);
Expand All @@ -688,7 +735,11 @@ CrashReportHelpers::GetStackPointer(
}

ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
#if defined(__x86_64__)
#if defined(__APPLE__) && defined(__x86_64__)
return static_cast<uint64_t>(ucontext->uc_mcontext->__ss.__rsp);
#elif defined(__APPLE__) && defined(__aarch64__)
return static_cast<uint64_t>(arm_thread_state64_get_sp(ucontext->uc_mcontext->__ss));
#elif defined(__x86_64__)
return static_cast<uint64_t>(ucontext->uc_mcontext.gregs[REG_RSP]);
#elif defined(__aarch64__)
return static_cast<uint64_t>(ucontext->uc_mcontext.sp);
Expand All @@ -709,7 +760,11 @@ CrashReportHelpers::GetFramePointer(
}

ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
#if defined(__x86_64__)
#if defined(__APPLE__) && defined(__x86_64__)
return static_cast<uint64_t>(ucontext->uc_mcontext->__ss.__rbp);
#elif defined(__APPLE__) && defined(__aarch64__)
return static_cast<uint64_t>(arm_thread_state64_get_fp(ucontext->uc_mcontext->__ss));
#elif defined(__x86_64__)
return static_cast<uint64_t>(ucontext->uc_mcontext.gregs[REG_RBP]);
#elif defined(__aarch64__)
return static_cast<uint64_t>(ucontext->uc_mcontext.regs[29]);
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/debug/crashreport/inproccrashreporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ class InProcCrashReporter
char m_reportPath[CRASHREPORT_PATH_BUFFER_SIZE] = {};
char m_processName[CRASHREPORT_STRING_BUFFER_SIZE] = {};
char m_hostName[CRASHREPORT_STRING_BUFFER_SIZE] = {};
#ifdef __APPLE__
char m_osVersion[CRASHREPORT_STRING_BUFFER_SIZE] = {};
char m_systemModel[CRASHREPORT_STRING_BUFFER_SIZE] = {};
#endif
};

// Free-function entry point used by the runtime to wire the in-proc crash
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/pal/src/exception/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,11 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t
{
if (signalRestarts)
{
// Shutdown and create the core dump before we restore the signal to the default handler.
// Shutdown, log the managed callstack (if a host callback is registered),
// and create the core dump before we restore the signal to the default handler.
PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

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

// Restore the original and restart h/w exception.
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/ceemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -709,9 +709,9 @@ void EEStartupHelper()
PAL_SetShutdownCallback(EESocketCleanupHelper);
#endif // TARGET_UNIX

#ifdef HOST_ANDROID
#if defined(HOST_ANDROID) || defined(HOST_IOS) || defined(HOST_TVOS) || defined(HOST_MACCATALYST)
PAL_SetLogManagedCallstackForSignalCallback(EEPolicy::LogManagedCallstackForSignal);
#endif // HOST_ANDROID
#endif

#ifdef FEATURE_INPROC_CRASHREPORT
CrashReportConfigure();
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/eepolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ int NOINLINE EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR
return -1;
}

#ifdef HOST_ANDROID
#if defined(HOST_ANDROID) || defined(HOST_IOS) || defined(HOST_TVOS) || defined(HOST_MACCATALYST)
// Logs the managed callstack when a signal is received.
void EEPolicy::LogManagedCallstackForSignal(LPCWSTR signalName)
{
Expand All @@ -926,4 +926,4 @@ void EEPolicy::LogManagedCallstackForSignal(LPCWSTR signalName)

LogInfoForFatalError(0, message.GetUnicode(), nullptr, nullptr, nullptr);
}
#endif // HOST_ANDROID
#endif
2 changes: 1 addition & 1 deletion src/coreclr/vm/eepolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class EEPolicy

static void DECLSPEC_NORETURN HandleFatalStackOverflow(EXCEPTION_POINTERS *pException, BOOL fSkipDebugger = FALSE);

#ifdef HOST_ANDROID
#if defined(HOST_ANDROID) || defined(HOST_IOS) || defined(HOST_TVOS) || defined(HOST_MACCATALYST)
static void LogManagedCallstackForSignal(LPCWSTR signalName);
#endif

Expand Down
Loading