diff --git a/docs/design/coreclr/botr/xplat-minidump-generation.md b/docs/design/coreclr/botr/xplat-minidump-generation.md index 997b9a1e5deaea..1fed91ac5b218a 100644 --- a/docs/design/coreclr/botr/xplat-minidump-generation.md +++ b/docs/design/coreclr/botr/xplat-minidump-generation.md @@ -61,6 +61,7 @@ Environment variables supported: - `DOTNET_DbgEnableMiniDump`: if set to "1", enables this core dump generation. The default is NOT to generate a dump. - `DOTNET_DbgMiniDumpType`: See below. Default is "2" MiniDumpWithPrivateReadWriteMemory. - `DOTNET_DbgMiniDumpName`: if set, use as the template to create the dump path and file name. See "Dump name formatting" for how the dump name can be formatted. The default is _/tmp/coredump.%p_. +- `DOTNET_DbgCreateDumpToolPath`: **(NativeAOT only)** if set, specifies the directory path where the createdump tool is located. The runtime will look for the createdump binary in this directory. This is useful in scenarios where createdump is not shipped with the runtime and you need to "bring your own" dump generation tool. This environment variable is only supported in NativeAOT applications and ignored otherwise. - `DOTNET_CreateDumpDiagnostics`: if set to "1", enables the _createdump_ utilities diagnostic messages (TRACE macro). - `DOTNET_CreateDumpVerboseDiagnostics`: if set to "1", enables the _createdump_ utilities verbose diagnostic messages (TRACE_VERBOSE macro). - `DOTNET_CreateDumpLogToFile`: if set, it is the path of the file to write the _createdump_ diagnostic messages. @@ -115,6 +116,18 @@ As of .NET 5.0, the following subset of the core pattern (see [core](https://man %h Hostname return by gethostname(). %t Time of dump, expressed as seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC). +**Using a custom createdump tool (NativeAOT only)** + +In scenarios where the NativeAOT runtime does not ship with the createdump tool, you can specify a custom directory path using the `DOTNET_DbgCreateDumpToolPath` environment variable: + +```bash +export DOTNET_DbgEnableMiniDump=1 +export DOTNET_DbgCreateDumpToolPath=/path/to/directory +./myapp +``` + +The runtime will look for the `createdump` binary in the specified directory. This allows you to "bring your own" dump generation tool. Note that this environment variable is only supported in NativeAOT applications and ignored otherwise. + # Testing # The test plan is to modify the SOS tests in the (still) private debuggertests repo to trigger and use the core minidumps generated. Debugging managed core dumps on Linux is not supported by _mdbg_ at this time until we have a ELF core dump reader so only the SOS tests (which use _lldb_ on Linux) will be modified. diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index 2e44a1c82ff4e8..d69d428392313e 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -604,29 +604,57 @@ PalCreateDumpInitialize() } // Build the createdump program path for the command line - Dl_info info; - if (dladdr((void*)&PalCreateDumpInitialize, &info) == 0) - { - return false; - } const char* DumpGeneratorName = "createdump"; - int programLen = strlen(info.dli_fname) + strlen(DumpGeneratorName) + 1; - char* program = (char*)malloc(programLen); - if (program == nullptr) - { - return false; - } - strncpy(program, info.dli_fname, programLen); - char *last = strrchr(program, '/'); - if (last != nullptr) + char* dumpToolPath = nullptr; + char* program = nullptr; + + // Check if user provided a custom path to createdump tool directory + if (RhConfig::Environment::TryGetStringValue("DbgCreateDumpToolPath", &dumpToolPath)) { - *(last + 1) = '\0'; + // Use the provided directory path and concatenate with "createdump" + size_t dumpToolPathLen = strlen(dumpToolPath); + bool needsSlash = dumpToolPathLen > 0 && dumpToolPath[dumpToolPathLen - 1] != '/'; + int programLen = dumpToolPathLen + (needsSlash ? 1 : 0) + strlen(DumpGeneratorName) + 1; + program = (char*)malloc(programLen); + if (program == nullptr) + { + free(dumpToolPath); + return false; + } + strncpy(program, dumpToolPath, programLen); + if (needsSlash) + { + strncat(program, "/", programLen); + } + strncat(program, DumpGeneratorName, programLen); + free(dumpToolPath); } else { - program[0] = '\0'; + // Default behavior: derive path from current library location + Dl_info info; + if (dladdr((void*)&PalCreateDumpInitialize, &info) == 0) + { + return false; + } + int programLen = strlen(info.dli_fname) + strlen(DumpGeneratorName) + 1; + program = (char*)malloc(programLen); + if (program == nullptr) + { + return false; + } + strncpy(program, info.dli_fname, programLen); + char *last = strrchr(program, '/'); + if (last != nullptr) + { + *(last + 1) = '\0'; + } + else + { + program[0] = '\0'; + } + strncat(program, DumpGeneratorName, programLen); } - strncat(program, DumpGeneratorName, programLen); g_szCreateDumpPath = program;