BambuStudio/src/BaseException.cpp

358 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "BaseException.h"
#include <iomanip>
#include <string>
#include <sstream>
#include <iostream>
#include <mutex>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
static std::string g_log_folder;
static std::atomic<int> g_crash_log_count = 0;
static std::mutex g_dump_mutex;
CBaseException::CBaseException(HANDLE hProcess, WORD wPID, LPCTSTR lpSymbolPath, PEXCEPTION_POINTERS pEp):
CStackWalker(hProcess, wPID, lpSymbolPath)
{
if (NULL != pEp)
{
m_pEp = new EXCEPTION_POINTERS;
CopyMemory(m_pEp, pEp, sizeof(EXCEPTION_POINTERS));
}
output_file = new boost::nowide::ofstream();
std::time_t t = std::time(0);
std::tm* now_time = std::localtime(&t);
std::stringstream buf;
if (!g_log_folder.empty()) {
buf << std::put_time(now_time, "crash_%a_%b_%d_%H_%M_%S_") <<g_crash_log_count++ <<".log";
auto log_folder = (boost::filesystem::path(g_log_folder) / "log").make_preferred();
if (!boost::filesystem::exists(log_folder)) {
boost::filesystem::create_directory(log_folder);
}
auto crash_log_path = boost::filesystem::path(log_folder / buf.str()).make_preferred();
std::string log_filename = crash_log_path.string();
output_file->open(log_filename, std::ios::out | std::ios::app);
}
}
CBaseException::~CBaseException(void)
{
if (output_file) {
output_file->close();
delete output_file;
}
}
//BBS set crash log folder
void CBaseException::set_log_folder(std::string log_folder)
{
g_log_folder = log_folder;
}
void CBaseException::OutputString(LPCTSTR lpszFormat, ...)
{
TCHAR szBuf[2048] = _T("");
va_list args;
va_start(args, lpszFormat);
_vsntprintf_s(szBuf, 2048, lpszFormat, args);
va_end(args);
//WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), szBuf, _tcslen(szBuf), NULL, NULL);
//output it to the current directory of binary
std::string output_str = textconv_helper::T2A_(szBuf);
*output_file << output_str;
output_file->flush();
}
void CBaseException::ShowLoadModules()
{
LoadSymbol();
LPMODULE_INFO pHead = GetLoadModules();
LPMODULE_INFO pmi = pHead;
TCHAR szBuf[MAX_COMPUTERNAME_LENGTH] = _T("");
DWORD dwSize = MAX_COMPUTERNAME_LENGTH;
GetUserName(szBuf, &dwSize);
OutputString(_T("Current User:%s\r\n"), szBuf);
OutputString(_T("BaseAddress:\tSize:\tName\tPath\tSymbolPath\tVersion\r\n"));
while (NULL != pmi)
{
OutputString(_T("%08x\t%d\t%s\t%s\t%s\t%s\r\n"), (unsigned long)(pmi->ModuleAddress), pmi->dwModSize, pmi->szModuleName, pmi->szModulePath, pmi->szSymbolPath, pmi->szVersion);
pmi = pmi->pNext;
}
FreeModuleInformations(pHead);
}
void CBaseException::ShowCallstack(HANDLE hThread, const CONTEXT* context)
{
OutputString(_T("Show CallStack:\r\n"));
LPSTACKINFO phead = StackWalker(hThread, context);
FreeStackInformations(phead);
}
void CBaseException::ShowExceptionResoult(DWORD dwExceptionCode)
{
OutputString(_T("Exception Code :%08x "), dwExceptionCode);
// BBS: to be checked
#if 1
switch (dwExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
{
//OutputString(_T("ACCESS_VIOLATION(%s)\r\n"), _T("<22><>д<EFBFBD>Ƿ<EFBFBD><C7B7>ڴ<EFBFBD>"));
OutputString(_T("ACCESS_VIOLATION\r\n"));
}
return ;
case EXCEPTION_DATATYPE_MISALIGNMENT:
{
//OutputString(_T("DATATYPE_MISALIGNMENT(%s)\r\n"), _T("<22>߳<EFBFBD><DFB3><EFBFBD>ͼ<EFBFBD>ڲ<EFBFBD>֧<EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD>϶<EFBFBD>дδ<D0B4><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("DATATYPE_MISALIGNMENT\r\n"));
}
return ;
case EXCEPTION_BREAKPOINT:
{
//OutputString(_T("BREAKPOINT(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ϵ<EFBFBD>"));
OutputString(_T("BREAKPOINT\r\n"));
}
return ;
case EXCEPTION_SINGLE_STEP:
{
//OutputString(_T("SINGLE_STEP(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD>")); //һ<><D2BB><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
OutputString(_T("SINGLE_STEP\r\n"));
}
return ;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
{
//OutputString(_T("ARRAY_BOUNDS_EXCEEDED(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>"));
OutputString(_T("ARRAY_BOUNDS_EXCEEDED\r\n"));
}
return ;
case EXCEPTION_FLT_DENORMAL_OPERAND:
{
//OutputString(_T("FLT_DENORMAL_OPERAND(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6A3AC><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><DEB7><EFBFBD>ʾ")); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OutputString(_T("FLT_DENORMAL_OPERAND\r\n"));
}
return ;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
{
//OutputString(_T("FLT_DIVIDE_BY_ZERO(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>"));
OutputString(_T("FLT_DIVIDE_BY_ZERO\r\n"));
}
return ;
case EXCEPTION_FLT_INEXACT_RESULT:
{
//OutputString(_T("FLT_INEXACT_RESULT(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD>޷<EFBFBD><DEB7><EFBFBD>ʾ")); //<2F>޷<EFBFBD><DEB7><EFBFBD>ʾһ<CABE><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̫С<CCAB><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ķ<EFBFBD>Χ, <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD>
OutputString(_T("FLT_INEXACT_RESULT\r\n"));
}
return ;
case EXCEPTION_FLT_INVALID_OPERATION:
{
//OutputString(_T("FLT_INVALID_OPERATION(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣"));
OutputString(_T("FLT_INVALID_OPERATION\r\n"));
}
return ;
case EXCEPTION_FLT_OVERFLOW:
{
//OutputString(_T("FLT_OVERFLOW(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD>ֵ"));
OutputString(_T("FLT_OVERFLOW\r\n"));
}
return ;
case EXCEPTION_FLT_STACK_CHECK:
{
//OutputString(_T("STACK_CHECK(%s)\r\n"), _T("ջԽ<D5BB><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
OutputString(_T("STACK_CHECK\r\n"));
}
return ;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
{
//OutputString(_T("INT_DIVIDE_BY_ZERO(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD>쳣"));
OutputString(_T("INT_DIVIDE_BY_ZERO\r\n"));
}
return ;
case EXCEPTION_INVALID_HANDLE:
{
//OutputString(_T("INVALID_HANDLE(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч"));
OutputString(_T("INVALID_HANDLE\r\n"));
}
return ;
case EXCEPTION_PRIV_INSTRUCTION:
{
//OutputString(_T("PRIV_INSTRUCTION(%s)\r\n"), _T("<22>߳<EFBFBD><DFB3><EFBFBD>ͼִ<CDBC>е<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>֧<EFBFBD>ֵ<EFBFBD>ָ<EFBFBD><D6B8>"));
OutputString(_T("PRIV_INSTRUCTION\r\n"));
}
return ;
case EXCEPTION_IN_PAGE_ERROR:
{
//OutputString(_T("IN_PAGE_ERROR(%s)\r\n"), _T("<22>߳<EFBFBD><DFB3><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD>߲<EFBFBD><DFB2>ܼ<EFBFBD><DCBC>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ"));
OutputString(_T("IN_PAGE_ERROR\r\n"));
}
return ;
case EXCEPTION_ILLEGAL_INSTRUCTION:
{
//OutputString(_T("ILLEGAL_INSTRUCTION(%s)\r\n"), _T("<22>߳<EFBFBD><DFB3><EFBFBD>ͼִ<CDBC><D6B4><EFBFBD><EFBFBD>Чָ<D0A7><D6B8>"));
OutputString(_T("ILLEGAL_INSTRUCTION\r\n"));
}
return ;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
{
//OutputString(_T("NONCONTINUABLE_EXCEPTION(%s)\r\n"), _T("<22>߳<EFBFBD><DFB3><EFBFBD>ͼ<EFBFBD><CDBC>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD>ִ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>"));
OutputString(_T("NONCONTINUABLE_EXCEPTION\r\n"));
}
return ;
case EXCEPTION_STACK_OVERFLOW:
{
//OutputString(_T("STACK_OVERFLOW(%s)\r\n"), _T("ջ<><D5BB><EFBFBD><EFBFBD>"));
OutputString(_T("STACK_OVERFLOW\r\n"));
}
return ;
case EXCEPTION_INVALID_DISPOSITION:
{
//OutputString(_T("INVALID_DISPOSITION(%s)\r\n"), _T("<22><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>")); //ʹ<>ø߼<C3B8><DFBC><EFBFBD><EFBFBD>Ա<EFBFBD>д<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OutputString(_T("INVALID_DISPOSITION\r\n"));
}
return ;
case EXCEPTION_FLT_UNDERFLOW:
{
//OutputString(_T("FLT_UNDERFLOW(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>С<EFBFBD><D0A1><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>͵<EFBFBD><CDB5><EFBFBD>Сֵ"));
OutputString(_T("FLT_UNDERFLOW\r\n"));
}
return ;
case EXCEPTION_INT_OVERFLOW:
{
//OutputString(_T("INT_OVERFLOW(%s)\r\n"), _T("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>"));
OutputString(_T("INT_OVERFLOW\r\n"));
}
return ;
}
TCHAR szBuffer[512] = { 0 };
FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle( _T("NTDLL.DLL") ),
dwExceptionCode, 0, szBuffer, sizeof( szBuffer ), 0 );
OutputString(_T("%s"), szBuffer);
OutputString(_T("\r\n"));
#endif
}
LONG WINAPI CBaseException::UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo )
{
if (pExceptionInfo->ExceptionRecord->ExceptionCode < 0x80000000
//BBS: Load project on computers with SDC may trigger this exception (in ShowModal()),
// It's not fatal and should be ignored, or there will be lots of meaningless crash logs
|| pExceptionInfo->ExceptionRecord->ExceptionCode==0xe0434352)
//BBS: ignore the exception when copy preset
//|| pExceptionInfo->ExceptionRecord->ExceptionCode==0xe06d7363)
{
//BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": got an ExceptionCode %1%, skip it!") % pExceptionInfo->ExceptionRecord->ExceptionCode;
return EXCEPTION_CONTINUE_SEARCH;
}
g_dump_mutex.lock();
CBaseException base(GetCurrentProcess(), GetCurrentProcessId(), NULL, pExceptionInfo);
base.ShowExceptionInformation();
g_dump_mutex.unlock();
return EXCEPTION_CONTINUE_SEARCH;
}
LONG WINAPI CBaseException::UnhandledExceptionFilter2(PEXCEPTION_POINTERS pExceptionInfo )
{
CBaseException base(GetCurrentProcess(), GetCurrentProcessId(), NULL, pExceptionInfo);
base.ShowExceptionInformation();
return EXCEPTION_CONTINUE_SEARCH;
}
BOOL CBaseException::GetLogicalAddress(
PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset )
{
MEMORY_BASIC_INFORMATION mbi;
if ( !VirtualQuery( addr, &mbi, sizeof(mbi) ) )
return FALSE;
DWORD hMod = (DWORD)mbi.AllocationBase;
if ( !GetModuleFileName( (HMODULE)hMod, szModule, len ) )
return FALSE;
if (!hMod)
return FALSE;
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );
DWORD rva = (DWORD)addr - hMod;
//<2F><><EFBFBD>㵱ǰ<E3B5B1><C7B0>ַ<EFBFBD>ڵڼ<DAB5><DABC><EFBFBD><EFBFBD><EFBFBD>
for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ )
{
DWORD sectionStart = pSection->VirtualAddress;
DWORD sectionEnd = sectionStart + max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
if ( (rva >= sectionStart) && (rva <= sectionEnd) )
{
section = i+1;
offset = rva - sectionStart;
return TRUE;
}
}
return FALSE; // Should never get here!
}
void CBaseException::ShowRegistorInformation(PCONTEXT pCtx)
{
#ifdef _M_IX86 // Intel Only!
OutputString( _T("\nRegisters:\r\n") );
OutputString(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n"),
pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi );
OutputString( _T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip );
OutputString( _T("SS:ESP:%04X:%08X EBP:%08X\r\n"),pCtx->SegSs, pCtx->Esp, pCtx->Ebp );
OutputString( _T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs );
OutputString( _T("Flags:%08X\r\n"), pCtx->EFlags );
#endif
OutputString( _T("\r\n") );
}
void CBaseException::STF(unsigned int ui, PEXCEPTION_POINTERS pEp)
{
CBaseException base(GetCurrentProcess(), GetCurrentProcessId(), NULL, pEp);
throw base;
}
void CBaseException::ShowExceptionInformation()
{
OutputString(_T("Exceptions:\r\n"));
ShowExceptionResoult(m_pEp->ExceptionRecord->ExceptionCode);
OutputString(_T("Exception Flag :0x%x "), m_pEp->ExceptionRecord->ExceptionFlags);
OutputString(_T("NumberParameters :%ld \n"), m_pEp->ExceptionRecord->NumberParameters);
for (int i = 0; i < m_pEp->ExceptionRecord->NumberParameters; i++)
{
OutputString(_T("Param %d :0x%x \n"), i, m_pEp->ExceptionRecord->ExceptionInformation[i]);
}
OutputString(_T("Context :%p \n"), m_pEp->ContextRecord);
OutputString(_T("ContextFlag : 0x%x, EFlags: 0x%x \n"), m_pEp->ContextRecord->ContextFlags, m_pEp->ContextRecord->EFlags);
TCHAR szFaultingModule[MAX_PATH];
DWORD section, offset;
GetLogicalAddress(m_pEp->ExceptionRecord->ExceptionAddress, szFaultingModule, sizeof(szFaultingModule), section, offset );
OutputString( _T("Fault address: 0x%X 0x%X:0x%X %s\r\n"), m_pEp->ExceptionRecord->ExceptionAddress, section, offset, szFaultingModule );
ShowRegistorInformation(m_pEp->ContextRecord);
ShowCallstack(GetCurrentThread(), m_pEp->ContextRecord);
}