| 
									
										
										
										
											2020-05-01 07:37:48 -06:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bli | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <Windows.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <dbghelp.h>
 | 
					
						
							|  |  |  | #include <shlwapi.h>
 | 
					
						
							|  |  |  | #include <tlhelp32.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static EXCEPTION_POINTERS *current_exception; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char *bli_windows_get_exception_description(const DWORD exceptioncode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (exceptioncode) { | 
					
						
							|  |  |  |     case EXCEPTION_ACCESS_VIOLATION: | 
					
						
							|  |  |  |       return "EXCEPTION_ACCESS_VIOLATION"; | 
					
						
							|  |  |  |     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: | 
					
						
							|  |  |  |       return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; | 
					
						
							|  |  |  |     case EXCEPTION_BREAKPOINT: | 
					
						
							|  |  |  |       return "EXCEPTION_BREAKPOINT"; | 
					
						
							|  |  |  |     case EXCEPTION_DATATYPE_MISALIGNMENT: | 
					
						
							|  |  |  |       return "EXCEPTION_DATATYPE_MISALIGNMENT"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_DENORMAL_OPERAND: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_DENORMAL_OPERAND"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_DIVIDE_BY_ZERO: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_INEXACT_RESULT: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_INEXACT_RESULT"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_INVALID_OPERATION: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_INVALID_OPERATION"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_OVERFLOW: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_OVERFLOW"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_STACK_CHECK: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_STACK_CHECK"; | 
					
						
							|  |  |  |     case EXCEPTION_FLT_UNDERFLOW: | 
					
						
							|  |  |  |       return "EXCEPTION_FLT_UNDERFLOW"; | 
					
						
							|  |  |  |     case EXCEPTION_ILLEGAL_INSTRUCTION: | 
					
						
							|  |  |  |       return "EXCEPTION_ILLEGAL_INSTRUCTION"; | 
					
						
							|  |  |  |     case EXCEPTION_IN_PAGE_ERROR: | 
					
						
							|  |  |  |       return "EXCEPTION_IN_PAGE_ERROR"; | 
					
						
							|  |  |  |     case EXCEPTION_INT_DIVIDE_BY_ZERO: | 
					
						
							|  |  |  |       return "EXCEPTION_INT_DIVIDE_BY_ZERO"; | 
					
						
							|  |  |  |     case EXCEPTION_INT_OVERFLOW: | 
					
						
							|  |  |  |       return "EXCEPTION_INT_OVERFLOW"; | 
					
						
							|  |  |  |     case EXCEPTION_INVALID_DISPOSITION: | 
					
						
							|  |  |  |       return "EXCEPTION_INVALID_DISPOSITION"; | 
					
						
							|  |  |  |     case EXCEPTION_NONCONTINUABLE_EXCEPTION: | 
					
						
							|  |  |  |       return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; | 
					
						
							|  |  |  |     case EXCEPTION_PRIV_INSTRUCTION: | 
					
						
							|  |  |  |       return "EXCEPTION_PRIV_INSTRUCTION"; | 
					
						
							|  |  |  |     case EXCEPTION_SINGLE_STEP: | 
					
						
							|  |  |  |       return "EXCEPTION_SINGLE_STEP"; | 
					
						
							|  |  |  |     case EXCEPTION_STACK_OVERFLOW: | 
					
						
							|  |  |  |       return "EXCEPTION_STACK_OVERFLOW"; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return "UNKNOWN EXCEPTION"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_windows_get_module_name(LPVOID address, PCHAR buffer, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   HMODULE mod; | 
					
						
							|  |  |  |   buffer[0] = 0; | 
					
						
							|  |  |  |   if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &mod)) { | 
					
						
							|  |  |  |     if (GetModuleFileName(mod, buffer, size)) { | 
					
						
							|  |  |  |       PathStripPath(buffer); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_windows_get_module_version(const char *file, char *buffer, size_t buffersize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   buffer[0] = 0; | 
					
						
							|  |  |  |   DWORD verHandle = 0; | 
					
						
							|  |  |  |   UINT size = 0; | 
					
						
							|  |  |  |   LPBYTE lpBuffer = NULL; | 
					
						
							|  |  |  |   DWORD verSize = GetFileVersionInfoSize(file, &verHandle); | 
					
						
							|  |  |  |   if (verSize != 0) { | 
					
						
							|  |  |  |     LPSTR verData = (LPSTR)MEM_callocN(verSize, "crash module version"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (GetFileVersionInfo(file, verHandle, verSize, verData)) { | 
					
						
							|  |  |  |       if (VerQueryValue(verData, "\\", (VOID FAR * FAR *)&lpBuffer, &size)) { | 
					
						
							|  |  |  |         if (size) { | 
					
						
							|  |  |  |           VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer; | 
					
						
							|  |  |  |           /* Magic value from
 | 
					
						
							|  |  |  |            * https://docs.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
 | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  |           if (verInfo->dwSignature == 0xfeef04bd) { | 
					
						
							|  |  |  |             BLI_snprintf(buffer, | 
					
						
							|  |  |  |                          buffersize, | 
					
						
							|  |  |  |                          "%d.%d.%d.%d", | 
					
						
							|  |  |  |                          (verInfo->dwFileVersionMS >> 16) & 0xffff, | 
					
						
							|  |  |  |                          (verInfo->dwFileVersionMS >> 0) & 0xffff, | 
					
						
							|  |  |  |                          (verInfo->dwFileVersionLS >> 16) & 0xffff, | 
					
						
							|  |  |  |                          (verInfo->dwFileVersionLS >> 0) & 0xffff); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     MEM_freeN(verData); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_windows_system_backtrace_exception_record(FILE *fp, PEXCEPTION_RECORD record) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char module[MAX_PATH]; | 
					
						
							|  |  |  |   fprintf(fp, "Exception Record:\n\n"); | 
					
						
							|  |  |  |   fprintf(fp, | 
					
						
							|  |  |  |           "ExceptionCode         : %s\n", | 
					
						
							|  |  |  |           bli_windows_get_exception_description(record->ExceptionCode)); | 
					
						
							|  |  |  |   fprintf(fp, "Exception Address     : 0x%p\n", record->ExceptionAddress); | 
					
						
							|  |  |  |   bli_windows_get_module_name(record->ExceptionAddress, module, sizeof(module)); | 
					
						
							|  |  |  |   fprintf(fp, "Exception Module      : %s\n", module); | 
					
						
							|  |  |  |   fprintf(fp, "Exception Flags       : 0x%.8x\n", record->ExceptionFlags); | 
					
						
							|  |  |  |   fprintf(fp, "Exception Parameters  : 0x%x\n", record->NumberParameters); | 
					
						
							|  |  |  |   for (DWORD idx = 0; idx < record->NumberParameters; idx++) { | 
					
						
							|  |  |  |     fprintf(fp, "\tParameters[%d] : 0x%p\n", idx, (LPVOID *)record->ExceptionInformation[idx]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (record->ExceptionRecord) { | 
					
						
							|  |  |  |     fprintf(fp, "Nested "); | 
					
						
							|  |  |  |     bli_windows_system_backtrace_exception_record(fp, record->ExceptionRecord); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   fprintf(fp, "\n\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool BLI_windows_system_backtrace_run_trace(FILE *fp, HANDLE hThread, PCONTEXT context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const int max_symbol_length = 100; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool result = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PSYMBOL_INFO symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + max_symbol_length * sizeof(char), | 
					
						
							|  |  |  |                                         "crash Symbol table"); | 
					
						
							|  |  |  |   symbolinfo->MaxNameLen = max_symbol_length - 1; | 
					
						
							|  |  |  |   symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   STACKFRAME frame = {0}; | 
					
						
							|  |  |  |   frame.AddrPC.Offset = context->Rip; | 
					
						
							|  |  |  |   frame.AddrPC.Mode = AddrModeFlat; | 
					
						
							|  |  |  |   frame.AddrFrame.Offset = context->Rsp; | 
					
						
							|  |  |  |   frame.AddrFrame.Mode = AddrModeFlat; | 
					
						
							|  |  |  |   frame.AddrStack.Offset = context->Rsp; | 
					
						
							|  |  |  |   frame.AddrStack.Mode = AddrModeFlat; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (true) { | 
					
						
							|  |  |  |     if (StackWalk64(IMAGE_FILE_MACHINE_AMD64, | 
					
						
							|  |  |  |                     GetCurrentProcess(), | 
					
						
							|  |  |  |                     hThread, | 
					
						
							|  |  |  |                     &frame, | 
					
						
							|  |  |  |                     context, | 
					
						
							|  |  |  |                     NULL, | 
					
						
							|  |  |  |                     SymFunctionTableAccess64, | 
					
						
							|  |  |  |                     SymGetModuleBase64, | 
					
						
							|  |  |  |                     0)) { | 
					
						
							|  |  |  |       if (frame.AddrPC.Offset) { | 
					
						
							|  |  |  |         char module[MAX_PATH]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bli_windows_get_module_name((LPVOID)frame.AddrPC.Offset, module, sizeof(module)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (SymFromAddr(GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), 0, symbolinfo)) { | 
					
						
							|  |  |  |           fprintf(fp, "%-20s:0x%p  %s", module, (LPVOID)symbolinfo->Address, symbolinfo->Name); | 
					
						
							|  |  |  |           IMAGEHLP_LINE lineinfo; | 
					
						
							|  |  |  |           lineinfo.SizeOfStruct = sizeof(lineinfo); | 
					
						
							|  |  |  |           DWORD displacement = 0; | 
					
						
							|  |  |  |           if (SymGetLineFromAddr( | 
					
						
							|  |  |  |                   GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), &displacement, &lineinfo)) { | 
					
						
							|  |  |  |             fprintf(fp, " %s:%d", lineinfo.FileName, lineinfo.LineNumber); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           fprintf(fp, "\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           fprintf(fp, | 
					
						
							|  |  |  |                   "%-20s:0x%p  %s\n", | 
					
						
							|  |  |  |                   module, | 
					
						
							|  |  |  |                   (LPVOID)frame.AddrPC.Offset, | 
					
						
							|  |  |  |                   "Symbols not available"); | 
					
						
							|  |  |  |           result = false; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   MEM_freeN(symbolinfo); | 
					
						
							|  |  |  |   fprintf(fp, "\n\n"); | 
					
						
							|  |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_windows_system_backtrace_stack_thread(FILE *fp, HANDLE hThread) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (hThread != GetCurrentThread()) { | 
					
						
							|  |  |  |     SuspendThread(hThread); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   CONTEXT context; | 
					
						
							|  |  |  |   context.ContextFlags = CONTEXT_ALL; | 
					
						
							|  |  |  |   if (!GetThreadContext(hThread, &context)) { | 
					
						
							|  |  |  |     fprintf(fp, "Cannot get thread context : 0x0%.8x\n", GetLastError()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   BLI_windows_system_backtrace_run_trace(fp, hThread, &context); | 
					
						
							|  |  |  |   if (hThread != GetCurrentThread()) { | 
					
						
							|  |  |  |     ResumeThread(hThread); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_windows_system_backtrace_modules(FILE *fp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   fprintf(fp, "Loaded Modules :\n"); | 
					
						
							|  |  |  |   HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); | 
					
						
							|  |  |  |   if (hModuleSnap == INVALID_HANDLE_VALUE) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MODULEENTRY32 me32; | 
					
						
							|  |  |  |   me32.dwSize = sizeof(MODULEENTRY32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!Module32First(hModuleSnap, &me32)) { | 
					
						
							|  |  |  |     CloseHandle(hModuleSnap);  // Must clean up the snapshot object!
 | 
					
						
							|  |  |  |     fprintf(fp, " Error getting module list.\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   do { | 
					
						
							|  |  |  |     if (me32.th32ProcessID == GetCurrentProcessId()) { | 
					
						
							|  |  |  |       char version[MAX_PATH]; | 
					
						
							|  |  |  |       bli_windows_get_module_version(me32.szExePath, version, sizeof(version)); | 
					
						
							|  |  |  |       fprintf(fp, "0x%p %-20s %s\n", me32.modBaseAddr, version, me32.szModule); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } while (Module32Next(hModuleSnap, &me32)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_windows_system_backtrace_threads(FILE *fp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   fprintf(fp, "Threads:\n"); | 
					
						
							|  |  |  |   HANDLE hThreadSnap = INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |   THREADENTRY32 te32; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); | 
					
						
							|  |  |  |   if (hThreadSnap == INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |     fprintf(fp, "Unable to retrieve threads list.\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   te32.dwSize = sizeof(THREADENTRY32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!Thread32First(hThreadSnap, &te32)) { | 
					
						
							|  |  |  |     CloseHandle(hThreadSnap); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   do { | 
					
						
							|  |  |  |     if (te32.th32OwnerProcessID == GetCurrentProcessId()) { | 
					
						
							|  |  |  |       if (GetCurrentThreadId() != te32.th32ThreadID) { | 
					
						
							|  |  |  |         fprintf(fp, "Thread : %.8x\n", te32.th32ThreadID); | 
					
						
							|  |  |  |         HANDLE ht = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); | 
					
						
							|  |  |  |         bli_windows_system_backtrace_stack_thread(fp, ht); | 
					
						
							|  |  |  |         CloseHandle(ht); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } while (Thread32Next(hThreadSnap, &te32)); | 
					
						
							|  |  |  |   CloseHandle(hThreadSnap); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool BLI_windows_system_backtrace_stack(FILE *fp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   fprintf(fp, "Stack trace:\n"); | 
					
						
							|  |  |  |   CONTEXT TempContext = *current_exception->ContextRecord; | 
					
						
							|  |  |  |   return BLI_windows_system_backtrace_run_trace(fp, GetCurrentThread(), &TempContext); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool bli_private_symbols_loaded() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   IMAGEHLP_MODULE64 m64; | 
					
						
							|  |  |  |   m64.SizeOfStruct = sizeof(m64); | 
					
						
							|  |  |  |   if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)GetModuleHandle(NULL), &m64)) { | 
					
						
							|  |  |  |     PathStripPath(m64.LoadedPdbName); | 
					
						
							|  |  |  |     return BLI_strcasecmp(m64.LoadedPdbName, "blender_private.pdb") == 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bli_load_symbols() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* If this is a developer station and the private pdb is already loaded leave it be. */ | 
					
						
							|  |  |  |   if (bli_private_symbols_loaded()) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   char pdb_file[MAX_PATH] = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get the currently executing image */ | 
					
						
							|  |  |  |   if (GetModuleFileNameA(NULL, pdb_file, sizeof(pdb_file))) { | 
					
						
							|  |  |  |     /* remove the filename */ | 
					
						
							|  |  |  |     PathRemoveFileSpecA(pdb_file); | 
					
						
							|  |  |  |     /* append blender.pdb */ | 
					
						
							|  |  |  |     PathAppendA(pdb_file, "blender.pdb"); | 
					
						
							| 
									
										
										
										
											2020-05-03 12:07:22 -06:00
										 |  |  |     if (PathFileExistsA(pdb_file)) { | 
					
						
							| 
									
										
										
										
											2020-05-01 07:37:48 -06:00
										 |  |  |       HMODULE mod = GetModuleHandle(NULL); | 
					
						
							|  |  |  |       if (mod) { | 
					
						
							| 
									
										
										
										
											2020-05-03 12:07:22 -06:00
										 |  |  |         WIN32_FILE_ATTRIBUTE_DATA file_data; | 
					
						
							|  |  |  |         if (GetFileAttributesExA(pdb_file, GetFileExInfoStandard, &file_data)) { | 
					
						
							|  |  |  |           /* SymInitialize will try to load symbols on its own, so we first must unload whatever it
 | 
					
						
							|  |  |  |            * did trying to help */ | 
					
						
							|  |  |  |           SymUnloadModule64(GetCurrentProcess(), (DWORD64)mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           DWORD64 module_base = SymLoadModule(GetCurrentProcess(), | 
					
						
							|  |  |  |                                               NULL, | 
					
						
							|  |  |  |                                               pdb_file, | 
					
						
							|  |  |  |                                               NULL, | 
					
						
							|  |  |  |                                               (DWORD64)mod, | 
					
						
							|  |  |  |                                               (DWORD)file_data.nFileSizeLow); | 
					
						
							|  |  |  |           if (module_base == 0) { | 
					
						
							|  |  |  |             fprintf(stderr, | 
					
						
							|  |  |  |                     "Error loading symbols %s\n\terror:0x%.8x\n\tsize = %d\n\tbase=0x%p\n", | 
					
						
							|  |  |  |                     pdb_file, | 
					
						
							|  |  |  |                     GetLastError(), | 
					
						
							|  |  |  |                     file_data.nFileSizeLow, | 
					
						
							|  |  |  |                     (LPVOID)mod); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2020-05-01 07:37:48 -06:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BLI_system_backtrace(FILE *fp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SymInitialize(GetCurrentProcess(), NULL, TRUE); | 
					
						
							|  |  |  |   bli_load_symbols(); | 
					
						
							|  |  |  |   bli_windows_system_backtrace_exception_record(fp, current_exception->ExceptionRecord); | 
					
						
							|  |  |  |   if (BLI_windows_system_backtrace_stack(fp)) { | 
					
						
							|  |  |  |     /* When the blender symbols are missing the stack traces will be unreliable
 | 
					
						
							|  |  |  |      * so only run if the previous step completed successfully. */ | 
					
						
							|  |  |  |     bli_windows_system_backtrace_threads(fp); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   bli_windows_system_backtrace_modules(fp); | 
					
						
							|  |  |  |   fputc(0, fp); /* Give our selves a nice zero terminator for later on */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BLI_windows_handle_exception(EXCEPTION_POINTERS *exception) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   current_exception = exception; | 
					
						
							|  |  |  |   fprintf(stderr, | 
					
						
							|  |  |  |           "Error   : %s\n", | 
					
						
							|  |  |  |           bli_windows_get_exception_description(exception->ExceptionRecord->ExceptionCode)); | 
					
						
							|  |  |  |   fflush(stderr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LPVOID address = exception->ExceptionRecord->ExceptionAddress; | 
					
						
							|  |  |  |   fprintf(stderr, "Address : 0x%p\n", address); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CHAR modulename[MAX_PATH]; | 
					
						
							|  |  |  |   bli_windows_get_module_name(address, modulename, sizeof(modulename)); | 
					
						
							|  |  |  |   fprintf(stderr, "Module  : %s\n", modulename); | 
					
						
							|  |  |  |   fflush(stderr); | 
					
						
							|  |  |  | } |