blob: 8f4cad7e9fe7ffb20900361519815a2d73151090 [file] [log] [blame]
Tom Zanussi454c4072010-05-01 01:41:20 -05001/*
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"
Andrew Vagin26a031e2012-08-07 16:56:04 +040011#include "util/color.h"
12#include "util/evlist.h"
13#include "util/evsel.h"
Tom Zanussi454c4072010-05-01 01:41:20 -050014#include "util/session.h"
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -020015#include "util/tool.h"
Tom Zanussi454c4072010-05-01 01:41:20 -050016#include "util/debug.h"
Andrew Vagin54a3cf52012-08-07 16:56:05 +040017#include "util/build-id.h"
Jiri Olsaf5fc1412013-10-15 16:27:32 +020018#include "util/data.h"
Tom Zanussi454c4072010-05-01 01:41:20 -050019
20#include "util/parse-options.h"
21
Andrew Vagin26a031e2012-08-07 16:56:04 +040022#include <linux/list.h>
23
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -030024struct perf_inject {
Jiri Olsa34069122013-10-29 19:04:57 +010025 struct perf_tool tool;
Namhyung Kim1cb8bdc2014-08-12 15:40:37 +090026 struct perf_session *session;
Jiri Olsa34069122013-10-29 19:04:57 +010027 bool build_ids;
28 bool sched_stat;
29 const char *input_name;
30 struct perf_data_file output;
31 u64 bytes_written;
32 struct list_head samples;
Andrew Vagin26a031e2012-08-07 16:56:04 +040033};
34
35struct event_entry {
36 struct list_head node;
37 u32 tid;
38 union perf_event event[0];
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -030039};
Tom Zanussi454c4072010-05-01 01:41:20 -050040
Adrian Huntercd17a9b2015-04-21 12:21:54 +030041static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
Tom Zanussi454c4072010-05-01 01:41:20 -050042{
Jiri Olsa34069122013-10-29 19:04:57 +010043 ssize_t size;
Tom Zanussi454c4072010-05-01 01:41:20 -050044
Adrian Huntercd17a9b2015-04-21 12:21:54 +030045 size = perf_data_file__write(&inject->output, buf, sz);
Jiri Olsa34069122013-10-29 19:04:57 +010046 if (size < 0)
47 return -errno;
Tom Zanussi454c4072010-05-01 01:41:20 -050048
Jiri Olsa34069122013-10-29 19:04:57 +010049 inject->bytes_written += size;
Tom Zanussi454c4072010-05-01 01:41:20 -050050 return 0;
51}
52
Adrian Huntercd17a9b2015-04-21 12:21:54 +030053static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
54{
55 char buf[4096];
56 ssize_t ssz;
57 int ret;
58
59 while (size > 0) {
60 ssz = read(fd, buf, min(size, (off_t)sizeof(buf)));
61 if (ssz < 0)
62 return -errno;
63 ret = output_bytes(inject, buf, ssz);
64 if (ret)
65 return ret;
66 size -= ssz;
67 }
68
69 return 0;
70}
71
72static int perf_event__repipe_synth(struct perf_tool *tool,
73 union perf_event *event)
74{
75 struct perf_inject *inject = container_of(tool, struct perf_inject,
76 tool);
77
78 return output_bytes(inject, event, event->header.size);
79}
80
Arnaldo Carvalho de Melod704ebd2015-03-03 12:37:54 -030081static int perf_event__repipe_oe_synth(struct perf_tool *tool,
82 union perf_event *event,
83 struct ordered_events *oe __maybe_unused)
84{
85 return perf_event__repipe_synth(tool, event);
86}
87
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -020088static int perf_event__repipe_op2_synth(struct perf_tool *tool,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -020089 union perf_event *event,
Irina Tirdea1d037ca2012-09-11 01:15:03 +030090 struct perf_session *session
91 __maybe_unused)
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -020092{
Adrian Hunter63c2c9f2013-07-04 16:20:20 +030093 return perf_event__repipe_synth(tool, event);
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -020094}
95
Adrian Hunter47c3d102013-07-04 16:20:21 +030096static int perf_event__repipe_attr(struct perf_tool *tool,
97 union perf_event *event,
98 struct perf_evlist **pevlist)
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -020099{
Adrian Hunter89c97d92013-10-22 10:34:09 +0300100 struct perf_inject *inject = container_of(tool, struct perf_inject,
101 tool);
Stephane Eranian1a1ed1b2012-05-15 13:28:11 +0200102 int ret;
Adrian Hunter47c3d102013-07-04 16:20:21 +0300103
104 ret = perf_event__process_attr(tool, event, pevlist);
Stephane Eranian1a1ed1b2012-05-15 13:28:11 +0200105 if (ret)
106 return ret;
107
Jiri Olsaa261e4a2014-06-05 18:51:44 +0200108 if (!inject->output.is_pipe)
Adrian Hunter89c97d92013-10-22 10:34:09 +0300109 return 0;
110
Adrian Hunter47c3d102013-07-04 16:20:21 +0300111 return perf_event__repipe_synth(tool, event);
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -0200112}
113
Adrian Huntercd17a9b2015-04-21 12:21:54 +0300114static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
115 union perf_event *event,
116 struct perf_session *session
117 __maybe_unused)
118{
119 struct perf_inject *inject = container_of(tool, struct perf_inject,
120 tool);
121 int ret;
122
123 if (perf_data_file__is_pipe(session->file) || !session->one_mmap) {
124 ret = output_bytes(inject, event, event->header.size);
125 if (ret < 0)
126 return ret;
127 ret = copy_bytes(inject, perf_data_file__fd(session->file),
128 event->auxtrace.size);
129 } else {
130 ret = output_bytes(inject, event,
131 event->header.size + event->auxtrace.size);
132 }
133 if (ret < 0)
134 return ret;
135
136 return event->auxtrace.size;
137}
138
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200139static int perf_event__repipe(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200140 union perf_event *event,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300141 struct perf_sample *sample __maybe_unused,
Adrian Hunter63c2c9f2013-07-04 16:20:20 +0300142 struct machine *machine __maybe_unused)
Arnaldo Carvalho de Melo640c03c2010-12-02 14:10:21 -0200143{
Adrian Hunter63c2c9f2013-07-04 16:20:20 +0300144 return perf_event__repipe_synth(tool, event);
Arnaldo Carvalho de Melo640c03c2010-12-02 14:10:21 -0200145}
146
Andrew Vagin26a031e2012-08-07 16:56:04 +0400147typedef int (*inject_handler)(struct perf_tool *tool,
148 union perf_event *event,
149 struct perf_sample *sample,
150 struct perf_evsel *evsel,
151 struct machine *machine);
152
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200153static int perf_event__repipe_sample(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200154 union perf_event *event,
Andrew Vagin26a031e2012-08-07 16:56:04 +0400155 struct perf_sample *sample,
156 struct perf_evsel *evsel,
157 struct machine *machine)
Arnaldo Carvalho de Melo9e69c212011-03-15 15:44:01 -0300158{
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -0300159 if (evsel->handler) {
160 inject_handler f = evsel->handler;
Andrew Vagin26a031e2012-08-07 16:56:04 +0400161 return f(tool, event, sample, evsel, machine);
162 }
163
Andrew Vagin54a3cf52012-08-07 16:56:05 +0400164 build_id__mark_dso_hit(tool, event, sample, evsel, machine);
165
Adrian Hunter63c2c9f2013-07-04 16:20:20 +0300166 return perf_event__repipe_synth(tool, event);
Arnaldo Carvalho de Melo9e69c212011-03-15 15:44:01 -0300167}
168
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200169static int perf_event__repipe_mmap(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200170 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200171 struct perf_sample *sample,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200172 struct machine *machine)
Tom Zanussi454c4072010-05-01 01:41:20 -0500173{
174 int err;
175
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200176 err = perf_event__process_mmap(tool, event, sample, machine);
177 perf_event__repipe(tool, event, sample, machine);
Tom Zanussi454c4072010-05-01 01:41:20 -0500178
179 return err;
180}
181
Stephane Eranian5c5e8542013-08-21 12:10:25 +0200182static int perf_event__repipe_mmap2(struct perf_tool *tool,
183 union perf_event *event,
184 struct perf_sample *sample,
185 struct machine *machine)
186{
187 int err;
188
189 err = perf_event__process_mmap2(tool, event, sample, machine);
190 perf_event__repipe(tool, event, sample, machine);
191
192 return err;
193}
194
Arnaldo Carvalho de Melof62d3f02012-10-06 15:44:59 -0300195static int perf_event__repipe_fork(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200196 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200197 struct perf_sample *sample,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200198 struct machine *machine)
Tom Zanussi454c4072010-05-01 01:41:20 -0500199{
200 int err;
201
Arnaldo Carvalho de Melof62d3f02012-10-06 15:44:59 -0300202 err = perf_event__process_fork(tool, event, sample, machine);
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200203 perf_event__repipe(tool, event, sample, machine);
Tom Zanussi454c4072010-05-01 01:41:20 -0500204
205 return err;
206}
207
Adrian Hunter47c3d102013-07-04 16:20:21 +0300208static int perf_event__repipe_tracing_data(struct perf_tool *tool,
209 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200210 struct perf_session *session)
Tom Zanussi454c4072010-05-01 01:41:20 -0500211{
212 int err;
213
Adrian Hunter47c3d102013-07-04 16:20:21 +0300214 perf_event__repipe_synth(tool, event);
215 err = perf_event__process_tracing_data(tool, event, session);
Tom Zanussi454c4072010-05-01 01:41:20 -0500216
217 return err;
218}
219
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300220static int dso__read_build_id(struct dso *dso)
Tom Zanussi454c4072010-05-01 01:41:20 -0500221{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300222 if (dso->has_build_id)
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300223 return 0;
Tom Zanussi454c4072010-05-01 01:41:20 -0500224
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300225 if (filename__read_build_id(dso->long_name, dso->build_id,
226 sizeof(dso->build_id)) > 0) {
227 dso->has_build_id = true;
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300228 return 0;
Tom Zanussi454c4072010-05-01 01:41:20 -0500229 }
230
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300231 return -1;
232}
Tom Zanussi454c4072010-05-01 01:41:20 -0500233
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300234static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200235 struct machine *machine)
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300236{
237 u16 misc = PERF_RECORD_MISC_USER;
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300238 int err;
Tom Zanussi454c4072010-05-01 01:41:20 -0500239
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300240 if (dso__read_build_id(dso) < 0) {
241 pr_debug("no build_id found for %s\n", dso->long_name);
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300242 return -1;
243 }
Tom Zanussi454c4072010-05-01 01:41:20 -0500244
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300245 if (dso->kernel)
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300246 misc = PERF_RECORD_MISC_KERNEL;
247
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300248 err = perf_event__synthesize_build_id(tool, dso, misc, perf_event__repipe,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200249 machine);
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300250 if (err) {
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300251 pr_err("Can't synthesize build_id event for %s\n", dso->long_name);
Tom Zanussi454c4072010-05-01 01:41:20 -0500252 return -1;
253 }
254
255 return 0;
256}
257
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200258static int perf_event__inject_buildid(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200259 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200260 struct perf_sample *sample,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300261 struct perf_evsel *evsel __maybe_unused,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200262 struct machine *machine)
Tom Zanussi454c4072010-05-01 01:41:20 -0500263{
264 struct addr_location al;
265 struct thread *thread;
266 u8 cpumode;
Tom Zanussi454c4072010-05-01 01:41:20 -0500267
268 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
269
Namhyung Kim13ce34d2014-05-12 09:56:42 +0900270 thread = machine__findnew_thread(machine, sample->pid, sample->tid);
Tom Zanussi454c4072010-05-01 01:41:20 -0500271 if (thread == NULL) {
272 pr_err("problem processing %d event, skipping it.\n",
273 event->header.type);
Tom Zanussi454c4072010-05-01 01:41:20 -0500274 goto repipe;
275 }
276
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -0300277 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
Tom Zanussi454c4072010-05-01 01:41:20 -0500278
279 if (al.map != NULL) {
280 if (!al.map->dso->hit) {
281 al.map->dso->hit = 1;
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300282 if (map__load(al.map, NULL) >= 0) {
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200283 dso__inject_build_id(al.map->dso, tool, machine);
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300284 /*
285 * If this fails, too bad, let the other side
286 * account this as unresolved.
287 */
Namhyung Kim393be2e2012-08-06 13:41:21 +0900288 } else {
Ingo Molnar89fe8082013-09-30 12:07:11 +0200289#ifdef HAVE_LIBELF_SUPPORT
Tom Zanussi454c4072010-05-01 01:41:20 -0500290 pr_warning("no symbols found in %s, maybe "
291 "install a debug package?\n",
292 al.map->dso->long_name);
Namhyung Kim393be2e2012-08-06 13:41:21 +0900293#endif
294 }
Tom Zanussi454c4072010-05-01 01:41:20 -0500295 }
296 }
297
298repipe:
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200299 perf_event__repipe(tool, event, sample, machine);
Arnaldo Carvalho de Melo090f7202010-05-02 19:46:36 -0300300 return 0;
Tom Zanussi454c4072010-05-01 01:41:20 -0500301}
302
Andrew Vagin26a031e2012-08-07 16:56:04 +0400303static int perf_inject__sched_process_exit(struct perf_tool *tool,
304 union perf_event *event __maybe_unused,
305 struct perf_sample *sample,
306 struct perf_evsel *evsel __maybe_unused,
307 struct machine *machine __maybe_unused)
308{
309 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
310 struct event_entry *ent;
311
312 list_for_each_entry(ent, &inject->samples, node) {
313 if (sample->tid == ent->tid) {
314 list_del_init(&ent->node);
315 free(ent);
316 break;
317 }
318 }
319
320 return 0;
321}
322
323static int perf_inject__sched_switch(struct perf_tool *tool,
324 union perf_event *event,
325 struct perf_sample *sample,
326 struct perf_evsel *evsel,
327 struct machine *machine)
328{
329 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
330 struct event_entry *ent;
331
332 perf_inject__sched_process_exit(tool, event, sample, evsel, machine);
333
334 ent = malloc(event->header.size + sizeof(struct event_entry));
335 if (ent == NULL) {
336 color_fprintf(stderr, PERF_COLOR_RED,
337 "Not enough memory to process sched switch event!");
338 return -1;
339 }
340
341 ent->tid = sample->tid;
342 memcpy(&ent->event, event, event->header.size);
343 list_add(&ent->node, &inject->samples);
344 return 0;
345}
346
347static int perf_inject__sched_stat(struct perf_tool *tool,
348 union perf_event *event __maybe_unused,
349 struct perf_sample *sample,
350 struct perf_evsel *evsel,
351 struct machine *machine)
352{
353 struct event_entry *ent;
354 union perf_event *event_sw;
355 struct perf_sample sample_sw;
356 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
357 u32 pid = perf_evsel__intval(evsel, sample, "pid");
358
359 list_for_each_entry(ent, &inject->samples, node) {
360 if (pid == ent->tid)
361 goto found;
362 }
363
364 return 0;
365found:
366 event_sw = &ent->event[0];
367 perf_evsel__parse_sample(evsel, event_sw, &sample_sw);
368
369 sample_sw.period = sample->period;
370 sample_sw.time = sample->time;
371 perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
Adrian Hunterd03f2172013-08-27 11:23:11 +0300372 evsel->attr.read_format, &sample_sw,
373 false);
Andrew Vagin54a3cf52012-08-07 16:56:05 +0400374 build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
Andrew Vagin26a031e2012-08-07 16:56:04 +0400375 return perf_event__repipe(tool, event_sw, &sample_sw, machine);
376}
377
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300378static void sig_handler(int sig __maybe_unused)
Tom Zanussi454c4072010-05-01 01:41:20 -0500379{
380 session_done = 1;
381}
382
Andrew Vagin26a031e2012-08-07 16:56:04 +0400383static int perf_evsel__check_stype(struct perf_evsel *evsel,
384 u64 sample_type, const char *sample_msg)
385{
386 struct perf_event_attr *attr = &evsel->attr;
387 const char *name = perf_evsel__name(evsel);
388
389 if (!(attr->sample_type & sample_type)) {
390 pr_err("Samples for %s event do not have %s attribute set.",
391 name, sample_msg);
392 return -EINVAL;
393 }
394
395 return 0;
396}
397
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300398static int __cmd_inject(struct perf_inject *inject)
Tom Zanussi454c4072010-05-01 01:41:20 -0500399{
Tom Zanussi454c4072010-05-01 01:41:20 -0500400 int ret = -EINVAL;
Namhyung Kim1cb8bdc2014-08-12 15:40:37 +0900401 struct perf_session *session = inject->session;
Jiri Olsa34069122013-10-29 19:04:57 +0100402 struct perf_data_file *file_out = &inject->output;
Namhyung Kim42aa2762015-01-29 17:06:48 +0900403 int fd = perf_data_file__fd(file_out);
Tom Zanussi454c4072010-05-01 01:41:20 -0500404
405 signal(SIGINT, sig_handler);
406
Andrew Vagin54a3cf52012-08-07 16:56:05 +0400407 if (inject->build_ids || inject->sched_stat) {
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300408 inject->tool.mmap = perf_event__repipe_mmap;
Stephane Eranian5c5e8542013-08-21 12:10:25 +0200409 inject->tool.mmap2 = perf_event__repipe_mmap2;
Arnaldo Carvalho de Melof62d3f02012-10-06 15:44:59 -0300410 inject->tool.fork = perf_event__repipe_fork;
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300411 inject->tool.tracing_data = perf_event__repipe_tracing_data;
Tom Zanussi454c4072010-05-01 01:41:20 -0500412 }
413
Andrew Vagin54a3cf52012-08-07 16:56:05 +0400414 if (inject->build_ids) {
415 inject->tool.sample = perf_event__inject_buildid;
416 } else if (inject->sched_stat) {
Andrew Vagin26a031e2012-08-07 16:56:04 +0400417 struct perf_evsel *evsel;
418
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -0300419 evlist__for_each(session->evlist, evsel) {
Andrew Vagin26a031e2012-08-07 16:56:04 +0400420 const char *name = perf_evsel__name(evsel);
421
422 if (!strcmp(name, "sched:sched_switch")) {
423 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
424 return -EINVAL;
425
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -0300426 evsel->handler = perf_inject__sched_switch;
Andrew Vagin26a031e2012-08-07 16:56:04 +0400427 } else if (!strcmp(name, "sched:sched_process_exit"))
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -0300428 evsel->handler = perf_inject__sched_process_exit;
Andrew Vagin26a031e2012-08-07 16:56:04 +0400429 else if (!strncmp(name, "sched:sched_stat_", 17))
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -0300430 evsel->handler = perf_inject__sched_stat;
Andrew Vagin26a031e2012-08-07 16:56:04 +0400431 }
432 }
433
Jiri Olsa34069122013-10-29 19:04:57 +0100434 if (!file_out->is_pipe)
Namhyung Kim42aa2762015-01-29 17:06:48 +0900435 lseek(fd, session->header.data_offset, SEEK_SET);
Andrew Vagine558a5b2012-08-07 16:56:02 +0400436
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -0300437 ret = perf_session__process_events(session);
Tom Zanussi454c4072010-05-01 01:41:20 -0500438
Jiri Olsa34069122013-10-29 19:04:57 +0100439 if (!file_out->is_pipe) {
Adrian Huntere38b43c2014-07-14 13:02:34 +0300440 if (inject->build_ids)
441 perf_header__set_feat(&session->header,
442 HEADER_BUILD_ID);
Andrew Vagine558a5b2012-08-07 16:56:02 +0400443 session->header.data_size = inject->bytes_written;
Namhyung Kim42aa2762015-01-29 17:06:48 +0900444 perf_session__write_header(session, session->evlist, fd, true);
Andrew Vagine558a5b2012-08-07 16:56:02 +0400445 }
446
Tom Zanussi454c4072010-05-01 01:41:20 -0500447 return ret;
448}
449
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300450int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
Tom Zanussi454c4072010-05-01 01:41:20 -0500451{
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300452 struct perf_inject inject = {
453 .tool = {
454 .sample = perf_event__repipe_sample,
455 .mmap = perf_event__repipe,
Stephane Eranian5c5e8542013-08-21 12:10:25 +0200456 .mmap2 = perf_event__repipe,
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300457 .comm = perf_event__repipe,
458 .fork = perf_event__repipe,
459 .exit = perf_event__repipe,
460 .lost = perf_event__repipe,
461 .read = perf_event__repipe_sample,
462 .throttle = perf_event__repipe,
463 .unthrottle = perf_event__repipe,
464 .attr = perf_event__repipe_attr,
Adrian Hunter47c3d102013-07-04 16:20:21 +0300465 .tracing_data = perf_event__repipe_op2_synth,
Adrian Huntercd17a9b2015-04-21 12:21:54 +0300466 .auxtrace_info = perf_event__repipe_op2_synth,
467 .auxtrace = perf_event__repipe_auxtrace,
468 .auxtrace_error = perf_event__repipe_op2_synth,
Arnaldo Carvalho de Melod704ebd2015-03-03 12:37:54 -0300469 .finished_round = perf_event__repipe_oe_synth,
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300470 .build_id = perf_event__repipe_op2_synth,
Adrian Hunter3c659ee2014-10-27 15:49:22 +0200471 .id_index = perf_event__repipe_op2_synth,
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300472 },
Andrew Vagine558a5b2012-08-07 16:56:02 +0400473 .input_name = "-",
Andrew Vagin26a031e2012-08-07 16:56:04 +0400474 .samples = LIST_HEAD_INIT(inject.samples),
Jiri Olsa34069122013-10-29 19:04:57 +0100475 .output = {
476 .path = "-",
477 .mode = PERF_DATA_MODE_WRITE,
478 },
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300479 };
Namhyung Kim1cb8bdc2014-08-12 15:40:37 +0900480 struct perf_data_file file = {
481 .mode = PERF_DATA_MODE_READ,
482 };
483 int ret;
484
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300485 const struct option options[] = {
486 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
487 "Inject build-ids into the output stream"),
Andrew Vagine558a5b2012-08-07 16:56:02 +0400488 OPT_STRING('i', "input", &inject.input_name, "file",
489 "input file name"),
Jiri Olsa34069122013-10-29 19:04:57 +0100490 OPT_STRING('o', "output", &inject.output.path, "file",
Andrew Vagine558a5b2012-08-07 16:56:02 +0400491 "output file name"),
Andrew Vagin26a031e2012-08-07 16:56:04 +0400492 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
493 "Merge sched-stat and sched-switch for getting events "
494 "where and how long tasks slept"),
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300495 OPT_INCR('v', "verbose", &verbose,
496 "be more verbose (show build ids, etc)"),
Adrian Huntera7a2b8b2014-07-22 16:17:38 +0300497 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
498 "kallsyms pathname"),
Yunlong Songccaa4742015-04-02 21:47:11 +0800499 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300500 OPT_END()
501 };
Arnaldo Carvalho de Melo002439e2012-10-01 15:20:58 -0300502 const char * const inject_usage[] = {
503 "perf inject [<options>]",
504 NULL
505 };
Arnaldo Carvalho de Melo5ded57a2012-09-30 19:54:10 -0300506
Arnaldo Carvalho de Melo002439e2012-10-01 15:20:58 -0300507 argc = parse_options(argc, argv, options, inject_usage, 0);
Tom Zanussi454c4072010-05-01 01:41:20 -0500508
509 /*
510 * Any (unrecognized) arguments left?
511 */
512 if (argc)
Arnaldo Carvalho de Melo002439e2012-10-01 15:20:58 -0300513 usage_with_options(inject_usage, options);
Tom Zanussi454c4072010-05-01 01:41:20 -0500514
Jiri Olsa34069122013-10-29 19:04:57 +0100515 if (perf_data_file__open(&inject.output)) {
516 perror("failed to create output file");
517 return -1;
Andrew Vagine558a5b2012-08-07 16:56:02 +0400518 }
519
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -0300520 inject.tool.ordered_events = inject.sched_stat;
521
Namhyung Kim1cb8bdc2014-08-12 15:40:37 +0900522 file.path = inject.input_name;
523 inject.session = perf_session__new(&file, true, &inject.tool);
524 if (inject.session == NULL)
Taeung Song52e02832014-09-24 10:33:37 +0900525 return -1;
Namhyung Kim1cb8bdc2014-08-12 15:40:37 +0900526
Namhyung Kim0a7e6d12014-08-12 15:40:45 +0900527 if (symbol__init(&inject.session->header.env) < 0)
Tom Zanussi454c4072010-05-01 01:41:20 -0500528 return -1;
529
Namhyung Kim1cb8bdc2014-08-12 15:40:37 +0900530 ret = __cmd_inject(&inject);
531
532 perf_session__delete(inject.session);
533
534 return ret;
Tom Zanussi454c4072010-05-01 01:41:20 -0500535}