diff options
Diffstat (limited to 'tools/perf/builtin-inject.c')
-rw-r--r-- | tools/perf/builtin-inject.c | 105 |
1 files changed, 99 insertions, 6 deletions
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 0022e02ed31a..7fa68663ed72 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "util/build-id.h" | 17 | #include "util/build-id.h" |
18 | #include "util/data.h" | 18 | #include "util/data.h" |
19 | #include "util/auxtrace.h" | 19 | #include "util/auxtrace.h" |
20 | #include "util/jit.h" | ||
20 | 21 | ||
21 | #include <subcmd/parse-options.h> | 22 | #include <subcmd/parse-options.h> |
22 | 23 | ||
@@ -29,6 +30,7 @@ struct perf_inject { | |||
29 | bool sched_stat; | 30 | bool sched_stat; |
30 | bool have_auxtrace; | 31 | bool have_auxtrace; |
31 | bool strip; | 32 | bool strip; |
33 | bool jit_mode; | ||
32 | const char *input_name; | 34 | const char *input_name; |
33 | struct perf_data_file output; | 35 | struct perf_data_file output; |
34 | u64 bytes_written; | 36 | u64 bytes_written; |
@@ -71,6 +73,15 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool, | |||
71 | return perf_event__repipe_synth(tool, event); | 73 | return perf_event__repipe_synth(tool, event); |
72 | } | 74 | } |
73 | 75 | ||
76 | #ifdef HAVE_JITDUMP | ||
77 | static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused, | ||
78 | union perf_event *event __maybe_unused, | ||
79 | struct ordered_events *oe __maybe_unused) | ||
80 | { | ||
81 | return 0; | ||
82 | } | ||
83 | #endif | ||
84 | |||
74 | static int perf_event__repipe_op2_synth(struct perf_tool *tool, | 85 | static int perf_event__repipe_op2_synth(struct perf_tool *tool, |
75 | union perf_event *event, | 86 | union perf_event *event, |
76 | struct perf_session *session | 87 | struct perf_session *session |
@@ -234,6 +245,31 @@ static int perf_event__repipe_mmap(struct perf_tool *tool, | |||
234 | return err; | 245 | return err; |
235 | } | 246 | } |
236 | 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 | |||
237 | static int perf_event__repipe_mmap2(struct perf_tool *tool, | 273 | static int perf_event__repipe_mmap2(struct perf_tool *tool, |
238 | union perf_event *event, | 274 | union perf_event *event, |
239 | struct perf_sample *sample, | 275 | struct perf_sample *sample, |
@@ -247,6 +283,31 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool, | |||
247 | return err; | 283 | return err; |
248 | } | 284 | } |
249 | 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 | |||
250 | static int perf_event__repipe_fork(struct perf_tool *tool, | 311 | static int perf_event__repipe_fork(struct perf_tool *tool, |
251 | union perf_event *event, | 312 | union perf_event *event, |
252 | struct perf_sample *sample, | 313 | struct perf_sample *sample, |
@@ -626,12 +687,16 @@ static int __cmd_inject(struct perf_inject *inject) | |||
626 | ret = perf_session__process_events(session); | 687 | ret = perf_session__process_events(session); |
627 | 688 | ||
628 | if (!file_out->is_pipe) { | 689 | if (!file_out->is_pipe) { |
629 | if (inject->build_ids) { | 690 | if (inject->build_ids) |
630 | perf_header__set_feat(&session->header, | 691 | perf_header__set_feat(&session->header, |
631 | HEADER_BUILD_ID); | 692 | HEADER_BUILD_ID); |
632 | if (inject->have_auxtrace) | 693 | /* |
633 | dsos__hit_all(session); | 694 | * Keep all buildids when there is unprocessed AUX data because |
634 | } | 695 | * it is not known which ones the AUX trace hits. |
696 | */ | ||
697 | if (perf_header__has_feat(&session->header, HEADER_BUILD_ID) && | ||
698 | inject->have_auxtrace && !inject->itrace_synth_opts.set) | ||
699 | dsos__hit_all(session); | ||
635 | /* | 700 | /* |
636 | * The AUX areas have been removed and replaced with | 701 | * The AUX areas have been removed and replaced with |
637 | * synthesized hardware events, so clear the feature flag and | 702 | * synthesized hardware events, so clear the feature flag and |
@@ -703,7 +768,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
703 | }; | 768 | }; |
704 | int ret; | 769 | int ret; |
705 | 770 | ||
706 | const struct option options[] = { | 771 | struct option options[] = { |
707 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, | 772 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, |
708 | "Inject build-ids into the output stream"), | 773 | "Inject build-ids into the output stream"), |
709 | OPT_STRING('i', "input", &inject.input_name, "file", | 774 | OPT_STRING('i', "input", &inject.input_name, "file", |
@@ -713,6 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
713 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, | 778 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, |
714 | "Merge sched-stat and sched-switch for getting events " | 779 | "Merge sched-stat and sched-switch for getting events " |
715 | "where and how long tasks slept"), | 780 | "where and how long tasks slept"), |
781 | #ifdef HAVE_JITDUMP | ||
782 | OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"), | ||
783 | #endif | ||
716 | OPT_INCR('v', "verbose", &verbose, | 784 | OPT_INCR('v', "verbose", &verbose, |
717 | "be more verbose (show build ids, etc)"), | 785 | "be more verbose (show build ids, etc)"), |
718 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", | 786 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", |
@@ -729,7 +797,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
729 | "perf inject [<options>]", | 797 | "perf inject [<options>]", |
730 | NULL | 798 | NULL |
731 | }; | 799 | }; |
732 | 800 | #ifndef HAVE_JITDUMP | |
801 | set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true); | ||
802 | #endif | ||
733 | argc = parse_options(argc, argv, options, inject_usage, 0); | 803 | argc = parse_options(argc, argv, options, inject_usage, 0); |
734 | 804 | ||
735 | /* | 805 | /* |
@@ -755,6 +825,29 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
755 | if (inject.session == NULL) | 825 | if (inject.session == NULL) |
756 | return -1; | 826 | return -1; |
757 | 827 | ||
828 | if (inject.build_ids) { | ||
829 | /* | ||
830 | * to make sure the mmap records are ordered correctly | ||
831 | * and so that the correct especially due to jitted code | ||
832 | * mmaps. We cannot generate the buildid hit list and | ||
833 | * inject the jit mmaps at the same time for now. | ||
834 | */ | ||
835 | inject.tool.ordered_events = true; | ||
836 | inject.tool.ordering_requires_timestamps = true; | ||
837 | } | ||
838 | #ifdef HAVE_JITDUMP | ||
839 | if (inject.jit_mode) { | ||
840 | inject.tool.mmap2 = perf_event__jit_repipe_mmap2; | ||
841 | inject.tool.mmap = perf_event__jit_repipe_mmap; | ||
842 | inject.tool.ordered_events = true; | ||
843 | inject.tool.ordering_requires_timestamps = true; | ||
844 | /* | ||
845 | * JIT MMAP injection injects all MMAP events in one go, so it | ||
846 | * does not obey finished_round semantics. | ||
847 | */ | ||
848 | inject.tool.finished_round = perf_event__drop_oe; | ||
849 | } | ||
850 | #endif | ||
758 | ret = symbol__init(&inject.session->header.env); | 851 | ret = symbol__init(&inject.session->header.env); |
759 | if (ret < 0) | 852 | if (ret < 0) |
760 | goto out_delete; | 853 | goto out_delete; |