perf symbols: Add the build id cache to the vmlinux path

So that if the kernel DSO has a build id because record inserted it in
the perf.data build id table in the header, or a BUILD_ID event was
inserted in the stream, we first look at the build id cache
($HOME/.debug/).

If we find it there, try to use it, allowing offline annotation in
addition to 'perf report'.

Reported-by: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+25 -6
+1 -1
tools/perf/builtin-top.c
··· 1060 1060 pr_err("Can't annotate %s", sym->name); 1061 1061 if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { 1062 1062 pr_err(": No vmlinux file was found in the path:\n"); 1063 - vmlinux_path__fprintf(stderr); 1063 + machine__fprintf_vmlinux_path(machine, stderr); 1064 1064 } else 1065 1065 pr_err(".\n"); 1066 1066 exit(1);
+23 -4
tools/perf/util/symbol.c
··· 1695 1695 symbol_filter_t filter) 1696 1696 { 1697 1697 int i, err = 0; 1698 + char *filename; 1698 1699 1699 1700 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1700 - vmlinux_path__nr_entries); 1701 + vmlinux_path__nr_entries + 1); 1702 + 1703 + filename = dso__build_id_filename(self, NULL, 0); 1704 + if (filename != NULL) { 1705 + err = dso__load_vmlinux(self, map, filename, filter); 1706 + if (err > 0) { 1707 + dso__set_long_name(self, filename); 1708 + goto out; 1709 + } 1710 + free(filename); 1711 + } 1701 1712 1702 1713 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1703 1714 err = dso__load_vmlinux(self, map, vmlinux_path[i], filter); ··· 1717 1706 break; 1718 1707 } 1719 1708 } 1720 - 1709 + out: 1721 1710 return err; 1722 1711 } 1723 1712 ··· 2113 2102 return -1; 2114 2103 } 2115 2104 2116 - size_t vmlinux_path__fprintf(FILE *fp) 2105 + size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp) 2117 2106 { 2118 2107 int i; 2119 2108 size_t printed = 0; 2109 + struct dso *kdso = self->vmlinux_maps[MAP__FUNCTION]->dso; 2110 + 2111 + if (kdso->has_build_id) { 2112 + char filename[PATH_MAX]; 2113 + if (dso__build_id_filename(kdso, filename, sizeof(filename))) 2114 + printed += fprintf(fp, "[0] %s\n", filename); 2115 + } 2120 2116 2121 2117 for (i = 0; i < vmlinux_path__nr_entries; ++i) 2122 - printed += fprintf(fp, "[%d] %s\n", i, vmlinux_path[i]); 2118 + printed += fprintf(fp, "[%d] %s\n", 2119 + i + kdso->has_build_id, vmlinux_path[i]); 2123 2120 2124 2121 return printed; 2125 2122 }
+1 -1
tools/perf/util/symbol.h
··· 216 216 int symbol__init(void); 217 217 bool symbol_type__is_a(char symbol_type, enum map_type map_type); 218 218 219 - size_t vmlinux_path__fprintf(FILE *fp); 219 + size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp); 220 220 221 221 #endif /* __PERF_SYMBOL */