-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
src,win: informative stack traces #23822
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,35 +100,104 @@ class Win32SymbolDebuggingContext final : public NativeSymbolDebuggingContext { | |
USE(SymInitialize(current_process_, nullptr, true)); | ||
} | ||
|
||
~Win32SymbolDebuggingContext() { | ||
~Win32SymbolDebuggingContext() override { | ||
USE(SymCleanup(current_process_)); | ||
} | ||
|
||
SymbolInfo LookupSymbol(void* address) override { | ||
// Ref: https://msdn.microsoft.com/en-en/library/windows/desktop/ms680578(v=vs.85).aspx | ||
char info_buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; | ||
SYMBOL_INFO* info = reinterpret_cast<SYMBOL_INFO*>(info_buf); | ||
char demangled[MAX_SYM_NAME]; | ||
using NameAndDisplacement = std::pair<std::string, DWORD64>; | ||
NameAndDisplacement WrappedSymFromAddr(DWORD64 dwAddress) const { | ||
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address | ||
// Patches: | ||
// Use `fprintf(stderr, ` instead of `printf` | ||
// `sym.filename = pSymbol->Name` on success | ||
// `current_process_` instead of `hProcess. | ||
DWORD64 dwDisplacement = 0; | ||
// Patch: made into arg - DWORD64 dwAddress = SOME_ADDRESS; | ||
|
||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; | ||
const auto pSymbol = reinterpret_cast<PSYMBOL_INFO>(buffer); | ||
|
||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); | ||
pSymbol->MaxNameLen = MAX_SYM_NAME; | ||
|
||
if (SymFromAddr(current_process_, dwAddress, &dwDisplacement, pSymbol)) { | ||
// SymFromAddr returned success | ||
return NameAndDisplacement(pSymbol->Name, dwDisplacement); | ||
} else { | ||
// SymFromAddr failed | ||
const DWORD error = GetLastError(); // "eat" the error anyway | ||
#ifdef DEBUG | ||
fprintf(stderr, "SymFromAddr returned error : %lu\n", error); | ||
#endif | ||
} | ||
// End MSDN code | ||
|
||
info->MaxNameLen = MAX_SYM_NAME; | ||
info->SizeOfStruct = sizeof(SYMBOL_INFO); | ||
return NameAndDisplacement(); | ||
} | ||
|
||
SymbolInfo ret; | ||
const bool have_info = SymFromAddr(current_process_, | ||
reinterpret_cast<DWORD64>(address), | ||
nullptr, | ||
info); | ||
if (have_info && strlen(info->Name) == 0) { | ||
if (UnDecorateSymbolName(info->Name, | ||
demangled, | ||
sizeof(demangled), | ||
UNDNAME_COMPLETE)) { | ||
ret.name = demangled; | ||
} else { | ||
ret.name = info->Name; | ||
} | ||
SymbolInfo WrappedGetLine(DWORD64 dwAddress) const { | ||
SymbolInfo sym{}; | ||
|
||
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address | ||
// Patches: | ||
// Use `fprintf(stderr, ` instead of `printf`. | ||
// Assign values to `sym` on success. | ||
// `current_process_` instead of `hProcess. | ||
|
||
// Patch: made into arg - DWORD64 dwAddress; | ||
DWORD dwDisplacement; | ||
IMAGEHLP_LINE64 line; | ||
|
||
SymSetOptions(SYMOPT_LOAD_LINES); | ||
|
||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); | ||
// Patch: made into arg - dwAddress = 0x1000000; | ||
|
||
if (SymGetLineFromAddr64(current_process_, dwAddress, | ||
&dwDisplacement, &line)) { | ||
// SymGetLineFromAddr64 returned success | ||
sym.filename = line.FileName; | ||
sym.line = line.LineNumber; | ||
} else { | ||
// SymGetLineFromAddr64 failed | ||
const DWORD error = GetLastError(); // "eat" the error anyway | ||
#ifdef DEBUG | ||
fprintf(stderr, "SymGetLineFromAddr64 returned error : %lu\n", error); | ||
#endif | ||
} | ||
// End MSDN code | ||
|
||
return sym; | ||
} | ||
|
||
// Fills the SymbolInfo::name of the io/out argument `sym` | ||
std::string WrappedUnDecorateSymbolName(const char* name) const { | ||
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-undecorated-symbol-names | ||
// Patches: | ||
// Use `fprintf(stderr, ` instead of `printf`. | ||
// return `szUndName` instead of `printf` on success | ||
char szUndName[MAX_SYM_NAME]; | ||
if (UnDecorateSymbolName(name, szUndName, sizeof(szUndName), | ||
UNDNAME_COMPLETE)) { | ||
// UnDecorateSymbolName returned success | ||
return szUndName; | ||
} else { | ||
// UnDecorateSymbolName failed | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not a fan of this type of comment: What happens is obvious in both branches, and the branches themselves are short. (And I think we have a convention of ending comments with a period.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code was lifter verbatim from https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address |
||
const DWORD error = GetLastError(); // "eat" the error anyway | ||
#ifdef DEBUG | ||
fprintf(stderr, "UnDecorateSymbolName returned error %lu\n", error); | ||
#endif | ||
} | ||
return nullptr; | ||
} | ||
|
||
SymbolInfo LookupSymbol(void* address) override { | ||
const DWORD64 dw_address = reinterpret_cast<DWORD64>(address); | ||
SymbolInfo ret = WrappedGetLine(dw_address); | ||
std::tie(ret.name, ret.dis) = WrappedSymFromAddr(dw_address); | ||
if (!ret.name.empty()) { | ||
ret.name = WrappedUnDecorateSymbolName(ret.name.c_str()); | ||
} | ||
return ret; | ||
} | ||
|
||
|
@@ -145,6 +214,13 @@ class Win32SymbolDebuggingContext final : public NativeSymbolDebuggingContext { | |
return CaptureStackBackTrace(0, count, frames, nullptr); | ||
} | ||
|
||
Win32SymbolDebuggingContext(const Win32SymbolDebuggingContext&) = delete; | ||
Win32SymbolDebuggingContext(Win32SymbolDebuggingContext&&) = delete; | ||
Win32SymbolDebuggingContext operator=(const Win32SymbolDebuggingContext&) | ||
= delete; | ||
Win32SymbolDebuggingContext operator=(Win32SymbolDebuggingContext&&) | ||
= delete; | ||
|
||
private: | ||
HANDLE current_process_; | ||
}; | ||
|
@@ -158,13 +234,18 @@ NativeSymbolDebuggingContext::New() { | |
#endif // __POSIX__ | ||
|
||
std::string NativeSymbolDebuggingContext::SymbolInfo::Display() const { | ||
std::string ret = name; | ||
std::ostringstream oss; | ||
oss << name; | ||
if (dis != 0) { | ||
oss << "+" << dis; | ||
} | ||
if (!filename.empty()) { | ||
ret += " ["; | ||
ret += filename; | ||
ret += ']'; | ||
oss << " [" << filename << ']'; | ||
} | ||
if (line != 0) { | ||
oss << ":L" << line; | ||
} | ||
return ret; | ||
return oss.str(); | ||
} | ||
|
||
void DumpBacktrace(FILE* fp) { | ||
|
@@ -173,8 +254,8 @@ void DumpBacktrace(FILE* fp) { | |
const int size = sym_ctx->GetStackTrace(frames, arraysize(frames)); | ||
for (int i = 1; i < size; i += 1) { | ||
void* frame = frames[i]; | ||
fprintf(fp, "%2d: %p %s\n", | ||
i, frame, sym_ctx->LookupSymbol(frame).Display().c_str()); | ||
NativeSymbolDebuggingContext::SymbolInfo s = sym_ctx->LookupSymbol(frame); | ||
fprintf(fp, "%2d: %p %s\n", i, frame, s.Display().c_str()); | ||
refack marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still not sure whether this is going to help us at some point, I suspect it won't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment are free.
Personally I have not been in a situation where I said "I wish there was less comments"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to agree, but someone will either change our code or the original, and updating the comment will mostly be a maintenance burden at that point from my perspective.