diff options
author | Ray Molenkamp <github@lazydodo.com> | 2020-04-30 23:00:11 +0300 |
---|---|---|
committer | Ray Molenkamp <github@lazydodo.com> | 2020-04-30 23:00:11 +0300 |
commit | 03f4d20bcf7f1819f31aa78315a7e8358928ca68 (patch) | |
tree | 8bafe10b62f8816b2015d0bcec58a6a8cda5d1f4 /source/blender/blenlib/intern | |
parent | 99cb6dbe652511eda388763c8b147a979efbd3ff (diff) |
Revert "Windows: Support backtraces on release builds."
Issues with older cmake.
Diffstat (limited to 'source/blender/blenlib/intern')
-rw-r--r-- | source/blender/blenlib/intern/system.c | 51 | ||||
-rw-r--r-- | source/blender/blenlib/intern/system_win32.c | 375 |
2 files changed, 43 insertions, 383 deletions
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index f0597b0e9e7..7d9ed2598a6 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -32,7 +32,11 @@ /* for backtrace and gethostname/GetComputerName */ #if defined(WIN32) # include <intrin.h> -# include "BLI_winstuff.h" +# include <windows.h> +# pragma warning(push) +# pragma warning(disable : 4091) +# include <dbghelp.h> +# pragma warning(pop) #else # include <execinfo.h> # include <unistd.h> @@ -70,8 +74,6 @@ int BLI_cpu_support_sse2(void) #endif } -/* Windows stackwalk lives in system_win32.c */ -#if !defined(_MSC_VER) /** * Write a backtrace into a file for systems which support it. */ @@ -79,9 +81,9 @@ void BLI_system_backtrace(FILE *fp) { /* ------------- */ /* Linux / Apple */ -# if defined(__linux__) || defined(__APPLE__) +#if defined(__linux__) || defined(__APPLE__) -# define SIZE 100 +# define SIZE 100 void *buffer[SIZE]; int nptrs; char **strings; @@ -96,15 +98,48 @@ void BLI_system_backtrace(FILE *fp) } free(strings); -# undef SIZE +# undef SIZE + + /* -------- */ + /* Windows */ +#elif defined(_MSC_VER) + +# ifndef NDEBUG +# define MAXSYMBOL 256 +# define SIZE 100 + unsigned short i; + void *stack[SIZE]; + unsigned short nframes; + SYMBOL_INFO *symbolinfo; + HANDLE process; + + process = GetCurrentProcess(); + + SymInitialize(process, NULL, TRUE); + + nframes = CaptureStackBackTrace(0, SIZE, stack, NULL); + symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table"); + symbolinfo->MaxNameLen = MAXSYMBOL - 1; + symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); + for (i = 0; i < nframes; i++) { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo); + + fprintf(fp, "%u: %s - 0x%0llX\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); + } + + MEM_freeN(symbolinfo); +# undef MAXSYMBOL +# undef SIZE # else + fprintf(fp, "Crash backtrace not supported on release builds\n"); +# endif /* NDEBUG */ +#else /* _MSC_VER */ /* ------------------ */ /* non msvc/osx/linux */ (void)fp; -# endif -} #endif +} /* end BLI_system_backtrace */ /* NOTE: The code for CPU brand string is adopted from Cycles. */ diff --git a/source/blender/blenlib/intern/system_win32.c b/source/blender/blenlib/intern/system_win32.c deleted file mode 100644 index f4c9057114c..00000000000 --- a/source/blender/blenlib/intern/system_win32.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * 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_fileops.h" -#include "BLI_path_util.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"); - if (BLI_exists(pdb_file)) { - HMODULE mod = GetModuleHandle(NULL); - if (mod) { - size_t size = BLI_file_size(pdb_file); - - /* 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)size); - if (module_base == 0) { - fprintf(stderr, - "Error loading symbols %s\n\terror:0x%.8x\n\tsize = %zi\n\tbase=0x%p\n", - pdb_file, - GetLastError(), - size, - (LPVOID)mod); - } - } - } - } -} - -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); -} |