Commit b36f19d572151abb987ce308a3e066b977a2146f

Authored by Arnaldo Carvalho de Melo
1 parent 17930b405e

perf annotate: Use build-ids to find the right DSO

We were still using the pathname found on the MMAP event, that could not
be the one we used when recording, so use the build-id cache for that,
only falling back to use the pathname in the MMAP event if no build-ids
are available.

With this we now also are able to do secure, seamless offline annotation.

Example:

[root@doppio linux-2.6-tip]# perf report -g none -v 2> /dev/null | head -10
     8.12%     Xorg  /usr/lib64/libpixman-1.so.0.14.0       0x0000000000026d02 B [.] pixman_rasterize_edges
     4.68%  firefox  /usr/lib64/xulrunner-1.9.1/libxul.so   0x00000000005dbdba B [.] 0x000000005dbdba
     3.70%  swapper  /lib/modules/2.6.34-rc6/build/vmlinux  0xffffffff81022cea ! [k] read_hpet
     2.96%     init  /lib/modules/2.6.34-rc6/build/vmlinux  0xffffffff81022cea ! [k] read_hpet
     2.73%  swapper  /lib/modules/2.6.34-rc6/build/vmlinux  0xffffffff8100a738 ! [k] mwait_idle_with_hints
[root@doppio linux-2.6-tip]# perf annotate -v pixman_rasterize_edges 2>&1 | grep Executing
Executing: objdump --start-address=0x000000371ce26670 --stop-address=0x000000371ce2709f -dS /root/.debug/.build-id/bd/6ac5199137aaeb279f864717d8d061477466c1|grep -v /root/.debug/.build-id/bd/6ac5199137aaeb279f864717d8d061477466c1|expand
[root@doppio linux-2.6-tip]# perf buildid-list | grep libpixman-1.so.0.14.0
bd6ac5199137aaeb279f864717d8d061477466c1 /usr/lib64/libpixman-1.so.0.14.0
[root@doppio linux-2.6-tip]#

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>

Showing 6 changed files with 54 additions and 18 deletions Side-by-side Diff

tools/perf/util/build-id.c
... ... @@ -6,6 +6,8 @@
6 6 * Copyright (C) 2009, 2010 Red Hat Inc.
7 7 * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
8 8 */
  9 +#include "util.h"
  10 +#include <stdio.h>
9 11 #include "build-id.h"
10 12 #include "event.h"
11 13 #include "symbol.h"
... ... @@ -37,4 +39,24 @@
37 39 .mmap = event__process_mmap,
38 40 .fork = event__process_task,
39 41 };
  42 +
  43 +char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
  44 +{
  45 + char build_id_hex[BUILD_ID_SIZE * 2 + 1];
  46 + const char *home;
  47 +
  48 + if (!self->has_build_id)
  49 + return NULL;
  50 +
  51 + build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex);
  52 + home = getenv("HOME");
  53 + if (bf == NULL) {
  54 + if (asprintf(&bf, "%s/%s/.build-id/%.2s/%s", home,
  55 + DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2) < 0)
  56 + return NULL;
  57 + } else
  58 + snprintf(bf, size, "%s/%s/.build-id/%.2s/%s", home,
  59 + DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2);
  60 + return bf;
  61 +}
tools/perf/util/build-id.h
... ... @@ -5,5 +5,7 @@
5 5  
6 6 extern struct perf_event_ops build_id__mark_dso_hit_ops;
7 7  
  8 +char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
  9 +
8 10 #endif
tools/perf/util/callchain.c
... ... @@ -15,6 +15,7 @@
15 15 #include <errno.h>
16 16 #include <math.h>
17 17  
  18 +#include "util.h"
