Chromium Code Reviews| Index: tools/win_dbghelp.cpp |
| =================================================================== |
| --- tools/win_dbghelp.cpp (revision 0) |
| +++ tools/win_dbghelp.cpp (revision 0) |
| @@ -0,0 +1,188 @@ |
| +/* |
| + * Copyright 2013 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#ifdef SK_BUILD_FOR_WIN32 |
| + |
| +#include "win_dbghelp.h" |
| +#include <process.h> |
| +#include <string.h> |
| +#include <stdlib.h> |
| + |
| +#define CDB_PRINT_CALLSTACK_CURRENT_THREAD "k" |
| + |
| +char debug_app_name[MAX_PATH] = ""; |
| +void setAppName(const char* app_name) { |
| + if (app_name == NULL) { |
| + app_name = ""; |
| + } |
| + strcpy(debug_app_name, app_name); |
| +} |
| + |
| +const char* getAppName() { |
| + return debug_app_name; |
| +} |
| + |
| +char debug_binaries_path[MAX_PATH] = ""; |
| +void setBinariesPath(const char* binaries_path) { |
| + if (binaries_path == NULL) { |
| + binaries_path = ""; |
| + } |
| + strcpy(debug_binaries_path, binaries_path); |
| +} |
| + |
| +const char* getBinariesPath() { |
| + return debug_binaries_path; |
| +} |
| + |
| +char debug_app_version[100] = ""; |
| +void setAppVersion(const char* version) { |
| + if (version == NULL) { |
| + version = ""; |
| + } |
| + strcpy(debug_app_version, version); |
| +} |
| + |
| +const char* getAppVersion() { |
| + return debug_app_version; |
| +} |
| + |
| +char debug_cdb_path[MAX_PATH] = ""; |
| +void setCdbPath(const char* path) { |
| + if (path == NULL) { |
| + path = ""; |
| + } |
| + strcpy(debug_cdb_path, path); |
| +} |
| + |
| +const char* getCdbPath() { |
| + return debug_cdb_path; |
| +} |
| + |
| +int GenerateDumpAndPrintCallstack(EXCEPTION_POINTERS* pExceptionPointers) { |
| + BOOL bMiniDumpSuccessful; |
| + char szPath[MAX_PATH]; |
| + char szFileName[MAX_PATH]; |
| + char* szAppName = getAppName(); |
| + char* szVersion = getAppVersion(); |
| + DWORD dwBufferSize = MAX_PATH; |
| + HANDLE hDumpFile; |
| + SYSTEMTIME stLocalTime; |
| + MINIDUMP_EXCEPTION_INFORMATION ExpParam; |
| + |
| + GetLocalTime( &stLocalTime ); |
| + GetTempPath( dwBufferSize, szPath ); |
| + |
| + sprintf( szFileName, "%s%s", szPath, szAppName ); |
| + CreateDirectory( szFileName, NULL ); |
| + |
| + sprintf( szFileName, "%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", |
| + szPath, szAppName, szVersion, |
| + stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, |
| + stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, |
| + GetCurrentProcessId(), GetCurrentThreadId()); |
| + |
| + SkDebugf("Minidump saved to %s.\n", szFileName); |
| + |
| + hDumpFile = CreateFile(szFileName, |
| + GENERIC_READ|GENERIC_WRITE, |
| + FILE_SHARE_WRITE|FILE_SHARE_READ, |
| + 0, |
| + CREATE_ALWAYS, |
| + 0, |
| + 0); |
| + |
| + ExpParam.ThreadId = GetCurrentThreadId(); |
| + ExpParam.ExceptionPointers = pExceptionPointers; |
| + ExpParam.ClientPointers = TRUE; |
| + |
| + bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), |
| + GetCurrentProcessId(), |
| + hDumpFile, |
| + MiniDumpWithDataSegs, |
| + &ExpParam, |
| + NULL, |
| + NULL); |
| + |
| + const char* cdbExePath = getCdbPath(); |
| + |
| + if (cdbExePath && *cdbExePath != '\0') { |
| + char exePath[MAX_PATH]; |
| + sprintf(exePath, "%s\\%s.exe", getBinariesPath(), getAppName()); |
| + |
| + char pdbPath[MAX_PATH]; |
| + sprintf(pdbPath, "%s\\%s.pdb", getBinariesPath(), getAppName()); |
| + |
| + _execl(cdbExePath, |
| + "-y", pdbPath, |
| + "-i", exePath, |
| + "-z", szFileName, |
| + "-c", CDB_PRINT_CALLSTACK_CURRENT_THREAD); |
| + } else { |
| + SkDebugf("Warning: CDB path not not set up.\n"); |
| + } |
| + |
| + return EXCEPTION_EXECUTE_HANDLER; |
| +} |
| + |
| +void setUpDebuggingFromArgs(const char* vargs0) { |
| + // remove .exe |
| + int i = strlen(vargs0); |
| + |
| + i--; |
| + if (i < 0 || (vargs0[i] != 'E' && vargs0[i] != 'e')) { |
| + return; |
| + } |
| + |
| + i--; |
| + if (i < 0 || (vargs0[i] != 'X' && vargs0[i] != 'x')) { |
| + return; |
| + } |
| + |
| + i--; |
| + if (i < 0 || (vargs0[i] != 'E' && vargs0[i] != 'e')) { |
| + return; |
| + } |
| + |
| + i--; |
| + if (i < 0 || vargs0[i] != '.') { |
| + return; |
| + } |
| + |
| + int pos_period = i; |
| + |
| + // Find last \ in path - this is Windows! |
| + while (i >= 0 && vargs0[i] != '\\') { |
| + i--; |
| + } |
| + |
| + if (i < 0) { |
| + return; |
| + } |
| + |
| + int pos_last_slash = i; |
| + |
| + char app_name[MAX_PATH]; |
| + strncpy(vargs0 + pos_last_slash + 1, app_name, pos_period - pos_last_slash - 1); |
| + app_name[pos_period - pos_last_slash] = '\0'; |
| + setAppName(app_name); |
| + |
| + char binaries_path[MAX_PATH]; |
| + strncpy(vargs0, binaries_path, pos_last_slash - 1); |
| + binaries_path[pos_last_slash] = '\0'; |
| + setBinariesPath(binaries_path); |
| + |
| + setAppVersion("1.0"); // Dummy for now, but use revision instead if we use |
| + // the minidump for anything else other than |
| + // collecting the callstack. |
| +#ifdef _WIN64 |
|
edisonn
2013/02/28 16:56:23
is there a better way to get the path to an exe pa
borenet
2013/02/28 20:28:19
I think an environment variable would be okay. I
|
| + setCdbPath(getenv("CDB_PATH_X64")); |
| +#else |
| + setCdbPath(getenv("CDB_PATH")); |
| +#endif |
| +} |
| + |
| +#endif // SK_BUILD_FOR_WIN32 |