1184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com/*
2184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com * Copyright 2013 Google Inc.
3184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com *
4184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com * Use of this source code is governed by a BSD-style license that can be
5184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com * found in the LICENSE file.
6184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com */
7184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
8184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#include "windows.h"
9184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#include "win_dbghelp.h"
10184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#include <process.h>
11184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#include <string.h>
12184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#include <stdlib.h>
13184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#include <stdio.h>
14184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
15184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// Remove prefix addresses. 18 = 2 * (8 digit hexa + 1 space).
16184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// e.g. "abcd1234 abcd1234 render_pdf!processInput
17184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define CDB_CALLSTACK_PREFIX (18)
18184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
19184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// CDB.EXE prints a lot of garbage and there is no argument to pass which
20184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// would remove all that noise.
21184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// Using eval feature that evaluates a number in hex and prints it to stdout
22184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// to mark where the callstack is printed.
23184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// For example, each thread's callstack will be marked with "12340000" at
24184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// the beginning and "12340001" at the end.
25184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// We just made up these numbers; they could be anything, as long as they
26184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// match up with their decimal equivalents.
27184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
28184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_THREAD_CALLSTACK_START_NUMBER "12340000"
29184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_THREAD_CALLSTACK_START "Evaluate expression: 305397760 = 12340000"
30184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
31184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_THREAD_CALLSTACK_STOP_NUMBER "12340001"
32184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_THREAD_CALLSTACK_STOP "Evaluate expression: 305397761 = 12340001"
33184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
34184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_EXCEPTION_CALLSTACK_START_NUMBER "12340002"
35184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_EXCEPTION_CALLSTACK_START "Evaluate expression: 305397762 = 12340002"
36184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
37184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_EXCEPTION_CALLSTACK_STOP_NUMBER "12340003"
38184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define MARKER_EXCEPTION_CALLSTACK_STOP "Evaluate expression: 305397763 = 12340003"
39184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
40184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// k - print stack
41184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// ? val - evaluate expression. Used to mark the log file.
42184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// .ecxr - load exception, if exception was thrown.
43184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// k - print the resolved stack by .ecxr
44184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// q - quit cdb.exe
45184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define CDB_PRINT_CALLSTACK_CURRENT_THREAD "? " MARKER_THREAD_CALLSTACK_START_NUMBER "; k; ? " MARKER_THREAD_CALLSTACK_STOP_NUMBER "; .ecxr; ? " MARKER_EXCEPTION_CALLSTACK_START_NUMBER "; k; ? " MARKER_EXCEPTION_CALLSTACK_STOP_NUMBER "; q"
46184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
47184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comstatic void strncpyOrSetBlank(char* dest, const char* src, size_t len) {
482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson  const char* srcOrEmptyString = (nullptr == src) ? "" : src;
49184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com  strncpy(dest, srcOrEmptyString, len);
50184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
51184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
52184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comchar debug_app_name[MAX_PATH] = "";
53eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.comvoid setAppName(const char* app_name) {
54184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    strncpyOrSetBlank(debug_app_name, app_name, sizeof(debug_app_name));
55184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
56184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
57184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comconst char* getAppName() {
58184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    return debug_app_name;
59184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
60184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
61184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comchar debug_binaries_path[MAX_PATH] = "";
62184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comvoid setBinariesPath(const char* binaries_path) {
63184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    strncpyOrSetBlank(debug_binaries_path, binaries_path,
64184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                      sizeof(debug_binaries_path));
65184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
66184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
67184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comconst char* getBinariesPath() {
68184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    return debug_binaries_path;
69184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
70184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
71184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comchar debug_app_version[100] = "";
72184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comvoid setAppVersion(const char* version) {
73184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    strncpyOrSetBlank(debug_app_version, version, sizeof(debug_app_version));
74184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
75184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
76184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comconst char* getAppVersion() {
77184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    return debug_app_version;
78184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
79184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
80184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comchar debug_cdb_path[MAX_PATH] = "";
81184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comvoid setCdbPath(const char* path) {
82184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com  strncpyOrSetBlank(debug_cdb_path, path, sizeof(debug_cdb_path));
83184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
84184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
85184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comconst char* getCdbPath() {
86184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    return debug_cdb_path;
87184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
88184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
89184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com/** Print all the lines of a CDB k command whicha are callstacks.
90184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com *  Callstack lines are marked by start and stop markers and they are prefixed
91184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com *  byt 2 hex adresses, which will not be reported.
92184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com */
93184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comstatic void printCallstack(const char* filename,
94184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           const char* start,
95184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           const char* stop) {
96184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    FILE* file = fopen(filename, "rt");
97184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    char line[1000];
98184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    bool started = false;
99184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    // Not the most performant code, but this will be used only to collect
100184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    // the callstack from a log files, only when the application had failed.
101184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    while (fgets(line, sizeof(line), file)) {
102184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        if (!started && strncmp(start, line, strlen(start)) == 0) {
103184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com            started = true;
104184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        } else if (started && strncmp(stop, line, strlen(stop)) == 0) {
105184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com            break;
106184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        } else if (started) {
107184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com            // Filter messages. Calstack lines contain "exe/dll!function"
1082880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            if (strchr(line, '!') != nullptr && strlen(line) > CDB_CALLSTACK_PREFIX) {
109184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                printf("%s", line + CDB_CALLSTACK_PREFIX);  // fgets includes \n already.
110184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com            }
111184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        }
112184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    }
113184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    fclose(file);
114184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
115184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
116184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#define BUILD_UNIQUE_FILENAME(var, ext, szPath, szAppName, szVersion, stLocalTime) \
117184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    sprintf(szFileName, "%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld" ext, \
118184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com           szPath, szAppName, szVersion, \
119184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com           stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, \
120184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com           stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, \
121eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com           GetCurrentProcessId(), GetCurrentThreadId());
122184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
123184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// Exception execution handler.  Exception is recognized. Transfer control to
124184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// the exception handler by executing the __except compound statement,
125184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com// then continue execution after the __except block.
126184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comint GenerateDumpAndPrintCallstack(EXCEPTION_POINTERS* pExceptionPointers) {
127184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    BOOL bMiniDumpSuccessful;
128eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com    char szPath[MAX_PATH];
129eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com    char szFileName[MAX_PATH];
130eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com    char szFileNameOutput[MAX_PATH];
131184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    const char* szAppName = getAppName();
132184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    const char* szVersion = getAppVersion();
133184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    DWORD dwBufferSize = MAX_PATH;
134184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    HANDLE hDumpFile;
135184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    SYSTEMTIME stLocalTime;
136184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    MINIDUMP_EXCEPTION_INFORMATION ExpParam;
137184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
138184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    GetLocalTime( &stLocalTime );
139184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    GetTempPath( dwBufferSize, szPath );
140184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
141184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    sprintf( szFileName, "%s%s", szPath, szAppName );
1422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    CreateDirectory( szFileName, nullptr );
143184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
144184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    BUILD_UNIQUE_FILENAME(szFileName, ".dmp", szPath, szAppName, szVersion, stLocalTime);
145184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    BUILD_UNIQUE_FILENAME(szFileNameOutput, ".out", szPath, szAppName, szVersion, stLocalTime);
146184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
147184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    hDumpFile = CreateFile(szFileName,
148eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com                           GENERIC_READ|GENERIC_WRITE,
149184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           FILE_SHARE_WRITE|FILE_SHARE_READ,
150184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           0,
151184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           CREATE_ALWAYS,
152184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           0,
153184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           0);
154184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
155184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    ExpParam.ThreadId = GetCurrentThreadId();
156184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    ExpParam.ExceptionPointers = pExceptionPointers;
157184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    ExpParam.ClientPointers = TRUE;
158184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
159184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(),
160eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com                                            GetCurrentProcessId(),
161184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                                            hDumpFile,
162184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                                            MiniDumpWithDataSegs,
163184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                                            &ExpParam,
1642880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                                            nullptr,
1652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                                            nullptr);
166184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
167184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    printf("MiniDump file:    %s\n", szFileName);
168184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    printf("App exe and pdb:  %s\n", getBinariesPath());
169184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
170184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    const char* cdbExePath = getCdbPath();
171184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    if (cdbExePath && *cdbExePath != '\0') {
172184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        printf("Cdb exe:          %s\n", cdbExePath);
173eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com
174184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        char command[MAX_PATH * 4];
175184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        sprintf(command, "%s -y \"%s\" -i \"%s\" -z \"%s\" -c \"%s\" -kqm >\"%s\"",
176184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                cdbExePath,
177184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                getBinariesPath(),
178184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                getBinariesPath(),
179184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                szFileName,
180184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                CDB_PRINT_CALLSTACK_CURRENT_THREAD,
181184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                szFileNameOutput);
182184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        system(command);
183184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
184184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        printf("\nThread Callstack:\n");
185eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com        printCallstack(szFileNameOutput,
186184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                       MARKER_THREAD_CALLSTACK_START,
187184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                       MARKER_THREAD_CALLSTACK_STOP);
188184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
189eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com        printf("\nException Callstack:\n");
190184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        printCallstack(szFileNameOutput,
191184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                       MARKER_EXCEPTION_CALLSTACK_START,
192184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                       MARKER_EXCEPTION_CALLSTACK_STOP);
193184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    } else {
194eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com        printf("Warning: CDB path not set up.\n");
195184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    }
196184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
197184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    return EXCEPTION_EXECUTE_HANDLER;
198184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
199184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
200184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com/** Sets the debugging variables. Input parameter is app location.
201184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com *  e.g out\Debug\render_pdfs.exe
202184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com *  This function expects the .pdb file to be in the same directory.
203184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com */
204184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.comvoid setUpDebuggingFromArgs(const char* vargs0) {
20581aca547caeb6d2a526e474eb7e49f234628966ebsalomon    size_t i = strlen(vargs0);
206184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
2072d137b6f8a29bf99c810aef35af6ba4ffc39932dborenet@google.com    if (i >= 4 && _stricmp(vargs0 - 4, ".exe") == 0) {
208184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        // Ignore .exe
209184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        i -= 4;
210184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    }
211184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
2125d8388b667d7b794cb83a66f04154f672207e3e2fmalita    size_t pos_period = i;
213184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
214184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    // Find last \ in path - this is Windows!
215184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    while (i >= 0 && vargs0[i] != '\\') {
216184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com        i--;
217184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    }
218184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
2195d8388b667d7b794cb83a66f04154f672207e3e2fmalita    size_t pos_last_slash = i;
220184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
221184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    char app_name[MAX_PATH];
222184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    strncpy(app_name, vargs0 + pos_last_slash + 1, pos_period - pos_last_slash - 1);
223184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    app_name[pos_period - pos_last_slash] = '\0';
224184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    setAppName(app_name);
225184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
226184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    char binaries_path[MAX_PATH];
227184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    strncpy(binaries_path, vargs0, pos_last_slash);
228184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    binaries_path[pos_last_slash] = '\0';
229184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    setBinariesPath(binaries_path);
230184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
231184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    setAppVersion("1.0");  // Dummy for now, but use revision instead if we use
232184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           // the minidump for anything else other than
233184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com                           // collecting the callstack.
234184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com
235184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    // cdb.exe is the app used to load the minidump which prints the callstack.
236184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    char cdbExePath[MAX_PATH];
237184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#ifdef _WIN64
238184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    sprintf(cdbExePath, "%s\\x64\\cdb.exe", SK_CDB_PATH);
239184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#else
240184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    sprintf(cdbExePath, "%s\\cdb.exe", SK_CDB_PATH);
241184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com#endif
242184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com    setCdbPath(cdbExePath);
243184487c8083e4e3958f9efe6fb6a9b1d4865fdf5edisonn@google.com}
244