diff options
author | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /tools/perf/builtin-script.c | |
parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r-- | tools/perf/builtin-script.c | 104 |
1 files changed, 98 insertions, 6 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 24809787369f..eb51325e8ad9 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "util/exec_cmd.h" | 6 | #include "util/exec_cmd.h" |
7 | #include "util/header.h" | 7 | #include "util/header.h" |
8 | #include "util/parse-options.h" | 8 | #include "util/parse-options.h" |
9 | #include "util/perf_regs.h" | ||
9 | #include "util/session.h" | 10 | #include "util/session.h" |
10 | #include "util/tool.h" | 11 | #include "util/tool.h" |
11 | #include "util/symbol.h" | 12 | #include "util/symbol.h" |
@@ -46,6 +47,7 @@ enum perf_output_field { | |||
46 | PERF_OUTPUT_SYMOFFSET = 1U << 11, | 47 | PERF_OUTPUT_SYMOFFSET = 1U << 11, |
47 | PERF_OUTPUT_SRCLINE = 1U << 12, | 48 | PERF_OUTPUT_SRCLINE = 1U << 12, |
48 | PERF_OUTPUT_PERIOD = 1U << 13, | 49 | PERF_OUTPUT_PERIOD = 1U << 13, |
50 | PERF_OUTPUT_IREGS = 1U << 14, | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | struct output_option { | 53 | struct output_option { |
@@ -66,6 +68,7 @@ struct output_option { | |||
66 | {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, | 68 | {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, |
67 | {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, | 69 | {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, |
68 | {.str = "period", .field = PERF_OUTPUT_PERIOD}, | 70 | {.str = "period", .field = PERF_OUTPUT_PERIOD}, |
71 | {.str = "iregs", .field = PERF_OUTPUT_IREGS}, | ||
69 | }; | 72 | }; |
70 | 73 | ||
71 | /* default set to maintain compatibility with current format */ | 74 | /* default set to maintain compatibility with current format */ |
@@ -255,6 +258,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
255 | PERF_OUTPUT_PERIOD)) | 258 | PERF_OUTPUT_PERIOD)) |
256 | return -EINVAL; | 259 | return -EINVAL; |
257 | 260 | ||
261 | if (PRINT_FIELD(IREGS) && | ||
262 | perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", | ||
263 | PERF_OUTPUT_IREGS)) | ||
264 | return -EINVAL; | ||
265 | |||
258 | return 0; | 266 | return 0; |
259 | } | 267 | } |
260 | 268 | ||
@@ -352,6 +360,24 @@ out: | |||
352 | return 0; | 360 | return 0; |
353 | } | 361 | } |
354 | 362 | ||
363 | static void print_sample_iregs(union perf_event *event __maybe_unused, | ||
364 | struct perf_sample *sample, | ||
365 | struct thread *thread __maybe_unused, | ||
366 | struct perf_event_attr *attr) | ||
367 | { | ||
368 | struct regs_dump *regs = &sample->intr_regs; | ||
369 | uint64_t mask = attr->sample_regs_intr; | ||
370 | unsigned i = 0, r; | ||
371 | |||
372 | if (!regs) | ||
373 | return; | ||
374 | |||
375 | for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { | ||
376 | u64 val = regs->regs[i++]; | ||
377 | printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val); | ||
378 | } | ||
379 | } | ||
380 | |||
355 | static void print_sample_start(struct perf_sample *sample, | 381 | static void print_sample_start(struct perf_sample *sample, |
356 | struct thread *thread, | 382 | struct thread *thread, |
357 | struct perf_evsel *evsel) | 383 | struct perf_evsel *evsel) |
@@ -525,6 +551,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample, | |||
525 | PERF_MAX_STACK_DEPTH); | 551 | PERF_MAX_STACK_DEPTH); |
526 | } | 552 | } |
527 | 553 | ||
554 | if (PRINT_FIELD(IREGS)) | ||
555 | print_sample_iregs(event, sample, thread, attr); | ||
556 | |||
528 | printf("\n"); | 557 | printf("\n"); |
529 | } | 558 | } |
530 | 559 | ||
@@ -623,6 +652,7 @@ struct perf_script { | |||
623 | struct perf_session *session; | 652 | struct perf_session *session; |
624 | bool show_task_events; | 653 | bool show_task_events; |
625 | bool show_mmap_events; | 654 | bool show_mmap_events; |
655 | bool show_switch_events; | ||
626 | }; | 656 | }; |
627 | 657 | ||
628 | static int process_attr(struct perf_tool *tool, union perf_event *event, | 658 | static int process_attr(struct perf_tool *tool, union perf_event *event, |
@@ -661,7 +691,7 @@ static int process_comm_event(struct perf_tool *tool, | |||
661 | struct thread *thread; | 691 | struct thread *thread; |
662 | struct perf_script *script = container_of(tool, struct perf_script, tool); | 692 | struct perf_script *script = container_of(tool, struct perf_script, tool); |
663 | struct perf_session *session = script->session; | 693 | struct perf_session *session = script->session; |
664 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | 694 | struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
665 | int ret = -1; | 695 | int ret = -1; |
666 | 696 | ||
667 | thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid); | 697 | thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid); |
@@ -695,7 +725,7 @@ static int process_fork_event(struct perf_tool *tool, | |||
695 | struct thread *thread; | 725 | struct thread *thread; |
696 | struct perf_script *script = container_of(tool, struct perf_script, tool); | 726 | struct perf_script *script = container_of(tool, struct perf_script, tool); |
697 | struct perf_session *session = script->session; | 727 | struct perf_session *session = script->session; |
698 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | 728 | struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
699 | 729 | ||
700 | if (perf_event__process_fork(tool, event, sample, machine) < 0) | 730 | if (perf_event__process_fork(tool, event, sample, machine) < 0) |
701 | return -1; | 731 | return -1; |
@@ -727,7 +757,7 @@ static int process_exit_event(struct perf_tool *tool, | |||
727 | struct thread *thread; | 757 | struct thread *thread; |
728 | struct perf_script *script = container_of(tool, struct perf_script, tool); | 758 | struct perf_script *script = container_of(tool, struct perf_script, tool); |
729 | struct perf_session *session = script->session; | 759 | struct perf_session *session = script->session; |
730 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | 760 | struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
731 | 761 | ||
732 | thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); | 762 | thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); |
733 | if (thread == NULL) { | 763 | if (thread == NULL) { |
@@ -759,7 +789,7 @@ static int process_mmap_event(struct perf_tool *tool, | |||
759 | struct thread *thread; | 789 | struct thread *thread; |
760 | struct perf_script *script = container_of(tool, struct perf_script, tool); | 790 | struct perf_script *script = container_of(tool, struct perf_script, tool); |
761 | struct perf_session *session = script->session; | 791 | struct perf_session *session = script->session; |
762 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | 792 | struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
763 | 793 | ||
764 | if (perf_event__process_mmap(tool, event, sample, machine) < 0) | 794 | if (perf_event__process_mmap(tool, event, sample, machine) < 0) |
765 | return -1; | 795 | return -1; |
@@ -790,7 +820,7 @@ static int process_mmap2_event(struct perf_tool *tool, | |||
790 | struct thread *thread; | 820 | struct thread *thread; |
791 | struct perf_script *script = container_of(tool, struct perf_script, tool); | 821 | struct perf_script *script = container_of(tool, struct perf_script, tool); |
792 | struct perf_session *session = script->session; | 822 | struct perf_session *session = script->session; |
793 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | 823 | struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
794 | 824 | ||
795 | if (perf_event__process_mmap2(tool, event, sample, machine) < 0) | 825 | if (perf_event__process_mmap2(tool, event, sample, machine) < 0) |
796 | return -1; | 826 | return -1; |
@@ -813,6 +843,32 @@ static int process_mmap2_event(struct perf_tool *tool, | |||
813 | return 0; | 843 | return 0; |
814 | } | 844 | } |
815 | 845 | ||
846 | static int process_switch_event(struct perf_tool *tool, | ||
847 | union perf_event *event, | ||
848 | struct perf_sample *sample, | ||
849 | struct machine *machine) | ||
850 | { | ||
851 | struct thread *thread; | ||
852 | struct perf_script *script = container_of(tool, struct perf_script, tool); | ||
853 | struct perf_session *session = script->session; | ||
854 | struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); | ||
855 | |||
856 | if (perf_event__process_switch(tool, event, sample, machine) < 0) | ||
857 | return -1; | ||
858 | |||
859 | thread = machine__findnew_thread(machine, sample->pid, | ||
860 | sample->tid); | ||
861 | if (thread == NULL) { | ||
862 | pr_debug("problem processing SWITCH event, skipping it.\n"); | ||
863 | return -1; | ||
864 | } | ||
865 | |||
866 | print_sample_start(sample, thread, evsel); | ||
867 | perf_event__fprintf(event, stdout); | ||
868 | thread__put(thread); | ||
869 | return 0; | ||
870 | } | ||
871 | |||
816 | static void sig_handler(int sig __maybe_unused) | 872 | static void sig_handler(int sig __maybe_unused) |
817 | { | 873 | { |
818 | session_done = 1; | 874 | session_done = 1; |
@@ -834,6 +890,8 @@ static int __cmd_script(struct perf_script *script) | |||
834 | script->tool.mmap = process_mmap_event; | 890 | script->tool.mmap = process_mmap_event; |
835 | script->tool.mmap2 = process_mmap2_event; | 891 | script->tool.mmap2 = process_mmap2_event; |
836 | } | 892 | } |
893 | if (script->show_switch_events) | ||
894 | script->tool.context_switch = process_switch_event; | ||
837 | 895 | ||
838 | ret = perf_session__process_events(script->session); | 896 | ret = perf_session__process_events(script->session); |
839 | 897 | ||
@@ -1532,6 +1590,22 @@ static int have_cmd(int argc, const char **argv) | |||
1532 | return 0; | 1590 | return 0; |
1533 | } | 1591 | } |
1534 | 1592 | ||
1593 | static void script__setup_sample_type(struct perf_script *script) | ||
1594 | { | ||
1595 | struct perf_session *session = script->session; | ||
1596 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); | ||
1597 | |||
1598 | if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { | ||
1599 | if ((sample_type & PERF_SAMPLE_REGS_USER) && | ||
1600 | (sample_type & PERF_SAMPLE_STACK_USER)) | ||
1601 | callchain_param.record_mode = CALLCHAIN_DWARF; | ||
1602 | else if (sample_type & PERF_SAMPLE_BRANCH_STACK) | ||
1603 | callchain_param.record_mode = CALLCHAIN_LBR; | ||
1604 | else | ||
1605 | callchain_param.record_mode = CALLCHAIN_FP; | ||
1606 | } | ||
1607 | } | ||
1608 | |||
1535 | int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | 1609 | int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) |
1536 | { | 1610 | { |
1537 | bool show_full_info = false; | 1611 | bool show_full_info = false; |
@@ -1598,7 +1672,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1598 | "comma separated output fields prepend with 'type:'. " | 1672 | "comma separated output fields prepend with 'type:'. " |
1599 | "Valid types: hw,sw,trace,raw. " | 1673 | "Valid types: hw,sw,trace,raw. " |
1600 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | 1674 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," |
1601 | "addr,symoff,period,flags", parse_output_fields), | 1675 | "addr,symoff,period,iregs,flags", parse_output_fields), |
1602 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 1676 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
1603 | "system-wide collection from all CPUs"), | 1677 | "system-wide collection from all CPUs"), |
1604 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", | 1678 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", |
@@ -1618,10 +1692,19 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1618 | "Show the fork/comm/exit events"), | 1692 | "Show the fork/comm/exit events"), |
1619 | OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, | 1693 | OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, |
1620 | "Show the mmap events"), | 1694 | "Show the mmap events"), |
1695 | OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, | ||
1696 | "Show context switch events (if recorded)"), | ||
1621 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), | 1697 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), |
1622 | OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", | 1698 | OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", |
1623 | "Instruction Tracing options", | 1699 | "Instruction Tracing options", |
1624 | itrace_parse_synth_opts), | 1700 | itrace_parse_synth_opts), |
1701 | OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, | ||
1702 | "Show full source file name path for source lines"), | ||
1703 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, | ||
1704 | "Enable symbol demangling"), | ||
1705 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, | ||
1706 | "Enable kernel symbol demangling"), | ||
1707 | |||
1625 | OPT_END() | 1708 | OPT_END() |
1626 | }; | 1709 | }; |
1627 | const char * const script_subcommands[] = { "record", "report", NULL }; | 1710 | const char * const script_subcommands[] = { "record", "report", NULL }; |
@@ -1816,6 +1899,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1816 | goto out_delete; | 1899 | goto out_delete; |
1817 | 1900 | ||
1818 | script.session = session; | 1901 | script.session = session; |
1902 | script__setup_sample_type(&script); | ||
1819 | 1903 | ||
1820 | session->itrace_synth_opts = &itrace_synth_opts; | 1904 | session->itrace_synth_opts = &itrace_synth_opts; |
1821 | 1905 | ||
@@ -1830,6 +1914,14 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1830 | else | 1914 | else |
1831 | symbol_conf.use_callchain = false; | 1915 | symbol_conf.use_callchain = false; |
1832 | 1916 | ||
1917 | if (session->tevent.pevent && | ||
1918 | pevent_set_function_resolver(session->tevent.pevent, | ||
1919 | machine__resolve_kernel_addr, | ||
1920 | &session->machines.host) < 0) { | ||
1921 | pr_err("%s: failed to set libtraceevent function resolver\n", __func__); | ||
1922 | return -1; | ||
1923 | } | ||
1924 | |||
1833 | if (generate_script_lang) { | 1925 | if (generate_script_lang) { |
1834 | struct stat perf_stat; | 1926 | struct stat perf_stat; |
1835 | int input; | 1927 | int input; |