diff options
Diffstat (limited to 'tools/perf/builtin-inject.c')
-rw-r--r-- | tools/perf/builtin-inject.c | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6567baedd92a..b38445f08c2f 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_LIBELF_SUPPORT | ||
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,27 @@ static int perf_event__repipe_mmap(struct perf_tool *tool, | |||
234 | return err; | 245 | return err; |
235 | } | 246 | } |
236 | 247 | ||
248 | #ifdef HAVE_LIBELF_SUPPORT | ||
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 | |||
257 | /* | ||
258 | * if jit marker, then inject jit mmaps and generate ELF images | ||
259 | */ | ||
260 | if (!jit_process(inject->session, &inject->output, machine, | ||
261 | event->mmap.filename, sample->pid, &n)) { | ||
262 | inject->bytes_written += n; | ||
263 | return 0; | ||
264 | } | ||
265 | return perf_event__repipe_mmap(tool, event, sample, machine); | ||
266 | } | ||
267 | #endif | ||
268 | |||
237 | static int perf_event__repipe_mmap2(struct perf_tool *tool, | 269 | static int perf_event__repipe_mmap2(struct perf_tool *tool, |
238 | union perf_event *event, | 270 | union perf_event *event, |
239 | struct perf_sample *sample, | 271 | struct perf_sample *sample, |
@@ -247,6 +279,27 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool, | |||
247 | return err; | 279 | return err; |
248 | } | 280 | } |
249 | 281 | ||
282 | #ifdef HAVE_LIBELF_SUPPORT | ||
283 | static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, | ||
284 | union perf_event *event, | ||
285 | struct perf_sample *sample, | ||
286 | struct machine *machine) | ||
287 | { | ||
288 | struct perf_inject *inject = container_of(tool, struct perf_inject, tool); | ||
289 | u64 n = 0; | ||
290 | |||
291 | /* | ||
292 | * if jit marker, then inject jit mmaps and generate ELF images | ||
293 | */ | ||
294 | if (!jit_process(inject->session, &inject->output, machine, | ||
295 | event->mmap2.filename, sample->pid, &n)) { | ||
296 | inject->bytes_written += n; | ||
297 | return 0; | ||
298 | } | ||
299 | return perf_event__repipe_mmap2(tool, event, sample, machine); | ||
300 | } | ||
301 | #endif | ||
302 | |||
250 | static int perf_event__repipe_fork(struct perf_tool *tool, | 303 | static int perf_event__repipe_fork(struct perf_tool *tool, |
251 | union perf_event *event, | 304 | union perf_event *event, |
252 | struct perf_sample *sample, | 305 | struct perf_sample *sample, |
@@ -664,6 +717,23 @@ static int __cmd_inject(struct perf_inject *inject) | |||
664 | return ret; | 717 | return ret; |
665 | } | 718 | } |
666 | 719 | ||
720 | #ifdef HAVE_LIBELF_SUPPORT | ||
721 | static int | ||
722 | jit_validate_events(struct perf_session *session) | ||
723 | { | ||
724 | struct perf_evsel *evsel; | ||
725 | |||
726 | /* | ||
727 | * check that all events use CLOCK_MONOTONIC | ||
728 | */ | ||
729 | evlist__for_each(session->evlist, evsel) { | ||
730 | if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) | ||
731 | return -1; | ||
732 | } | ||
733 | return 0; | ||
734 | } | ||
735 | #endif | ||
736 | |||
667 | int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | 737 | int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) |
668 | { | 738 | { |
669 | struct perf_inject inject = { | 739 | struct perf_inject inject = { |
@@ -703,7 +773,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
703 | }; | 773 | }; |
704 | int ret; | 774 | int ret; |
705 | 775 | ||
706 | const struct option options[] = { | 776 | struct option options[] = { |
707 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, | 777 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, |
708 | "Inject build-ids into the output stream"), | 778 | "Inject build-ids into the output stream"), |
709 | OPT_STRING('i', "input", &inject.input_name, "file", | 779 | OPT_STRING('i', "input", &inject.input_name, "file", |
@@ -713,6 +783,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
713 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, | 783 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, |
714 | "Merge sched-stat and sched-switch for getting events " | 784 | "Merge sched-stat and sched-switch for getting events " |
715 | "where and how long tasks slept"), | 785 | "where and how long tasks slept"), |
786 | OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"), | ||
716 | OPT_INCR('v', "verbose", &verbose, | 787 | OPT_INCR('v', "verbose", &verbose, |
717 | "be more verbose (show build ids, etc)"), | 788 | "be more verbose (show build ids, etc)"), |
718 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", | 789 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", |
@@ -729,7 +800,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
729 | "perf inject [<options>]", | 800 | "perf inject [<options>]", |
730 | NULL | 801 | NULL |
731 | }; | 802 | }; |
732 | 803 | #ifndef HAVE_LIBELF_SUPPORT | |
804 | set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true); | ||
805 | #endif | ||
733 | argc = parse_options(argc, argv, options, inject_usage, 0); | 806 | argc = parse_options(argc, argv, options, inject_usage, 0); |
734 | 807 | ||
735 | /* | 808 | /* |
@@ -765,7 +838,26 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
765 | inject.tool.ordered_events = true; | 838 | inject.tool.ordered_events = true; |
766 | inject.tool.ordering_requires_timestamps = true; | 839 | inject.tool.ordering_requires_timestamps = true; |
767 | } | 840 | } |
768 | 841 | #ifdef HAVE_LIBELF_SUPPORT | |
842 | if (inject.jit_mode) { | ||
843 | /* | ||
844 | * validate event is using the correct clockid | ||
845 | */ | ||
846 | if (jit_validate_events(inject.session)) { | ||
847 | fprintf(stderr, "error, jitted code must be sampled with perf record -k 1\n"); | ||
848 | return -1; | ||
849 | } | ||
850 | inject.tool.mmap2 = perf_event__jit_repipe_mmap2; | ||
851 | inject.tool.mmap = perf_event__jit_repipe_mmap; | ||
852 | inject.tool.ordered_events = true; | ||
853 | inject.tool.ordering_requires_timestamps = true; | ||
854 | /* | ||
855 | * JIT MMAP injection injects all MMAP events in one go, so it | ||
856 | * does not obey finished_round semantics. | ||
857 | */ | ||
858 | inject.tool.finished_round = perf_event__drop_oe; | ||
859 | } | ||
860 | #endif | ||
769 | ret = symbol__init(&inject.session->header.env); | 861 | ret = symbol__init(&inject.session->header.env); |
770 | if (ret < 0) | 862 | if (ret < 0) |
771 | goto out_delete; | 863 | goto out_delete; |