Skip to content

Commit 24b1864

Browse files
refacktargos
authored andcommittedNov 2, 2018
src,win: informative stack traces
Refresh `Win32SymbolDebuggingContext::LookupSymbol` to use more APIs PR-URL: #23822 Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-undecorated-symbol-names Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent 2b54219 commit 24b1864

File tree

2 files changed

+123
-30
lines changed

2 files changed

+123
-30
lines changed
 

‎src/debug_utils.cc

+110-29
Original file line numberDiff line numberDiff line change
@@ -100,35 +100,104 @@ class Win32SymbolDebuggingContext final : public NativeSymbolDebuggingContext {
100100
USE(SymInitialize(current_process_, nullptr, true));
101101
}
102102

103-
~Win32SymbolDebuggingContext() {
103+
~Win32SymbolDebuggingContext() override {
104104
USE(SymCleanup(current_process_));
105105
}
106106

107-
SymbolInfo LookupSymbol(void* address) override {
108-
// Ref: https://msdn.microsoft.com/en-en/library/windows/desktop/ms680578(v=vs.85).aspx
109-
char info_buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
110-
SYMBOL_INFO* info = reinterpret_cast<SYMBOL_INFO*>(info_buf);
111-
char demangled[MAX_SYM_NAME];
107+
using NameAndDisplacement = std::pair<std::string, DWORD64>;
108+
NameAndDisplacement WrappedSymFromAddr(DWORD64 dwAddress) const {
109+
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address
110+
// Patches:
111+
// Use `fprintf(stderr, ` instead of `printf`
112+
// `sym.filename = pSymbol->Name` on success
113+
// `current_process_` instead of `hProcess.
114+
DWORD64 dwDisplacement = 0;
115+
// Patch: made into arg - DWORD64 dwAddress = SOME_ADDRESS;
116+
117+
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
118+
const auto pSymbol = reinterpret_cast<PSYMBOL_INFO>(buffer);
119+
120+
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
121+
pSymbol->MaxNameLen = MAX_SYM_NAME;
122+
123+
if (SymFromAddr(current_process_, dwAddress, &dwDisplacement, pSymbol)) {
124+
// SymFromAddr returned success
125+
return NameAndDisplacement(pSymbol->Name, dwDisplacement);
126+
} else {
127+
// SymFromAddr failed
128+
const DWORD error = GetLastError(); // "eat" the error anyway
129+
#ifdef DEBUG
130+
fprintf(stderr, "SymFromAddr returned error : %lu\n", error);
131+
#endif
132+
}
133+
// End MSDN code
112134

113-
info->MaxNameLen = MAX_SYM_NAME;
114-
info->SizeOfStruct = sizeof(SYMBOL_INFO);
135+
return NameAndDisplacement();
136+
}
115137

116-
SymbolInfo ret;
117-
const bool have_info = SymFromAddr(current_process_,
118-
reinterpret_cast<DWORD64>(address),
119-
nullptr,
120-
info);
121-
if (have_info && strlen(info->Name) == 0) {
122-
if (UnDecorateSymbolName(info->Name,
123-
demangled,
124-
sizeof(demangled),
125-
UNDNAME_COMPLETE)) {
126-
ret.name = demangled;
127-
} else {
128-
ret.name = info->Name;
129-
}
138+
SymbolInfo WrappedGetLine(DWORD64 dwAddress) const {
139+
SymbolInfo sym{};
140+
141+
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address
142+
// Patches:
143+
// Use `fprintf(stderr, ` instead of `printf`.
144+
// Assign values to `sym` on success.
145+
// `current_process_` instead of `hProcess.
146+
147+
// Patch: made into arg - DWORD64 dwAddress;
148+
DWORD dwDisplacement;
149+
IMAGEHLP_LINE64 line;
150+
151+
SymSetOptions(SYMOPT_LOAD_LINES);
152+
153+
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
154+
// Patch: made into arg - dwAddress = 0x1000000;
155+
156+
if (SymGetLineFromAddr64(current_process_, dwAddress,
157+
&dwDisplacement, &line)) {
158+
// SymGetLineFromAddr64 returned success
159+
sym.filename = line.FileName;
160+
sym.line = line.LineNumber;
161+
} else {
162+
// SymGetLineFromAddr64 failed
163+
const DWORD error = GetLastError(); // "eat" the error anyway
164+
#ifdef DEBUG
165+
fprintf(stderr, "SymGetLineFromAddr64 returned error : %lu\n", error);
166+
#endif
167+
}
168+
// End MSDN code
169+
170+
return sym;
171+
}
172+
173+
// Fills the SymbolInfo::name of the io/out argument `sym`
174+
std::string WrappedUnDecorateSymbolName(const char* name) const {
175+
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-undecorated-symbol-names
176+
// Patches:
177+
// Use `fprintf(stderr, ` instead of `printf`.
178+
// return `szUndName` instead of `printf` on success
179+
char szUndName[MAX_SYM_NAME];
180+
if (UnDecorateSymbolName(name, szUndName, sizeof(szUndName),
181+
UNDNAME_COMPLETE)) {
182+
// UnDecorateSymbolName returned success
183+
return szUndName;
184+
} else {
185+
// UnDecorateSymbolName failed
186+
const DWORD error = GetLastError(); // "eat" the error anyway
187+
#ifdef DEBUG
188+
fprintf(stderr, "UnDecorateSymbolName returned error %lu\n", error);
189+
#endif
130190
}
191+
return nullptr;
192+
}
131193

194+
SymbolInfo LookupSymbol(void* address) override {
195+
const DWORD64 dw_address = reinterpret_cast<DWORD64>(address);
196+
SymbolInfo ret = WrappedGetLine(dw_address);
197+
std::tie(ret.name, ret.dis) = WrappedSymFromAddr(dw_address);
198+
if (!ret.name.empty()) {
199+
ret.name = WrappedUnDecorateSymbolName(ret.name.c_str());
200+
}
132201
return ret;
133202
}
134203

@@ -145,6 +214,13 @@ class Win32SymbolDebuggingContext final : public NativeSymbolDebuggingContext {
145214
return CaptureStackBackTrace(0, count, frames, nullptr);
146215
}
147216

217+
Win32SymbolDebuggingContext(const Win32SymbolDebuggingContext&) = delete;
218+
Win32SymbolDebuggingContext(Win32SymbolDebuggingContext&&) = delete;
219+
Win32SymbolDebuggingContext operator=(const Win32SymbolDebuggingContext&)
220+
= delete;
221+
Win32SymbolDebuggingContext operator=(Win32SymbolDebuggingContext&&)
222+
= delete;
223+
148224
private:
149225
HANDLE current_process_;
150226
};
@@ -158,13 +234,18 @@ NativeSymbolDebuggingContext::New() {
158234
#endif // __POSIX__
159235

160236
std::string NativeSymbolDebuggingContext::SymbolInfo::Display() const {
161-
std::string ret = name;
237+
std::ostringstream oss;
238+
oss << name;
239+
if (dis != 0) {
240+
oss << "+" << dis;
241+
}
162242
if (!filename.empty()) {
163-
ret += " [";
164-
ret += filename;
165-
ret += ']';
243+
oss << " [" << filename << ']';
244+
}
245+
if (line != 0) {
246+
oss << ":L" << line;
166247
}
167-
return ret;
248+
return oss.str();
168249
}
169250

170251
void DumpBacktrace(FILE* fp) {
@@ -173,8 +254,8 @@ void DumpBacktrace(FILE* fp) {
173254
const int size = sym_ctx->GetStackTrace(frames, arraysize(frames));
174255
for (int i = 1; i < size; i += 1) {
175256
void* frame = frames[i];
176-
fprintf(fp, "%2d: %p %s\n",
177-
i, frame, sym_ctx->LookupSymbol(frame).Display().c_str());
257+
NativeSymbolDebuggingContext::SymbolInfo s = sym_ctx->LookupSymbol(frame);
258+
fprintf(fp, "%2d: %p %s\n", i, frame, s.Display().c_str());
178259
}
179260
}
180261

‎src/debug_utils.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "async_wrap.h"
77
#include "env.h"
88
#include <string>
9+
#include <sstream>
910

1011
// Use FORCE_INLINE on functions that have a debug-category-enabled check first
1112
// and then ideally only a single function call following it, to maintain
@@ -93,14 +94,25 @@ class NativeSymbolDebuggingContext {
9394
public:
9495
std::string name;
9596
std::string filename;
97+
size_t line = 0;
98+
size_t dis = 0;
9699

97100
std::string Display() const;
98101
};
99102

103+
NativeSymbolDebuggingContext() = default;
100104
virtual ~NativeSymbolDebuggingContext() {}
101-
virtual SymbolInfo LookupSymbol(void* address) { return { "", "" }; }
105+
106+
virtual SymbolInfo LookupSymbol(void* address) { return {}; }
102107
virtual bool IsMapped(void* address) { return false; }
103108
virtual int GetStackTrace(void** frames, int count) { return 0; }
109+
110+
NativeSymbolDebuggingContext(const NativeSymbolDebuggingContext&) = delete;
111+
NativeSymbolDebuggingContext(NativeSymbolDebuggingContext&&) = delete;
112+
NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&)
113+
= delete;
114+
NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&&)
115+
= delete;
104116
};
105117

106118
// Variant of `uv_loop_close` that tries to be as helpful as possible

0 commit comments

Comments
 (0)