From 454c407ec17a0c63e4023ac0877d687945a7df4a Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sat, 1 May 2010 01:41:20 -0500 Subject: perf: add perf-inject builtin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, perf 'live mode' writes build-ids at the end of the session, which isn't actually useful for processing live mode events. What would be better would be to have the build-ids sent before any of the samples that reference them, which can be done by processing the event stream and retrieving the build-ids on the first hit. Doing that in perf-record itself, however, is off-limits. This patch introduces perf-inject, which does the same job while leaving perf-record untouched. Normal mode perf still records the build-ids at the end of the session as it should, but for live mode, perf-inject can be injected in between the record and report steps e.g.: perf record -o - ./hackbench 10 | perf inject -v -b | perf report -v -i - perf-inject reads a perf-record event stream and repipes it to stdout. At any point the processing code can inject other events into the event stream - in this case build-ids (-b option) are read and injected as needed into the event stream. Build-ids are just the first user of perf-inject - potentially anything that needs userspace processing to augment the trace stream with additional information could make use of this facility. Cc: Ingo Molnar Cc: Steven Rostedt Cc: Frédéric Weisbecker LKML-Reference: <1272696080-16435-3-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'tools/perf/util/header.c') diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2d1d97e0746d..79da0e50ef8f 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -713,10 +713,18 @@ static int __event_process_build_id(struct build_id_event *bev, dso = __dsos__findnew(head, filename); if (dso != NULL) { + char sbuild_id[BUILD_ID_SIZE * 2 + 1]; + dso__set_build_id(dso, &bev->build_id); - if (filename[0] == '[') - dso->kernel = dso_type; - } + + if (filename[0] == '[') + dso->kernel = dso_type; + + build_id__sprintf(dso->build_id, sizeof(dso->build_id), + sbuild_id); + pr_debug("build id event received for %s: %s\n", + dso->long_name, sbuild_id); + } err = 0; out: @@ -767,7 +775,7 @@ static int perf_file_section__process(struct perf_file_section *self, switch (feat) { case HEADER_TRACE_INFO: - trace_report(fd); + trace_report(fd, false); break; case HEADER_BUILD_ID: @@ -782,12 +790,16 @@ static int perf_file_section__process(struct perf_file_section *self, } static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, - struct perf_header *ph, int fd) + struct perf_header *ph, int fd, + bool repipe) { if (do_read(fd, self, sizeof(*self)) <= 0 || memcmp(&self->magic, __perf_magic, sizeof(self->magic))) return -1; + if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) + return -1; + if (self->size != sizeof(*self)) { u64 size = bswap_64(self->size); @@ -805,7 +817,8 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) struct perf_header *self = &session->header; struct perf_pipe_file_header f_header; - if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { + if (perf_file_header__read_pipe(&f_header, self, fd, + session->repipe) < 0) { pr_debug("incompatible file format\n"); return -EINVAL; } @@ -1096,12 +1109,17 @@ int event__process_tracing_data(event_t *self, lseek(session->fd, offset + sizeof(struct tracing_data_event), SEEK_SET); - size_read = trace_report(session->fd); + size_read = trace_report(session->fd, session->repipe); padding = ALIGN(size_read, sizeof(u64)) - size_read; if (read(session->fd, buf, padding) < 0) die("reading input file"); + if (session->repipe) { + int retw = write(STDOUT_FILENO, buf, padding); + if (retw <= 0 || retw != padding) + die("repiping tracing data padding"); + } if (size_read + padding != size) die("tracing data size mismatch"); @@ -1110,7 +1128,8 @@ int event__process_tracing_data(event_t *self, } int event__synthesize_build_id(struct dso *pos, u16 misc, - event__handler_t process, struct machine *machine, + event__handler_t process, + struct machine *machine, struct perf_session *session) { event_t ev; -- cgit v1.2.3