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