summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar lat9nq2022-07-18 21:36:26 -0400
committerGravatar lat9nq2022-09-04 21:36:05 -0400
commite339ec0e00905821dbb4fee8e45a2514555f5b0e (patch)
treecd902de955922083625bd0ae49a367f75ba5a9a3
parentmini_dump: Cleanup and add comments (diff)
downloadyuzu-e339ec0e00905821dbb4fee8e45a2514555f5b0e.tar.gz
yuzu-e339ec0e00905821dbb4fee8e45a2514555f5b0e.tar.xz
yuzu-e339ec0e00905821dbb4fee8e45a2514555f5b0e.zip
mini_dump: Check for debugger before spawning a child
mini_dump: Clean up mini_dump: Fix MSVC error mini_dump: Silence MSVC warning C4700 Zero initialize deb_ev. mini_dump: Add license info
-rw-r--r--src/yuzu/mini_dump.cpp97
-rw-r--r--src/yuzu/mini_dump.h3
2 files changed, 37 insertions, 63 deletions
diff --git a/src/yuzu/mini_dump.cpp b/src/yuzu/mini_dump.cpp
index e60456d9b..b25067c10 100644
--- a/src/yuzu/mini_dump.cpp
+++ b/src/yuzu/mini_dump.cpp
@@ -1,3 +1,6 @@
1// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
1#include <cstdio> 4#include <cstdio>
2#include <cstring> 5#include <cstring>
3#include <ctime> 6#include <ctime>
@@ -16,28 +19,28 @@ void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_
16 std::strftime(file_name, 255, "yuzu-crash-%Y%m%d%H%M%S.dmp", std::localtime(&the_time)); 19 std::strftime(file_name, 255, "yuzu-crash-%Y%m%d%H%M%S.dmp", std::localtime(&the_time));
17 20
18 // Open the file 21 // Open the file
19 HANDLE file_handle = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE, 0, nullptr, 22 HANDLE file_handle = CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
20 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); 23 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
21
22 if ((file_handle != nullptr) && (file_handle != INVALID_HANDLE_VALUE)) {
23 // Create the minidump
24 const MINIDUMP_TYPE dump_type = MiniDumpNormal;
25 24
26 const bool write_dump_status = MiniDumpWriteDump(process_handle, process_id, file_handle, 25 if (file_handle == nullptr || file_handle == INVALID_HANDLE_VALUE) {
27 dump_type, (pep != 0) ? info : 0, 0, 0); 26 std::fprintf(stderr, "CreateFileA failed. Error: %d\n", GetLastError());
27 return;
28 }
28 29
29 if (!write_dump_status) { 30 // Create the minidump
30 std::fprintf(stderr, "MiniDumpWriteDump failed. Error: %d\n", GetLastError()); 31 const MINIDUMP_TYPE dump_type = MiniDumpNormal;
31 } else {
32 std::fprintf(stderr, "MiniDump created: %s\n", file_name);
33 }
34 32
35 // Close the file 33 const bool write_dump_status = MiniDumpWriteDump(process_handle, process_id, file_handle,
36 CloseHandle(file_handle); 34 dump_type, (pep != 0) ? info : 0, 0, 0);
37 35
36 if (write_dump_status) {
37 std::fprintf(stderr, "MiniDump created: %s\n", file_name);
38 } else { 38 } else {
39 std::fprintf(stderr, "CreateFile failed. Error: %d\n", GetLastError()); 39 std::fprintf(stderr, "MiniDumpWriteDump failed. Error: %d\n", GetLastError());
40 } 40 }
41
42 // Close the file
43 CloseHandle(file_handle);
41} 44}
42 45
43void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) { 46void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) {
@@ -77,13 +80,13 @@ void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) {
77bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi) { 80bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi) {
78 std::memset(&pi, 0, sizeof(pi)); 81 std::memset(&pi, 0, sizeof(pi));
79 82
80 if (!SpawnChild(arg0, &pi, 0)) { 83 // Don't debug if we are already being debugged
81 std::fprintf(stderr, "warning: continuing without crash dumps\n"); 84 if (IsDebuggerPresent()) {
82 return false; 85 return false;
83 } 86 }
84 87
85 // Don't debug if we are already being debugged 88 if (!SpawnChild(arg0, &pi, 0)) {
86 if (IsDebuggerPresent()) { 89 std::fprintf(stderr, "warning: continuing without crash dumps\n");
87 return false; 90 return false;
88 } 91 }
89 92
@@ -100,8 +103,7 @@ bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi) {
100 103
101void DebugDebuggee(PROCESS_INFORMATION& pi) { 104void DebugDebuggee(PROCESS_INFORMATION& pi) {
102 DEBUG_EVENT deb_ev; 105 DEBUG_EVENT deb_ev;
103 const std::time_t start_time = std::time(nullptr); 106 std::memset(&deb_ev, 0, sizeof(deb_ev));
104 //~ bool seen_nonzero_thread_exit = false;
105 107
106 while (deb_ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) { 108 while (deb_ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) {
107 const bool wait_success = WaitForDebugEvent(&deb_ev, INFINITE); 109 const bool wait_success = WaitForDebugEvent(&deb_ev, INFINITE);
@@ -119,59 +121,28 @@ void DebugDebuggee(PROCESS_INFORMATION& pi) {
119 case LOAD_DLL_DEBUG_EVENT: 121 case LOAD_DLL_DEBUG_EVENT:
120 case RIP_EVENT: 122 case RIP_EVENT:
121 case UNLOAD_DLL_DEBUG_EVENT: 123 case UNLOAD_DLL_DEBUG_EVENT:
124 // Continue on all other debug events
122 ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE); 125 ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
123 break; 126 break;
124 //~ case EXIT_THREAD_DEBUG_EVENT: { 127 case EXCEPTION_DEBUG_EVENT:
125 //~ const DWORD& exit_code = deb_ev.u.ExitThread.dwExitCode;
126
127 //~ // Generate a crash dump on the first abnormal thread exit.
128 //~ // We don't want to generate on every abnormal thread exit since ALL the other
129 // threads ~ // in the application will follow by exiting with the same code. ~ if
130 //(!seen_nonzero_thread_exit && exit_code != 0) { ~ seen_nonzero_thread_exit = true; ~
131 // std::fprintf(stderr, ~ "Creating MiniDump on first non-zero thread exit: code
132 // 0x%08x\n", ~ exit_code);
133 //~ DumpFromDebugEvent(deb_ev, pi);
134 //~ }
135 //~ ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
136 //~ break;
137 //~ }
138 case EXCEPTION_DEBUG_EVENT: {
139 EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord; 128 EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
140 const std::time_t now = std::time(nullptr); 129
141 const std::time_t delta = now - start_time;
142
143 if (ExceptionName(record.ExceptionCode) == nullptr) {
144 int record_count = 0;
145 EXCEPTION_RECORD* next_record = &deb_ev.u.Exception.ExceptionRecord;
146 while (next_record != nullptr) {
147 std::fprintf(stderr,
148 "[%d] code(%d): 0x%08x\n\tflags: %08x %s\n\taddress: "
149 "0x%08x\n\tparameters: %d\n",
150 delta, record_count, next_record->ExceptionCode,
151 next_record->ExceptionFlags,
152 next_record->ExceptionFlags == EXCEPTION_NONCONTINUABLE
153 ? "noncontinuable"
154 : "",
155 next_record->ExceptionAddress, next_record->NumberParameters);
156 for (int i = 0; i < static_cast<int>(next_record->NumberParameters); i++) {
157 std::fprintf(stderr, "\t\t%0d: 0x%08x\n", i,
158 next_record->ExceptionInformation[i]);
159 }
160
161 record_count++;
162 next_record = next_record->ExceptionRecord;
163 }
164 }
165 // We want to generate a crash dump if we are seeing the same exception again. 130 // We want to generate a crash dump if we are seeing the same exception again.
166 if (!deb_ev.u.Exception.dwFirstChance) { 131 if (!deb_ev.u.Exception.dwFirstChance) {
167 std::fprintf(stderr, "Creating MiniDump on ExceptionCode: 0x%08x %s\n", 132 std::fprintf(stderr, "Creating MiniDump on ExceptionCode: 0x%08x %s\n",
168 record.ExceptionCode, ExceptionName(record.ExceptionCode)); 133 record.ExceptionCode, ExceptionName(record.ExceptionCode));
169 DumpFromDebugEvent(deb_ev, pi); 134 DumpFromDebugEvent(deb_ev, pi);
170 } 135 }
136
137 // Continue without handling the exception.
138 // Lets the debuggee use its own exception handler.
139 // - If one does not exist, we will see the exception once more where we make a minidump
140 // for. Then when it reaches here again, yuzu will probably crash.
141 // - DBG_CONTINUE on an exception that the debuggee does not handle can set us up for an
142 // infinite loop of exceptions.
171 ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); 143 ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
172 break; 144 break;
173 } 145 }
174 }
175 } 146 }
176} 147}
177 148
diff --git a/src/yuzu/mini_dump.h b/src/yuzu/mini_dump.h
index f6f5dc2c7..2052e5248 100644
--- a/src/yuzu/mini_dump.h
+++ b/src/yuzu/mini_dump.h
@@ -1,3 +1,6 @@
1// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
1#pragma once 4#pragma once
2 5
3#include <windows.h> 6#include <windows.h>