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";
70 return "UNKNOWN EXCEPTION";
78 if (GetModuleHandleEx(
79 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
static_cast<LPCSTR
>(address), &
mod))
81 if (GetModuleFileName(
mod, buffer,
size)) {
82 PathStripPath(buffer);
92 LPBYTE lpBuffer =
nullptr;
93 DWORD verSize = GetFileVersionInfoSize(file, &verHandle);
95 LPSTR verData = (LPSTR)
MEM_callocN(verSize,
"crash module version");
97 if (GetFileVersionInfo(file, verHandle, verSize, verData)) {
98 if (VerQueryValue(verData,
"\\", (VOID FAR * FAR *)&lpBuffer, &
size)) {
100 VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer;
104 if (verInfo->dwSignature == 0xfeef04bd) {
108 (verInfo->dwFileVersionMS >> 16) & 0xffff,
109 (verInfo->dwFileVersionMS >> 0) & 0xffff,
110 (verInfo->dwFileVersionLS >> 16) & 0xffff,
111 (verInfo->dwFileVersionLS >> 0) & 0xffff);
123 fprintf(fp,
"Exception Record:\n\n");
125 "ExceptionCode : %s\n",
127 fprintf(fp,
"Exception Address : 0x%p\n", record->ExceptionAddress);
129 fprintf(fp,
"Exception Module : %s\n",
module);
130 fprintf(fp,
"Exception Flags : 0x%.8x\n", record->ExceptionFlags);
131 fprintf(fp,
"Exception Parameters : 0x%x\n", record->NumberParameters);
132 for (DWORD idx = 0; idx < record->NumberParameters; idx++) {
133 fprintf(fp,
"\tParameters[%d] : 0x%p\n", idx, (LPVOID *)record->ExceptionInformation[idx]);
135 if (record->ExceptionRecord) {
136 fprintf(fp,
"Nested ");
144 const int max_symbol_length = 100;
148 PSYMBOL_INFO symbolinfo =
static_cast<PSYMBOL_INFO
>(
149 MEM_callocN(
sizeof(SYMBOL_INFO) + max_symbol_length *
sizeof(
char),
"crash Symbol table"));
150 symbolinfo->MaxNameLen = max_symbol_length - 1;
151 symbolinfo->SizeOfStruct =
sizeof(SYMBOL_INFO);
153 STACKFRAME frame = {0};
154 DWORD machineType = 0;
156 frame.AddrPC.Offset = context->Rip;
157 frame.AddrPC.Mode = AddrModeFlat;
158 frame.AddrFrame.Offset = context->Rsp;
159 frame.AddrFrame.Mode = AddrModeFlat;
160 frame.AddrStack.Offset = context->Rsp;
161 frame.AddrStack.Mode = AddrModeFlat;
162 machineType = IMAGE_FILE_MACHINE_AMD64;
163#elif defined(_M_ARM64)
164 frame.AddrPC.Offset = context->Pc;
165 frame.AddrPC.Mode = AddrModeFlat;
166 frame.AddrFrame.Offset = context->Fp;
167 frame.AddrFrame.Mode = AddrModeFlat;
168 frame.AddrStack.Offset = context->Sp;
169 frame.AddrStack.Mode = AddrModeFlat;
170 machineType = IMAGE_FILE_MACHINE_ARM64;
174 if (StackWalk64(machineType,
180 SymFunctionTableAccess64,
184 if (frame.AddrPC.Offset) {
189 if (SymFromAddr(GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), 0, symbolinfo)) {
190 fprintf(fp,
"%-20s:0x%p %s",
module, (LPVOID)symbolinfo->Address, symbolinfo->Name);
191 IMAGEHLP_LINE lineinfo;
192 lineinfo.SizeOfStruct =
sizeof(lineinfo);
193 DWORD displacement = 0;
194 if (SymGetLineFromAddr(
195 GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), &displacement, &lineinfo))
197 fprintf(fp,
" %s:%d", lineinfo.FileName, lineinfo.LineNumber);
205 (LPVOID)frame.AddrPC.Offset,
206 "Symbols not available");
226 CONTEXT context = {0};
227 context.ContextFlags = CONTEXT_ALL;
230 if (hThread != GetCurrentThread()) {
231 SuspendThread(hThread);
232 bool success = GetThreadContext(hThread, &context);
233 ResumeThread(hThread);
235 fprintf(fp,
"Cannot get thread context : 0x0%.8x\n", GetLastError());
240 RtlCaptureContext(&context);
247 fprintf(fp,
"Loaded Modules :\n");
248 HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
249 if (hModuleSnap == INVALID_HANDLE_VALUE) {
254 me32.dwSize =
sizeof(MODULEENTRY32);
256 if (!Module32First(hModuleSnap, &me32)) {
257 CloseHandle(hModuleSnap);
258 fprintf(fp,
" Error getting module list.\n");
263 if (me32.th32ProcessID == GetCurrentProcessId()) {
264 char version[MAX_PATH];
267 IMAGEHLP_MODULE64 m64;
268 m64.SizeOfStruct =
sizeof(m64);
269 if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)me32.modBaseAddr, &m64)) {
271 "0x%p %-20s %s %s %s\n",
276 m64.PdbUnmatched ?
"[unmatched]" :
"");
279 fprintf(fp,
"0x%p %-20s %s\n", me32.modBaseAddr, version, me32.szModule);
282 }
while (Module32Next(hModuleSnap, &me32));
287 fprintf(fp,
"Threads:\n");
288 HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
291 hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
292 if (hThreadSnap == INVALID_HANDLE_VALUE) {
293 fprintf(fp,
"Unable to retrieve threads list.\n");
297 te32.dwSize =
sizeof(THREADENTRY32);
299 if (!Thread32First(hThreadSnap, &te32)) {
300 CloseHandle(hThreadSnap);
304 if (te32.th32OwnerProcessID == GetCurrentProcessId()) {
305 if (GetCurrentThreadId() != te32.th32ThreadID) {
306 fprintf(fp,
"Thread : %.8x\n", te32.th32ThreadID);
307 HANDLE ht = OpenThread(THREAD_ALL_ACCESS,
FALSE, te32.th32ThreadID);
312 }
while (Thread32Next(hThreadSnap, &te32));
313 CloseHandle(hThreadSnap);
318 fprintf(fp,
"Stack trace:\n");
320 if (exception_info && exception_info->ExceptionRecord->ExceptionAddress) {
323 CONTEXT TempContext = *exception_info->ContextRecord;
334 IMAGEHLP_MODULE64 m64;
335 m64.SizeOfStruct =
sizeof(m64);
336 if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)GetModuleHandle(
nullptr), &m64)) {
337 return m64.GlobalSymbols;
349 char pdb_file[MAX_PATH] = {0};
352 if (GetModuleFileNameA(
nullptr, pdb_file,
sizeof(pdb_file))) {
354 PathRemoveFileSpecA(pdb_file);
356 PathAppendA(pdb_file,
"blender.pdb");
357 if (PathFileExistsA(pdb_file)) {
358 HMODULE
mod = GetModuleHandle(
nullptr);
360 WIN32_FILE_ATTRIBUTE_DATA file_data;
361 if (GetFileAttributesExA(pdb_file, GetFileExInfoStandard, &file_data)) {
364 SymUnloadModule64(GetCurrentProcess(), (DWORD64)
mod);
366 DWORD64 module_base = SymLoadModule(GetCurrentProcess(),
371 (DWORD)file_data.nFileSizeLow);
372 if (module_base == 0) {
374 "Error loading symbols %s\n\terror:0x%.8x\n\tsize = %d\n\tbase=0x%p\n",
377 file_data.nFileSizeLow,
388 const EXCEPTION_POINTERS *exception_info =
static_cast<const EXCEPTION_POINTERS *
>(os_info);
389 SymInitialize(GetCurrentProcess(),
nullptr, TRUE);
391 if (exception_info) {
408 const EXCEPTION_POINTERS *exception =
static_cast<const EXCEPTION_POINTERS *
>(os_info);
410 exception->ExceptionRecord->ExceptionCode);
411 LPVOID address = exception->ExceptionRecord->ExceptionAddress;
412 CHAR modulename[MAX_PATH];
414 DWORD threadId = GetCurrentThreadId();
428 fprintf(stderr, message);
438 OSVERSIONINFOEX osvi;
439 ZeroMemory(&osvi,
sizeof(OSVERSIONINFOEX));
440 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
441 if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {
442 return "Unknown System";
445 std::string version = std::to_string(osvi.dwMajorVersion) +
"-" +
446 std::to_string(osvi.dwMajorVersion) +
"." +
447 std::to_string(osvi.dwMinorVersion) +
"." +
448 std::to_string(osvi.dwBuildNumber) +
"-SP" +
449 std::to_string(osvi.wServicePackMajor);
453 std::string architecture;
454 switch (si.wProcessorArchitecture) {
455 case PROCESSOR_ARCHITECTURE_AMD64:
456 architecture =
"64 Bits";
458 case PROCESSOR_ARCHITECTURE_INTEL:
459 architecture =
"32 Bits";
461 case PROCESSOR_ARCHITECTURE_ARM:
462 architecture =
"ARM Architecture";
464 case PROCESSOR_ARCHITECTURE_ARM64:
465 architecture =
"ARM64 Architecture";
467 case PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64:
468 architecture =
"ARM32 on Windows 64-bit";
470 case PROCESSOR_ARCHITECTURE_IA32_ON_ARM64:
471 architecture =
"IA32 on ARM64";
474 architecture =
"Unknown Architecture";
477 return "Windows-" + version +
" " + architecture;
486 wchar_t executable_path[MAX_PATH];
487 DWORD nSize = GetModuleFileNameW(
nullptr, executable_path, MAX_PATH);
488 if (nSize == 0 || nSize == MAX_PATH) {
497 if (wcscpy_s(path,
size, executable_path) != 0) {
502 if (!PathRemoveFileSpecW(executable_path)) {
506 if (!PathAppendW(executable_path,
L"blender-launcher.exe")) {
512 DWORD attributes = GetFileAttributesW(executable_path);
513 if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
518 if (wcslen(executable_path) + 1 >
size) {
524 if (wcscpy_s(path,
size, executable_path) != 0) {
535 size_t len =
str.length();
538 size_t encoded_len_max =
len * 3 + 1;
540 char *encoded_str =
new char[encoded_len_max];
544 std::wstring
result(encoded_str, encoded_str + strlen(encoded_str));
546 delete[] encoded_str;
552 const char *filepath_relaunch,
553 const char *gpu_name,
554 const char *build_version)
561 wchar_t *filepath_relaunch_utf16 = filepath_relaunch[0] ?
565 std::wstring full_message_16 =
566 L"A problem has caused the program to stop functioning correctly. If you know the steps to "
567 L"reproduce this issue, please submit a bug report.\n"
569 L"The crash log can be found at:\n" +
570 std::wstring(filepath_crashlog_utf16);
572 TASKDIALOGCONFIG config = {0};
573 const TASKDIALOG_BUTTON buttons[] = {
574 {IDRETRY,
L"Restart"},
579 {IDOK,
L"Report a Bug"},
581 {IDHELP,
L"View Crash Log"},
585 config.cbSize =
sizeof(config);
586 config.hwndParent = GetActiveWindow();
587 config.hInstance = 0;
588 config.dwCommonButtons = 0;
589 config.pszMainIcon = TD_ERROR_ICON;
590 config.pszWindowTitle =
L"Blender";
591 config.pszMainInstruction =
L"Blender has stopped working";
592 config.pszContent = full_message_16.c_str();
593 config.pButtons = buttons;
598 const wchar_t *filepath_crashlog_utf16;
599 const wchar_t *filepath_relaunch_utf16;
600 const char *gpu_name;
601 const char *build_version;
602 }
data = {filepath_crashlog_utf16, filepath_relaunch_utf16, gpu_name, build_version};
603 config.lpCallbackData =
reinterpret_cast<LONG_PTR
>(&
data);
606 config.pfCallback = [](HWND ,
610 LONG_PTR dwRefData) -> HRESULT {
611 const Data *data_ptr =
reinterpret_cast<const Data *
>(dwRefData);
612 if (uNotification != TDN_BUTTON_CLICKED) {
615 int pnButton =
static_cast<int>(wParam);
621 wchar_t executable_path[MAX_PATH];
623 std::wstring parameters;
624 if (data_ptr->filepath_relaunch_utf16) {
626 parameters =
L"\"" + std::wstring(data_ptr->filepath_relaunch_utf16) +
L"\"";
633 nullptr,
L"open", executable_path, parameters.c_str(),
nullptr, SW_SHOWNORMAL);
640 nullptr,
L"open", data_ptr->filepath_crashlog_utf16,
nullptr,
nullptr, SW_SHOWNORMAL);
646 L"https://redirect.blender.org/"
653 ShellExecuteW(
nullptr,
L"open", link.c_str(),
nullptr,
nullptr, SW_SHOWNORMAL);
661 TaskDialogIndirect(&config,
nullptr,
nullptr,
nullptr);
662 free((
void *)filepath_crashlog_utf16);
663 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)