-
Notifications
You must be signed in to change notification settings - Fork 2
/
symbols_from_binary.cpp
113 lines (89 loc) · 3.54 KB
/
symbols_from_binary.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
#include "stdafx.h"
#include "symbols_from_binary.h"
#include "symbol_enum.h"
CString SymbolsFromBinary(SymbolsFromBinaryOptions options,
CStringA* logOutput,
std::function<void(int)> progressCallback,
std::stop_token* stopToken) {
CString enumSymbolsResult;
// Use a set for sorting and to avoid duplicate chunks in the output.
// Duplicates can happen if the same symbol is listed with multiple types,
// such as SymTagFunction and SymTagPublicSymbol, or if two variants of a
// decorated name are identical when undecorated.
std::set<CString> resultListChunks;
size_t resultListTotalLength = 0;
size_t count = 0;
{
SymbolEnum::Callbacks callbacks;
if (stopToken) {
callbacks.queryCancel = [&stopToken]() {
return stopToken->stop_requested();
};
}
if (progressCallback) {
callbacks.notifyProgress = progressCallback;
}
if (logOutput) {
callbacks.notifyLog = [&logOutput](PCSTR message) {
CStringA messageStr = message;
// Convert all newlines to CRLF and trim trailing newlines.
messageStr.Replace("\r\n", "\n");
messageStr.Replace('\r', '\n');
messageStr.TrimRight("\n");
messageStr.Replace("\n", "\r\n");
*logOutput += messageStr;
*logOutput += "\r\n";
};
}
CString addressPrefix;
CString chunk;
SymbolEnum symbolEnum(
options.targetExecutable.GetString(), nullptr,
options.engineDir.GetString(), options.symbolsDir.GetString(),
options.symbolServer.GetString(),
options.undecorated ? SymbolEnum::UndecorateMode::Default
: SymbolEnum::UndecorateMode::None,
callbacks);
while (auto iter = symbolEnum.GetNextSymbol()) {
if (stopToken && stopToken->stop_requested()) {
throw std::runtime_error("Canceled");
}
if (!options.decorated && !options.undecorated) {
count++;
continue;
}
if (!iter->nameDecorated && !iter->name) {
continue;
}
addressPrefix.Format(L"[%08" TEXT(PRIXPTR) L"] ", iter->address);
chunk.Empty();
if (options.decorated) {
chunk += addressPrefix;
chunk += iter->nameDecorated ? iter->nameDecorated
: L"<no-decorated-name>";
chunk += L"\r\n";
}
if (options.undecorated) {
chunk += addressPrefix;
chunk += iter->name ? iter->name : L"<no-undecorated-name>";
chunk += L"\r\n";
}
auto [_, inserted] = resultListChunks.insert(chunk);
if (inserted) {
resultListTotalLength += chunk.GetLength();
count++;
}
}
}
enumSymbolsResult.Preallocate((logOutput ? logOutput->GetLength() : 0) +
static_cast<int>(resultListTotalLength) +
128);
enumSymbolsResult.Format(L"Found %zu symbols\r\n", count);
if (logOutput) {
enumSymbolsResult += *logOutput;
}
for (const auto& chunk : resultListChunks) {
enumSymbolsResult += chunk;
}
return enumSymbolsResult;
}