Skip to content

Commit

Permalink
cc: Retry symbol resolution using perfmap
Browse files Browse the repository at this point in the history
When a symbol lies within a module, and that module doesn't have
debuginfo (or doesn't even have an ELF header), the symbol will
always be resolved as [unknown]. However, the /tmp/perf-PID.map
(perf map) for that process might actually have an entry for that
symbol, if it was dynamically generated by some external tool.
This commit changes the resolution process such that if the desired
address lies in a module but that module doesn't have debuginfo,
we keep trying to resolve it in subsequent modules (including the
perf map). If we resolve it successfully using the perf map, the
reported symbol information will have the original module's name,
so we don't lose fidelity.

The motivation for this change is the way symbols work with .NET
Core on Linux. The runtime binaries are compiled ahead-of-time to
native code, but do not have debuginfo. There is an external tool,
which generates a file similar to a perf map (albeit with relative
addresses) for these binaries. This file can then be merged into
the main perf map for the process and used for symbol resolution,
but only if we keep trying to use the perf map when the symbol is
in a previously-seen module.
  • Loading branch information
goldshtn committed Feb 28, 2017
1 parent 4d0d430 commit 8a3fb6c
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/cc/bcc_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym) {
sym->demangle_name = nullptr;
sym->offset = 0x0;

const char *original_module = nullptr;
for (Module &mod : modules_) {
if (addr >= mod.start_ && addr < mod.end_) {
bool res = mod.find_addr(addr, sym);
Expand All @@ -122,7 +123,21 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym) {
if (!sym->demangle_name)
sym->demangle_name = sym->name;
}
return res;
// If we have a match, return right away. But if we don't have a match in
// this module, we might have a match in the perf map (even though the
// module itself doesn't have symbols). Wait until we see the perf map if
// any, but keep the original module name for reporting.
if (res) {
// If we have already seen this module, report the original name rather
// than the perf map name:
if (original_module)
sym->module = original_module;
return res;
} else {
// Record the module to which this symbol belongs, so that even if it's
// later found using a perf map, we still report the right module name.
original_module = mod.name_.c_str();
}
}
}
return false;
Expand Down

0 comments on commit 8a3fb6c

Please sign in to comment.