summaryrefslogtreecommitdiff
path: root/Editor/Utils/HelperFuncs.cpp
blob: fd91d85707d3edc12d05bfdf02c4bc04ca6e349f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "HelperFuncs.h"
#include <string.h>
#include <windows.h>
#include <dbghelp.h>
#include <process.h>
#include <exception>
#include <locale.h>
#include <stdlib.h>

using namespace std;

#pragma comment(lib,"Dbghelp.lib")

std::string to_string(const char* cstr)
{
	string s(cstr);
	return s;
}

void _Exceptor() 
{
	throw exception();
}

//https://stackoverflow.com/questions/22467604/
const int MaxNameLen = 256;
void printStack(CONTEXT* ctx) //Prints stack trace based on context record
{
	BOOL    result;
	HANDLE  process;
	HANDLE  thread;
	HMODULE hModule;

	STACKFRAME64        stack;
	ULONG               frame;
	DWORD64             displacement;

	DWORD disp;
	IMAGEHLP_LINE64 *line;

	char buffer[sizeof(SYMBOL_INFO) + 2000 * sizeof(TCHAR)];
	char name[MaxNameLen];
	char module[MaxNameLen];
	PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;

	memset(&stack, 0, 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;

		//get symbol name for address
		pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
		pSymbol->MaxNameLen = 2000;
		SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, pSymbol);

		line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
		line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);

		//try to get line
		if (SymGetLineFromAddr64(process, stack.AddrPC.Offset, &disp, line))
		{
			printf("\tat %s in %s: line: %lu: address: 0x%0X\n", pSymbol->Name, line->FileName, line->LineNumber, pSymbol->Address);
		}
		else
		{
			//failed to get line
			printf("\tat %s, address 0x%0X.\n", 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
			if (hModule != NULL)GetModuleFileNameA(hModule, module, MaxNameLen);

			printf("in %s\n", module);
		}

		free(line);
		line = NULL;
	}
}

int seh_filter(_EXCEPTION_POINTERS* ex)
{
	printf("*** Exception 0x%x occured ***\n\n", ex->ExceptionRecord->ExceptionCode);
	printStack(ex->ContextRecord);

	return EXCEPTION_EXECUTE_HANDLER;
}

void PrintCallStack()
{
	__try
	{
		_Exceptor();
	}
	__except (seh_filter(GetExceptionInformation()))
	{
		printf("Exception \n");
	}
}