Skip to content

Commit

Permalink
feat(dbghelp): show source line number if present
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiud committed Jan 8, 2024
1 parent c469cc2 commit d65d2a4
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 15 deletions.
4 changes: 4 additions & 0 deletions bazel/glog.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ def glog_library(with_gflags = 1, **kwargs):
"@bazel_tools//src/conditions:windows": [":strip_include_prefix_hack"],
"//conditions:default": [],
}),
linkopts = select({
"@bazel_tools//src/conditions:windows": ["dbghelp.lib"],
"//conditions:default": [],
}),
**kwargs
)

Expand Down
56 changes: 41 additions & 15 deletions src/symbolize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -854,24 +854,19 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
# include <dbghelp.h>
# include <windows.h>

# ifdef _MSC_VER
# pragma comment(lib, "dbghelp")
# endif

namespace google {

class SymInitializer {
class SymInitializer final {
public:
HANDLE process;
bool ready;
SymInitializer() : process(nullptr), ready(false) {
SymInitializer() : process(GetCurrentProcess()), ready(false) {
// Initialize the symbol handler.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
process = GetCurrentProcess();
// Defer symbol loading.
// We do not request undecorated symbols with SYMOPT_UNDNAME
// because the mangling library calls UnDecorateSymbolName.
SymSetOptions(SYMOPT_DEFERRED_LOADS);
SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
if (SymInitialize(process, nullptr, true)) {
ready = true;
}
Expand All @@ -881,9 +876,10 @@ class SymInitializer {
// We do not need to close `HANDLE process` because it's a "pseudo handle."
}

private:
SymInitializer(const SymInitializer&);
SymInitializer& operator=(const SymInitializer&);
SymInitializer(const SymInitializer&) = delete;
SymInitializer& operator=(const SymInitializer&) = delete;
SymInitializer(SymInitializer&&) = delete;
SymInitializer& operator=(SymInitializer&&) = delete;
};

static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
Expand All @@ -902,12 +898,42 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
// This could break if a symbol has Unicode in it.
BOOL ret = SymFromAddr(symInitializer.process, reinterpret_cast<DWORD64>(pc),
0, symbol);
if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) {
// `NameLen` does not include the null terminating character.
strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1);
out[static_cast<size_t>(symbol->NameLen)] = '\0';
std::size_t namelen = static_cast<size_t>(symbol->NameLen);
if (ret && namelen < out_size) {
std::strncpy(out, symbol->Name, namelen);

out[namelen] = '\0';

DWORD displacement;
IMAGEHLP_LINE64 line{sizeof(IMAGEHLP_LINE64)};

BOOL found = SymGetLineFromAddr64(symInitializer.process,
reinterpret_cast<DWORD64>(pc),
&displacement, &line);

// Symbolization succeeded. Now we try to demangle the symbol.
DemangleInplace(out, out_size);

out_size -= std::strlen(out);

if (found) {
std::size_t fnlen = std::strlen(line.FileName);

// Determine the number of digits (base 10) necessary to represent the
// line number
std::size_t digits = 1; // At least one digit required
for (DWORD value = line.LineNumber; (value /= 10) != 0; ++digits) {
}

constexpr std::size_t extralen = 4; // space + parens () + :
const std::size_t suffixlen = fnlen + extralen + fnlen + digits;

if (suffixlen < out_size) {
out_size -= std::snprintf(out + namelen, out_size, " (%s:%u)",
line.FileName, line.LineNumber);
}
}

return true;
}
return false;
Expand Down

0 comments on commit d65d2a4

Please sign in to comment.