diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-02-17 12:03:57 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-02-17 12:03:57 +0100 |
commit | 2441ddbea6e9865bd6027c6ecc144559d13393b9 (patch) | |
tree | e35021322e9f867387ea1975702953e0f9ad6452 /src/common/Debugging/WheatyExceptionReport.cpp | |
parent | b9c2dca59f350edd5b2b877d8a34001389f17a13 (diff) |
Core/CrashHandler: Support ARM64
Diffstat (limited to 'src/common/Debugging/WheatyExceptionReport.cpp')
-rw-r--r-- | src/common/Debugging/WheatyExceptionReport.cpp | 277 |
1 files changed, 239 insertions, 38 deletions
diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp index 2c20a8a2e0b..0879913cb76 100644 --- a/src/common/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -674,12 +674,12 @@ PEXCEPTION_POINTERS pExceptionInfo) sizeof(szFaultingModule), section, offset); -#ifdef _M_IX86 +#if defined(_M_IX86) || defined(_M_ARM) Log(_T("Fault address: %08X %02X:%08X %s\r\n"), pExceptionRecord->ExceptionAddress, section, offset, szFaultingModule); #endif -#ifdef _M_X64 +#if defined(_M_X64) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined (_M_ARM64EC) Log(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"), pExceptionRecord->ExceptionAddress, section, offset, szFaultingModule); @@ -708,15 +708,31 @@ PEXCEPTION_POINTERS pExceptionInfo) Log(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n") _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") , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, - pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15); + pCtx->Rsi, pCtx->Rdi, pCtx->R8, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15); Log(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip); - Log(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"), + Log(_T("SS:RSP:%04X:%016I64X RBP:%08X\r\n"), pCtx->SegSs, pCtx->Rsp, pCtx->Rbp); Log(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); Log(_T("Flags:%08X\r\n"), pCtx->EFlags); #endif +#ifdef _M_ARM64 + Log(_T("\r\nRegisters:\r\n")); + Log(_T("X0:%016I64X\r\nX1:%016I64X\r\nX2:%016I64X\r\nX3:%016I64X\r\nX4:%016I64X\r\nX5:%016I64X\r\n"), + _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"), + _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"), + _T("X22:%016I64X\r\nX23:%016I64X\r\nX24:%016I64X\r\nX25:%016I64X\r\nX26:%016I64X\r\nX27:%016I64X\r\nX28:%016I64X\r\n"), + pCtx->X0, pCtx->X1, pCtx->X2, pCtx->X3, pCtx->X4, pCtx->X5, + pCtx->X6, pCtx->X7, pCtx->X8, pCtx->X9, pCtx->X10, pCtx->X11, pCtx->X12, pCtx->X13, + pCtx->X14, pCtx->X15, pCtx->X16, pCtx->X17, pCtx->X18, pCtx->X19, pCtx->X20, pCtx->X21, + pCtx->X22, pCtx->X23, pCtx->X24, pCtx->X25, pCtx->X26, pCtx->X27, pCtx->X28); + Log(_T("LR:%016I64X\r\n"), pCtx->Lr); + Log(_T("PC:%016I64X\r\n"), pCtx->Pc); + Log(_T("SP:%016I64X FP:%016I64X\r\n"), pCtx->Sp, pCtx->Fp); + Log(_T("Flags:%08X\r\n"), pCtx->Cpsr); +#endif + SymSetOptions(SYMOPT_DEFERRED_LOADS); // Initialize DbgHelp @@ -968,27 +984,26 @@ bool bWriteVariables, HANDLE pThreadHandle) STACKFRAME64 sf; memset(&sf, 0, sizeof(sf)); - #ifdef _M_IX86 - // Initialize the STACKFRAME structure for the first call. This is only - // necessary for Intel CPUs, and isn't mentioned in the documentation. - sf.AddrPC.Offset = pContext->Eip; + // Initialize the STACKFRAME structure for the first call. sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Esp; sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Ebp; sf.AddrFrame.Mode = AddrModeFlat; +#ifdef _M_IX86 + sf.AddrPC.Offset = pContext->Eip; + sf.AddrStack.Offset = pContext->Esp; + sf.AddrFrame.Offset = pContext->Ebp; dwMachineType = IMAGE_FILE_MACHINE_I386; - #endif - -#ifdef _M_X64 - sf.AddrPC.Offset = pContext->Rip; - sf.AddrPC.Mode = AddrModeFlat; +#elif defined(_M_X64) + sf.AddrPC.Offset = pContext->Rip; sf.AddrStack.Offset = pContext->Rsp; - sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = pContext->Rbp; - sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_AMD64; +#elif defined(_M_ARM64) + sf.AddrPC.Offset = pContext->Pc; + sf.AddrStack.Offset = pContext->Sp; + sf.AddrFrame.Offset = pContext->Fp; + dwMachineType = IMAGE_FILE_MACHINE_ARM64; #endif for (;;) @@ -1008,8 +1023,7 @@ bool bWriteVariables, HANDLE pThreadHandle) break; // the frame is OK. Bail if not. #ifdef _M_IX86 Log(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif -#ifdef _M_X64 +#elif defined(_M_X64) || defined(_M_ARM64) Log(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); #endif @@ -1037,8 +1051,7 @@ bool bWriteVariables, HANDLE pThreadHandle) szModule, sizeof(szModule), section, offset); #ifdef _M_IX86 Log(_T("%04X:%08X %s"), section, offset, szModule); -#endif -#ifdef _M_X64 +#elif defined(_M_X64) || defined(_M_ARM64) Log(_T("%04X:%016I64X %s"), section, offset, szModule); #endif } @@ -1063,7 +1076,10 @@ bool bWriteVariables, HANDLE pThreadHandle) SymSetContext(m_hProcess, &imagehlpStackFrame, nullptr); // Enumerate the locals/parameters - SymEnumSymbols(m_hProcess, 0, nullptr, EnumerateSymbolsCallback, &sf); + EnumerateSymbolsCallbackContext ctx; + ctx.sf = &sf; + ctx.context = pContext; + SymEnumSymbols(m_hProcess, 0, nullptr, EnumerateSymbolsCallback, &ctx); Log(_T("\r\n")); } @@ -1084,7 +1100,7 @@ PVOID UserContext) __try { ClearSymbols(); - FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext); + FormatSymbolValue(pSymInfo, (EnumerateSymbolsCallbackContext*)UserContext); } __except (EXCEPTION_EXECUTE_HANDLER) @@ -1095,6 +1111,191 @@ PVOID UserContext) return TRUE; } +Optional<DWORD_PTR> WheatyExceptionReport::GetIntegerRegisterValue(PCONTEXT context, ULONG registerId) +{ +#define REG_L(x) ((BYTE)(((DWORD_PTR)(x)) & 0xff)) +#define REG_H(x) ((BYTE)((((DWORD_PTR)(x)) >> 8) & 0xff)) +#define REG_X(x) ((WORD)(((DWORD_PTR)(x)) & 0xffff)) +#define REG_E(x) ((DWORD)(((DWORD_PTR)(x)) & 0xffffffff)) +#define REG_R(x) ((DWORD64)(((DWORD_PTR)(x)) & 0xffffffffffffffff)) +#define CPU_REG(reg, field, part) case reg: return part(context->field); + switch (registerId) + { +#ifdef _M_IX86 + CPU_REG(CV_REG_AL, Eax, REG_L); + CPU_REG(CV_REG_CL, Ecx, REG_L); + CPU_REG(CV_REG_DL, Edx, REG_L); + CPU_REG(CV_REG_BL, Ebx, REG_L); + CPU_REG(CV_REG_AH, Eax, REG_H); + CPU_REG(CV_REG_CH, Ecx, REG_H); + CPU_REG(CV_REG_DH, Edx, REG_H); + CPU_REG(CV_REG_BH, Ebx, REG_H); + CPU_REG(CV_REG_AX, Eax, REG_X); + CPU_REG(CV_REG_CX, Ecx, REG_X); + CPU_REG(CV_REG_DX, Edx, REG_X); + CPU_REG(CV_REG_BX, Ebx, REG_X); + CPU_REG(CV_REG_SP, Esp, REG_X); + CPU_REG(CV_REG_BP, Ebp, REG_X); + CPU_REG(CV_REG_SI, Esi, REG_X); + CPU_REG(CV_REG_DI, Edi, REG_X); + CPU_REG(CV_REG_EAX, Eax, REG_E); + CPU_REG(CV_REG_ECX, Ecx, REG_E); + CPU_REG(CV_REG_EDX, Edx, REG_E); + CPU_REG(CV_REG_EBX, Ebx, REG_E); + CPU_REG(CV_REG_ESP, Esp, REG_E); + CPU_REG(CV_REG_EBP, Ebp, REG_E); + CPU_REG(CV_REG_ESI, Esi, REG_E); + CPU_REG(CV_REG_EDI, Edi, REG_E); + CPU_REG(CV_REG_EIP, Eip, REG_E); +#elif defined (_M_X64) + CPU_REG(CV_AMD64_AL, Rax, REG_L); + CPU_REG(CV_AMD64_CL, Rcx, REG_L); + CPU_REG(CV_AMD64_DL, Rdx, REG_L); + CPU_REG(CV_AMD64_BL, Rbx, REG_L); + CPU_REG(CV_AMD64_SIL, Rsi, REG_L); + CPU_REG(CV_AMD64_DIL, Rdi, REG_L); + CPU_REG(CV_AMD64_BPL, Rbp, REG_L); + CPU_REG(CV_AMD64_SPL, Rsp, REG_L); + CPU_REG(CV_AMD64_R8B, R8, REG_L); + CPU_REG(CV_AMD64_R9B, R9, REG_L); + CPU_REG(CV_AMD64_R10B, R10, REG_L); + CPU_REG(CV_AMD64_R11B, R11, REG_L); + CPU_REG(CV_AMD64_R12B, R12, REG_L); + CPU_REG(CV_AMD64_R13B, R13, REG_L); + CPU_REG(CV_AMD64_R14B, R14, REG_L); + CPU_REG(CV_AMD64_R15B, R15, REG_L); + CPU_REG(CV_AMD64_AH, Rax, REG_H); + CPU_REG(CV_AMD64_CH, Rcx, REG_H); + CPU_REG(CV_AMD64_DH, Rdx, REG_H); + CPU_REG(CV_AMD64_BH, Rbx, REG_H); + CPU_REG(CV_AMD64_AX, Rax, REG_X); + CPU_REG(CV_AMD64_CX, Rcx, REG_X); + CPU_REG(CV_AMD64_DX, Rdx, REG_X); + CPU_REG(CV_AMD64_BX, Rbx, REG_X); + CPU_REG(CV_AMD64_SP, Rsp, REG_X); + CPU_REG(CV_AMD64_BP, Rbp, REG_X); + CPU_REG(CV_AMD64_SI, Rsi, REG_X); + CPU_REG(CV_AMD64_DI, Rdi, REG_X); + CPU_REG(CV_AMD64_R8W, R8, REG_X); + CPU_REG(CV_AMD64_R9W, R9, REG_X); + CPU_REG(CV_AMD64_R10W, R10, REG_X); + CPU_REG(CV_AMD64_R11W, R11, REG_X); + CPU_REG(CV_AMD64_R12W, R12, REG_X); + CPU_REG(CV_AMD64_R13W, R13, REG_X); + CPU_REG(CV_AMD64_R14W, R14, REG_X); + CPU_REG(CV_AMD64_R15W, R15, REG_X); + CPU_REG(CV_AMD64_EAX, Rax, REG_E); + CPU_REG(CV_AMD64_ECX, Rcx, REG_E); + CPU_REG(CV_AMD64_EDX, Rdx, REG_E); + CPU_REG(CV_AMD64_EBX, Rbx, REG_E); + CPU_REG(CV_AMD64_ESP, Rsp, REG_E); + CPU_REG(CV_AMD64_EBP, Rbp, REG_E); + CPU_REG(CV_AMD64_ESI, Rsi, REG_E); + CPU_REG(CV_AMD64_EDI, Rdi, REG_E); + CPU_REG(CV_AMD64_R8D, R8, REG_E); + CPU_REG(CV_AMD64_R9D, R9, REG_E); + CPU_REG(CV_AMD64_R10D, R10, REG_E); + CPU_REG(CV_AMD64_R11D, R11, REG_E); + CPU_REG(CV_AMD64_R12D, R12, REG_E); + CPU_REG(CV_AMD64_R13D, R13, REG_E); + CPU_REG(CV_AMD64_R14D, R14, REG_E); + CPU_REG(CV_AMD64_R15D, R15, REG_E); + CPU_REG(CV_AMD64_RIP, Rip, REG_R); + CPU_REG(CV_AMD64_RAX, Rax, REG_R); + CPU_REG(CV_AMD64_RBX, Rbx, REG_R); + CPU_REG(CV_AMD64_RCX, Rcx, REG_R); + CPU_REG(CV_AMD64_RDX, Rdx, REG_R); + CPU_REG(CV_AMD64_RSI, Rsi, REG_R); + CPU_REG(CV_AMD64_RDI, Rdi, REG_R); + CPU_REG(CV_AMD64_RBP, Rbp, REG_R); + CPU_REG(CV_AMD64_RSP, Rsp, REG_R); + CPU_REG(CV_AMD64_R8, R8, REG_R); + CPU_REG(CV_AMD64_R9, R9, REG_R); + CPU_REG(CV_AMD64_R10, R10, REG_R); + CPU_REG(CV_AMD64_R11, R11, REG_R); + CPU_REG(CV_AMD64_R12, R12, REG_R); + CPU_REG(CV_AMD64_R13, R13, REG_R); + CPU_REG(CV_AMD64_R14, R14, REG_R); + CPU_REG(CV_AMD64_R15, R15, REG_R); +#elif defined(_M_ARM64) + CPU_REG(CV_ARM64_W0, X0, REG_E); + CPU_REG(CV_ARM64_W1, X1, REG_E); + CPU_REG(CV_ARM64_W2, X2, REG_E); + CPU_REG(CV_ARM64_W3, X3, REG_E); + CPU_REG(CV_ARM64_W4, X4, REG_E); + CPU_REG(CV_ARM64_W5, X5, REG_E); + CPU_REG(CV_ARM64_W6, X6, REG_E); + CPU_REG(CV_ARM64_W7, X7, REG_E); + CPU_REG(CV_ARM64_W8, X8, REG_E); + CPU_REG(CV_ARM64_W9, X9, REG_E); + CPU_REG(CV_ARM64_W10, X10, REG_E); + CPU_REG(CV_ARM64_W11, X11, REG_E); + CPU_REG(CV_ARM64_W12, X12, REG_E); + CPU_REG(CV_ARM64_W13, X13, REG_E); + CPU_REG(CV_ARM64_W14, X14, REG_E); + CPU_REG(CV_ARM64_W15, X15, REG_E); + CPU_REG(CV_ARM64_W16, X16, REG_E); + CPU_REG(CV_ARM64_W17, X17, REG_E); + CPU_REG(CV_ARM64_W18, X18, REG_E); + CPU_REG(CV_ARM64_W19, X19, REG_E); + CPU_REG(CV_ARM64_W20, X20, REG_E); + CPU_REG(CV_ARM64_W21, X21, REG_E); + CPU_REG(CV_ARM64_W22, X22, REG_E); + CPU_REG(CV_ARM64_W23, X23, REG_E); + CPU_REG(CV_ARM64_W24, X24, REG_E); + CPU_REG(CV_ARM64_W25, X25, REG_E); + CPU_REG(CV_ARM64_W26, X26, REG_E); + CPU_REG(CV_ARM64_W27, X27, REG_E); + CPU_REG(CV_ARM64_W28, X28, REG_E); + CPU_REG(CV_ARM64_W29, Fp, REG_E); + CPU_REG(CV_ARM64_W30, Lr, REG_E); + case CV_ARM64_WZR: return 0; + CPU_REG(CV_ARM64_X0, X0, REG_R); + CPU_REG(CV_ARM64_X1, X1, REG_R); + CPU_REG(CV_ARM64_X2, X2, REG_R); + CPU_REG(CV_ARM64_X3, X3, REG_R); + CPU_REG(CV_ARM64_X4, X4, REG_R); + CPU_REG(CV_ARM64_X5, X5, REG_R); + CPU_REG(CV_ARM64_X6, X6, REG_R); + CPU_REG(CV_ARM64_X7, X7, REG_R); + CPU_REG(CV_ARM64_X8, X8, REG_R); + CPU_REG(CV_ARM64_X9, X9, REG_R); + CPU_REG(CV_ARM64_X10, X10, REG_R); + CPU_REG(CV_ARM64_X11, X11, REG_R); + CPU_REG(CV_ARM64_X12, X12, REG_R); + CPU_REG(CV_ARM64_X13, X13, REG_R); + CPU_REG(CV_ARM64_X14, X14, REG_R); + CPU_REG(CV_ARM64_X15, X15, REG_R); + CPU_REG(CV_ARM64_IP0, X16, REG_R); + CPU_REG(CV_ARM64_IP1, X17, REG_R); + CPU_REG(CV_ARM64_X18, X18, REG_R); + CPU_REG(CV_ARM64_X19, X19, REG_R); + CPU_REG(CV_ARM64_X20, X20, REG_R); + CPU_REG(CV_ARM64_X21, X21, REG_R); + CPU_REG(CV_ARM64_X22, X22, REG_R); + CPU_REG(CV_ARM64_X23, X23, REG_R); + CPU_REG(CV_ARM64_X24, X24, REG_R); + CPU_REG(CV_ARM64_X25, X25, REG_R); + CPU_REG(CV_ARM64_X26, X26, REG_R); + CPU_REG(CV_ARM64_X27, X27, REG_R); + CPU_REG(CV_ARM64_X28, X28, REG_R); + CPU_REG(CV_ARM64_FP, Fp, REG_R); + CPU_REG(CV_ARM64_LR, Lr, REG_R); + CPU_REG(CV_ARM64_SP, Sp, REG_R); + case CV_ARM64_ZR: return 0; +#endif + default: + break; + } + return {}; +#undef CPU_REG +#undef REG_R +#undef REG_E +#undef REG_X +#undef REG_H +#undef REG_L +} + ////////////////////////////////////////////////////////////////////////////// // Given a SYMBOL_INFO representing a particular variable, displays its // contents. If it's a user defined type, display the members and their @@ -1102,33 +1303,33 @@ PVOID UserContext) ////////////////////////////////////////////////////////////////////////////// bool WheatyExceptionReport::FormatSymbolValue( PSYMBOL_INFO pSym, -STACKFRAME64 * sf) +EnumerateSymbolsCallbackContext* pCtx) { // If it's a function, don't do anything. if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK return false; - DWORD_PTR pVariable = 0; // Will point to the variable's data in memory + DWORD_PTR pVariable = pSym->Address; // Will point to the variable's data in memory + Optional<DWORD_PTR> registerVariableStorage; - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) + if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE + || (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE && pSym->Register == CV_ALLREG_VFRAME)) { - // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) - { // This may change!!! -#ifdef _M_IX86 - pVariable = sf->AddrFrame.Offset; -#elif _M_X64 - pVariable = sf->AddrStack.Offset; -#endif - pVariable += (DWORD_PTR)pSym->Address; - } - // else - // return false; + pVariable += pCtx->sf->AddrFrame.Offset; + } + else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) + { + Optional<DWORD_PTR> registerValue = GetIntegerRegisterValue(pCtx->context, pSym->Register); + if (!registerValue) + return false; + + pVariable += *registerValue; } else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) return false; // Don't try to report register variable else { - pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable + // It must be a global variable } PushSymbolDetail(); |