28 switch (exceptioncode) {
29 case EXCEPTION_ACCESS_VIOLATION:
30 return "EXCEPTION_ACCESS_VIOLATION";
31 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
32 return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
33 case EXCEPTION_BREAKPOINT:
34 return "EXCEPTION_BREAKPOINT";
35 case EXCEPTION_DATATYPE_MISALIGNMENT:
36 return "EXCEPTION_DATATYPE_MISALIGNMENT";
37 case EXCEPTION_FLT_DENORMAL_OPERAND:
38 return "EXCEPTION_FLT_DENORMAL_OPERAND";
39 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
40 return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
41 case EXCEPTION_FLT_INEXACT_RESULT:
42 return "EXCEPTION_FLT_INEXACT_RESULT";
43 case EXCEPTION_FLT_INVALID_OPERATION:
44 return "EXCEPTION_FLT_INVALID_OPERATION";
45 case EXCEPTION_FLT_OVERFLOW:
46 return "EXCEPTION_FLT_OVERFLOW";
47 case EXCEPTION_FLT_STACK_CHECK:
48 return "EXCEPTION_FLT_STACK_CHECK";
49 case EXCEPTION_FLT_UNDERFLOW:
50 return "EXCEPTION_FLT_UNDERFLOW";
51 case EXCEPTION_ILLEGAL_INSTRUCTION:
52 return "EXCEPTION_ILLEGAL_INSTRUCTION";
53 case EXCEPTION_IN_PAGE_ERROR:
54 return "EXCEPTION_IN_PAGE_ERROR";
55 case EXCEPTION_INT_DIVIDE_BY_ZERO:
56 return "EXCEPTION_INT_DIVIDE_BY_ZERO";
57 case EXCEPTION_INT_OVERFLOW:
58 return "EXCEPTION_INT_OVERFLOW";
59 case EXCEPTION_INVALID_DISPOSITION:
60 return "EXCEPTION_INVALID_DISPOSITION";
61 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
62 return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
63 case EXCEPTION_PRIV_INSTRUCTION:
64 return "EXCEPTION_PRIV_INSTRUCTION";
65 case EXCEPTION_SINGLE_STEP:
66 return "EXCEPTION_SINGLE_STEP";
67 case EXCEPTION_STACK_OVERFLOW:
68 return "EXCEPTION_STACK_OVERFLOW";
73 return "Microsoft C++ Exception";
75 return "UNKNOWN EXCEPTION";
83 if (GetModuleHandleEx(
84 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
static_cast<LPCSTR
>(address), &
mod))
86 if (GetModuleFileName(
mod, buffer,
size)) {
87 PathStripPath(buffer);
97 LPBYTE lpBuffer =
nullptr;
98 DWORD verSize = GetFileVersionInfoSize(file, &verHandle);
100 LPSTR verData = (LPSTR)
MEM_callocN(verSize,
"crash module version");
102 if (GetFileVersionInfo(file, verHandle, verSize, verData)) {
103 if (VerQueryValue(verData,
"\\", (VOID FAR * FAR *)&lpBuffer, &
size)) {
105 VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer;
109 if (verInfo->dwSignature == 0xfeef04bd) {
113 (verInfo->dwFileVersionMS >> 16) & 0xffff,
114 (verInfo->dwFileVersionMS >> 0) & 0xffff,
115 (verInfo->dwFileVersionLS >> 16) & 0xffff,
116 (verInfo->dwFileVersionLS >> 0) & 0xffff);
128 fprintf(fp,
"Exception Record:\n\n");
130 "ExceptionCode : %s (0x%.8x)\n",
132 record->ExceptionCode);
133 fprintf(fp,
"Exception Address : 0x%p\n", record->ExceptionAddress);
135 fprintf(fp,
"Exception Module : %s\n",
module);
136 fprintf(fp,
"Exception Flags : 0x%.8x\n", record->ExceptionFlags);
137 fprintf(fp,
"Exception Parameters : 0x%x\n", record->NumberParameters);
140 if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && record->NumberParameters == 2) {
142 switch (record->ExceptionInformation[0]) {
157 "\tParameters[0] (action) : 0x%p (%s)\n",
158 (LPVOID *)record->ExceptionInformation[0],
160 fprintf(fp,
"\tParameters[1] (address) : 0x%p\n", (LPVOID *)record->ExceptionInformation[1]);
163 for (DWORD idx = 0; idx < record->NumberParameters; idx++) {
164 fprintf(fp,
"\tParameters[%d] : 0x%p\n", idx, (LPVOID *)record->ExceptionInformation[idx]);
167 if (record->ExceptionRecord) {
168 fprintf(fp,
"Nested ");
176 const int max_symbol_length = 100;
180 PSYMBOL_INFO symbolinfo =
static_cast<PSYMBOL_INFO
>(
181 MEM_callocN(
sizeof(SYMBOL_INFO) + max_symbol_length *
sizeof(
char),
"crash Symbol table"));
182 symbolinfo->MaxNameLen = max_symbol_length - 1;
183 symbolinfo->SizeOfStruct =
sizeof(SYMBOL_INFO);
185 STACKFRAME frame = {0};
186 DWORD machineType = 0;
188 frame.AddrPC.Offset = context->Rip;
189 frame.AddrPC.Mode = AddrModeFlat;
190 frame.AddrFrame.Offset = context->Rsp;
191 frame.AddrFrame.Mode = AddrModeFlat;
192 frame.AddrStack.Offset = context->Rsp;
193 frame.AddrStack.Mode = AddrModeFlat;
194 machineType = IMAGE_FILE_MACHINE_AMD64;
195#elif defined(_M_ARM64)
196 frame.AddrPC.Offset = context->Pc;
197 frame.AddrPC.Mode = AddrModeFlat;
198 frame.AddrFrame.Offset = context->Fp;
199 frame.AddrFrame.Mode = AddrModeFlat;
200 frame.AddrStack.Offset = context->Sp;
201 frame.AddrStack.Mode = AddrModeFlat;
202 machineType = IMAGE_FILE_MACHINE_ARM64;
206 if (StackWalk64(machineType,
212 SymFunctionTableAccess64,
216 if (frame.AddrPC.Offset) {
221 if (SymFromAddr(GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), 0, symbolinfo)) {
222 fprintf(fp,
"%-20s:0x%p %s",
module, (LPVOID)symbolinfo->Address, symbolinfo->Name);
223 IMAGEHLP_LINE lineinfo;
224 lineinfo.SizeOfStruct =
sizeof(lineinfo);
225 DWORD displacement = 0;
226 if (SymGetLineFromAddr(
227 GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), &displacement, &lineinfo))
229 fprintf(fp,
" %s:%d", lineinfo.FileName, lineinfo.LineNumber);
237 (LPVOID)frame.AddrPC.Offset,
238 "Symbols not available");
258 CONTEXT context = {0};
259 context.ContextFlags = CONTEXT_ALL;
262 if (hThread != GetCurrentThread()) {
263 SuspendThread(hThread);
264 bool success = GetThreadContext(hThread, &context);
265 ResumeThread(hThread);
267 fprintf(fp,
"Cannot get thread context : 0x0%.8x\n", GetLastError());
272 RtlCaptureContext(&context);
279 fprintf(fp,
"Loaded Modules :\n");
280 HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
281 if (hModuleSnap == INVALID_HANDLE_VALUE) {
286 me32.dwSize =
sizeof(MODULEENTRY32);
288 if (!Module32First(hModuleSnap, &me32)) {
289 CloseHandle(hModuleSnap);
290 fprintf(fp,
" Error getting module list.\n");
295 if (me32.th32ProcessID == GetCurrentProcessId()) {
296 char version[MAX_PATH];
299 IMAGEHLP_MODULE64 m64;
300 m64.SizeOfStruct =
sizeof(m64);
301 if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)me32.modBaseAddr, &m64)) {
303 "0x%p %-20s %s %s %s\n",
308 m64.PdbUnmatched ?
"[unmatched]" :
"");
311 fprintf(fp,
"0x%p %-20s %s\n", me32.modBaseAddr, version, me32.szModule);
314 }
while (Module32Next(hModuleSnap, &me32));
319 fprintf(fp,
"Threads:\n");
320 HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
323 hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
324 if (hThreadSnap == INVALID_HANDLE_VALUE) {
325 fprintf(fp,
"Unable to retrieve threads list.\n");
329 te32.dwSize =
sizeof(THREADENTRY32);
331 if (!Thread32First(hThreadSnap, &te32)) {
332 CloseHandle(hThreadSnap);
336 if (te32.th32OwnerProcessID == GetCurrentProcessId()) {
337 if (GetCurrentThreadId() != te32.th32ThreadID) {
338 fprintf(fp,
"Thread : %.8x\n", te32.th32ThreadID);
339 HANDLE ht = OpenThread(THREAD_ALL_ACCESS,
FALSE, te32.th32ThreadID);
344 }
while (Thread32Next(hThreadSnap, &te32));
345 CloseHandle(hThreadSnap);
350 fprintf(fp,
"Stack trace:\n");
352 if (exception_info && exception_info->ExceptionRecord->ExceptionAddress) {
355 CONTEXT TempContext = *exception_info->ContextRecord;
366 IMAGEHLP_MODULE64 m64;
367 m64.SizeOfStruct =
sizeof(m64);
368 if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)GetModuleHandle(
nullptr), &m64)) {
369 return m64.GlobalSymbols;
381 char pdb_file[MAX_PATH] = {0};
384 if (GetModuleFileNameA(
nullptr, pdb_file,
sizeof(pdb_file))) {
386 PathRemoveFileSpecA(pdb_file);
388 PathAppendA(pdb_file,
"blender.pdb");
389 if (PathFileExistsA(pdb_file)) {
390 HMODULE
mod = GetModuleHandle(
nullptr);
392 WIN32_FILE_ATTRIBUTE_DATA file_data;
393 if (GetFileAttributesExA(pdb_file, GetFileExInfoStandard, &file_data)) {
396 SymUnloadModule64(GetCurrentProcess(), (DWORD64)
mod);
398 DWORD64 module_base = SymLoadModule(GetCurrentProcess(),
403 (DWORD)file_data.nFileSizeLow);
404 if (module_base == 0) {
406 "Error loading symbols %s\n\terror:0x%.8x\n\tsize = %d\n\tbase=0x%p\n",
409 file_data.nFileSizeLow,
420 const EXCEPTION_POINTERS *exception_info =
static_cast<const EXCEPTION_POINTERS *
>(os_info);
421 SymInitialize(GetCurrentProcess(),
nullptr, TRUE);
423 if (exception_info) {
440 const EXCEPTION_POINTERS *exception =
static_cast<const EXCEPTION_POINTERS *
>(os_info);
442 exception->ExceptionRecord->ExceptionCode);
443 LPVOID address = exception->ExceptionRecord->ExceptionAddress;
444 CHAR modulename[MAX_PATH];
446 DWORD threadId = GetCurrentThreadId();
460 fprintf(stderr, message);
470 OSVERSIONINFOEX osvi;
471 ZeroMemory(&osvi,
sizeof(OSVERSIONINFOEX));
472 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
473 if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {
474 return "Unknown System";
477 std::string version = std::to_string(osvi.dwMajorVersion) +
"-" +
478 std::to_string(osvi.dwMajorVersion) +
"." +
479 std::to_string(osvi.dwMinorVersion) +
"." +
480 std::to_string(osvi.dwBuildNumber) +
"-SP" +
481 std::to_string(osvi.wServicePackMajor);
485 std::string architecture;
486 switch (si.wProcessorArchitecture) {
487 case PROCESSOR_ARCHITECTURE_AMD64:
488 architecture =
"64 Bits";
490 case PROCESSOR_ARCHITECTURE_INTEL:
491 architecture =
"32 Bits";
493 case PROCESSOR_ARCHITECTURE_ARM:
494 architecture =
"ARM Architecture";
496 case PROCESSOR_ARCHITECTURE_ARM64:
497 architecture =
"ARM64 Architecture";
499 case PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64:
500 architecture =
"ARM32 on Windows 64-bit";
502 case PROCESSOR_ARCHITECTURE_IA32_ON_ARM64:
503 architecture =
"IA32 on ARM64";
506 architecture =
"Unknown Architecture";
509 return "Windows-" + version +
" " + architecture;
518 wchar_t executable_path[MAX_PATH];
519 DWORD nSize = GetModuleFileNameW(
nullptr, executable_path, MAX_PATH);
520 if (nSize == 0 || nSize == MAX_PATH) {
529 if (wcscpy_s(path,
size, executable_path) != 0) {
534 if (!PathRemoveFileSpecW(executable_path)) {
538 if (!PathAppendW(executable_path,
L"blender-launcher.exe")) {
544 DWORD attributes = GetFileAttributesW(executable_path);
545 if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
550 if (wcslen(executable_path) + 1 >
size) {
556 if (wcscpy_s(path,
size, executable_path) != 0) {
567 size_t len =
str.length();
570 size_t encoded_len_max =
len * 3 + 1;
572 char *encoded_str =
new char[encoded_len_max];
576 std::wstring
result(encoded_str, encoded_str + strlen(encoded_str));
578 delete[] encoded_str;
584 const char *filepath_relaunch,
585 const char *gpu_name,
586 const char *build_version)
593 wchar_t *filepath_relaunch_utf16 = filepath_relaunch[0] ?
597 std::wstring full_message_16 =
598 L"A problem has caused the program to stop functioning correctly. If you know the steps to "
599 L"reproduce this issue, please submit a bug report.\n"
601 L"The crash log can be found at:\n" +
602 std::wstring(filepath_crashlog_utf16);
604 TASKDIALOGCONFIG config = {0};
605 const TASKDIALOG_BUTTON buttons[] = {{IDRETRY,
L"Restart"},
610 {IDOK,
L"Report a Bug"},
612 {IDHELP,
L"View Crash Log"},
613 {IDCLOSE,
L"Close"}};
615 config.cbSize =
sizeof(config);
616 config.hwndParent = GetActiveWindow();
617 config.hInstance = 0;
618 config.dwCommonButtons = 0;
619 config.pszMainIcon = TD_ERROR_ICON;
620 config.pszWindowTitle =
L"Blender";
621 config.pszMainInstruction =
L"Blender has stopped working";
622 config.pszContent = full_message_16.c_str();
623 config.pButtons = buttons;
628 const wchar_t *filepath_crashlog_utf16;
629 const wchar_t *filepath_relaunch_utf16;
630 const char *gpu_name;
631 const char *build_version;
632 }
data = {filepath_crashlog_utf16, filepath_relaunch_utf16, gpu_name, build_version};
633 config.lpCallbackData =
reinterpret_cast<LONG_PTR
>(&
data);
636 config.pfCallback = [](HWND ,
640 LONG_PTR dwRefData) -> HRESULT {
641 const Data *data_ptr =
reinterpret_cast<const Data *
>(dwRefData);
642 if (uNotification != TDN_BUTTON_CLICKED) {
645 int pnButton =
static_cast<int>(wParam);
651 wchar_t executable_path[MAX_PATH];
653 std::wstring parameters;
654 if (data_ptr->filepath_relaunch_utf16) {
656 parameters =
L"\"" + std::wstring(data_ptr->filepath_relaunch_utf16) +
L"\"";
663 nullptr,
L"open", executable_path, parameters.c_str(),
nullptr, SW_SHOWNORMAL);
670 nullptr,
L"open", data_ptr->filepath_crashlog_utf16,
nullptr,
nullptr, SW_SHOWNORMAL);
676 L"https://redirect.blender.org/"
683 ShellExecuteW(
nullptr,
L"open", link.c_str(),
nullptr,
nullptr, SW_SHOWNORMAL);
691 TaskDialogIndirect(&config,
nullptr,
nullptr,
nullptr);
692 free((
void *)filepath_crashlog_utf16);
693 free((
void *)filepath_relaunch_utf16);
void BLI_kdtree_nd_ free(KDTree *tree)
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
Read Guarded memory(de)allocation.
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)
static struct PyModuleDef module
static void bli_windows_get_module_version(const char *file, char *buffer, size_t buffersize)
static bool bli_windows_system_backtrace_stack_thread(FILE *fp, HANDLE hThread)
static std::wstring url_encode_wstring(const std::string &str)
static void bli_windows_get_module_name(LPVOID address, PCHAR buffer, size_t size)
void BLI_windows_exception_print_message(const void *os_info)
static void bli_windows_system_backtrace_modules(FILE *fp)
static void bli_windows_system_backtrace_exception_record(FILE *fp, PEXCEPTION_RECORD record)
static bool bli_private_symbols_loaded()
static std::string get_os_info()
static bool bli_windows_system_backtrace_stack(FILE *fp, const EXCEPTION_POINTERS *exception_info)
void BLI_windows_exception_show_dialog(const char *filepath_crashlog, const char *filepath_relaunch, const char *gpu_name, const char *build_version)
static void bli_windows_system_backtrace_threads(FILE *fp)
static void bli_load_symbols()
void BLI_system_backtrace_with_os_info(FILE *fp, const void *os_info)
static bool BLI_windows_system_backtrace_run_trace(FILE *fp, HANDLE hThread, PCONTEXT context)
static const char * bli_windows_get_exception_description(const DWORD exceptioncode)
static bool bli_executable_path_get(LPWSTR path, DWORD size)
bool url_encode(const char *str, char *dst, size_t dst_size)
Encodes a string into URL format by converting special characters into percent-encoded sequences.
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)