Linux Perf
builtin-inject.c
Go to the documentation of this file.
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;
33  bool build_ids;
34  bool sched_stat;
36  bool strip;
37  bool jit_mode;
38  const char *input_name;
39  struct perf_data output;
41  u64 aux_id;
42  struct list_head samples;
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__write(&inject->output, buf, sz);
57  if (size < 0)
58  return -errno;
59 
60  inject->bytes_written += size;
61  return 0;
62 }
63 
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 
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 
90  union perf_event *event,
91  struct perf_session *session
92  __maybe_unused)
93 {
94  return perf_event__repipe_synth(tool, event);
95 }
96 
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.file.fd, 0, SEEK_CUR);
150  if (offset == -1)
151  return -errno;
153  event, offset);
154  if (ret < 0)
155  return ret;
156  }
157 
158  if (perf_data__is_pipe(session->data) || !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__fd(session->data),
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 
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 
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 
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  if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) {
444  if (!al.map->dso->hit) {
445  al.map->dso->hit = 1;
446  if (map__load(al.map) >= 0) {
447  dso__inject_build_id(al.map->dso, tool, machine);
448  /*
449  * If this fails, too bad, let the other side
450  * account this as unresolved.
451  */
452  } else {
453 #ifdef HAVE_LIBELF_SUPPORT
454  pr_warning("no symbols found in %s, maybe "
455  "install a debug package?\n",
456  al.map->dso->long_name);
457 #endif
458  }
459  }
460  }
461 
462  thread__put(thread);
463 repipe:
464  perf_event__repipe(tool, event, sample, machine);
465  return 0;
466 }
467 
469  union perf_event *event __maybe_unused,
470  struct perf_sample *sample,
471  struct perf_evsel *evsel __maybe_unused,
472  struct machine *machine __maybe_unused)
473 {
474  struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
475  struct event_entry *ent;
476 
477  list_for_each_entry(ent, &inject->samples, node) {
478  if (sample->tid == ent->tid) {
479  list_del_init(&ent->node);
480  free(ent);
481  break;
482  }
483  }
484 
485  return 0;
486 }
487 
488 static int perf_inject__sched_switch(struct perf_tool *tool,
489  union perf_event *event,
490  struct perf_sample *sample,
491  struct perf_evsel *evsel,
492  struct machine *machine)
493 {
494  struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
495  struct event_entry *ent;
496 
497  perf_inject__sched_process_exit(tool, event, sample, evsel, machine);
498 
499  ent = malloc(event->header.size + sizeof(struct event_entry));
500  if (ent == NULL) {
502  "Not enough memory to process sched switch event!");
503  return -1;
504  }
505 
506  ent->tid = sample->tid;
507  memcpy(&ent->event, event, event->header.size);
508  list_add(&ent->node, &inject->samples);
509  return 0;
510 }
511 
512 static int perf_inject__sched_stat(struct perf_tool *tool,
513  union perf_event *event __maybe_unused,
514  struct perf_sample *sample,
515  struct perf_evsel *evsel,
516  struct machine *machine)
517 {
518  struct event_entry *ent;
519  union perf_event *event_sw;
520  struct perf_sample sample_sw;
521  struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
522  u32 pid = perf_evsel__intval(evsel, sample, "pid");
523 
524  list_for_each_entry(ent, &inject->samples, node) {
525  if (pid == ent->tid)
526  goto found;
527  }
528 
529  return 0;
530 found:
531  event_sw = &ent->event[0];
532  perf_evsel__parse_sample(evsel, event_sw, &sample_sw);
533 
534  sample_sw.period = sample->period;
535  sample_sw.time = sample->time;
536  perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
537  evsel->attr.read_format, &sample_sw);
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 
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 *data_out = &inject->output;
639  int fd = perf_data__fd(data_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) {
650  }
651 
652  output_data_offset = session->header.data_offset;
653 
654  if (inject->build_ids) {
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 
667  } else if (!strcmp(name, "sched:sched_process_exit"))
669  else if (!strncmp(name, "sched:sched_stat_", 17))
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;
681  inject->tool.aux = 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)
693 
694  if (!data_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 (!data_out->is_pipe) {
702  if (inject->build_ids)
703  perf_header__set_feat(&session->header,
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 
722  if (inject->itrace_synth_opts.last_branch)
723  perf_header__set_feat(&session->header,
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 = {
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,
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  .feature = perf_event__repipe_op2_synth,
772  },
773  .input_name = "-",
774  .samples = LIST_HEAD_INIT(inject.samples),
775  .output = {
776  .file = {
777  .path = "-",
778  },
779  .mode = PERF_DATA_MODE_WRITE,
780  },
781  };
782  struct perf_data data = {
784  };
785  int ret;
786 
787  struct option options[] = {
788  OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
789  "Inject build-ids into the output stream"),
790  OPT_STRING('i', "input", &inject.input_name, "file",
791  "input file name"),
792  OPT_STRING('o', "output", &inject.output.file.path, "file",
793  "output file name"),
794  OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
795  "Merge sched-stat and sched-switch for getting events "
796  "where and how long tasks slept"),
797 #ifdef HAVE_JITDUMP
798  OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"),
799 #endif
800  OPT_INCR('v', "verbose", &verbose,
801  "be more verbose (show build ids, etc)"),
802  OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
803  "kallsyms pathname"),
804  OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
805  OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
806  NULL, "opts", "Instruction Tracing options",
808  OPT_BOOLEAN(0, "strip", &inject.strip,
809  "strip non-synthesized events (use with --itrace)"),
810  OPT_END()
811  };
812  const char * const inject_usage[] = {
813  "perf inject [<options>]",
814  NULL
815  };
816 #ifndef HAVE_JITDUMP
817  set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true);
818 #endif
819  argc = parse_options(argc, argv, options, inject_usage, 0);
820 
821  /*
822  * Any (unrecognized) arguments left?
823  */
824  if (argc)
825  usage_with_options(inject_usage, options);
826 
827  if (inject.strip && !inject.itrace_synth_opts.set) {
828  pr_err("--strip option requires --itrace option\n");
829  return -1;
830  }
831 
832  if (perf_data__open(&inject.output)) {
833  perror("failed to create output file");
834  return -1;
835  }
836 
837  inject.tool.ordered_events = inject.sched_stat;
838 
839  data.file.path = inject.input_name;
840  inject.session = perf_session__new(&data, true, &inject.tool);
841  if (inject.session == NULL)
842  return -1;
843 
844  if (inject.build_ids) {
845  /*
846  * to make sure the mmap records are ordered correctly
847  * and so that the correct especially due to jitted code
848  * mmaps. We cannot generate the buildid hit list and
849  * inject the jit mmaps at the same time for now.
850  */
851  inject.tool.ordered_events = true;
852  inject.tool.ordering_requires_timestamps = true;
853  }
854 #ifdef HAVE_JITDUMP
855  if (inject.jit_mode) {
856  inject.tool.mmap2 = perf_event__jit_repipe_mmap2;
857  inject.tool.mmap = perf_event__jit_repipe_mmap;
858  inject.tool.ordered_events = true;
859  inject.tool.ordering_requires_timestamps = true;
860  /*
861  * JIT MMAP injection injects all MMAP events in one go, so it
862  * does not obey finished_round semantics.
863  */
864  inject.tool.finished_round = perf_event__drop_oe;
865  }
866 #endif
867  ret = symbol__init(&inject.session->header.env);
868  if (ret < 0)
869  goto out_delete;
870 
871  ret = __cmd_inject(&inject);
872 
873 out_delete:
875  return ret;
876 }
int perf_event__process_attr(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_evlist **pevlist)
Definition: header.c:3721
event_op mmap2
Definition: tool.h:47
static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
Definition: symbol-elf.c:1212
static int perf_event__drop_aux(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, struct machine *machine __maybe_unused)
int color_fprintf(FILE *fp, const char *color, const char *fmt,...)
Definition: color.c:123
Definition: mem2node.c:7
bool have_auxtrace
enum perf_data_mode mode
Definition: data.h:22
struct perf_evlist * evlist
Definition: session.h:25
static int perf_event__repipe_fork(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
struct perf_data * data
Definition: session.h:36
u8 has_build_id
Definition: dso.h:160
char filename[PATH_MAX]
Definition: event.h:34
size_t size
Definition: evsel.c:60
int fd
Definition: data.h:14
struct list_head samples
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1385
int jit_process(struct perf_session *session, struct perf_data *output, struct machine *machine, char *filename, pid_t pid, u64 *nbytes)
Definition: jitdump.c:754
struct perf_evsel * perf_evlist__id2evsel_strict(struct perf_evlist *evlist, u64 id)
Definition: evlist.c:606
struct map * thread__find_map(struct thread *thread, u8 cpumode, u64 addr, struct addr_location *al)
Definition: event.c:1511
int int err
Definition: 5sec.c:44
union perf_event event[0]
int filename__read_build_id(const char *filename, void *bf, size_t size)
Definition: symbol-elf.c:487
static int __cmd_inject(struct perf_inject *inject)
struct itrace_synth_opts * itrace_synth_opts
Definition: session.h:27
struct perf_data_file file
Definition: data.h:18
event_op2 tracing_data
Definition: tool.h:62
struct perf_env env
Definition: header.h:82
void perf_evsel__delete(struct perf_evsel *evsel)
Definition: evsel.c:1261
void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
Definition: evlist.c:189
event_op2 auxtrace_info
Definition: tool.h:64
const char * long_name
Definition: dso.h:173
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1273
u32 tid
#define COMPAT_MASK
int perf_event__process_exit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1416
struct list_head node
void perf_header__clear_feat(struct perf_header *header, int feat)
Definition: header.c:81
int perf_event__process_fork(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1408
u8 hit
Definition: dso.h:162
struct itrace_synth_opts itrace_synth_opts
int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *pos, u16 misc, perf_event__handler_t process, struct machine *machine)
Definition: header.c:3894
static void sig_handler(int sig __maybe_unused)
static int perf_event__repipe_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
u64 ip
Definition: event.h:192
#define pr_err(fmt,...)
Definition: json.h:21
void perf_session__delete(struct perf_session *session)
Definition: session.c:187
#define min(x, y)
Definition: jevents.h:15
#define session_done()
Definition: session.h:117
static int perf_event__repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
u64 id
Definition: event.h:196
static int perf_event__repipe_tracing_data(struct perf_tool *tool, union perf_event *event, struct perf_session *session)
int dsos__hit_all(struct perf_session *session)
Definition: build-id.c:390
static int perf_event__repipe_exit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
void * malloc(YYSIZE_T)
#define evlist__for_each_entry_safe(evlist, tmp, evsel)
Definition: evlist.h:297
static int perf_inject__sched_process_exit(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel __maybe_unused, struct machine *machine __maybe_unused)
int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel __maybe_unused, struct machine *machine)
Definition: build-id.c:34
struct map * map
Definition: symbol.h:210
static int dso__read_build_id(struct dso *dso)
static int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel __maybe_unused, struct machine *machine)
Definition: thread.h:18
const char * name
static void strip_init(struct perf_inject *inject)
int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, const struct perf_sample *sample)
Definition: evsel.c:2490
struct perf_evlist * evlist
Definition: evsel.h:92
static int perf_inject__sched_switch(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
#define pr_debug(fmt,...)
Definition: json.h:27
Definition: tool.h:44
int perf_data__open(struct perf_data *data)
Definition: data.c:122
#define evlist__for_each_entry(evlist, evsel)
Definition: evlist.h:247
event_oe finished_round
Definition: tool.h:63
struct dso * dso
Definition: map.h:45
static int perf_event__repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static bool repipe
struct perf_data output
event_op exit
Definition: tool.h:47
bool is_pipe
Definition: data.h:19
static int perf_event__repipe_namespaces(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
int itrace_parse_synth_opts(const struct option *opt, const char *str, int unset)
Definition: auxtrace.c:981
u64 period
Definition: event.h:198
u32 pid
Definition: event.h:193
event_op aux
Definition: tool.h:47
u32 tid
Definition: event.h:193
void auxtrace_index__free(struct list_head *head)
Definition: auxtrace.c:613
void perf_header__set_feat(struct perf_header *header, int feat)
Definition: header.c:76
bool ordered_events
Definition: tool.h:76
Definition: dso.h:138
#define event
s64 perf_event__process_auxtrace(struct perf_tool *tool, union perf_event *event, struct perf_session *session)
Definition: auxtrace.c:929
int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session)
Definition: auxtrace.c:905
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name)
Definition: evsel.c:2722
int(* inject_handler)(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
enum dso_kernel_type kernel
Definition: dso.h:154
bool ordering_requires_timestamps
Definition: tool.h:77
Definition: data.h:17
static int perf_data__fd(struct perf_data *data)
Definition: data.h:40
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session)
Definition: header.c:3854
bool one_mmap
Definition: session.h:32
const char * perf_evsel__name(struct perf_evsel *evsel)
Definition: evsel.c:577
struct perf_event_header header
Definition: event.h:624
u32 pid
Definition: hists_common.c:15
static int perf_event__drop(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused)
static int perf_data__is_pipe(struct perf_data *data)
Definition: data.h:35
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
Definition: session.c:116
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1393
const char * kallsyms_name
Definition: symbol.h:123
void thread__put(struct thread *thread)
Definition: thread.c:119
bool perf_header__has_feat(const struct perf_header *header, int feat)
Definition: header.c:86
static s64 perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_session *session __maybe_unused)
int perf_session__process_events(struct perf_session *session)
Definition: session.c:1945
u8 build_id[BUILD_ID_SIZE]
Definition: dso.h:170
struct list_head auxtrace_index
Definition: session.h:28
event_op namespaces
Definition: tool.h:47
int cmd_inject(int argc, const char **argv)
u64 data_offset
Definition: header.h:78
static bool has_tracking(struct perf_evsel *evsel)
u64 time
Definition: event.h:194
struct auxtrace_event auxtrace
Definition: event.h:642
struct perf_session * session
event_op2 id_index
Definition: tool.h:64
ssize_t perf_data__write(struct perf_data *data, void *buf, size_t size)
Definition: data.c:144
const char * input_name
static int drop_sample(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, struct perf_evsel *evsel __maybe_unused, struct machine *machine __maybe_unused)
struct perf_header header
Definition: session.h:23
int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event, off_t file_offset)
Definition: auxtrace.c:647
event_op comm
Definition: tool.h:47
int symbol__init(struct perf_env *env)
Definition: symbol.c:2112
#define PERF_COLOR_RED
Definition: color.h:13
void free(void *)
int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session)
Definition: session.c:2136
static int perf_event__repipe_comm(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
struct mmap2_event mmap2
Definition: event.h:626
static int perf_event__repipe(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused)
event_op itrace_start
Definition: tool.h:47
static int perf_inject__sched_stat(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
static FILE * f
Definition: intel-pt-log.c:30
static int perf_event__repipe_attr(struct perf_tool *tool, union perf_event *event, struct perf_evlist **pevlist)
static int perf_event__repipe_op2_synth(struct perf_tool *tool, union perf_event *event, struct perf_session *session __maybe_unused)
Definition: attr.py:1
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *data)
Definition: evsel.c:2059
int verbose
Definition: jevents.c:53
static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool, struct machine *machine)
int perf_session__write_header(struct perf_session *session, struct perf_evlist *evlist, int fd, bool at_exit)
Definition: header.c:2765
static bool ok_to_remove(struct perf_evlist *evlist, struct perf_evsel *evsel_to_remove)
#define pr_warning(fmt,...)
Definition: debug.h:25
event_op fork
Definition: tool.h:47
struct perf_tool tool
static int perf_event__repipe_oe_synth(struct perf_tool *tool, union perf_event *event, struct ordered_events *oe __maybe_unused)
bool force
Definition: data.h:20
event_op mmap
Definition: tool.h:47
char filename[PATH_MAX]
Definition: event.h:19
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1281
event_op context_switch
Definition: tool.h:47
int map__load(struct map *map)
Definition: map.c:307
struct mmap_event mmap
Definition: event.h:625
u8 cpumode
Definition: event.h:207
static int perf_evsel__check_stype(struct perf_evsel *evsel, u64 sample_type, const char *sample_msg)
const char * path
Definition: data.h:13
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
Definition: machine.c:492
struct perf_event_attr attr
Definition: evsel.h:93
static int perf_event__repipe_id_index(struct perf_tool *tool, union perf_event *event, struct perf_session *session)
static void strip_fini(struct perf_inject *inject)
event_op3 auxtrace
Definition: tool.h:75
event_sample sample
Definition: tool.h:45
u64 data_size
Definition: header.h:79
static int perf_event__repipe_synth(struct perf_tool *tool, union perf_event *event)
void * handler
Definition: evsel.h:111