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.c74
1 files changed, 58 insertions, 16 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4bce7d8679cb..2999e7e425f6 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -119,6 +119,11 @@ struct output_option {
119 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, 119 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
120}; 120};
121 121
122enum {
123 OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
124 OUTPUT_TYPE_MAX
125};
126
122/* default set to maintain compatibility with current format */ 127/* default set to maintain compatibility with current format */
123static struct { 128static struct {
124 bool user_set; 129 bool user_set;
@@ -126,7 +131,7 @@ static struct {
126 unsigned int print_ip_opts; 131 unsigned int print_ip_opts;
127 u64 fields; 132 u64 fields;
128 u64 invalid_fields; 133 u64 invalid_fields;
129} output[PERF_TYPE_MAX] = { 134} output[OUTPUT_TYPE_MAX] = {
130 135
131 [PERF_TYPE_HARDWARE] = { 136 [PERF_TYPE_HARDWARE] = {
132 .user_set = false, 137 .user_set = false,
@@ -184,12 +189,43 @@ static struct {
184 189
185 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 190 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
186 }, 191 },
192
193 [OUTPUT_TYPE_SYNTH] = {
194 .user_set = false,
195
196 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
197 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
198 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
199 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
200
201 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
202 },
187}; 203};
188 204
205static inline int output_type(unsigned int type)
206{
207 switch (type) {
208 case PERF_TYPE_SYNTH:
209 return OUTPUT_TYPE_SYNTH;
210 default:
211 return type;
212 }
213}
214
215static inline unsigned int attr_type(unsigned int type)
216{
217 switch (type) {
218 case OUTPUT_TYPE_SYNTH:
219 return PERF_TYPE_SYNTH;
220 default:
221 return type;
222 }
223}
224
189static bool output_set_by_user(void) 225static bool output_set_by_user(void)
190{ 226{
191 int j; 227 int j;
192 for (j = 0; j < PERF_TYPE_MAX; ++j) { 228 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
193 if (output[j].user_set) 229 if (output[j].user_set)
194 return true; 230 return true;
195 } 231 }
@@ -210,7 +246,7 @@ static const char *output_field2str(enum perf_output_field field)
210 return str; 246 return str;
211} 247}
212 248
213#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 249#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
214 250
215static int perf_evsel__do_check_stype(struct perf_evsel *evsel, 251static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
216 u64 sample_type, const char *sample_msg, 252 u64 sample_type, const char *sample_msg,
@@ -218,7 +254,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
218 bool allow_user_set) 254 bool allow_user_set)
219{ 255{
220 struct perf_event_attr *attr = &evsel->attr; 256 struct perf_event_attr *attr = &evsel->attr;
221 int type = attr->type; 257 int type = output_type(attr->type);
222 const char *evname; 258 const char *evname;
223 259
224 if (attr->sample_type & sample_type) 260 if (attr->sample_type & sample_type)
@@ -348,7 +384,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
348 384
349static void set_print_ip_opts(struct perf_event_attr *attr) 385static void set_print_ip_opts(struct perf_event_attr *attr)
350{ 386{
351 unsigned int type = attr->type; 387 unsigned int type = output_type(attr->type);
352 388
353 output[type].print_ip_opts = 0; 389 output[type].print_ip_opts = 0;
354 if (PRINT_FIELD(IP)) 390 if (PRINT_FIELD(IP))
@@ -376,14 +412,15 @@ static int perf_session__check_output_opt(struct perf_session *session)
376 unsigned int j; 412 unsigned int j;
377 struct perf_evsel *evsel; 413 struct perf_evsel *evsel;
378 414
379 for (j = 0; j < PERF_TYPE_MAX; ++j) { 415 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
380 evsel = perf_session__find_first_evtype(session, j); 416 evsel = perf_session__find_first_evtype(session, attr_type(j));
381 417
382 /* 418 /*
383 * even if fields is set to 0 (ie., show nothing) event must 419 * even if fields is set to 0 (ie., show nothing) event must
384 * exist if user explicitly includes it on the command line 420 * exist if user explicitly includes it on the command line
385 */ 421 */
386 if (!evsel && output[j].user_set && !output[j].wildcard_set) { 422 if (!evsel && output[j].user_set && !output[j].wildcard_set &&
423 j != OUTPUT_TYPE_SYNTH) {
387 pr_err("%s events do not exist. " 424 pr_err("%s events do not exist. "
388 "Remove corresponding -F option to proceed.\n", 425 "Remove corresponding -F option to proceed.\n",
389 event_type(j)); 426 event_type(j));
@@ -989,6 +1026,7 @@ static void print_sample_bts(struct perf_sample *sample,
989 struct machine *machine) 1026 struct machine *machine)
990{ 1027{
991 struct perf_event_attr *attr = &evsel->attr; 1028 struct perf_event_attr *attr = &evsel->attr;
1029 unsigned int type = output_type(attr->type);
992 bool print_srcline_last = false; 1030 bool print_srcline_last = false;
993 1031
994 if (PRINT_FIELD(CALLINDENT)) 1032 if (PRINT_FIELD(CALLINDENT))
@@ -996,7 +1034,7 @@ static void print_sample_bts(struct perf_sample *sample,
996 1034
997 /* print branch_from information */ 1035 /* print branch_from information */
998 if (PRINT_FIELD(IP)) { 1036 if (PRINT_FIELD(IP)) {
999 unsigned int print_opts = output[attr->type].print_ip_opts; 1037 unsigned int print_opts = output[type].print_ip_opts;
1000 struct callchain_cursor *cursor = NULL; 1038 struct callchain_cursor *cursor = NULL;
1001 1039
1002 if (symbol_conf.use_callchain && sample->callchain && 1040 if (symbol_conf.use_callchain && sample->callchain &&
@@ -1019,7 +1057,7 @@ static void print_sample_bts(struct perf_sample *sample,
1019 /* print branch_to information */ 1057 /* print branch_to information */
1020 if (PRINT_FIELD(ADDR) || 1058 if (PRINT_FIELD(ADDR) ||
1021 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 1059 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
1022 !output[attr->type].user_set)) { 1060 !output[type].user_set)) {
1023 printf(" => "); 1061 printf(" => ");
1024 print_sample_addr(sample, thread, attr); 1062 print_sample_addr(sample, thread, attr);
1025 } 1063 }
@@ -1215,8 +1253,9 @@ static void process_event(struct perf_script *script,
1215{ 1253{
1216 struct thread *thread = al->thread; 1254 struct thread *thread = al->thread;
1217 struct perf_event_attr *attr = &evsel->attr; 1255 struct perf_event_attr *attr = &evsel->attr;
1256 unsigned int type = output_type(attr->type);
1218 1257
1219 if (output[attr->type].fields == 0) 1258 if (output[type].fields == 0)
1220 return; 1259 return;
1221 1260
1222 print_sample_start(sample, thread, evsel); 1261 print_sample_start(sample, thread, evsel);
@@ -1263,7 +1302,7 @@ static void process_event(struct perf_script *script,
1263 cursor = &callchain_cursor; 1302 cursor = &callchain_cursor;
1264 1303
1265 putchar(cursor ? '\n' : ' '); 1304 putchar(cursor ? '\n' : ' ');
1266 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); 1305 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, stdout);
1267 } 1306 }
1268 1307
1269 if (PRINT_FIELD(IREGS)) 1308 if (PRINT_FIELD(IREGS))
@@ -1410,7 +1449,8 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
1410 evlist = *pevlist; 1449 evlist = *pevlist;
1411 evsel = perf_evlist__last(*pevlist); 1450 evsel = perf_evlist__last(*pevlist);
1412 1451
1413 if (evsel->attr.type >= PERF_TYPE_MAX) 1452 if (evsel->attr.type >= PERF_TYPE_MAX &&
1453 evsel->attr.type != PERF_TYPE_SYNTH)
1414 return 0; 1454 return 0;
1415 1455
1416 evlist__for_each_entry(evlist, pos) { 1456 evlist__for_each_entry(evlist, pos) {
@@ -1835,6 +1875,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1835 type = PERF_TYPE_RAW; 1875 type = PERF_TYPE_RAW;
1836 else if (!strcmp(str, "break")) 1876 else if (!strcmp(str, "break"))
1837 type = PERF_TYPE_BREAKPOINT; 1877 type = PERF_TYPE_BREAKPOINT;
1878 else if (!strcmp(str, "synth"))
1879 type = OUTPUT_TYPE_SYNTH;
1838 else { 1880 else {
1839 fprintf(stderr, "Invalid event type in field string.\n"); 1881 fprintf(stderr, "Invalid event type in field string.\n");
1840 rc = -EINVAL; 1882 rc = -EINVAL;
@@ -1865,7 +1907,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1865 if (output_set_by_user()) 1907 if (output_set_by_user())
1866 pr_warning("Overriding previous field request for all events.\n"); 1908 pr_warning("Overriding previous field request for all events.\n");
1867 1909
1868 for (j = 0; j < PERF_TYPE_MAX; ++j) { 1910 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
1869 output[j].fields = 0; 1911 output[j].fields = 0;
1870 output[j].user_set = true; 1912 output[j].user_set = true;
1871 output[j].wildcard_set = true; 1913 output[j].wildcard_set = true;
@@ -1908,7 +1950,7 @@ parse:
1908 /* add user option to all events types for 1950 /* add user option to all events types for
1909 * which it is valid 1951 * which it is valid
1910 */ 1952 */
1911 for (j = 0; j < PERF_TYPE_MAX; ++j) { 1953 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
1912 if (output[j].invalid_fields & all_output_options[i].field) { 1954 if (output[j].invalid_fields & all_output_options[i].field) {
1913 pr_warning("\'%s\' not valid for %s events. Ignoring.\n", 1955 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
1914 all_output_options[i].str, event_type(j)); 1956 all_output_options[i].str, event_type(j));
@@ -2560,7 +2602,7 @@ int cmd_script(int argc, const char **argv)
2560 OPT_CALLBACK('F', "fields", NULL, "str", 2602 OPT_CALLBACK('F', "fields", NULL, "str",
2561 "comma separated output fields prepend with 'type:'. " 2603 "comma separated output fields prepend with 'type:'. "
2562 "+field to add and -field to remove." 2604 "+field to add and -field to remove."
2563 "Valid types: hw,sw,trace,raw. " 2605 "Valid types: hw,sw,trace,raw,synth. "
2564 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2606 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2565 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2607 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2566 "bpf-output,callindent,insn,insnlen,brstackinsn", 2608 "bpf-output,callindent,insn,insnlen,brstackinsn",