[ Upstream commit c966d23a351a33f8a977fd7efbb6f467132f7383 ]
Usually DSOs are mapped from the beginning of the file, so the base address of the DSO can be calculated by map->start - map->pgoff.
However, JIT DSOs which are generated by `perf inject -j`, are mapped only the code segment. This makes unwind-libdw code confusing and rejects processing unwinds in the JIT DSOs. It should use the map start address as base for them to fix the confusion.
Fixes: 1fe627da30331024 ("perf unwind: Take pgoff into account when reporting elf to libdwfl") Signed-off-by: Namhyung Kim namhyung@kernel.org Cc: Adrian Hunter adrian.hunter@intel.com Cc: Fangrui Song maskray@google.com Cc: Ian Rogers irogers@google.com Cc: Ingo Molnar mingo@kernel.org Cc: Jiri Olsa jolsa@kernel.org Cc: Milian Wolff milian.wolff@kdab.com Cc: Pablo Galindo pablogsal@gmail.com Cc: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20231212070547.612536-3-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com --- tools/perf/util/unwind-libdw.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 94aa40f6e348..9a7bdc0e14cc 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -45,6 +45,7 @@ static int __report_module(struct addr_location *al, u64 ip, { Dwfl_Module *mod; struct dso *dso = NULL; + Dwarf_Addr base; /* * Some callers will use al->sym, so we can't just use the * cheaper thread__find_map() here. @@ -57,24 +58,36 @@ static int __report_module(struct addr_location *al, u64 ip, if (!dso) return 0;
+ /* + * The generated JIT DSO files only map the code segment without + * ELF headers. Since JIT codes used to be packed in a memory + * segment, calculating the base address using pgoff falls info + * a different code in another DSO. So just use the map->start + * directly to pick the correct one. + */ + if (!strncmp(dso->long_name, "/tmp/jitted-", 12)) + base = al->map->start; + else + base = al->map->start - al->map->pgoff; + mod = dwfl_addrmodule(ui->dwfl, ip); if (mod) { Dwarf_Addr s;
dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); - if (s != al->map->start - al->map->pgoff) - mod = 0; + if (s != base) + mod = NULL; }
if (!mod) mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1, - al->map->start - al->map->pgoff, false); + base, 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); + base, false); }
if (mod) {