aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorTom Zanussi <tzanussi@gmail.com>2010-05-01 02:41:20 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-05-02 12:36:56 -0400
commit454c407ec17a0c63e4023ac0877d687945a7df4a (patch)
tree1271299a59a89419c0dd4dcbf29b4492b63555ca /tools/perf
parent789688faef5b3ba78065beaf2f3d6f1c839f74a3 (diff)
perf: add perf-inject builtin
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 <mingo@elte.hu> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frédéric Weisbecker <fweisbec@gmail.com> LKML-Reference: <1272696080-16435-3-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-buildid-list.c2
-rw-r--r--tools/perf/builtin-diff.c4
-rw-r--r--tools/perf/builtin-inject.c228
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-timechart.c2
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/util/header.c35
-rw-r--r--tools/perf/util/session.c3
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/trace-event-read.c19
-rw-r--r--tools/perf/util/trace-event.h2
20 files changed, 293 insertions, 24 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index c5ac0a991565..0ef5cfe52f2d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -490,6 +490,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
490BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 490BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
491BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o 491BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
492BUILTIN_OBJS += $(OUTPUT)builtin-test.o 492BUILTIN_OBJS += $(OUTPUT)builtin-test.o
493BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
493 494
494PERFLIBS = $(LIB_FILE) 495PERFLIBS = $(LIB_FILE)
495 496
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index b57dbcf62af3..ee154b58772b 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -554,7 +554,7 @@ static int __cmd_annotate(void)
554 int ret; 554 int ret;
555 struct perf_session *session; 555 struct perf_session *session;
556 556
557 session = perf_session__new(input_name, O_RDONLY, force); 557 session = perf_session__new(input_name, O_RDONLY, force, false);
558 if (session == NULL) 558 if (session == NULL)
559 return -ENOMEM; 559 return -ENOMEM;
560 560
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 7dc3b2e7a5e4..44a47e13bd67 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -39,7 +39,7 @@ static int __cmd_buildid_list(void)
39 int err = -1; 39 int err = -1;
40 struct perf_session *session; 40 struct perf_session *session;
41 41
42 session = perf_session__new(input_name, O_RDONLY, force); 42 session = perf_session__new(input_name, O_RDONLY, force, false);
43 if (session == NULL) 43 if (session == NULL)
44 return -1; 44 return -1;
45 45
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 207e860591e2..4cce68f23686 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -156,8 +156,8 @@ static int __cmd_diff(void)
156 int ret, i; 156 int ret, i;
157 struct perf_session *session[2]; 157 struct perf_session *session[2];
158 158
159 session[0] = perf_session__new(input_old, O_RDONLY, force); 159 session[0] = perf_session__new(input_old, O_RDONLY, force, false);
160 session[1] = perf_session__new(input_new, O_RDONLY, force); 160 session[1] = perf_session__new(input_new, O_RDONLY, force, false);
161 if (session[0] == NULL || session[1] == NULL) 161 if (session[0] == NULL || session[1] == NULL)
162 return -ENOMEM; 162 return -ENOMEM;
163 163
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
new file mode 100644
index 000000000000..a5902a3eadd3
--- /dev/null
+++ b/tools/perf/builtin-inject.c
@@ -0,0 +1,228 @@
1/*
2 * builtin-inject.c
3 *
4 * Builtin inject command: Examine the live mode (stdin) event stream
5 * and repipe it to stdout while optionally injecting additional
6 * events into it.
7 */
8#include "builtin.h"
9
10#include "perf.h"
11#include "util/session.h"
12#include "util/debug.h"
13
14#include "util/parse-options.h"
15
16static char const *input_name = "-";
17static bool inject_build_ids;
18
19static int event__repipe(event_t *event __used,
20 struct perf_session *session __used)
21{
22 uint32_t size;
23 void *buf = event;
24
25 size = event->header.size;
26
27 while (size) {
28 int ret = write(STDOUT_FILENO, buf, size);
29 if (ret < 0)
30 return -errno;
31
32 size -= ret;
33 buf += ret;
34 }
35
36 return 0;
37}
38
39static int event__repipe_mmap(event_t *self, struct perf_session *session)
40{
41 int err;
42
43 err = event__process_mmap(self, session);
44 event__repipe(self, session);
45
46 return err;
47}
48
49static int event__repipe_task(event_t *self, struct perf_session *session)
50{
51 int err;
52
53 err = event__process_task(self, session);
54 event__repipe(self, session);
55
56 return err;
57}
58
59static int event__repipe_tracing_data(event_t *self,
60 struct perf_session *session)
61{
62 int err;
63
64 event__repipe(self, session);
65 err = event__process_tracing_data(self, session);
66
67 return err;
68}
69
70static int read_buildid(struct map *self, struct perf_session *session)
71{
72 const char *name = self->dso->long_name;
73 int err;
74
75 if (filename__read_build_id(self->dso->long_name, self->dso->build_id,
76 sizeof(self->dso->build_id)) > 0) {
77 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
78
79 self->dso->has_build_id = true;
80
81 build_id__sprintf(self->dso->build_id,
82 sizeof(self->dso->build_id),
83 sbuild_id);
84 pr_debug("build id found for %s: %s\n", self->dso->long_name,
85 sbuild_id);
86 }
87
88 if (self->dso->has_build_id) {
89 u16 misc = PERF_RECORD_MISC_USER;
90 struct machine *machine;
91
92 misc = self->dso->kernel ? PERF_RECORD_MISC_KERNEL : misc;
93
94 machine = perf_session__find_host_machine(session);
95 if (!machine) {
96 pr_err("Can't find machine for session\n");
97 return -1;
98 }
99
100 err = event__synthesize_build_id(self->dso, misc,
101 event__repipe, machine,
102 session);
103 if (err) {
104 pr_err("Can't synthesize build_id event for %s\n",
105 name);
106 return -1;
107 }
108 } else {
109 pr_debug("no build_id found for %s\n", name);
110 return -1;
111 }
112
113 return 0;
114}
115
116static int event__inject_buildid(event_t *event, struct perf_session *session)
117{
118 struct addr_location al;
119 struct thread *thread;
120 u8 cpumode;
121 int err = 0;
122
123 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
124
125 thread = perf_session__findnew(session, event->ip.pid);
126 if (thread == NULL) {
127 pr_err("problem processing %d event, skipping it.\n",
128 event->header.type);
129 err = -1;
130 goto repipe;
131 }
132
133 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
134 event->ip.pid, event->ip.ip, &al);
135
136 if (al.map != NULL) {
137 if (!al.map->dso->hit) {
138 al.map->dso->hit = 1;
139 if (map__load(al.map, NULL) >= 0)
140 read_buildid(al.map, session);
141 else
142 pr_warning("no symbols found in %s, maybe "
143 "install a debug package?\n",
144 al.map->dso->long_name);
145 }
146 }
147
148repipe:
149 event__repipe(event, session);
150 return err;
151}
152
153struct perf_event_ops inject_ops = {
154 .sample = event__repipe,
155 .mmap = event__repipe,
156 .comm = event__repipe,
157 .fork = event__repipe,
158 .exit = event__repipe,
159 .lost = event__repipe,
160 .read = event__repipe,
161 .throttle = event__repipe,
162 .unthrottle = event__repipe,
163 .attr = event__repipe,
164 .event_type = event__repipe,
165 .tracing_data = event__repipe,
166 .build_id = event__repipe,
167};
168
169extern volatile int session_done;
170
171static void sig_handler(int sig __attribute__((__unused__)))
172{
173 session_done = 1;
174}
175
176static int __cmd_inject(void)
177{
178 struct perf_session *session;
179 int ret = -EINVAL;
180
181 signal(SIGINT, sig_handler);
182
183 if (inject_build_ids) {
184 inject_ops.sample = event__inject_buildid;
185 inject_ops.mmap = event__repipe_mmap;
186 inject_ops.fork = event__repipe_task;
187 inject_ops.tracing_data = event__repipe_tracing_data;
188 }
189
190 session = perf_session__new(input_name, O_RDONLY, false, true);
191 if (session == NULL)
192 return -ENOMEM;
193
194 ret = perf_session__process_events(session, &inject_ops);
195
196 perf_session__delete(session);
197
198 return ret;
199}
200
201static const char * const report_usage[] = {
202 "perf inject [<options>]",
203 NULL
204};
205
206static const struct option options[] = {
207 OPT_BOOLEAN('b', "inject build-ids", &inject_build_ids,
208 "Inject build-ids into the output stream"),
209 OPT_INCR('v', "verbose", &verbose,
210 "be more verbose (show build ids, etc)"),
211 OPT_END()
212};
213
214int cmd_inject(int argc, const char **argv, const char *prefix __used)
215{
216 argc = parse_options(argc, argv, options, report_usage, 0);
217
218 /*
219 * Any (unrecognized) arguments left?
220 */
221 if (argc)
222 usage_with_options(report_usage, options);
223
224 if (symbol__init() < 0)
225 return -1;
226
227 return __cmd_inject();
228}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index ee05dba9609a..31f60a2535e0 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -492,7 +492,7 @@ static void sort_result(void)
492static int __cmd_kmem(void) 492static int __cmd_kmem(void)
493{ 493{
494 int err = -EINVAL; 494 int err = -EINVAL;
495 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); 495 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
496 if (session == NULL) 496 if (session == NULL)
497 return -ENOMEM; 497 return -ENOMEM;
498 498
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ce276750b140..6605000ed73d 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -818,7 +818,7 @@ static struct perf_event_ops eops = {
818 818
819static int read_events(void) 819static int read_events(void)
820{ 820{
821 session = perf_session__new(input_name, O_RDONLY, 0); 821 session = perf_session__new(input_name, O_RDONLY, 0, false);
822 if (!session) 822 if (!session)
823 die("Initializing perf session failed\n"); 823 die("Initializing perf session failed\n");
824 824
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 1a7379674c29..e382d93d369c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -548,7 +548,7 @@ static int __cmd_record(int argc, const char **argv)
548 } 548 }
549 549
550 session = perf_session__new(output_name, O_WRONLY, 550 session = perf_session__new(output_name, O_WRONLY,
551 write_mode == WRITE_FORCE); 551 write_mode == WRITE_FORCE, false);
552 if (session == NULL) { 552 if (session == NULL) {
553 pr_err("Not enough memory for reading perf file header\n"); 553 pr_err("Not enough memory for reading perf file header\n");
554 return -1; 554 return -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f1b46eb7ef9a..0152b5412cc3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -289,7 +289,7 @@ static int __cmd_report(void)
289 289
290 signal(SIGINT, sig_handler); 290 signal(SIGINT, sig_handler);
291 291
292 session = perf_session__new(input_name, O_RDONLY, force); 292 session = perf_session__new(input_name, O_RDONLY, force, false);
293 if (session == NULL) 293 if (session == NULL)
294 return -ENOMEM; 294 return -ENOMEM;
295 295
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 94453f1e4e01..aef6ed0e119c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1660,7 +1660,7 @@ static struct perf_event_ops event_ops = {
1660static int read_events(void) 1660static int read_events(void)
1661{ 1661{
1662 int err = -EINVAL; 1662 int err = -EINVAL;
1663 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); 1663 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
1664 if (session == NULL) 1664 if (session == NULL)
1665 return -ENOMEM; 1665 return -ENOMEM;
1666 1666
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index c35aa44f82ba..5a52ed9fc10b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -936,7 +936,7 @@ static struct perf_event_ops event_ops = {
936 936
937static int __cmd_timechart(void) 937static int __cmd_timechart(void)
938{ 938{
939 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); 939 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
940 int ret = -EINVAL; 940 int ret = -EINVAL;
941 941
942 if (session == NULL) 942 if (session == NULL)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index d95281f588d2..3de397764cb3 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1287,7 +1287,7 @@ static int __cmd_top(void)
1287 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1287 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1288 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1288 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1289 */ 1289 */
1290 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false); 1290 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false);
1291 if (session == NULL) 1291 if (session == NULL)
1292 return -ENOMEM; 1292 return -ENOMEM;
1293 1293
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 77f556f7604c..9c483e92e8db 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -661,7 +661,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
661 if (!script_name) 661 if (!script_name)
662 setup_pager(); 662 setup_pager();
663 663
664 session = perf_session__new(input_name, O_RDONLY, 0); 664 session = perf_session__new(input_name, O_RDONLY, 0, false);
665 if (session == NULL) 665 if (session == NULL)
666 return -ENOMEM; 666 return -ENOMEM;
667 667
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 34a8a9ab9617..921245b28583 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -34,5 +34,6 @@ extern int cmd_kmem(int argc, const char **argv, const char *prefix);
34extern int cmd_lock(int argc, const char **argv, const char *prefix); 34extern int cmd_lock(int argc, const char **argv, const char *prefix);
35extern int cmd_kvm(int argc, const char **argv, const char *prefix); 35extern int cmd_kvm(int argc, const char **argv, const char *prefix);
36extern int cmd_test(int argc, const char **argv, const char *prefix); 36extern int cmd_test(int argc, const char **argv, const char *prefix);
37extern int cmd_inject(int argc, const char **argv, const char *prefix);
37 38
38#endif 39#endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 5ff9b5b46970..08e0e5d2b50e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -309,6 +309,7 @@ static void handle_internal_command(int argc, const char **argv)
309 { "lock", cmd_lock, 0 }, 309 { "lock", cmd_lock, 0 },
310 { "kvm", cmd_kvm, 0 }, 310 { "kvm", cmd_kvm, 0 },
311 { "test", cmd_test, 0 }, 311 { "test", cmd_test, 0 },
312 { "inject", cmd_inject, 0 },
312 }; 313 };
313 unsigned int i; 314 unsigned int i;
314 static const char ext[] = STRIP_EXTENSION; 315 static const char ext[] = STRIP_EXTENSION;
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,
713 713
714 dso = __dsos__findnew(head, filename); 714 dso = __dsos__findnew(head, filename);
715 if (dso != NULL) { 715 if (dso != NULL) {
716 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
717
716 dso__set_build_id(dso, &bev->build_id); 718 dso__set_build_id(dso, &bev->build_id);
717 if (filename[0] == '[') 719
718 dso->kernel = dso_type; 720 if (filename[0] == '[')
719 } 721 dso->kernel = dso_type;
722
723 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
724 sbuild_id);
725 pr_debug("build id event received for %s: %s\n",
726 dso->long_name, sbuild_id);
727 }
720 728
721 err = 0; 729 err = 0;
722out: 730out:
@@ -767,7 +775,7 @@ static int perf_file_section__process(struct perf_file_section *self,
767 775
768 switch (feat) { 776 switch (feat) {
769 case HEADER_TRACE_INFO: 777 case HEADER_TRACE_INFO:
770 trace_report(fd); 778 trace_report(fd, false);
771 break; 779 break;
772 780
773 case HEADER_BUILD_ID: 781 case HEADER_BUILD_ID:
@@ -782,12 +790,16 @@ static int perf_file_section__process(struct perf_file_section *self,
782} 790}
783 791
784static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, 792static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
785 struct perf_header *ph, int fd) 793 struct perf_header *ph, int fd,
794 bool repipe)
786{ 795{
787 if (do_read(fd, self, sizeof(*self)) <= 0 || 796 if (do_read(fd, self, sizeof(*self)) <= 0 ||
788 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 797 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
789 return -1; 798 return -1;
790 799
800 if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0)
801 return -1;
802
791 if (self->size != sizeof(*self)) { 803 if (self->size != sizeof(*self)) {
792 u64 size = bswap_64(self->size); 804 u64 size = bswap_64(self->size);
793 805
@@ -805,7 +817,8 @@ static int perf_header__read_pipe(struct perf_session *session, int fd)
805 struct perf_header *self = &session->header; 817 struct perf_header *self = &session->header;
806 struct perf_pipe_file_header f_header; 818 struct perf_pipe_file_header f_header;
807 819
808 if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { 820 if (perf_file_header__read_pipe(&f_header, self, fd,
821 session->repipe) < 0) {
809 pr_debug("incompatible file format\n"); 822 pr_debug("incompatible file format\n");
810 return -EINVAL; 823 return -EINVAL;
811 } 824 }
@@ -1096,12 +1109,17 @@ int event__process_tracing_data(event_t *self,
1096 lseek(session->fd, offset + sizeof(struct tracing_data_event), 1109 lseek(session->fd, offset + sizeof(struct tracing_data_event),
1097 SEEK_SET); 1110 SEEK_SET);
1098 1111
1099 size_read = trace_report(session->fd); 1112 size_read = trace_report(session->fd, session->repipe);
1100 1113
1101 padding = ALIGN(size_read, sizeof(u64)) - size_read; 1114 padding = ALIGN(size_read, sizeof(u64)) - size_read;
1102 1115
1103 if (read(session->fd, buf, padding) < 0) 1116 if (read(session->fd, buf, padding) < 0)
1104 die("reading input file"); 1117 die("reading input file");
1118 if (session->repipe) {
1119 int retw = write(STDOUT_FILENO, buf, padding);
1120 if (retw <= 0 || retw != padding)
1121 die("repiping tracing data padding");
1122 }
1105 1123
1106 if (size_read + padding != size) 1124 if (size_read + padding != size)
1107 die("tracing data size mismatch"); 1125 die("tracing data size mismatch");
@@ -1110,7 +1128,8 @@ int event__process_tracing_data(event_t *self,
1110} 1128}
1111 1129
1112int event__synthesize_build_id(struct dso *pos, u16 misc, 1130int event__synthesize_build_id(struct dso *pos, u16 misc,
1113 event__handler_t process, struct machine *machine, 1131 event__handler_t process,
1132 struct machine *machine,
1114 struct perf_session *session) 1133 struct perf_session *session)
1115{ 1134{
1116 event_t ev; 1135 event_t ev;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a8dd73ed1581..5d353e70fe26 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -77,7 +77,7 @@ int perf_session__create_kernel_maps(struct perf_session *self)
77 return ret; 77 return ret;
78} 78}
79 79
80struct perf_session *perf_session__new(const char *filename, int mode, bool force) 80struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe)
81{ 81{
82 size_t len = filename ? strlen(filename) + 1 : 0; 82 size_t len = filename ? strlen(filename) + 1 : 0;
83 struct perf_session *self = zalloc(sizeof(*self) + len); 83 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -97,6 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
97 self->cwdlen = 0; 97 self->cwdlen = 0;
98 self->unknown_events = 0; 98 self->unknown_events = 0;
99 self->machines = RB_ROOT; 99 self->machines = RB_ROOT;
100 self->repipe = repipe;
100 self->ordered_samples.flush_limit = ULLONG_MAX; 101 self->ordered_samples.flush_limit = ULLONG_MAX;
101 INIT_LIST_HEAD(&self->ordered_samples.samples_head); 102 INIT_LIST_HEAD(&self->ordered_samples.samples_head);
102 103
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 61ca92e58ad4..f2b2c6a3a49d 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -34,6 +34,7 @@ struct perf_session {
34 u64 sample_type; 34 u64 sample_type;
35 int fd; 35 int fd;
36 bool fd_pipe; 36 bool fd_pipe;
37 bool repipe;
37 int cwdlen; 38 int cwdlen;
38 char *cwd; 39 char *cwd;
39 struct ordered_samples ordered_samples; 40 struct ordered_samples ordered_samples;
@@ -59,7 +60,7 @@ struct perf_event_ops {
59 bool ordered_samples; 60 bool ordered_samples;
60}; 61};
61 62
62struct perf_session *perf_session__new(const char *filename, int mode, bool force); 63struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe);
63void perf_session__delete(struct perf_session *self); 64void perf_session__delete(struct perf_session *self);
64 65
65void perf_event_header__bswap(struct perf_event_header *self); 66void perf_event_header__bswap(struct perf_event_header *self);
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 44889c9b5630..43f19c1fed3a 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -51,6 +51,7 @@ static int long_size;
51static unsigned long page_size; 51static unsigned long page_size;
52 52
53static ssize_t calc_data_size; 53static ssize_t calc_data_size;
54static bool repipe;
54 55
55static int do_read(int fd, void *buf, int size) 56static int do_read(int fd, void *buf, int size)
56{ 57{
@@ -62,6 +63,13 @@ static int do_read(int fd, void *buf, int size)
62 if (ret <= 0) 63 if (ret <= 0)
63 return -1; 64 return -1;
64 65
66 if (repipe) {
67 int retw = write(STDOUT_FILENO, buf, ret);
68
69 if (retw <= 0 || retw != ret)
70 die("repiping input file");
71 }
72
65 size -= ret; 73 size -= ret;
66 buf += ret; 74 buf += ret;
67 } 75 }
@@ -116,6 +124,13 @@ static char *read_string(void)
116 if (!r) 124 if (!r)
117 die("no data"); 125 die("no data");
118 126
127 if (repipe) {
128 int retw = write(STDOUT_FILENO, &c, 1);
129
130 if (retw <= 0 || retw != r)
131 die("repiping input file string");
132 }
133
119 buf[size++] = c; 134 buf[size++] = c;
120 135
121 if (!c) 136 if (!c)
@@ -454,7 +469,7 @@ struct record *trace_read_data(int cpu)
454 return data; 469 return data;
455} 470}
456 471
457ssize_t trace_report(int fd) 472ssize_t trace_report(int fd, bool __repipe)
458{ 473{
459 char buf[BUFSIZ]; 474 char buf[BUFSIZ];
460 char test[] = { 23, 8, 68 }; 475 char test[] = { 23, 8, 68 };
@@ -465,6 +480,7 @@ ssize_t trace_report(int fd)
465 ssize_t size; 480 ssize_t size;
466 481
467 calc_data_size = 1; 482 calc_data_size = 1;
483 repipe = __repipe;
468 484
469 input_fd = fd; 485 input_fd = fd;
470 486
@@ -499,6 +515,7 @@ ssize_t trace_report(int fd)
499 515
500 size = calc_data_size - 1; 516 size = calc_data_size - 1;
501 calc_data_size = 0; 517 calc_data_size = 0;
518 repipe = false;
502 519
503 if (show_funcs) { 520 if (show_funcs) {
504 print_funcs(); 521 print_funcs();
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 1f45d468fd9a..ebfee80e4a07 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -163,7 +163,7 @@ struct record *trace_read_data(int cpu);
163 163
164void parse_set_info(int nr_cpus, int long_sz); 164void parse_set_info(int nr_cpus, int long_sz);
165 165
166ssize_t trace_report(int fd); 166ssize_t trace_report(int fd, bool repipe);
167 167
168void *malloc_or_die(unsigned int size); 168void *malloc_or_die(unsigned int size);
169 169