| .. | .. |
|---|
| 5 | 5 | #include <inttypes.h> |
|---|
| 6 | 6 | #include <errno.h> |
|---|
| 7 | 7 | #include "debug.h" |
|---|
| 8 | +#include "dso.h" |
|---|
| 8 | 9 | #include "unwind.h" |
|---|
| 9 | 10 | #include "unwind-libdw.h" |
|---|
| 10 | 11 | #include "machine.h" |
|---|
| 12 | +#include "map.h" |
|---|
| 13 | +#include "symbol.h" |
|---|
| 11 | 14 | #include "thread.h" |
|---|
| 12 | 15 | #include <linux/types.h> |
|---|
| 16 | +#include <linux/zalloc.h> |
|---|
| 13 | 17 | #include "event.h" |
|---|
| 14 | 18 | #include "perf_regs.h" |
|---|
| 15 | 19 | #include "callchain.h" |
|---|
| 16 | | -#include "util.h" |
|---|
| 17 | 20 | |
|---|
| 18 | 21 | static char *debuginfo_path; |
|---|
| 19 | 22 | |
|---|
| 23 | +static int __find_debuginfo(Dwfl_Module *mod __maybe_unused, void **userdata, |
|---|
| 24 | + const char *modname __maybe_unused, Dwarf_Addr base __maybe_unused, |
|---|
| 25 | + const char *file_name, const char *debuglink_file __maybe_unused, |
|---|
| 26 | + GElf_Word debuglink_crc __maybe_unused, char **debuginfo_file_name) |
|---|
| 27 | +{ |
|---|
| 28 | + const struct dso *dso = *userdata; |
|---|
| 29 | + |
|---|
| 30 | + assert(dso); |
|---|
| 31 | + if (dso->symsrc_filename && strcmp (file_name, dso->symsrc_filename)) |
|---|
| 32 | + *debuginfo_file_name = strdup(dso->symsrc_filename); |
|---|
| 33 | + return -1; |
|---|
| 34 | +} |
|---|
| 35 | + |
|---|
| 20 | 36 | static const Dwfl_Callbacks offline_callbacks = { |
|---|
| 21 | | - .find_debuginfo = dwfl_standard_find_debuginfo, |
|---|
| 37 | + .find_debuginfo = __find_debuginfo, |
|---|
| 22 | 38 | .debuginfo_path = &debuginfo_path, |
|---|
| 23 | 39 | .section_address = dwfl_offline_section_address, |
|---|
| 40 | + // .find_elf is not set as we use dwfl_report_elf() instead. |
|---|
| 24 | 41 | }; |
|---|
| 25 | 42 | |
|---|
| 26 | 43 | static int __report_module(struct addr_location *al, u64 ip, |
|---|
| .. | .. |
|---|
| 50 | 67 | } |
|---|
| 51 | 68 | |
|---|
| 52 | 69 | if (!mod) |
|---|
| 53 | | - mod = dwfl_report_elf(ui->dwfl, dso->short_name, |
|---|
| 54 | | - (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff, |
|---|
| 55 | | - false); |
|---|
| 70 | + mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1, |
|---|
| 71 | + al->map->start - al->map->pgoff, false); |
|---|
| 72 | + if (!mod) { |
|---|
| 73 | + char filename[PATH_MAX]; |
|---|
| 74 | + |
|---|
| 75 | + if (dso__build_id_filename(dso, filename, sizeof(filename), false)) |
|---|
| 76 | + mod = dwfl_report_elf(ui->dwfl, dso->short_name, filename, -1, |
|---|
| 77 | + al->map->start - al->map->pgoff, false); |
|---|
| 78 | + } |
|---|
| 79 | + |
|---|
| 80 | + if (mod) { |
|---|
| 81 | + void **userdatap; |
|---|
| 82 | + |
|---|
| 83 | + dwfl_module_info(mod, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); |
|---|
| 84 | + *userdatap = dso; |
|---|
| 85 | + } |
|---|
| 56 | 86 | |
|---|
| 57 | 87 | return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; |
|---|
| 58 | 88 | } |
|---|
| .. | .. |
|---|
| 77 | 107 | if (__report_module(&al, ip, ui)) |
|---|
| 78 | 108 | return -1; |
|---|
| 79 | 109 | |
|---|
| 80 | | - e->ip = ip; |
|---|
| 81 | | - e->map = al.map; |
|---|
| 82 | | - e->sym = al.sym; |
|---|
| 110 | + e->ip = ip; |
|---|
| 111 | + e->ms.maps = al.maps; |
|---|
| 112 | + e->ms.map = al.map; |
|---|
| 113 | + e->ms.sym = al.sym; |
|---|
| 83 | 114 | |
|---|
| 84 | 115 | pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", |
|---|
| 85 | 116 | al.sym ? al.sym->name : "''", |
|---|
| .. | .. |
|---|
| 196 | 227 | struct unwind_info *ui, ui_buf = { |
|---|
| 197 | 228 | .sample = data, |
|---|
| 198 | 229 | .thread = thread, |
|---|
| 199 | | - .machine = thread->mg->machine, |
|---|
| 230 | + .machine = thread->maps->machine, |
|---|
| 200 | 231 | .cb = cb, |
|---|
| 201 | 232 | .arg = arg, |
|---|
| 202 | 233 | .max_stack = max_stack, |
|---|