18 19 #include "callchain.h"
19 20  
20 21 bool ip_callchain__valid(struct ip_callchain *chain, event_t *event)
tools/perf/util/callchain.h
... ... @@ -5,7 +5,6 @@
5 5 #include <linux/list.h>
6 6 #include <linux/rbtree.h>
7 7 #include "event.h"
8   -#include "util.h"
9 8 #include "symbol.h"
10 9  
11 10 enum chain_mode {
tools/perf/util/hist.c
  1 +#include "build-id.h"
1 2 #include "util.h"
2 3 #include "hist.h"
3 4 #include "session.h"
4 5  
5 6  
6 7  
7 8  
... ... @@ -988,22 +989,35 @@
988 989 struct symbol *sym = self->ms.sym;
989 990 struct map *map = self->ms.map;
990 991 struct dso *dso = map->dso;
991   - const char *filename = dso->long_name;
  992 + char *filename = dso__build_id_filename(dso, NULL, 0);
992 993 char command[PATH_MAX * 2];
993 994 FILE *file;
  995 + int err = -1;
994 996 u64 len;
995 997  
996   - if (!filename)
997   - return -1;
  998 + if (filename == NULL) {
  999 + if (dso->has_build_id) {
  1000 + pr_err("Can't annotate %s: not enough memory\n",
  1001 + sym->name);
  1002 + return -1;
  1003 + }
  1004 + /*
  1005 + * If we don't have build-ids, well, lets hope that this
  1006 + * DSO is the same as when 'perf record' ran.
  1007 + */
  1008 + filename = dso->long_name;
  1009 + }
998 1010  
999 1011 if (dso->origin == DSO__ORIG_KERNEL) {
1000   - if (dso->annotate_warned)
1001   - return 0;
  1012 + if (dso->annotate_warned) {
  1013 + err = 0;
  1014 + goto out_free_filename;
  1015 + }
1002 1016 dso->annotate_warned = 1;
1003 1017 pr_err("Can't annotate %s: No vmlinux file was found in the "
1004 1018 "path:\n", sym->name);
1005 1019 vmlinux_path__fprintf(stderr);
1006   - return -1;
  1020 + goto out_free_filename;
1007 1021 }
1008 1022  
1009 1023 pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__,
1010 1024  
... ... @@ -1025,14 +1039,18 @@
1025 1039  
1026 1040 file = popen(command, "r");
1027 1041 if (!file)
1028   - return -1;
  1042 + goto out_free_filename;
1029 1043  
1030 1044 while (!feof(file))
1031 1045 if (hist_entry__parse_objdump_line(self, file, head) < 0)
1032 1046 break;
1033 1047  
1034 1048 pclose(file);
1035   - return 0;
  1049 + err = 0;
  1050 +out_free_filename:
  1051 + if (dso->has_build_id)
  1052 + free(filename);
  1053 + return err;
1036 1054 }
1037 1055  
1038 1056 void hists__inc_nr_events(struct hists *self, u32 type)
tools/perf/util/symbol.c
... ... @@ -11,6 +11,7 @@
11 11 #include <sys/param.h>
12 12 #include <fcntl.h>
13 13 #include <unistd.h>
  14 +#include "build-id.h"
14 15 #include "symbol.h"
15 16 #include "strlist.h"
16 17  
... ... @@ -1293,7 +1294,6 @@
1293 1294 int size = PATH_MAX;
1294 1295 char *name;
1295 1296 u8 build_id[BUILD_ID_SIZE];
1296   - char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1297 1297 int ret = -1;
1298 1298 int fd;
1299 1299 struct machine *machine;
1300 1300  
... ... @@ -1325,15 +1325,8 @@
1325 1325 }
1326 1326  
1327 1327 self->origin = DSO__ORIG_BUILD_ID_CACHE;
1328   -
1329   - if (self->has_build_id) {
1330   - build_id__sprintf(self->build_id, sizeof(self->build_id),
1331   - build_id_hex);
1332   - snprintf(name, size, "%s/%s/.build-id/%.2s/%s",
1333   - getenv("HOME"), DEBUG_CACHE_DIR,
1334   - build_id_hex, build_id_hex + 2);
  1328 + if (dso__build_id_filename(self, name, size) != NULL)
1335 1329 goto open_file;
1336   - }
1337 1330 more:
1338 1331 do {
1339 1332 self->origin++;
... ... @@ -1349,6 +1342,7 @@
1349 1342 case DSO__ORIG_BUILDID:
1350 1343 if (filename__read_build_id(self->long_name, build_id,
1351 1344 sizeof(build_id))) {
  1345 + char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1352 1346 build_id__sprintf(build_id, sizeof(build_id),
1353 1347 build_id_hex);
1354 1348 snprintf(name, size,