aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c297
1 files changed, 229 insertions, 68 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ac574ea23917..22747de7234b 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -10,7 +10,6 @@
10#include "util/symbol.h" 10#include "util/symbol.h"
11#include "util/thread.h" 11#include "util/thread.h"
12#include "util/trace-event.h" 12#include "util/trace-event.h"
13#include "util/parse-options.h"
14#include "util/util.h" 13#include "util/util.h"
15#include "util/evlist.h" 14#include "util/evlist.h"
16#include "util/evsel.h" 15#include "util/evsel.h"
@@ -49,57 +48,169 @@ struct output_option {
49}; 48};
50 49
51/* default set to maintain compatibility with current format */ 50/* default set to maintain compatibility with current format */
52static u64 output_fields[PERF_TYPE_MAX] = { 51static struct {
53 [PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 52 bool user_set;
54 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 53 bool wildcard_set;
55 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 54 u64 fields;
56 55 u64 invalid_fields;
57 [PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 56} output[PERF_TYPE_MAX] = {
58 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 57
59 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 58 [PERF_TYPE_HARDWARE] = {
60 59 .user_set = false,
61 [PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 60
62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 61 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, 62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
64
65 .invalid_fields = PERF_OUTPUT_TRACE,
66 },
67
68 [PERF_TYPE_SOFTWARE] = {
69 .user_set = false,
70
71 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
72 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
73 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
74
75 .invalid_fields = PERF_OUTPUT_TRACE,
76 },
77
78 [PERF_TYPE_TRACEPOINT] = {
79 .user_set = false,
80
81 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
82 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
83 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
84 },
85
86 [PERF_TYPE_RAW] = {
87 .user_set = false,
88
89 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
90 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
91 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
92
93 .invalid_fields = PERF_OUTPUT_TRACE,
94 },
64}; 95};
65 96
66static bool output_set_by_user; 97static bool output_set_by_user(void)
98{
99 int j;
100 for (j = 0; j < PERF_TYPE_MAX; ++j) {
101 if (output[j].user_set)
102 return true;
103 }
104 return false;
105}
106
107static const char *output_field2str(enum perf_output_field field)
108{
109 int i, imax = ARRAY_SIZE(all_output_options);
110 const char *str = "";
111
112 for (i = 0; i < imax; ++i) {
113 if (all_output_options[i].field == field) {
114 str = all_output_options[i].str;
115 break;
116 }
117 }
118 return str;
119}
120
121#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
122
123static int perf_event_attr__check_stype(struct perf_event_attr *attr,
124 u64 sample_type, const char *sample_msg,
125 enum perf_output_field field)
126{
127 int type = attr->type;
128 const char *evname;
129
130 if (attr->sample_type & sample_type)
131 return 0;
67 132
68#define PRINT_FIELD(x) (output_fields[attr->type] & PERF_OUTPUT_##x) 133 if (output[type].user_set) {
134 evname = __event_name(attr->type, attr->config);
135 pr_err("Samples for '%s' event do not have %s attribute set. "
136 "Cannot print '%s' field.\n",
137 evname, sample_msg, output_field2str(field));
138 return -1;
139 }
140
141 /* user did not ask for it explicitly so remove from the default list */
142 output[type].fields &= ~field;
143 evname = __event_name(attr->type, attr->config);
144 pr_debug("Samples for '%s' event do not have %s attribute set. "
145 "Skipping '%s' field.\n",
146 evname, sample_msg, output_field2str(field));
147
148 return 0;
149}
69 150
70static int perf_session__check_attr(struct perf_session *session, 151static int perf_evsel__check_attr(struct perf_evsel *evsel,
71 struct perf_event_attr *attr) 152 struct perf_session *session)
72{ 153{
154 struct perf_event_attr *attr = &evsel->attr;
155
73 if (PRINT_FIELD(TRACE) && 156 if (PRINT_FIELD(TRACE) &&
74 !perf_session__has_traces(session, "record -R")) 157 !perf_session__has_traces(session, "record -R"))
75 return -EINVAL; 158 return -EINVAL;
76 159
77 if (PRINT_FIELD(SYM)) { 160 if (PRINT_FIELD(SYM)) {
78 if (!(session->sample_type & PERF_SAMPLE_IP)) { 161 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
79 pr_err("Samples do not contain IP data.\n"); 162 PERF_OUTPUT_SYM))
80 return -EINVAL; 163 return -EINVAL;
81 } 164
82 if (!no_callchain && 165 if (!no_callchain &&
83 !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) 166 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
84 symbol_conf.use_callchain = false; 167 symbol_conf.use_callchain = false;
85 } 168 }
86 169
87 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 170 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
88 !(session->sample_type & PERF_SAMPLE_TID)) { 171 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
89 pr_err("Samples do not contain TID/PID data.\n"); 172 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
90 return -EINVAL; 173 return -EINVAL;
91 }
92 174
93 if (PRINT_FIELD(TIME) && 175 if (PRINT_FIELD(TIME) &&
94 !(session->sample_type & PERF_SAMPLE_TIME)) { 176 perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME",
95 pr_err("Samples do not contain timestamps.\n"); 177 PERF_OUTPUT_TIME))
96 return -EINVAL; 178 return -EINVAL;
97 }
98 179
99 if (PRINT_FIELD(CPU) && 180 if (PRINT_FIELD(CPU) &&
100 !(session->sample_type & PERF_SAMPLE_CPU)) { 181 perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU",
101 pr_err("Samples do not contain cpu.\n"); 182 PERF_OUTPUT_CPU))
102 return -EINVAL; 183 return -EINVAL;
184
185 return 0;
186}
187
188/*
189 * verify all user requested events exist and the samples
190 * have the expected data
191 */
192static int perf_session__check_output_opt(struct perf_session *session)
193{
194 int j;
195 struct perf_evsel *evsel;
196
197 for (j = 0; j < PERF_TYPE_MAX; ++j) {
198 evsel = perf_session__find_first_evtype(session, j);
199
200 /*
201 * even if fields is set to 0 (ie., show nothing) event must
202 * exist if user explicitly includes it on the command line
203 */
204 if (!evsel && output[j].user_set && !output[j].wildcard_set) {
205 pr_err("%s events do not exist. "
206 "Remove corresponding -f option to proceed.\n",
207 event_type(j));
208 return -1;
209 }
210
211 if (evsel && output[j].fields &&
212 perf_evsel__check_attr(evsel, session))
213 return -1;
103 } 214 }
104 215
105 return 0; 216 return 0;
@@ -168,10 +279,7 @@ static void process_event(union perf_event *event __unused,
168{ 279{
169 struct perf_event_attr *attr = &evsel->attr; 280 struct perf_event_attr *attr = &evsel->attr;
170 281
171 if (output_fields[attr->type] == 0) 282 if (output[attr->type].fields == 0)
172 return;
173
174 if (perf_session__check_attr(session, attr) < 0)
175 return; 283 return;
176 284
177 print_sample_start(sample, thread, attr); 285 print_sample_start(sample, thread, attr);
@@ -451,6 +559,7 @@ static int parse_output_fields(const struct option *opt __used,
451{ 559{
452 char *tok; 560 char *tok;
453 int i, imax = sizeof(all_output_options) / sizeof(struct output_option); 561 int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
562 int j;
454 int rc = 0; 563 int rc = 0;
455 char *str = strdup(arg); 564 char *str = strdup(arg);
456 int type = -1; 565 int type = -1;
@@ -458,52 +567,99 @@ static int parse_output_fields(const struct option *opt __used,
458 if (!str) 567 if (!str)
459 return -ENOMEM; 568 return -ENOMEM;
460 569
461 tok = strtok(str, ":"); 570 /* first word can state for which event type the user is specifying
462 if (!tok) { 571 * the fields. If no type exists, the specified fields apply to all
463 fprintf(stderr, 572 * event types found in the file minus the invalid fields for a type.
464 "Invalid field string - not prepended with type.");
465 return -EINVAL;
466 }
467
468 /* first word should state which event type user
469 * is specifying the fields
470 */ 573 */
471 if (!strcmp(tok, "hw")) 574 tok = strchr(str, ':');
472 type = PERF_TYPE_HARDWARE; 575 if (tok) {
473 else if (!strcmp(tok, "sw")) 576 *tok = '\0';
474 type = PERF_TYPE_SOFTWARE; 577 tok++;
475 else if (!strcmp(tok, "trace")) 578 if (!strcmp(str, "hw"))
476 type = PERF_TYPE_TRACEPOINT; 579 type = PERF_TYPE_HARDWARE;
477 else { 580 else if (!strcmp(str, "sw"))
478 fprintf(stderr, "Invalid event type in field string."); 581 type = PERF_TYPE_SOFTWARE;
479 return -EINVAL; 582 else if (!strcmp(str, "trace"))
583 type = PERF_TYPE_TRACEPOINT;
584 else if (!strcmp(str, "raw"))
585 type = PERF_TYPE_RAW;
586 else {
587 fprintf(stderr, "Invalid event type in field string.\n");
588 return -EINVAL;
589 }
590
591 if (output[type].user_set)
592 pr_warning("Overriding previous field request for %s events.\n",
593 event_type(type));
594
595 output[type].fields = 0;
596 output[type].user_set = true;
597 output[type].wildcard_set = false;
598
599 } else {
600 tok = str;
601 if (strlen(str) == 0) {
602 fprintf(stderr,
603 "Cannot set fields to 'none' for all event types.\n");
604 rc = -EINVAL;
605 goto out;
606 }
607
608 if (output_set_by_user())
609 pr_warning("Overriding previous field request for all events.\n");
610
611 for (j = 0; j < PERF_TYPE_MAX; ++j) {
612 output[j].fields = 0;
613 output[j].user_set = true;
614 output[j].wildcard_set = true;
615 }
480 } 616 }
481 617
482 output_fields[type] = 0; 618 tok = strtok(tok, ",");
483 while (1) { 619 while (tok) {
484 tok = strtok(NULL, ",");
485 if (!tok)
486 break;
487 for (i = 0; i < imax; ++i) { 620 for (i = 0; i < imax; ++i) {
488 if (strcmp(tok, all_output_options[i].str) == 0) { 621 if (strcmp(tok, all_output_options[i].str) == 0)
489 output_fields[type] |= all_output_options[i].field;
490 break; 622 break;
491 }
492 } 623 }
493 if (i == imax) { 624 if (i == imax) {
494 fprintf(stderr, "Invalid field requested."); 625 fprintf(stderr, "Invalid field requested.\n");
495 rc = -EINVAL; 626 rc = -EINVAL;
496 break; 627 goto out;
497 } 628 }
498 }
499 629
500 if (output_fields[type] == 0) { 630 if (type == -1) {
501 pr_debug("No fields requested for %s type. " 631 /* add user option to all events types for
502 "Events will not be displayed\n", event_type(type)); 632 * which it is valid
633 */
634 for (j = 0; j < PERF_TYPE_MAX; ++j) {
635 if (output[j].invalid_fields & all_output_options[i].field) {
636 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
637 all_output_options[i].str, event_type(j));
638 } else
639 output[j].fields |= all_output_options[i].field;
640 }
641 } else {
642 if (output[type].invalid_fields & all_output_options[i].field) {
643 fprintf(stderr, "\'%s\' not valid for %s events.\n",
644 all_output_options[i].str, event_type(type));
645
646 rc = -EINVAL;
647 goto out;
648 }
649 output[type].fields |= all_output_options[i].field;
650 }
651
652 tok = strtok(NULL, ",");
503 } 653 }
504 654
505 output_set_by_user = true; 655 if (type >= 0) {
656 if (output[type].fields == 0) {
657 pr_debug("No fields requested for %s type. "
658 "Events will not be displayed.\n", event_type(type));
659 }
660 }
506 661
662out:
507 free(str); 663 free(str);
508 return rc; 664 return rc;
509} 665}
@@ -829,7 +985,7 @@ static const struct option options[] = {
829 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 985 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
830 "Look for files with symbols relative to this directory"), 986 "Look for files with symbols relative to this directory"),
831 OPT_CALLBACK('f', "fields", NULL, "str", 987 OPT_CALLBACK('f', "fields", NULL, "str",
832 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym", 988 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym",
833 parse_output_fields), 989 parse_output_fields),
834 990
835 OPT_END() 991 OPT_END()
@@ -1020,7 +1176,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1020 struct stat perf_stat; 1176 struct stat perf_stat;
1021 int input; 1177 int input;
1022 1178
1023 if (output_set_by_user) { 1179 if (output_set_by_user()) {
1024 fprintf(stderr, 1180 fprintf(stderr,
1025 "custom fields not supported for generated scripts"); 1181 "custom fields not supported for generated scripts");
1026 return -1; 1182 return -1;
@@ -1060,6 +1216,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1060 pr_debug("perf script started with script %s\n\n", script_name); 1216 pr_debug("perf script started with script %s\n\n", script_name);
1061 } 1217 }
1062 1218
1219
1220 err = perf_session__check_output_opt(session);
1221 if (err < 0)
1222 goto out;
1223
1063 err = __cmd_script(session); 1224 err = __cmd_script(session);
1064 1225
1065 perf_session__delete(session); 1226 perf_session__delete(session);