104PEXCEPTION_POINTERS pExceptionInfo)
109 return EXCEPTION_EXECUTE_HANDLER;
113 TCHAR module_folder_name[MAX_PATH];
114 GetModuleFileName(
nullptr, module_folder_name, MAX_PATH);
115 TCHAR* pos = _tcsrchr(module_folder_name,
'\\');
121 TCHAR crash_folder_path[MAX_PATH];
122 _stprintf_s(crash_folder_path, _T(
"%s\\%s"), module_folder_name,
CrashFolder);
123 if (!CreateDirectory(crash_folder_path,
nullptr))
125 if (GetLastError() != ERROR_ALREADY_EXISTS)
136 GetLocalTime(&systime);
138 crash_folder_path,
GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
141 crash_folder_path,
GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
148 FILE_FLAG_WRITE_THROUGH,
153 MINIDUMP_EXCEPTION_INFORMATION info;
154 info.ClientPointers = FALSE;
155 info.ExceptionPointers = pExceptionInfo;
156 info.ThreadId = GetCurrentThreadId();
158 MINIDUMP_USER_STREAM additionalStream = {};
159 MINIDUMP_USER_STREAM_INFORMATION additionalStreamInfo = {};
161 if (pExceptionInfo->ExceptionRecord->ExceptionCode ==
EXCEPTION_ASSERTION_FAILURE && pExceptionInfo->ExceptionRecord->NumberParameters > 0)
163 additionalStream.Type = CommentStreamA;
164 additionalStream.Buffer =
reinterpret_cast<PVOID
>(pExceptionInfo->ExceptionRecord->ExceptionInformation[0]);
165 additionalStream.BufferSize = strlen(
reinterpret_cast<char const*
>(pExceptionInfo->ExceptionRecord->ExceptionInformation[0])) + 1;
167 additionalStreamInfo.UserStreamArray = &additionalStream;
168 additionalStreamInfo.UserStreamCount = 1;
171 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
172 m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, &additionalStreamInfo,
nullptr);
190 return EXCEPTION_EXECUTE_HANDLER;
236 *szVersion = _T(
'\0');
243 RTL_OSVERSIONINFOEXW osvi = { };
244 osvi.dwOSVersionInfoSize =
sizeof(RTL_OSVERSIONINFOEXW);
245 NTSTATUS bVersionEx =
RtlGetVersion((PRTL_OSVERSIONINFOW)&osvi);
246 if (FAILED(bVersionEx))
248 osvi.dwOSVersionInfoSize =
sizeof(RTL_OSVERSIONINFOW);
253 TCHAR szCSDVersion[256];
254 ToTchar(osvi.szCSDVersion, szCSDVersion);
257 switch (osvi.dwPlatformId)
260 case VER_PLATFORM_WIN32_NT:
263 BYTE suiteMask = osvi.wReserved[0];
264 BYTE productType = osvi.wReserved[1];
266 WORD suiteMask = osvi.wSuiteMask;
267 BYTE productType = osvi.wProductType;
271 if (osvi.dwMajorVersion == 10)
273 if (productType == VER_NT_WORKSTATION)
274 _tcsncat(szVersion, _T(
"Windows 10 "), cntMax);
276 _tcsncat(szVersion, _T(
"Windows Server 2016 "), cntMax);
278 else if (osvi.dwMajorVersion == 6)
280 if (productType == VER_NT_WORKSTATION)
282 if (osvi.dwMinorVersion == 3)
283 _tcsncat(szVersion, _T(
"Windows 8.1 "), cntMax);
284 else if (osvi.dwMinorVersion == 2)
285 _tcsncat(szVersion, _T(
"Windows 8 "), cntMax);
286 else if (osvi.dwMinorVersion == 1)
287 _tcsncat(szVersion, _T(
"Windows 7 "), cntMax);
289 _tcsncat(szVersion, _T(
"Windows Vista "), cntMax);
291 else if (osvi.dwMinorVersion == 3)
292 _tcsncat(szVersion, _T(
"Windows Server 2012 R2 "), cntMax);
293 else if (osvi.dwMinorVersion == 2)
294 _tcsncat(szVersion, _T(
"Windows Server 2012 "), cntMax);
295 else if (osvi.dwMinorVersion == 1)
296 _tcsncat(szVersion, _T(
"Windows Server 2008 R2 "), cntMax);
298 _tcsncat(szVersion, _T(
"Windows Server 2008 "), cntMax);
300 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
301 _tcsncat(szVersion, _T(
"Microsoft Windows Server 2003 "), cntMax);
302 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
303 _tcsncat(szVersion, _T(
"Microsoft Windows XP "), cntMax);
304 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
305 _tcsncat(szVersion, _T(
"Microsoft Windows 2000 "), cntMax);
306 else if (osvi.dwMajorVersion <= 4)
307 _tcsncat(szVersion, _T(
"Microsoft Windows NT "), cntMax);
313 if (productType == VER_NT_WORKSTATION)
315 if (osvi.dwMajorVersion == 4)
316 _tcsncat(szVersion, _T(
"Workstation 4.0 "), cntMax);
317 else if (suiteMask & VER_SUITE_PERSONAL)
318 _tcsncat(szVersion, _T(
"Home Edition "), cntMax);
319 else if (suiteMask & VER_SUITE_EMBEDDEDNT)
320 _tcsncat(szVersion, _T(
"Embedded "), cntMax);
322 _tcsncat(szVersion, _T(
"Professional "), cntMax);
325 else if (productType == VER_NT_SERVER)
327 if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10)
329 if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
330 _tcsncat(szVersion, _T(
"Essentials "), cntMax);
331 else if (suiteMask & VER_SUITE_DATACENTER)
332 _tcsncat(szVersion, _T(
"Datacenter "), cntMax);
333 else if (suiteMask & VER_SUITE_ENTERPRISE)
334 _tcsncat(szVersion, _T(
"Enterprise "), cntMax);
336 _tcsncat(szVersion, _T(
"Standard "), cntMax);
338 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
340 if (suiteMask & VER_SUITE_DATACENTER)
341 _tcsncat(szVersion, _T(
"Datacenter Edition "), cntMax);
342 else if (suiteMask & VER_SUITE_ENTERPRISE)
343 _tcsncat(szVersion, _T(
"Enterprise Edition "), cntMax);
344 else if (suiteMask == VER_SUITE_BLADE)
345 _tcsncat(szVersion, _T(
"Web Edition "), cntMax);
347 _tcsncat(szVersion, _T(
"Standard Edition "), cntMax);
349 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
351 if (suiteMask & VER_SUITE_DATACENTER)
352 _tcsncat(szVersion, _T(
"Datacenter Server "), cntMax);
353 else if (suiteMask & VER_SUITE_ENTERPRISE)
354 _tcsncat(szVersion, _T(
"Advanced Server "), cntMax);
356 _tcsncat(szVersion, _T(
"Server "), cntMax);
360 if (suiteMask & VER_SUITE_ENTERPRISE)
361 _tcsncat(szVersion, _T(
"Server 4.0, Enterprise Edition "), cntMax);
363 _tcsncat(szVersion, _T(
"Server 4.0 "), cntMax);
369 if (osvi.dwMajorVersion == 4 && _tcsicmp(szCSDVersion, _T(
"Service Pack 6")) == 0)
375 lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey);
376 if (lRet == ERROR_SUCCESS)
378 _stprintf_s(wszTmp, _T(
"Service Pack 6a (Version %d.%d, Build %d)"),
379 osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
380 _tcsncat(szVersion, wszTmp, cntMax);
384 _stprintf_s(wszTmp, _T(
"%s (Version %d.%d, Build %d)"),
385 szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
386 _tcsncat(szVersion, wszTmp, cntMax);
392 if (!_tcslen(szCSDVersion))
393 _stprintf_s(wszTmp, _T(
"(Version %d.%d, Build %d)"),
394 osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
396 _stprintf_s(wszTmp, _T(
"%s (Version %d.%d, Build %d)"),
397 szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
398 _tcsncat(szVersion, wszTmp, cntMax);
403 _stprintf_s(wszTmp, _T(
"%s (Version %d.%d, Build %d)"),
404 szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
405 _tcsncat(szVersion, wszTmp, cntMax);
416 HRESULT hres = CoInitializeEx(
nullptr, COINIT_MULTITHREADED);
420 std::shared_ptr<void> com(
nullptr, [](
void*)
427 hres = CoInitializeSecurity(
432 RPC_C_AUTHN_LEVEL_DEFAULT,
433 RPC_C_IMP_LEVEL_IMPERSONATE,
444 std::shared_ptr<IWbemLocator> loc = []() -> std::shared_ptr<IWbemLocator>
446 IWbemLocator* tmp =
nullptr;
447 HRESULT hres = CoCreateInstance(
450 CLSCTX_INPROC_SERVER,
452 reinterpret_cast<LPVOID*
>(&tmp));
457 return { tmp, [](IWbemLocator* ptr) {
if (ptr) ptr->Release(); } };
467 std::shared_ptr<IWbemServices> svc = [loc]() ->std::shared_ptr<IWbemServices>
469 IWbemServices* tmp =
nullptr;
470 HRESULT hres = loc->ConnectServer(
471 bstr_t(L
"ROOT\\CIMV2"),
475 WBEM_FLAG_CONNECT_USE_MAX_WAIT,
484 return { tmp, [](IWbemServices* ptr) {
if (ptr) ptr->Release(); } };
492 hres = CoSetProxyBlanket(
497 RPC_C_AUTHN_LEVEL_CALL,
498 RPC_C_IMP_LEVEL_IMPERSONATE,
510 std::shared_ptr<IEnumWbemClassObject> queryResult = [svc]() -> std::shared_ptr<IEnumWbemClassObject>
512 IEnumWbemClassObject* tmp =
nullptr;
513 HRESULT hres = svc->ExecQuery(
515 bstr_t(
"SELECT Caption, CSDVersion FROM Win32_OperatingSystem"),
516 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
523 return { tmp, [](IEnumWbemClassObject* ptr) {
if (ptr) ptr->Release(); } };
533 IWbemClassObject* fields =
nullptr;
536 queryResult->Next(WBEM_INFINITE, 1, &fields, &rows);
542 fields->Get(L
"Caption", 0, &field,
nullptr,
nullptr);
543 TCHAR buf[256] = { };
545 _tcsncat(szVersion, buf, cntMax);
546 VariantClear(&field);
548 fields->Get(L
"CSDVersion", 0, &field,
nullptr,
nullptr);
549 if (field.vt == VT_BSTR)
551 _tcsncat(szVersion, _T(
" "), cntMax);
552 memset(buf, 0,
sizeof(buf));
555 _tcsncat(szVersion, buf, cntMax);
557 VariantClear(&field);
644PEXCEPTION_POINTERS pExceptionInfo)
649 GetLocalTime(&systime);
653 Log(_T(
"Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
654 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
658 Log(_T(
"\r\n//=====================================================\r\n"));
659 Log(_T(
"Exception code: %08X %s\r\n"),
660 pExceptionRecord->ExceptionCode,
664 pExceptionRecord->ExceptionAddress =
reinterpret_cast<PVOID
>(pExceptionRecord->ExceptionInformation[1]);
665 Log(_T(
"Assertion message: %s\r\n"), pExceptionRecord->ExceptionInformation[0]);
669 TCHAR szFaultingModule[MAX_PATH];
674 sizeof(szFaultingModule),
677#if defined(_M_IX86) || defined(_M_ARM)
678 Log(_T(
"Fault address: %08X %02X:%08X %s\r\n"),
679 pExceptionRecord->ExceptionAddress,
680 section, offset, szFaultingModule);
682#if defined(_M_X64) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined (_M_ARM64EC)
683 Log(_T(
"Fault address: %016I64X %02X:%016I64X %s\r\n"),
684 pExceptionRecord->ExceptionAddress,
685 section, offset, szFaultingModule);
688 PCONTEXT pCtx = pExceptionInfo->ContextRecord;
692 Log(_T(
"\r\nRegisters:\r\n"));
694 Log(_T(
"EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
695 , pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
696 pCtx->Esi, pCtx->Edi);
698 Log(_T(
"CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
699 Log(_T(
"SS:ESP:%04X:%08X EBP:%08X\r\n"),
700 pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
701 Log(_T(
"DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
702 pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
703 Log(_T(
"Flags:%08X\r\n"), pCtx->EFlags);
707 Log(_T(
"\r\nRegisters:\r\n"));
708 Log(_T(
"RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
709 _T(
"R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
710 , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
711 pCtx->Rsi, pCtx->Rdi, pCtx->R8, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);
712 Log(_T(
"CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
713 Log(_T(
"SS:RSP:%04X:%016I64X RBP:%08X\r\n"),
714 pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
715 Log(_T(
"DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
716 pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
717 Log(_T(
"Flags:%08X\r\n"), pCtx->EFlags);
721 Log(_T(
"\r\nRegisters:\r\n"));
722 Log(_T(
"X0:%016I64X\r\nX1:%016I64X\r\nX2:%016I64X\r\nX3:%016I64X\r\nX4:%016I64X\r\nX5:%016I64X\r\n"),
723 _T(
"X6:%016I64X\r\nX7:%016I64X\r\nX8:%016I64X\r\nX9:%016I64X\r\nX10:%016I64X\r\nX11:%016I64X\r\nX12:%016I64X\r\nX13:%016I64X\r\n"),
724 _T(
"X14:%016I64X\r\nX15:%016I64X\r\nX16:%016I64X\r\nX17:%016I64X\r\nX18:%016I64X\r\nX19:%016I64X\r\nX20:%016I64X\r\nX21:%016I64X\r\n"),
725 _T(
"X22:%016I64X\r\nX23:%016I64X\r\nX24:%016I64X\r\nX25:%016I64X\r\nX26:%016I64X\r\nX27:%016I64X\r\nX28:%016I64X\r\n"),
726 pCtx->X0, pCtx->X1, pCtx->X2, pCtx->X3, pCtx->X4, pCtx->X5,
727 pCtx->X6, pCtx->X7, pCtx->X8, pCtx->X9, pCtx->X10, pCtx->X11, pCtx->X12, pCtx->X13,
728 pCtx->X14, pCtx->X15, pCtx->X16, pCtx->X17, pCtx->X18, pCtx->X19, pCtx->X20, pCtx->X21,
729 pCtx->X22, pCtx->X23, pCtx->X24, pCtx->X25, pCtx->X26, pCtx->X27, pCtx->X28);
730 Log(_T(
"LR:%016I64X\r\n"), pCtx->Lr);
731 Log(_T(
"PC:%016I64X\r\n"), pCtx->Pc);
732 Log(_T(
"SP:%016I64X FP:%016I64X\r\n"), pCtx->Sp, pCtx->Fp);
733 Log(_T(
"Flags:%08X\r\n"), pCtx->Cpsr);
736 SymSetOptions(SYMOPT_DEFERRED_LOADS);
739 if (!SymInitialize(GetCurrentProcess(),
nullptr, TRUE))
743 Log(_T(
"SYMBOL HANDLER ERROR (THIS IS NOT THE CRASH ERROR)\r\n\r\n"));
744 Log(_T(
"Couldn't initialize symbol handler for process when generating crash report\r\n"));
746 Log(_T(
"THE BELOW CALL STACKS MIGHT HAVE MISSING OR INACCURATE FILE/FUNCTION NAMES\r\n\r\n"));
750 if (pExceptionRecord->ExceptionCode == 0xE06D7363 && pExceptionRecord->NumberParameters >= 2)
752 PVOID exceptionObject =
reinterpret_cast<PVOID
>(pExceptionRecord->ExceptionInformation[1]);
753 ThrowInfo
const* throwInfo =
reinterpret_cast<ThrowInfo const*
>(pExceptionRecord->ExceptionInformation[2]);
754#if _EH_RELATIVE_TYPEINFO
756 auto resolveExceptionRVA = [pExceptionRecord](
int32 rva) -> DWORD_PTR
758 return rva + (pExceptionRecord->NumberParameters >= 4 ? pExceptionRecord->ExceptionInformation[3] : 0);
762 auto resolveExceptionRVA = [](
void const* input) ->
void const* {
return input; };
765 CatchableTypeArray
const* catchables =
reinterpret_cast<CatchableTypeArray const*
>(resolveExceptionRVA(throwInfo->pCatchableTypeArray));
766 CatchableType
const* catchable = catchables->nCatchableTypes ?
reinterpret_cast<CatchableType const*
>(resolveExceptionRVA(catchables->arrayOfCatchableTypes[0])) :
nullptr;
767 TypeDescriptor
const* exceptionTypeinfo = catchable ?
reinterpret_cast<TypeDescriptor const*
>(resolveExceptionRVA(catchable->pType)) :
nullptr;
769 if (exceptionTypeinfo)
771 void* stdExceptionTypeInfo = []() ->
void*
776 return __RTtypeid(&fake);
783 std::exception
const* exceptionPtr = [](
void* object, TypeDescriptor
const* typeInfo,
void* stdExceptionTypeInfo) -> std::exception
const*
792 return reinterpret_cast<std::exception const*
>(__RTDynamicCast(
object, 0, stdExceptionTypeInfo, (
void*)typeInfo,
false));
798 }(exceptionObject, exceptionTypeinfo, stdExceptionTypeInfo);
801 if (!exceptionPtr && exceptionTypeinfo == stdExceptionTypeInfo)
802 exceptionPtr =
reinterpret_cast<std::exception*
>(exceptionObject);
804 Log(_T(
"\r\nUncaught C++ exception info:"));
806 Log(_T(
" %s"), exceptionPtr->what());
810 char undName[MAX_SYM_NAME] = { };
811 if (UnDecorateSymbolName(&exceptionTypeinfo->name[1], &undName[0], MAX_SYM_NAME, UNDNAME_32_BIT_DECODE | UNDNAME_NAME_ONLY | UNDNAME_NO_ARGUMENTS))
813 char buf[MAX_SYM_NAME +
sizeof(SYMBOL_INFO)] = { };
814 PSYMBOL_INFO sym = (PSYMBOL_INFO)&buf[0];
815 sym->SizeOfStruct =
sizeof(SYMBOL_INFO);
816 sym->MaxNameLen = MAX_SYM_NAME;
817 if (SymGetTypeFromName(
m_hProcess, (ULONG64)GetModuleHandle(
nullptr), undName, sym))
819 sym->Address = pExceptionRecord->ExceptionInformation[1];
821 char const* variableName =
"uncaught_exception";
822 memset(sym->Name, 0, MAX_SYM_NAME);
823 memcpy(sym->Name, variableName, strlen(variableName));
830 CONTEXT trashableContext = *pCtx;
837 Log(_T(
"========================\r\n"));
838 Log(_T(
"Local Variables And Parameters\r\n"));
840 trashableContext = *pCtx;
844 SymCleanup(GetCurrentProcess());
848 __except (EXCEPTION_EXECUTE_HANDLER)
850 Log(_T(
"Error writing the crash log\r\n"));
909PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
911 MEMORY_BASIC_INFORMATION mbi;
913 if (!VirtualQuery(addr, &mbi,
sizeof(mbi)))
916 DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase;
921 if (!GetModuleFileName((HMODULE)hMod, szModule, len))
925 PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
928 PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew));
930 PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr);
932 DWORD_PTR rva = (DWORD_PTR)addr - hMod;
937 i < pNtHdr->FileHeader.NumberOfSections;
940 DWORD_PTR sectionStart = pSection->VirtualAddress;
941 DWORD_PTR sectionEnd = sectionStart
942 + DWORD_PTR(std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize));
945 if ((rva >= sectionStart) && (rva <= sectionEnd))
951 offset = rva - sectionStart;
975bool bWriteVariables, HANDLE pThreadHandle)
977 Log(_T(
"\r\nCall stack:\r\n"));
979 Log(_T(
"Address Frame Function SourceFile\r\n"));
981 DWORD dwMachineType = 0;
985 memset(&sf, 0,
sizeof(sf));
988 sf.AddrPC.Mode = AddrModeFlat;
989 sf.AddrStack.Mode = AddrModeFlat;
990 sf.AddrFrame.Mode = AddrModeFlat;
993 sf.AddrPC.Offset = pContext->Eip;
994 sf.AddrStack.Offset = pContext->Esp;
995 sf.AddrFrame.Offset = pContext->Ebp;
996 dwMachineType = IMAGE_FILE_MACHINE_I386;
998 sf.AddrPC.Offset = pContext->Rip;
999 sf.AddrStack.Offset = pContext->Rsp;
1000 sf.AddrFrame.Offset = pContext->Rbp;
1001 dwMachineType = IMAGE_FILE_MACHINE_AMD64;
1002#elif defined(_M_ARM64)
1003 sf.AddrPC.Offset = pContext->Pc;
1004 sf.AddrStack.Offset = pContext->Sp;
1005 sf.AddrFrame.Offset = pContext->Fp;
1006 dwMachineType = IMAGE_FILE_MACHINE_ARM64;
1012 if (! StackWalk64(dwMachineType,
1014 pThreadHandle !=
nullptr ? pThreadHandle : GetCurrentThread(),
1018 SymFunctionTableAccess64,
1022 if (0 == sf.AddrFrame.Offset)
1025 Log(_T(
"%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
1026#elif defined(_M_X64) || defined(_M_ARM64)
1027 Log(_T(
"%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
1030 DWORD64 symDisplacement = 0;
1041 Log(_T(
"%hs+%I64X"), sip.si.Name, symDisplacement);
1046 TCHAR szModule[MAX_PATH] = _T(
"");
1048 DWORD_PTR offset = 0;
1051 szModule,
sizeof(szModule), section, offset);
1053 Log(_T(
"%04X:%08X %s"), section, offset, szModule);
1054#elif defined(_M_X64) || defined(_M_ARM64)
1055 Log(_T(
"%04X:%016I64X %s"), section, offset, szModule);
1060 IMAGEHLP_LINE64 lineInfo = {
sizeof(IMAGEHLP_LINE64) };
1061 DWORD dwLineDisplacement;
1062 if (SymGetLineFromAddr64(
m_hProcess, sf.AddrPC.Offset,
1063 &dwLineDisplacement, &lineInfo))
1065 Log(_T(
" %s line %u"), lineInfo.FileName, lineInfo.LineNumber);
1071 if (bWriteVariables)
1074 IMAGEHLP_STACK_FRAME imagehlpStackFrame;
1075 imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset;
1076 SymSetContext(
m_hProcess, &imagehlpStackFrame,
nullptr);
1397 if (!SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag))
1402 WCHAR * pwszTypeName;
1403 if (SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME,
1407 if (wcscmp(pwszTypeName, L
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0)
1409 LocalFree(pwszTypeName);
1414 if (Name !=
nullptr && Name[0] !=
'\0')
1421 wcstombs(buffer, pwszTypeName,
sizeof(buffer));
1423 if (Name !=
nullptr && Name[0] !=
'\0')
1428 else if (buffer[0] !=
'\0')
1431 LocalFree(pwszTypeName);
1433 else if (Name !=
nullptr && Name[0] !=
'\0')
1439 if (typeTag == SymTagBaseClass)
1447 case SymTagPointerType:
1448 if (SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
1450 if (Name !=
nullptr && Name[0] !=
'\0')
1454 SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference);
1456 char addressStr[40];
1457 memset(addressStr, 0,
sizeof(addressStr));
1472 logChildren =
false;
1475 if (address == NULL || address == DWORD_PTR(-1))
1476 logChildren =
false;
1478 DumpTypeIndex(modBase, innerTypeID, address, bHandled, Name, addressStr,
false, logChildren);
1486 if (address == NULL)
1488 else if (address == DWORD_PTR(-1))
1494 SymGetTypeInfo(
m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length);
1502 else if (address == NULL)
1504 else if (address == DWORD_PTR(-1))
1513 if (SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
1516 if (!SymGetTypeInfo(
m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag))
1519 switch (innerTypeTag)
1523 logChildren =
false;
1525 offset, bHandled,
symbolDetails.top().Name.c_str(),
"",
false, logChildren);
1527 case SymTagPointerType:
1528 if (Name !=
nullptr && Name[0] !=
'\0')
1531 offset, bHandled,
symbolDetails.top().Name.c_str(),
"",
false, logChildren);
1533 case SymTagArrayType:
1535 offset, bHandled,
symbolDetails.top().Name.c_str(),
"",
false, logChildren);
1542 case SymTagArrayType:
1543 if (SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
1549 offset, bHandled, Name,
"",
false,
false);
1555 DWORD elementsCount;
1556 if (SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_COUNT, &elementsCount))
1557 symbolDetails.top().Suffix +=
"[" + std::to_string(elementsCount) +
"]";
1571 SymGetTypeInfo(
m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length);
1578 FormatOutputValue(buffer, basicType, length, (PVOID)offset,
sizeof(buffer), elementsCount);
1584 bool elementHandled =
false;
1588 if (firstElementValue.empty())
1590 FormatOutputValue(buffer, basicType, length, (PVOID)(offset + length * index),
sizeof(buffer));
1591 firstElementValue = buffer;
1597 DumpTypeIndex(modBase, innerTypeID, offset + length * index, elementHandled,
"",
"",
false,
false);
1598 if (!elementHandled)
1600 FormatOutputValue(buffer, basicType, length, (PVOID)(offset + length * index),
sizeof(buffer));
1606 symbolDetails.top().Suffix =
"[" + std::to_string(index) +
"]";
1616 case SymTagBaseType:
1625 DWORD dwChildrenCount = 0;
1626 SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount);
1628 if (!dwChildrenCount)
1634 struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
1636 ULONG MoreChildIds[1024*2];
1637 FINDCHILDREN(){Count =
sizeof(MoreChildIds) /
sizeof(MoreChildIds[0]);}
1640 children.Count = dwChildrenCount;
1644 if (!SymGetTypeInfo(
m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN,
1651 for (
unsigned i = 0; i < dwChildrenCount; i++)
1654 SymGetTypeInfo(
m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag);
1656 if (symTag == SymTagFunction ||
1657 symTag == SymTagEnum ||
1658 symTag == SymTagTypedef ||
1659 symTag == SymTagVTable)
1664 SymGetTypeInfo(
m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind);
1682 DWORD dwMemberOffset;
1683 SymGetTypeInfo(
m_hProcess, modBase, children.ChildId[i],
1684 TI_GET_OFFSET, &dwMemberOffset);
1687 DWORD_PTR dwFinalOffset = offset + dwMemberOffset;
1690 children.ChildId[i],
1691 dwFinalOffset, bHandled2,
"",
"",
true,
true);
1702 SymGetTypeInfo(
m_hProcess, modBase, children.ChildId[i],
1703 TI_GET_TYPEID, &typeId);
1707 SymGetTypeInfo(
m_hProcess, modBase, typeId, TI_GET_LENGTH, &length);
1710 FormatOutputValue(buffer, basicType, length, (PVOID)dwFinalOffset,
sizeof(buffer));
1725size_t countOverride)
1734 if (countOverride != 0)
1735 length = countOverride;
1737 length = strlen((
char*)pAddress);
1739 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"\"%.*s...\"", (
int)(
bufferSize - 6), (
char*)pAddress);
1741 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"\"%.*s\"", (
int)length, (
char*)pAddress);
1746 std::string* value =
static_cast<std::string*
>(pAddress);
1748 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"\"%.*s...\"", (
int)(
bufferSize - 6), value->c_str());
1750 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"\"%s\"", value->c_str());
1756 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%X", *(PBYTE)pAddress);
1757 else if (length == 2)
1758 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%X", *(PWORD)pAddress);
1759 else if (length == 4)
1762 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"%f", *(PFLOAT)pAddress);
1764 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%X", *(PDWORD)pAddress);
1766 else if (length == 8)
1770 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"%f",
1771 *(
double *)pAddress);
1774 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%I64X",
1775 *(DWORD64*)pAddress);
1780 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%I64X", (DWORD64)pAddress);
1782 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%X", (DWORD)pAddress);
1788 __except (EXCEPTION_EXECUTE_HANDLER)
1791 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%I64X <Unable to read memory>", (DWORD64)pAddress);
1793 pszCurrBuffer += snprintf(pszCurrBuffer,
bufferSize,
"0x%X <Unable to read memory>", (DWORD)pAddress);