Commit 8a3fb6cc authored by Sasha Goldshtein's avatar Sasha Goldshtein

cc: Retry symbol resolution using perfmap

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.
parent 4d0d4308
......@@ -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);
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment