diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2015-04-09 11:54:00 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-04-29 09:37:57 -0400 |
commit | 0f0aa5e0693ce4000a7657cc47ce4f32b86b91ba (patch) | |
tree | 306c85337ffc7a4f75f41040ecc16bc84cff3344 /tools/perf/builtin-inject.c | |
parent | cd17a9b54463970a47fec33d94f220950c9990c4 (diff) |
perf inject: Add Instruction Tracing support
Add support for decoding an AUX area assuming it contains instruction
tracing data. The AUX area tracing events are stripped and replaced by
synthesized events.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1428594864-29309-21-git-send-email-adrian.hunter@intel.com
[ Do not use -Z as an alternative to --itrace ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-inject.c')
-rw-r--r-- | tools/perf/builtin-inject.c | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 8f4cad7e9fe7..c5f6515f0723 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "util/debug.h" | 16 | #include "util/debug.h" |
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 | 20 | ||
20 | #include "util/parse-options.h" | 21 | #include "util/parse-options.h" |
21 | 22 | ||
@@ -30,6 +31,7 @@ struct perf_inject { | |||
30 | struct perf_data_file output; | 31 | struct perf_data_file output; |
31 | u64 bytes_written; | 32 | u64 bytes_written; |
32 | struct list_head samples; | 33 | struct list_head samples; |
34 | struct itrace_synth_opts itrace_synth_opts; | ||
33 | }; | 35 | }; |
34 | 36 | ||
35 | struct event_entry { | 37 | struct event_entry { |
@@ -205,6 +207,32 @@ static int perf_event__repipe_fork(struct perf_tool *tool, | |||
205 | return err; | 207 | return err; |
206 | } | 208 | } |
207 | 209 | ||
210 | static int perf_event__repipe_comm(struct perf_tool *tool, | ||
211 | union perf_event *event, | ||
212 | struct perf_sample *sample, | ||
213 | struct machine *machine) | ||
214 | { | ||
215 | int err; | ||
216 | |||
217 | err = perf_event__process_comm(tool, event, sample, machine); | ||
218 | perf_event__repipe(tool, event, sample, machine); | ||
219 | |||
220 | return err; | ||
221 | } | ||
222 | |||
223 | static int perf_event__repipe_exit(struct perf_tool *tool, | ||
224 | union perf_event *event, | ||
225 | struct perf_sample *sample, | ||
226 | struct machine *machine) | ||
227 | { | ||
228 | int err; | ||
229 | |||
230 | err = perf_event__process_exit(tool, event, sample, machine); | ||
231 | perf_event__repipe(tool, event, sample, machine); | ||
232 | |||
233 | return err; | ||
234 | } | ||
235 | |||
208 | static int perf_event__repipe_tracing_data(struct perf_tool *tool, | 236 | static int perf_event__repipe_tracing_data(struct perf_tool *tool, |
209 | union perf_event *event, | 237 | union perf_event *event, |
210 | struct perf_session *session) | 238 | struct perf_session *session) |
@@ -217,6 +245,18 @@ static int perf_event__repipe_tracing_data(struct perf_tool *tool, | |||
217 | return err; | 245 | return err; |
218 | } | 246 | } |
219 | 247 | ||
248 | static int perf_event__repipe_id_index(struct perf_tool *tool, | ||
249 | union perf_event *event, | ||
250 | struct perf_session *session) | ||
251 | { | ||
252 | int err; | ||
253 | |||
254 | perf_event__repipe_synth(tool, event); | ||
255 | err = perf_event__process_id_index(tool, event, session); | ||
256 | |||
257 | return err; | ||
258 | } | ||
259 | |||
220 | static int dso__read_build_id(struct dso *dso) | 260 | static int dso__read_build_id(struct dso *dso) |
221 | { | 261 | { |
222 | if (dso->has_build_id) | 262 | if (dso->has_build_id) |
@@ -401,16 +441,20 @@ static int __cmd_inject(struct perf_inject *inject) | |||
401 | struct perf_session *session = inject->session; | 441 | struct perf_session *session = inject->session; |
402 | struct perf_data_file *file_out = &inject->output; | 442 | struct perf_data_file *file_out = &inject->output; |
403 | int fd = perf_data_file__fd(file_out); | 443 | int fd = perf_data_file__fd(file_out); |
444 | u64 output_data_offset; | ||
404 | 445 | ||
405 | signal(SIGINT, sig_handler); | 446 | signal(SIGINT, sig_handler); |
406 | 447 | ||
407 | if (inject->build_ids || inject->sched_stat) { | 448 | if (inject->build_ids || inject->sched_stat || |
449 | inject->itrace_synth_opts.set) { | ||
408 | inject->tool.mmap = perf_event__repipe_mmap; | 450 | inject->tool.mmap = perf_event__repipe_mmap; |
409 | inject->tool.mmap2 = perf_event__repipe_mmap2; | 451 | inject->tool.mmap2 = perf_event__repipe_mmap2; |
410 | inject->tool.fork = perf_event__repipe_fork; | 452 | inject->tool.fork = perf_event__repipe_fork; |
411 | inject->tool.tracing_data = perf_event__repipe_tracing_data; | 453 | inject->tool.tracing_data = perf_event__repipe_tracing_data; |
412 | } | 454 | } |
413 | 455 | ||
456 | output_data_offset = session->header.data_offset; | ||
457 | |||
414 | if (inject->build_ids) { | 458 | if (inject->build_ids) { |
415 | inject->tool.sample = perf_event__inject_buildid; | 459 | inject->tool.sample = perf_event__inject_buildid; |
416 | } else if (inject->sched_stat) { | 460 | } else if (inject->sched_stat) { |
@@ -429,10 +473,22 @@ static int __cmd_inject(struct perf_inject *inject) | |||
429 | else if (!strncmp(name, "sched:sched_stat_", 17)) | 473 | else if (!strncmp(name, "sched:sched_stat_", 17)) |
430 | evsel->handler = perf_inject__sched_stat; | 474 | evsel->handler = perf_inject__sched_stat; |
431 | } | 475 | } |
476 | } else if (inject->itrace_synth_opts.set) { | ||
477 | session->itrace_synth_opts = &inject->itrace_synth_opts; | ||
478 | inject->itrace_synth_opts.inject = true; | ||
479 | inject->tool.comm = perf_event__repipe_comm; | ||
480 | inject->tool.exit = perf_event__repipe_exit; | ||
481 | inject->tool.id_index = perf_event__repipe_id_index; | ||
482 | inject->tool.auxtrace_info = perf_event__process_auxtrace_info; | ||
483 | inject->tool.auxtrace = perf_event__process_auxtrace; | ||
484 | inject->tool.ordered_events = true; | ||
485 | inject->tool.ordering_requires_timestamps = true; | ||
486 | /* Allow space in the header for new attributes */ | ||
487 | output_data_offset = 4096; | ||
432 | } | 488 | } |
433 | 489 | ||
434 | if (!file_out->is_pipe) | 490 | if (!file_out->is_pipe) |
435 | lseek(fd, session->header.data_offset, SEEK_SET); | 491 | lseek(fd, output_data_offset, SEEK_SET); |
436 | 492 | ||
437 | ret = perf_session__process_events(session); | 493 | ret = perf_session__process_events(session); |
438 | 494 | ||
@@ -440,6 +496,14 @@ static int __cmd_inject(struct perf_inject *inject) | |||
440 | if (inject->build_ids) | 496 | if (inject->build_ids) |
441 | perf_header__set_feat(&session->header, | 497 | perf_header__set_feat(&session->header, |
442 | HEADER_BUILD_ID); | 498 | HEADER_BUILD_ID); |
499 | /* | ||
500 | * The AUX areas have been removed and replaced with | ||
501 | * synthesized hardware events, so clear the feature flag. | ||
502 | */ | ||
503 | if (inject->itrace_synth_opts.set) | ||
504 | perf_header__clear_feat(&session->header, | ||
505 | HEADER_AUXTRACE); | ||
506 | session->header.data_offset = output_data_offset; | ||
443 | session->header.data_size = inject->bytes_written; | 507 | session->header.data_size = inject->bytes_written; |
444 | perf_session__write_header(session, session->evlist, fd, true); | 508 | perf_session__write_header(session, session->evlist, fd, true); |
445 | } | 509 | } |
@@ -497,6 +561,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
497 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", | 561 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", |
498 | "kallsyms pathname"), | 562 | "kallsyms pathname"), |
499 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), | 563 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), |
564 | OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, | ||
565 | NULL, "opts", "Instruction Tracing options", | ||
566 | itrace_parse_synth_opts), | ||
500 | OPT_END() | 567 | OPT_END() |
501 | }; | 568 | }; |
502 | const char * const inject_usage[] = { | 569 | const char * const inject_usage[] = { |