| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -5,6 +5,7 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <cstring>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <ctime>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <filesystem>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <fmt/format.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <windows.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include "yuzu/mini_dump.h"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include "yuzu/startup_checks.h"
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -12,6 +13,8 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				// dbghelp.h must be included after windows.h
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <dbghelp.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				namespace MiniDump {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_INFORMATION* info,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    EXCEPTION_POINTERS* pep) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    char file_name[255];
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -23,7 +26,7 @@ void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (file_handle == nullptr || file_handle == INVALID_HANDLE_VALUE) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "CreateFileA failed. Error: %d\n", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "CreateFileA failed. Error: {}", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -34,9 +37,9 @@ void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                                     dump_type, (pep != 0) ? info : 0, 0, 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (write_dump_status) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "MiniDump created: %s\n", file_name);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "MiniDump created: {}", file_name);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "MiniDumpWriteDump failed. Error: %d\n", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "MiniDumpWriteDump failed. Error: {}", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // Close the file
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -48,15 +51,15 @@ void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    HANDLE thread_handle = OpenThread(THREAD_GET_CONTEXT, false, deb_ev.dwThreadId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (thread_handle == nullptr) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "OpenThread failed (%d)\n", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "OpenThread failed ({})", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // Get child process context
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    CONTEXT context;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    std::memset(&context, 0, sizeof(context));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    CONTEXT context = {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    context.ContextFlags = CONTEXT_ALL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!GetThreadContext(thread_handle, &context)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "GetThreadContext failed (%d)\n", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "GetThreadContext failed ({})", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -73,7 +76,7 @@ void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    CreateMiniDump(pi.hProcess, pi.dwProcessId, &info, &ep);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (CloseHandle(thread_handle) == 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "error: CloseHandle(thread_handle) failed (%d)\n", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "error: CloseHandle(thread_handle) failed ({})", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -86,67 +89,22 @@ bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!SpawnChild(arg0, &pi, 0)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr, "warning: continuing without crash dumps\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr, "warning: continuing without crash dumps");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const bool can_debug = DebugActiveProcess(pi.dwProcessId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!can_debug) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        std::fprintf(stderr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                     "warning: DebugActiveProcess failed (%d), continuing without crash dumps\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                     GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fmt::print(stderr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                   "warning: DebugActiveProcess failed ({}), continuing without crash dumps",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                   GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void DebugDebuggee(PROCESS_INFORMATION& pi) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    DEBUG_EVENT deb_ev;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    std::memset(&deb_ev, 0, sizeof(deb_ev));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    while (deb_ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const bool wait_success = WaitForDebugEvent(&deb_ev, INFINITE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (!wait_success) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            std::fprintf(stderr, "error: WaitForDebugEvent failed (%d)\n", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        switch (deb_ev.dwDebugEventCode) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case OUTPUT_DEBUG_STRING_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case CREATE_PROCESS_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case CREATE_THREAD_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case EXIT_PROCESS_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case EXIT_THREAD_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case LOAD_DLL_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case RIP_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case UNLOAD_DLL_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // Continue on all other debug events
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case EXCEPTION_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // We want to generate a crash dump if we are seeing the same exception again.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (!deb_ev.u.Exception.dwFirstChance) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                std::fprintf(stderr, "Creating MiniDump on ExceptionCode: 0x%08x %s\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                             record.ExceptionCode, ExceptionName(record.ExceptionCode));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                DumpFromDebugEvent(deb_ev, pi);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // Continue without handling the exception.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // Lets the debuggee use its own exception handler.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // - If one does not exist, we will see the exception once more where we make a minidump
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            //     for. Then when it reaches here again, yuzu will probably crash.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // - DBG_CONTINUE on an exception that the debuggee does not handle can set us up for an
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            //     infinite loop of exceptions.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				const char* ExceptionName(DWORD exception) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static const char* ExceptionName(DWORD exception) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    switch (exception) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    case EXCEPTION_ACCESS_VIOLATION:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return "EXCEPTION_ACCESS_VIOLATION";
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -193,6 +151,52 @@ const char* ExceptionName(DWORD exception) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    case EXCEPTION_INVALID_HANDLE:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return "EXCEPTION_INVALID_HANDLE";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    default:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return nullptr;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return "unknown exception type";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void DebugDebuggee(PROCESS_INFORMATION& pi) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    DEBUG_EVENT deb_ev = {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    while (deb_ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const bool wait_success = WaitForDebugEvent(&deb_ev, INFINITE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (!wait_success) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            fmt::print(stderr, "error: WaitForDebugEvent failed ({})", GetLastError());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        switch (deb_ev.dwDebugEventCode) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case OUTPUT_DEBUG_STRING_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case CREATE_PROCESS_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case CREATE_THREAD_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case EXIT_PROCESS_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case EXIT_THREAD_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case LOAD_DLL_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case RIP_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case UNLOAD_DLL_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // Continue on all other debug events
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        case EXCEPTION_DEBUG_EVENT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // We want to generate a crash dump if we are seeing the same exception again.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (!deb_ev.u.Exception.dwFirstChance) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                fmt::print(stderr, "Creating MiniDump on ExceptionCode: 0x{:08x} {}\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                           record.ExceptionCode, ExceptionName(record.ExceptionCode));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                DumpFromDebugEvent(deb_ev, pi);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // Continue without handling the exception.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // Lets the debuggee use its own exception handler.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // - If one does not exist, we will see the exception once more where we make a minidump
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            //     for. Then when it reaches here again, yuzu will probably crash.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // - DBG_CONTINUE on an exception that the debuggee does not handle can set us up for an
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            //     infinite loop of exceptions.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} // namespace MiniDump
 | 
			
		
		
	
	
		
			
				
					
					| 
						 
							
							
							
						 
					 | 
				
			
			 | 
			 | 
			
				 
 |