diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 2 | ||||
-rw-r--r-- | tools/perf/builtin-evlist.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 20 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 11 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 8 | ||||
-rw-r--r-- | tools/perf/builtin-stat.c | 59 | ||||
-rw-r--r-- | tools/perf/util/cpumap.c | 17 | ||||
-rw-r--r-- | tools/perf/util/cpumap.h | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 9 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 4 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 14 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-events.l | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-options.c | 62 | ||||
-rw-r--r-- | tools/perf/util/parse-options.h | 5 | ||||
-rw-r--r-- | tools/perf/util/strbuf.c | 22 | ||||
-rw-r--r-- | tools/perf/util/strbuf.h | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 11 |
21 files changed, 216 insertions, 49 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index ab1fd64e3627..5ce8da1e1256 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -29,7 +29,7 @@ OPTIONS | |||
29 | --show-nr-samples:: | 29 | --show-nr-samples:: |
30 | Show the number of samples for each symbol | 30 | Show the number of samples for each symbol |
31 | 31 | ||
32 | --showcpuutilization:: | 32 | --show-cpu-utilization:: |
33 | Show sample percentage for different cpu modes. | 33 | Show sample percentage for different cpu modes. |
34 | 34 | ||
35 | -T:: | 35 | -T:: |
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 695ec5a50cf2..f4d62510acbb 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c | |||
@@ -61,8 +61,8 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) | |||
61 | usage_with_options(evlist_usage, options); | 61 | usage_with_options(evlist_usage, options); |
62 | 62 | ||
63 | if (details.event_group && (details.verbose || details.freq)) { | 63 | if (details.event_group && (details.verbose || details.freq)) { |
64 | pr_err("--group option is not compatible with other options\n"); | 64 | usage_with_options_msg(evlist_usage, options, |
65 | usage_with_options(evlist_usage, options); | 65 | "--group option is not compatible with other options\n"); |
66 | } | 66 | } |
67 | 67 | ||
68 | return __cmd_evlist(input_name, &details); | 68 | return __cmd_evlist(input_name, &details); |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 530c3a28a58c..132afc97676c 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -528,12 +528,12 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
528 | PARSE_OPT_STOP_AT_NON_OPTION); | 528 | PARSE_OPT_STOP_AT_NON_OPTION); |
529 | if (argc > 0) { | 529 | if (argc > 0) { |
530 | if (strcmp(argv[0], "-") == 0) { | 530 | if (strcmp(argv[0], "-") == 0) { |
531 | pr_warning(" Error: '-' is not supported.\n"); | 531 | usage_with_options_msg(probe_usage, options, |
532 | usage_with_options(probe_usage, options); | 532 | "'-' is not supported.\n"); |
533 | } | 533 | } |
534 | if (params.command && params.command != 'a') { | 534 | if (params.command && params.command != 'a') { |
535 | pr_warning(" Error: another command except --add is set.\n"); | 535 | usage_with_options_msg(probe_usage, options, |
536 | usage_with_options(probe_usage, options); | 536 | "another command except --add is set.\n"); |
537 | } | 537 | } |
538 | ret = parse_probe_event_argv(argc, argv); | 538 | ret = parse_probe_event_argv(argc, argv); |
539 | if (ret < 0) { | 539 | if (ret < 0) { |
@@ -562,8 +562,10 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
562 | switch (params.command) { | 562 | switch (params.command) { |
563 | case 'l': | 563 | case 'l': |
564 | if (params.uprobes) { | 564 | if (params.uprobes) { |
565 | pr_warning(" Error: Don't use --list with --exec.\n"); | 565 | pr_err(" Error: Don't use --list with --exec.\n"); |
566 | usage_with_options(probe_usage, options); | 566 | parse_options_usage(probe_usage, options, "l", true); |
567 | parse_options_usage(NULL, options, "x", true); | ||
568 | return -EINVAL; | ||
567 | } | 569 | } |
568 | ret = show_perf_probe_events(params.filter); | 570 | ret = show_perf_probe_events(params.filter); |
569 | if (ret < 0) | 571 | if (ret < 0) |
@@ -603,8 +605,10 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
603 | case 'a': | 605 | case 'a': |
604 | /* Ensure the last given target is used */ | 606 | /* Ensure the last given target is used */ |
605 | if (params.target && !params.target_used) { | 607 | if (params.target && !params.target_used) { |
606 | pr_warning(" Error: -x/-m must follow the probe definitions.\n"); | 608 | pr_err(" Error: -x/-m must follow the probe definitions.\n"); |
607 | usage_with_options(probe_usage, options); | 609 | parse_options_usage(probe_usage, options, "m", true); |
610 | parse_options_usage(NULL, options, "x", true); | ||
611 | return -EINVAL; | ||
608 | } | 612 | } |
609 | 613 | ||
610 | ret = perf_add_probe_events(params.events, params.nevents); | 614 | ret = perf_add_probe_events(params.events, params.nevents); |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2740d7a82ae8..de02267c73d8 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -1135,14 +1135,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1135 | usage_with_options(record_usage, record_options); | 1135 | usage_with_options(record_usage, record_options); |
1136 | 1136 | ||
1137 | if (nr_cgroups && !rec->opts.target.system_wide) { | 1137 | if (nr_cgroups && !rec->opts.target.system_wide) { |
1138 | ui__error("cgroup monitoring only available in" | 1138 | usage_with_options_msg(record_usage, record_options, |
1139 | " system-wide mode\n"); | 1139 | "cgroup monitoring only available in system-wide mode"); |
1140 | usage_with_options(record_usage, record_options); | 1140 | |
1141 | } | 1141 | } |
1142 | if (rec->opts.record_switch_events && | 1142 | if (rec->opts.record_switch_events && |
1143 | !perf_can_record_switch_events()) { | 1143 | !perf_can_record_switch_events()) { |
1144 | ui__error("kernel does not support recording context switch events (--switch-events option)\n"); | 1144 | ui__error("kernel does not support recording context switch events\n"); |
1145 | usage_with_options(record_usage, record_options); | 1145 | parse_options_usage(record_usage, record_options, "switch-events", 0); |
1146 | return -EINVAL; | ||
1146 | } | 1147 | } |
1147 | 1148 | ||
1148 | if (!rec->itr) { | 1149 | if (!rec->itr) { |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 50dd4d3d8667..2853ad2bd435 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -699,8 +699,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
699 | " Please refer the man page for the complete list."), | 699 | " Please refer the man page for the complete list."), |
700 | OPT_STRING('F', "fields", &field_order, "key[,keys...]", | 700 | OPT_STRING('F', "fields", &field_order, "key[,keys...]", |
701 | "output field(s): overhead, period, sample plus all of sort keys"), | 701 | "output field(s): overhead, period, sample plus all of sort keys"), |
702 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | 702 | OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization, |
703 | "Show sample percentage for different cpu modes"), | 703 | "Show sample percentage for different cpu modes"), |
704 | OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | ||
705 | "Show sample percentage for different cpu modes", PARSE_OPT_HIDDEN), | ||
704 | OPT_STRING('p', "parent", &parent_pattern, "regex", | 706 | OPT_STRING('p', "parent", &parent_pattern, "regex", |
705 | "regex filter to identify parent, see: '--sort parent'"), | 707 | "regex filter to identify parent, see: '--sort parent'"), |
706 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, | 708 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 33962612a5e9..0ee6d900e100 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1728,8 +1728,8 @@ static void setup_sorting(struct perf_sched *sched, const struct option *options | |||
1728 | for (tok = strtok_r(str, ", ", &tmp); | 1728 | for (tok = strtok_r(str, ", ", &tmp); |
1729 | tok; tok = strtok_r(NULL, ", ", &tmp)) { | 1729 | tok; tok = strtok_r(NULL, ", ", &tmp)) { |
1730 | if (sort_dimension__add(tok, &sched->sort_list) < 0) { | 1730 | if (sort_dimension__add(tok, &sched->sort_list) < 0) { |
1731 | error("Unknown --sort key: `%s'", tok); | 1731 | usage_with_options_msg(usage_msg, options, |
1732 | usage_with_options(usage_msg, options); | 1732 | "Unknown --sort key: `%s'", tok); |
1733 | } | 1733 | } |
1734 | } | 1734 | } |
1735 | 1735 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 2653c0273b89..278acb22f029 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -1767,9 +1767,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1767 | rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); | 1767 | rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); |
1768 | 1768 | ||
1769 | if (!rec_script_path && !rep_script_path) { | 1769 | if (!rec_script_path && !rep_script_path) { |
1770 | fprintf(stderr, " Couldn't find script %s\n\n See perf" | 1770 | usage_with_options_msg(script_usage, options, |
1771 | "Couldn't find script `%s'\n\n See perf" | ||
1771 | " script -l for available scripts.\n", argv[0]); | 1772 | " script -l for available scripts.\n", argv[0]); |
1772 | usage_with_options(script_usage, options); | ||
1773 | } | 1773 | } |
1774 | 1774 | ||
1775 | if (is_top_script(argv[0])) { | 1775 | if (is_top_script(argv[0])) { |
@@ -1780,10 +1780,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1780 | rep_args = has_required_arg(rep_script_path); | 1780 | rep_args = has_required_arg(rep_script_path); |
1781 | rec_args = (argc - 1) - rep_args; | 1781 | rec_args = (argc - 1) - rep_args; |
1782 | if (rec_args < 0) { | 1782 | if (rec_args < 0) { |
1783 | fprintf(stderr, " %s script requires options." | 1783 | usage_with_options_msg(script_usage, options, |
1784 | "`%s' script requires options." | ||
1784 | "\n\n See perf script -l for available " | 1785 | "\n\n See perf script -l for available " |
1785 | "scripts and options.\n", argv[0]); | 1786 | "scripts and options.\n", argv[0]); |
1786 | usage_with_options(script_usage, options); | ||
1787 | } | 1787 | } |
1788 | } | 1788 | } |
1789 | 1789 | ||
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 91e793a76929..2f438f76cceb 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -100,6 +100,8 @@ static struct target target = { | |||
100 | .uid = UINT_MAX, | 100 | .uid = UINT_MAX, |
101 | }; | 101 | }; |
102 | 102 | ||
103 | typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); | ||
104 | |||
103 | static int run_count = 1; | 105 | static int run_count = 1; |
104 | static bool no_inherit = false; | 106 | static bool no_inherit = false; |
105 | static volatile pid_t child_pid = -1; | 107 | static volatile pid_t child_pid = -1; |
@@ -119,7 +121,7 @@ static unsigned int unit_width = 4; /* strlen("unit") */ | |||
119 | static bool forever = false; | 121 | static bool forever = false; |
120 | static struct timespec ref_time; | 122 | static struct timespec ref_time; |
121 | static struct cpu_map *aggr_map; | 123 | static struct cpu_map *aggr_map; |
122 | static int (*aggr_get_id)(struct cpu_map *m, int cpu); | 124 | static aggr_get_id_t aggr_get_id; |
123 | 125 | ||
124 | static volatile int done = 0; | 126 | static volatile int done = 0; |
125 | 127 | ||
@@ -954,22 +956,63 @@ static int perf_stat__get_core(struct cpu_map *map, int cpu) | |||
954 | return cpu_map__get_core(map, cpu, NULL); | 956 | return cpu_map__get_core(map, cpu, NULL); |
955 | } | 957 | } |
956 | 958 | ||
959 | static int cpu_map__get_max(struct cpu_map *map) | ||
960 | { | ||
961 | int i, max = -1; | ||
962 | |||
963 | for (i = 0; i < map->nr; i++) { | ||
964 | if (map->map[i] > max) | ||
965 | max = map->map[i]; | ||
966 | } | ||
967 | |||
968 | return max; | ||
969 | } | ||
970 | |||
971 | static struct cpu_map *cpus_aggr_map; | ||
972 | |||
973 | static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx) | ||
974 | { | ||
975 | int cpu; | ||
976 | |||
977 | if (idx >= map->nr) | ||
978 | return -1; | ||
979 | |||
980 | cpu = map->map[idx]; | ||
981 | |||
982 | if (cpus_aggr_map->map[cpu] == -1) | ||
983 | cpus_aggr_map->map[cpu] = get_id(map, idx); | ||
984 | |||
985 | return cpus_aggr_map->map[cpu]; | ||
986 | } | ||
987 | |||
988 | static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) | ||
989 | { | ||
990 | return perf_stat__get_aggr(perf_stat__get_socket, map, idx); | ||
991 | } | ||
992 | |||
993 | static int perf_stat__get_core_cached(struct cpu_map *map, int idx) | ||
994 | { | ||
995 | return perf_stat__get_aggr(perf_stat__get_core, map, idx); | ||
996 | } | ||
997 | |||
957 | static int perf_stat_init_aggr_mode(void) | 998 | static int perf_stat_init_aggr_mode(void) |
958 | { | 999 | { |
1000 | int nr; | ||
1001 | |||
959 | switch (stat_config.aggr_mode) { | 1002 | switch (stat_config.aggr_mode) { |
960 | case AGGR_SOCKET: | 1003 | case AGGR_SOCKET: |
961 | if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { | 1004 | if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { |
962 | perror("cannot build socket map"); | 1005 | perror("cannot build socket map"); |
963 | return -1; | 1006 | return -1; |
964 | } | 1007 | } |
965 | aggr_get_id = perf_stat__get_socket; | 1008 | aggr_get_id = perf_stat__get_socket_cached; |
966 | break; | 1009 | break; |
967 | case AGGR_CORE: | 1010 | case AGGR_CORE: |
968 | if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { | 1011 | if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { |
969 | perror("cannot build core map"); | 1012 | perror("cannot build core map"); |
970 | return -1; | 1013 | return -1; |
971 | } | 1014 | } |
972 | aggr_get_id = perf_stat__get_core; | 1015 | aggr_get_id = perf_stat__get_core_cached; |
973 | break; | 1016 | break; |
974 | case AGGR_NONE: | 1017 | case AGGR_NONE: |
975 | case AGGR_GLOBAL: | 1018 | case AGGR_GLOBAL: |
@@ -978,7 +1021,15 @@ static int perf_stat_init_aggr_mode(void) | |||
978 | default: | 1021 | default: |
979 | break; | 1022 | break; |
980 | } | 1023 | } |
981 | return 0; | 1024 | |
1025 | /* | ||
1026 | * The evsel_list->cpus is the base we operate on, | ||
1027 | * taking the highest cpu number to be the size of | ||
1028 | * the aggregation translate cpumap. | ||
1029 | */ | ||
1030 | nr = cpu_map__get_max(evsel_list->cpus); | ||
1031 | cpus_aggr_map = cpu_map__empty_new(nr + 1); | ||
1032 | return cpus_aggr_map ? 0 : -ENOMEM; | ||
982 | } | 1033 | } |
983 | 1034 | ||
984 | /* | 1035 | /* |
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index aa6b490aa471..10af1e7524fb 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -203,6 +203,23 @@ struct cpu_map *cpu_map__dummy_new(void) | |||
203 | return cpus; | 203 | return cpus; |
204 | } | 204 | } |
205 | 205 | ||
206 | struct cpu_map *cpu_map__empty_new(int nr) | ||
207 | { | ||
208 | struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr); | ||
209 | |||
210 | if (cpus != NULL) { | ||
211 | int i; | ||
212 | |||
213 | cpus->nr = nr; | ||
214 | for (i = 0; i < nr; i++) | ||
215 | cpus->map[i] = -1; | ||
216 | |||
217 | atomic_set(&cpus->refcnt, 1); | ||
218 | } | ||
219 | |||
220 | return cpus; | ||
221 | } | ||
222 | |||
206 | static void cpu_map__delete(struct cpu_map *map) | 223 | static void cpu_map__delete(struct cpu_map *map) |
207 | { | 224 | { |
208 | if (map) { | 225 | if (map) { |
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index f1bcd2cfa164..85f7772457fa 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -15,6 +15,7 @@ struct cpu_map { | |||
15 | }; | 15 | }; |
16 | 16 | ||
17 | struct cpu_map *cpu_map__new(const char *cpu_list); | 17 | struct cpu_map *cpu_map__new(const char *cpu_list); |
18 | struct cpu_map *cpu_map__empty_new(int nr); | ||
18 | struct cpu_map *cpu_map__dummy_new(void); | 19 | struct cpu_map *cpu_map__dummy_new(void); |
19 | struct cpu_map *cpu_map__read(FILE *file); | 20 | struct cpu_map *cpu_map__read(FILE *file); |
20 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); | 21 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ab05fa52a5cd..3ac4ee9c6a6e 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -652,6 +652,15 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
652 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: | 652 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: |
653 | dump_size = term->val.stack_user; | 653 | dump_size = term->val.stack_user; |
654 | break; | 654 | break; |
655 | case PERF_EVSEL__CONFIG_TERM_INHERIT: | ||
656 | /* | ||
657 | * attr->inherit should has already been set by | ||
658 | * perf_evsel__config. If user explicitly set | ||
659 | * inherit using config terms, override global | ||
660 | * opt->no_inherit setting. | ||
661 | */ | ||
662 | attr->inherit = term->val.inherit ? 1 : 0; | ||
663 | break; | ||
655 | default: | 664 | default: |
656 | break; | 665 | break; |
657 | } | 666 | } |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 02a5fed8d924..1e8ff1906f71 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -43,6 +43,7 @@ enum { | |||
43 | PERF_EVSEL__CONFIG_TERM_TIME, | 43 | PERF_EVSEL__CONFIG_TERM_TIME, |
44 | PERF_EVSEL__CONFIG_TERM_CALLGRAPH, | 44 | PERF_EVSEL__CONFIG_TERM_CALLGRAPH, |
45 | PERF_EVSEL__CONFIG_TERM_STACK_USER, | 45 | PERF_EVSEL__CONFIG_TERM_STACK_USER, |
46 | PERF_EVSEL__CONFIG_TERM_INHERIT, | ||
46 | PERF_EVSEL__CONFIG_TERM_MAX, | 47 | PERF_EVSEL__CONFIG_TERM_MAX, |
47 | }; | 48 | }; |
48 | 49 | ||
@@ -55,6 +56,7 @@ struct perf_evsel_config_term { | |||
55 | bool time; | 56 | bool time; |
56 | char *callgraph; | 57 | char *callgraph; |
57 | u64 stack_user; | 58 | u64 stack_user; |
59 | bool inherit; | ||
58 | } val; | 60 | } val; |
59 | }; | 61 | }; |
60 | 62 | ||
@@ -90,9 +92,9 @@ struct perf_evsel { | |||
90 | double scale; | 92 | double scale; |
91 | const char *unit; | 93 | const char *unit; |
92 | struct event_format *tp_format; | 94 | struct event_format *tp_format; |
95 | off_t id_offset; | ||
93 | union { | 96 | union { |
94 | void *priv; | 97 | void *priv; |
95 | off_t id_offset; | ||
96 | u64 db_id; | 98 | u64 db_id; |
97 | }; | 99 | }; |
98 | struct cgroup_sel *cgrp; | 100 | struct cgroup_sel *cgrp; |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 991bbd469bea..72abcf254ccb 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -666,6 +666,12 @@ do { \ | |||
666 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | 666 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: |
667 | CHECK_TYPE_VAL(NUM); | 667 | CHECK_TYPE_VAL(NUM); |
668 | break; | 668 | break; |
669 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | ||
670 | CHECK_TYPE_VAL(NUM); | ||
671 | break; | ||
672 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | ||
673 | CHECK_TYPE_VAL(NUM); | ||
674 | break; | ||
669 | case PARSE_EVENTS__TERM_TYPE_NAME: | 675 | case PARSE_EVENTS__TERM_TYPE_NAME: |
670 | CHECK_TYPE_VAL(STR); | 676 | CHECK_TYPE_VAL(STR); |
671 | break; | 677 | break; |
@@ -701,6 +707,8 @@ static int config_term_tracepoint(struct perf_event_attr *attr, | |||
701 | switch (term->type_term) { | 707 | switch (term->type_term) { |
702 | case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: | 708 | case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: |
703 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | 709 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: |
710 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | ||
711 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | ||
704 | return config_term_common(attr, term, err); | 712 | return config_term_common(attr, term, err); |
705 | default: | 713 | default: |
706 | if (err) { | 714 | if (err) { |
@@ -764,6 +772,12 @@ do { \ | |||
764 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | 772 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: |
765 | ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); | 773 | ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); |
766 | break; | 774 | break; |
775 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | ||
776 | ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0); | ||
777 | break; | ||
778 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | ||
779 | ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); | ||
780 | break; | ||
767 | default: | 781 | default: |
768 | break; | 782 | break; |
769 | } | 783 | } |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index f13d3ccda444..13c9063513eb 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -67,6 +67,8 @@ enum { | |||
67 | PARSE_EVENTS__TERM_TYPE_TIME, | 67 | PARSE_EVENTS__TERM_TYPE_TIME, |
68 | PARSE_EVENTS__TERM_TYPE_CALLGRAPH, | 68 | PARSE_EVENTS__TERM_TYPE_CALLGRAPH, |
69 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, | 69 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, |
70 | PARSE_EVENTS__TERM_TYPE_NOINHERIT, | ||
71 | PARSE_EVENTS__TERM_TYPE_INHERIT | ||
70 | }; | 72 | }; |
71 | 73 | ||
72 | struct parse_events_term { | 74 | struct parse_events_term { |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index be244573a02e..8d0de5b2991d 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
@@ -187,6 +187,8 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE | |||
187 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } | 187 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } |
188 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } | 188 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } |
189 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } | 189 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } |
190 | inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } | ||
191 | no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } | ||
190 | , { return ','; } | 192 | , { return ','; } |
191 | "/" { BEGIN(INITIAL); return '/'; } | 193 | "/" { BEGIN(INITIAL); return '/'; } |
192 | {name_minus} { return str(yyscanner, PE_NAME); } | 194 | {name_minus} { return str(yyscanner, PE_NAME); } |
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 22c2806bda98..9fca09296eb3 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #define OPT_SHORT 1 | 7 | #define OPT_SHORT 1 |
8 | #define OPT_UNSET 2 | 8 | #define OPT_UNSET 2 |
9 | 9 | ||
10 | static struct strbuf error_buf = STRBUF_INIT; | ||
11 | |||
10 | static int opterror(const struct option *opt, const char *reason, int flags) | 12 | static int opterror(const struct option *opt, const char *reason, int flags) |
11 | { | 13 | { |
12 | if (flags & OPT_SHORT) | 14 | if (flags & OPT_SHORT) |
@@ -540,9 +542,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o | |||
540 | exit(130); | 542 | exit(130); |
541 | default: /* PARSE_OPT_UNKNOWN */ | 543 | default: /* PARSE_OPT_UNKNOWN */ |
542 | if (ctx.argv[0][1] == '-') { | 544 | if (ctx.argv[0][1] == '-') { |
543 | error("unknown option `%s'", ctx.argv[0] + 2); | 545 | strbuf_addf(&error_buf, "unknown option `%s'", |
546 | ctx.argv[0] + 2); | ||
544 | } else { | 547 | } else { |
545 | error("unknown switch `%c'", *ctx.opt); | 548 | strbuf_addf(&error_buf, "unknown switch `%c'", |
549 | *ctx.opt); | ||
546 | } | 550 | } |
547 | usage_with_options(usagestr, options); | 551 | usage_with_options(usagestr, options); |
548 | } | 552 | } |
@@ -691,8 +695,21 @@ static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx | |||
691 | for (i = 1; i < ctx->argc; ++i) { | 695 | for (i = 1; i < ctx->argc; ++i) { |
692 | const char *arg = ctx->argv[i]; | 696 | const char *arg = ctx->argv[i]; |
693 | 697 | ||
694 | if (arg[0] != '-') | 698 | if (arg[0] != '-') { |
699 | if (arg[1] == '\0') { | ||
700 | if (arg[0] == opt->short_name) | ||
701 | return true; | ||
702 | continue; | ||
703 | } | ||
704 | |||
705 | if (opt->long_name && strcmp(opt->long_name, arg) == 0) | ||
706 | return true; | ||
707 | |||
708 | if (opt->help && strcasestr(opt->help, arg) != NULL) | ||
709 | return true; | ||
710 | |||
695 | continue; | 711 | continue; |
712 | } | ||
696 | 713 | ||
697 | if (arg[1] == opt->short_name || | 714 | if (arg[1] == opt->short_name || |
698 | (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0)) | 715 | (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0)) |
@@ -711,6 +728,13 @@ int usage_with_options_internal(const char * const *usagestr, | |||
711 | if (!usagestr) | 728 | if (!usagestr) |
712 | return PARSE_OPT_HELP; | 729 | return PARSE_OPT_HELP; |
713 | 730 | ||
731 | setup_pager(); | ||
732 | |||
733 | if (strbuf_avail(&error_buf)) { | ||
734 | fprintf(stderr, " Error: %s\n", error_buf.buf); | ||
735 | strbuf_release(&error_buf); | ||
736 | } | ||
737 | |||
714 | fprintf(stderr, "\n Usage: %s\n", *usagestr++); | 738 | fprintf(stderr, "\n Usage: %s\n", *usagestr++); |
715 | while (*usagestr && **usagestr) | 739 | while (*usagestr && **usagestr) |
716 | fprintf(stderr, " or: %s\n", *usagestr++); | 740 | fprintf(stderr, " or: %s\n", *usagestr++); |
@@ -749,6 +773,21 @@ void usage_with_options(const char * const *usagestr, | |||
749 | exit(129); | 773 | exit(129); |
750 | } | 774 | } |
751 | 775 | ||
776 | void usage_with_options_msg(const char * const *usagestr, | ||
777 | const struct option *opts, const char *fmt, ...) | ||
778 | { | ||
779 | va_list ap; | ||
780 | |||
781 | exit_browser(false); | ||
782 | |||
783 | va_start(ap, fmt); | ||
784 | strbuf_addv(&error_buf, fmt, ap); | ||
785 | va_end(ap); | ||
786 | |||
787 | usage_with_options_internal(usagestr, opts, 0, NULL); | ||
788 | exit(129); | ||
789 | } | ||
790 | |||
752 | int parse_options_usage(const char * const *usagestr, | 791 | int parse_options_usage(const char * const *usagestr, |
753 | const struct option *opts, | 792 | const struct option *opts, |
754 | const char *optstr, bool short_opt) | 793 | const char *optstr, bool short_opt) |
@@ -770,24 +809,23 @@ int parse_options_usage(const char * const *usagestr, | |||
770 | opt: | 809 | opt: |
771 | for ( ; opts->type != OPTION_END; opts++) { | 810 | for ( ; opts->type != OPTION_END; opts++) { |
772 | if (short_opt) { | 811 | if (short_opt) { |
773 | if (opts->short_name == *optstr) | 812 | if (opts->short_name == *optstr) { |
813 | print_option_help(opts, 0); | ||
774 | break; | 814 | break; |
815 | } | ||
775 | continue; | 816 | continue; |
776 | } | 817 | } |
777 | 818 | ||
778 | if (opts->long_name == NULL) | 819 | if (opts->long_name == NULL) |
779 | continue; | 820 | continue; |
780 | 821 | ||
781 | if (!prefixcmp(optstr, opts->long_name)) | 822 | if (!prefixcmp(opts->long_name, optstr)) |
782 | break; | 823 | print_option_help(opts, 0); |
783 | if (!prefixcmp(optstr, "no-") && | 824 | if (!prefixcmp("no-", optstr) && |
784 | !prefixcmp(optstr + 3, opts->long_name)) | 825 | !prefixcmp(opts->long_name, optstr + 3)) |
785 | break; | 826 | print_option_help(opts, 0); |
786 | } | 827 | } |
787 | 828 | ||
788 | if (opts->type != OPTION_END) | ||
789 | print_option_help(opts, 0); | ||
790 | |||
791 | return PARSE_OPT_HELP; | 829 | return PARSE_OPT_HELP; |
792 | } | 830 | } |
793 | 831 | ||
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 367d8b816cc7..a8e407bc251e 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -111,6 +111,7 @@ struct option { | |||
111 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } | 111 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } |
112 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } | 112 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } |
113 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } | 113 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } |
114 | #define OPT_BOOLEAN_FLAG(s, l, v, h, f) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) } | ||
114 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ | 115 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ |
115 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ | 116 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ |
116 | .value = check_vtype(v, bool *), .help = (h), \ | 117 | .value = check_vtype(v, bool *), .help = (h), \ |
@@ -160,6 +161,10 @@ extern int parse_options_subcommand(int argc, const char **argv, | |||
160 | 161 | ||
161 | extern NORETURN void usage_with_options(const char * const *usagestr, | 162 | extern NORETURN void usage_with_options(const char * const *usagestr, |
162 | const struct option *options); | 163 | const struct option *options); |
164 | extern NORETURN __attribute__((format(printf,3,4))) | ||
165 | void usage_with_options_msg(const char * const *usagestr, | ||
166 | const struct option *options, | ||
167 | const char *fmt, ...); | ||
163 | 168 | ||
164 | /*----- incremantal advanced APIs -----*/ | 169 | /*----- incremantal advanced APIs -----*/ |
165 | 170 | ||
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 4abe23550c73..25671fa16618 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -82,23 +82,22 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len) | |||
82 | strbuf_setlen(sb, sb->len + len); | 82 | strbuf_setlen(sb, sb->len + len); |
83 | } | 83 | } |
84 | 84 | ||
85 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | 85 | void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) |
86 | { | 86 | { |
87 | int len; | 87 | int len; |
88 | va_list ap; | 88 | va_list ap_saved; |
89 | 89 | ||
90 | if (!strbuf_avail(sb)) | 90 | if (!strbuf_avail(sb)) |
91 | strbuf_grow(sb, 64); | 91 | strbuf_grow(sb, 64); |
92 | va_start(ap, fmt); | 92 | |
93 | va_copy(ap_saved, ap); | ||
93 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); | 94 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); |
94 | va_end(ap); | ||
95 | if (len < 0) | 95 | if (len < 0) |
96 | die("your vsnprintf is broken"); | 96 | die("your vsnprintf is broken"); |
97 | if (len > strbuf_avail(sb)) { | 97 | if (len > strbuf_avail(sb)) { |
98 | strbuf_grow(sb, len); | 98 | strbuf_grow(sb, len); |
99 | va_start(ap, fmt); | 99 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); |
100 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); | 100 | va_end(ap_saved); |
101 | va_end(ap); | ||
102 | if (len > strbuf_avail(sb)) { | 101 | if (len > strbuf_avail(sb)) { |
103 | die("this should not happen, your vsnprintf is broken"); | 102 | die("this should not happen, your vsnprintf is broken"); |
104 | } | 103 | } |
@@ -106,6 +105,15 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | |||
106 | strbuf_setlen(sb, sb->len + len); | 105 | strbuf_setlen(sb, sb->len + len); |
107 | } | 106 | } |
108 | 107 | ||
108 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | ||
109 | { | ||
110 | va_list ap; | ||
111 | |||
112 | va_start(ap, fmt); | ||
113 | strbuf_addv(sb, fmt, ap); | ||
114 | va_end(ap); | ||
115 | } | ||
116 | |||
109 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) | 117 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) |
110 | { | 118 | { |
111 | size_t oldlen = sb->len; | 119 | size_t oldlen = sb->len; |
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 436ac319f6c7..529f2f035249 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h | |||
@@ -39,6 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include <assert.h> | 41 | #include <assert.h> |
42 | #include <stdarg.h> | ||
42 | 43 | ||
43 | extern char strbuf_slopbuf[]; | 44 | extern char strbuf_slopbuf[]; |
44 | struct strbuf { | 45 | struct strbuf { |
@@ -85,6 +86,7 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s) { | |||
85 | 86 | ||
86 | __attribute__((format(printf,2,3))) | 87 | __attribute__((format(printf,2,3))) |
87 | extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); | 88 | extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); |
89 | extern void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap); | ||
88 | 90 | ||
89 | /* XXX: if read fails, any partial read is undone */ | 91 | /* XXX: if read fails, any partial read is undone */ |
90 | extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); | 92 | extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index fd8477cacf88..48906333a858 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -337,7 +337,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, | |||
337 | symbol_filter_t filter __maybe_unused, | 337 | symbol_filter_t filter __maybe_unused, |
338 | int kmodule __maybe_unused) | 338 | int kmodule __maybe_unused) |
339 | { | 339 | { |
340 | unsigned char *build_id[BUILD_ID_SIZE]; | 340 | unsigned char build_id[BUILD_ID_SIZE]; |
341 | int ret; | 341 | int ret; |
342 | 342 | ||
343 | ret = fd__is_64_bit(ss->fd); | 343 | ret = fd__is_64_bit(ss->fd); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e7bf0c46918d..b4cc7662677e 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -680,7 +680,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | |||
680 | pos->start -= curr_map->start - curr_map->pgoff; | 680 | pos->start -= curr_map->start - curr_map->pgoff; |
681 | if (pos->end) | 681 | if (pos->end) |
682 | pos->end -= curr_map->start - curr_map->pgoff; | 682 | pos->end -= curr_map->start - curr_map->pgoff; |
683 | if (curr_map != map) { | 683 | if (curr_map->dso != map->dso) { |
684 | rb_erase_init(&pos->rb_node, root); | 684 | rb_erase_init(&pos->rb_node, root); |
685 | symbols__insert( | 685 | symbols__insert( |
686 | &curr_map->dso->symbols[curr_map->type], | 686 | &curr_map->dso->symbols[curr_map->type], |
@@ -1406,6 +1406,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1406 | struct symsrc ss_[2]; | 1406 | struct symsrc ss_[2]; |
1407 | struct symsrc *syms_ss = NULL, *runtime_ss = NULL; | 1407 | struct symsrc *syms_ss = NULL, *runtime_ss = NULL; |
1408 | bool kmod; | 1408 | bool kmod; |
1409 | unsigned char build_id[BUILD_ID_SIZE]; | ||
1409 | 1410 | ||
1410 | pthread_mutex_lock(&dso->lock); | 1411 | pthread_mutex_lock(&dso->lock); |
1411 | 1412 | ||
@@ -1461,6 +1462,14 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1461 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || | 1462 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || |
1462 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; | 1463 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; |
1463 | 1464 | ||
1465 | |||
1466 | /* | ||
1467 | * Read the build id if possible. This is required for | ||
1468 | * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work | ||
1469 | */ | ||
1470 | if (filename__read_build_id(dso->name, build_id, BUILD_ID_SIZE) > 0) | ||
1471 | dso__set_build_id(dso, build_id); | ||
1472 | |||
1464 | /* | 1473 | /* |
1465 | * Iterate over candidate debug images. | 1474 | * Iterate over candidate debug images. |
1466 | * Keep track of "interesting" ones (those which have a symtab, dynsym, | 1475 | * Keep track of "interesting" ones (those which have a symtab, dynsym, |