diff --git a/docs/design/coreclr/botr/xplat-minidump-generation.md b/docs/design/coreclr/botr/xplat-minidump-generation.md index f0836ae5c2143b..9ac1d20409061b 100644 --- a/docs/design/coreclr/botr/xplat-minidump-generation.md +++ b/docs/design/coreclr/botr/xplat-minidump-generation.md @@ -1,6 +1,6 @@ # Introduction # -Core dump generation on Linux and other non-Windows platforms has several challenges. Dumps can be very large and the default name/location of a dump is not consistent across all our supported platforms. The size of a full core dumps can be controlled somewhat with the "coredump_filter" file/flags but even with the smallest settings may be still too large and may not contain all the managed state needed for debugging. By default, some platforms use _core_ as the name and place the core dump in the current directory from where the program is launched; others add the _pid_ to the name. Configuring the core name and location requires superuser permission. Requiring superuser to make this consistent is not a satisfactory option. +Dump generation on Windows, Linux and other non-Windows platforms has several challenges. Dumps can be very large and the default name/location of a dump is not consistent across all our supported platforms. The size of a full core dumps can be controlled somewhat with the "coredump_filter" file/flags but even with the smallest settings may be still too large and may not contain all the managed state needed for debugging. By default, some platforms use _core_ as the name and place the core dump in the current directory from where the program is launched; others add the _pid_ to the name. Configuring the core name and location requires superuser permission. Requiring superuser to make this consistent is not a satisfactory option. Our goal is to generate core dumps that are on par with WER (Windows Error Reporting) crash dumps on any supported Linux platform. To the very least we want to enable the following: - automatic generation of minimal size minidumps. The quality and quantity of the information contained in the dump should be on par with the information contained in a traditional Windows mini-dump. @@ -42,7 +42,11 @@ There will be some differences gathering the crash information but these platfor ### OS X ### -Gathering the crash information on OS X will be quite a bit different than Linux and the core dump will be written in the Mach-O format instead of ELF. The OS X support currently has not been implemented. +As of .NET Core 5.0, createdump is supported on MacOS but instead of the MachO dump format, it generates the ELF coredumps. This is because of time constraints developing a MachO dump writer on the generation side and a MachO reader for the diagnostics tooling side (dotnet-dump and CLRMD). This means the native debuggers like gdb and lldb will not work with these dumps but the dotnet-dump tool will allow the managed state to be analyzed. Because of this behavior an additional environment variable will need to be set (COMPlus_DbgEnableElfDumpOnMacOS=1) along with the ones below in the Configuration/Policy section. + +### Windows ### + +As of .NET Core 5.0, createdump and the below configuration environment variables are supported on Windows. It is implemented using the Windows MiniDumpWriteDump API. This allows consistent crash/unhandled exception dumps across all of our platforms. # Configuration/Policy # diff --git a/src/coreclr/src/debug/createdump/main.cpp b/src/coreclr/src/debug/createdump/main.cpp index 66b1976119104b..902ee1a693fa4b 100644 --- a/src/coreclr/src/debug/createdump/main.cpp +++ b/src/coreclr/src/debug/createdump/main.cpp @@ -40,6 +40,15 @@ int __cdecl main(const int argc, const char* argv[]) int exitCode = 0; int pid = 0; +#ifdef __APPLE__ + char* enabled = getenv("COMPlus_DbgEnableElfDumpOnMacOS"); + if (enabled == nullptr || strcmp(enabled, "1") != 0) + { + fprintf(stderr, "MachO coredumps are not supported. To enable ELF coredumps on MacOS, set the COMPlus_DbgEnableElfDumpOnMacOS environment variable to 1.\n"); + return -1; + } +#endif + #ifdef HOST_UNIX exitCode = PAL_InitializeDLL(); if (exitCode != 0) diff --git a/src/coreclr/src/debug/dbgutil/machoreader.cpp b/src/coreclr/src/debug/dbgutil/machoreader.cpp index 155ec15a3af004..fa94b49b8d4a40 100644 --- a/src/coreclr/src/debug/dbgutil/machoreader.cpp +++ b/src/coreclr/src/debug/dbgutil/machoreader.cpp @@ -401,6 +401,7 @@ MachOReader::ReadString(const char* address, std::string& str) char c = 0; if (!ReadMemory((void*)(address + i), &c, sizeof(char))) { + Trace("ERROR: Failed to read string at %p\n", (void*)(address + i)); return false; } if (c == '\0') diff --git a/src/coreclr/tests/testenvironment.proj b/src/coreclr/tests/testenvironment.proj index fcb722769e9e4a..65dbb3ffb10b74 100644 --- a/src/coreclr/tests/testenvironment.proj +++ b/src/coreclr/tests/testenvironment.proj @@ -15,6 +15,7 @@ COMPlus_TieredCompilation; COMPlus_DbgEnableMiniDump; + COMPlus_DbgEnableElfDumpOnMacOS; COMPlus_DbgMiniDumpName; COMPlus_EnableAES; COMPlus_EnableAVX; @@ -65,6 +66,7 @@ 0 1 + 1 $HELIX_DUMP_FOLDER/coredump.%d.dmp diff --git a/src/tests/Common/Coreclr.TestWrapper/CoreclrTestWrapperLib.cs b/src/tests/Common/Coreclr.TestWrapper/CoreclrTestWrapperLib.cs index 0d9c4ab88985c7..e2d08676ec599a 100644 --- a/src/tests/Common/Coreclr.TestWrapper/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/Coreclr.TestWrapper/CoreclrTestWrapperLib.cs @@ -205,7 +205,6 @@ public class CoreclrTestWrapperLib static bool CollectCrashDump(Process process, string path) { - ProcessStartInfo createdumpInfo = null; string coreRoot = Environment.GetEnvironmentVariable("CORE_ROOT"); string createdumpPath = Path.Combine(coreRoot, "createdump"); string arguments = $"--name \"{path}\" {process.Id} --withheap"; @@ -220,6 +219,7 @@ static bool CollectCrashDump(Process process, string path) { createdump.StartInfo.FileName = "sudo"; createdump.StartInfo.Arguments = $"{createdumpPath} " + arguments; + createdump.StartInfo.EnvironmentVariables.Add("COMPlus_DbgEnableElfDumpOnMacOS", "1"); } createdump.StartInfo.UseShellExecute = false;