aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-05-20 11:15:33 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-05-20 11:15:33 -0400
commitb36f19d572151abb987ce308a3e066b977a2146f (patch)
tree07f520f8b3da969d288e34a121cc31a0209eb519 /tools/perf/util
parent17930b405e0ecdc8ecc4d336377a92950e2de76a (diff)
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>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/build-id.c22
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/callchain.c1
-rw-r--r--tools/perf/util/callchain.h1
-rw-r--r--tools/perf/util/hist.c34
-rw-r--r--tools/perf/util/symbol.c12
6 files changed, 54 insertions, 18 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0f60a3906808..70c5cf87d020 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -6,6 +6,8 @@
6 * Copyright (C) 2009, 2010 Red Hat Inc. 6 * Copyright (C) 2009, 2010 Red Hat Inc.
7 * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com> 7 * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 8 */
9#include "util.h"
10#include <stdio.h>
9#include "build-id.h" 11#include "build-id.h"
10#include "event.h" 12#include "event.h"
11#include "symbol.h" 13#include "symbol.h"
@@ -37,3 +39,23 @@ struct perf_event_ops build_id__mark_dso_hit_ops = {
37 .mmap = event__process_mmap, 39 .mmap = event__process_mmap,
38 .fork = event__process_task, 40 .fork = event__process_task,
39}; 41};
42
43char *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}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 1d981d63cf9a..5dafb00eaa06 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -5,4 +5,6 @@
5 5
6extern struct perf_event_ops build_id__mark_dso_hit_ops; 6extern struct perf_event_ops build_id__mark_dso_hit_ops;
7 7
8char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
9
8#endif 10#endif
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 21a52e0a4435..62b69ad4aa73 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,6 +15,7 @@
15#include <errno.h> 15#include <errno.h>
16#include <math.h> 16#include <math.h>
17 17
18#include "util.h"
18#include "callchain.h" 19#include "callchain.h"
19 20
20bool ip_callchain__valid(struct ip_callchain *chain, event_t *event) 21bool ip_callchain__valid(struct ip_callchain *chain, event_t *event)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 1cba1f5504e7..1ca73e4a2723 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -5,7 +5,6 @@
5#include <linux/list.h> 5#include <linux/list.h>
6#include <linux/rbtree.h> 6#include <linux/rbtree.h>
7#include "event.h" 7#include "event.h"
8#include "util.h"
9#include "symbol.h" 8#include "symbol.h"
10 9
11enum chain_mode { 10enum chain_mode {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9a71c94f057a..739c39fd0ade 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
1#include "build-id.h"
1#include "util.h" 2#include "util.h"
2#include "hist.h" 3#include "hist.h"
3#include "session.h" 4#include "session.h"
@@ -988,22 +989,35 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
988 struct symbol *sym = self->ms.sym; 989 struct symbol *sym = self->ms.sym;
989 struct map *map = self->ms.map; 990 struct map *map = self->ms.map;
990 struct dso *dso = map->dso; 991 struct dso *dso = map->dso;
991 const char *filename = dso->long_name; 992 char *filename = dso__build_id_filename(dso, NULL, 0);
992 char command[PATH_MAX * 2]; 993 char command[PATH_MAX * 2];
993 FILE *file; 994 FILE *file;
995 int err = -1;
994 u64 len; 996 u64 len;
995 997
996 if (!filename) 998 if (filename == NULL) {
997 return -1; 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 if (dso->origin == DSO__ORIG_KERNEL) { 1011 if (dso->origin == DSO__ORIG_KERNEL) {
1000 if (dso->annotate_warned) 1012 if (dso->annotate_warned) {
1001 return 0; 1013 err = 0;
1014 goto out_free_filename;
1015 }
1002 dso->annotate_warned = 1; 1016 dso->annotate_warned = 1;
1003 pr_err("Can't annotate %s: No vmlinux file was found in the " 1017 pr_err("Can't annotate %s: No vmlinux file was found in the "
1004 "path:\n", sym->name); 1018 "path:\n", sym->name);
1005 vmlinux_path__fprintf(stderr); 1019 vmlinux_path__fprintf(stderr);
1006 return -1; 1020 goto out_free_filename;
1007 } 1021 }
1008 1022
1009 pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, 1023 pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__,
@@ -1025,14 +1039,18 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
1025 1039
1026 file = popen(command, "r"); 1040 file = popen(command, "r");
1027 if (!file) 1041 if (!file)
1028 return -1; 1042 goto out_free_filename;
1029 1043
1030 while (!feof(file)) 1044 while (!feof(file))
1031 if (hist_entry__parse_objdump_line(self, file, head) < 0) 1045 if (hist_entry__parse_objdump_line(self, file, head) < 0)
1032 break; 1046 break;
1033 1047
1034 pclose(file); 1048 pclose(file);
1035 return 0; 1049 err = 0;
1050out_free_filename:
1051 if (dso->has_build_id)
1052 free(filename);
1053 return err;
1036} 1054}
1037 1055
1038void hists__inc_nr_events(struct hists *self, u32 type) 1056void hists__inc_nr_events(struct hists *self, u32 type)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 96bff0e54863..aaa51ba147df 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -11,6 +11,7 @@
11#include <sys/param.h> 11#include <sys/param.h>
12#include <fcntl.h> 12#include <fcntl.h>
13#include <unistd.h> 13#include <unistd.h>
14#include "build-id.h"
14#include "symbol.h" 15#include "symbol.h"
15#include "strlist.h" 16#include "strlist.h"
16 17
@@ -1293,7 +1294,6 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1293 int size = PATH_MAX; 1294 int size = PATH_MAX;
1294 char *name; 1295 char *name;
1295 u8 build_id[BUILD_ID_SIZE]; 1296 u8 build_id[BUILD_ID_SIZE];
1296 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1297 int ret = -1; 1297 int ret = -1;
1298 int fd; 1298 int fd;
1299 struct machine *machine; 1299 struct machine *machine;
@@ -1325,15 +1325,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1325 } 1325 }
1326 1326
1327 self->origin = DSO__ORIG_BUILD_ID_CACHE; 1327 self->origin = DSO__ORIG_BUILD_ID_CACHE;
1328 1328 if (dso__build_id_filename(self, name, size) != NULL)
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);
1335 goto open_file; 1329 goto open_file;
1336 }
1337more: 1330more:
1338 do { 1331 do {
1339 self->origin++; 1332 self->origin++;
@@ -1349,6 +1342,7 @@ more:
1349 case DSO__ORIG_BUILDID: 1342 case DSO__ORIG_BUILDID:
1350 if (filename__read_build_id(self->long_name, build_id, 1343 if (filename__read_build_id(self->long_name, build_id,
1351 sizeof(build_id))) { 1344 sizeof(build_id))) {
1345 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1352 build_id__sprintf(build_id, sizeof(build_id), 1346 build_id__sprintf(build_id, sizeof(build_id),
1353 build_id_hex); 1347 build_id_hex);
1354 snprintf(name, size, 1348 snprintf(name, size,