aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-inject.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-inject.c')
-rw-r--r--tools/perf/builtin-inject.c98
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
77static 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
74static int perf_event__repipe_op2_synth(struct perf_tool *tool, 85static 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
249static 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
237static int perf_event__repipe_mmap2(struct perf_tool *tool, 269static 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
283static 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
250static int perf_event__repipe_fork(struct perf_tool *tool, 303static 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
721static int
722jit_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
667int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) 737int 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;