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
|
/**
* \file
* \author Egor Tensin <Egor.Tensin@gmail.com>
* \date 2015
* \copyright This file is licensed under the terms of the MIT License.
* See LICENSE.txt for details.
*/
#pragma once
#ifdef WIN32
#include <Windows.h>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")
#endif
#include <cstddef>
#include <sstream>
#include <string>
namespace aesni
{
namespace aux
{
class CallStackFormatter
{
public:
CallStackFormatter()
{
#ifdef WIN32
m_valid = SymInitialize(GetCurrentProcess(), NULL, TRUE) ? true : false;
#endif
}
std::string format(void* addr) const
{
#ifdef WIN32
if (!m_valid)
return format_fallback(addr);
DWORD64 symbol_info_buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
PSYMBOL_INFO symbol_info = (PSYMBOL_INFO) symbol_info_buf;
symbol_info->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol_info->MaxNameLen = MAX_SYM_NAME;
IMAGEHLP_MODULE64 module_info;
module_info.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
DWORD64 displacement_within_symbol;
if (!SymFromAddr(GetCurrentProcess(), reinterpret_cast<DWORD64>(addr), &displacement_within_symbol, symbol_info))
{
if (!SymGetModuleInfo64(GetCurrentProcess(), reinterpret_cast<DWORD64>(addr), &module_info))
return format_fallback(addr);
void* const displacement_within_module = reinterpret_cast<char*>(addr) - module_info.BaseOfImage;
return format_with_module(module_info.ModuleName, displacement_within_module);
}
if (!SymGetModuleInfo64(GetCurrentProcess(), symbol_info->ModBase, &module_info))
return format_with_symbol(symbol_info->Name, addr);
return format_with_symbol_and_module(symbol_info->Name, module_info.ModuleName, reinterpret_cast<void*>(displacement_within_symbol));
#else
return format_fallback(addr);
#endif
}
~CallStackFormatter()
{
#ifdef WIN32
if (m_valid)
SymCleanup(GetCurrentProcess());
#endif
}
private:
template <typename T>
static std::string put_between_brackets(const T& x)
{
std::ostringstream oss;
oss << "[" << x << "]";
return oss.str();
}
template <typename T>
static std::string stringify(const T& x)
{
std::ostringstream oss;
oss << x;
return oss.str();
}
std::string format_fallback(void* addr) const
{
return put_between_brackets(addr);
}
std::string format_with_module(const std::string& module_name, void* displacement) const
{
if (displacement == NULL)
return put_between_brackets(module_name);
else
return put_between_brackets(module_name + "+" + stringify(displacement));
}
std::string format_with_symbol(const std::string& symbol_name, void* displacement) const
{
return format_with_module(symbol_name, displacement);
}
std::string format_with_symbol_and_module(const std::string& symbol_name, const std::string& module_name, void* displacement) const
{
return format_with_symbol(module_name + "!" + symbol_name, displacement);
}
#ifdef WIN32
bool m_valid = false;
#endif
};
}
}
|