diff options
author | Jan Kratochvil <[email protected]> | 2020-12-04 09:17:02 -0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <[email protected]> | 2020-12-17 14:36:16 -0300 |
commit | bf53fc6b5f415cddc7118091cb8fd6a211b2320d (patch) | |
tree | f4547562c01c6f155abf40c26996cffcf1acafab | |
parent | 2eb5dd418034ecea2f7031e3d33f2991a878b148 (diff) |
perf unwind: Fix separate debug info files when using elfutils' libdw's unwinder
elfutils needs to be provided main binary and separate debug info file
respectively. Providing separate debug info file instead of the main
binary is not sufficient.
One needs to try both supplied filename and its possible cache by its
build-id depending on the use case.
Signed-off-by: Jan Kratochvil <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ian Rogers <[email protected]>
Cc: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
-rw-r--r-- | tools/perf/util/unwind-libdw.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 7a3dbc259cec..0ada907c60d4 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -20,10 +20,24 @@ static char *debuginfo_path; +static int __find_debuginfo(Dwfl_Module *mod __maybe_unused, void **userdata, + const char *modname __maybe_unused, Dwarf_Addr base __maybe_unused, + const char *file_name, const char *debuglink_file __maybe_unused, + GElf_Word debuglink_crc __maybe_unused, char **debuginfo_file_name) +{ + const struct dso *dso = *userdata; + + assert(dso); + if (dso->symsrc_filename && strcmp (file_name, dso->symsrc_filename)) + *debuginfo_file_name = strdup(dso->symsrc_filename); + return -1; +} + static const Dwfl_Callbacks offline_callbacks = { - .find_debuginfo = dwfl_standard_find_debuginfo, + .find_debuginfo = __find_debuginfo, .debuginfo_path = &debuginfo_path, .section_address = dwfl_offline_section_address, + // .find_elf is not set as we use dwfl_report_elf() instead. }; static int __report_module(struct addr_location *al, u64 ip, @@ -46,16 +60,24 @@ static int __report_module(struct addr_location *al, u64 ip, mod = dwfl_addrmodule(ui->dwfl, ip); if (mod) { Dwarf_Addr s; + void **userdatap; - dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); + dwfl_module_info(mod, &userdatap, &s, NULL, NULL, NULL, NULL, NULL); + *userdatap = dso; if (s != al->map->start - al->map->pgoff) mod = 0; } if (!mod) - mod = dwfl_report_elf(ui->dwfl, dso->short_name, - (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff, - false); + mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1, + al->map->start - al->map->pgoff, false); + if (!mod) { + char filename[PATH_MAX]; + + if (dso__build_id_filename(dso, filename, sizeof(filename), false)) + mod = dwfl_report_elf(ui->dwfl, dso->short_name, filename, -1, + al->map->start - al->map->pgoff, false); + } return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; } |