Code:
#include "includes.h"
#include <DbgHelp.h>
#pragma comment( lib, "DbgHelp")
constexpr static int MODULE_MAX_LEN = _MAX_FNAME;
std::vector< std::string > szExceptionRecord;
//https://stackoverflow.com/questions/22467604/how-can-you-use-capturestackbacktrace-to-capture-the-exception-stack-not-the-ca
void GetStackInformation(CONTEXT* ctx)
{
BOOL result;
HANDLE process;
HANDLE thread;
HMODULE hModule;
STACKFRAME64 stack;
ULONG frame;
DWORD64 displacement;
DWORD disp;
IMAGEHLP_LINE64 *line;
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
char module[MODULE_MAX_LEN];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
SecureZeroMemory(&stack, sizeof(STACKFRAME64));
process = GetCurrentProcess();
thread = GetCurrentThread();
displacement = 0;
#if !defined(_M_AMD64)
stack.AddrPC.Offset = (*ctx).Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = (*ctx).Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = (*ctx).Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
#endif
SymInitialize(process, NULL, TRUE); //load symbols
for (frame = 0; ; frame++)
{
//get next call from stack
result = StackWalk64
(
#if defined(_M_AMD64)
IMAGE_FILE_MACHINE_AMD64
#else
IMAGE_FILE_MACHINE_I386
#endif
,
process,
thread,
&stack,
ctx,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL
);
if (!result) break;
char *szPrintInfo = new char[MODULE_MAX_LEN];
//get symbol name for address
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, pSymbol);
line = new IMAGEHLP_LINE64[sizeof(IMAGEHLP_LINE64)];
line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
//try to get line
if (SymGetLineFromAddr64(process, stack.AddrPC.Offset, &disp, line))
{
sprintf(szPrintInfo, "Exception Info: At: %s in %s: At Line: %lu: At Address: 0x%0X\n", pSymbol->Name, line->FileName, line->LineNumber, pSymbol->Address);
szExceptionRecord.push_back(szPrintInfo);
}
else
{
//failed to get line
sprintf(szPrintInfo, "Exception Info: At: %s, At Address: 0x%0X ", pSymbol->Name, pSymbol->Address);
hModule = NULL;
lstrcpyA(module, "");
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)(stack.AddrPC.Offset), &hModule);
//at least print module name
DWORD dwCB = 256;
if (hModule != NULL)
QueryFullProcessImageNameA((HANDLE)-1, 0, module, &dwCB);
//GetModuleFileNameA(hModule, module, MODULE_MAX_LEN);
sprintf(szPrintInfo, "At Module: %s\n", module);
szExceptionRecord.push_back(szPrintInfo);
}
delete[] szPrintInfo;
delete[] line;
}
}
LONG WINAPI MyExceptionHandler(_EXCEPTION_POINTERS* ex)
{
szExceptionRecord.clear();
if (ex->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
ex->ExceptionRecord->ExceptionCode == 0xE06D7363 /* C++ Exception */)
{
//Get information from the exception stack...
GetStackInformation(ex->ContextRecord);
for (auto exp : szExceptionRecord)
Tools::AddToLogFile(exp.c_str());
}
return EXCEPTION_CONTINUE_SEARCH;
}
void SetupExceptionHandler()
{
SetUnhandledExceptionFilter(MyExceptionHandler);
AddVectoredExceptionHandler(1, MyExceptionHandler);
}
easy shit, and looks like you guys really need this.
if there's a present .pdb file the code will try to load it to get information and will tell you exactly where your copypaste is crashing.
have fun, the stack tracing is 1% modified code from stackoverflow.