未验证 提交 14e6a418 编写于 作者: M Mike McLaughlin 提交者: GitHub

Add log to file option to createdump (#67181)

Add log to file option to createdump

Add DOTNET_CreateDumpVerboseDiagnostics env var

Make the timestamp ms and 8 hex digits

Add printf_status and printf_error that all stdout goes through.

Prefix "[createdump" to all printf_status/error output.
上级 370f1604
......@@ -67,7 +67,7 @@ CrashInfo::~CrashInfo()
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
......@@ -241,25 +241,25 @@ CrashInfo::InitializeDAC()
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;
}
}
......@@ -302,7 +302,7 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType)
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");
......@@ -324,7 +324,7 @@ CrashInfo::EnumerateManagedModules()
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;
}
......@@ -768,32 +768,6 @@ CrashInfo::SearchMemoryRegions(const std::set<MemoryRegion>& regions, const Memo
return nullptr;
}
void
CrashInfo::Trace(const char* format, ...)
{
if (g_diagnostics)
{
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
fflush(stdout);
va_end(args);
}
}
void
CrashInfo::TraceVerbose(const char* format, ...)
{
if (g_diagnosticsVerbose)
{
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
fflush(stdout);
va_end(args);
}
}
//
// Lookup a symbol in a module. The caller needs to call "free()" on symbol returned.
//
......
......@@ -12,7 +12,7 @@ CrashInfo::Initialize()
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;
......@@ -37,14 +37,14 @@ CrashInfo::EnumerateAndSuspendThreads()
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;
}
......
......@@ -14,7 +14,7 @@ CrashInfo::Initialize()
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
......@@ -58,7 +58,7 @@ CrashInfo::EnumerateAndSuspendThreads()
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;
}
......@@ -76,7 +76,7 @@ CrashInfo::EnumerateAndSuspendThreads()
}
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;
}
......@@ -102,7 +102,7 @@ CrashInfo::GetAuxvEntries()
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;
......@@ -159,7 +159,7 @@ CrashInfo::EnumerateModuleMappings()
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
......@@ -377,7 +377,7 @@ GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, std::string* name)
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;
}
......
......@@ -33,7 +33,7 @@ CrashReportWriter::WriteCrashReport(const std::string& dumpFileName)
{
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())) {
......@@ -44,7 +44,7 @@ CrashReportWriter::WriteCrashReport(const std::string& dumpFileName)
}
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());
......@@ -271,7 +271,7 @@ CrashReportWriter::OpenWriter(const char* fileName)
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");
......
......@@ -6,12 +6,12 @@
#define ___in _SAL1_Source_(__in, (), _In_)
#define ___out _SAL1_Source_(__out, (), _Out_)
extern void trace_printf(const char* format, ...);
extern void trace_verbose_printf(const char* format, ...);
extern bool g_diagnostics;
extern bool g_diagnosticsVerbose;
#ifdef HOST_UNIX
extern void trace_printf(const char* format, ...);
extern void trace_verbose_printf(const char* format, ...);
#define TRACE(args...) trace_printf(args)
#define TRACE_VERBOSE(args...) trace_verbose_printf(args)
#else
......@@ -104,6 +104,8 @@ typedef int T_CONTEXT;
#define MAX_LONGPATH 1024
#endif
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 bool FormatDumpName(std::string& name, const char* pattern, const char* exename, int pid);
extern 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, ...);
......@@ -19,11 +19,11 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
{
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
......@@ -52,7 +52,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
{
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()))
......@@ -61,7 +61,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
}
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());
......
......@@ -20,24 +20,24 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
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;
}
......@@ -54,7 +54,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
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;
}
}
......
......@@ -37,7 +37,7 @@ FormatDumpName(std::string& name, const char* pattern, const char* exename, int
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;
}
......@@ -81,7 +81,7 @@ FormatDumpName(std::string& name, const char* pattern, const char* exename, int
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
......@@ -114,7 +114,7 @@ FormatDumpName(std::string& name, const char* pattern, const char* exename, int
// 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;
}
}
......
......@@ -26,7 +26,7 @@ DumpWriter::OpenDump(const char* dumpFileName)
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;
......@@ -46,7 +46,7 @@ DumpWriter::WriteData(int fd, const void* buffer, size_t length)
} 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;
......
......@@ -161,7 +161,7 @@ DumpWriter::WriteDump()
// 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);
......@@ -189,13 +189,13 @@ DumpWriter::WriteDump()
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;
}
......@@ -209,8 +209,7 @@ DumpWriter::WriteDump()
}
}
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;
}
......
......@@ -56,7 +56,7 @@ DumpWriter::WriteDump()
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);
......@@ -264,13 +264,13 @@ DumpWriter::WriteSegments()
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;
}
......@@ -284,6 +284,6 @@ DumpWriter::WriteSegments()
}
}
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;
}
......@@ -23,15 +23,23 @@ const char* g_help = "createdump [options] pid\n"
"-u, --full - create full core dump.\n"
"-d, --diag - enable diagnostic messages.\n"
"-v, --verbose - enable verbose diagnostic messages.\n"
"-l, --logtofile - file path and name to log diagnostic messages.\n"
#ifdef HOST_UNIX
"--crashreport - write crash report file.\n"
"--crashreport - write crash report file (dump file path + .crashreport.json).\n"
"--crashthread <id> - the thread id of the crashing thread.\n"
"--signal <code> - the signal code of the crash.\n"
#endif
;
FILE *g_logfile = nullptr;
FILE *g_stdout = stdout;
FILE *g_stderr = stderr;
bool g_diagnostics = false;
bool g_diagnosticsVerbose = false;
#ifdef HOST_UNIX
uint64_t g_ticksPerMS = 0;
uint64_t GetTickFrequency();
#endif
//
// Main entry point
......@@ -57,7 +65,7 @@ int __cdecl main(const int argc, const char* argv[])
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
......@@ -137,6 +145,18 @@ int __cdecl main(const int argc, const char* argv[])
g_diagnostics = true;
g_diagnosticsVerbose = true;
}
else if ((strcmp(*argv, "-l") == 0) || (strcmp(*argv, "--logtofile") == 0))
{
const char* logFilePath = *++argv;
g_logfile = fopen(logFilePath, "w");
if (g_logfile == nullptr)
{
printf_error("Can not create log file %s: %d %s\n", logFilePath, errno, strerror(errno));
return errno;
}
g_stdout = g_logfile;
g_stderr = g_logfile;
}
else {
pid = atoi(*argv);
}
......@@ -144,6 +164,11 @@ int __cdecl main(const int argc, const char* argv[])
}
}
#ifdef HOST_UNIX
g_ticksPerMS = GetTickFrequency() / 1000000UL;
TRACE("TickFrequency: %d ticks per ms\n", g_ticksPerMS);
#endif
if (pid != 0)
{
ArrayHolder<char> tmpPath = new char[MAX_LONGPATH];
......@@ -152,13 +177,13 @@ int __cdecl main(const int argc, const char* argv[])
{
if (::GetTempPathA(MAX_LONGPATH, tmpPath) == 0)
{
fprintf(stderr, "GetTempPath failed (0x%08x)", ::GetLastError());
printf_error("GetTempPath failed (0x%08x)", ::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)", exitCode);
return exitCode;
}
dumpPathTemplate = tmpPath;
......@@ -166,20 +191,25 @@ int __cdecl main(const int argc, const char* argv[])
if (CreateDump(dumpPathTemplate, pid, dumpType, minidumpType, crashReport, crashThread, signal))
{
printf("Dump successfully written\n");
printf_status("Dump successfully written\n");
}
else
{
exitCode = -1;
}
fflush(stdout);
fflush(stderr);
fflush(g_stdout);
fflush(g_stderr);
if (g_logfile != nullptr)
{
fclose(g_logfile);
}
}
else
{
// if no pid or invalid command line option
fprintf(stderr, "%s", g_help);
printf_error("%s", g_help);
exitCode = -1;
}
#ifdef HOST_UNIX
......@@ -188,6 +218,65 @@ int __cdecl main(const int argc, const char* argv[])
return exitCode;
}
void
printf_status(const char* format, ...)
{
va_list args;
va_start(args, format);
if (g_logfile == nullptr)
{
fprintf(g_stdout, "[createdump] ");
}
vfprintf(g_stdout, format, args);
fflush(g_stdout);
va_end(args);
}
void
printf_error(const char* format, ...)
{
va_list args;
va_start(args, format);
if (g_logfile == nullptr)
{
fprintf(g_stderr, "[createdump] ");
}
vfprintf(g_stderr, format, args);
fflush(g_stderr);
va_end(args);
}
#ifdef HOST_UNIX
uint64_t
GetTickFrequency()
{
LARGE_INTEGER ret;
ZeroMemory(&ret, sizeof(LARGE_INTEGER));
QueryPerformanceFrequency(&ret);
return ret.QuadPart;
}
static uint64_t
GetTimeStamp()
{
LARGE_INTEGER ret;
ZeroMemory(&ret, sizeof(LARGE_INTEGER));
QueryPerformanceCounter(&ret);
return ret.QuadPart / g_ticksPerMS;
}
static void
trace_prefix()
{
// Only add this prefix if logging to the console
if (g_logfile == nullptr)
{
fprintf(g_stdout, "[createdump] ");
}
fprintf(g_stdout, "%08" PRIx64 " ", GetTimeStamp());
}
void
trace_printf(const char* format, ...)
{
......@@ -195,8 +284,9 @@ trace_printf(const char* format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
fflush(stdout);
trace_prefix();
vfprintf(g_stdout, format, args);
fflush(g_stdout);
va_end(args);
}
}
......@@ -208,10 +298,39 @@ trace_verbose_printf(const char* format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
fflush(stdout);
trace_prefix();
vfprintf(g_stdout, format, args);
fflush(g_stdout);
va_end(args);
}
}
void
CrashInfo::Trace(const char* format, ...)
{
if (g_diagnostics)
{
va_list args;
va_start(args, format);
trace_prefix();
vfprintf(g_stdout, format, args);
fflush(g_stdout);
va_end(args);
}
}
void
CrashInfo::TraceVerbose(const char* format, ...)
{
if (g_diagnosticsVerbose)
{
va_list args;
va_start(args, format);
trace_prefix();
vfprintf(g_stdout, format, args);
fflush(g_stdout);
va_end(args);
}
}
#endif // HOST_UNIX
......@@ -23,7 +23,7 @@ ThreadInfo::~ThreadInfo()
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));
}
}
......@@ -38,7 +38,7 @@ ThreadInfo::Initialize()
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;
}
......@@ -46,7 +46,7 @@ ThreadInfo::Initialize()
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__)
......@@ -54,7 +54,7 @@ ThreadInfo::Initialize()
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;
}
......@@ -62,7 +62,7 @@ ThreadInfo::Initialize()
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
......
......@@ -69,7 +69,7 @@ ThreadInfo::GetRegistersWithPTrace()
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);
......@@ -80,7 +80,7 @@ ThreadInfo::GetRegistersWithPTrace()
#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
}
......@@ -89,7 +89,7 @@ ThreadInfo::GetRegistersWithPTrace()
#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__)
......@@ -100,7 +100,7 @@ ThreadInfo::GetRegistersWithPTrace()
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
......
......@@ -3134,6 +3134,7 @@ PROCBuildCreateDumpCommandLine(
char** pprogram,
char** ppidarg,
const char* dumpName,
const char* logFileName,
INT dumpType,
ULONG32 flags)
{
......@@ -3208,6 +3209,12 @@ PROCBuildCreateDumpCommandLine(
argv.push_back("--crashreport");
}
if (logFileName != nullptr)
{
argv.push_back("--logtofile");
argv.push_back(logFileName);
}
argv.push_back(*ppidarg);
argv.push_back(nullptr);
......@@ -3285,14 +3292,16 @@ Return
BOOL
PROCAbortInitialize()
{
CLRConfigNoCache enabledCfg= CLRConfigNoCache::Get("DbgEnableMiniDump", /*noprefix*/ false, &getenv);
CLRConfigNoCache enabledCfg = CLRConfigNoCache::Get("DbgEnableMiniDump", /*noprefix*/ false, &getenv);
DWORD enabled = 0;
if (enabledCfg.IsSet()
&& enabledCfg.TryAsInteger(10, enabled)
&& enabled)
if (enabledCfg.IsSet() && enabledCfg.TryAsInteger(10, enabled) && enabled)
{
CLRConfigNoCache dmpNameCfg = CLRConfigNoCache::Get("DbgMiniDumpName", /*noprefix*/ false, &getenv);
const char* dumpName = dmpNameCfg.IsSet() ? dmpNameCfg.AsString() : nullptr;
CLRConfigNoCache dmpLogToFileCfg = CLRConfigNoCache::Get("CreateDumpLogToFile", /*noprefix*/ false, &getenv);
const char* logFilePath = dmpLogToFileCfg.IsSet() ? dmpLogToFileCfg.AsString() : nullptr;
CLRConfigNoCache dmpTypeCfg = CLRConfigNoCache::Get("DbgMiniDumpType", /*noprefix*/ false, &getenv);
DWORD dumpType = UndefinedDumpType;
......@@ -3306,21 +3315,28 @@ PROCAbortInitialize()
}
ULONG32 flags = GenerateDumpFlagsNone;
CLRConfigNoCache createDumpCfg = CLRConfigNoCache::Get("CreateDumpDiagnostics", /*noprefix*/ false, &getenv);
CLRConfigNoCache createDumpDiag = CLRConfigNoCache::Get("CreateDumpDiagnostics", /*noprefix*/ false, &getenv);
DWORD val = 0;
if (createDumpCfg.IsSet() && createDumpCfg.TryAsInteger(10, val) && val == 1)
if (createDumpDiag.IsSet() && createDumpDiag.TryAsInteger(10, val) && val == 1)
{
flags |= GenerateDumpFlagsLoggingEnabled;
}
CLRConfigNoCache createDumpVerboseDiag = CLRConfigNoCache::Get("CreateDumpVerboseDiagnostics", /*noprefix*/ false, &getenv);
val = 0;
if (createDumpVerboseDiag.IsSet() && createDumpVerboseDiag.TryAsInteger(10, val) && val == 1)
{
flags |= GenerateDumpFlagsVerboseLoggingEnabled;
}
CLRConfigNoCache enabldReportCfg = CLRConfigNoCache::Get("EnableCrashReport", /*noprefix*/ false, &getenv);
val = 0;
if (enabldReportCfg.IsSet() && enabldReportCfg.TryAsInteger(10, val) && val == 1)
{
flags |= GenerateDumpFlagsCrashReportEnabled;
}
char* program = nullptr;
char* pidarg = nullptr;
if (!PROCBuildCreateDumpCommandLine(g_argvCreateDump, &program, &pidarg, dmpNameCfg.AsString(), dumpType, flags))
if (!PROCBuildCreateDumpCommandLine(g_argvCreateDump, &program, &pidarg, dumpName, logFilePath, dumpType, flags))
{
return FALSE;
}
......@@ -3367,7 +3383,7 @@ PAL_GenerateCoreDump(
}
char* program = nullptr;
char* pidarg = nullptr;
BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, dumpName, dumpType, flags);
BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, dumpName, nullptr, dumpType, flags);
if (result)
{
result = PROCCreateCrashDump(argvCreateDump);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册