aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-script.c111
-rw-r--r--tools/perf/util/session.c12
-rw-r--r--tools/perf/util/session.h3
3 files changed, 109 insertions, 17 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index b3012c4fff19..974f6d3f4e53 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -51,6 +51,7 @@ struct output_option {
51/* default set to maintain compatibility with current format */ 51/* default set to maintain compatibility with current format */
52static struct { 52static struct {
53 bool user_set; 53 bool user_set;
54 bool wildcard_set;
54 u64 fields; 55 u64 fields;
55 u64 invalid_fields; 56 u64 invalid_fields;
56} output[PERF_TYPE_MAX] = { 57} output[PERF_TYPE_MAX] = {
@@ -104,41 +105,113 @@ static bool output_set_by_user(void)
104 return false; 105 return false;
105} 106}
106 107
108static const char *output_field2str(enum perf_output_field field)
109{
110 int i, imax = ARRAY_SIZE(all_output_options);
111 const char *str = "";
112
113 for (i = 0; i < imax; ++i) {
114 if (all_output_options[i].field == field) {
115 str = all_output_options[i].str;
116 break;
117 }
118 }
119 return str;
120}
121
107#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 122#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
108 123
109static int perf_session__check_attr(struct perf_session *session, 124static int perf_event_attr__check_stype(struct perf_event_attr *attr,
110 struct perf_event_attr *attr) 125 u64 sample_type, const char *sample_msg,
126 enum perf_output_field field)
111{ 127{
128 int type = attr->type;
129 const char *evname;
130
131 if (attr->sample_type & sample_type)
132 return 0;
133
134 if (output[type].user_set) {
135 evname = __event_name(attr->type, attr->config);
136 pr_err("Samples for '%s' event do not have %s attribute set. "
137 "Cannot print '%s' field.\n",
138 evname, sample_msg, output_field2str(field));
139 return -1;
140 }
141
142 /* user did not ask for it explicitly so remove from the default list */
143 output[type].fields &= ~field;
144 evname = __event_name(attr->type, attr->config);
145 pr_debug("Samples for '%s' event do not have %s attribute set. "
146 "Skipping '%s' field.\n",
147 evname, sample_msg, output_field2str(field));
148
149 return 0;
150}
151
152static int perf_evsel__check_attr(struct perf_evsel *evsel,
153 struct perf_session *session)
154{
155 struct perf_event_attr *attr = &evsel->attr;
156
112 if (PRINT_FIELD(TRACE) && 157 if (PRINT_FIELD(TRACE) &&
113 !perf_session__has_traces(session, "record -R")) 158 !perf_session__has_traces(session, "record -R"))
114 return -EINVAL; 159 return -EINVAL;
115 160
116 if (PRINT_FIELD(SYM)) { 161 if (PRINT_FIELD(SYM)) {
117 if (!(session->sample_type & PERF_SAMPLE_IP)) { 162 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
118 pr_err("Samples do not contain IP data.\n"); 163 PERF_OUTPUT_SYM))
119 return -EINVAL; 164 return -EINVAL;
120 } 165
121 if (!no_callchain && 166 if (!no_callchain &&
122 !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) 167 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
123 symbol_conf.use_callchain = false; 168 symbol_conf.use_callchain = false;
124 } 169 }
125 170
126 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 171 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
127 !(session->sample_type & PERF_SAMPLE_TID)) { 172 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
128 pr_err("Samples do not contain TID/PID data.\n"); 173 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
129 return -EINVAL; 174 return -EINVAL;
130 }
131 175
132 if (PRINT_FIELD(TIME) && 176 if (PRINT_FIELD(TIME) &&
133 !(session->sample_type & PERF_SAMPLE_TIME)) { 177 perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME",
134 pr_err("Samples do not contain timestamps.\n"); 178 PERF_OUTPUT_TIME))
135 return -EINVAL; 179 return -EINVAL;
136 }
137 180
138 if (PRINT_FIELD(CPU) && 181 if (PRINT_FIELD(CPU) &&
139 !(session->sample_type & PERF_SAMPLE_CPU)) { 182 perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU",
140 pr_err("Samples do not contain cpu.\n"); 183 PERF_OUTPUT_CPU))
141 return -EINVAL; 184 return -EINVAL;
185
186 return 0;
187}
188
189/*
190 * verify all user requested events exist and the samples
191 * have the expected data
192 */
193static int perf_session__check_output_opt(struct perf_session *session)
194{
195 int j;
196 struct perf_evsel *evsel;
197
198 for (j = 0; j < PERF_TYPE_MAX; ++j) {
199 evsel = perf_session__find_first_evtype(session, j);
200
201 /*
202 * even if fields is set to 0 (ie., show nothing) event must
203 * exist if user explicitly includes it on the command line
204 */
205 if (!evsel && output[j].user_set && !output[j].wildcard_set) {
206 pr_err("%s events do not exist. "
207 "Remove corresponding -f option to proceed.\n",
208 event_type(j));
209 return -1;
210 }
211
212 if (evsel && output[j].fields &&
213 perf_evsel__check_attr(evsel, session))
214 return -1;
142 } 215 }
143 216
144 return 0; 217 return 0;
@@ -210,9 +283,6 @@ static void process_event(union perf_event *event __unused,
210 if (output[attr->type].fields == 0) 283 if (output[attr->type].fields == 0)
211 return; 284 return;
212 285
213 if (perf_session__check_attr(session, attr) < 0)
214 return;
215
216 print_sample_start(sample, thread, attr); 286 print_sample_start(sample, thread, attr);
217 287
218 if (PRINT_FIELD(TRACE)) 288 if (PRINT_FIELD(TRACE))
@@ -525,6 +595,7 @@ static int parse_output_fields(const struct option *opt __used,
525 595
526 output[type].fields = 0; 596 output[type].fields = 0;
527 output[type].user_set = true; 597 output[type].user_set = true;
598 output[type].wildcard_set = false;
528 599
529 } else { 600 } else {
530 tok = str; 601 tok = str;
@@ -541,6 +612,7 @@ static int parse_output_fields(const struct option *opt __used,
541 for (j = 0; j < PERF_TYPE_MAX; ++j) { 612 for (j = 0; j < PERF_TYPE_MAX; ++j) {
542 output[j].fields = 0; 613 output[j].fields = 0;
543 output[j].user_set = true; 614 output[j].user_set = true;
615 output[j].wildcard_set = true;
544 } 616 }
545 } 617 }
546 618
@@ -1145,6 +1217,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1145 pr_debug("perf script started with script %s\n\n", script_name); 1217 pr_debug("perf script started with script %s\n\n", script_name);
1146 } 1218 }
1147 1219
1220
1221 err = perf_session__check_output_opt(session);
1222 if (err < 0)
1223 goto out;
1224
1148 err = __cmd_script(session); 1225 err = __cmd_script(session);
1149 1226
1150 perf_session__delete(session); 1227 perf_session__delete(session);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index caa224522fea..fff66741f18d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1156,6 +1156,18 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1156 return ret; 1156 return ret;
1157} 1157}
1158 1158
1159struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1160 unsigned int type)
1161{
1162 struct perf_evsel *pos;
1163
1164 list_for_each_entry(pos, &session->evlist->entries, node) {
1165 if (pos->attr.type == type)
1166 return pos;
1167 }
1168 return NULL;
1169}
1170
1159void perf_session__print_symbols(union perf_event *event, 1171void perf_session__print_symbols(union perf_event *event,
1160 struct perf_sample *sample, 1172 struct perf_sample *sample,
1161 struct perf_session *session) 1173 struct perf_session *session)
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 1ac481fc1100..8daaa2d15396 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -162,6 +162,9 @@ static inline int perf_session__parse_sample(struct perf_session *session,
162 session->sample_id_all, sample); 162 session->sample_id_all, sample);
163} 163}
164 164
165struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
166 unsigned int type);
167
165void perf_session__print_symbols(union perf_event *event, 168void perf_session__print_symbols(union perf_event *event,
166 struct perf_sample *sample, 169 struct perf_sample *sample,
167 struct perf_session *session); 170 struct perf_session *session);