-
Notifications
You must be signed in to change notification settings - Fork 5
/
msvcfilt.cpp
188 lines (160 loc) · 5.29 KB
/
msvcfilt.cpp
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include <iostream>
#include <memory>
#include <regex>
#include <string>
#include <tuple>
#include <vector>
#include <cstring>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <DbgHelp.h>
using namespace std;
/// The regex pattern to recognize a decorated symbol. Only a guess.
static const char *DECORATED_SYMBOL_PATTERN = "\\?[a-zA-Z0-9_@?$]+";
//------------------------------------------------------------------------------
/**
* This class interacts with the DbgHelp symbol handler functions.
*
* It is designed as a Meyers' Singleton, so that SymInitialize() will only
* be called if it is actually necessary, and that SymCleanup() will be called
* at the end of the program.
*/
class SymbolHandler
{
public:
/// The maximum length of a symbol name in bytes
static const size_t MAX_SYMBOL_NAME_LEN = MAX_SYM_NAME;
/**
* Undecorates a decorated symbol.
*
* @param symbol The symbol to undecorate
* @param result Receives the result
*
* @return True if the symbol was undecorated, otherwise false
*/
bool UndecorateSymbol(const string &symbol, string &result)
{
DWORD res = UnDecorateSymbolName(symbol.c_str(), undecorateBuffer.get(),
MAX_SYMBOL_NAME_LEN, UNDNAME_COMPLETE);
bool success = (res != 0);
if (success)
{
result = undecorateBuffer.get();
}
return success;
}
/// Returns the singleton instance of the class
static SymbolHandler &GetInstance()
{
static SymbolHandler instance;
return instance;
}
private:
/// True if the instance was successfully initialized
bool initialized;
/// Windows handle for the current process
HANDLE hProc;
/// Internal buffer that receives the undecorated symbols
unique_ptr<char[]> undecorateBuffer;
// no copy ctor, copy assignment
SymbolHandler(const SymbolHandler &);
SymbolHandler &operator=(const SymbolHandler &);
/// Default constructor
SymbolHandler()
: initialized(false), hProc(0)
{
hProc = GetCurrentProcess();
if (SymInitialize(hProc, NULL, FALSE) == TRUE)
{
initialized = true;
// allocate the buffer that receives the undecorated symbols
undecorateBuffer.reset(new char[MAX_SYMBOL_NAME_LEN]);
}
}
/// Destructor
~SymbolHandler()
{
if (initialized)
{
SymCleanup(hProc);
}
}
};
//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
// if false, the decorated name will be replaced by the undecorated name.
// is set by a command line option.
bool keepOldName = false;
// process cmdline arguments
if (argc > 1)
{
for (int idx = 1; idx < argc; ++idx)
{
if (strcmp("-help", argv[idx]) == 0 ||
strcmp("--help", argv[idx]) == 0)
{
cout << "Usage: msvcfilt [OPTIONS]..." << endl
<< "Searches in STDIN for Microsoft Visual C++ decorated symbol names" << endl
<< "and replaces them with their undecorated equivalent." << endl
<< endl
<< "Options:" << endl
<< "\t-help, --help\tDisplay this help and exit." << endl
<< "\t-keep, --keep\tDoes not replace the original, decorated symbol name." << endl
<< "\t \tInstead, the undecorated name will be inserted after it." << endl
<< endl;
return 0;
}
else if (strcmp("-keep", argv[idx]) == 0 ||
strcmp("--keep", argv[idx]) == 0)
{
keepOldName = true;
}
}
}
// instantiate the regex pattern to search for
regex pattern(DECORATED_SYMBOL_PATTERN);
while (cin.good())
{
// read a line
string line;
getline(cin, line);
// for every match, store the position and length of the original text,
// and the string with which it will be replaced
typedef tuple<size_t, size_t, string> replacement;
vector<replacement> replacement_list;
// iterate through the matches, store them and prepare the undecorated name
const sregex_token_iterator end;
for (sregex_token_iterator it(line.begin(), line.end(), pattern); it != end; ++it)
{
string result;
bool success = SymbolHandler::GetInstance().UndecorateSymbol(it->str(), result);
if (success)
{
tuple_element<0, replacement>::type pos = it->first - line.begin();
tuple_element<1, replacement>::type len = it->length();
replacement_list.push_back(make_tuple(pos, len, result));
}
}
// now process the replacements. the vector is traversed in reverse so that
// the positions in the original string stay valid.
for (auto it = replacement_list.rbegin(); it != replacement_list.rend(); ++it)
{
// 0 : position in original string
// 1 : length of text in original string
// 2 : replacement string
if (keepOldName)
{
auto insertText = get<2>(*it);
insertText.insert(0, " \"", 2);
insertText += '"';
line.insert(get<0>(*it) + get<1>(*it), insertText);
}
else
{
line.replace(get<0>(*it), get<1>(*it), get<2>(*it));
}
}
cout << line << endl;
}
}