]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/builtin-inject.c
perf tools: Include errno.h where needed
[karo-tx-linux.git] / tools / perf / builtin-inject.c
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/color.h"
12 #include "util/evlist.h"
13 #include "util/evsel.h"
14 #include "util/session.h"
15 #include "util/tool.h"
16 #include "util/debug.h"
17 #include "util/build-id.h"
18 #include "util/data.h"
19 #include "util/auxtrace.h"
20 #include "util/jit.h"
21
22 #include <subcmd/parse-options.h>
23
24 #include <linux/list.h>
25 #include <errno.h>
26
27 struct perf_inject {
28         struct perf_tool        tool;
29         struct perf_session     *session;
30         bool                    build_ids;
31         bool                    sched_stat;
32         bool                    have_auxtrace;
33         bool                    strip;
34         bool                    jit_mode;
35         const char              *input_name;
36         struct perf_data_file   output;
37         u64                     bytes_written;
38         u64                     aux_id;
39         struct list_head        samples;
40         struct itrace_synth_opts itrace_synth_opts;
41 };
42
43 struct event_entry {
44         struct list_head node;
45         u32              tid;
46         union perf_event event[0];
47 };
48
49 static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
50 {
51         ssize_t size;
52
53         size = perf_data_file__write(&inject->output, buf, sz);
54         if (size < 0)
55                 return -errno;
56
57         inject->bytes_written += size;
58         return 0;
59 }
60
61 static int perf_event__repipe_synth(struct perf_tool *tool,
62                                     union perf_event *event)
63 {
64         struct perf_inject *inject = container_of(tool, struct perf_inject,
65                                                   tool);
66
67         return output_bytes(inject, event, event->header.size);
68 }
69
70 static int perf_event__repipe_oe_synth(struct perf_tool *tool,
71                                        union perf_event *event,
72                                        struct ordered_events *oe __maybe_unused)
73 {
74         return perf_event__repipe_synth(tool, event);
75 }
76
77 #ifdef HAVE_JITDUMP
78 static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused,
79                                union perf_event *event __maybe_unused,
80                                struct ordered_events *oe __maybe_unused)
81 {
82         return 0;
83 }
84 #endif
85
86 static int perf_event__repipe_op2_synth(struct perf_tool *tool,
87                                         union perf_event *event,
88                                         struct perf_session *session
89                                         __maybe_unused)
90 {
91         return perf_event__repipe_synth(tool, event);
92 }
93
94 static int perf_event__repipe_attr(struct perf_tool *tool,
95                                    union perf_event *event,
96                                    struct perf_evlist **pevlist)
97 {
98         struct perf_inject *inject = container_of(tool, struct perf_inject,
99                                                   tool);
100         int ret;
101
102         ret = perf_event__process_attr(tool, event, pevlist);
103         if (ret)
104                 return ret;
105
106         if (!inject->output.is_pipe)
107                 return 0;
108
109         return perf_event__repipe_synth(tool, event);
110 }
111
112 #ifdef HAVE_AUXTRACE_SUPPORT
113
114 static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
115 {
116         char buf[4096];
117         ssize_t ssz;
118         int ret;
119
120         while (size > 0) {
121                 ssz = read(fd, buf, min(size, (off_t)sizeof(buf)));
122                 if (ssz < 0)
123                         return -errno;
124                 ret = output_bytes(inject, buf, ssz);
125                 if (ret)
126                         return ret;
127                 size -= ssz;
128         }
129
130         return 0;
131 }
132
133 static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
134                                        union perf_event *event,
135                                        struct perf_session *session)
136 {
137         struct perf_inject *inject = container_of(tool, struct perf_inject,
138                                                   tool);
139         int ret;
140
141         inject->have_auxtrace = true;
142
143         if (!inject->output.is_pipe) {
144                 off_t offset;
145
146                 offset = lseek(inject->output.fd, 0, SEEK_CUR);
147                 if (offset == -1)
148                         return -errno;
149                 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index,
150                                                      event, offset);
151                 if (ret < 0)
152                         return ret;
153         }
154
155         if (perf_data_file__is_pipe(session->file) || !session->one_mmap) {
156                 ret = output_bytes(inject, event, event->header.size);
157                 if (ret < 0)
158                         return ret;
159                 ret = copy_bytes(inject, perf_data_file__fd(session->file),
160                                  event->auxtrace.size);
161         } else {
162                 ret = output_bytes(inject, event,
163                                    event->header.size + event->auxtrace.size);
164         }
165         if (ret < 0)
166                 return ret;
167
168         return event->auxtrace.size;
169 }
170
171 #else
172
173 static s64
174 perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused,
175                             union perf_event *event __maybe_unused,
176                             struct perf_session *session __maybe_unused)
177 {
178         pr_err("AUX area tracing not supported\n");
179         return -EINVAL;
180 }
181
182 #endif
183
184 static int perf_event__repipe(struct perf_tool *tool,
185                               union perf_event *event,
186                               struct perf_sample *sample __maybe_unused,
187                               struct machine *machine __maybe_unused)
188 {
189         return perf_event__repipe_synth(tool, event);
190 }
191
192 static int perf_event__drop(struct perf_tool *tool __maybe_unused,
193                             union perf_event *event __maybe_unused,
194                             struct perf_sample *sample __maybe_unused,
195                             struct machine *machine __maybe_unused)
196 {
197         return 0;
198 }
199
200 static int perf_event__drop_aux(struct perf_tool *tool,
201                                 union perf_event *event __maybe_unused,
202                                 struct perf_sample *sample,
203                                 struct machine *machine __maybe_unused)
204 {
205         struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
206
207         if (!inject->aux_id)
208                 inject->aux_id = sample->id;
209
210         return 0;
211 }
212
213 typedef int (*inject_handler)(struct perf_tool *tool,
214                               union perf_event *event,
215                               struct perf_sample *sample,
216                               struct perf_evsel *evsel,
217                               struct machine *machine);
218
219 static int perf_event__repipe_sample(struct perf_tool *tool,
220                                      union perf_event *event,
221                                      struct perf_sample *sample,
222                                      struct perf_evsel *evsel,
223                                      struct machine *machine)
224 {
225         if (evsel->handler) {
226                 inject_handler f = evsel->handler;
227                 return f(tool, event, sample, evsel, machine);
228         }
229
230         build_id__mark_dso_hit(tool, event, sample, evsel, machine);
231
232         return perf_event__repipe_synth(tool, event);
233 }
234
235 static int perf_event__repipe_mmap(struct perf_tool *tool,
236                                    union perf_event *event,
237                                    struct perf_sample *sample,
238                                    struct machine *machine)
239 {
240         int err;
241
242         err = perf_event__process_mmap(tool, event, sample, machine);
243         perf_event__repipe(tool, event, sample, machine);
244
245         return err;
246 }
247
248 #ifdef HAVE_JITDUMP
249 static int perf_event__jit_repipe_mmap(struct perf_tool *tool,
250                                        union perf_event *event,
251                                        struct perf_sample *sample,
252                                        struct machine *machine)
253 {
254         struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
255         u64 n = 0;
256         int ret;
257
258         /*
259          * if jit marker, then inject jit mmaps and generate ELF images
260          */
261         ret = jit_process(inject->session, &inject->output, machine,
262                           event->mmap.filename, sample->pid, &n);
263         if (ret < 0)
264                 return ret;
265         if (ret) {
266                 inject->bytes_written += n;
267                 return 0;
268         }
269         return perf_event__repipe_mmap(tool, event, sample, machine);
270 }
271 #endif
272
273 static int perf_event__repipe_mmap2(struct perf_tool *tool,
274                                    union perf_event *event,
275                                    struct perf_sample *sample,
276                                    struct machine *machine)
277 {
278         int err;
279
280         err = perf_event__process_mmap2(tool, event, sample, machine);
281         perf_event__repipe(tool, event, sample, machine);
282
283         return err;
284 }
285
286 #ifdef HAVE_JITDUMP
287 static int perf_event__jit_repipe_mmap2(struct perf_tool *tool,
288                                         union perf_event *event,
289                                         struct perf_sample *sample,
290                                         struct machine *machine)
291 {
292         struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
293         u64 n = 0;
294         int ret;
295
296         /*
297          * if jit marker, then inject jit mmaps and generate ELF images
298          */
299         ret = jit_process(inject->session, &inject->output, machine,
300                           event->mmap2.filename, sample->pid, &n);
301         if (ret < 0)
302                 return ret;
303         if (ret) {
304                 inject->bytes_written += n;
305                 return 0;
306         }
307         return perf_event__repipe_mmap2(tool, event, sample, machine);
308 }
309 #endif
310
311 static int perf_event__repipe_fork(struct perf_tool *tool,
312                                    union perf_event *event,
313                                    struct perf_sample *sample,
314                                    struct machine *machine)
315 {
316         int err;
317
318         err = perf_event__process_fork(tool, event, sample, machine);
319         perf_event__repipe(tool, event, sample, machine);
320
321         return err;
322 }
323
324 static int perf_event__repipe_comm(struct perf_tool *tool,
325                                    union perf_event *event,
326                                    struct perf_sample *sample,
327                                    struct machine *machine)
328 {
329         int err;
330
331         err = perf_event__process_comm(tool, event, sample, machine);
332         perf_event__repipe(tool, event, sample, machine);
333
334         return err;
335 }
336
337 static int perf_event__repipe_namespaces(struct perf_tool *tool,
338                                          union perf_event *event,
339                                          struct perf_sample *sample,
340                                          struct machine *machine)
341 {
342         int err = perf_event__process_namespaces(tool, event, sample, machine);
343
344         perf_event__repipe(tool, event, sample, machine);
345
346         return err;
347 }
348
349 static int perf_event__repipe_exit(struct perf_tool *tool,
350                                    union perf_event *event,
351                                    struct perf_sample *sample,
352                                    struct machine *machine)
353 {
354         int err;
355
356         err = perf_event__process_exit(tool, event, sample, machine);
357         perf_event__repipe(tool, event, sample, machine);
358
359         return err;
360 }
361
362 static int perf_event__repipe_tracing_data(struct perf_tool *tool,
363                                            union perf_event *event,
364                                            struct perf_session *session)
365 {
366         int err;
367
368         perf_event__repipe_synth(tool, event);
369         err = perf_event__process_tracing_data(tool, event, session);
370
371         return err;
372 }
373
374 static int perf_event__repipe_id_index(struct perf_tool *tool,
375                                        union perf_event *event,
376                                        struct perf_session *session)
377 {
378         int err;
379
380         perf_event__repipe_synth(tool, event);
381         err = perf_event__process_id_index(tool, event, session);
382
383         return err;
384 }
385
386 static int dso__read_build_id(struct dso *dso)
387 {
388         if (dso->has_build_id)
389                 return 0;
390
391         if (filename__read_build_id(dso->long_name, dso->build_id,
392                                     sizeof(dso->build_id)) > 0) {
393                 dso->has_build_id = true;
394                 return 0;
395         }
396
397         return -1;
398 }
399
400 static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
401                                 struct machine *machine)
402 {
403         u16 misc = PERF_RECORD_MISC_USER;
404         int err;
405
406         if (dso__read_build_id(dso) < 0) {
407                 pr_debug("no build_id found for %s\n", dso->long_name);
408                 return -1;
409         }
410
411         if (dso->kernel)
412                 misc = PERF_RECORD_MISC_KERNEL;
413
414         err = perf_event__synthesize_build_id(tool, dso, misc, perf_event__repipe,
415                                               machine);
416         if (err) {
417                 pr_err("Can't synthesize build_id event for %s\n", dso->long_name);
418                 return -1;
419         }
420
421         return 0;
422 }
423
424 static int perf_event__inject_buildid(struct perf_tool *tool,
425                                       union perf_event *event,
426                                       struct perf_sample *sample,
427                                       struct perf_evsel *evsel __maybe_unused,
428                                       struct machine *machine)
429 {
430         struct addr_location al;
431         struct thread *thread;
432
433         thread = machine__findnew_thread(machine, sample->pid, sample->tid);
434         if (thread == NULL) {
435                 pr_err("problem processing %d event, skipping it.\n",
436                        event->header.type);
437                 goto repipe;
438         }
439
440         thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, &al);
441
442         if (al.map != NULL) {
443                 if (!al.map->dso->hit) {
444                         al.map->dso->hit = 1;
445                         if (map__load(al.map) >= 0) {
446                                 dso__inject_build_id(al.map->dso, tool, machine);
447                                 /*
448                                  * If this fails, too bad, let the other side
449                                  * account this as unresolved.
450                                  */
451                         } else {
452 #ifdef HAVE_LIBELF_SUPPORT
453                                 pr_warning("no symbols found in %s, maybe "
454                                            "install a debug package?\n",
455                                            al.map->dso->long_name);
456 #endif
457                         }
458                 }
459         }
460
461         thread__put(thread);
462 repipe:
463         perf_event__repipe(tool, event, sample, machine);
464         return 0;
465 }
466
467 static int perf_inject__sched_process_exit(struct perf_tool *tool,
468                                            union perf_event *event __maybe_unused,
469                                            struct perf_sample *sample,
470                                            struct perf_evsel *evsel __maybe_unused,
471                                            struct machine *machine __maybe_unused)
472 {
473         struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
474         struct event_entry *ent;
475
476         list_for_each_entry(ent, &inject->samples, node) {
477                 if (sample->tid == ent->tid) {
478                         list_del_init(&ent->node);
479                         free(ent);
480                         break;
481                 }
482         }
483
484         return 0;
485 }
486
487 static int perf_inject__sched_switch(struct perf_tool *tool,
488                                      union perf_event *event,
489                                      struct perf_sample *sample,
490                                      struct perf_evsel *evsel,
491                                      struct machine *machine)
492 {
493         struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
494         struct event_entry *ent;
495
496         perf_inject__sched_process_exit(tool, event, sample, evsel, machine);
497
498         ent = malloc(event->header.size + sizeof(struct event_entry));
499         if (ent == NULL) {
500                 color_fprintf(stderr, PERF_COLOR_RED,
501                              "Not enough memory to process sched switch event!");
502                 return -1;
503         }
504
505         ent->tid = sample->tid;
506         memcpy(&ent->event, event, event->header.size);
507         list_add(&ent->node, &inject->samples);
508         return 0;
509 }
510
511 static int perf_inject__sched_stat(struct perf_tool *tool,
512                                    union perf_event *event __maybe_unused,
513                                    struct perf_sample *sample,
514                                    struct perf_evsel *evsel,
515                                    struct machine *machine)
516 {
517         struct event_entry *ent;
518         union perf_event *event_sw;
519         struct perf_sample sample_sw;
520         struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
521         u32 pid = perf_evsel__intval(evsel, sample, "pid");
522
523         list_for_each_entry(ent, &inject->samples, node) {
524                 if (pid == ent->tid)
525                         goto found;
526         }
527
528         return 0;
529 found:
530         event_sw = &ent->event[0];
531         perf_evsel__parse_sample(evsel, event_sw, &sample_sw);
532
533         sample_sw.period = sample->period;
534         sample_sw.time   = sample->time;
535         perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
536                                       evsel->attr.read_format, &sample_sw,
537                                       false);
538         build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
539         return perf_event__repipe(tool, event_sw, &sample_sw, machine);
540 }
541
542 static void sig_handler(int sig __maybe_unused)
543 {
544         session_done = 1;
545 }
546
547 static int perf_evsel__check_stype(struct perf_evsel *evsel,
548                                    u64 sample_type, const char *sample_msg)
549 {
550         struct perf_event_attr *attr = &evsel->attr;
551         const char *name = perf_evsel__name(evsel);
552
553         if (!(attr->sample_type & sample_type)) {
554                 pr_err("Samples for %s event do not have %s attribute set.",
555                         name, sample_msg);
556                 return -EINVAL;
557         }
558
559         return 0;
560 }
561
562 static int drop_sample(struct perf_tool *tool __maybe_unused,
563                        union perf_event *event __maybe_unused,
564                        struct perf_sample *sample __maybe_unused,
565                        struct perf_evsel *evsel __maybe_unused,
566                        struct machine *machine __maybe_unused)
567 {
568         return 0;
569 }
570
571 static void strip_init(struct perf_inject *inject)
572 {
573         struct perf_evlist *evlist = inject->session->evlist;
574         struct perf_evsel *evsel;
575
576         inject->tool.context_switch = perf_event__drop;
577
578         evlist__for_each_entry(evlist, evsel)
579                 evsel->handler = drop_sample;
580 }
581
582 static bool has_tracking(struct perf_evsel *evsel)
583 {
584         return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm ||
585                evsel->attr.task;
586 }
587
588 #define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \
589                      PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER)
590
591 /*
592  * In order that the perf.data file is parsable, tracking events like MMAP need
593  * their selected event to exist, except if there is only 1 selected event left
594  * and it has a compatible sample type.
595  */
596 static bool ok_to_remove(struct perf_evlist *evlist,
597                          struct perf_evsel *evsel_to_remove)
598 {
599         struct perf_evsel *evsel;
600         int cnt = 0;
601         bool ok = false;
602
603         if (!has_tracking(evsel_to_remove))
604                 return true;
605
606         evlist__for_each_entry(evlist, evsel) {
607                 if (evsel->handler != drop_sample) {
608                         cnt += 1;
609                         if ((evsel->attr.sample_type & COMPAT_MASK) ==
610                             (evsel_to_remove->attr.sample_type & COMPAT_MASK))
611                                 ok = true;
612                 }
613         }
614
615         return ok && cnt == 1;
616 }
617
618 static void strip_fini(struct perf_inject *inject)
619 {
620         struct perf_evlist *evlist = inject->session->evlist;
621         struct perf_evsel *evsel, *tmp;
622
623         /* Remove non-synthesized evsels if possible */
624         evlist__for_each_entry_safe(evlist, tmp, evsel) {
625                 if (evsel->handler == drop_sample &&
626                     ok_to_remove(evlist, evsel)) {
627                         pr_debug("Deleting %s\n", perf_evsel__name(evsel));
628                         perf_evlist__remove(evlist, evsel);
629                         perf_evsel__delete(evsel);
630                 }
631         }
632 }
633
634 static int __cmd_inject(struct perf_inject *inject)
635 {
636         int ret = -EINVAL;
637         struct perf_session *session = inject->session;
638         struct perf_data_file *file_out = &inject->output;
639         int fd = perf_data_file__fd(file_out);
640         u64 output_data_offset;
641
642         signal(SIGINT, sig_handler);
643
644         if (inject->build_ids || inject->sched_stat ||
645             inject->itrace_synth_opts.set) {
646                 inject->tool.mmap         = perf_event__repipe_mmap;
647                 inject->tool.mmap2        = perf_event__repipe_mmap2;
648                 inject->tool.fork         = perf_event__repipe_fork;
649                 inject->tool.tracing_data = perf_event__repipe_tracing_data;
650         }
651
652         output_data_offset = session->header.data_offset;
653
654         if (inject->build_ids) {
655                 inject->tool.sample = perf_event__inject_buildid;
656         } else if (inject->sched_stat) {
657                 struct perf_evsel *evsel;
658
659                 evlist__for_each_entry(session->evlist, evsel) {
660                         const char *name = perf_evsel__name(evsel);
661
662                         if (!strcmp(name, "sched:sched_switch")) {
663                                 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
664                                         return -EINVAL;
665
666                                 evsel->handler = perf_inject__sched_switch;
667                         } else if (!strcmp(name, "sched:sched_process_exit"))
668                                 evsel->handler = perf_inject__sched_process_exit;
669                         else if (!strncmp(name, "sched:sched_stat_", 17))
670                                 evsel->handler = perf_inject__sched_stat;
671                 }
672         } else if (inject->itrace_synth_opts.set) {
673                 session->itrace_synth_opts = &inject->itrace_synth_opts;
674                 inject->itrace_synth_opts.inject = true;
675                 inject->tool.comm           = perf_event__repipe_comm;
676                 inject->tool.namespaces     = perf_event__repipe_namespaces;
677                 inject->tool.exit           = perf_event__repipe_exit;
678                 inject->tool.id_index       = perf_event__repipe_id_index;
679                 inject->tool.auxtrace_info  = perf_event__process_auxtrace_info;
680                 inject->tool.auxtrace       = perf_event__process_auxtrace;
681                 inject->tool.aux            = perf_event__drop_aux;
682                 inject->tool.itrace_start   = perf_event__drop_aux,
683                 inject->tool.ordered_events = true;
684                 inject->tool.ordering_requires_timestamps = true;
685                 /* Allow space in the header for new attributes */
686                 output_data_offset = 4096;
687                 if (inject->strip)
688                         strip_init(inject);
689         }
690
691         if (!inject->itrace_synth_opts.set)
692                 auxtrace_index__free(&session->auxtrace_index);
693
694         if (!file_out->is_pipe)
695                 lseek(fd, output_data_offset, SEEK_SET);
696
697         ret = perf_session__process_events(session);
698         if (ret)
699                 return ret;
700
701         if (!file_out->is_pipe) {
702                 if (inject->build_ids)
703                         perf_header__set_feat(&session->header,
704                                               HEADER_BUILD_ID);
705                 /*
706                  * Keep all buildids when there is unprocessed AUX data because
707                  * it is not known which ones the AUX trace hits.
708                  */
709                 if (perf_header__has_feat(&session->header, HEADER_BUILD_ID) &&
710                     inject->have_auxtrace && !inject->itrace_synth_opts.set)
711                         dsos__hit_all(session);
712                 /*
713                  * The AUX areas have been removed and replaced with
714                  * synthesized hardware events, so clear the feature flag and
715                  * remove the evsel.
716                  */
717                 if (inject->itrace_synth_opts.set) {
718                         struct perf_evsel *evsel;
719
720                         perf_header__clear_feat(&session->header,
721                                                 HEADER_AUXTRACE);
722                         if (inject->itrace_synth_opts.last_branch)
723                                 perf_header__set_feat(&session->header,
724                                                       HEADER_BRANCH_STACK);
725                         evsel = perf_evlist__id2evsel_strict(session->evlist,
726                                                              inject->aux_id);
727                         if (evsel) {
728                                 pr_debug("Deleting %s\n",
729                                          perf_evsel__name(evsel));
730                                 perf_evlist__remove(session->evlist, evsel);
731                                 perf_evsel__delete(evsel);
732                         }
733                         if (inject->strip)
734                                 strip_fini(inject);
735                 }
736                 session->header.data_offset = output_data_offset;
737                 session->header.data_size = inject->bytes_written;
738                 perf_session__write_header(session, session->evlist, fd, true);
739         }
740
741         return ret;
742 }
743
744 int cmd_inject(int argc, const char **argv)
745 {
746         struct perf_inject inject = {
747                 .tool = {
748                         .sample         = perf_event__repipe_sample,
749                         .mmap           = perf_event__repipe,
750                         .mmap2          = perf_event__repipe,
751                         .comm           = perf_event__repipe,
752                         .fork           = perf_event__repipe,
753                         .exit           = perf_event__repipe,
754                         .lost           = perf_event__repipe,
755                         .lost_samples   = perf_event__repipe,
756                         .aux            = perf_event__repipe,
757                         .itrace_start   = perf_event__repipe,
758                         .context_switch = perf_event__repipe,
759                         .read           = perf_event__repipe_sample,
760                         .throttle       = perf_event__repipe,
761                         .unthrottle     = perf_event__repipe,
762                         .attr           = perf_event__repipe_attr,
763                         .tracing_data   = perf_event__repipe_op2_synth,
764                         .auxtrace_info  = perf_event__repipe_op2_synth,
765                         .auxtrace       = perf_event__repipe_auxtrace,
766                         .auxtrace_error = perf_event__repipe_op2_synth,
767                         .time_conv      = perf_event__repipe_op2_synth,
768                         .finished_round = perf_event__repipe_oe_synth,
769                         .build_id       = perf_event__repipe_op2_synth,
770                         .id_index       = perf_event__repipe_op2_synth,
771                 },
772                 .input_name  = "-",
773                 .samples = LIST_HEAD_INIT(inject.samples),
774                 .output = {
775                         .path = "-",
776                         .mode = PERF_DATA_MODE_WRITE,
777                 },
778         };
779         struct perf_data_file file = {
780                 .mode = PERF_DATA_MODE_READ,
781         };
782         int ret;
783
784         struct option options[] = {
785                 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
786                             "Inject build-ids into the output stream"),
787                 OPT_STRING('i', "input", &inject.input_name, "file",
788                            "input file name"),
789                 OPT_STRING('o', "output", &inject.output.path, "file",
790                            "output file name"),
791                 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
792                             "Merge sched-stat and sched-switch for getting events "
793                             "where and how long tasks slept"),
794 #ifdef HAVE_JITDUMP
795                 OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"),
796 #endif
797                 OPT_INCR('v', "verbose", &verbose,
798                          "be more verbose (show build ids, etc)"),
799                 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
800                            "kallsyms pathname"),
801                 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
802                 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
803                                     NULL, "opts", "Instruction Tracing options",
804                                     itrace_parse_synth_opts),
805                 OPT_BOOLEAN(0, "strip", &inject.strip,
806                             "strip non-synthesized events (use with --itrace)"),
807                 OPT_END()
808         };
809         const char * const inject_usage[] = {
810                 "perf inject [<options>]",
811                 NULL
812         };
813 #ifndef HAVE_JITDUMP
814         set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true);
815 #endif
816         argc = parse_options(argc, argv, options, inject_usage, 0);
817
818         /*
819          * Any (unrecognized) arguments left?
820          */
821         if (argc)
822                 usage_with_options(inject_usage, options);
823
824         if (inject.strip && !inject.itrace_synth_opts.set) {
825                 pr_err("--strip option requires --itrace option\n");
826                 return -1;
827         }
828
829         if (perf_data_file__open(&inject.output)) {
830                 perror("failed to create output file");
831                 return -1;
832         }
833
834         inject.tool.ordered_events = inject.sched_stat;
835
836         file.path = inject.input_name;
837         inject.session = perf_session__new(&file, true, &inject.tool);
838         if (inject.session == NULL)
839                 return -1;
840
841         if (inject.build_ids) {
842                 /*
843                  * to make sure the mmap records are ordered correctly
844                  * and so that the correct especially due to jitted code
845                  * mmaps. We cannot generate the buildid hit list and
846                  * inject the jit mmaps at the same time for now.
847                  */
848                 inject.tool.ordered_events = true;
849                 inject.tool.ordering_requires_timestamps = true;
850         }
851 #ifdef HAVE_JITDUMP
852         if (inject.jit_mode) {
853                 inject.tool.mmap2          = perf_event__jit_repipe_mmap2;
854                 inject.tool.mmap           = perf_event__jit_repipe_mmap;
855                 inject.tool.ordered_events = true;
856                 inject.tool.ordering_requires_timestamps = true;
857                 /*
858                  * JIT MMAP injection injects all MMAP events in one go, so it
859                  * does not obey finished_round semantics.
860                  */
861                 inject.tool.finished_round = perf_event__drop_oe;
862         }
863 #endif
864         ret = symbol__init(&inject.session->header.env);
865         if (ret < 0)
866                 goto out_delete;
867
868         ret = __cmd_inject(&inject);
869
870 out_delete:
871         perf_session__delete(inject.session);
872         return ret;
873 }