aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-04 15:50:43 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-08 04:44:36 -0500
commit8d06367fa79c053a4a56a2ce0bb9e840f5da1236 (patch)
tree8ea057102e390c8411b77aeab7ea9c06ec0e0561 /tools/perf/builtin-record.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/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4a73d89ce5d..ab333812ace 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -17,6 +17,7 @@
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h" 18#include "util/event.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/symbol.h"
20 21
21#include <unistd.h> 22#include <unistd.h>
22#include <sched.h> 23#include <sched.h>
@@ -109,9 +110,21 @@ static void write_output(void *buf, size_t size)
109 } 110 }
110} 111}
111 112
113static void write_event(event_t *buf, size_t size)
114{
115 /*
116 * Add it to the list of DSOs, so that when we finish this
117 * record session we can pick the available build-ids.
118 */
119 if (buf->header.type == PERF_RECORD_MMAP)
120 dsos__findnew(buf->mmap.filename);
121
122 write_output(buf, size);
123}
124
112static int process_synthesized_event(event_t *event) 125static int process_synthesized_event(event_t *event)
113{ 126{
114 write_output(event, event->header.size); 127 write_event(event, event->header.size);
115 return 0; 128 return 0;
116} 129}
117 130
@@ -163,14 +176,14 @@ static void mmap_read(struct mmap_data *md)
163 size = md->mask + 1 - (old & md->mask); 176 size = md->mask + 1 - (old & md->mask);
164 old += size; 177 old += size;
165 178
166 write_output(buf, size); 179 write_event(buf, size);
167 } 180 }
168 181
169 buf = &data[old & md->mask]; 182 buf = &data[old & md->mask];
170 size = head - old; 183 size = head - old;
171 old += size; 184 old += size;
172 185
173 write_output(buf, size); 186 write_event(buf, size);
174 187
175 md->prev = old; 188 md->prev = old;
176 mmap_write_tail(md, old); 189 mmap_write_tail(md, old);
@@ -365,10 +378,38 @@ static void open_counters(int cpu, pid_t pid)
365 nr_cpu++; 378 nr_cpu++;
366} 379}
367 380
381static bool write_buildid_table(void)
382{
383 struct dso *pos;
384 bool have_buildid = false;
385
386 list_for_each_entry(pos, &dsos, node) {
387 struct build_id_event b;
388 size_t len;
389
390 if (filename__read_build_id(pos->long_name,
391 &b.build_id,
392 sizeof(b.build_id)) < 0)
393 continue;
394 have_buildid = true;
395 memset(&b.header, 0, sizeof(b.header));
396 len = strlen(pos->long_name) + 1;
397 len = ALIGN(len, 64);
398 b.header.size = sizeof(b) + len;
399 write_output(&b, sizeof(b));
400 write_output(pos->long_name, len);
401 }
402
403 return have_buildid;
404}
405
368static void atexit_header(void) 406static void atexit_header(void)
369{ 407{
370 header->data_size += bytes_written; 408 header->data_size += bytes_written;
371 409
410 if (write_buildid_table())
411 perf_header__set_feat(header, HEADER_BUILD_ID);
412
372 perf_header__write(header, output); 413 perf_header__write(header, output);
373} 414}
374 415
@@ -572,6 +613,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
572{ 613{
573 int counter; 614 int counter;
574 615
616 symbol__init(0);
617
575 argc = parse_options(argc, argv, options, record_usage, 618 argc = parse_options(argc, argv, options, record_usage,
576 PARSE_OPT_STOP_AT_NON_OPTION); 619 PARSE_OPT_STOP_AT_NON_OPTION);
577 if (!argc && target_pid == -1 && !system_wide) 620 if (!argc && target_pid == -1 && !system_wide)