summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/data_map.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-04 18:50:43 -0200
committerIngo Molnar <mingo@elte.hu>2009-11-08 10:44:36 +0100
commit8d06367fa79c053a4a56a2ce0bb9e840f5da1236 (patch)
tree8ea057102e390c8411b77aeab7ea9c06ec0e0561 /tools/perf/util/data_map.c
parent2643ce11457a99a85c5bed8dd631e35968e6ca5a (diff)
perf symbols: Use the buildids if present
With this change 'perf record' will intercept PERF_RECORD_MMAP calls, creating a linked list of DSOs, then when the session finishes, it will traverse this list and read the buildids, stashing them at the end of the file and will set up a new feature bit in the header bitmask. 'perf report' will then notice this feature and populate the 'dsos' list and set the build ids. When reading the symtabs it will refuse to load from a file that doesn't have the same build id. This improves the reliability of the profiler output, as symbols and profiling data is more guaranteed to match. Example: [root@doppio ~]# perf report | head /home/acme/bin/perf with build id b1ea544ac3746e7538972548a09aadecc5753868 not found, continuing without symbols # Samples: 2621434559 # # Overhead Command Shared Object Symbol # ........ ............... ............................. ...... # 7.91% init [kernel] [k] read_hpet 7.64% init [kernel] [k] mwait_idle_with_hints 7.60% swapper [kernel] [k] read_hpet 7.60% swapper [kernel] [k] mwait_idle_with_hints 3.65% init [kernel] [k] 0xffffffffa02339d9 [root@doppio ~]# In this case the 'perf' binary was an older one, vanished, so its symbols probably wouldn't match or would cause subtly different (and misleading) output. Next patches will support the kernel as well, reading the build id notes for it and the modules from /sys. Another patch should also introduce a new plumbing command: 'perf list-buildids' that will then be used in porcelain that is distro specific to fetch -debuginfo packages where such buildids are present. This will in turn allow for one to run 'perf record' in one machine and 'perf report' in another. Future work on having the buildid sent directly from the kernel in the PERF_RECORD_MMAP event is needed to close races, as the DSO can be changed during a 'perf record' session, but this patch at least helps with non-corner cases and current/older kernels. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jason Baron <jbaron@redhat.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: K. Prasad <prasad@linux.vnet.ibm.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Roland McGrath <roland@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <1257367843-26224-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/data_map.c')
-rw-r--r--tools/perf/util/data_map.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index c458db9ede6..00a9c114c8d 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -70,6 +70,39 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
}
}
+static int perf_header__read_build_ids(const struct perf_header *self,
+ int input, off_t file_size)
+{
+ off_t offset = self->data_offset + self->data_size;
+ struct build_id_event bev;
+ char filename[PATH_MAX];
+ int err = -1;
+
+ if (lseek(input, offset, SEEK_SET) < 0)
+ return -1;
+
+ while (offset < file_size) {
+ struct dso *dso;
+ ssize_t len;
+
+ if (read(input, &bev, sizeof(bev)) != sizeof(bev))
+ goto out;
+
+ len = bev.header.size - sizeof(bev);
+ if (read(input, filename, len) != len)
+ goto out;
+
+ dso = dsos__findnew(filename);
+ if (dso != NULL)
+ dso__set_build_id(dso, &bev.build_id);
+
+ offset += bev.header.size;
+ }
+ err = 0;
+out:
+ return err;
+}
+
int mmap_dispatch_perf_file(struct perf_header **pheader,
const char *input_name,
int force,
@@ -130,6 +163,10 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
if (curr_handler->sample_type_check(sample_type) < 0)
exit(-1);
+ if (perf_header__has_feat(header, HEADER_BUILD_ID) &&
+ perf_header__read_build_ids(header, input, input_stat.st_size))
+ pr_debug("failed to read buildids, continuing...\n");
+
if (load_kernel(NULL) < 0) {
perror("failed to load kernel symbols");
return EXIT_FAILURE;