kern_return_t result = ::mach_port_deallocate(mach_task_self(), m_task);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "~CrashInfo: mach_port_deallocate FAILED %x %s\n", result, mach_error_string(result));
+ printf_error("~CrashInfo: mach_port_deallocate FAILED %x %s\n", result, mach_error_string(result));
}
}
#endif
m_hdac = LoadLibraryA(dacPath.c_str());
if (m_hdac == nullptr)
{
- fprintf(stderr, "LoadLibraryA(%s) FAILED %d\n", dacPath.c_str(), GetLastError());
+ printf_error("LoadLibraryA(%s) FAILED %d\n", dacPath.c_str(), GetLastError());
goto exit;
}
pfnCLRDataCreateInstance = (PFN_CLRDataCreateInstance)GetProcAddress(m_hdac, "CLRDataCreateInstance");
if (pfnCLRDataCreateInstance == nullptr)
{
- fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError());
+ printf_error("GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError());
goto exit;
}
hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), dataTarget, (void**)&m_pClrDataEnumRegions);
if (FAILED(hr))
{
- fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr);
+ printf_error("CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr);
goto exit;
}
hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), dataTarget, (void**)&m_pClrDataProcess);
if (FAILED(hr))
{
- fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr);
+ printf_error("CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr);
goto exit;
}
}
HRESULT hr = m_pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT);
if (FAILED(hr))
{
- fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr);
+ printf_error("EnumMemoryRegions FAILED %08x\n", hr);
return false;
}
TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration FINISHED\n");
TRACE("EnumerateManagedModules: Module enumeration STARTED\n");
if (FAILED(hr = m_pClrDataProcess->StartEnumModules(&enumModules))) {
- fprintf(stderr, "StartEnumModules FAILED %08x\n", hr);
+ printf_error("StartEnumModules FAILED %08x\n", hr);
return false;
}
{
va_list args;
va_start(args, format);
+ fprintf(stdout, "[createdump] ");
vfprintf(stdout, format, args);
fflush(stdout);
va_end(args);
{
va_list args;
va_start(args, format);
+ fprintf(stdout, "[createdump] ");
vfprintf(stdout, format, args);
fflush(stdout);
va_end(args);
kern_return_t result = ::task_for_pid(mach_task_self(), m_pid, &m_task);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "task_for_pid(%d) FAILED %x %s\n", m_pid, result, mach_error_string(result));
+ printf_error("task_for_pid(%d) FAILED %x %s\n", m_pid, result, mach_error_string(result));
return false;
}
return true;
kern_return_t result = ::task_suspend(Task());
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "task_suspend(%d) FAILED %x %s\n", m_pid, result, mach_error_string(result));
+ printf_error("task_suspend(%d) FAILED %x %s\n", m_pid, result, mach_error_string(result));
return false;
}
result = ::task_threads(Task(), &threadList, &threadCount);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "task_threads(%d) FAILED %x %s\n", m_pid, result, mach_error_string(result));
+ printf_error("task_threads(%d) FAILED %x %s\n", m_pid, result, mach_error_string(result));
return false;
}
m_fd = open(memPath, O_RDONLY);
if (m_fd == -1)
{
- fprintf(stderr, "open(%s) FAILED %d (%s)\n", memPath, errno, strerror(errno));
+ printf_error("open(%s) FAILED %d (%s)\n", memPath, errno, strerror(errno));
return false;
}
// Get the process info
DIR* taskDir = opendir(taskPath);
if (taskDir == nullptr)
{
- fprintf(stderr, "opendir(%s) FAILED %s\n", taskPath, strerror(errno));
+ printf_error("opendir(%s) FAILED %s\n", taskPath, strerror(errno));
return false;
}
}
else
{
- fprintf(stderr, "ptrace(ATTACH, %d) FAILED %s\n", tid, strerror(errno));
+ printf_error("ptrace(ATTACH, %d) FAILED %s\n", tid, strerror(errno));
closedir(taskDir);
return false;
}
int fd = open(auxvPath, O_RDONLY, 0);
if (fd == -1)
{
- fprintf(stderr, "open(%s) FAILED %s\n", auxvPath, strerror(errno));
+ printf_error("open(%s) FAILED %s\n", auxvPath, strerror(errno));
return false;
}
bool result = false;
FILE* mapsFile = fopen(mapPath, "r");
if (mapsFile == nullptr)
{
- fprintf(stderr, "fopen(%s) FAILED %s\n", mapPath, strerror(errno));
+ printf_error("fopen(%s) FAILED %s\n", mapPath, strerror(errno));
return false;
}
// linuxGateAddress is the beginning of the kernel's mapping of
FILE *statusFile = fopen(statusPath, "r");
if (statusFile == nullptr)
{
- fprintf(stderr, "GetStatus fopen(%s) FAILED\n", statusPath);
+ printf_error("GetStatus fopen(%s) FAILED\n", statusPath);
return false;
}
{
std::string crashReportFile(dumpFileName);
crashReportFile.append(".crashreport.json");
- printf("Writing crash report to file %s\n", crashReportFile.c_str());
+ printf_status("Writing crash report to file %s\n", crashReportFile.c_str());
try
{
if (!OpenWriter(crashReportFile.c_str())) {
}
catch (const std::exception& e)
{
- fprintf(stderr, "Writing the crash report file FAILED\n");
+ printf_error("Writing the crash report file FAILED\n");
// Delete the partial json file on error
remove(crashReportFile.c_str());
m_fd = open(fileName, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR | S_IRUSR);
if (m_fd == -1)
{
- fprintf(stderr, "Could not create json file %s: %d %s\n", fileName, errno, strerror(errno));
+ printf_error("Could not create json file %s: %d %s\n", fileName, errno, strerror(errno));
return false;
}
Write("{\n");
bool FormatDumpName(std::string& name, const char* pattern, const char* exename, int pid);
bool CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool crashReport, int crashThread, int signal);
+extern void printf_status(const char* format, ...);
+extern void printf_error(const char* format, ...);
{
goto exit;
}
- printf("Gathering state for process %d %s\n", pid, crashInfo->Name().c_str());
+ printf_status("Gathering state for process %d %s\n", pid, crashInfo->Name().c_str());
if (signal != 0 || crashThread != 0)
{
- printf("Crashing thread %08x signal %08x\n", crashThread, signal);
+ printf_status("Crashing thread %08x signal %08x\n", crashThread, signal);
}
// Suspend all the threads in the target process and build the list of threads
{
goto exit;
}
- fprintf(stdout, "Writing %s to file %s\n", dumpType, dumpPath.c_str());
+ printf_status("Writing %s to file %s\n", dumpType, dumpPath.c_str());
// Write the actual dump file
if (!dumpWriter.OpenDump(dumpPath.c_str()))
}
if (!dumpWriter.WriteDump())
{
- fprintf(stderr, "Writing dump FAILED\n");
+ printf_error( "Writing dump FAILED\n");
// Delete the partial dump file on error
remove(dumpPath.c_str());
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess == NULL)
{
- fprintf(stderr, "Invalid process id '%d' error %d\n", pid, GetLastError());
+ printf_error("Invalid process id '%d' error %d\n", pid, GetLastError());
goto exit;
}
if (GetModuleBaseNameA(hProcess, NULL, pszName, MAX_LONGPATH) <= 0)
{
- fprintf(stderr, "Get process name FAILED %d\n", GetLastError());
+ printf_error("Get process name FAILED %d\n", GetLastError());
goto exit;
}
if (!FormatDumpName(dumpPath, dumpPathTemplate, pszName, pid))
{
goto exit;
}
- printf("Writing %s to file %s\n", dumpType, dumpPath.c_str());
+ printf_status("Writing %s to file %s\n", dumpType, dumpPath.c_str());
hFile = CreateFileA(dumpPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
- fprintf(stderr, "Invalid dump path '%s' error %d\n", dumpPath.c_str(), GetLastError());
+ printf_error("Invalid dump path '%s' error %d\n", dumpPath.c_str(), GetLastError());
goto exit;
}
int err = GetLastError();
if (err != HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY))
{
- fprintf(stderr, "Write dump FAILED 0x%08x\n", err);
+ printf_error("Write dump FAILED 0x%08x\n", err);
break;
}
}
const char* p = pattern;
if (*p == '|')
{
- fprintf(stderr, "Pipe syntax in dump name not supported\n");
+ printf_error("Pipe syntax in dump name not supported\n");
return false;
}
ArrayHolder<char> buffer = new char[MAX_LONGPATH + 1];
if (gethostname(buffer, MAX_LONGPATH) != 0)
{
- fprintf(stderr, "Could not get the host name for dump name: %d\n",
+ printf_error("Could not get the host name for dump name: %d\n",
#ifdef HOST_WINDOWS
WSAGetLastError());
#else
// pid of dumped process
case 'P':
default:
- fprintf(stderr, "Invalid dump name format char '%c'\n", *p);
+ printf_error("Invalid dump name format char '%c'\n", *p);
return false;
}
}
m_fd = open(dumpFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR | S_IRUSR);
if (m_fd == -1)
{
- fprintf(stderr, "Could not open output %s: %d %s\n", dumpFileName, errno, strerror(errno));
+ printf_error("Could not open output %s: %d %s\n", dumpFileName, errno, strerror(errno));
return false;
}
return true;
} while (written == -1 && errno == EINTR);
if (written < 1) {
- fprintf(stderr, "WriteData FAILED %d %s\n", errno, strerror(errno));
+ printf_error("WriteData FAILED %d %s\n", errno, strerror(errno));
return false;
}
done += written;
// and then laydown the memory blocks
if (finalNoteAlignment > 0) {
if (finalNoteAlignment > sizeof(m_tempBuffer)) {
- fprintf(stderr, "finalNoteAlignment %zu > sizeof(m_tempBuffer)\n", finalNoteAlignment);
+ printf_error("finalNoteAlignment %zu > sizeof(m_tempBuffer)\n", finalNoteAlignment);
return false;
}
memset(m_tempBuffer, 0, finalNoteAlignment);
size_t read = 0;
if (!m_crashInfo.ReadProcessMemory((void*)address, m_tempBuffer, bytesToRead, &read)) {
- fprintf(stderr, "ReadProcessMemory(%" PRIA PRIx64 ", %08zx) FAILED\n", address, bytesToRead);
+ printf_error("ReadProcessMemory(%" PRIA PRIx64 ", %08zx) FAILED\n", address, bytesToRead);
return false;
}
// This can happen if the target process dies before createdump is finished
if (read == 0) {
- fprintf(stderr, "ReadProcessMemory(%" PRIA PRIx64 ", %08zx) returned 0 bytes read\n", address, bytesToRead);
+ printf_error("ReadProcessMemory(%" PRIA PRIx64 ", %08zx) returned 0 bytes read\n", address, bytesToRead);
return false;
}
}
}
- printf("Written %" PRId64 " bytes (%" PRId64 " pages) to core file\n", total, total / PAGE_SIZE);
-
+ printf_status("Written %" PRId64 " bytes (%" PRId64 " pages) to core file\n", total, total / PAGE_SIZE);
return true;
}
if (alignment > 0)
{
if (alignment > sizeof(m_tempBuffer)) {
- fprintf(stderr, "Segment alignment %llu > sizeof(m_tempBuffer)\n", alignment);
+ printf_error("Segment alignment %llu > sizeof(m_tempBuffer)\n", alignment);
return false;
}
memset(m_tempBuffer, 0, alignment);
size_t read = 0;
if (!m_crashInfo.ReadProcessMemory((void*)address, m_tempBuffer, bytesToRead, &read)) {
- fprintf(stderr, "ReadProcessMemory(%" PRIA PRIx64 ", %08zx) FAILED\n", address, bytesToRead);
+ printf_error("ReadProcessMemory(%" PRIA PRIx64 ", %08zx) FAILED\n", address, bytesToRead);
return false;
}
// This can happen if the target process dies before createdump is finished
if (read == 0) {
- fprintf(stderr, "ReadProcessMemory(%" PRIA PRIx64 ", %08zx) returned 0 bytes read\n", address, bytesToRead);
+ printf_error("ReadProcessMemory(%" PRIA PRIx64 ", %08zx) returned 0 bytes read\n", address, bytesToRead);
return false;
}
}
}
- printf("Written %" PRId64 " bytes (%" PRId64 " pages) to core file\n", total, total / PAGE_SIZE);
+ printf_status("Written %" PRId64 " bytes (%" PRId64 " pages) to core file\n", total, total / PAGE_SIZE);
return true;
}
exitCode = PAL_InitializeDLL();
if (exitCode != 0)
{
- fprintf(stderr, "PAL initialization FAILED %d\n", exitCode);
+ printf_error("PAL initialization FAILED %d\n", exitCode);
return exitCode;
}
#endif
{
if (::GetTempPathA(MAX_LONGPATH, tmpPath) == 0)
{
- fprintf(stderr, "GetTempPath failed (0x%08x)", ::GetLastError());
+ printf_error("GetTempPath failed (0x%08x)\n", ::GetLastError());
return ::GetLastError();
}
exitCode = strcat_s(tmpPath, MAX_LONGPATH, DEFAULT_DUMP_TEMPLATE);
if (exitCode != 0)
{
- fprintf(stderr, "strcat_s failed (%d)", exitCode);
+ printf_error("strcat_s failed (%d)\n", exitCode);
return exitCode;
}
dumpPathTemplate = tmpPath;
if (CreateDump(dumpPathTemplate, pid, dumpType, minidumpType, crashReport, crashThread, signal))
{
- printf("Dump successfully written\n");
+ printf_status("Dump successfully written\n");
}
else
{
else
{
// if no pid or invalid command line option
- fprintf(stderr, "%s", g_help);
+ printf_error("%s", g_help);
exitCode = -1;
}
#ifdef HOST_UNIX
}
void
+printf_status(const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ fprintf(stdout, "[createdump] ");
+ vfprintf(stdout, format, args);
+ fflush(stdout);
+ va_end(args);
+}
+
+void
+printf_error(const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ fprintf(stderr, "[createdump] ");
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+ va_end(args);
+}
+
+void
trace_printf(const char* format, ...)
{
if (g_diagnostics)
{
va_list args;
va_start(args, format);
+ fprintf(stdout, "[createdump] ");
vfprintf(stdout, format, args);
fflush(stdout);
va_end(args);
{
va_list args;
va_start(args, format);
+ fprintf(stdout, "[createdump] ");
vfprintf(stdout, format, args);
fflush(stdout);
va_end(args);
kern_return_t result = ::mach_port_deallocate(mach_task_self(), m_port);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "~ThreadInfo: mach_port_deallocate FAILED %x %s\n", result, mach_error_string(result));
+ printf_error("~ThreadInfo: mach_port_deallocate FAILED %x %s\n", result, mach_error_string(result));
}
}
kern_return_t result = ::thread_get_state(Port(), x86_THREAD_STATE64, (thread_state_t)&m_gpRegisters, &stateCount);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
+ printf_error("thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
return false;
}
result = ::thread_get_state(Port(), x86_FLOAT_STATE64, (thread_state_t)&m_fpRegisters, &stateCount);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
+ printf_error("thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
return false;
}
#elif defined(__aarch64__)
kern_return_t result = ::thread_get_state(Port(), ARM_THREAD_STATE64, (thread_state_t)&m_gpRegisters, &stateCount);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
+ printf_error("thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
return false;
}
result = ::thread_get_state(Port(), ARM_NEON_STATE64, (thread_state_t)&m_fpRegisters, &stateCount);
if (result != KERN_SUCCESS)
{
- fprintf(stderr, "thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
+ printf_error("thread_get_state(%x) FAILED %x %s\n", m_tid, result, mach_error_string(result));
return false;
}
#else
struct iovec gpRegsVec = { &m_gpRegisters, sizeof(m_gpRegisters) };
if (ptrace((__ptrace_request)PTRACE_GETREGSET, m_tid, NT_PRSTATUS, &gpRegsVec) == -1)
{
- fprintf(stderr, "ptrace(PTRACE_GETREGSET, %d, NT_PRSTATUS) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
+ printf_error("ptrace(PTRACE_GETREGSET, %d, NT_PRSTATUS) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
return false;
}
assert(sizeof(m_gpRegisters) == gpRegsVec.iov_len);
#if defined(__arm__)
// Some aarch64 kernels may not support NT_FPREGSET for arm processes. We treat this failure as non-fatal.
#else
- fprintf(stderr, "ptrace(PTRACE_GETREGSET, %d, NT_FPREGSET) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
+ printf_error("ptrace(PTRACE_GETREGSET, %d, NT_FPREGSET) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
return false;
#endif
}
#if defined(__i386__)
if (ptrace((__ptrace_request)PTRACE_GETFPXREGS, m_tid, nullptr, &m_fpxRegisters) == -1)
{
- fprintf(stderr, "ptrace(GETFPXREGS, %d) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
+ printf_error("ptrace(GETFPXREGS, %d) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
return false;
}
#elif defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__)
if (ptrace((__ptrace_request)PTRACE_GETVFPREGS, m_tid, nullptr, &m_vfpRegisters) == -1)
{
- fprintf(stderr, "ptrace(PTRACE_GETVFPREGS, %d) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
+ printf_error("ptrace(PTRACE_GETVFPREGS, %d) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
return false;
}
#endif
char* dumpType = getenv("COMPlus_DbgMiniDumpType");
char* diagStr = getenv("COMPlus_CreateDumpDiagnostics");
BOOL diag = diagStr != nullptr && strcmp(diagStr, "1") == 0;
+ char* verboseStr = getenv("COMPlus_CreateDumpVerboseDiagnostics");
+ BOOL verbose = verboseStr != nullptr && strcmp(verboseStr, "1") == 0;
char* crashReportStr = getenv("COMPlus_EnableCrashReport");
BOOL crashReport = crashReportStr != nullptr && strcmp(crashReportStr, "1") == 0;
ULONG32 flags = GenerateDumpFlagsNone;
{
flags |= GenerateDumpFlagsLoggingEnabled;
}
+ if (verbose)
+ {
+ flags |= GenerateDumpFlagsVerboseLoggingEnabled;
+ }
if (crashReport)
{
flags |= GenerateDumpFlagsCrashReportEnabled;