aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/traceevent/Makefile14
-rw-r--r--tools/lib/traceevent/event-parse.c399
-rw-r--r--tools/lib/traceevent/event-parse.h7
-rw-r--r--tools/lib/traceevent/parse-filter.c86
-rw-r--r--tools/perf/Documentation/perf-bench.txt78
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/Makefile8
-rw-r--r--tools/perf/bench/mem-memcpy.c84
-rw-r--r--tools/perf/bench/mem-memset.c88
-rw-r--r--tools/perf/builtin-bench.c4
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-kmem.c37
-rw-r--r--tools/perf/builtin-lock.c4
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/builtin-sched.c38
-rw-r--r--tools/perf/builtin-script.c106
-rw-r--r--tools/perf/builtin-stat.c12
-rw-r--r--tools/perf/builtin-test.c2
-rw-r--r--tools/perf/builtin-top.c12
-rw-r--r--tools/perf/config/feature-tests.mak13
-rw-r--r--tools/perf/ui/browsers/annotate.c4
-rw-r--r--tools/perf/ui/browsers/hists.c210
-rw-r--r--tools/perf/ui/gtk/browser.c69
-rw-r--r--tools/perf/ui/gtk/gtk.h31
-rw-r--r--tools/perf/ui/gtk/setup.c5
-rw-r--r--tools/perf/ui/gtk/util.c129
-rw-r--r--tools/perf/ui/tui/setup.c6
-rw-r--r--tools/perf/ui/tui/util.c243
-rw-r--r--tools/perf/ui/util.c277
-rw-r--r--tools/perf/ui/util.h9
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h23
-rw-r--r--tools/perf/util/evlist.c4
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c227
-rw-r--r--tools/perf/util/evsel.h15
-rw-r--r--tools/perf/util/header.c33
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/include/linux/kernel.h10
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/parse-events-test.c179
-rw-r--r--tools/perf/util/parse-events.c470
-rw-r--r--tools/perf/util/parse-events.h17
-rw-r--r--tools/perf/util/parse-events.l134
-rw-r--r--tools/perf/util/parse-events.y86
-rw-r--r--tools/perf/util/pmu.c169
-rw-r--r--tools/perf/util/pmu.h11
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c32
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c25
-rw-r--r--tools/perf/util/session.c65
-rw-r--r--tools/perf/util/session.h14
-rw-r--r--tools/perf/util/sort.c49
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/string.c22
-rw-r--r--tools/perf/util/symbol.c94
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/top.c2
-rw-r--r--tools/perf/util/trace-event-parse.c58
-rw-r--r--tools/perf/util/trace-event-read.c97
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h38
-rw-r--r--tools/perf/util/util.h2
-rw-r--r--tools/usb/testusb.c21
65 files changed, 2811 insertions, 1105 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 3d69aa9ff51e..46c2f6b7b123 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -250,8 +250,12 @@ endef
250all_objs := $(sort $(ALL_OBJS)) 250all_objs := $(sort $(ALL_OBJS))
251all_deps := $(all_objs:%.o=.%.d) 251all_deps := $(all_objs:%.o=.%.d)
252 252
253# let .d file also depends on the source and header files
253define check_deps 254define check_deps
254 $(CC) -M $(CFLAGS) $< > $@; 255 @set -e; $(RM) $@; \
256 $(CC) -M $(CFLAGS) $< > $@.$$$$; \
257 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
258 $(RM) $@.$$$$
255endef 259endef
256 260
257$(gui_deps): ks_version.h 261$(gui_deps): ks_version.h
@@ -270,11 +274,13 @@ endif
270 274
271tags: force 275tags: force
272 $(RM) tags 276 $(RM) tags
273 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px 277 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
278 --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
274 279
275TAGS: force 280TAGS: force
276 $(RM) TAGS 281 $(RM) TAGS
277 find . -name '*.[ch]' | xargs etags 282 find . -name '*.[ch]' | xargs etags \
283 --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
278 284
279define do_install 285define do_install
280 $(print_install) \ 286 $(print_install) \
@@ -290,7 +296,7 @@ install_lib: all_cmd install_plugins install_python
290install: install_lib 296install: install_lib
291 297
292clean: 298clean:
293 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d 299 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
294 $(RM) tags TAGS 300 $(RM) tags TAGS
295 301
296endif # skip-makefile 302endif # skip-makefile
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 554828219c33..5f34aa371b56 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func,
467 item->mod = NULL; 467 item->mod = NULL;
468 item->addr = addr; 468 item->addr = addr;
469 469
470 pevent->funclist = item; 470 if (!item->func || (mod && !item->mod))
471 die("malloc func");
471 472
473 pevent->funclist = item;
472 pevent->func_count++; 474 pevent->func_count++;
473 475
474 return 0; 476 return 0;
@@ -511,12 +513,12 @@ struct printk_list {
511 513
512static int printk_cmp(const void *a, const void *b) 514static int printk_cmp(const void *a, const void *b)
513{ 515{
514 const struct func_map *fa = a; 516 const struct printk_map *pa = a;
515 const struct func_map *fb = b; 517 const struct printk_map *pb = b;
516 518
517 if (fa->addr < fb->addr) 519 if (pa->addr < pb->addr)
518 return -1; 520 return -1;
519 if (fa->addr > fb->addr) 521 if (pa->addr > pb->addr)
520 return 1; 522 return 1;
521 523
522 return 0; 524 return 0;
@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
583 item = malloc_or_die(sizeof(*item)); 585 item = malloc_or_die(sizeof(*item));
584 586
585 item->next = pevent->printklist; 587 item->next = pevent->printklist;
586 pevent->printklist = item;
587 item->printk = strdup(fmt); 588 item->printk = strdup(fmt);
588 item->addr = addr; 589 item->addr = addr;
589 590
591 if (!item->printk)
592 die("malloc fmt");
593
594 pevent->printklist = item;
590 pevent->printk_count++; 595 pevent->printk_count++;
591 596
592 return 0; 597 return 0;
@@ -616,7 +621,9 @@ static struct event_format *alloc_event(void)
616{ 621{
617 struct event_format *event; 622 struct event_format *event;
618 623
619 event = malloc_or_die(sizeof(*event)); 624 event = malloc(sizeof(*event));
625 if (!event)
626 return NULL;
620 memset(event, 0, sizeof(*event)); 627 memset(event, 0, sizeof(*event));
621 628
622 return event; 629 return event;
@@ -626,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event)
626{ 633{
627 int i; 634 int i;
628 635
629 if (!pevent->events) 636 pevent->events = realloc(pevent->events, sizeof(event) *
630 pevent->events = malloc_or_die(sizeof(event)); 637 (pevent->nr_events + 1));
631 else
632 pevent->events =
633 realloc(pevent->events, sizeof(event) *
634 (pevent->nr_events + 1));
635 if (!pevent->events) 638 if (!pevent->events)
636 die("Can not allocate events"); 639 die("Can not allocate events");
637 640
@@ -697,6 +700,10 @@ static void free_arg(struct print_arg *arg)
697 free_arg(arg->symbol.field); 700 free_arg(arg->symbol.field);
698 free_flag_sym(arg->symbol.symbols); 701 free_flag_sym(arg->symbol.symbols);
699 break; 702 break;
703 case PRINT_HEX:
704 free_arg(arg->hex.field);
705 free_arg(arg->hex.size);
706 break;
700 case PRINT_TYPE: 707 case PRINT_TYPE:
701 free(arg->typecast.type); 708 free(arg->typecast.type);
702 free_arg(arg->typecast.item); 709 free_arg(arg->typecast.item);
@@ -775,6 +782,25 @@ int pevent_peek_char(void)
775 return __peek_char(); 782 return __peek_char();
776} 783}
777 784
785static int extend_token(char **tok, char *buf, int size)
786{
787 char *newtok = realloc(*tok, size);
788
789 if (!newtok) {
790 free(*tok);
791 *tok = NULL;
792 return -1;
793 }
794
795 if (!*tok)
796 strcpy(newtok, buf);
797 else
798 strcat(newtok, buf);
799 *tok = newtok;
800
801 return 0;
802}
803
778static enum event_type force_token(const char *str, char **tok); 804static enum event_type force_token(const char *str, char **tok);
779 805
780static enum event_type __read_token(char **tok) 806static enum event_type __read_token(char **tok)
@@ -859,17 +885,10 @@ static enum event_type __read_token(char **tok)
859 do { 885 do {
860 if (i == (BUFSIZ - 1)) { 886 if (i == (BUFSIZ - 1)) {
861 buf[i] = 0; 887 buf[i] = 0;
862 if (*tok) { 888 tok_size += BUFSIZ;
863 *tok = realloc(*tok, tok_size + BUFSIZ);
864 if (!*tok)
865 return EVENT_NONE;
866 strcat(*tok, buf);
867 } else
868 *tok = strdup(buf);
869 889
870 if (!*tok) 890 if (extend_token(tok, buf, tok_size) < 0)
871 return EVENT_NONE; 891 return EVENT_NONE;
872 tok_size += BUFSIZ;
873 i = 0; 892 i = 0;
874 } 893 }
875 last_ch = ch; 894 last_ch = ch;
@@ -908,17 +927,10 @@ static enum event_type __read_token(char **tok)
908 while (get_type(__peek_char()) == type) { 927 while (get_type(__peek_char()) == type) {
909 if (i == (BUFSIZ - 1)) { 928 if (i == (BUFSIZ - 1)) {
910 buf[i] = 0; 929 buf[i] = 0;
911 if (*tok) { 930 tok_size += BUFSIZ;
912 *tok = realloc(*tok, tok_size + BUFSIZ);
913 if (!*tok)
914 return EVENT_NONE;
915 strcat(*tok, buf);
916 } else
917 *tok = strdup(buf);
918 931
919 if (!*tok) 932 if (extend_token(tok, buf, tok_size) < 0)
920 return EVENT_NONE; 933 return EVENT_NONE;
921 tok_size += BUFSIZ;
922 i = 0; 934 i = 0;
923 } 935 }
924 ch = __read_char(); 936 ch = __read_char();
@@ -927,14 +939,7 @@ static enum event_type __read_token(char **tok)
927 939
928 out: 940 out:
929 buf[i] = 0; 941 buf[i] = 0;
930 if (*tok) { 942 if (extend_token(tok, buf, tok_size + i + 1) < 0)
931 *tok = realloc(*tok, tok_size + i);
932 if (!*tok)
933 return EVENT_NONE;
934 strcat(*tok, buf);
935 } else
936 *tok = strdup(buf);
937 if (!*tok)
938 return EVENT_NONE; 943 return EVENT_NONE;
939 944
940 if (type == EVENT_ITEM) { 945 if (type == EVENT_ITEM) {
@@ -1255,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1255 field->flags |= FIELD_IS_POINTER; 1260 field->flags |= FIELD_IS_POINTER;
1256 1261
1257 if (field->type) { 1262 if (field->type) {
1258 field->type = realloc(field->type, 1263 char *new_type;
1259 strlen(field->type) + 1264 new_type = realloc(field->type,
1260 strlen(last_token) + 2); 1265 strlen(field->type) +
1266 strlen(last_token) + 2);
1267 if (!new_type) {
1268 free(last_token);
1269 goto fail;
1270 }
1271 field->type = new_type;
1261 strcat(field->type, " "); 1272 strcat(field->type, " ");
1262 strcat(field->type, last_token); 1273 strcat(field->type, last_token);
1263 free(last_token); 1274 free(last_token);
@@ -1282,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1282 if (strcmp(token, "[") == 0) { 1293 if (strcmp(token, "[") == 0) {
1283 enum event_type last_type = type; 1294 enum event_type last_type = type;
1284 char *brackets = token; 1295 char *brackets = token;
1296 char *new_brackets;
1285 int len; 1297 int len;
1286 1298
1287 field->flags |= FIELD_IS_ARRAY; 1299 field->flags |= FIELD_IS_ARRAY;
@@ -1301,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1301 len = 1; 1313 len = 1;
1302 last_type = type; 1314 last_type = type;
1303 1315
1304 brackets = realloc(brackets, 1316 new_brackets = realloc(brackets,
1305 strlen(brackets) + 1317 strlen(brackets) +
1306 strlen(token) + len); 1318 strlen(token) + len);
1319 if (!new_brackets) {
1320 free(brackets);
1321 goto fail;
1322 }
1323 brackets = new_brackets;
1307 if (len == 2) 1324 if (len == 2)
1308 strcat(brackets, " "); 1325 strcat(brackets, " ");
1309 strcat(brackets, token); 1326 strcat(brackets, token);
@@ -1319,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1319 1336
1320 free_token(token); 1337 free_token(token);
1321 1338
1322 brackets = realloc(brackets, strlen(brackets) + 2); 1339 new_brackets = realloc(brackets, strlen(brackets) + 2);
1340 if (!new_brackets) {
1341 free(brackets);
1342 goto fail;
1343 }
1344 brackets = new_brackets;
1323 strcat(brackets, "]"); 1345 strcat(brackets, "]");
1324 1346
1325 /* add brackets to type */ 1347 /* add brackets to type */
@@ -1330,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1330 * the format: type [] item; 1352 * the format: type [] item;
1331 */ 1353 */
1332 if (type == EVENT_ITEM) { 1354 if (type == EVENT_ITEM) {
1333 field->type = realloc(field->type, 1355 char *new_type;
1334 strlen(field->type) + 1356 new_type = realloc(field->type,
1335 strlen(field->name) + 1357 strlen(field->type) +
1336 strlen(brackets) + 2); 1358 strlen(field->name) +
1359 strlen(brackets) + 2);
1360 if (!new_type) {
1361 free(brackets);
1362 goto fail;
1363 }
1364 field->type = new_type;
1337 strcat(field->type, " "); 1365 strcat(field->type, " ");
1338 strcat(field->type, field->name); 1366 strcat(field->type, field->name);
1339 free_token(field->name); 1367 free_token(field->name);
@@ -1341,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1341 field->name = token; 1369 field->name = token;
1342 type = read_token(&token); 1370 type = read_token(&token);
1343 } else { 1371 } else {
1344 field->type = realloc(field->type, 1372 char *new_type;
1345 strlen(field->type) + 1373 new_type = realloc(field->type,
1346 strlen(brackets) + 1); 1374 strlen(field->type) +
1375 strlen(brackets) + 1);
1376 if (!new_type) {
1377 free(brackets);
1378 goto fail;
1379 }
1380 field->type = new_type;
1347 strcat(field->type, brackets); 1381 strcat(field->type, brackets);
1348 } 1382 }
1349 free(brackets); 1383 free(brackets);
@@ -1726,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1726 /* could just be a type pointer */ 1760 /* could just be a type pointer */
1727 if ((strcmp(arg->op.op, "*") == 0) && 1761 if ((strcmp(arg->op.op, "*") == 0) &&
1728 type == EVENT_DELIM && (strcmp(token, ")") == 0)) { 1762 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1763 char *new_atom;
1764
1729 if (left->type != PRINT_ATOM) 1765 if (left->type != PRINT_ATOM)
1730 die("bad pointer type"); 1766 die("bad pointer type");
1731 left->atom.atom = realloc(left->atom.atom, 1767 new_atom = realloc(left->atom.atom,
1732 strlen(left->atom.atom) + 3); 1768 strlen(left->atom.atom) + 3);
1769 if (!new_atom)
1770 goto out_free;
1771
1772 left->atom.atom = new_atom;
1733 strcat(left->atom.atom, " *"); 1773 strcat(left->atom.atom, " *");
1734 free(arg->op.op); 1774 free(arg->op.op);
1735 *arg = *left; 1775 *arg = *left;
@@ -2146,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
2146 if (value == NULL) 2186 if (value == NULL)
2147 goto out_free; 2187 goto out_free;
2148 field->value = strdup(value); 2188 field->value = strdup(value);
2189 if (field->value == NULL)
2190 goto out_free;
2149 2191
2150 free_arg(arg); 2192 free_arg(arg);
2151 arg = alloc_arg(); 2193 arg = alloc_arg();
@@ -2159,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
2159 if (value == NULL) 2201 if (value == NULL)
2160 goto out_free; 2202 goto out_free;
2161 field->str = strdup(value); 2203 field->str = strdup(value);
2204 if (field->str == NULL)
2205 goto out_free;
2162 free_arg(arg); 2206 free_arg(arg);
2163 arg = NULL; 2207 arg = NULL;
2164 2208
@@ -2260,6 +2304,45 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
2260} 2304}
2261 2305
2262static enum event_type 2306static enum event_type
2307process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2308{
2309 struct print_arg *field;
2310 enum event_type type;
2311 char *token;
2312
2313 memset(arg, 0, sizeof(*arg));
2314 arg->type = PRINT_HEX;
2315
2316 field = alloc_arg();
2317 type = process_arg(event, field, &token);
2318
2319 if (test_type_token(type, token, EVENT_DELIM, ","))
2320 goto out_free;
2321
2322 arg->hex.field = field;
2323
2324 free_token(token);
2325
2326 field = alloc_arg();
2327 type = process_arg(event, field, &token);
2328
2329 if (test_type_token(type, token, EVENT_DELIM, ")"))
2330 goto out_free;
2331
2332 arg->hex.size = field;
2333
2334 free_token(token);
2335 type = read_token_item(tok);
2336 return type;
2337
2338 out_free:
2339 free_arg(field);
2340 free_token(token);
2341 *tok = NULL;
2342 return EVENT_ERROR;
2343}
2344
2345static enum event_type
2263process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) 2346process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
2264{ 2347{
2265 struct format_field *field; 2348 struct format_field *field;
@@ -2488,6 +2571,10 @@ process_function(struct event_format *event, struct print_arg *arg,
2488 is_symbolic_field = 1; 2571 is_symbolic_field = 1;
2489 return process_symbols(event, arg, tok); 2572 return process_symbols(event, arg, tok);
2490 } 2573 }
2574 if (strcmp(token, "__print_hex") == 0) {
2575 free_token(token);
2576 return process_hex(event, arg, tok);
2577 }
2491 if (strcmp(token, "__get_str") == 0) { 2578 if (strcmp(token, "__get_str") == 0) {
2492 free_token(token); 2579 free_token(token);
2493 return process_str(event, arg, tok); 2580 return process_str(event, arg, tok);
@@ -2541,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
2541 } 2628 }
2542 /* atoms can be more than one token long */ 2629 /* atoms can be more than one token long */
2543 while (type == EVENT_ITEM) { 2630 while (type == EVENT_ITEM) {
2544 atom = realloc(atom, strlen(atom) + strlen(token) + 2); 2631 char *new_atom;
2632 new_atom = realloc(atom,
2633 strlen(atom) + strlen(token) + 2);
2634 if (!new_atom) {
2635 free(atom);
2636 *tok = NULL;
2637 free_token(token);
2638 return EVENT_ERROR;
2639 }
2640 atom = new_atom;
2545 strcat(atom, " "); 2641 strcat(atom, " ");
2546 strcat(atom, token); 2642 strcat(atom, token);
2547 free_token(token); 2643 free_token(token);
@@ -2835,7 +2931,7 @@ static int get_common_info(struct pevent *pevent,
2835 event = pevent->events[0]; 2931 event = pevent->events[0];
2836 field = pevent_find_common_field(event, type); 2932 field = pevent_find_common_field(event, type);
2837 if (!field) 2933 if (!field)
2838 die("field '%s' not found", type); 2934 return -1;
2839 2935
2840 *offset = field->offset; 2936 *offset = field->offset;
2841 *size = field->size; 2937 *size = field->size;
@@ -2886,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data)
2886 2982
2887static int parse_common_lock_depth(struct pevent *pevent, void *data) 2983static int parse_common_lock_depth(struct pevent *pevent, void *data)
2888{ 2984{
2889 int ret; 2985 return __parse_common(pevent, data,
2890 2986 &pevent->ld_size, &pevent->ld_offset,
2891 ret = __parse_common(pevent, data, 2987 "common_lock_depth");
2892 &pevent->ld_size, &pevent->ld_offset, 2988}
2893 "common_lock_depth");
2894 if (ret < 0)
2895 return -1;
2896 2989
2897 return ret; 2990static int parse_common_migrate_disable(struct pevent *pevent, void *data)
2991{
2992 return __parse_common(pevent, data,
2993 &pevent->ld_size, &pevent->ld_offset,
2994 "common_migrate_disable");
2898} 2995}
2899 2996
2900static int events_id_cmp(const void *a, const void *b); 2997static int events_id_cmp(const void *a, const void *b);
@@ -2995,6 +3092,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
2995 break; 3092 break;
2996 case PRINT_FLAGS: 3093 case PRINT_FLAGS:
2997 case PRINT_SYMBOL: 3094 case PRINT_SYMBOL:
3095 case PRINT_HEX:
2998 break; 3096 break;
2999 case PRINT_TYPE: 3097 case PRINT_TYPE:
3000 val = eval_num_arg(data, size, event, arg->typecast.item); 3098 val = eval_num_arg(data, size, event, arg->typecast.item);
@@ -3214,11 +3312,13 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3214{ 3312{
3215 struct pevent *pevent = event->pevent; 3313 struct pevent *pevent = event->pevent;
3216 struct print_flag_sym *flag; 3314 struct print_flag_sym *flag;
3315 struct format_field *field;
3217 unsigned long long val, fval; 3316 unsigned long long val, fval;
3218 unsigned long addr; 3317 unsigned long addr;
3219 char *str; 3318 char *str;
3319 unsigned char *hex;
3220 int print; 3320 int print;
3221 int len; 3321 int i, len;
3222 3322
3223 switch (arg->type) { 3323 switch (arg->type) {
3224 case PRINT_NULL: 3324 case PRINT_NULL:
@@ -3228,27 +3328,29 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3228 print_str_to_seq(s, format, len_arg, arg->atom.atom); 3328 print_str_to_seq(s, format, len_arg, arg->atom.atom);
3229 return; 3329 return;
3230 case PRINT_FIELD: 3330 case PRINT_FIELD:
3231 if (!arg->field.field) { 3331 field = arg->field.field;
3232 arg->field.field = pevent_find_any_field(event, arg->field.name); 3332 if (!field) {
3233 if (!arg->field.field) 3333 field = pevent_find_any_field(event, arg->field.name);
3334 if (!field)
3234 die("field %s not found", arg->field.name); 3335 die("field %s not found", arg->field.name);
3336 arg->field.field = field;
3235 } 3337 }
3236 /* Zero sized fields, mean the rest of the data */ 3338 /* Zero sized fields, mean the rest of the data */
3237 len = arg->field.field->size ? : size - arg->field.field->offset; 3339 len = field->size ? : size - field->offset;
3238 3340
3239 /* 3341 /*
3240 * Some events pass in pointers. If this is not an array 3342 * Some events pass in pointers. If this is not an array
3241 * and the size is the same as long_size, assume that it 3343 * and the size is the same as long_size, assume that it
3242 * is a pointer. 3344 * is a pointer.
3243 */ 3345 */
3244 if (!(arg->field.field->flags & FIELD_IS_ARRAY) && 3346 if (!(field->flags & FIELD_IS_ARRAY) &&
3245 arg->field.field->size == pevent->long_size) { 3347 field->size == pevent->long_size) {
3246 addr = *(unsigned long *)(data + arg->field.field->offset); 3348 addr = *(unsigned long *)(data + field->offset);
3247 trace_seq_printf(s, "%lx", addr); 3349 trace_seq_printf(s, "%lx", addr);
3248 break; 3350 break;
3249 } 3351 }
3250 str = malloc_or_die(len + 1); 3352 str = malloc_or_die(len + 1);
3251 memcpy(str, data + arg->field.field->offset, len); 3353 memcpy(str, data + field->offset, len);
3252 str[len] = 0; 3354 str[len] = 0;
3253 print_str_to_seq(s, format, len_arg, str); 3355 print_str_to_seq(s, format, len_arg, str);
3254 free(str); 3356 free(str);
@@ -3281,6 +3383,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3281 } 3383 }
3282 } 3384 }
3283 break; 3385 break;
3386 case PRINT_HEX:
3387 field = arg->hex.field->field.field;
3388 if (!field) {
3389 str = arg->hex.field->field.name;
3390 field = pevent_find_any_field(event, str);
3391 if (!field)
3392 die("field %s not found", str);
3393 arg->hex.field->field.field = field;
3394 }
3395 hex = data + field->offset;
3396 len = eval_num_arg(data, size, event, arg->hex.size);
3397 for (i = 0; i < len; i++) {
3398 if (i)
3399 trace_seq_putc(s, ' ');
3400 trace_seq_printf(s, "%02x", hex[i]);
3401 }
3402 break;
3284 3403
3285 case PRINT_TYPE: 3404 case PRINT_TYPE:
3286 break; 3405 break;
@@ -3299,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3299 break; 3418 break;
3300 } 3419 }
3301 case PRINT_BSTRING: 3420 case PRINT_BSTRING:
3302 trace_seq_printf(s, format, arg->string.string); 3421 print_str_to_seq(s, format, len_arg, arg->string.string);
3303 break; 3422 break;
3304 case PRINT_OP: 3423 case PRINT_OP:
3305 /* 3424 /*
@@ -3363,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size,
3363 string = malloc_or_die(sizeof(*string)); 3482 string = malloc_or_die(sizeof(*string));
3364 string->next = strings; 3483 string->next = strings;
3365 string->str = strdup(str.buffer); 3484 string->str = strdup(str.buffer);
3485 if (!string->str)
3486 die("malloc str");
3487
3488 args[i] = (unsigned long long)string->str;
3366 strings = string; 3489 strings = string;
3367 trace_seq_destroy(&str); 3490 trace_seq_destroy(&str);
3368 break; 3491 break;
@@ -3400,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3400 unsigned long long ip, val; 3523 unsigned long long ip, val;
3401 char *ptr; 3524 char *ptr;
3402 void *bptr; 3525 void *bptr;
3526 int vsize;
3403 3527
3404 field = pevent->bprint_buf_field; 3528 field = pevent->bprint_buf_field;
3405 ip_field = pevent->bprint_ip_field; 3529 ip_field = pevent->bprint_ip_field;
@@ -3448,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3448 goto process_again; 3572 goto process_again;
3449 case '0' ... '9': 3573 case '0' ... '9':
3450 goto process_again; 3574 goto process_again;
3575 case '.':
3576 goto process_again;
3451 case 'p': 3577 case 'p':
3452 ls = 1; 3578 ls = 1;
3453 /* fall through */ 3579 /* fall through */
@@ -3455,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3455 case 'u': 3581 case 'u':
3456 case 'x': 3582 case 'x':
3457 case 'i': 3583 case 'i':
3458 /* the pointers are always 4 bytes aligned */
3459 bptr = (void *)(((unsigned long)bptr + 3) &
3460 ~3);
3461 switch (ls) { 3584 switch (ls) {
3462 case 0: 3585 case 0:
3463 ls = 4; 3586 vsize = 4;
3464 break; 3587 break;
3465 case 1: 3588 case 1:
3466 ls = pevent->long_size; 3589 vsize = pevent->long_size;
3467 break; 3590 break;
3468 case 2: 3591 case 2:
3469 ls = 8; 3592 vsize = 8;
3593 break;
3470 default: 3594 default:
3595 vsize = ls; /* ? */
3471 break; 3596 break;
3472 } 3597 }
3473 val = pevent_read_number(pevent, bptr, ls); 3598 /* fall through */
3474 bptr += ls; 3599 case '*':
3600 if (*ptr == '*')
3601 vsize = 4;
3602
3603 /* the pointers are always 4 bytes aligned */
3604 bptr = (void *)(((unsigned long)bptr + 3) &
3605 ~3);
3606 val = pevent_read_number(pevent, bptr, vsize);
3607 bptr += vsize;
3475 arg = alloc_arg(); 3608 arg = alloc_arg();
3476 arg->next = NULL; 3609 arg->next = NULL;
3477 arg->type = PRINT_ATOM; 3610 arg->type = PRINT_ATOM;
@@ -3479,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3479 sprintf(arg->atom.atom, "%lld", val); 3612 sprintf(arg->atom.atom, "%lld", val);
3480 *next = arg; 3613 *next = arg;
3481 next = &arg->next; 3614 next = &arg->next;
3615 /*
3616 * The '*' case means that an arg is used as the length.
3617 * We need to continue to figure out for what.
3618 */
3619 if (*ptr == '*')
3620 goto process_again;
3621
3482 break; 3622 break;
3483 case 's': 3623 case 's':
3484 arg = alloc_arg(); 3624 arg = alloc_arg();
3485 arg->next = NULL; 3625 arg->next = NULL;
3486 arg->type = PRINT_BSTRING; 3626 arg->type = PRINT_BSTRING;
3487 arg->string.string = strdup(bptr); 3627 arg->string.string = strdup(bptr);
3628 if (!arg->string.string)
3629 break;
3488 bptr += strlen(bptr) + 1; 3630 bptr += strlen(bptr) + 1;
3489 *next = arg; 3631 *next = arg;
3490 next = &arg->next; 3632 next = &arg->next;
@@ -3589,6 +3731,16 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
3589 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 3731 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
3590} 3732}
3591 3733
3734static int is_printable_array(char *p, unsigned int len)
3735{
3736 unsigned int i;
3737
3738 for (i = 0; i < len && p[i]; i++)
3739 if (!isprint(p[i]))
3740 return 0;
3741 return 1;
3742}
3743
3592static void print_event_fields(struct trace_seq *s, void *data, int size, 3744static void print_event_fields(struct trace_seq *s, void *data, int size,
3593 struct event_format *event) 3745 struct event_format *event)
3594{ 3746{
@@ -3608,7 +3760,8 @@ static void print_event_fields(struct trace_seq *s, void *data, int size,
3608 len = offset >> 16; 3760 len = offset >> 16;
3609 offset &= 0xffff; 3761 offset &= 0xffff;
3610 } 3762 }
3611 if (field->flags & FIELD_IS_STRING) { 3763 if (field->flags & FIELD_IS_STRING &&
3764 is_printable_array(data + offset, len)) {
3612 trace_seq_printf(s, "%s", (char *)data + offset); 3765 trace_seq_printf(s, "%s", (char *)data + offset);
3613 } else { 3766 } else {
3614 trace_seq_puts(s, "ARRAY["); 3767 trace_seq_puts(s, "ARRAY[");
@@ -3619,6 +3772,7 @@ static void print_event_fields(struct trace_seq *s, void *data, int size,
3619 *((unsigned char *)data + offset + i)); 3772 *((unsigned char *)data + offset + i));
3620 } 3773 }
3621 trace_seq_putc(s, ']'); 3774 trace_seq_putc(s, ']');
3775 field->flags &= ~FIELD_IS_STRING;
3622 } 3776 }
3623 } else { 3777 } else {
3624 val = pevent_read_number(event->pevent, data + field->offset, 3778 val = pevent_read_number(event->pevent, data + field->offset,
@@ -3758,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
3758 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { 3912 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
3759 print_mac_arg(s, *(ptr+1), data, size, event, arg); 3913 print_mac_arg(s, *(ptr+1), data, size, event, arg);
3760 ptr++; 3914 ptr++;
3915 arg = arg->next;
3761 break; 3916 break;
3762 } 3917 }
3763 3918
@@ -3794,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
3794 break; 3949 break;
3795 } 3950 }
3796 } 3951 }
3797 if (pevent->long_size == 8 && ls) { 3952 if (pevent->long_size == 8 && ls &&
3953 sizeof(long) != 8) {
3798 char *p; 3954 char *p;
3799 3955
3800 ls = 2; 3956 ls = 2;
3801 /* make %l into %ll */ 3957 /* make %l into %ll */
3802 p = strchr(format, 'l'); 3958 p = strchr(format, 'l');
3803 if (p) 3959 if (p)
3804 memmove(p, p+1, strlen(p)+1); 3960 memmove(p+1, p, strlen(p)+1);
3805 else if (strcmp(format, "%p") == 0) 3961 else if (strcmp(format, "%p") == 0)
3806 strcpy(format, "0x%llx"); 3962 strcpy(format, "0x%llx");
3807 } 3963 }
@@ -3878,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
3878 * pevent_data_lat_fmt - parse the data for the latency format 4034 * pevent_data_lat_fmt - parse the data for the latency format
3879 * @pevent: a handle to the pevent 4035 * @pevent: a handle to the pevent
3880 * @s: the trace_seq to write to 4036 * @s: the trace_seq to write to
3881 * @data: the raw data to read from 4037 * @record: the record to read from
3882 * @size: currently unused.
3883 * 4038 *
3884 * This parses out the Latency format (interrupts disabled, 4039 * This parses out the Latency format (interrupts disabled,
3885 * need rescheduling, in hard/soft interrupt, preempt count 4040 * need rescheduling, in hard/soft interrupt, preempt count
@@ -3889,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
3889 struct trace_seq *s, struct pevent_record *record) 4044 struct trace_seq *s, struct pevent_record *record)
3890{ 4045{
3891 static int check_lock_depth = 1; 4046 static int check_lock_depth = 1;
4047 static int check_migrate_disable = 1;
3892 static int lock_depth_exists; 4048 static int lock_depth_exists;
4049 static int migrate_disable_exists;
3893 unsigned int lat_flags; 4050 unsigned int lat_flags;
3894 unsigned int pc; 4051 unsigned int pc;
3895 int lock_depth; 4052 int lock_depth;
4053 int migrate_disable;
3896 int hardirq; 4054 int hardirq;
3897 int softirq; 4055 int softirq;
3898 void *data = record->data; 4056 void *data = record->data;
@@ -3900,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent,
3900 lat_flags = parse_common_flags(pevent, data); 4058 lat_flags = parse_common_flags(pevent, data);
3901 pc = parse_common_pc(pevent, data); 4059 pc = parse_common_pc(pevent, data);
3902 /* lock_depth may not always exist */ 4060 /* lock_depth may not always exist */
3903 if (check_lock_depth) {
3904 struct format_field *field;
3905 struct event_format *event;
3906
3907 check_lock_depth = 0;
3908 event = pevent->events[0];
3909 field = pevent_find_common_field(event, "common_lock_depth");
3910 if (field)
3911 lock_depth_exists = 1;
3912 }
3913 if (lock_depth_exists) 4061 if (lock_depth_exists)
3914 lock_depth = parse_common_lock_depth(pevent, data); 4062 lock_depth = parse_common_lock_depth(pevent, data);
4063 else if (check_lock_depth) {
4064 lock_depth = parse_common_lock_depth(pevent, data);
4065 if (lock_depth < 0)
4066 check_lock_depth = 0;
4067 else
4068 lock_depth_exists = 1;
4069 }
4070
4071 /* migrate_disable may not always exist */
4072 if (migrate_disable_exists)
4073 migrate_disable = parse_common_migrate_disable(pevent, data);
4074 else if (check_migrate_disable) {
4075 migrate_disable = parse_common_migrate_disable(pevent, data);
4076 if (migrate_disable < 0)
4077 check_migrate_disable = 0;
4078 else
4079 migrate_disable_exists = 1;
4080 }
3915 4081
3916 hardirq = lat_flags & TRACE_FLAG_HARDIRQ; 4082 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
3917 softirq = lat_flags & TRACE_FLAG_SOFTIRQ; 4083 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
@@ -3930,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
3930 else 4096 else
3931 trace_seq_putc(s, '.'); 4097 trace_seq_putc(s, '.');
3932 4098
4099 if (migrate_disable_exists) {
4100 if (migrate_disable < 0)
4101 trace_seq_putc(s, '.');
4102 else
4103 trace_seq_printf(s, "%d", migrate_disable);
4104 }
4105
3933 if (lock_depth_exists) { 4106 if (lock_depth_exists) {
3934 if (lock_depth < 0) 4107 if (lock_depth < 0)
3935 trace_seq_putc(s, '.'); 4108 trace_seq_putc(s, '.');
@@ -3996,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
3996 * pevent_data_comm_from_pid - parse the data into the print format 4169 * pevent_data_comm_from_pid - parse the data into the print format
3997 * @s: the trace_seq to write to 4170 * @s: the trace_seq to write to
3998 * @event: the handle to the event 4171 * @event: the handle to the event
3999 * @cpu: the cpu the event was recorded on 4172 * @record: the record to read from
4000 * @data: the raw data
4001 * @size: the size of the raw data
4002 * @nsecs: the timestamp of the event
4003 * 4173 *
4004 * This parses the raw @data using the given @event information and 4174 * This parses the raw @data using the given @event information and
4005 * writes the print format into the trace_seq. 4175 * writes the print format into the trace_seq.
@@ -4279,6 +4449,13 @@ static void print_args(struct print_arg *args)
4279 trace_seq_destroy(&s); 4449 trace_seq_destroy(&s);
4280 printf(")"); 4450 printf(")");
4281 break; 4451 break;
4452 case PRINT_HEX:
4453 printf("__print_hex(");
4454 print_args(args->hex.field);
4455 printf(", ");
4456 print_args(args->hex.size);
4457 printf(")");
4458 break;
4282 case PRINT_STRING: 4459 case PRINT_STRING:
4283 case PRINT_BSTRING: 4460 case PRINT_BSTRING:
4284 printf("__get_str(%s)", args->string.string); 4461 printf("__get_str(%s)", args->string.string);
@@ -4541,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent,
4541 die("failed to read event id"); 4718 die("failed to read event id");
4542 4719
4543 event->system = strdup(sys); 4720 event->system = strdup(sys);
4721 if (!event->system)
4722 die("failed to allocate system");
4544 4723
4545 /* Add pevent to event so that it can be referenced */ 4724 /* Add pevent to event so that it can be referenced */
4546 event->pevent = pevent; 4725 event->pevent = pevent;
@@ -4582,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent,
4582 list = &arg->next; 4761 list = &arg->next;
4583 arg->type = PRINT_FIELD; 4762 arg->type = PRINT_FIELD;
4584 arg->field.name = strdup(field->name); 4763 arg->field.name = strdup(field->name);
4764 if (!arg->field.name) {
4765 do_warning("failed to allocate field name");
4766 event->flags |= EVENT_FL_FAILED;
4767 return -1;
4768 }
4585 arg->field.field = field; 4769 arg->field.field = field;
4586 } 4770 }
4587 return 0; 4771 return 0;
@@ -4753,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
4753 * @record: The record with the field name. 4937 * @record: The record with the field name.
4754 * @err: print default error if failed. 4938 * @err: print default error if failed.
4755 * 4939 *
4756 * Returns: 0 on success, -1 field not fould, or 1 if buffer is full. 4940 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
4757 */ 4941 */
4758int pevent_print_num_field(struct trace_seq *s, const char *fmt, 4942int pevent_print_num_field(struct trace_seq *s, const char *fmt,
4759 struct event_format *event, const char *name, 4943 struct event_format *event, const char *name,
@@ -4795,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func)
4795 * pevent_register_print_function - register a helper function 4979 * pevent_register_print_function - register a helper function
4796 * @pevent: the handle to the pevent 4980 * @pevent: the handle to the pevent
4797 * @func: the function to process the helper function 4981 * @func: the function to process the helper function
4982 * @ret_type: the return type of the helper function
4798 * @name: the name of the helper function 4983 * @name: the name of the helper function
4799 * @parameters: A list of enum pevent_func_arg_type 4984 * @parameters: A list of enum pevent_func_arg_type
4800 * 4985 *
4801 * Some events may have helper functions in the print format arguments. 4986 * Some events may have helper functions in the print format arguments.
4802 * This allows a plugin to dynmically create a way to process one 4987 * This allows a plugin to dynamically create a way to process one
4803 * of these functions. 4988 * of these functions.
4804 * 4989 *
4805 * The @parameters is a variable list of pevent_func_arg_type enums that 4990 * The @parameters is a variable list of pevent_func_arg_type enums that
@@ -4870,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent,
4870} 5055}
4871 5056
4872/** 5057/**
4873 * pevent_register_event_handle - register a way to parse an event 5058 * pevent_register_event_handler - register a way to parse an event
4874 * @pevent: the handle to the pevent 5059 * @pevent: the handle to the pevent
4875 * @id: the id of the event to register 5060 * @id: the id of the event to register
4876 * @sys_name: the system name the event belongs to 5061 * @sys_name: the system name the event belongs to
4877 * @event_name: the name of the event 5062 * @event_name: the name of the event
4878 * @func: the function to call to parse the event information 5063 * @func: the function to call to parse the event information
5064 * @context: the data to be passed to @func
4879 * 5065 *
4880 * This function allows a developer to override the parsing of 5066 * This function allows a developer to override the parsing of
4881 * a given event. If for some reason the default print format 5067 * a given event. If for some reason the default print format
@@ -4925,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent,
4925 if (sys_name) 5111 if (sys_name)
4926 handle->sys_name = strdup(sys_name); 5112 handle->sys_name = strdup(sys_name);
4927 5113
5114 if ((event_name && !handle->event_name) ||
5115 (sys_name && !handle->sys_name)) {
5116 die("Failed to allocate event/sys name");
5117 }
5118
4928 handle->func = func; 5119 handle->func = func;
4929 handle->next = pevent->handlers; 5120 handle->next = pevent->handlers;
4930 pevent->handlers = handle; 5121 pevent->handlers = handle;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index ac997bc7b592..5772ad8cb386 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -226,6 +226,11 @@ struct print_arg_symbol {
226 struct print_flag_sym *symbols; 226 struct print_flag_sym *symbols;
227}; 227};
228 228
229struct print_arg_hex {
230 struct print_arg *field;
231 struct print_arg *size;
232};
233
229struct print_arg_dynarray { 234struct print_arg_dynarray {
230 struct format_field *field; 235 struct format_field *field;
231 struct print_arg *index; 236 struct print_arg *index;
@@ -253,6 +258,7 @@ enum print_arg_type {
253 PRINT_FIELD, 258 PRINT_FIELD,
254 PRINT_FLAGS, 259 PRINT_FLAGS,
255 PRINT_SYMBOL, 260 PRINT_SYMBOL,
261 PRINT_HEX,
256 PRINT_TYPE, 262 PRINT_TYPE,
257 PRINT_STRING, 263 PRINT_STRING,
258 PRINT_BSTRING, 264 PRINT_BSTRING,
@@ -270,6 +276,7 @@ struct print_arg {
270 struct print_arg_typecast typecast; 276 struct print_arg_typecast typecast;
271 struct print_arg_flags flags; 277 struct print_arg_flags flags;
272 struct print_arg_symbol symbol; 278 struct print_arg_symbol symbol;
279 struct print_arg_hex hex;
273 struct print_arg_func func; 280 struct print_arg_func func;
274 struct print_arg_string string; 281 struct print_arg_string string;
275 struct print_arg_op op; 282 struct print_arg_op op;
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index dfcfe2c131de..ad17855528f9 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok)
96 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && 96 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
97 pevent_peek_char() == '~') { 97 pevent_peek_char() == '~') {
98 /* append it */ 98 /* append it */
99 *tok = malloc(3); 99 *tok = malloc_or_die(3);
100 sprintf(*tok, "%c%c", *token, '~'); 100 sprintf(*tok, "%c%c", *token, '~');
101 free_token(token); 101 free_token(token);
102 /* Now remove the '~' from the buffer */ 102 /* Now remove the '~' from the buffer */
@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id)
148 if (filter_type) 148 if (filter_type)
149 return filter_type; 149 return filter_type;
150 150
151 if (!filter->filters) 151 filter->event_filters = realloc(filter->event_filters,
152 filter->event_filters = 152 sizeof(*filter->event_filters) *
153 malloc_or_die(sizeof(*filter->event_filters)); 153 (filter->filters + 1));
154 else { 154 if (!filter->event_filters)
155 filter->event_filters = 155 die("Could not allocate filter");
156 realloc(filter->event_filters,
157 sizeof(*filter->event_filters) *
158 (filter->filters + 1));
159 if (!filter->event_filters)
160 die("Could not allocate filter");
161 }
162 156
163 for (i = 0; i < filter->filters; i++) { 157 for (i = 0; i < filter->filters; i++) {
164 if (filter->event_filters[i].event_id > id) 158 if (filter->event_filters[i].event_id > id)
@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
1480{ 1474{
1481 struct filter_type *filter_type; 1475 struct filter_type *filter_type;
1482 int count = 0; 1476 int count = 0;
1483 int *ids; 1477 int *ids = NULL;
1484 int i; 1478 int i;
1485 1479
1486 if (!filter->filters) 1480 if (!filter->filters)
@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
1504 default: 1498 default:
1505 break; 1499 break;
1506 } 1500 }
1507 if (count) 1501
1508 ids = realloc(ids, sizeof(*ids) * (count + 1)); 1502 ids = realloc(ids, sizeof(*ids) * (count + 1));
1509 else
1510 ids = malloc(sizeof(*ids));
1511 if (!ids) 1503 if (!ids)
1512 die("Can't allocate ids"); 1504 die("Can't allocate ids");
1513 ids[count++] = filter_type->event_id; 1505 ids[count++] = filter_type->event_id;
@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event,
1710 1702
1711static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) 1703static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
1712{ 1704{
1713 const char *val = record->data + arg->str.field->offset; 1705 struct event_format *event;
1706 struct pevent *pevent;
1707 unsigned long long addr;
1708 const char *val = NULL;
1709 char hex[64];
1714 1710
1715 /* 1711 /* If the field is not a string convert it */
1716 * We need to copy the data since we can't be sure the field 1712 if (arg->str.field->flags & FIELD_IS_STRING) {
1717 * is null terminated. 1713 val = record->data + arg->str.field->offset;
1718 */ 1714
1719 if (*(val + arg->str.field->size - 1)) { 1715 /*
1720 /* copy it */ 1716 * We need to copy the data since we can't be sure the field
1721 memcpy(arg->str.buffer, val, arg->str.field->size); 1717 * is null terminated.
1722 /* the buffer is already NULL terminated */ 1718 */
1723 val = arg->str.buffer; 1719 if (*(val + arg->str.field->size - 1)) {
1720 /* copy it */
1721 memcpy(arg->str.buffer, val, arg->str.field->size);
1722 /* the buffer is already NULL terminated */
1723 val = arg->str.buffer;
1724 }
1725
1726 } else {
1727 event = arg->str.field->event;
1728 pevent = event->pevent;
1729 addr = get_value(event, arg->str.field, record);
1730
1731 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
1732 /* convert to a kernel symbol */
1733 val = pevent_find_function(pevent, addr);
1734
1735 if (val == NULL) {
1736 /* just use the hex of the string name */
1737 snprintf(hex, 64, "0x%llx", addr);
1738 val = hex;
1739 }
1724 } 1740 }
1741
1725 return val; 1742 return val;
1726} 1743}
1727 1744
@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2001 char *lstr; 2018 char *lstr;
2002 char *rstr; 2019 char *rstr;
2003 char *op; 2020 char *op;
2004 char *str; 2021 char *str = NULL;
2005 int len; 2022 int len;
2006 2023
2007 lstr = arg_to_str(filter, arg->exp.left); 2024 lstr = arg_to_str(filter, arg->exp.left);
2008 rstr = arg_to_str(filter, arg->exp.right); 2025 rstr = arg_to_str(filter, arg->exp.right);
2026 if (!lstr || !rstr)
2027 goto out;
2009 2028
2010 switch (arg->exp.type) { 2029 switch (arg->exp.type) {
2011 case FILTER_EXP_ADD: 2030 case FILTER_EXP_ADD:
@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2045 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; 2064 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
2046 str = malloc_or_die(len); 2065 str = malloc_or_die(len);
2047 snprintf(str, len, "%s %s %s", lstr, op, rstr); 2066 snprintf(str, len, "%s %s %s", lstr, op, rstr);
2067out:
2048 free(lstr); 2068 free(lstr);
2049 free(rstr); 2069 free(rstr);
2050 2070
@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2061 2081
2062 lstr = arg_to_str(filter, arg->num.left); 2082 lstr = arg_to_str(filter, arg->num.left);
2063 rstr = arg_to_str(filter, arg->num.right); 2083 rstr = arg_to_str(filter, arg->num.right);
2084 if (!lstr || !rstr)
2085 goto out;
2064 2086
2065 switch (arg->num.type) { 2087 switch (arg->num.type) {
2066 case FILTER_CMP_EQ: 2088 case FILTER_CMP_EQ:
@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2097 break; 2119 break;
2098 } 2120 }
2099 2121
2122out:
2100 free(lstr); 2123 free(lstr);
2101 free(rstr); 2124 free(rstr);
2102 return str; 2125 return str;
@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil
2247 /* The best way to compare complex filters is with strings */ 2270 /* The best way to compare complex filters is with strings */
2248 str1 = arg_to_str(filter1, filter_type1->filter); 2271 str1 = arg_to_str(filter1, filter_type1->filter);
2249 str2 = arg_to_str(filter2, filter_type2->filter); 2272 str2 = arg_to_str(filter2, filter_type2->filter);
2250 result = strcmp(str1, str2) != 0; 2273 if (str1 && str2)
2274 result = strcmp(str1, str2) != 0;
2275 else
2276 /* bail out if allocation fails */
2277 result = 1;
2278
2251 free(str1); 2279 free(str1);
2252 free(str2); 2280 free(str2);
2253 if (result) 2281 if (result)
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index a3dbadb26ef5..7065cd6fbdfc 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -12,7 +12,7 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This 'perf bench' command is general framework for benchmark suites. 15This 'perf bench' command is a general framework for benchmark suites.
16 16
17COMMON OPTIONS 17COMMON OPTIONS
18-------------- 18--------------
@@ -45,14 +45,20 @@ SUBSYSTEM
45'sched':: 45'sched'::
46 Scheduler and IPC mechanisms. 46 Scheduler and IPC mechanisms.
47 47
48'mem'::
49 Memory access performance.
50
51'all'::
52 All benchmark subsystems.
53
48SUITES FOR 'sched' 54SUITES FOR 'sched'
49~~~~~~~~~~~~~~~~~~ 55~~~~~~~~~~~~~~~~~~
50*messaging*:: 56*messaging*::
51Suite for evaluating performance of scheduler and IPC mechanisms. 57Suite for evaluating performance of scheduler and IPC mechanisms.
52Based on hackbench by Rusty Russell. 58Based on hackbench by Rusty Russell.
53 59
54Options of *pipe* 60Options of *messaging*
55^^^^^^^^^^^^^^^^^ 61^^^^^^^^^^^^^^^^^^^^^^
56-p:: 62-p::
57--pipe:: 63--pipe::
58Use pipe() instead of socketpair() 64Use pipe() instead of socketpair()
@@ -115,6 +121,72 @@ Example of *pipe*
115 59004 ops/sec 121 59004 ops/sec
116--------------------- 122---------------------
117 123
124SUITES FOR 'mem'
125~~~~~~~~~~~~~~~~
126*memcpy*::
127Suite for evaluating performance of simple memory copy in various ways.
128
129Options of *memcpy*
130^^^^^^^^^^^^^^^^^^^
131-l::
132--length::
133Specify length of memory to copy (default: 1MB).
134Available units are B, KB, MB, GB and TB (case insensitive).
135
136-r::
137--routine::
138Specify routine to copy (default: default).
139Available routines are depend on the architecture.
140On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
141
142-i::
143--iterations::
144Repeat memcpy invocation this number of times.
145
146-c::
147--cycle::
148Use perf's cpu-cycles event instead of gettimeofday syscall.
149
150-o::
151--only-prefault::
152Show only the result with page faults before memcpy.
153
154-n::
155--no-prefault::
156Show only the result without page faults before memcpy.
157
158*memset*::
159Suite for evaluating performance of simple memory set in various ways.
160
161Options of *memset*
162^^^^^^^^^^^^^^^^^^^
163-l::
164--length::
165Specify length of memory to set (default: 1MB).
166Available units are B, KB, MB, GB and TB (case insensitive).
167
168-r::
169--routine::
170Specify routine to set (default: default).
171Available routines are depend on the architecture.
172On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
173
174-i::
175--iterations::
176Repeat memset invocation this number of times.
177
178-c::
179--cycle::
180Use perf's cpu-cycles event instead of gettimeofday syscall.
181
182-o::
183--only-prefault::
184Show only the result with page faults before memset.
185
186-n::
187--no-prefault::
188Show only the result without page faults before memset.
189
118SEE ALSO 190SEE ALSO
119-------- 191--------
120linkperf:perf[1] 192linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 2d89f02719b5..495210a612c4 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -57,7 +57,7 @@ OPTIONS
57 57
58-s:: 58-s::
59--sort=:: 59--sort=::
60 Sort by key(s): pid, comm, dso, symbol, parent. 60 Sort by key(s): pid, comm, dso, symbol, parent, srcline.
61 61
62-p:: 62-p::
63--parent=<regex>:: 63--parent=<regex>::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 4a5680cb242e..5b80d84d6b4a 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -112,7 +112,7 @@ Default is to monitor all CPUS.
112 112
113-s:: 113-s::
114--sort:: 114--sort::
115 Sort by key(s): pid, comm, dso, symbol, parent 115 Sort by key(s): pid, comm, dso, symbol, parent, srcline.
116 116
117-n:: 117-n::
118--show-nr-samples:: 118--show-nr-samples::
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 0eee64cfe9a0..75d74e5db8d5 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -155,7 +155,7 @@ endif
155 155
156### --- END CONFIGURATION SECTION --- 156### --- END CONFIGURATION SECTION ---
157 157
158BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 158BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
159BASIC_LDFLAGS = 159BASIC_LDFLAGS =
160 160
161# Guard against environment variables 161# Guard against environment variables
@@ -503,6 +503,7 @@ else
503 LIB_OBJS += $(OUTPUT)ui/progress.o 503 LIB_OBJS += $(OUTPUT)ui/progress.o
504 LIB_OBJS += $(OUTPUT)ui/util.o 504 LIB_OBJS += $(OUTPUT)ui/util.o
505 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 505 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
506 LIB_OBJS += $(OUTPUT)ui/tui/util.o
506 LIB_H += ui/browser.h 507 LIB_H += ui/browser.h
507 LIB_H += ui/browsers/map.h 508 LIB_H += ui/browsers/map.h
508 LIB_H += ui/helpline.h 509 LIB_H += ui/helpline.h
@@ -522,13 +523,18 @@ else
522 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 523 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
523 BASIC_CFLAGS += -DNO_GTK2_SUPPORT 524 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
524 else 525 else
526 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
527 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
528 endif
525 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0) 529 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
526 EXTLIBS += $(shell pkg-config --libs gtk+-2.0) 530 EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
527 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o 531 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
528 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o 532 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
533 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
529 # Make sure that it'd be included only once. 534 # Make sure that it'd be included only once.
530 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),) 535 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
531 LIB_OBJS += $(OUTPUT)ui/setup.o 536 LIB_OBJS += $(OUTPUT)ui/setup.o
537 LIB_OBJS += $(OUTPUT)ui/util.o
532 endif 538 endif
533 endif 539 endif
534endif 540endif
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 71557225bf92..02dad5d3359b 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -24,21 +24,21 @@
24static const char *length_str = "1MB"; 24static const char *length_str = "1MB";
25static const char *routine = "default"; 25static const char *routine = "default";
26static int iterations = 1; 26static int iterations = 1;
27static bool use_clock; 27static bool use_cycle;
28static int clock_fd; 28static int cycle_fd;
29static bool only_prefault; 29static bool only_prefault;
30static bool no_prefault; 30static bool no_prefault;
31 31
32static const struct option options[] = { 32static const struct option options[] = {
33 OPT_STRING('l', "length", &length_str, "1MB", 33 OPT_STRING('l', "length", &length_str, "1MB",
34 "Specify length of memory to copy. " 34 "Specify length of memory to copy. "
35 "available unit: B, MB, GB (upper and lower)"), 35 "Available units: B, KB, MB, GB and TB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 37 "Specify routine to copy"),
38 OPT_INTEGER('i', "iterations", &iterations, 38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memcpy() invocation this number of times"), 39 "repeat memcpy() invocation this number of times"),
40 OPT_BOOLEAN('c', "clock", &use_clock, 40 OPT_BOOLEAN('c', "cycle", &use_cycle,
41 "Use CPU clock for measuring"), 41 "Use cycles event instead of gettimeofday() for measuring"),
42 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
43 "Show only the result with page faults before memcpy()"), 43 "Show only the result with page faults before memcpy()"),
44 OPT_BOOLEAN('n', "no-prefault", &no_prefault, 44 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = {
76 NULL 76 NULL
77}; 77};
78 78
79static struct perf_event_attr clock_attr = { 79static struct perf_event_attr cycle_attr = {
80 .type = PERF_TYPE_HARDWARE, 80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES 81 .config = PERF_COUNT_HW_CPU_CYCLES
82}; 82};
83 83
84static void init_clock(void) 84static void init_cycle(void)
85{ 85{
86 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); 86 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
87 87
88 if (clock_fd < 0 && errno == ENOSYS) 88 if (cycle_fd < 0 && errno == ENOSYS)
89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
90 else 90 else
91 BUG_ON(clock_fd < 0); 91 BUG_ON(cycle_fd < 0);
92} 92}
93 93
94static u64 get_clock(void) 94static u64 get_cycle(void)
95{ 95{
96 int ret; 96 int ret;
97 u64 clk; 97 u64 clk;
98 98
99 ret = read(clock_fd, &clk, sizeof(u64)); 99 ret = read(cycle_fd, &clk, sizeof(u64));
100 BUG_ON(ret != sizeof(u64)); 100 BUG_ON(ret != sizeof(u64));
101 101
102 return clk; 102 return clk;
@@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length)
119 die("memory allocation failed - maybe length is too large?\n"); 119 die("memory allocation failed - maybe length is too large?\n");
120} 120}
121 121
122static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) 122static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
123{ 123{
124 u64 clock_start = 0ULL, clock_end = 0ULL; 124 u64 cycle_start = 0ULL, cycle_end = 0ULL;
125 void *src = NULL, *dst = NULL; 125 void *src = NULL, *dst = NULL;
126 int i; 126 int i;
127 127
@@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
130 if (prefault) 130 if (prefault)
131 fn(dst, src, len); 131 fn(dst, src, len);
132 132
133 clock_start = get_clock(); 133 cycle_start = get_cycle();
134 for (i = 0; i < iterations; ++i) 134 for (i = 0; i < iterations; ++i)
135 fn(dst, src, len); 135 fn(dst, src, len);
136 clock_end = get_clock(); 136 cycle_end = get_cycle();
137 137
138 free(src); 138 free(src);
139 free(dst); 139 free(dst);
140 return clock_end - clock_start; 140 return cycle_end - cycle_start;
141} 141}
142 142
143static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) 143static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
@@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv,
182 int i; 182 int i;
183 size_t len; 183 size_t len;
184 double result_bps[2]; 184 double result_bps[2];
185 u64 result_clock[2]; 185 u64 result_cycle[2];
186 186
187 argc = parse_options(argc, argv, options, 187 argc = parse_options(argc, argv, options,
188 bench_mem_memcpy_usage, 0); 188 bench_mem_memcpy_usage, 0);
189 189
190 if (use_clock) 190 if (use_cycle)
191 init_clock(); 191 init_cycle();
192 192
193 len = (size_t)perf_atoll((char *)length_str); 193 len = (size_t)perf_atoll((char *)length_str);
194 194
195 result_clock[0] = result_clock[1] = 0ULL; 195 result_cycle[0] = result_cycle[1] = 0ULL;
196 result_bps[0] = result_bps[1] = 0.0; 196 result_bps[0] = result_bps[1] = 0.0;
197 197
198 if ((s64)len <= 0) { 198 if ((s64)len <= 0) {
@@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv,
223 223
224 if (!only_prefault && !no_prefault) { 224 if (!only_prefault && !no_prefault) {
225 /* show both of results */ 225 /* show both of results */
226 if (use_clock) { 226 if (use_cycle) {
227 result_clock[0] = 227 result_cycle[0] =
228 do_memcpy_clock(routines[i].fn, len, false); 228 do_memcpy_cycle(routines[i].fn, len, false);
229 result_clock[1] = 229 result_cycle[1] =
230 do_memcpy_clock(routines[i].fn, len, true); 230 do_memcpy_cycle(routines[i].fn, len, true);
231 } else { 231 } else {
232 result_bps[0] = 232 result_bps[0] =
233 do_memcpy_gettimeofday(routines[i].fn, 233 do_memcpy_gettimeofday(routines[i].fn,
@@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv,
237 len, true); 237 len, true);
238 } 238 }
239 } else { 239 } else {
240 if (use_clock) { 240 if (use_cycle) {
241 result_clock[pf] = 241 result_cycle[pf] =
242 do_memcpy_clock(routines[i].fn, 242 do_memcpy_cycle(routines[i].fn,
243 len, only_prefault); 243 len, only_prefault);
244 } else { 244 } else {
245 result_bps[pf] = 245 result_bps[pf] =
@@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv,
251 switch (bench_format) { 251 switch (bench_format) {
252 case BENCH_FORMAT_DEFAULT: 252 case BENCH_FORMAT_DEFAULT:
253 if (!only_prefault && !no_prefault) { 253 if (!only_prefault && !no_prefault) {
254 if (use_clock) { 254 if (use_cycle) {
255 printf(" %14lf Clock/Byte\n", 255 printf(" %14lf Cycle/Byte\n",
256 (double)result_clock[0] 256 (double)result_cycle[0]
257 / (double)len); 257 / (double)len);
258 printf(" %14lf Clock/Byte (with prefault)\n", 258 printf(" %14lf Cycle/Byte (with prefault)\n",
259 (double)result_clock[1] 259 (double)result_cycle[1]
260 / (double)len); 260 / (double)len);
261 } else { 261 } else {
262 print_bps(result_bps[0]); 262 print_bps(result_bps[0]);
@@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv,
265 printf(" (with prefault)\n"); 265 printf(" (with prefault)\n");
266 } 266 }
267 } else { 267 } else {
268 if (use_clock) { 268 if (use_cycle) {
269 printf(" %14lf Clock/Byte", 269 printf(" %14lf Cycle/Byte",
270 (double)result_clock[pf] 270 (double)result_cycle[pf]
271 / (double)len); 271 / (double)len);
272 } else 272 } else
273 print_bps(result_bps[pf]); 273 print_bps(result_bps[pf]);
@@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv,
277 break; 277 break;
278 case BENCH_FORMAT_SIMPLE: 278 case BENCH_FORMAT_SIMPLE:
279 if (!only_prefault && !no_prefault) { 279 if (!only_prefault && !no_prefault) {
280 if (use_clock) { 280 if (use_cycle) {
281 printf("%lf %lf\n", 281 printf("%lf %lf\n",
282 (double)result_clock[0] / (double)len, 282 (double)result_cycle[0] / (double)len,
283 (double)result_clock[1] / (double)len); 283 (double)result_cycle[1] / (double)len);
284 } else { 284 } else {
285 printf("%lf %lf\n", 285 printf("%lf %lf\n",
286 result_bps[0], result_bps[1]); 286 result_bps[0], result_bps[1]);
287 } 287 }
288 } else { 288 } else {
289 if (use_clock) { 289 if (use_cycle) {
290 printf("%lf\n", (double)result_clock[pf] 290 printf("%lf\n", (double)result_cycle[pf]
291 / (double)len); 291 / (double)len);
292 } else 292 } else
293 printf("%lf\n", result_bps[pf]); 293 printf("%lf\n", result_bps[pf]);
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
index e9079185bd72..350cc9557265 100644
--- a/tools/perf/bench/mem-memset.c
+++ b/tools/perf/bench/mem-memset.c
@@ -24,21 +24,21 @@
24static const char *length_str = "1MB"; 24static const char *length_str = "1MB";
25static const char *routine = "default"; 25static const char *routine = "default";
26static int iterations = 1; 26static int iterations = 1;
27static bool use_clock; 27static bool use_cycle;
28static int clock_fd; 28static int cycle_fd;
29static bool only_prefault; 29static bool only_prefault;
30static bool no_prefault; 30static bool no_prefault;
31 31
32static const struct option options[] = { 32static const struct option options[] = {
33 OPT_STRING('l', "length", &length_str, "1MB", 33 OPT_STRING('l', "length", &length_str, "1MB",
34 "Specify length of memory to copy. " 34 "Specify length of memory to set. "
35 "available unit: B, MB, GB (upper and lower)"), 35 "Available units: B, KB, MB, GB and TB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 37 "Specify routine to set"),
38 OPT_INTEGER('i', "iterations", &iterations, 38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memset() invocation this number of times"), 39 "repeat memset() invocation this number of times"),
40 OPT_BOOLEAN('c', "clock", &use_clock, 40 OPT_BOOLEAN('c', "cycle", &use_cycle,
41 "Use CPU clock for measuring"), 41 "Use cycles event instead of gettimeofday() for measuring"),
42 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
43 "Show only the result with page faults before memset()"), 43 "Show only the result with page faults before memset()"),
44 OPT_BOOLEAN('n', "no-prefault", &no_prefault, 44 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = {
76 NULL 76 NULL
77}; 77};
78 78
79static struct perf_event_attr clock_attr = { 79static struct perf_event_attr cycle_attr = {
80 .type = PERF_TYPE_HARDWARE, 80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES 81 .config = PERF_COUNT_HW_CPU_CYCLES
82}; 82};
83 83
84static void init_clock(void) 84static void init_cycle(void)
85{ 85{
86 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); 86 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
87 87
88 if (clock_fd < 0 && errno == ENOSYS) 88 if (cycle_fd < 0 && errno == ENOSYS)
89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
90 else 90 else
91 BUG_ON(clock_fd < 0); 91 BUG_ON(cycle_fd < 0);
92} 92}
93 93
94static u64 get_clock(void) 94static u64 get_cycle(void)
95{ 95{
96 int ret; 96 int ret;
97 u64 clk; 97 u64 clk;
98 98
99 ret = read(clock_fd, &clk, sizeof(u64)); 99 ret = read(cycle_fd, &clk, sizeof(u64));
100 BUG_ON(ret != sizeof(u64)); 100 BUG_ON(ret != sizeof(u64));
101 101
102 return clk; 102 return clk;
@@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length)
115 die("memory allocation failed - maybe length is too large?\n"); 115 die("memory allocation failed - maybe length is too large?\n");
116} 116}
117 117
118static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) 118static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
119{ 119{
120 u64 clock_start = 0ULL, clock_end = 0ULL; 120 u64 cycle_start = 0ULL, cycle_end = 0ULL;
121 void *dst = NULL; 121 void *dst = NULL;
122 int i; 122 int i;
123 123
@@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
126 if (prefault) 126 if (prefault)
127 fn(dst, -1, len); 127 fn(dst, -1, len);
128 128
129 clock_start = get_clock(); 129 cycle_start = get_cycle();
130 for (i = 0; i < iterations; ++i) 130 for (i = 0; i < iterations; ++i)
131 fn(dst, i, len); 131 fn(dst, i, len);
132 clock_end = get_clock(); 132 cycle_end = get_cycle();
133 133
134 free(dst); 134 free(dst);
135 return clock_end - clock_start; 135 return cycle_end - cycle_start;
136} 136}
137 137
138static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) 138static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
@@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv,
176 int i; 176 int i;
177 size_t len; 177 size_t len;
178 double result_bps[2]; 178 double result_bps[2];
179 u64 result_clock[2]; 179 u64 result_cycle[2];
180 180
181 argc = parse_options(argc, argv, options, 181 argc = parse_options(argc, argv, options,
182 bench_mem_memset_usage, 0); 182 bench_mem_memset_usage, 0);
183 183
184 if (use_clock) 184 if (use_cycle)
185 init_clock(); 185 init_cycle();
186 186
187 len = (size_t)perf_atoll((char *)length_str); 187 len = (size_t)perf_atoll((char *)length_str);
188 188
189 result_clock[0] = result_clock[1] = 0ULL; 189 result_cycle[0] = result_cycle[1] = 0ULL;
190 result_bps[0] = result_bps[1] = 0.0; 190 result_bps[0] = result_bps[1] = 0.0;
191 191
192 if ((s64)len <= 0) { 192 if ((s64)len <= 0) {
@@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv,
217 217
218 if (!only_prefault && !no_prefault) { 218 if (!only_prefault && !no_prefault) {
219 /* show both of results */ 219 /* show both of results */
220 if (use_clock) { 220 if (use_cycle) {
221 result_clock[0] = 221 result_cycle[0] =
222 do_memset_clock(routines[i].fn, len, false); 222 do_memset_cycle(routines[i].fn, len, false);
223 result_clock[1] = 223 result_cycle[1] =
224 do_memset_clock(routines[i].fn, len, true); 224 do_memset_cycle(routines[i].fn, len, true);
225 } else { 225 } else {
226 result_bps[0] = 226 result_bps[0] =
227 do_memset_gettimeofday(routines[i].fn, 227 do_memset_gettimeofday(routines[i].fn,
@@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv,
231 len, true); 231 len, true);
232 } 232 }
233 } else { 233 } else {
234 if (use_clock) { 234 if (use_cycle) {
235 result_clock[pf] = 235 result_cycle[pf] =
236 do_memset_clock(routines[i].fn, 236 do_memset_cycle(routines[i].fn,
237 len, only_prefault); 237 len, only_prefault);
238 } else { 238 } else {
239 result_bps[pf] = 239 result_bps[pf] =
@@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv,
245 switch (bench_format) { 245 switch (bench_format) {
246 case BENCH_FORMAT_DEFAULT: 246 case BENCH_FORMAT_DEFAULT:
247 if (!only_prefault && !no_prefault) { 247 if (!only_prefault && !no_prefault) {
248 if (use_clock) { 248 if (use_cycle) {
249 printf(" %14lf Clock/Byte\n", 249 printf(" %14lf Cycle/Byte\n",
250 (double)result_clock[0] 250 (double)result_cycle[0]
251 / (double)len); 251 / (double)len);
252 printf(" %14lf Clock/Byte (with prefault)\n ", 252 printf(" %14lf Cycle/Byte (with prefault)\n ",
253 (double)result_clock[1] 253 (double)result_cycle[1]
254 / (double)len); 254 / (double)len);
255 } else { 255 } else {
256 print_bps(result_bps[0]); 256 print_bps(result_bps[0]);
@@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv,
259 printf(" (with prefault)\n"); 259 printf(" (with prefault)\n");
260 } 260 }
261 } else { 261 } else {
262 if (use_clock) { 262 if (use_cycle) {
263 printf(" %14lf Clock/Byte", 263 printf(" %14lf Cycle/Byte",
264 (double)result_clock[pf] 264 (double)result_cycle[pf]
265 / (double)len); 265 / (double)len);
266 } else 266 } else
267 print_bps(result_bps[pf]); 267 print_bps(result_bps[pf]);
@@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv,
271 break; 271 break;
272 case BENCH_FORMAT_SIMPLE: 272 case BENCH_FORMAT_SIMPLE:
273 if (!only_prefault && !no_prefault) { 273 if (!only_prefault && !no_prefault) {
274 if (use_clock) { 274 if (use_cycle) {
275 printf("%lf %lf\n", 275 printf("%lf %lf\n",
276 (double)result_clock[0] / (double)len, 276 (double)result_cycle[0] / (double)len,
277 (double)result_clock[1] / (double)len); 277 (double)result_cycle[1] / (double)len);
278 } else { 278 } else {
279 printf("%lf %lf\n", 279 printf("%lf %lf\n",
280 result_bps[0], result_bps[1]); 280 result_bps[0], result_bps[1]);
281 } 281 }
282 } else { 282 } else {
283 if (use_clock) { 283 if (use_cycle) {
284 printf("%lf\n", (double)result_clock[pf] 284 printf("%lf\n", (double)result_cycle[pf]
285 / (double)len); 285 / (double)len);
286 } else 286 } else
287 printf("%lf\n", result_bps[pf]); 287 printf("%lf\n", result_bps[pf]);
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index b0e74ab2d7a2..1f3100216448 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -33,7 +33,7 @@ struct bench_suite {
33}; 33};
34 \ 34 \
35/* sentinel: easy for help */ 35/* sentinel: easy for help */
36#define suite_all { "all", "test all suite (pseudo suite)", NULL } 36#define suite_all { "all", "Test all benchmark suites", NULL }
37 37
38static struct bench_suite sched_suites[] = { 38static struct bench_suite sched_suites[] = {
39 { "messaging", 39 { "messaging",
@@ -75,7 +75,7 @@ static struct bench_subsys subsystems[] = {
75 "memory access performance", 75 "memory access performance",
76 mem_suites }, 76 mem_suites },
77 { "all", /* sentinel: easy for help */ 77 { "all", /* sentinel: easy for help */
78 "test all subsystem (pseudo subsystem)", 78 "all benchmark subsystem",
79 NULL }, 79 NULL },
80 { NULL, 80 { NULL,
81 NULL, 81 NULL,
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index acd78dc28341..0dd5a058f766 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -60,7 +60,7 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
60 list_for_each_entry(pos, &session->evlist->entries, node) { 60 list_for_each_entry(pos, &session->evlist->entries, node) {
61 bool first = true; 61 bool first = true;
62 62
63 printf("%s", event_name(pos)); 63 printf("%s", perf_evsel__name(pos));
64 64
65 if (details->verbose || details->freq) { 65 if (details->verbose || details->freq) {
66 comma_printf(&first, " sample_freq=%" PRIu64, 66 comma_printf(&first, " sample_freq=%" PRIu64,
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 547af48deb4f..ce35015f2dc6 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -57,6 +57,11 @@ static unsigned long nr_allocs, nr_cross_allocs;
57 57
58#define PATH_SYS_NODE "/sys/devices/system/node" 58#define PATH_SYS_NODE "/sys/devices/system/node"
59 59
60struct perf_kmem {
61 struct perf_tool tool;
62 struct perf_session *session;
63};
64
60static void init_cpunode_map(void) 65static void init_cpunode_map(void)
61{ 66{
62 FILE *fp; 67 FILE *fp;
@@ -278,14 +283,16 @@ static void process_free_event(void *data,
278 s_alloc->alloc_cpu = -1; 283 s_alloc->alloc_cpu = -1;
279} 284}
280 285
281static void process_raw_event(union perf_event *raw_event __used, void *data, 286static void process_raw_event(struct perf_tool *tool,
287 union perf_event *raw_event __used, void *data,
282 int cpu, u64 timestamp, struct thread *thread) 288 int cpu, u64 timestamp, struct thread *thread)
283{ 289{
290 struct perf_kmem *kmem = container_of(tool, struct perf_kmem, tool);
284 struct event_format *event; 291 struct event_format *event;
285 int type; 292 int type;
286 293
287 type = trace_parse_common_type(data); 294 type = trace_parse_common_type(kmem->session->pevent, data);
288 event = trace_find_event(type); 295 event = pevent_find_event(kmem->session->pevent, type);
289 296
290 if (!strcmp(event->name, "kmalloc") || 297 if (!strcmp(event->name, "kmalloc") ||
291 !strcmp(event->name, "kmem_cache_alloc")) { 298 !strcmp(event->name, "kmem_cache_alloc")) {
@@ -306,7 +313,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
306 } 313 }
307} 314}
308 315
309static int process_sample_event(struct perf_tool *tool __used, 316static int process_sample_event(struct perf_tool *tool,
310 union perf_event *event, 317 union perf_event *event,
311 struct perf_sample *sample, 318 struct perf_sample *sample,
312 struct perf_evsel *evsel __used, 319 struct perf_evsel *evsel __used,
@@ -322,16 +329,18 @@ static int process_sample_event(struct perf_tool *tool __used,
322 329
323 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 330 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
324 331
325 process_raw_event(event, sample->raw_data, sample->cpu, 332 process_raw_event(tool, event, sample->raw_data, sample->cpu,
326 sample->time, thread); 333 sample->time, thread);
327 334
328 return 0; 335 return 0;
329} 336}
330 337
331static struct perf_tool perf_kmem = { 338static struct perf_kmem perf_kmem = {
332 .sample = process_sample_event, 339 .tool = {
333 .comm = perf_event__process_comm, 340 .sample = process_sample_event,
334 .ordered_samples = true, 341 .comm = perf_event__process_comm,
342 .ordered_samples = true,
343 },
335}; 344};
336 345
337static double fragmentation(unsigned long n_req, unsigned long n_alloc) 346static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -486,11 +495,15 @@ static void sort_result(void)
486static int __cmd_kmem(void) 495static int __cmd_kmem(void)
487{ 496{
488 int err = -EINVAL; 497 int err = -EINVAL;
489 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 498 struct perf_session *session;
490 0, false, &perf_kmem); 499
500 session = perf_session__new(input_name, O_RDONLY, 0, false,
501 &perf_kmem.tool);
491 if (session == NULL) 502 if (session == NULL)
492 return -ENOMEM; 503 return -ENOMEM;
493 504
505 perf_kmem.session = session;
506
494 if (perf_session__create_kernel_maps(session) < 0) 507 if (perf_session__create_kernel_maps(session) < 0)
495 goto out_delete; 508 goto out_delete;
496 509
@@ -498,7 +511,7 @@ static int __cmd_kmem(void)
498 goto out_delete; 511 goto out_delete;
499 512
500 setup_pager(); 513 setup_pager();
501 err = perf_session__process_events(session, &perf_kmem); 514 err = perf_session__process_events(session, &perf_kmem.tool);
502 if (err != 0) 515 if (err != 0)
503 goto out_delete; 516 goto out_delete;
504 sort_result(); 517 sort_result();
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index fd53319de20d..b3c428548868 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -724,8 +724,8 @@ process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
724 struct event_format *event; 724 struct event_format *event;
725 int type; 725 int type;
726 726
727 type = trace_parse_common_type(data); 727 type = trace_parse_common_type(session->pevent, data);
728 event = trace_find_event(type); 728 event = pevent_find_event(session->pevent, type);
729 729
730 if (!strcmp(event->name, "lock_acquire")) 730 if (!strcmp(event->name, "lock_acquire"))
731 process_lock_acquire_event(data, event, cpu, timestamp, thread); 731 process_lock_acquire_event(data, event, cpu, timestamp, thread);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f95840d04e4c..f5a6452931e6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -265,7 +265,7 @@ try_again:
265 265
266 if (err == ENOENT) { 266 if (err == ENOENT) {
267 ui__error("The %s event is not supported.\n", 267 ui__error("The %s event is not supported.\n",
268 event_name(pos)); 268 perf_evsel__name(pos));
269 exit(EXIT_FAILURE); 269 exit(EXIT_FAILURE);
270 } 270 }
271 271
@@ -916,7 +916,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
916 usage_with_options(record_usage, record_options); 916 usage_with_options(record_usage, record_options);
917 917
918 list_for_each_entry(pos, &evsel_list->entries, node) { 918 list_for_each_entry(pos, &evsel_list->entries, node) {
919 if (perf_header__push_event(pos->attr.config, event_name(pos))) 919 if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
920 goto out_free_fd; 920 goto out_free_fd;
921 } 921 }
922 922
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 25249f76329d..69b1c1185159 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -69,7 +69,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
69 69
70 if ((sort__has_parent || symbol_conf.use_callchain) 70 if ((sort__has_parent || symbol_conf.use_callchain)
71 && sample->callchain) { 71 && sample->callchain) {
72 err = machine__resolve_callchain(machine, evsel, al->thread, 72 err = machine__resolve_callchain(machine, al->thread,
73 sample->callchain, &parent); 73 sample->callchain, &parent);
74 if (err) 74 if (err)
75 return err; 75 return err;
@@ -140,7 +140,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
140 struct hist_entry *he; 140 struct hist_entry *he;
141 141
142 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 142 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
143 err = machine__resolve_callchain(machine, evsel, al->thread, 143 err = machine__resolve_callchain(machine, al->thread,
144 sample->callchain, &parent); 144 sample->callchain, &parent);
145 if (err) 145 if (err)
146 return err; 146 return err;
@@ -230,7 +230,7 @@ static int process_read_event(struct perf_tool *tool,
230 struct perf_report *rep = container_of(tool, struct perf_report, tool); 230 struct perf_report *rep = container_of(tool, struct perf_report, tool);
231 231
232 if (rep->show_threads) { 232 if (rep->show_threads) {
233 const char *name = evsel ? event_name(evsel) : "unknown"; 233 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
234 perf_read_values_add_value(&rep->show_threads_values, 234 perf_read_values_add_value(&rep->show_threads_values,
235 event->read.pid, event->read.tid, 235 event->read.pid, event->read.tid,
236 event->read.id, 236 event->read.id,
@@ -239,17 +239,18 @@ static int process_read_event(struct perf_tool *tool,
239 } 239 }
240 240
241 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid, 241 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
242 evsel ? event_name(evsel) : "FAIL", 242 evsel ? perf_evsel__name(evsel) : "FAIL",
243 event->read.value); 243 event->read.value);
244 244
245 return 0; 245 return 0;
246} 246}
247 247
248/* For pipe mode, sample_type is not currently set */
248static int perf_report__setup_sample_type(struct perf_report *rep) 249static int perf_report__setup_sample_type(struct perf_report *rep)
249{ 250{
250 struct perf_session *self = rep->session; 251 struct perf_session *self = rep->session;
251 252
252 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 253 if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
253 if (sort__has_parent) { 254 if (sort__has_parent) {
254 ui__error("Selected --sort parent, but no " 255 ui__error("Selected --sort parent, but no "
255 "callchain data. Did you call " 256 "callchain data. Did you call "
@@ -272,7 +273,8 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
272 } 273 }
273 274
274 if (sort__branch_mode == 1) { 275 if (sort__branch_mode == 1) {
275 if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) { 276 if (!self->fd_pipe &&
277 !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
276 ui__error("Selected -b but no branch data. " 278 ui__error("Selected -b but no branch data. "
277 "Did you call perf record without -b?\n"); 279 "Did you call perf record without -b?\n");
278 return -1; 280 return -1;
@@ -314,7 +316,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
314 316
315 list_for_each_entry(pos, &evlist->entries, node) { 317 list_for_each_entry(pos, &evlist->entries, node) {
316 struct hists *hists = &pos->hists; 318 struct hists *hists = &pos->hists;
317 const char *evname = event_name(pos); 319 const char *evname = perf_evsel__name(pos);
318 320
319 hists__fprintf_nr_sample_events(hists, evname, stdout); 321 hists__fprintf_nr_sample_events(hists, evname, stdout);
320 hists__fprintf(hists, NULL, false, true, 0, 0, stdout); 322 hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index b125e07eb399..7a9ad2b1ee76 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -43,6 +43,11 @@ static u64 sleep_measurement_overhead;
43 43
44static unsigned long nr_tasks; 44static unsigned long nr_tasks;
45 45
46struct perf_sched {
47 struct perf_tool tool;
48 struct perf_session *session;
49};
50
46struct sched_atom; 51struct sched_atom;
47 52
48struct task_desc { 53struct task_desc {
@@ -1597,11 +1602,13 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1597 struct perf_evsel *evsel, 1602 struct perf_evsel *evsel,
1598 struct machine *machine) 1603 struct machine *machine)
1599{ 1604{
1605 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1606 struct pevent *pevent = sched->session->pevent;
1600 struct thread *thread = machine__findnew_thread(machine, sample->pid); 1607 struct thread *thread = machine__findnew_thread(machine, sample->pid);
1601 1608
1602 if (thread == NULL) { 1609 if (thread == NULL) {
1603 pr_debug("problem processing %s event, skipping it.\n", 1610 pr_debug("problem processing %s event, skipping it.\n",
1604 evsel->name); 1611 perf_evsel__name(evsel));
1605 return -1; 1612 return -1;
1606 } 1613 }
1607 1614
@@ -1612,7 +1619,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1612 tracepoint_handler f = evsel->handler.func; 1619 tracepoint_handler f = evsel->handler.func;
1613 1620
1614 if (evsel->handler.data == NULL) 1621 if (evsel->handler.data == NULL)
1615 evsel->handler.data = trace_find_event(evsel->attr.config); 1622 evsel->handler.data = pevent_find_event(pevent,
1623 evsel->attr.config);
1616 1624
1617 f(tool, evsel->handler.data, sample, machine, thread); 1625 f(tool, evsel->handler.data, sample, machine, thread);
1618 } 1626 }
@@ -1620,12 +1628,14 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1620 return 0; 1628 return 0;
1621} 1629}
1622 1630
1623static struct perf_tool perf_sched = { 1631static struct perf_sched perf_sched = {
1624 .sample = perf_sched__process_tracepoint_sample, 1632 .tool = {
1625 .comm = perf_event__process_comm, 1633 .sample = perf_sched__process_tracepoint_sample,
1626 .lost = perf_event__process_lost, 1634 .comm = perf_event__process_comm,
1627 .fork = perf_event__process_task, 1635 .lost = perf_event__process_lost,
1628 .ordered_samples = true, 1636 .fork = perf_event__process_task,
1637 .ordered_samples = true,
1638 },
1629}; 1639};
1630 1640
1631static void read_events(bool destroy, struct perf_session **psession) 1641static void read_events(bool destroy, struct perf_session **psession)
@@ -1640,16 +1650,20 @@ static void read_events(bool destroy, struct perf_session **psession)
1640 { "sched:sched_process_exit", process_sched_exit_event, }, 1650 { "sched:sched_process_exit", process_sched_exit_event, },
1641 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1651 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1642 }; 1652 };
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1653 struct perf_session *session;
1644 0, false, &perf_sched); 1654
1655 session = perf_session__new(input_name, O_RDONLY, 0, false,
1656 &perf_sched.tool);
1645 if (session == NULL) 1657 if (session == NULL)
1646 die("No Memory"); 1658 die("No Memory");
1647 1659
1648 err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers); 1660 perf_sched.session = session;
1661
1662 err = perf_session__set_tracepoints_handlers(session, handlers);
1649 assert(err == 0); 1663 assert(err == 0);
1650 1664
1651 if (perf_session__has_traces(session, "record -R")) { 1665 if (perf_session__has_traces(session, "record -R")) {
1652 err = perf_session__process_events(session, &perf_sched); 1666 err = perf_session__process_events(session, &perf_sched.tool);
1653 if (err) 1667 if (err)
1654 die("Failed to process events, error %d", err); 1668 die("Failed to process events, error %d", err);
1655 1669
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 8e395a538eb9..1e60ab70b2b1 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -28,6 +28,11 @@ static bool system_wide;
28static const char *cpu_list; 28static const char *cpu_list;
29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
30 30
31struct perf_script {
32 struct perf_tool tool;
33 struct perf_session *session;
34};
35
31enum perf_output_field { 36enum perf_output_field {
32 PERF_OUTPUT_COMM = 1U << 0, 37 PERF_OUTPUT_COMM = 1U << 0,
33 PERF_OUTPUT_TID = 1U << 1, 38 PERF_OUTPUT_TID = 1U << 1,
@@ -137,10 +142,11 @@ static const char *output_field2str(enum perf_output_field field)
137 142
138#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 143#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
139 144
140static int perf_event_attr__check_stype(struct perf_event_attr *attr, 145static int perf_evsel__check_stype(struct perf_evsel *evsel,
141 u64 sample_type, const char *sample_msg, 146 u64 sample_type, const char *sample_msg,
142 enum perf_output_field field) 147 enum perf_output_field field)
143{ 148{
149 struct perf_event_attr *attr = &evsel->attr;
144 int type = attr->type; 150 int type = attr->type;
145 const char *evname; 151 const char *evname;
146 152
@@ -148,7 +154,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
148 return 0; 154 return 0;
149 155
150 if (output[type].user_set) { 156 if (output[type].user_set) {
151 evname = __event_name(attr->type, attr->config); 157 evname = perf_evsel__name(evsel);
152 pr_err("Samples for '%s' event do not have %s attribute set. " 158 pr_err("Samples for '%s' event do not have %s attribute set. "
153 "Cannot print '%s' field.\n", 159 "Cannot print '%s' field.\n",
154 evname, sample_msg, output_field2str(field)); 160 evname, sample_msg, output_field2str(field));
@@ -157,7 +163,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
157 163
158 /* user did not ask for it explicitly so remove from the default list */ 164 /* user did not ask for it explicitly so remove from the default list */
159 output[type].fields &= ~field; 165 output[type].fields &= ~field;
160 evname = __event_name(attr->type, attr->config); 166 evname = perf_evsel__name(evsel);
161 pr_debug("Samples for '%s' event do not have %s attribute set. " 167 pr_debug("Samples for '%s' event do not have %s attribute set. "
162 "Skipping '%s' field.\n", 168 "Skipping '%s' field.\n",
163 evname, sample_msg, output_field2str(field)); 169 evname, sample_msg, output_field2str(field));
@@ -175,8 +181,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
175 return -EINVAL; 181 return -EINVAL;
176 182
177 if (PRINT_FIELD(IP)) { 183 if (PRINT_FIELD(IP)) {
178 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", 184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
179 PERF_OUTPUT_IP)) 185 PERF_OUTPUT_IP))
180 return -EINVAL; 186 return -EINVAL;
181 187
182 if (!no_callchain && 188 if (!no_callchain &&
@@ -185,8 +191,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
185 } 191 }
186 192
187 if (PRINT_FIELD(ADDR) && 193 if (PRINT_FIELD(ADDR) &&
188 perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", 194 perf_evsel__check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
189 PERF_OUTPUT_ADDR)) 195 PERF_OUTPUT_ADDR))
190 return -EINVAL; 196 return -EINVAL;
191 197
192 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 198 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
@@ -208,18 +214,18 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
208 } 214 }
209 215
210 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 216 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
211 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", 217 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
212 PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 218 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
213 return -EINVAL; 219 return -EINVAL;
214 220
215 if (PRINT_FIELD(TIME) && 221 if (PRINT_FIELD(TIME) &&
216 perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME", 222 perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
217 PERF_OUTPUT_TIME)) 223 PERF_OUTPUT_TIME))
218 return -EINVAL; 224 return -EINVAL;
219 225
220 if (PRINT_FIELD(CPU) && 226 if (PRINT_FIELD(CPU) &&
221 perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU", 227 perf_evsel__check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
222 PERF_OUTPUT_CPU)) 228 PERF_OUTPUT_CPU))
223 return -EINVAL; 229 return -EINVAL;
224 230
225 return 0; 231 return 0;
@@ -256,11 +262,13 @@ static int perf_session__check_output_opt(struct perf_session *session)
256 return 0; 262 return 0;
257} 263}
258 264
259static void print_sample_start(struct perf_sample *sample, 265static void print_sample_start(struct pevent *pevent,
266 struct perf_sample *sample,
260 struct thread *thread, 267 struct thread *thread,
261 struct perf_event_attr *attr) 268 struct perf_evsel *evsel)
262{ 269{
263 int type; 270 int type;
271 struct perf_event_attr *attr = &evsel->attr;
264 struct event_format *event; 272 struct event_format *event;
265 const char *evname = NULL; 273 const char *evname = NULL;
266 unsigned long secs; 274 unsigned long secs;
@@ -300,12 +308,18 @@ static void print_sample_start(struct perf_sample *sample,
300 308
301 if (PRINT_FIELD(EVNAME)) { 309 if (PRINT_FIELD(EVNAME)) {
302 if (attr->type == PERF_TYPE_TRACEPOINT) { 310 if (attr->type == PERF_TYPE_TRACEPOINT) {
303 type = trace_parse_common_type(sample->raw_data); 311 /*
304 event = trace_find_event(type); 312 * XXX Do we really need this here?
313 * perf_evlist__set_tracepoint_names should have done
314 * this already
315 */
316 type = trace_parse_common_type(pevent,
317 sample->raw_data);
318 event = pevent_find_event(pevent, type);
305 if (event) 319 if (event)
306 evname = event->name; 320 evname = event->name;
307 } else 321 } else
308 evname = __event_name(attr->type, attr->config); 322 evname = perf_evsel__name(evsel);
309 323
310 printf("%s: ", evname ? evname : "[unknown]"); 324 printf("%s: ", evname ? evname : "[unknown]");
311 } 325 }
@@ -387,7 +401,7 @@ static void print_sample_bts(union perf_event *event,
387 printf(" "); 401 printf(" ");
388 else 402 else
389 printf("\n"); 403 printf("\n");
390 perf_event__print_ip(event, sample, machine, evsel, 404 perf_event__print_ip(event, sample, machine,
391 PRINT_FIELD(SYM), PRINT_FIELD(DSO), 405 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
392 PRINT_FIELD(SYMOFFSET)); 406 PRINT_FIELD(SYMOFFSET));
393 } 407 }
@@ -402,6 +416,7 @@ static void print_sample_bts(union perf_event *event,
402} 416}
403 417
404static void process_event(union perf_event *event __unused, 418static void process_event(union perf_event *event __unused,
419 struct pevent *pevent,
405 struct perf_sample *sample, 420 struct perf_sample *sample,
406 struct perf_evsel *evsel, 421 struct perf_evsel *evsel,
407 struct machine *machine, 422 struct machine *machine,
@@ -412,7 +427,7 @@ static void process_event(union perf_event *event __unused,
412 if (output[attr->type].fields == 0) 427 if (output[attr->type].fields == 0)
413 return; 428 return;
414 429
415 print_sample_start(sample, thread, attr); 430 print_sample_start(pevent, sample, thread, evsel);
416 431
417 if (is_bts_event(attr)) { 432 if (is_bts_event(attr)) {
418 print_sample_bts(event, sample, evsel, machine, thread); 433 print_sample_bts(event, sample, evsel, machine, thread);
@@ -420,7 +435,7 @@ static void process_event(union perf_event *event __unused,
420 } 435 }
421 436
422 if (PRINT_FIELD(TRACE)) 437 if (PRINT_FIELD(TRACE))
423 print_trace_event(sample->cpu, sample->raw_data, 438 print_trace_event(pevent, sample->cpu, sample->raw_data,
424 sample->raw_size); 439 sample->raw_size);
425 440
426 if (PRINT_FIELD(ADDR)) 441 if (PRINT_FIELD(ADDR))
@@ -431,7 +446,7 @@ static void process_event(union perf_event *event __unused,
431 printf(" "); 446 printf(" ");
432 else 447 else
433 printf("\n"); 448 printf("\n");
434 perf_event__print_ip(event, sample, machine, evsel, 449 perf_event__print_ip(event, sample, machine,
435 PRINT_FIELD(SYM), PRINT_FIELD(DSO), 450 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
436 PRINT_FIELD(SYMOFFSET)); 451 PRINT_FIELD(SYMOFFSET));
437 } 452 }
@@ -451,7 +466,8 @@ static int default_stop_script(void)
451 return 0; 466 return 0;
452} 467}
453 468
454static int default_generate_script(const char *outfile __unused) 469static int default_generate_script(struct pevent *pevent __unused,
470 const char *outfile __unused)
455{ 471{
456 return 0; 472 return 0;
457} 473}
@@ -489,6 +505,7 @@ static int process_sample_event(struct perf_tool *tool __used,
489 struct machine *machine) 505 struct machine *machine)
490{ 506{
491 struct addr_location al; 507 struct addr_location al;
508 struct perf_script *scr = container_of(tool, struct perf_script, tool);
492 struct thread *thread = machine__findnew_thread(machine, event->ip.tid); 509 struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
493 510
494 if (thread == NULL) { 511 if (thread == NULL) {
@@ -520,24 +537,27 @@ static int process_sample_event(struct perf_tool *tool __used,
520 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 537 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
521 return 0; 538 return 0;
522 539
523 scripting_ops->process_event(event, sample, evsel, machine, thread); 540 scripting_ops->process_event(event, scr->session->pevent,
541 sample, evsel, machine, thread);
524 542
525 evsel->hists.stats.total_period += sample->period; 543 evsel->hists.stats.total_period += sample->period;
526 return 0; 544 return 0;
527} 545}
528 546
529static struct perf_tool perf_script = { 547static struct perf_script perf_script = {
530 .sample = process_sample_event, 548 .tool = {
531 .mmap = perf_event__process_mmap, 549 .sample = process_sample_event,
532 .comm = perf_event__process_comm, 550 .mmap = perf_event__process_mmap,
533 .exit = perf_event__process_task, 551 .comm = perf_event__process_comm,
534 .fork = perf_event__process_task, 552 .exit = perf_event__process_task,
535 .attr = perf_event__process_attr, 553 .fork = perf_event__process_task,
536 .event_type = perf_event__process_event_type, 554 .attr = perf_event__process_attr,
537 .tracing_data = perf_event__process_tracing_data, 555 .event_type = perf_event__process_event_type,
538 .build_id = perf_event__process_build_id, 556 .tracing_data = perf_event__process_tracing_data,
539 .ordered_samples = true, 557 .build_id = perf_event__process_build_id,
540 .ordering_requires_timestamps = true, 558 .ordered_samples = true,
559 .ordering_requires_timestamps = true,
560 },
541}; 561};
542 562
543extern volatile int session_done; 563extern volatile int session_done;
@@ -553,7 +573,7 @@ static int __cmd_script(struct perf_session *session)
553 573
554 signal(SIGINT, sig_handler); 574 signal(SIGINT, sig_handler);
555 575
556 ret = perf_session__process_events(session, &perf_script); 576 ret = perf_session__process_events(session, &perf_script.tool);
557 577
558 if (debug_mode) 578 if (debug_mode)
559 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 579 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1335,10 +1355,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1335 if (!script_name) 1355 if (!script_name)
1336 setup_pager(); 1356 setup_pager();
1337 1357
1338 session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script); 1358 session = perf_session__new(input_name, O_RDONLY, 0, false,
1359 &perf_script.tool);
1339 if (session == NULL) 1360 if (session == NULL)
1340 return -ENOMEM; 1361 return -ENOMEM;
1341 1362
1363 perf_script.session = session;
1364
1342 if (cpu_list) { 1365 if (cpu_list) {
1343 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1366 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1344 return -1; 1367 return -1;
@@ -1384,7 +1407,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1384 return -1; 1407 return -1;
1385 } 1408 }
1386 1409
1387 err = scripting_ops->generate_script("perf-script"); 1410 err = scripting_ops->generate_script(session->pevent,
1411 "perf-script");
1388 goto out; 1412 goto out;
1389 } 1413 }
1390 1414
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 07b5c7703dd1..861f0aec77ae 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -391,7 +391,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
391 391
392 if (verbose) { 392 if (verbose) {
393 fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 393 fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
394 event_name(counter), count[0], count[1], count[2]); 394 perf_evsel__name(counter), count[0], count[1], count[2]);
395 } 395 }
396 396
397 /* 397 /*
@@ -496,7 +496,7 @@ static int run_perf_stat(int argc __used, const char **argv)
496 errno == ENXIO) { 496 errno == ENXIO) {
497 if (verbose) 497 if (verbose)
498 ui__warning("%s event is not supported by the kernel.\n", 498 ui__warning("%s event is not supported by the kernel.\n",
499 event_name(counter)); 499 perf_evsel__name(counter));
500 counter->supported = false; 500 counter->supported = false;
501 continue; 501 continue;
502 } 502 }
@@ -594,7 +594,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
594 csv_output ? 0 : -4, 594 csv_output ? 0 : -4,
595 evsel_list->cpus->map[cpu], csv_sep); 595 evsel_list->cpus->map[cpu], csv_sep);
596 596
597 fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 597 fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
598 598
599 if (evsel->cgrp) 599 if (evsel->cgrp)
600 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 600 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -792,7 +792,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
792 else 792 else
793 cpu = 0; 793 cpu = 0;
794 794
795 fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel)); 795 fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
796 796
797 if (evsel->cgrp) 797 if (evsel->cgrp)
798 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 798 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,7 +908,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
908 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 908 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
909 csv_sep, 909 csv_sep,
910 csv_output ? 0 : -24, 910 csv_output ? 0 : -24,
911 event_name(counter)); 911 perf_evsel__name(counter));
912 912
913 if (counter->cgrp) 913 if (counter->cgrp)
914 fprintf(output, "%s%s", csv_sep, counter->cgrp->name); 914 fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
@@ -961,7 +961,7 @@ static void print_counter(struct perf_evsel *counter)
961 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 961 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
962 csv_sep, 962 csv_sep,
963 csv_output ? 0 : -24, 963 csv_output ? 0 : -24,
964 event_name(counter)); 964 perf_evsel__name(counter));
965 965
966 if (counter->cgrp) 966 if (counter->cgrp)
967 fprintf(output, "%s%s", 967 fprintf(output, "%s%s",
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 5a8727c08757..5ce30305462b 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -583,7 +583,7 @@ static int test__basic_mmap(void)
583 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 583 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
584 pr_debug("expected %d %s events, got %d\n", 584 pr_debug("expected %d %s events, got %d\n",
585 expected_nr_events[evsel->idx], 585 expected_nr_events[evsel->idx],
586 event_name(evsel), nr_events[evsel->idx]); 586 perf_evsel__name(evsel), nr_events[evsel->idx]);
587 goto out_munmap; 587 goto out_munmap;
588 } 588 }
589 } 589 }
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6bb0277b7dfe..e3cab5f088f8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -245,7 +245,7 @@ static void perf_top__show_details(struct perf_top *top)
245 if (notes->src == NULL) 245 if (notes->src == NULL)
246 goto out_unlock; 246 goto out_unlock;
247 247
248 printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name); 248 printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
249 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter); 249 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
250 250
251 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx, 251 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
@@ -408,7 +408,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
408 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries); 408 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries);
409 409
410 if (top->evlist->nr_entries > 1) 410 if (top->evlist->nr_entries > 1)
411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top->sym_evsel)); 411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", perf_evsel__name(top->sym_evsel));
412 412
413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter); 413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
414 414
@@ -503,13 +503,13 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
503 fprintf(stderr, "\nAvailable events:"); 503 fprintf(stderr, "\nAvailable events:");
504 504
505 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) 505 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
506 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel)); 506 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
507 507
508 prompt_integer(&counter, "Enter details event counter"); 508 prompt_integer(&counter, "Enter details event counter");
509 509
510 if (counter >= top->evlist->nr_entries) { 510 if (counter >= top->evlist->nr_entries) {
511 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node); 511 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
512 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel)); 512 fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
513 sleep(1); 513 sleep(1);
514 break; 514 break;
515 } 515 }
@@ -774,7 +774,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
774 774
775 if ((sort__has_parent || symbol_conf.use_callchain) && 775 if ((sort__has_parent || symbol_conf.use_callchain) &&
776 sample->callchain) { 776 sample->callchain) {
777 err = machine__resolve_callchain(machine, evsel, al.thread, 777 err = machine__resolve_callchain(machine, al.thread,
778 sample->callchain, &parent); 778 sample->callchain, &parent);
779 if (err) 779 if (err)
780 return; 780 return;
@@ -960,7 +960,7 @@ try_again:
960 960
961 if (err == ENOENT) { 961 if (err == ENOENT) {
962 ui__error("The %s event is not supported.\n", 962 ui__error("The %s event is not supported.\n",
963 event_name(counter)); 963 perf_evsel__name(counter));
964 goto out_err; 964 goto out_err;
965 } else if (err == EMFILE) { 965 } else if (err == EMFILE) {
966 ui__error("Too many events are opened.\n" 966 ui__error("Too many events are opened.\n"
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index d9084e03ce56..6c18785a6417 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -78,6 +78,19 @@ int main(int argc, char *argv[])
78 return 0; 78 return 0;
79} 79}
80endef 80endef
81
82define SOURCE_GTK2_INFOBAR
83#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
84#include <gtk/gtk.h>
85#pragma GCC diagnostic error \"-Wstrict-prototypes\"
86
87int main(void)
88{
89 gtk_info_bar_new();
90
91 return 0;
92}
93endef
81endif 94endif
82 95
83ifndef NO_LIBPERL 96ifndef NO_LIBPERL
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 34b1c46eaf42..67a2703e666a 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -814,7 +814,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
814{ 814{
815 struct disasm_line *pos, *n; 815 struct disasm_line *pos, *n;
816 struct annotation *notes; 816 struct annotation *notes;
817 const size_t size = symbol__size(sym); 817 size_t size;
818 struct map_symbol ms = { 818 struct map_symbol ms = {
819 .map = map, 819 .map = map,
820 .sym = sym, 820 .sym = sym,
@@ -834,6 +834,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
834 if (sym == NULL) 834 if (sym == NULL)
835 return -1; 835 return -1;
836 836
837 size = symbol__size(sym);
838
837 if (map->dso->annotate_warned) 839 if (map->dso->annotate_warned)
838 return -1; 840 return -1;
839 841
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 53f6697d014e..482f0517b61e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -23,6 +23,7 @@ struct hist_browser {
23 struct hists *hists; 23 struct hists *hists;
24 struct hist_entry *he_selection; 24 struct hist_entry *he_selection;
25 struct map_symbol *selection; 25 struct map_symbol *selection;
26 int print_seq;
26 bool has_symbols; 27 bool has_symbols;
27}; 28};
28 29
@@ -800,6 +801,196 @@ do_offset:
800 } 801 }
801} 802}
802 803
804static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
805 struct callchain_node *chain_node,
806 u64 total, int level,
807 FILE *fp)
808{
809 struct rb_node *node;
810 int offset = level * LEVEL_OFFSET_STEP;
811 u64 new_total, remaining;
812 int printed = 0;
813
814 if (callchain_param.mode == CHAIN_GRAPH_REL)
815 new_total = chain_node->children_hit;
816 else
817 new_total = total;
818
819 remaining = new_total;
820 node = rb_first(&chain_node->rb_root);
821 while (node) {
822 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
823 struct rb_node *next = rb_next(node);
824 u64 cumul = callchain_cumul_hits(child);
825 struct callchain_list *chain;
826 char folded_sign = ' ';
827 int first = true;
828 int extra_offset = 0;
829
830 remaining -= cumul;
831
832 list_for_each_entry(chain, &child->val, list) {
833 char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str;
834 const char *str;
835 bool was_first = first;
836
837 if (first)
838 first = false;
839 else
840 extra_offset = LEVEL_OFFSET_STEP;
841
842 folded_sign = callchain_list__folded(chain);
843
844 alloc_str = NULL;
845 str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
846 if (was_first) {
847 double percent = cumul * 100.0 / new_total;
848
849 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
850 str = "Not enough memory!";
851 else
852 str = alloc_str;
853 }
854
855 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
856 free(alloc_str);
857 if (folded_sign == '+')
858 break;
859 }
860
861 if (folded_sign == '-') {
862 const int new_level = level + (extra_offset ? 2 : 1);
863 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
864 new_level, fp);
865 }
866
867 node = next;
868 }
869
870 return printed;
871}
872
873static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
874 struct callchain_node *node,
875 int level, FILE *fp)
876{
877 struct callchain_list *chain;
878 int offset = level * LEVEL_OFFSET_STEP;
879 char folded_sign = ' ';
880 int printed = 0;
881
882 list_for_each_entry(chain, &node->val, list) {
883 char ipstr[BITS_PER_LONG / 4 + 1], *s;
884
885 folded_sign = callchain_list__folded(chain);
886 s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
887 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
888 }
889
890 if (folded_sign == '-')
891 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
892 browser->hists->stats.total_period,
893 level + 1, fp);
894 return printed;
895}
896
897static int hist_browser__fprintf_callchain(struct hist_browser *browser,
898 struct rb_root *chain, int level, FILE *fp)
899{
900 struct rb_node *nd;
901 int printed = 0;
902
903 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
904 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
905
906 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp);
907 }
908
909 return printed;
910}
911
912static int hist_browser__fprintf_entry(struct hist_browser *browser,
913 struct hist_entry *he, FILE *fp)
914{
915 char s[8192];
916 double percent;
917 int printed = 0;
918 char folded_sign = ' ';
919
920 if (symbol_conf.use_callchain)
921 folded_sign = hist_entry__folded(he);
922
923 hist_entry__snprintf(he, s, sizeof(s), browser->hists);
924 percent = (he->period * 100.0) / browser->hists->stats.total_period;
925
926 if (symbol_conf.use_callchain)
927 printed += fprintf(fp, "%c ", folded_sign);
928
929 printed += fprintf(fp, " %5.2f%%", percent);
930
931 if (symbol_conf.show_nr_samples)
932 printed += fprintf(fp, " %11u", he->nr_events);
933
934 if (symbol_conf.show_total_period)
935 printed += fprintf(fp, " %12" PRIu64, he->period);
936
937 printed += fprintf(fp, "%s\n", rtrim(s));
938
939 if (folded_sign == '-')
940 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp);
941
942 return printed;
943}
944
945static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)
946{
947 struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries));
948 int printed = 0;
949
950 while (nd) {
951 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
952
953 printed += hist_browser__fprintf_entry(browser, h, fp);
954 nd = hists__filter_entries(rb_next(nd));
955 }
956
957 return printed;
958}
959
960static int hist_browser__dump(struct hist_browser *browser)
961{
962 char filename[64];
963 FILE *fp;
964
965 while (1) {
966 scnprintf(filename, sizeof(filename), "perf.hist.%d", browser->print_seq);
967 if (access(filename, F_OK))
968 break;
969 /*
970 * XXX: Just an arbitrary lazy upper limit
971 */
972 if (++browser->print_seq == 8192) {
973 ui_helpline__fpush("Too many perf.hist.N files, nothing written!");
974 return -1;
975 }
976 }
977
978 fp = fopen(filename, "w");
979 if (fp == NULL) {
980 char bf[64];
981 strerror_r(errno, bf, sizeof(bf));
982 ui_helpline__fpush("Couldn't write to %s: %s", filename, bf);
983 return -1;
984 }
985
986 ++browser->print_seq;
987 hist_browser__fprintf(browser, fp);
988 fclose(fp);
989 ui_helpline__fpush("%s written!", filename);
990
991 return 0;
992}
993
803static struct hist_browser *hist_browser__new(struct hists *hists) 994static struct hist_browser *hist_browser__new(struct hists *hists)
804{ 995{
805 struct hist_browser *browser = zalloc(sizeof(*browser)); 996 struct hist_browser *browser = zalloc(sizeof(*browser));
@@ -937,6 +1128,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
937 browser->selection->map->dso->annotate_warned) 1128 browser->selection->map->dso->annotate_warned)
938 continue; 1129 continue;
939 goto do_annotate; 1130 goto do_annotate;
1131 case 'P':
1132 hist_browser__dump(browser);
1133 continue;
940 case 'd': 1134 case 'd':
941 goto zoom_dso; 1135 goto zoom_dso;
942 case 't': 1136 case 't':
@@ -969,6 +1163,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
969 "E Expand all callchains\n" 1163 "E Expand all callchains\n"
970 "d Zoom into current DSO\n" 1164 "d Zoom into current DSO\n"
971 "t Zoom into current Thread\n" 1165 "t Zoom into current Thread\n"
1166 "P Print histograms to perf.hist.N\n"
972 "/ Filter symbol by name"); 1167 "/ Filter symbol by name");
973 continue; 1168 continue;
974 case K_ENTER: 1169 case K_ENTER:
@@ -1172,7 +1367,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1172 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1367 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1173 bool current_entry = ui_browser__is_current_entry(browser, row); 1368 bool current_entry = ui_browser__is_current_entry(browser, row);
1174 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1369 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1175 const char *ev_name = event_name(evsel); 1370 const char *ev_name = perf_evsel__name(evsel);
1176 char bf[256], unit; 1371 char bf[256], unit;
1177 const char *warn = " "; 1372 const char *warn = " ";
1178 size_t printed; 1373 size_t printed;
@@ -1240,7 +1435,7 @@ browse_hists:
1240 */ 1435 */
1241 if (timer) 1436 if (timer)
1242 timer(arg); 1437 timer(arg);
1243 ev_name = event_name(pos); 1438 ev_name = perf_evsel__name(pos);
1244 key = perf_evsel__hists_browse(pos, nr_events, help, 1439 key = perf_evsel__hists_browse(pos, nr_events, help,
1245 ev_name, true, timer, 1440 ev_name, true, timer,
1246 arg, delay_secs); 1441 arg, delay_secs);
@@ -1309,17 +1504,11 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1309 ui_helpline__push("Press ESC to exit"); 1504 ui_helpline__push("Press ESC to exit");
1310 1505
1311 list_for_each_entry(pos, &evlist->entries, node) { 1506 list_for_each_entry(pos, &evlist->entries, node) {
1312 const char *ev_name = event_name(pos); 1507 const char *ev_name = perf_evsel__name(pos);
1313 size_t line_len = strlen(ev_name) + 7; 1508 size_t line_len = strlen(ev_name) + 7;
1314 1509
1315 if (menu.b.width < line_len) 1510 if (menu.b.width < line_len)
1316 menu.b.width = line_len; 1511 menu.b.width = line_len;
1317 /*
1318 * Cache the evsel name, tracepoints have a _high_ cost per
1319 * event_name() call.
1320 */
1321 if (pos->name == NULL)
1322 pos->name = strdup(ev_name);
1323 } 1512 }
1324 1513
1325 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, 1514 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer,
@@ -1330,11 +1519,10 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
1330 void(*timer)(void *arg), void *arg, 1519 void(*timer)(void *arg), void *arg,
1331 int delay_secs) 1520 int delay_secs)
1332{ 1521{
1333
1334 if (evlist->nr_entries == 1) { 1522 if (evlist->nr_entries == 1) {
1335 struct perf_evsel *first = list_entry(evlist->entries.next, 1523 struct perf_evsel *first = list_entry(evlist->entries.next,
1336 struct perf_evsel, node); 1524 struct perf_evsel, node);
1337 const char *ev_name = event_name(first); 1525 const char *ev_name = perf_evsel__name(first);
1338 return perf_evsel__hists_browse(first, evlist->nr_entries, help, 1526 return perf_evsel__hists_browse(first, evlist->nr_entries, help,
1339 ev_name, false, timer, arg, 1527 ev_name, false, timer, arg,
1340 delay_secs); 1528 delay_secs);
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 0656c381a89c..ec12e0b4ded6 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -11,8 +11,8 @@
11 11
12static void perf_gtk__signal(int sig) 12static void perf_gtk__signal(int sig)
13{ 13{
14 perf_gtk__exit(false);
14 psignal(sig, "perf"); 15 psignal(sig, "perf");
15 gtk_main_quit();
16} 16}
17 17
18static void perf_gtk__resize_window(GtkWidget *window) 18static void perf_gtk__resize_window(GtkWidget *window)
@@ -122,13 +122,59 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
122 gtk_container_add(GTK_CONTAINER(window), view); 122 gtk_container_add(GTK_CONTAINER(window), view);
123} 123}
124 124
125#ifdef HAVE_GTK_INFO_BAR
126static GtkWidget *perf_gtk__setup_info_bar(void)
127{
128 GtkWidget *info_bar;
129 GtkWidget *label;
130 GtkWidget *content_area;
131
132 info_bar = gtk_info_bar_new();
133 gtk_widget_set_no_show_all(info_bar, TRUE);
134
135 label = gtk_label_new("");
136 gtk_widget_show(label);
137
138 content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar));
139 gtk_container_add(GTK_CONTAINER(content_area), label);
140
141 gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), GTK_STOCK_OK,
142 GTK_RESPONSE_OK);
143 g_signal_connect(info_bar, "response",
144 G_CALLBACK(gtk_widget_hide), NULL);
145
146 pgctx->info_bar = info_bar;
147 pgctx->message_label = label;
148
149 return info_bar;
150}
151#endif
152
153static GtkWidget *perf_gtk__setup_statusbar(void)
154{
155 GtkWidget *stbar;
156 unsigned ctxid;
157
158 stbar = gtk_statusbar_new();
159
160 ctxid = gtk_statusbar_get_context_id(GTK_STATUSBAR(stbar),
161 "perf report");
162 pgctx->statbar = stbar;
163 pgctx->statbar_ctx_id = ctxid;
164
165 return stbar;
166}
167
125int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, 168int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
126 const char *help __used, 169 const char *help __used,
127 void (*timer) (void *arg)__used, 170 void (*timer) (void *arg)__used,
128 void *arg __used, int delay_secs __used) 171 void *arg __used, int delay_secs __used)
129{ 172{
130 struct perf_evsel *pos; 173 struct perf_evsel *pos;
174 GtkWidget *vbox;
131 GtkWidget *notebook; 175 GtkWidget *notebook;
176 GtkWidget *info_bar;
177 GtkWidget *statbar;
132 GtkWidget *window; 178 GtkWidget *window;
133 179
134 signal(SIGSEGV, perf_gtk__signal); 180 signal(SIGSEGV, perf_gtk__signal);
@@ -143,11 +189,17 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
143 189
144 g_signal_connect(window, "delete_event", gtk_main_quit, NULL); 190 g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
145 191
192 pgctx = perf_gtk__activate_context(window);
193 if (!pgctx)
194 return -1;
195
196 vbox = gtk_vbox_new(FALSE, 0);
197
146 notebook = gtk_notebook_new(); 198 notebook = gtk_notebook_new();
147 199
148 list_for_each_entry(pos, &evlist->entries, node) { 200 list_for_each_entry(pos, &evlist->entries, node) {
149 struct hists *hists = &pos->hists; 201 struct hists *hists = &pos->hists;
150 const char *evname = event_name(pos); 202 const char *evname = perf_evsel__name(pos);
151 GtkWidget *scrolled_window; 203 GtkWidget *scrolled_window;
152 GtkWidget *tab_label; 204 GtkWidget *tab_label;
153 205
@@ -164,7 +216,16 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
164 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); 216 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
165 } 217 }
166 218
167 gtk_container_add(GTK_CONTAINER(window), notebook); 219 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
220
221 info_bar = perf_gtk__setup_info_bar();
222 if (info_bar)
223 gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
224
225 statbar = perf_gtk__setup_statusbar();
226 gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
227
228 gtk_container_add(GTK_CONTAINER(window), vbox);
168 229
169 gtk_widget_show_all(window); 230 gtk_widget_show_all(window);
170 231
@@ -174,5 +235,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
174 235
175 gtk_main(); 236 gtk_main();
176 237
238 perf_gtk__deactivate_context(&pgctx);
239
177 return 0; 240 return 0;
178} 241}
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 75177ee04032..a4d0f2b4a2dc 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -1,8 +1,39 @@
1#ifndef _PERF_GTK_H_ 1#ifndef _PERF_GTK_H_
2#define _PERF_GTK_H_ 1 2#define _PERF_GTK_H_ 1
3 3
4#include <stdbool.h>
5
4#pragma GCC diagnostic ignored "-Wstrict-prototypes" 6#pragma GCC diagnostic ignored "-Wstrict-prototypes"
5#include <gtk/gtk.h> 7#include <gtk/gtk.h>
6#pragma GCC diagnostic error "-Wstrict-prototypes" 8#pragma GCC diagnostic error "-Wstrict-prototypes"
7 9
10
11struct perf_gtk_context {
12 GtkWidget *main_window;
13
14#ifdef HAVE_GTK_INFO_BAR
15 GtkWidget *info_bar;
16 GtkWidget *message_label;
17#endif
18 GtkWidget *statbar;
19 guint statbar_ctx_id;
20};
21
22extern struct perf_gtk_context *pgctx;
23
24static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
25{
26 return ctx && ctx->main_window;
27}
28
29struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
30int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
31
32#ifndef HAVE_GTK_INFO_BAR
33static inline GtkWidget *perf_gtk__setup_info_bar(void)
34{
35 return NULL;
36}
37#endif
38
8#endif /* _PERF_GTK_H_ */ 39#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 829529957766..92879ce61e2f 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -1,12 +1,17 @@
1#include "gtk.h" 1#include "gtk.h"
2#include "../../util/cache.h" 2#include "../../util/cache.h"
3#include "../../util/debug.h"
4
5extern struct perf_error_ops perf_gtk_eops;
3 6
4int perf_gtk__init(void) 7int perf_gtk__init(void)
5{ 8{
9 perf_error__register(&perf_gtk_eops);
6 return gtk_init_check(NULL, NULL) ? 0 : -1; 10 return gtk_init_check(NULL, NULL) ? 0 : -1;
7} 11}
8 12
9void perf_gtk__exit(bool wait_for_ok __used) 13void perf_gtk__exit(bool wait_for_ok __used)
10{ 14{
15 perf_error__unregister(&perf_gtk_eops);
11 gtk_main_quit(); 16 gtk_main_quit();
12} 17}
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
new file mode 100644
index 000000000000..0ead373c0dfb
--- /dev/null
+++ b/tools/perf/ui/gtk/util.c
@@ -0,0 +1,129 @@
1#include "../util.h"
2#include "../../util/debug.h"
3#include "gtk.h"
4
5#include <string.h>
6
7
8struct perf_gtk_context *pgctx;
9
10struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window)
11{
12 struct perf_gtk_context *ctx;
13
14 ctx = malloc(sizeof(*pgctx));
15 if (ctx)
16 ctx->main_window = window;
17
18 return ctx;
19}
20
21int perf_gtk__deactivate_context(struct perf_gtk_context **ctx)
22{
23 if (!perf_gtk__is_active_context(*ctx))
24 return -1;
25
26 free(*ctx);
27 *ctx = NULL;
28 return 0;
29}
30
31static int perf_gtk__error(const char *format, va_list args)
32{
33 char *msg;
34 GtkWidget *dialog;
35
36 if (!perf_gtk__is_active_context(pgctx) ||
37 vasprintf(&msg, format, args) < 0) {
38 fprintf(stderr, "Error:\n");
39 vfprintf(stderr, format, args);
40 fprintf(stderr, "\n");
41 return -1;
42 }
43
44 dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(pgctx->main_window),
45 GTK_DIALOG_DESTROY_WITH_PARENT,
46 GTK_MESSAGE_ERROR,
47 GTK_BUTTONS_CLOSE,
48 "<b>Error</b>\n\n%s", msg);
49 gtk_dialog_run(GTK_DIALOG(dialog));
50
51 gtk_widget_destroy(dialog);
52 free(msg);
53 return 0;
54}
55
56#ifdef HAVE_GTK_INFO_BAR
57static int perf_gtk__warning_info_bar(const char *format, va_list args)
58{
59 char *msg;
60
61 if (!perf_gtk__is_active_context(pgctx) ||
62 vasprintf(&msg, format, args) < 0) {
63 fprintf(stderr, "Warning:\n");
64 vfprintf(stderr, format, args);
65 fprintf(stderr, "\n");
66 return -1;
67 }
68
69 gtk_label_set_text(GTK_LABEL(pgctx->message_label), msg);
70 gtk_info_bar_set_message_type(GTK_INFO_BAR(pgctx->info_bar),
71 GTK_MESSAGE_WARNING);
72 gtk_widget_show(pgctx->info_bar);
73
74 free(msg);
75 return 0;
76}
77#else
78static int perf_gtk__warning_statusbar(const char *format, va_list args)
79{
80 char *msg, *p;
81
82 if (!perf_gtk__is_active_context(pgctx) ||
83 vasprintf(&msg, format, args) < 0) {
84 fprintf(stderr, "Warning:\n");
85 vfprintf(stderr, format, args);
86 fprintf(stderr, "\n");
87 return -1;
88 }
89
90 gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar),
91 pgctx->statbar_ctx_id);
92
93 /* Only first line can be displayed */
94 p = strchr(msg, '\n');
95 if (p)
96 *p = '\0';
97
98 gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar),
99 pgctx->statbar_ctx_id, msg);
100
101 free(msg);
102 return 0;
103}
104#endif
105
106struct perf_error_ops perf_gtk_eops = {
107 .error = perf_gtk__error,
108#ifdef HAVE_GTK_INFO_BAR
109 .warning = perf_gtk__warning_info_bar,
110#else
111 .warning = perf_gtk__warning_statusbar,
112#endif
113};
114
115/*
116 * FIXME: Functions below should be implemented properly.
117 * For now, just add stubs for NO_NEWT=1 build.
118 */
119#ifdef NO_NEWT_SUPPORT
120int ui_helpline__show_help(const char *format __used, va_list ap __used)
121{
122 return 0;
123}
124
125void ui_progress__update(u64 curr __used, u64 total __used,
126 const char *title __used)
127{
128}
129#endif
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index d33e943ac434..e813c1d17346 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -15,6 +15,8 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
15 15
16static volatile int ui__need_resize; 16static volatile int ui__need_resize;
17 17
18extern struct perf_error_ops perf_tui_eops;
19
18void ui__refresh_dimensions(bool force) 20void ui__refresh_dimensions(bool force)
19{ 21{
20 if (force || ui__need_resize) { 22 if (force || ui__need_resize) {
@@ -122,6 +124,8 @@ int ui__init(void)
122 signal(SIGINT, ui__signal); 124 signal(SIGINT, ui__signal);
123 signal(SIGQUIT, ui__signal); 125 signal(SIGQUIT, ui__signal);
124 signal(SIGTERM, ui__signal); 126 signal(SIGTERM, ui__signal);
127
128 perf_error__register(&perf_tui_eops);
125out: 129out:
126 return err; 130 return err;
127} 131}
@@ -137,4 +141,6 @@ void ui__exit(bool wait_for_ok)
137 SLsmg_refresh(); 141 SLsmg_refresh();
138 SLsmg_reset_smg(); 142 SLsmg_reset_smg();
139 SLang_reset_tty(); 143 SLang_reset_tty();
144
145 perf_error__unregister(&perf_tui_eops);
140} 146}
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
new file mode 100644
index 000000000000..092902e30cee
--- /dev/null
+++ b/tools/perf/ui/tui/util.c
@@ -0,0 +1,243 @@
1#include "../../util/util.h"
2#include <signal.h>
3#include <stdbool.h>
4#include <string.h>
5#include <sys/ttydefaults.h>
6
7#include "../../util/cache.h"
8#include "../../util/debug.h"
9#include "../browser.h"
10#include "../keysyms.h"
11#include "../helpline.h"
12#include "../ui.h"
13#include "../util.h"
14#include "../libslang.h"
15
16static void ui_browser__argv_write(struct ui_browser *browser,
17 void *entry, int row)
18{
19 char **arg = entry;
20 bool current_entry = ui_browser__is_current_entry(browser, row);
21
22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
23 HE_COLORSET_NORMAL);
24 slsmg_write_nstring(*arg, browser->width);
25}
26
27static int popup_menu__run(struct ui_browser *menu)
28{
29 int key;
30
31 if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
32 return -1;
33
34 while (1) {
35 key = ui_browser__run(menu, 0);
36
37 switch (key) {
38 case K_RIGHT:
39 case K_ENTER:
40 key = menu->index;
41 break;
42 case K_LEFT:
43 case K_ESC:
44 case 'q':
45 case CTRL('c'):
46 key = -1;
47 break;
48 default:
49 continue;
50 }
51
52 break;
53 }
54
55 ui_browser__hide(menu);
56 return key;
57}
58
59int ui__popup_menu(int argc, char * const argv[])
60{
61 struct ui_browser menu = {
62 .entries = (void *)argv,
63 .refresh = ui_browser__argv_refresh,
64 .seek = ui_browser__argv_seek,
65 .write = ui_browser__argv_write,
66 .nr_entries = argc,
67 };
68
69 return popup_menu__run(&menu);
70}
71
72int ui_browser__input_window(const char *title, const char *text, char *input,
73 const char *exit_msg, int delay_secs)
74{
75 int x, y, len, key;
76 int max_len = 60, nr_lines = 0;
77 static char buf[50];
78 const char *t;
79
80 t = text;
81 while (1) {
82 const char *sep = strchr(t, '\n');
83
84 if (sep == NULL)
85 sep = strchr(t, '\0');
86 len = sep - t;
87 if (max_len < len)
88 max_len = len;
89 ++nr_lines;
90 if (*sep == '\0')
91 break;
92 t = sep + 1;
93 }
94
95 max_len += 2;
96 nr_lines += 8;
97 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
98 x = SLtt_Screen_Cols / 2 - max_len / 2;
99
100 SLsmg_set_color(0);
101 SLsmg_draw_box(y, x++, nr_lines, max_len);
102 if (title) {
103 SLsmg_gotorc(y, x + 1);
104 SLsmg_write_string((char *)title);
105 }
106 SLsmg_gotorc(++y, x);
107 nr_lines -= 7;
108 max_len -= 2;
109 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
110 nr_lines, max_len, 1);
111 y += nr_lines;
112 len = 5;
113 while (len--) {
114 SLsmg_gotorc(y + len - 1, x);
115 SLsmg_write_nstring((char *)" ", max_len);
116 }
117 SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
118
119 SLsmg_gotorc(y + 3, x);
120 SLsmg_write_nstring((char *)exit_msg, max_len);
121 SLsmg_refresh();
122
123 x += 2;
124 len = 0;
125 key = ui__getch(delay_secs);
126 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
127 if (key == K_BKSPC) {
128 if (len == 0)
129 goto next_key;
130 SLsmg_gotorc(y, x + --len);
131 SLsmg_write_char(' ');
132 } else {
133 buf[len] = key;
134 SLsmg_gotorc(y, x + len++);
135 SLsmg_write_char(key);
136 }
137 SLsmg_refresh();
138
139 /* XXX more graceful overflow handling needed */
140 if (len == sizeof(buf) - 1) {
141 ui_helpline__push("maximum size of symbol name reached!");
142 key = K_ENTER;
143 break;
144 }
145next_key:
146 key = ui__getch(delay_secs);
147 }
148
149 buf[len] = '\0';
150 strncpy(input, buf, len+1);
151 return key;
152}
153
154int ui__question_window(const char *title, const char *text,
155 const char *exit_msg, int delay_secs)
156{
157 int x, y;
158 int max_len = 0, nr_lines = 0;
159 const char *t;
160
161 t = text;
162 while (1) {
163 const char *sep = strchr(t, '\n');
164 int len;
165
166 if (sep == NULL)
167 sep = strchr(t, '\0');
168 len = sep - t;
169 if (max_len < len)
170 max_len = len;
171 ++nr_lines;
172 if (*sep == '\0')
173 break;
174 t = sep + 1;
175 }
176
177 max_len += 2;
178 nr_lines += 4;
179 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
180 x = SLtt_Screen_Cols / 2 - max_len / 2;
181
182 SLsmg_set_color(0);
183 SLsmg_draw_box(y, x++, nr_lines, max_len);
184 if (title) {
185 SLsmg_gotorc(y, x + 1);
186 SLsmg_write_string((char *)title);
187 }
188 SLsmg_gotorc(++y, x);
189 nr_lines -= 2;
190 max_len -= 2;
191 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
192 nr_lines, max_len, 1);
193 SLsmg_gotorc(y + nr_lines - 2, x);
194 SLsmg_write_nstring((char *)" ", max_len);
195 SLsmg_gotorc(y + nr_lines - 1, x);
196 SLsmg_write_nstring((char *)exit_msg, max_len);
197 SLsmg_refresh();
198 return ui__getch(delay_secs);
199}
200
201int ui__help_window(const char *text)
202{
203 return ui__question_window("Help", text, "Press any key...", 0);
204}
205
206int ui__dialog_yesno(const char *msg)
207{
208 return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
209}
210
211static int __ui__warning(const char *title, const char *format, va_list args)
212{
213 char *s;
214
215 if (vasprintf(&s, format, args) > 0) {
216 int key;
217
218 pthread_mutex_lock(&ui__lock);
219 key = ui__question_window(title, s, "Press any key...", 0);
220 pthread_mutex_unlock(&ui__lock);
221 free(s);
222 return key;
223 }
224
225 fprintf(stderr, "%s\n", title);
226 vfprintf(stderr, format, args);
227 return K_ESC;
228}
229
230static int perf_tui__error(const char *format, va_list args)
231{
232 return __ui__warning("Error:", format, args);
233}
234
235static int perf_tui__warning(const char *format, va_list args)
236{
237 return __ui__warning("Warning:", format, args);
238}
239
240struct perf_error_ops perf_tui_eops = {
241 .error = perf_tui__error,
242 .warning = perf_tui__warning,
243};
diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c
index ad4374a16bb0..4f989774c8c6 100644
--- a/tools/perf/ui/util.c
+++ b/tools/perf/ui/util.c
@@ -1,250 +1,85 @@
1#include "../util.h"
2#include <signal.h>
3#include <stdbool.h>
4#include <string.h>
5#include <sys/ttydefaults.h>
6
7#include "../cache.h"
8#include "../debug.h"
9#include "browser.h"
10#include "keysyms.h"
11#include "helpline.h"
12#include "ui.h"
13#include "util.h" 1#include "util.h"
14#include "libslang.h" 2#include "../debug.h"
15
16static void ui_browser__argv_write(struct ui_browser *browser,
17 void *entry, int row)
18{
19 char **arg = entry;
20 bool current_entry = ui_browser__is_current_entry(browser, row);
21
22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
23 HE_COLORSET_NORMAL);
24 slsmg_write_nstring(*arg, browser->width);
25}
26
27static int popup_menu__run(struct ui_browser *menu)
28{
29 int key;
30
31 if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
32 return -1;
33 3
34 while (1) {
35 key = ui_browser__run(menu, 0);
36
37 switch (key) {
38 case K_RIGHT:
39 case K_ENTER:
40 key = menu->index;
41 break;
42 case K_LEFT:
43 case K_ESC:
44 case 'q':
45 case CTRL('c'):
46 key = -1;
47 break;
48 default:
49 continue;
50 }
51
52 break;
53 }
54
55 ui_browser__hide(menu);
56 return key;
57}
58 4
59int ui__popup_menu(int argc, char * const argv[]) 5/*
6 * Default error logging functions
7 */
8static int perf_stdio__error(const char *format, va_list args)
60{ 9{
61 struct ui_browser menu = { 10 fprintf(stderr, "Error:\n");
62 .entries = (void *)argv, 11 vfprintf(stderr, format, args);
63 .refresh = ui_browser__argv_refresh, 12 return 0;
64 .seek = ui_browser__argv_seek,
65 .write = ui_browser__argv_write,
66 .nr_entries = argc,
67 };
68
69 return popup_menu__run(&menu);
70} 13}
71 14
72int ui_browser__input_window(const char *title, const char *text, char *input, 15static int perf_stdio__warning(const char *format, va_list args)
73 const char *exit_msg, int delay_secs)
74{ 16{
75 int x, y, len, key; 17 fprintf(stderr, "Warning:\n");
76 int max_len = 60, nr_lines = 0; 18 vfprintf(stderr, format, args);
77 static char buf[50]; 19 return 0;
78 const char *t;
79
80 t = text;
81 while (1) {
82 const char *sep = strchr(t, '\n');
83
84 if (sep == NULL)
85 sep = strchr(t, '\0');
86 len = sep - t;
87 if (max_len < len)
88 max_len = len;
89 ++nr_lines;
90 if (*sep == '\0')
91 break;
92 t = sep + 1;
93 }
94
95 max_len += 2;
96 nr_lines += 8;
97 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
98 x = SLtt_Screen_Cols / 2 - max_len / 2;
99
100 SLsmg_set_color(0);
101 SLsmg_draw_box(y, x++, nr_lines, max_len);
102 if (title) {
103 SLsmg_gotorc(y, x + 1);
104 SLsmg_write_string((char *)title);
105 }
106 SLsmg_gotorc(++y, x);
107 nr_lines -= 7;
108 max_len -= 2;
109 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
110 nr_lines, max_len, 1);
111 y += nr_lines;
112 len = 5;
113 while (len--) {
114 SLsmg_gotorc(y + len - 1, x);
115 SLsmg_write_nstring((char *)" ", max_len);
116 }
117 SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
118
119 SLsmg_gotorc(y + 3, x);
120 SLsmg_write_nstring((char *)exit_msg, max_len);
121 SLsmg_refresh();
122
123 x += 2;
124 len = 0;
125 key = ui__getch(delay_secs);
126 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
127 if (key == K_BKSPC) {
128 if (len == 0)
129 goto next_key;
130 SLsmg_gotorc(y, x + --len);
131 SLsmg_write_char(' ');
132 } else {
133 buf[len] = key;
134 SLsmg_gotorc(y, x + len++);
135 SLsmg_write_char(key);
136 }
137 SLsmg_refresh();
138
139 /* XXX more graceful overflow handling needed */
140 if (len == sizeof(buf) - 1) {
141 ui_helpline__push("maximum size of symbol name reached!");
142 key = K_ENTER;
143 break;
144 }
145next_key:
146 key = ui__getch(delay_secs);
147 }
148
149 buf[len] = '\0';
150 strncpy(input, buf, len+1);
151 return key;
152} 20}
153 21
154int ui__question_window(const char *title, const char *text, 22static struct perf_error_ops default_eops =
155 const char *exit_msg, int delay_secs)
156{ 23{
157 int x, y; 24 .error = perf_stdio__error,
158 int max_len = 0, nr_lines = 0; 25 .warning = perf_stdio__warning,
159 const char *t; 26};
160
161 t = text;
162 while (1) {
163 const char *sep = strchr(t, '\n');
164 int len;
165
166 if (sep == NULL)
167 sep = strchr(t, '\0');
168 len = sep - t;
169 if (max_len < len)
170 max_len = len;
171 ++nr_lines;
172 if (*sep == '\0')
173 break;
174 t = sep + 1;
175 }
176
177 max_len += 2;
178 nr_lines += 4;
179 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
180 x = SLtt_Screen_Cols / 2 - max_len / 2;
181
182 SLsmg_set_color(0);
183 SLsmg_draw_box(y, x++, nr_lines, max_len);
184 if (title) {
185 SLsmg_gotorc(y, x + 1);
186 SLsmg_write_string((char *)title);
187 }
188 SLsmg_gotorc(++y, x);
189 nr_lines -= 2;
190 max_len -= 2;
191 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
192 nr_lines, max_len, 1);
193 SLsmg_gotorc(y + nr_lines - 2, x);
194 SLsmg_write_nstring((char *)" ", max_len);
195 SLsmg_gotorc(y + nr_lines - 1, x);
196 SLsmg_write_nstring((char *)exit_msg, max_len);
197 SLsmg_refresh();
198 return ui__getch(delay_secs);
199}
200 27
201int ui__help_window(const char *text) 28static struct perf_error_ops *perf_eops = &default_eops;
202{
203 return ui__question_window("Help", text, "Press any key...", 0);
204}
205 29
206int ui__dialog_yesno(const char *msg)
207{
208 return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
209}
210 30
211int __ui__warning(const char *title, const char *format, va_list args) 31int ui__error(const char *format, ...)
212{ 32{
213 char *s; 33 int ret;
214 34 va_list args;
215 if (use_browser > 0 && vasprintf(&s, format, args) > 0) {
216 int key;
217 35
218 pthread_mutex_lock(&ui__lock); 36 va_start(args, format);
219 key = ui__question_window(title, s, "Press any key...", 0); 37 ret = perf_eops->error(format, args);
220 pthread_mutex_unlock(&ui__lock); 38 va_end(args);
221 free(s);
222 return key;
223 }
224 39
225 fprintf(stderr, "%s:\n", title); 40 return ret;
226 vfprintf(stderr, format, args);
227 return K_ESC;
228} 41}
229 42
230int ui__warning(const char *format, ...) 43int ui__warning(const char *format, ...)
231{ 44{
232 int key; 45 int ret;
233 va_list args; 46 va_list args;
234 47
235 va_start(args, format); 48 va_start(args, format);
236 key = __ui__warning("Warning", format, args); 49 ret = perf_eops->warning(format, args);
237 va_end(args); 50 va_end(args);
238 return key; 51
52 return ret;
239} 53}
240 54
241int ui__error(const char *format, ...) 55
56/**
57 * perf_error__register - Register error logging functions
58 * @eops: The pointer to error logging function struct
59 *
60 * Register UI-specific error logging functions. Before calling this,
61 * other logging functions should be unregistered, if any.
62 */
63int perf_error__register(struct perf_error_ops *eops)
242{ 64{
243 int key; 65 if (perf_eops != &default_eops)
244 va_list args; 66 return -1;
245 67
246 va_start(args, format); 68 perf_eops = eops;
247 key = __ui__warning("Error", format, args); 69 return 0;
248 va_end(args); 70}
249 return key; 71
72/**
73 * perf_error__unregister - Unregister error logging functions
74 * @eops: The pointer to error logging function struct
75 *
76 * Unregister already registered error logging functions.
77 */
78int perf_error__unregister(struct perf_error_ops *eops)
79{
80 if (perf_eops != eops)
81 return -1;
82
83 perf_eops = &default_eops;
84 return 0;
250} 85}
diff --git a/tools/perf/ui/util.h b/tools/perf/ui/util.h
index 2d1738bd71c8..361f08c52d37 100644
--- a/tools/perf/ui/util.h
+++ b/tools/perf/ui/util.h
@@ -9,6 +9,13 @@ int ui__help_window(const char *text);
9int ui__dialog_yesno(const char *msg); 9int ui__dialog_yesno(const char *msg);
10int ui__question_window(const char *title, const char *text, 10int ui__question_window(const char *title, const char *text,
11 const char *exit_msg, int delay_secs); 11 const char *exit_msg, int delay_secs);
12int __ui__warning(const char *title, const char *format, va_list args); 12
13struct perf_error_ops {
14 int (*error)(const char *format, va_list args);
15 int (*warning)(const char *format, va_list args);
16};
17
18int perf_error__register(struct perf_error_ops *eops);
19int perf_error__unregister(struct perf_error_ops *eops);
13 20
14#endif /* _PERF_UI_UTIL_H_ */ 21#endif /* _PERF_UI_UTIL_H_ */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index efb1fce259a4..4dfe0bb3c322 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -47,7 +47,7 @@ int dump_printf(const char *fmt, ...)
47 return ret; 47 return ret;
48} 48}
49 49
50#ifdef NO_NEWT_SUPPORT 50#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
51int ui__warning(const char *format, ...) 51int ui__warning(const char *format, ...)
52{ 52{
53 va_list args; 53 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 6bebe7f0a20c..015c91dbc096 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -12,8 +12,9 @@ int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
12void trace_event(union perf_event *event); 12void trace_event(union perf_event *event);
13 13
14struct ui_progress; 14struct ui_progress;
15struct perf_error_ops;
15 16
16#ifdef NO_NEWT_SUPPORT 17#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
17static inline int ui_helpline__show_help(const char *format __used, va_list ap __used) 18static inline int ui_helpline__show_help(const char *format __used, va_list ap __used)
18{ 19{
19 return 0; 20 return 0;
@@ -23,12 +24,28 @@ static inline void ui_progress__update(u64 curr __used, u64 total __used,
23 const char *title __used) {} 24 const char *title __used) {}
24 25
25#define ui__error(format, arg...) ui__warning(format, ##arg) 26#define ui__error(format, arg...) ui__warning(format, ##arg)
26#else 27
28static inline int
29perf_error__register(struct perf_error_ops *eops __used)
30{
31 return 0;
32}
33
34static inline int
35perf_error__unregister(struct perf_error_ops *eops __used)
36{
37 return 0;
38}
39
40#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
41
27extern char ui_helpline__last_msg[]; 42extern char ui_helpline__last_msg[];
28int ui_helpline__show_help(const char *format, va_list ap); 43int ui_helpline__show_help(const char *format, va_list ap);
29#include "../ui/progress.h" 44#include "../ui/progress.h"
30int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 45int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
31#endif 46#include "../ui/util.h"
47
48#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
32 49
33int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 50int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
34int ui__error_paranoid(void); 51int ui__error_paranoid(void);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 7400fb3fc50c..f74e9560350e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -224,8 +224,8 @@ out_free_attrs:
224 return err; 224 return err;
225} 225}
226 226
227static struct perf_evsel * 227struct perf_evsel *
228 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 228perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
229{ 229{
230 struct perf_evsel *evsel; 230 struct perf_evsel *evsel;
231 231
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 989bee9624c2..40d4d3cdced0 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -73,6 +73,9 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
75 75
76struct perf_evsel *
77perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
78
76void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 79void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
77 int cpu, int thread, u64 id); 80 int cpu, int thread, u64 id);
78 81
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9f6cebd798ee..e81771364867 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,7 +15,7 @@
15#include "cpumap.h" 15#include "cpumap.h"
16#include "thread_map.h" 16#include "thread_map.h"
17#include "target.h" 17#include "target.h"
18#include "../../include/linux/perf_event.h" 18#include "../../../include/linux/hw_breakpoint.h"
19 19
20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
21#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 21#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -78,7 +78,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
78 "ref-cycles", 78 "ref-cycles",
79}; 79};
80 80
81const char *__perf_evsel__hw_name(u64 config) 81static const char *__perf_evsel__hw_name(u64 config)
82{ 82{
83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) 83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
84 return perf_evsel__hw_names[config]; 84 return perf_evsel__hw_names[config];
@@ -86,16 +86,15 @@ const char *__perf_evsel__hw_name(u64 config)
86 return "unknown-hardware"; 86 return "unknown-hardware";
87} 87}
88 88
89static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) 89static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
90{ 90{
91 int colon = 0; 91 int colon = 0, r = 0;
92 struct perf_event_attr *attr = &evsel->attr; 92 struct perf_event_attr *attr = &evsel->attr;
93 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
94 bool exclude_guest_default = false; 93 bool exclude_guest_default = false;
95 94
96#define MOD_PRINT(context, mod) do { \ 95#define MOD_PRINT(context, mod) do { \
97 if (!attr->exclude_##context) { \ 96 if (!attr->exclude_##context) { \
98 if (!colon) colon = r++; \ 97 if (!colon) colon = ++r; \
99 r += scnprintf(bf + r, size - r, "%c", mod); \ 98 r += scnprintf(bf + r, size - r, "%c", mod); \
100 } } while(0) 99 } } while(0)
101 100
@@ -108,7 +107,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
108 107
109 if (attr->precise_ip) { 108 if (attr->precise_ip) {
110 if (!colon) 109 if (!colon)
111 colon = r++; 110 colon = ++r;
112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 111 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
113 exclude_guest_default = true; 112 exclude_guest_default = true;
114 } 113 }
@@ -119,39 +118,211 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
119 } 118 }
120#undef MOD_PRINT 119#undef MOD_PRINT
121 if (colon) 120 if (colon)
122 bf[colon] = ':'; 121 bf[colon - 1] = ':';
123 return r; 122 return r;
124} 123}
125 124
126int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) 125static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
126{
127 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
128 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
129}
130
131static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
132 "cpu-clock",
133 "task-clock",
134 "page-faults",
135 "context-switches",
136 "CPU-migrations",
137 "minor-faults",
138 "major-faults",
139 "alignment-faults",
140 "emulation-faults",
141};
142
143static const char *__perf_evsel__sw_name(u64 config)
127{ 144{
128 int ret; 145 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
146 return perf_evsel__sw_names[config];
147 return "unknown-software";
148}
149
150static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
151{
152 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
153 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
154}
155
156static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
157{
158 int r;
159
160 r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
161
162 if (type & HW_BREAKPOINT_R)
163 r += scnprintf(bf + r, size - r, "r");
164
165 if (type & HW_BREAKPOINT_W)
166 r += scnprintf(bf + r, size - r, "w");
167
168 if (type & HW_BREAKPOINT_X)
169 r += scnprintf(bf + r, size - r, "x");
170
171 return r;
172}
173
174static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
175{
176 struct perf_event_attr *attr = &evsel->attr;
177 int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
178 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
179}
180
181const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
182 [PERF_EVSEL__MAX_ALIASES] = {
183 { "L1-dcache", "l1-d", "l1d", "L1-data", },
184 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
185 { "LLC", "L2", },
186 { "dTLB", "d-tlb", "Data-TLB", },
187 { "iTLB", "i-tlb", "Instruction-TLB", },
188 { "branch", "branches", "bpu", "btb", "bpc", },
189 { "node", },
190};
191
192const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
193 [PERF_EVSEL__MAX_ALIASES] = {
194 { "load", "loads", "read", },
195 { "store", "stores", "write", },
196 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
197};
198
199const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
200 [PERF_EVSEL__MAX_ALIASES] = {
201 { "refs", "Reference", "ops", "access", },
202 { "misses", "miss", },
203};
204
205#define C(x) PERF_COUNT_HW_CACHE_##x
206#define CACHE_READ (1 << C(OP_READ))
207#define CACHE_WRITE (1 << C(OP_WRITE))
208#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
209#define COP(x) (1 << x)
210
211/*
212 * cache operartion stat
213 * L1I : Read and prefetch only
214 * ITLB and BPU : Read-only
215 */
216static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
217 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
218 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
219 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
220 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
221 [C(ITLB)] = (CACHE_READ),
222 [C(BPU)] = (CACHE_READ),
223 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
224};
225
226bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
227{
228 if (perf_evsel__hw_cache_stat[type] & COP(op))
229 return true; /* valid */
230 else
231 return false; /* invalid */
232}
233
234int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
235 char *bf, size_t size)
236{
237 if (result) {
238 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
239 perf_evsel__hw_cache_op[op][0],
240 perf_evsel__hw_cache_result[result][0]);
241 }
242
243 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
244 perf_evsel__hw_cache_op[op][1]);
245}
246
247static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
248{
249 u8 op, result, type = (config >> 0) & 0xff;
250 const char *err = "unknown-ext-hardware-cache-type";
251
252 if (type > PERF_COUNT_HW_CACHE_MAX)
253 goto out_err;
254
255 op = (config >> 8) & 0xff;
256 err = "unknown-ext-hardware-cache-op";
257 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
258 goto out_err;
259
260 result = (config >> 16) & 0xff;
261 err = "unknown-ext-hardware-cache-result";
262 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
263 goto out_err;
264
265 err = "invalid-cache";
266 if (!perf_evsel__is_cache_op_valid(type, op))
267 goto out_err;
268
269 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
270out_err:
271 return scnprintf(bf, size, "%s", err);
272}
273
274static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
275{
276 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
277 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
278}
279
280static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
281{
282 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
283 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
284}
285
286const char *perf_evsel__name(struct perf_evsel *evsel)
287{
288 char bf[128];
289
290 if (evsel->name)
291 return evsel->name;
129 292
130 switch (evsel->attr.type) { 293 switch (evsel->attr.type) {
131 case PERF_TYPE_RAW: 294 case PERF_TYPE_RAW:
132 ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); 295 perf_evsel__raw_name(evsel, bf, sizeof(bf));
133 break; 296 break;
134 297
135 case PERF_TYPE_HARDWARE: 298 case PERF_TYPE_HARDWARE:
136 ret = perf_evsel__hw_name(evsel, bf, size); 299 perf_evsel__hw_name(evsel, bf, sizeof(bf));
300 break;
301
302 case PERF_TYPE_HW_CACHE:
303 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
304 break;
305
306 case PERF_TYPE_SOFTWARE:
307 perf_evsel__sw_name(evsel, bf, sizeof(bf));
137 break; 308 break;
309
310 case PERF_TYPE_TRACEPOINT:
311 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
312 break;
313
314 case PERF_TYPE_BREAKPOINT:
315 perf_evsel__bp_name(evsel, bf, sizeof(bf));
316 break;
317
138 default: 318 default:
139 /* 319 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
140 * FIXME 320 break;
141 * 321 }
142 * This is the minimal perf_evsel__name so that we can 322
143 * reconstruct event names taking into account event modifiers. 323 evsel->name = strdup(bf);
144 * 324
145 * The old event_name uses it now for raw anr hw events, so that 325 return evsel->name ?: "unknown";
146 * we don't drag all the parsing stuff into the python binding.
147 *
148 * On the next devel cycle the rest of the event naming will be
149 * brought here.
150 */
151 return 0;
152 }
153
154 return ret;
155} 326}
156 327
157void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 328void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4ba8b564e6f4..67cc5033d192 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -83,8 +83,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts, 83 struct perf_record_opts *opts,
84 struct perf_evsel *first); 84 struct perf_evsel *first);
85 85
86const char* __perf_evsel__hw_name(u64 config); 86bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
87int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size); 87
88#define PERF_EVSEL__MAX_ALIASES 8
89
90extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
91 [PERF_EVSEL__MAX_ALIASES];
92extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
93 [PERF_EVSEL__MAX_ALIASES];
94const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
95 [PERF_EVSEL__MAX_ALIASES];
96int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
97 char *bf, size_t size);
98const char *perf_evsel__name(struct perf_evsel *evsel);
88 99
89int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 100int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
90int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 101int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e909d43cf542..5a47aba46759 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -641,7 +641,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
641 /* 641 /*
642 * write event string as passed on cmdline 642 * write event string as passed on cmdline
643 */ 643 */
644 ret = do_write_string(fd, event_name(attr)); 644 ret = do_write_string(fd, perf_evsel__name(attr));
645 if (ret < 0) 645 if (ret < 0)
646 return ret; 646 return ret;
647 /* 647 /*
@@ -1474,15 +1474,15 @@ out:
1474 1474
1475static int process_tracing_data(struct perf_file_section *section __unused, 1475static int process_tracing_data(struct perf_file_section *section __unused,
1476 struct perf_header *ph __unused, 1476 struct perf_header *ph __unused,
1477 int feat __unused, int fd) 1477 int feat __unused, int fd, void *data)
1478{ 1478{
1479 trace_report(fd, false); 1479 trace_report(fd, data, false);
1480 return 0; 1480 return 0;
1481} 1481}
1482 1482
1483static int process_build_id(struct perf_file_section *section, 1483static int process_build_id(struct perf_file_section *section,
1484 struct perf_header *ph, 1484 struct perf_header *ph,
1485 int feat __unused, int fd) 1485 int feat __unused, int fd, void *data __used)
1486{ 1486{
1487 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1487 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1488 pr_debug("Failed to read buildids, continuing...\n"); 1488 pr_debug("Failed to read buildids, continuing...\n");
@@ -1493,7 +1493,7 @@ struct feature_ops {
1493 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1493 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1494 void (*print)(struct perf_header *h, int fd, FILE *fp); 1494 void (*print)(struct perf_header *h, int fd, FILE *fp);
1495 int (*process)(struct perf_file_section *section, 1495 int (*process)(struct perf_file_section *section,
1496 struct perf_header *h, int feat, int fd); 1496 struct perf_header *h, int feat, int fd, void *data);
1497 const char *name; 1497 const char *name;
1498 bool full_only; 1498 bool full_only;
1499}; 1499};
@@ -1988,7 +1988,7 @@ int perf_file_header__read(struct perf_file_header *header,
1988 1988
1989static int perf_file_section__process(struct perf_file_section *section, 1989static int perf_file_section__process(struct perf_file_section *section,
1990 struct perf_header *ph, 1990 struct perf_header *ph,
1991 int feat, int fd, void *data __used) 1991 int feat, int fd, void *data)
1992{ 1992{
1993 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 1993 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
1994 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 1994 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2004,7 +2004,7 @@ static int perf_file_section__process(struct perf_file_section *section,
2004 if (!feat_ops[feat].process) 2004 if (!feat_ops[feat].process)
2005 return 0; 2005 return 0;
2006 2006
2007 return feat_ops[feat].process(section, ph, feat, fd); 2007 return feat_ops[feat].process(section, ph, feat, fd, data);
2008} 2008}
2009 2009
2010static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2010static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2093,9 +2093,11 @@ static int read_attr(int fd, struct perf_header *ph,
2093 return ret <= 0 ? -1 : 0; 2093 return ret <= 0 ? -1 : 0;
2094} 2094}
2095 2095
2096static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel) 2096static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
2097 struct pevent *pevent)
2097{ 2098{
2098 struct event_format *event = trace_find_event(evsel->attr.config); 2099 struct event_format *event = pevent_find_event(pevent,
2100 evsel->attr.config);
2099 char bf[128]; 2101 char bf[128];
2100 2102
2101 if (event == NULL) 2103 if (event == NULL)
@@ -2109,13 +2111,14 @@ static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
2109 return 0; 2111 return 0;
2110} 2112}
2111 2113
2112static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist) 2114static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist,
2115 struct pevent *pevent)
2113{ 2116{
2114 struct perf_evsel *pos; 2117 struct perf_evsel *pos;
2115 2118
2116 list_for_each_entry(pos, &evlist->entries, node) { 2119 list_for_each_entry(pos, &evlist->entries, node) {
2117 if (pos->attr.type == PERF_TYPE_TRACEPOINT && 2120 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2118 perf_evsel__set_tracepoint_name(pos)) 2121 perf_evsel__set_tracepoint_name(pos, pevent))
2119 return -1; 2122 return -1;
2120 } 2123 }
2121 2124
@@ -2198,12 +2201,12 @@ int perf_session__read_header(struct perf_session *session, int fd)
2198 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 2201 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
2199 } 2202 }
2200 2203
2201 perf_header__process_sections(header, fd, NULL, 2204 perf_header__process_sections(header, fd, &session->pevent,
2202 perf_file_section__process); 2205 perf_file_section__process);
2203 2206
2204 lseek(fd, header->data_offset, SEEK_SET); 2207 lseek(fd, header->data_offset, SEEK_SET);
2205 2208
2206 if (perf_evlist__set_tracepoint_names(session->evlist)) 2209 if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent))
2207 goto out_delete_evlist; 2210 goto out_delete_evlist;
2208 2211
2209 header->frozen = 1; 2212 header->frozen = 1;
@@ -2419,8 +2422,8 @@ int perf_event__process_tracing_data(union perf_event *event,
2419 lseek(session->fd, offset + sizeof(struct tracing_data_event), 2422 lseek(session->fd, offset + sizeof(struct tracing_data_event),
2420 SEEK_SET); 2423 SEEK_SET);
2421 2424
2422 size_read = trace_report(session->fd, session->repipe); 2425 size_read = trace_report(session->fd, &session->pevent,
2423 2426 session->repipe);
2424 padding = ALIGN(size_read, sizeof(u64)) - size_read; 2427 padding = ALIGN(size_read, sizeof(u64)) - size_read;
2425 2428
2426 if (read(session->fd, buf, padding) < 0) 2429 if (read(session->fd, buf, padding) < 0)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 34bb556d6219..0b096c27a419 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -47,6 +47,7 @@ enum hist_column {
47 HISTC_SYMBOL_TO, 47 HISTC_SYMBOL_TO,
48 HISTC_DSO_FROM, 48 HISTC_DSO_FROM,
49 HISTC_DSO_TO, 49 HISTC_DSO_TO,
50 HISTC_SRCLINE,
50 HISTC_NR_COLS, /* Last entry */ 51 HISTC_NR_COLS, /* Last entry */
51}; 52};
52 53
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 1eb804fd3fbf..b6842c1d02a8 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -108,4 +108,14 @@ int eprintf(int level,
108#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 108#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
109#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 109#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
110 110
111/*
112 * This looks more complex than it should be. But we need to
113 * get the type for the ~ right in round_down (it needs to be
114 * as wide as the result!), and we want to evaluate the macro
115 * arguments just once each.
116 */
117#define __round_mask(x, y) ((__typeof__(x))((y)-1))
118#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
119#define round_down(x, y) ((x) & ~__round_mask(x, y))
120
111#endif 121#endif
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 81371bad4ef0..c14c665d9a25 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -157,7 +157,7 @@ void machine__exit(struct machine *self);
157void machine__delete(struct machine *self); 157void machine__delete(struct machine *self);
158 158
159int machine__resolve_callchain(struct machine *machine, 159int machine__resolve_callchain(struct machine *machine,
160 struct perf_evsel *evsel, struct thread *thread, 160 struct thread *thread,
161 struct ip_callchain *chain, 161 struct ip_callchain *chain,
162 struct symbol **parent); 162 struct symbol **parent);
163int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 163int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 76b98e2a587d..1b997d2b89ce 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
181 return 0; 181 return 0;
182} 182}
183 183
184static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
185{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next,
187 struct perf_evsel, node);
188
189 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
190 TEST_ASSERT_VAL("wrong type",
191 PERF_TYPE_BREAKPOINT == evsel->attr.type);
192 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
193 TEST_ASSERT_VAL("wrong bp_type",
194 (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
195 TEST_ASSERT_VAL("wrong bp_len",
196 HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
197 return 0;
198}
199
184static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) 200static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
185{ 201{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next, 202 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
309 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 325 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
310 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 326 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
311 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 327 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
328 TEST_ASSERT_VAL("wrong name",
329 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
312 330
313 return test__checkevent_breakpoint(evlist); 331 return test__checkevent_breakpoint(evlist);
314} 332}
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
322 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 340 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
323 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 341 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
324 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 342 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
343 TEST_ASSERT_VAL("wrong name",
344 !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
325 345
326 return test__checkevent_breakpoint_x(evlist); 346 return test__checkevent_breakpoint_x(evlist);
327} 347}
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
335 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 355 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
336 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 356 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
337 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 357 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
358 TEST_ASSERT_VAL("wrong name",
359 !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
338 360
339 return test__checkevent_breakpoint_r(evlist); 361 return test__checkevent_breakpoint_r(evlist);
340} 362}
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
348 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 370 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
349 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 371 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
350 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 372 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
373 TEST_ASSERT_VAL("wrong name",
374 !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
351 375
352 return test__checkevent_breakpoint_w(evlist); 376 return test__checkevent_breakpoint_w(evlist);
353} 377}
354 378
379static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
380{
381 struct perf_evsel *evsel = list_entry(evlist->entries.next,
382 struct perf_evsel, node);
383
384 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
385 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
386 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
387 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
388 TEST_ASSERT_VAL("wrong name",
389 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
390
391 return test__checkevent_breakpoint_rw(evlist);
392}
393
355static int test__checkevent_pmu(struct perf_evlist *evlist) 394static int test__checkevent_pmu(struct perf_evlist *evlist)
356{ 395{
357 396
@@ -413,19 +452,63 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
413{ 452{
414 struct perf_evsel *evsel; 453 struct perf_evsel *evsel;
415 454
416 /* cpu/config=1,name=krava1/u */ 455 /* cpu/config=1,name=krava/u */
417 evsel = list_entry(evlist->entries.next, struct perf_evsel, node); 456 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
418 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 457 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
419 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 458 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
420 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 459 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
421 TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava")); 460 TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
422 461
423 /* cpu/config=2/" */ 462 /* cpu/config=2/u" */
424 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 463 evsel = list_entry(evsel->node.next, struct perf_evsel, node);
425 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 464 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
426 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 465 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
427 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); 466 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
428 TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2")); 467 TEST_ASSERT_VAL("wrong name",
468 !strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
469
470 return 0;
471}
472
473static int test__checkterms_simple(struct list_head *terms)
474{
475 struct parse_events__term *term;
476
477 /* config=10 */
478 term = list_entry(terms->next, struct parse_events__term, list);
479 TEST_ASSERT_VAL("wrong type term",
480 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
481 TEST_ASSERT_VAL("wrong type val",
482 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
483 TEST_ASSERT_VAL("wrong val", term->val.num == 10);
484 TEST_ASSERT_VAL("wrong config", !term->config);
485
486 /* config1 */
487 term = list_entry(term->list.next, struct parse_events__term, list);
488 TEST_ASSERT_VAL("wrong type term",
489 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
490 TEST_ASSERT_VAL("wrong type val",
491 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
492 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
493 TEST_ASSERT_VAL("wrong config", !term->config);
494
495 /* config2=3 */
496 term = list_entry(term->list.next, struct parse_events__term, list);
497 TEST_ASSERT_VAL("wrong type term",
498 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
499 TEST_ASSERT_VAL("wrong type val",
500 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
501 TEST_ASSERT_VAL("wrong val", term->val.num == 3);
502 TEST_ASSERT_VAL("wrong config", !term->config);
503
504 /* umask=1*/
505 term = list_entry(term->list.next, struct parse_events__term, list);
506 TEST_ASSERT_VAL("wrong type term",
507 term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
508 TEST_ASSERT_VAL("wrong type val",
509 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
510 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
511 TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask"));
429 512
430 return 0; 513 return 0;
431} 514}
@@ -541,10 +624,16 @@ static struct test__event_st test__events[] = {
541 .name = "instructions:H", 624 .name = "instructions:H",
542 .check = test__checkevent_exclude_guest_modifier, 625 .check = test__checkevent_exclude_guest_modifier,
543 }, 626 },
627 [26] = {
628 .name = "mem:0:rw",
629 .check = test__checkevent_breakpoint_rw,
630 },
631 [27] = {
632 .name = "mem:0:rw:kp",
633 .check = test__checkevent_breakpoint_rw_modifier,
634 },
544}; 635};
545 636
546#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
547
548static struct test__event_st test__events_pmu[] = { 637static struct test__event_st test__events_pmu[] = {
549 [0] = { 638 [0] = {
550 .name = "cpu/config=10,config1,config2=3,period=1000/u", 639 .name = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -556,10 +645,23 @@ static struct test__event_st test__events_pmu[] = {
556 }, 645 },
557}; 646};
558 647
559#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ 648struct test__term {
560 sizeof(struct test__event_st)) 649 const char *str;
650 __u32 type;
651 int (*check)(struct list_head *terms);
652};
653
654static struct test__term test__terms[] = {
655 [0] = {
656 .str = "config=10,config1,config2=3,umask=1",
657 .check = test__checkterms_simple,
658 },
659};
660
661#define TEST__TERMS_CNT (sizeof(test__terms) / \
662 sizeof(struct test__term))
561 663
562static int test(struct test__event_st *e) 664static int test_event(struct test__event_st *e)
563{ 665{
564 struct perf_evlist *evlist; 666 struct perf_evlist *evlist;
565 int ret; 667 int ret;
@@ -590,7 +692,48 @@ static int test_events(struct test__event_st *events, unsigned cnt)
590 struct test__event_st *e = &events[i]; 692 struct test__event_st *e = &events[i];
591 693
592 pr_debug("running test %d '%s'\n", i, e->name); 694 pr_debug("running test %d '%s'\n", i, e->name);
593 ret = test(e); 695 ret = test_event(e);
696 if (ret)
697 break;
698 }
699
700 return ret;
701}
702
703static int test_term(struct test__term *t)
704{
705 struct list_head *terms;
706 int ret;
707
708 terms = malloc(sizeof(*terms));
709 if (!terms)
710 return -ENOMEM;
711
712 INIT_LIST_HEAD(terms);
713
714 ret = parse_events_terms(terms, t->str);
715 if (ret) {
716 pr_debug("failed to parse terms '%s', err %d\n",
717 t->str , ret);
718 return ret;
719 }
720
721 ret = t->check(terms);
722 parse_events__free_terms(terms);
723
724 return ret;
725}
726
727static int test_terms(struct test__term *terms, unsigned cnt)
728{
729 int ret = 0;
730 unsigned i;
731
732 for (i = 0; i < cnt; i++) {
733 struct test__term *t = &terms[i];
734
735 pr_debug("running test %d '%s'\n", i, t->str);
736 ret = test_term(t);
594 if (ret) 737 if (ret)
595 break; 738 break;
596 } 739 }
@@ -617,9 +760,17 @@ int parse_events__test(void)
617{ 760{
618 int ret; 761 int ret;
619 762
620 ret = test_events(test__events, TEST__EVENTS_CNT); 763#define TEST_EVENTS(tests) \
621 if (!ret && test_pmu()) 764do { \
622 ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT); 765 ret = test_events(tests, ARRAY_SIZE(tests)); \
766 if (ret) \
767 return ret; \
768} while (0)
623 769
624 return ret; 770 TEST_EVENTS(test__events);
771
772 if (test_pmu())
773 TEST_EVENTS(test__events_pmu);
774
775 return test_terms(test__terms, ARRAY_SIZE(test__terms));
625} 776}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 05dbc8b3c767..1aa721d7c10f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -11,14 +11,14 @@
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debugfs.h" 13#include "debugfs.h"
14#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int
14#include "parse-events-flex.h" 16#include "parse-events-flex.h"
15#include "pmu.h" 17#include "pmu.h"
16 18
17#define MAX_NAME_LEN 100 19#define MAX_NAME_LEN 100
18 20
19struct event_symbol { 21struct event_symbol {
20 u8 type;
21 u64 config;
22 const char *symbol; 22 const char *symbol;
23 const char *alias; 23 const char *alias;
24}; 24};
@@ -26,32 +26,88 @@ struct event_symbol {
26#ifdef PARSER_DEBUG 26#ifdef PARSER_DEBUG
27extern int parse_events_debug; 27extern int parse_events_debug;
28#endif 28#endif
29int parse_events_parse(struct list_head *list, int *idx); 29int parse_events_parse(void *data, void *scanner);
30 30
31#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 31static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
32#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 32 [PERF_COUNT_HW_CPU_CYCLES] = {
33 33 .symbol = "cpu-cycles",
34static struct event_symbol event_symbols[] = { 34 .alias = "cycles",
35 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 35 },
36 { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, 36 [PERF_COUNT_HW_INSTRUCTIONS] = {
37 { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, 37 .symbol = "instructions",
38 { CHW(INSTRUCTIONS), "instructions", "" }, 38 .alias = "",
39 { CHW(CACHE_REFERENCES), "cache-references", "" }, 39 },
40 { CHW(CACHE_MISSES), "cache-misses", "" }, 40 [PERF_COUNT_HW_CACHE_REFERENCES] = {
41 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 41 .symbol = "cache-references",
42 { CHW(BRANCH_MISSES), "branch-misses", "" }, 42 .alias = "",
43 { CHW(BUS_CYCLES), "bus-cycles", "" }, 43 },
44 { CHW(REF_CPU_CYCLES), "ref-cycles", "" }, 44 [PERF_COUNT_HW_CACHE_MISSES] = {
45 45 .symbol = "cache-misses",
46 { CSW(CPU_CLOCK), "cpu-clock", "" }, 46 .alias = "",
47 { CSW(TASK_CLOCK), "task-clock", "" }, 47 },
48 { CSW(PAGE_FAULTS), "page-faults", "faults" }, 48 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
49 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 49 .symbol = "branch-instructions",
50 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 50 .alias = "branches",
51 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 51 },
52 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 52 [PERF_COUNT_HW_BRANCH_MISSES] = {
53 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 53 .symbol = "branch-misses",
54 { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 54 .alias = "",
55 },
56 [PERF_COUNT_HW_BUS_CYCLES] = {
57 .symbol = "bus-cycles",
58 .alias = "",
59 },
60 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
61 .symbol = "stalled-cycles-frontend",
62 .alias = "idle-cycles-frontend",
63 },
64 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
65 .symbol = "stalled-cycles-backend",
66 .alias = "idle-cycles-backend",
67 },
68 [PERF_COUNT_HW_REF_CPU_CYCLES] = {
69 .symbol = "ref-cycles",
70 .alias = "",
71 },
72};
73
74static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
75 [PERF_COUNT_SW_CPU_CLOCK] = {
76 .symbol = "cpu-clock",
77 .alias = "",
78 },
79 [PERF_COUNT_SW_TASK_CLOCK] = {
80 .symbol = "task-clock",
81 .alias = "",
82 },
83 [PERF_COUNT_SW_PAGE_FAULTS] = {
84 .symbol = "page-faults",
85 .alias = "faults",
86 },
87 [PERF_COUNT_SW_CONTEXT_SWITCHES] = {
88 .symbol = "context-switches",
89 .alias = "cs",
90 },
91 [PERF_COUNT_SW_CPU_MIGRATIONS] = {
92 .symbol = "cpu-migrations",
93 .alias = "migrations",
94 },
95 [PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
96 .symbol = "minor-faults",
97 .alias = "",
98 },
99 [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
100 .symbol = "major-faults",
101 .alias = "",
102 },
103 [PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
104 .symbol = "alignment-faults",
105 .alias = "",
106 },
107 [PERF_COUNT_SW_EMULATION_FAULTS] = {
108 .symbol = "emulation-faults",
109 .alias = "",
110 },
55}; 111};
56 112
57#define __PERF_EVENT_FIELD(config, name) \ 113#define __PERF_EVENT_FIELD(config, name) \
@@ -62,63 +118,6 @@ static struct event_symbol event_symbols[] = {
62#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 118#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
63#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 119#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
64 120
65static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
66 "cpu-clock",
67 "task-clock",
68 "page-faults",
69 "context-switches",
70 "CPU-migrations",
71 "minor-faults",
72 "major-faults",
73 "alignment-faults",
74 "emulation-faults",
75};
76
77#define MAX_ALIASES 8
78
79static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
80 { "L1-dcache", "l1-d", "l1d", "L1-data", },
81 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
82 { "LLC", "L2", },
83 { "dTLB", "d-tlb", "Data-TLB", },
84 { "iTLB", "i-tlb", "Instruction-TLB", },
85 { "branch", "branches", "bpu", "btb", "bpc", },
86 { "node", },
87};
88
89static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
90 { "load", "loads", "read", },
91 { "store", "stores", "write", },
92 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
93};
94
95static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
96 [MAX_ALIASES] = {
97 { "refs", "Reference", "ops", "access", },
98 { "misses", "miss", },
99};
100
101#define C(x) PERF_COUNT_HW_CACHE_##x
102#define CACHE_READ (1 << C(OP_READ))
103#define CACHE_WRITE (1 << C(OP_WRITE))
104#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
105#define COP(x) (1 << x)
106
107/*
108 * cache operartion stat
109 * L1I : Read and prefetch only
110 * ITLB and BPU : Read-only
111 */
112static unsigned long hw_cache_stat[C(MAX)] = {
113 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
114 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
115 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
116 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
117 [C(ITLB)] = (CACHE_READ),
118 [C(BPU)] = (CACHE_READ),
119 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
120};
121
122#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 121#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \
123 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 122 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
124 if (sys_dirent.d_type == DT_DIR && \ 123 if (sys_dirent.d_type == DT_DIR && \
@@ -218,48 +217,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
218 return NULL; 217 return NULL;
219} 218}
220 219
221#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
222static const char *tracepoint_id_to_name(u64 config)
223{
224 static char buf[TP_PATH_LEN];
225 struct tracepoint_path *path;
226
227 path = tracepoint_id_to_path(config);
228 if (path) {
229 snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
230 free(path->name);
231 free(path->system);
232 free(path);
233 } else
234 snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
235
236 return buf;
237}
238
239static int is_cache_op_valid(u8 cache_type, u8 cache_op)
240{
241 if (hw_cache_stat[cache_type] & COP(cache_op))
242 return 1; /* valid */
243 else
244 return 0; /* invalid */
245}
246
247static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
248{
249 static char name[50];
250
251 if (cache_result) {
252 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
253 hw_cache_op[cache_op][0],
254 hw_cache_result[cache_result][0]);
255 } else {
256 sprintf(name, "%s-%s", hw_cache[cache_type][0],
257 hw_cache_op[cache_op][1]);
258 }
259
260 return name;
261}
262
263const char *event_type(int type) 220const char *event_type(int type)
264{ 221{
265 switch (type) { 222 switch (type) {
@@ -282,76 +239,6 @@ const char *event_type(int type)
282 return "unknown"; 239 return "unknown";
283} 240}
284 241
285const char *event_name(struct perf_evsel *evsel)
286{
287 u64 config = evsel->attr.config;
288 int type = evsel->attr.type;
289
290 if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
291 /*
292 * XXX minimal fix, see comment on perf_evsen__name, this static buffer
293 * will go away together with event_name in the next devel cycle.
294 */
295 static char bf[128];
296 perf_evsel__name(evsel, bf, sizeof(bf));
297 return bf;
298 }
299
300 if (evsel->name)
301 return evsel->name;
302
303 return __event_name(type, config);
304}
305
306const char *__event_name(int type, u64 config)
307{
308 static char buf[32];
309
310 if (type == PERF_TYPE_RAW) {
311 sprintf(buf, "raw 0x%" PRIx64, config);
312 return buf;
313 }
314
315 switch (type) {
316 case PERF_TYPE_HARDWARE:
317 return __perf_evsel__hw_name(config);
318
319 case PERF_TYPE_HW_CACHE: {
320 u8 cache_type, cache_op, cache_result;
321
322 cache_type = (config >> 0) & 0xff;
323 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
324 return "unknown-ext-hardware-cache-type";
325
326 cache_op = (config >> 8) & 0xff;
327 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
328 return "unknown-ext-hardware-cache-op";
329
330 cache_result = (config >> 16) & 0xff;
331 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
332 return "unknown-ext-hardware-cache-result";
333
334 if (!is_cache_op_valid(cache_type, cache_op))
335 return "invalid-cache";
336
337 return event_cache_name(cache_type, cache_op, cache_result);
338 }
339
340 case PERF_TYPE_SOFTWARE:
341 if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
342 return sw_event_names[config];
343 return "unknown-software";
344
345 case PERF_TYPE_TRACEPOINT:
346 return tracepoint_id_to_name(config);
347
348 default:
349 break;
350 }
351
352 return "unknown";
353}
354
355static int add_event(struct list_head **_list, int *idx, 242static int add_event(struct list_head **_list, int *idx,
356 struct perf_event_attr *attr, char *name) 243 struct perf_event_attr *attr, char *name)
357{ 244{
@@ -373,19 +260,20 @@ static int add_event(struct list_head **_list, int *idx,
373 return -ENOMEM; 260 return -ENOMEM;
374 } 261 }
375 262
376 evsel->name = strdup(name); 263 if (name)
264 evsel->name = strdup(name);
377 list_add_tail(&evsel->node, list); 265 list_add_tail(&evsel->node, list);
378 *_list = list; 266 *_list = list;
379 return 0; 267 return 0;
380} 268}
381 269
382static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) 270static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
383{ 271{
384 int i, j; 272 int i, j;
385 int n, longest = -1; 273 int n, longest = -1;
386 274
387 for (i = 0; i < size; i++) { 275 for (i = 0; i < size; i++) {
388 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 276 for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {
389 n = strlen(names[i][j]); 277 n = strlen(names[i][j]);
390 if (n > longest && !strncasecmp(str, names[i][j], n)) 278 if (n > longest && !strncasecmp(str, names[i][j], n))
391 longest = n; 279 longest = n;
@@ -410,7 +298,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
410 * No fallback - if we cannot get a clear cache type 298 * No fallback - if we cannot get a clear cache type
411 * then bail out: 299 * then bail out:
412 */ 300 */
413 cache_type = parse_aliases(type, hw_cache, 301 cache_type = parse_aliases(type, perf_evsel__hw_cache,
414 PERF_COUNT_HW_CACHE_MAX); 302 PERF_COUNT_HW_CACHE_MAX);
415 if (cache_type == -1) 303 if (cache_type == -1)
416 return -EINVAL; 304 return -EINVAL;
@@ -423,18 +311,18 @@ int parse_events_add_cache(struct list_head **list, int *idx,
423 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); 311 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
424 312
425 if (cache_op == -1) { 313 if (cache_op == -1) {
426 cache_op = parse_aliases(str, hw_cache_op, 314 cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
427 PERF_COUNT_HW_CACHE_OP_MAX); 315 PERF_COUNT_HW_CACHE_OP_MAX);
428 if (cache_op >= 0) { 316 if (cache_op >= 0) {
429 if (!is_cache_op_valid(cache_type, cache_op)) 317 if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))
430 return -EINVAL; 318 return -EINVAL;
431 continue; 319 continue;
432 } 320 }
433 } 321 }
434 322
435 if (cache_result == -1) { 323 if (cache_result == -1) {
436 cache_result = parse_aliases(str, hw_cache_result, 324 cache_result = parse_aliases(str, perf_evsel__hw_cache_result,
437 PERF_COUNT_HW_CACHE_RESULT_MAX); 325 PERF_COUNT_HW_CACHE_RESULT_MAX);
438 if (cache_result >= 0) 326 if (cache_result >= 0)
439 continue; 327 continue;
440 } 328 }
@@ -549,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
549 if (!type || !type[i]) 437 if (!type || !type[i])
550 break; 438 break;
551 439
440#define CHECK_SET_TYPE(bit) \
441do { \
442 if (attr->bp_type & bit) \
443 return -EINVAL; \
444 else \
445 attr->bp_type |= bit; \
446} while (0)
447
552 switch (type[i]) { 448 switch (type[i]) {
553 case 'r': 449 case 'r':
554 attr->bp_type |= HW_BREAKPOINT_R; 450 CHECK_SET_TYPE(HW_BREAKPOINT_R);
555 break; 451 break;
556 case 'w': 452 case 'w':
557 attr->bp_type |= HW_BREAKPOINT_W; 453 CHECK_SET_TYPE(HW_BREAKPOINT_W);
558 break; 454 break;
559 case 'x': 455 case 'x':
560 attr->bp_type |= HW_BREAKPOINT_X; 456 CHECK_SET_TYPE(HW_BREAKPOINT_X);
561 break; 457 break;
562 default: 458 default:
563 return -EINVAL; 459 return -EINVAL;
564 } 460 }
565 } 461 }
566 462
463#undef CHECK_SET_TYPE
464
567 if (!attr->bp_type) /* Default */ 465 if (!attr->bp_type) /* Default */
568 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 466 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
569 467
@@ -574,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
574 void *ptr, char *type) 472 void *ptr, char *type)
575{ 473{
576 struct perf_event_attr attr; 474 struct perf_event_attr attr;
577 char name[MAX_NAME_LEN];
578 475
579 memset(&attr, 0, sizeof(attr)); 476 memset(&attr, 0, sizeof(attr));
580 attr.bp_addr = (unsigned long) ptr; 477 attr.bp_addr = (unsigned long) ptr;
@@ -593,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
593 490
594 attr.type = PERF_TYPE_BREAKPOINT; 491 attr.type = PERF_TYPE_BREAKPOINT;
595 492
596 snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); 493 return add_event(list, idx, &attr, NULL);
597 return add_event(list, idx, &attr, name);
598} 494}
599 495
600static int config_term(struct perf_event_attr *attr, 496static int config_term(struct perf_event_attr *attr,
@@ -666,8 +562,7 @@ int parse_events_add_numeric(struct list_head **list, int *idx,
666 config_attr(&attr, head_config, 1)) 562 config_attr(&attr, head_config, 1))
667 return -EINVAL; 563 return -EINVAL;
668 564
669 return add_event(list, idx, &attr, 565 return add_event(list, idx, &attr, NULL);
670 (char *) __event_name(type, config));
671} 566}
672 567
673static int parse_events__is_name_term(struct parse_events__term *term) 568static int parse_events__is_name_term(struct parse_events__term *term)
@@ -675,8 +570,7 @@ static int parse_events__is_name_term(struct parse_events__term *term)
675 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; 570 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
676} 571}
677 572
678static char *pmu_event_name(struct perf_event_attr *attr, 573static char *pmu_event_name(struct list_head *head_terms)
679 struct list_head *head_terms)
680{ 574{
681 struct parse_events__term *term; 575 struct parse_events__term *term;
682 576
@@ -684,7 +578,7 @@ static char *pmu_event_name(struct perf_event_attr *attr,
684 if (parse_events__is_name_term(term)) 578 if (parse_events__is_name_term(term))
685 return term->val.str; 579 return term->val.str;
686 580
687 return (char *) __event_name(PERF_TYPE_RAW, attr->config); 581 return NULL;
688} 582}
689 583
690int parse_events_add_pmu(struct list_head **list, int *idx, 584int parse_events_add_pmu(struct list_head **list, int *idx,
@@ -699,6 +593,9 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
699 593
700 memset(&attr, 0, sizeof(attr)); 594 memset(&attr, 0, sizeof(attr));
701 595
596 if (perf_pmu__check_alias(pmu, head_config))
597 return -EINVAL;
598
702 /* 599 /*
703 * Configure hardcoded terms first, no need to check 600 * Configure hardcoded terms first, no need to check
704 * return value when called with fail == 0 ;) 601 * return value when called with fail == 0 ;)
@@ -709,7 +606,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
709 return -EINVAL; 606 return -EINVAL;
710 607
711 return add_event(list, idx, &attr, 608 return add_event(list, idx, &attr,
712 pmu_event_name(&attr, head_config)); 609 pmu_event_name(head_config));
713} 610}
714 611
715void parse_events_update_lists(struct list_head *list_event, 612void parse_events_update_lists(struct list_head *list_event,
@@ -787,27 +684,62 @@ int parse_events_modifier(struct list_head *list, char *str)
787 return 0; 684 return 0;
788} 685}
789 686
790int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 687static int parse_events__scanner(const char *str, void *data, int start_token)
791{ 688{
792 LIST_HEAD(list);
793 LIST_HEAD(list_tmp);
794 YY_BUFFER_STATE buffer; 689 YY_BUFFER_STATE buffer;
795 int ret, idx = evlist->nr_entries; 690 void *scanner;
691 int ret;
692
693 ret = parse_events_lex_init_extra(start_token, &scanner);
694 if (ret)
695 return ret;
796 696
797 buffer = parse_events__scan_string(str); 697 buffer = parse_events__scan_string(str, scanner);
798 698
799#ifdef PARSER_DEBUG 699#ifdef PARSER_DEBUG
800 parse_events_debug = 1; 700 parse_events_debug = 1;
801#endif 701#endif
802 ret = parse_events_parse(&list, &idx); 702 ret = parse_events_parse(data, scanner);
803 703
804 parse_events__flush_buffer(buffer); 704 parse_events__flush_buffer(buffer, scanner);
805 parse_events__delete_buffer(buffer); 705 parse_events__delete_buffer(buffer, scanner);
806 parse_events_lex_destroy(); 706 parse_events_lex_destroy(scanner);
707 return ret;
708}
709
710/*
711 * parse event config string, return a list of event terms.
712 */
713int parse_events_terms(struct list_head *terms, const char *str)
714{
715 struct parse_events_data__terms data = {
716 .terms = NULL,
717 };
718 int ret;
807 719
720 ret = parse_events__scanner(str, &data, PE_START_TERMS);
808 if (!ret) { 721 if (!ret) {
809 int entries = idx - evlist->nr_entries; 722 list_splice(data.terms, terms);
810 perf_evlist__splice_list_tail(evlist, &list, entries); 723 free(data.terms);
724 return 0;
725 }
726
727 parse_events__free_terms(data.terms);
728 return ret;
729}
730
731int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
732{
733 struct parse_events_data__events data = {
734 .list = LIST_HEAD_INIT(data.list),
735 .idx = evlist->nr_entries,
736 };
737 int ret;
738
739 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
740 if (!ret) {
741 int entries = data.idx - evlist->nr_entries;
742 perf_evlist__splice_list_tail(evlist, &data.list, entries);
811 return 0; 743 return 0;
812 } 744 }
813 745
@@ -946,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
946 return 0; 878 return 0;
947} 879}
948 880
949void print_events_type(u8 type) 881static void __print_events_type(u8 type, struct event_symbol *syms,
882 unsigned max)
950{ 883{
951 struct event_symbol *syms = event_symbols;
952 unsigned int i;
953 char name[64]; 884 char name[64];
885 unsigned i;
954 886
955 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 887 for (i = 0; i < max ; i++, syms++) {
956 if (type != syms->type)
957 continue;
958
959 if (strlen(syms->alias)) 888 if (strlen(syms->alias))
960 snprintf(name, sizeof(name), "%s OR %s", 889 snprintf(name, sizeof(name), "%s OR %s",
961 syms->symbol, syms->alias); 890 syms->symbol, syms->alias);
@@ -967,19 +896,28 @@ void print_events_type(u8 type)
967 } 896 }
968} 897}
969 898
899void print_events_type(u8 type)
900{
901 if (type == PERF_TYPE_SOFTWARE)
902 __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
903 else
904 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
905}
906
970int print_hwcache_events(const char *event_glob) 907int print_hwcache_events(const char *event_glob)
971{ 908{
972 unsigned int type, op, i, printed = 0; 909 unsigned int type, op, i, printed = 0;
910 char name[64];
973 911
974 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 912 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
975 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 913 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
976 /* skip invalid cache type */ 914 /* skip invalid cache type */
977 if (!is_cache_op_valid(type, op)) 915 if (!perf_evsel__is_cache_op_valid(type, op))
978 continue; 916 continue;
979 917
980 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 918 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
981 char *name = event_cache_name(type, op, i); 919 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
982 920 name, sizeof(name));
983 if (event_glob != NULL && !strglobmatch(name, event_glob)) 921 if (event_glob != NULL && !strglobmatch(name, event_glob))
984 continue; 922 continue;
985 923
@@ -993,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
993 return printed; 931 return printed;
994} 932}
995 933
996/* 934static void print_symbol_events(const char *event_glob, unsigned type,
997 * Print the help text for the event symbols: 935 struct event_symbol *syms, unsigned max)
998 */
999void print_events(const char *event_glob)
1000{ 936{
1001 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; 937 unsigned i, printed = 0;
1002 struct event_symbol *syms = event_symbols;
1003 char name[MAX_NAME_LEN]; 938 char name[MAX_NAME_LEN];
1004 939
1005 printf("\n"); 940 for (i = 0; i < max; i++, syms++) {
1006 printf("List of pre-defined events (to be used in -e):\n");
1007
1008 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
1009 type = syms->type;
1010
1011 if (type != prev_type && printed) {
1012 printf("\n");
1013 printed = 0;
1014 ntypes_printed++;
1015 }
1016 941
1017 if (event_glob != NULL && 942 if (event_glob != NULL &&
1018 !(strglobmatch(syms->symbol, event_glob) || 943 !(strglobmatch(syms->symbol, event_glob) ||
@@ -1023,17 +948,31 @@ void print_events(const char *event_glob)
1023 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 948 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1024 else 949 else
1025 strncpy(name, syms->symbol, MAX_NAME_LEN); 950 strncpy(name, syms->symbol, MAX_NAME_LEN);
1026 printf(" %-50s [%s]\n", name,
1027 event_type_descriptors[type]);
1028 951
1029 prev_type = type; 952 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
1030 ++printed; 953
954 printed++;
1031 } 955 }
1032 956
1033 if (ntypes_printed) { 957 if (printed)
1034 printed = 0;
1035 printf("\n"); 958 printf("\n");
1036 } 959}
960
961/*
962 * Print the help text for the event symbols:
963 */
964void print_events(const char *event_glob)
965{
966
967 printf("\n");
968 printf("List of pre-defined events (to be used in -e):\n");
969
970 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
971 event_symbols_hw, PERF_COUNT_HW_MAX);
972
973 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
974 event_symbols_sw, PERF_COUNT_SW_MAX);
975
1037 print_hwcache_events(event_glob); 976 print_hwcache_events(event_glob);
1038 977
1039 if (event_glob != NULL) 978 if (event_glob != NULL)
@@ -1106,6 +1045,13 @@ int parse_events__term_str(struct parse_events__term **term,
1106 config, str, 0); 1045 config, str, 0);
1107} 1046}
1108 1047
1048int parse_events__term_clone(struct parse_events__term **new,
1049 struct parse_events__term *term)
1050{
1051 return new_term(new, term->type_val, term->type_term, term->config,
1052 term->val.str, term->val.num);
1053}
1054
1109void parse_events__free_terms(struct list_head *terms) 1055void parse_events__free_terms(struct list_head *terms)
1110{ 1056{
1111 struct parse_events__term *term, *h; 1057 struct parse_events__term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 8cac57ab4ee6..ee9c218a193c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -26,13 +26,12 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
26extern bool have_tracepoints(struct list_head *evlist); 26extern bool have_tracepoints(struct list_head *evlist);
27 27
28const char *event_type(int type); 28const char *event_type(int type);
29const char *event_name(struct perf_evsel *event);
30extern const char *__event_name(int type, u64 config);
31 29
32extern int parse_events_option(const struct option *opt, const char *str, 30extern int parse_events_option(const struct option *opt, const char *str,
33 int unset); 31 int unset);
34extern int parse_events(struct perf_evlist *evlist, const char *str, 32extern int parse_events(struct perf_evlist *evlist, const char *str,
35 int unset); 33 int unset);
34extern int parse_events_terms(struct list_head *terms, const char *str);
36extern int parse_filter(const struct option *opt, const char *str, int unset); 35extern int parse_filter(const struct option *opt, const char *str, int unset);
37 36
38#define EVENTS_HELP_MAX (128*1024) 37#define EVENTS_HELP_MAX (128*1024)
@@ -63,11 +62,22 @@ struct parse_events__term {
63 struct list_head list; 62 struct list_head list;
64}; 63};
65 64
65struct parse_events_data__events {
66 struct list_head list;
67 int idx;
68};
69
70struct parse_events_data__terms {
71 struct list_head *terms;
72};
73
66int parse_events__is_hardcoded_term(struct parse_events__term *term); 74int parse_events__is_hardcoded_term(struct parse_events__term *term);
67int parse_events__term_num(struct parse_events__term **_term, 75int parse_events__term_num(struct parse_events__term **_term,
68 int type_term, char *config, long num); 76 int type_term, char *config, long num);
69int parse_events__term_str(struct parse_events__term **_term, 77int parse_events__term_str(struct parse_events__term **_term,
70 int type_term, char *config, char *str); 78 int type_term, char *config, char *str);
79int parse_events__term_clone(struct parse_events__term **new,
80 struct parse_events__term *term);
71void parse_events__free_terms(struct list_head *terms); 81void parse_events__free_terms(struct list_head *terms);
72int parse_events_modifier(struct list_head *list, char *str); 82int parse_events_modifier(struct list_head *list, char *str);
73int parse_events_add_tracepoint(struct list_head **list, int *idx, 83int parse_events_add_tracepoint(struct list_head **list, int *idx,
@@ -83,8 +93,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
83 char *pmu , struct list_head *head_config); 93 char *pmu , struct list_head *head_config);
84void parse_events_update_lists(struct list_head *list_event, 94void parse_events_update_lists(struct list_head *list_event,
85 struct list_head *list_all); 95 struct list_head *list_all);
86void parse_events_error(struct list_head *list_all, 96void parse_events_error(void *data, void *scanner, char const *msg);
87 int *idx, char const *msg);
88int parse_events__test(void); 97int parse_events__test(void);
89 98
90void print_events(const char *event_glob); 99void print_events(const char *event_glob);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 618a8e788399..384ca74c6b22 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -1,4 +1,6 @@
1 1
2%option reentrant
3%option bison-bridge
2%option prefix="parse_events_" 4%option prefix="parse_events_"
3%option stack 5%option stack
4 6
@@ -8,7 +10,10 @@
8#include "parse-events-bison.h" 10#include "parse-events-bison.h"
9#include "parse-events.h" 11#include "parse-events.h"
10 12
11static int __value(char *str, int base, int token) 13char *parse_events_get_text(yyscan_t yyscanner);
14YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
15
16static int __value(YYSTYPE *yylval, char *str, int base, int token)
12{ 17{
13 long num; 18 long num;
14 19
@@ -17,35 +22,48 @@ static int __value(char *str, int base, int token)
17 if (errno) 22 if (errno)
18 return PE_ERROR; 23 return PE_ERROR;
19 24
20 parse_events_lval.num = num; 25 yylval->num = num;
21 return token; 26 return token;
22} 27}
23 28
24static int value(int base) 29static int value(yyscan_t scanner, int base)
25{ 30{
26 return __value(parse_events_text, base, PE_VALUE); 31 YYSTYPE *yylval = parse_events_get_lval(scanner);
32 char *text = parse_events_get_text(scanner);
33
34 return __value(yylval, text, base, PE_VALUE);
27} 35}
28 36
29static int raw(void) 37static int raw(yyscan_t scanner)
30{ 38{
31 return __value(parse_events_text + 1, 16, PE_RAW); 39 YYSTYPE *yylval = parse_events_get_lval(scanner);
40 char *text = parse_events_get_text(scanner);
41
42 return __value(yylval, text + 1, 16, PE_RAW);
32} 43}
33 44
34static int str(int token) 45static int str(yyscan_t scanner, int token)
35{ 46{
36 parse_events_lval.str = strdup(parse_events_text); 47 YYSTYPE *yylval = parse_events_get_lval(scanner);
48 char *text = parse_events_get_text(scanner);
49
50 yylval->str = strdup(text);
37 return token; 51 return token;
38} 52}
39 53
40static int sym(int type, int config) 54static int sym(yyscan_t scanner, int type, int config)
41{ 55{
42 parse_events_lval.num = (type << 16) + config; 56 YYSTYPE *yylval = parse_events_get_lval(scanner);
43 return PE_VALUE_SYM; 57
58 yylval->num = (type << 16) + config;
59 return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
44} 60}
45 61
46static int term(int type) 62static int term(yyscan_t scanner, int type)
47{ 63{
48 parse_events_lval.num = type; 64 YYSTYPE *yylval = parse_events_get_lval(scanner);
65
66 yylval->num = type;
49 return PE_TERM; 67 return PE_TERM;
50} 68}
51 69
@@ -58,28 +76,41 @@ num_hex 0x[a-fA-F0-9]+
58num_raw_hex [a-fA-F0-9]+ 76num_raw_hex [a-fA-F0-9]+
59name [a-zA-Z_*?][a-zA-Z0-9_*?]* 77name [a-zA-Z_*?][a-zA-Z0-9_*?]*
60modifier_event [ukhpGH]{1,8} 78modifier_event [ukhpGH]{1,8}
61modifier_bp [rwx] 79modifier_bp [rwx]{1,3}
62 80
63%% 81%%
64cpu-cycles|cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 82
65stalled-cycles-frontend|idle-cycles-frontend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 83%{
66stalled-cycles-backend|idle-cycles-backend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 84 {
67instructions { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); } 85 int start_token;
68cache-references { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); } 86
69cache-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); } 87 start_token = (int) parse_events_get_extra(yyscanner);
70branch-instructions|branches { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 88 if (start_token) {
71branch-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); } 89 parse_events_set_extra(NULL, yyscanner);
72bus-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); } 90 return start_token;
73ref-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); } 91 }
74cpu-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); } 92 }
75task-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); } 93%}
76page-faults|faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); } 94
77minor-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); } 95cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
78major-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); } 96stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
79context-switches|cs { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); } 97stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
80cpu-migrations|migrations { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); } 98instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
81alignment-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 99cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
82emulation-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 100cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
101branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
102branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
103bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
104ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
105cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
106task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
107page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
108minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
109major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
110context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
111cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
112alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
113emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
83 114
84L1-dcache|l1-d|l1d|L1-data | 115L1-dcache|l1-d|l1d|L1-data |
85L1-icache|l1-i|l1i|L1-instruction | 116L1-icache|l1-i|l1i|L1-instruction |
@@ -87,14 +118,14 @@ LLC|L2 |
87dTLB|d-tlb|Data-TLB | 118dTLB|d-tlb|Data-TLB |
88iTLB|i-tlb|Instruction-TLB | 119iTLB|i-tlb|Instruction-TLB |
89branch|branches|bpu|btb|bpc | 120branch|branches|bpu|btb|bpc |
90node { return str(PE_NAME_CACHE_TYPE); } 121node { return str(yyscanner, PE_NAME_CACHE_TYPE); }
91 122
92load|loads|read | 123load|loads|read |
93store|stores|write | 124store|stores|write |
94prefetch|prefetches | 125prefetch|prefetches |
95speculative-read|speculative-load | 126speculative-read|speculative-load |
96refs|Reference|ops|access | 127refs|Reference|ops|access |
97misses|miss { return str(PE_NAME_CACHE_OP_RESULT); } 128misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
98 129
99 /* 130 /*
100 * These are event config hardcoded term names to be specified 131 * These are event config hardcoded term names to be specified
@@ -102,38 +133,39 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
102 * so we can put them here directly. In case the we have a conflict 133 * so we can put them here directly. In case the we have a conflict
103 * in future, this needs to go into '//' condition block. 134 * in future, this needs to go into '//' condition block.
104 */ 135 */
105config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); } 136config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
106config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); } 137config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
107config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); } 138config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
108name { return term(PARSE_EVENTS__TERM_TYPE_NAME); } 139name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
109period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 140period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
110branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 141branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
111 142
112mem: { BEGIN(mem); return PE_PREFIX_MEM; } 143mem: { BEGIN(mem); return PE_PREFIX_MEM; }
113r{num_raw_hex} { return raw(); } 144r{num_raw_hex} { return raw(yyscanner); }
114{num_dec} { return value(10); } 145{num_dec} { return value(yyscanner, 10); }
115{num_hex} { return value(16); } 146{num_hex} { return value(yyscanner, 16); }
116 147
117{modifier_event} { return str(PE_MODIFIER_EVENT); } 148{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
118{name} { return str(PE_NAME); } 149{name} { return str(yyscanner, PE_NAME); }
119"/" { return '/'; } 150"/" { return '/'; }
120- { return '-'; } 151- { return '-'; }
121, { return ','; } 152, { return ','; }
122: { return ':'; } 153: { return ':'; }
123= { return '='; } 154= { return '='; }
155\n { }
124 156
125<mem>{ 157<mem>{
126{modifier_bp} { return str(PE_MODIFIER_BP); } 158{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
127: { return ':'; } 159: { return ':'; }
128{num_dec} { return value(10); } 160{num_dec} { return value(yyscanner, 10); }
129{num_hex} { return value(16); } 161{num_hex} { return value(yyscanner, 16); }
130 /* 162 /*
131 * We need to separate 'mem:' scanner part, in order to get specific 163 * We need to separate 'mem:' scanner part, in order to get specific
132 * modifier bits parsed out. Otherwise we would need to handle PE_NAME 164 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
133 * and we'd need to parse it manually. During the escape from <mem> 165 * and we'd need to parse it manually. During the escape from <mem>
134 * state we need to put the escaping char back, so we dont miss it. 166 * state we need to put the escaping char back, so we dont miss it.
135 */ 167 */
136. { unput(*parse_events_text); BEGIN(INITIAL); } 168. { unput(*yytext); BEGIN(INITIAL); }
137 /* 169 /*
138 * We destroy the scanner after reaching EOF, 170 * We destroy the scanner after reaching EOF,
139 * but anyway just to be sure get back to INIT state. 171 * but anyway just to be sure get back to INIT state.
@@ -143,7 +175,7 @@ r{num_raw_hex} { return raw(); }
143 175
144%% 176%%
145 177
146int parse_events_wrap(void) 178int parse_events_wrap(void *scanner __used)
147{ 179{
148 return 1; 180 return 1;
149} 181}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 362cc59332ae..2bc5fbff2b5d 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -1,7 +1,8 @@
1 1%pure-parser
2%name-prefix "parse_events_" 2%name-prefix "parse_events_"
3%parse-param {struct list_head *list_all} 3%parse-param {void *_data}
4%parse-param {int *idx} 4%parse-param {void *scanner}
5%lex-param {void* scanner}
5 6
6%{ 7%{
7 8
@@ -12,8 +13,9 @@
12#include "types.h" 13#include "types.h"
13#include "util.h" 14#include "util.h"
14#include "parse-events.h" 15#include "parse-events.h"
16#include "parse-events-bison.h"
15 17
16extern int parse_events_lex (void); 18extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
17 19
18#define ABORT_ON(val) \ 20#define ABORT_ON(val) \
19do { \ 21do { \
@@ -23,14 +25,16 @@ do { \
23 25
24%} 26%}
25 27
26%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM 28%token PE_START_EVENTS PE_START_TERMS
29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
27%token PE_NAME 30%token PE_NAME
28%token PE_MODIFIER_EVENT PE_MODIFIER_BP 31%token PE_MODIFIER_EVENT PE_MODIFIER_BP
29%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
30%token PE_PREFIX_MEM PE_PREFIX_RAW 33%token PE_PREFIX_MEM PE_PREFIX_RAW
31%token PE_ERROR 34%token PE_ERROR
32%type <num> PE_VALUE 35%type <num> PE_VALUE
33%type <num> PE_VALUE_SYM 36%type <num> PE_VALUE_SYM_HW
37%type <num> PE_VALUE_SYM_SW
34%type <num> PE_RAW 38%type <num> PE_RAW
35%type <num> PE_TERM 39%type <num> PE_TERM
36%type <str> PE_NAME 40%type <str> PE_NAME
@@ -38,6 +42,7 @@ do { \
38%type <str> PE_NAME_CACHE_OP_RESULT 42%type <str> PE_NAME_CACHE_OP_RESULT
39%type <str> PE_MODIFIER_EVENT 43%type <str> PE_MODIFIER_EVENT
40%type <str> PE_MODIFIER_BP 44%type <str> PE_MODIFIER_BP
45%type <num> value_sym
41%type <head> event_config 46%type <head> event_config
42%type <term> event_term 47%type <term> event_term
43%type <head> event_pmu 48%type <head> event_pmu
@@ -58,24 +63,33 @@ do { \
58} 63}
59%% 64%%
60 65
66start:
67PE_START_EVENTS events
68|
69PE_START_TERMS terms
70
61events: 71events:
62events ',' event | event 72events ',' event | event
63 73
64event: 74event:
65event_def PE_MODIFIER_EVENT 75event_def PE_MODIFIER_EVENT
66{ 76{
77 struct parse_events_data__events *data = _data;
78
67 /* 79 /*
68 * Apply modifier on all events added by single event definition 80 * Apply modifier on all events added by single event definition
69 * (there could be more events added for multiple tracepoint 81 * (there could be more events added for multiple tracepoint
70 * definitions via '*?'. 82 * definitions via '*?'.
71 */ 83 */
72 ABORT_ON(parse_events_modifier($1, $2)); 84 ABORT_ON(parse_events_modifier($1, $2));
73 parse_events_update_lists($1, list_all); 85 parse_events_update_lists($1, &data->list);
74} 86}
75| 87|
76event_def 88event_def
77{ 89{
78 parse_events_update_lists($1, list_all); 90 struct parse_events_data__events *data = _data;
91
92 parse_events_update_lists($1, &data->list);
79} 93}
80 94
81event_def: event_pmu | 95event_def: event_pmu |
@@ -89,104 +103,131 @@ event_def: event_pmu |
89event_pmu: 103event_pmu:
90PE_NAME '/' event_config '/' 104PE_NAME '/' event_config '/'
91{ 105{
106 struct parse_events_data__events *data = _data;
92 struct list_head *list = NULL; 107 struct list_head *list = NULL;
93 108
94 ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3)); 109 ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
95 parse_events__free_terms($3); 110 parse_events__free_terms($3);
96 $$ = list; 111 $$ = list;
97} 112}
98 113
114value_sym:
115PE_VALUE_SYM_HW
116|
117PE_VALUE_SYM_SW
118
99event_legacy_symbol: 119event_legacy_symbol:
100PE_VALUE_SYM '/' event_config '/' 120value_sym '/' event_config '/'
101{ 121{
122 struct parse_events_data__events *data = _data;
102 struct list_head *list = NULL; 123 struct list_head *list = NULL;
103 int type = $1 >> 16; 124 int type = $1 >> 16;
104 int config = $1 & 255; 125 int config = $1 & 255;
105 126
106 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3)); 127 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
128 type, config, $3));
107 parse_events__free_terms($3); 129 parse_events__free_terms($3);
108 $$ = list; 130 $$ = list;
109} 131}
110| 132|
111PE_VALUE_SYM sep_slash_dc 133value_sym sep_slash_dc
112{ 134{
135 struct parse_events_data__events *data = _data;
113 struct list_head *list = NULL; 136 struct list_head *list = NULL;
114 int type = $1 >> 16; 137 int type = $1 >> 16;
115 int config = $1 & 255; 138 int config = $1 & 255;
116 139
117 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL)); 140 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
141 type, config, NULL));
118 $$ = list; 142 $$ = list;
119} 143}
120 144
121event_legacy_cache: 145event_legacy_cache:
122PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 146PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
123{ 147{
148 struct parse_events_data__events *data = _data;
124 struct list_head *list = NULL; 149 struct list_head *list = NULL;
125 150
126 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5)); 151 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
127 $$ = list; 152 $$ = list;
128} 153}
129| 154|
130PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 155PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
131{ 156{
157 struct parse_events_data__events *data = _data;
132 struct list_head *list = NULL; 158 struct list_head *list = NULL;
133 159
134 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL)); 160 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
135 $$ = list; 161 $$ = list;
136} 162}
137| 163|
138PE_NAME_CACHE_TYPE 164PE_NAME_CACHE_TYPE
139{ 165{
166 struct parse_events_data__events *data = _data;
140 struct list_head *list = NULL; 167 struct list_head *list = NULL;
141 168
142 ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL)); 169 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
143 $$ = list; 170 $$ = list;
144} 171}
145 172
146event_legacy_mem: 173event_legacy_mem:
147PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 174PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
148{ 175{
176 struct parse_events_data__events *data = _data;
149 struct list_head *list = NULL; 177 struct list_head *list = NULL;
150 178
151 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4)); 179 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
180 (void *) $2, $4));
152 $$ = list; 181 $$ = list;
153} 182}
154| 183|
155PE_PREFIX_MEM PE_VALUE sep_dc 184PE_PREFIX_MEM PE_VALUE sep_dc
156{ 185{
186 struct parse_events_data__events *data = _data;
157 struct list_head *list = NULL; 187 struct list_head *list = NULL;
158 188
159 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL)); 189 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
190 (void *) $2, NULL));
160 $$ = list; 191 $$ = list;
161} 192}
162 193
163event_legacy_tracepoint: 194event_legacy_tracepoint:
164PE_NAME ':' PE_NAME 195PE_NAME ':' PE_NAME
165{ 196{
197 struct parse_events_data__events *data = _data;
166 struct list_head *list = NULL; 198 struct list_head *list = NULL;
167 199
168 ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3)); 200 ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
169 $$ = list; 201 $$ = list;
170} 202}
171 203
172event_legacy_numeric: 204event_legacy_numeric:
173PE_VALUE ':' PE_VALUE 205PE_VALUE ':' PE_VALUE
174{ 206{
207 struct parse_events_data__events *data = _data;
175 struct list_head *list = NULL; 208 struct list_head *list = NULL;
176 209
177 ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL)); 210 ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL));
178 $$ = list; 211 $$ = list;
179} 212}
180 213
181event_legacy_raw: 214event_legacy_raw:
182PE_RAW 215PE_RAW
183{ 216{
217 struct parse_events_data__events *data = _data;
184 struct list_head *list = NULL; 218 struct list_head *list = NULL;
185 219
186 ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL)); 220 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
221 PERF_TYPE_RAW, $1, NULL));
187 $$ = list; 222 $$ = list;
188} 223}
189 224
225terms: event_config
226{
227 struct parse_events_data__terms *data = _data;
228 data->terms = $1;
229}
230
190event_config: 231event_config:
191event_config ',' event_term 232event_config ',' event_term
192{ 233{
@@ -267,8 +308,7 @@ sep_slash_dc: '/' | ':' |
267 308
268%% 309%%
269 310
270void parse_events_error(struct list_head *list_all __used, 311void parse_events_error(void *data __used, void *scanner __used,
271 int *idx __used,
272 char const *msg __used) 312 char const *msg __used)
273{ 313{
274} 314}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index a119a5371699..67715a42cd6d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 72 "%s/bus/event_source/devices/%s/format", sysfs, name);
73 73
74 if (stat(path, &st) < 0) 74 if (stat(path, &st) < 0)
75 return -1; 75 return 0; /* no error if format does not exist */
76 76
77 if (pmu_format_parse(path, format)) 77 if (pmu_format_parse(path, format))
78 return -1; 78 return -1;
@@ -80,6 +80,114 @@ static int pmu_format(char *name, struct list_head *format)
80 return 0; 80 return 0;
81} 81}
82 82
83static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
84{
85 struct perf_pmu__alias *alias;
86 char buf[256];
87 int ret;
88
89 ret = fread(buf, 1, sizeof(buf), file);
90 if (ret == 0)
91 return -EINVAL;
92 buf[ret] = 0;
93
94 alias = malloc(sizeof(*alias));
95 if (!alias)
96 return -ENOMEM;
97
98 INIT_LIST_HEAD(&alias->terms);
99 ret = parse_events_terms(&alias->terms, buf);
100 if (ret) {
101 free(alias);
102 return ret;
103 }
104
105 alias->name = strdup(name);
106 list_add_tail(&alias->list, list);
107 return 0;
108}
109
110/*
111 * Process all the sysfs attributes located under the directory
112 * specified in 'dir' parameter.
113 */
114static int pmu_aliases_parse(char *dir, struct list_head *head)
115{
116 struct dirent *evt_ent;
117 DIR *event_dir;
118 int ret = 0;
119
120 event_dir = opendir(dir);
121 if (!event_dir)
122 return -EINVAL;
123
124 while (!ret && (evt_ent = readdir(event_dir))) {
125 char path[PATH_MAX];
126 char *name = evt_ent->d_name;
127 FILE *file;
128
129 if (!strcmp(name, ".") || !strcmp(name, ".."))
130 continue;
131
132 snprintf(path, PATH_MAX, "%s/%s", dir, name);
133
134 ret = -EINVAL;
135 file = fopen(path, "r");
136 if (!file)
137 break;
138 ret = perf_pmu__new_alias(head, name, file);
139 fclose(file);
140 }
141
142 closedir(event_dir);
143 return ret;
144}
145
146/*
147 * Reading the pmu event aliases definition, which should be located at:
148 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
149 */
150static int pmu_aliases(char *name, struct list_head *head)
151{
152 struct stat st;
153 char path[PATH_MAX];
154 const char *sysfs;
155
156 sysfs = sysfs_find_mountpoint();
157 if (!sysfs)
158 return -1;
159
160 snprintf(path, PATH_MAX,
161 "%s/bus/event_source/devices/%s/events", sysfs, name);
162
163 if (stat(path, &st) < 0)
164 return -1;
165
166 if (pmu_aliases_parse(path, head))
167 return -1;
168
169 return 0;
170}
171
172static int pmu_alias_terms(struct perf_pmu__alias *alias,
173 struct list_head *terms)
174{
175 struct parse_events__term *term, *clone;
176 LIST_HEAD(list);
177 int ret;
178
179 list_for_each_entry(term, &alias->terms, list) {
180 ret = parse_events__term_clone(&clone, term);
181 if (ret) {
182 parse_events__free_terms(&list);
183 return ret;
184 }
185 list_add_tail(&clone->list, &list);
186 }
187 list_splice(&list, terms);
188 return 0;
189}
190
83/* 191/*
84 * Reading/parsing the default pmu type value, which should be 192 * Reading/parsing the default pmu type value, which should be
85 * located at: 193 * located at:
@@ -118,6 +226,7 @@ static struct perf_pmu *pmu_lookup(char *name)
118{ 226{
119 struct perf_pmu *pmu; 227 struct perf_pmu *pmu;
120 LIST_HEAD(format); 228 LIST_HEAD(format);
229 LIST_HEAD(aliases);
121 __u32 type; 230 __u32 type;
122 231
123 /* 232 /*
@@ -135,10 +244,15 @@ static struct perf_pmu *pmu_lookup(char *name)
135 if (!pmu) 244 if (!pmu)
136 return NULL; 245 return NULL;
137 246
247 pmu_aliases(name, &aliases);
248
138 INIT_LIST_HEAD(&pmu->format); 249 INIT_LIST_HEAD(&pmu->format);
250 INIT_LIST_HEAD(&pmu->aliases);
139 list_splice(&format, &pmu->format); 251 list_splice(&format, &pmu->format);
252 list_splice(&aliases, &pmu->aliases);
140 pmu->name = strdup(name); 253 pmu->name = strdup(name);
141 pmu->type = type; 254 pmu->type = type;
255 list_add_tail(&pmu->list, &pmus);
142 return pmu; 256 return pmu;
143} 257}
144 258
@@ -279,6 +393,59 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
279 return pmu_config(&pmu->format, attr, head_terms); 393 return pmu_config(&pmu->format, attr, head_terms);
280} 394}
281 395
396static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
397 struct parse_events__term *term)
398{
399 struct perf_pmu__alias *alias;
400 char *name;
401
402 if (parse_events__is_hardcoded_term(term))
403 return NULL;
404
405 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
406 if (term->val.num != 1)
407 return NULL;
408 if (pmu_find_format(&pmu->format, term->config))
409 return NULL;
410 name = term->config;
411 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
412 if (strcasecmp(term->config, "event"))
413 return NULL;
414 name = term->val.str;
415 } else {
416 return NULL;
417 }
418
419 list_for_each_entry(alias, &pmu->aliases, list) {
420 if (!strcasecmp(alias->name, name))
421 return alias;
422 }
423 return NULL;
424}
425
426/*
427 * Find alias in the terms list and replace it with the terms
428 * defined for the alias
429 */
430int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
431{
432 struct parse_events__term *term, *h;
433 struct perf_pmu__alias *alias;
434 int ret;
435
436 list_for_each_entry_safe(term, h, head_terms, list) {
437 alias = pmu_find_alias(pmu, term);
438 if (!alias)
439 continue;
440 ret = pmu_alias_terms(alias, &term->list);
441 if (ret)
442 return ret;
443 list_del(&term->list);
444 free(term);
445 }
446 return 0;
447}
448
282int perf_pmu__new_format(struct list_head *list, char *name, 449int perf_pmu__new_format(struct list_head *list, char *name,
283 int config, unsigned long *bits) 450 int config, unsigned long *bits)
284{ 451{
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 68c0db965e1f..535f2c5258ab 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -19,17 +19,26 @@ struct perf_pmu__format {
19 struct list_head list; 19 struct list_head list;
20}; 20};
21 21
22struct perf_pmu__alias {
23 char *name;
24 struct list_head terms;
25 struct list_head list;
26};
27
22struct perf_pmu { 28struct perf_pmu {
23 char *name; 29 char *name;
24 __u32 type; 30 __u32 type;
25 struct list_head format; 31 struct list_head format;
32 struct list_head aliases;
26 struct list_head list; 33 struct list_head list;
27}; 34};
28 35
29struct perf_pmu *perf_pmu__find(char *name); 36struct perf_pmu *perf_pmu__find(char *name);
30int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 37int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
31 struct list_head *head_terms); 38 struct list_head *head_terms);
32 39int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
40struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
41 struct list_head *head_terms);
33int perf_pmu_wrap(void); 42int perf_pmu_wrap(void);
34void perf_pmu_error(struct list_head *list, char *name, char const *msg); 43void perf_pmu_error(struct list_head *list, char *name, char const *msg);
35 44
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 4c1b3d72a1d2..02dfa19a467f 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event,
209 define_symbolic_values(args->symbol.symbols, ev_name, 209 define_symbolic_values(args->symbol.symbols, ev_name,
210 cur_field_name); 210 cur_field_name);
211 break; 211 break;
212 case PRINT_HEX:
213 define_event_symbols(event, ev_name, args->hex.field);
214 define_event_symbols(event, ev_name, args->hex.size);
215 break;
212 case PRINT_BSTRING: 216 case PRINT_BSTRING:
213 case PRINT_DYNAMIC_ARRAY: 217 case PRINT_DYNAMIC_ARRAY:
214 case PRINT_STRING: 218 case PRINT_STRING:
@@ -233,7 +237,8 @@ static void define_event_symbols(struct event_format *event,
233 define_event_symbols(event, ev_name, args->next); 237 define_event_symbols(event, ev_name, args->next);
234} 238}
235 239
236static inline struct event_format *find_cache_event(int type) 240static inline
241struct event_format *find_cache_event(struct pevent *pevent, int type)
237{ 242{
238 static char ev_name[256]; 243 static char ev_name[256];
239 struct event_format *event; 244 struct event_format *event;
@@ -241,7 +246,7 @@ static inline struct event_format *find_cache_event(int type)
241 if (events[type]) 246 if (events[type])
242 return events[type]; 247 return events[type];
243 248
244 events[type] = event = trace_find_event(type); 249 events[type] = event = pevent_find_event(pevent, type);
245 if (!event) 250 if (!event)
246 return NULL; 251 return NULL;
247 252
@@ -252,7 +257,8 @@ static inline struct event_format *find_cache_event(int type)
252 return event; 257 return event;
253} 258}
254 259
255static void perl_process_tracepoint(union perf_event *pevent __unused, 260static void perl_process_tracepoint(union perf_event *perf_event __unused,
261 struct pevent *pevent,
256 struct perf_sample *sample, 262 struct perf_sample *sample,
257 struct perf_evsel *evsel, 263 struct perf_evsel *evsel,
258 struct machine *machine __unused, 264 struct machine *machine __unused,
@@ -275,13 +281,13 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
275 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 281 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
276 return; 282 return;
277 283
278 type = trace_parse_common_type(data); 284 type = trace_parse_common_type(pevent, data);
279 285
280 event = find_cache_event(type); 286 event = find_cache_event(pevent, type);
281 if (!event) 287 if (!event)
282 die("ug! no event found for type %d", type); 288 die("ug! no event found for type %d", type);
283 289
284 pid = trace_parse_common_pid(data); 290 pid = trace_parse_common_pid(pevent, data);
285 291
286 sprintf(handler, "%s::%s", event->system, event->name); 292 sprintf(handler, "%s::%s", event->system, event->name);
287 293
@@ -314,7 +320,8 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
314 offset = field->offset; 320 offset = field->offset;
315 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0))); 321 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
316 } else { /* FIELD_IS_NUMERIC */ 322 } else { /* FIELD_IS_NUMERIC */
317 val = read_size(data + field->offset, field->size); 323 val = read_size(pevent, data + field->offset,
324 field->size);
318 if (field->flags & FIELD_IS_SIGNED) { 325 if (field->flags & FIELD_IS_SIGNED) {
319 XPUSHs(sv_2mortal(newSViv(val))); 326 XPUSHs(sv_2mortal(newSViv(val)));
320 } else { 327 } else {
@@ -368,14 +375,15 @@ static void perl_process_event_generic(union perf_event *pevent __unused,
368 LEAVE; 375 LEAVE;
369} 376}
370 377
371static void perl_process_event(union perf_event *pevent, 378static void perl_process_event(union perf_event *event,
379 struct pevent *pevent,
372 struct perf_sample *sample, 380 struct perf_sample *sample,
373 struct perf_evsel *evsel, 381 struct perf_evsel *evsel,
374 struct machine *machine, 382 struct machine *machine,
375 struct thread *thread) 383 struct thread *thread)
376{ 384{
377 perl_process_tracepoint(pevent, sample, evsel, machine, thread); 385 perl_process_tracepoint(event, pevent, sample, evsel, machine, thread);
378 perl_process_event_generic(pevent, sample, evsel, machine, thread); 386 perl_process_event_generic(event, sample, evsel, machine, thread);
379} 387}
380 388
381static void run_start_sub(void) 389static void run_start_sub(void)
@@ -448,7 +456,7 @@ static int perl_stop_script(void)
448 return 0; 456 return 0;
449} 457}
450 458
451static int perl_generate_script(const char *outfile) 459static int perl_generate_script(struct pevent *pevent, const char *outfile)
452{ 460{
453 struct event_format *event = NULL; 461 struct event_format *event = NULL;
454 struct format_field *f; 462 struct format_field *f;
@@ -495,7 +503,7 @@ static int perl_generate_script(const char *outfile)
495 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); 503 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
496 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n"); 504 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
497 505
498 while ((event = trace_find_next_event(event))) { 506 while ((event = trace_find_next_event(pevent, event))) {
499 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); 507 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
500 fprintf(ofp, "\tmy ("); 508 fprintf(ofp, "\tmy (");
501 509
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index acb9795286c4..ce4d1b0c3862 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event,
166 define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, 166 define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
167 cur_field_name); 167 cur_field_name);
168 break; 168 break;
169 case PRINT_HEX:
170 define_event_symbols(event, ev_name, args->hex.field);
171 define_event_symbols(event, ev_name, args->hex.size);
172 break;
169 case PRINT_STRING: 173 case PRINT_STRING:
170 break; 174 break;
171 case PRINT_TYPE: 175 case PRINT_TYPE:
@@ -190,7 +194,8 @@ static void define_event_symbols(struct event_format *event,
190 define_event_symbols(event, ev_name, args->next); 194 define_event_symbols(event, ev_name, args->next);
191} 195}
192 196
193static inline struct event_format *find_cache_event(int type) 197static inline
198struct event_format *find_cache_event(struct pevent *pevent, int type)
194{ 199{
195 static char ev_name[256]; 200 static char ev_name[256];
196 struct event_format *event; 201 struct event_format *event;
@@ -198,7 +203,7 @@ static inline struct event_format *find_cache_event(int type)
198 if (events[type]) 203 if (events[type])
199 return events[type]; 204 return events[type];
200 205
201 events[type] = event = trace_find_event(type); 206 events[type] = event = pevent_find_event(pevent, type);
202 if (!event) 207 if (!event)
203 return NULL; 208 return NULL;
204 209
@@ -209,7 +214,8 @@ static inline struct event_format *find_cache_event(int type)
209 return event; 214 return event;
210} 215}
211 216
212static void python_process_event(union perf_event *pevent __unused, 217static void python_process_event(union perf_event *perf_event __unused,
218 struct pevent *pevent,
213 struct perf_sample *sample, 219 struct perf_sample *sample,
214 struct perf_evsel *evsel __unused, 220 struct perf_evsel *evsel __unused,
215 struct machine *machine __unused, 221 struct machine *machine __unused,
@@ -233,13 +239,13 @@ static void python_process_event(union perf_event *pevent __unused,
233 if (!t) 239 if (!t)
234 Py_FatalError("couldn't create Python tuple"); 240 Py_FatalError("couldn't create Python tuple");
235 241
236 type = trace_parse_common_type(data); 242 type = trace_parse_common_type(pevent, data);
237 243
238 event = find_cache_event(type); 244 event = find_cache_event(pevent, type);
239 if (!event) 245 if (!event)
240 die("ug! no event found for type %d", type); 246 die("ug! no event found for type %d", type);
241 247
242 pid = trace_parse_common_pid(data); 248 pid = trace_parse_common_pid(pevent, data);
243 249
244 sprintf(handler_name, "%s__%s", event->system, event->name); 250 sprintf(handler_name, "%s__%s", event->system, event->name);
245 251
@@ -284,7 +290,8 @@ static void python_process_event(union perf_event *pevent __unused,
284 offset = field->offset; 290 offset = field->offset;
285 obj = PyString_FromString((char *)data + offset); 291 obj = PyString_FromString((char *)data + offset);
286 } else { /* FIELD_IS_NUMERIC */ 292 } else { /* FIELD_IS_NUMERIC */
287 val = read_size(data + field->offset, field->size); 293 val = read_size(pevent, data + field->offset,
294 field->size);
288 if (field->flags & FIELD_IS_SIGNED) { 295 if (field->flags & FIELD_IS_SIGNED) {
289 if ((long long)val >= LONG_MIN && 296 if ((long long)val >= LONG_MIN &&
290 (long long)val <= LONG_MAX) 297 (long long)val <= LONG_MAX)
@@ -438,7 +445,7 @@ out:
438 return err; 445 return err;
439} 446}
440 447
441static int python_generate_script(const char *outfile) 448static int python_generate_script(struct pevent *pevent, const char *outfile)
442{ 449{
443 struct event_format *event = NULL; 450 struct event_format *event = NULL;
444 struct format_field *f; 451 struct format_field *f;
@@ -487,7 +494,7 @@ static int python_generate_script(const char *outfile)
487 fprintf(ofp, "def trace_end():\n"); 494 fprintf(ofp, "def trace_end():\n");
488 fprintf(ofp, "\tprint \"in trace_end\"\n\n"); 495 fprintf(ofp, "\tprint \"in trace_end\"\n\n");
489 496
490 while ((event = trace_find_next_event(event))) { 497 while ((event = trace_find_next_event(pevent, event))) {
491 fprintf(ofp, "def %s__%s(", event->system, event->name); 498 fprintf(ofp, "def %s__%s(", event->system, event->name);
492 fprintf(ofp, "event_name, "); 499 fprintf(ofp, "event_name, ");
493 fprintf(ofp, "context, "); 500 fprintf(ofp, "context, ");
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 56142d0fb8d7..8e485592ca20 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "sort.h" 14#include "sort.h"
15#include "util.h" 15#include "util.h"
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h"
17 18
18static int perf_session__open(struct perf_session *self, bool force) 19static int perf_session__open(struct perf_session *self, bool force)
19{ 20{
@@ -289,7 +290,6 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
289} 290}
290 291
291int machine__resolve_callchain(struct machine *self, 292int machine__resolve_callchain(struct machine *self,
292 struct perf_evsel *evsel __used,
293 struct thread *thread, 293 struct thread *thread,
294 struct ip_callchain *chain, 294 struct ip_callchain *chain,
295 struct symbol **parent) 295 struct symbol **parent)
@@ -1449,7 +1449,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1449 ret += hists__fprintf_nr_events(&session->hists, fp); 1449 ret += hists__fprintf_nr_events(&session->hists, fp);
1450 1450
1451 list_for_each_entry(pos, &session->evlist->entries, node) { 1451 list_for_each_entry(pos, &session->evlist->entries, node) {
1452 ret += fprintf(fp, "%s stats:\n", event_name(pos)); 1452 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1453 ret += hists__fprintf_nr_events(&pos->hists, fp); 1453 ret += hists__fprintf_nr_events(&pos->hists, fp);
1454 } 1454 }
1455 1455
@@ -1490,8 +1490,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1490} 1490}
1491 1491
1492void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1492void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1493 struct machine *machine, struct perf_evsel *evsel, 1493 struct machine *machine, int print_sym,
1494 int print_sym, int print_dso, int print_symoffset) 1494 int print_dso, int print_symoffset)
1495{ 1495{
1496 struct addr_location al; 1496 struct addr_location al;
1497 struct callchain_cursor_node *node; 1497 struct callchain_cursor_node *node;
@@ -1505,7 +1505,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1505 1505
1506 if (symbol_conf.use_callchain && sample->callchain) { 1506 if (symbol_conf.use_callchain && sample->callchain) {
1507 1507
1508 if (machine__resolve_callchain(machine, evsel, al.thread, 1508 if (machine__resolve_callchain(machine, al.thread,
1509 sample->callchain, NULL) != 0) { 1509 sample->callchain, NULL) != 0) {
1510 if (verbose) 1510 if (verbose)
1511 error("Failed to resolve callchain. Skipping\n"); 1511 error("Failed to resolve callchain. Skipping\n");
@@ -1611,3 +1611,58 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1611 perf_header__fprintf_info(session, fp, full); 1611 perf_header__fprintf_info(session, fp, full);
1612 fprintf(fp, "# ========\n#\n"); 1612 fprintf(fp, "# ========\n#\n");
1613} 1613}
1614
1615
1616int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1617 const struct perf_evsel_str_handler *assocs,
1618 size_t nr_assocs)
1619{
1620 struct perf_evlist *evlist = session->evlist;
1621 struct event_format *format;
1622 struct perf_evsel *evsel;
1623 char *tracepoint, *name;
1624 size_t i;
1625 int err;
1626
1627 for (i = 0; i < nr_assocs; i++) {
1628 err = -ENOMEM;
1629 tracepoint = strdup(assocs[i].name);
1630 if (tracepoint == NULL)
1631 goto out;
1632
1633 err = -ENOENT;
1634 name = strchr(tracepoint, ':');
1635 if (name == NULL)
1636 goto out_free;
1637
1638 *name++ = '\0';
1639 format = pevent_find_event_by_name(session->pevent,
1640 tracepoint, name);
1641 if (format == NULL) {
1642 /*
1643 * Adding a handler for an event not in the session,
1644 * just ignore it.
1645 */
1646 goto next;
1647 }
1648
1649 evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
1650 if (evsel == NULL)
1651 goto next;
1652
1653 err = -EEXIST;
1654 if (evsel->handler.func != NULL)
1655 goto out_free;
1656 evsel->handler.func = assocs[i].handler;
1657next:
1658 free(tracepoint);
1659 }
1660
1661 err = 0;
1662out:
1663 return err;
1664
1665out_free:
1666 free(tracepoint);
1667 goto out;
1668}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0c702e3f0a36..7c435bde6eb0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -33,6 +33,7 @@ struct perf_session {
33 struct machine host_machine; 33 struct machine host_machine;
34 struct rb_root machines; 34 struct rb_root machines;
35 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
36 struct pevent *pevent;
36 /* 37 /*
37 * FIXME: Need to split this up further, we need global 38 * FIXME: Need to split this up further, we need global
38 * stats + per event stats. 'perf diff' also needs 39 * stats + per event stats. 'perf diff' also needs
@@ -151,11 +152,20 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
151 unsigned int type); 152 unsigned int type);
152 153
153void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 154void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
154 struct machine *machine, struct perf_evsel *evsel, 155 struct machine *machine, int print_sym,
155 int print_sym, int print_dso, int print_symoffset); 156 int print_dso, int print_symoffset);
156 157
157int perf_session__cpu_bitmap(struct perf_session *session, 158int perf_session__cpu_bitmap(struct perf_session *session,
158 const char *cpu_list, unsigned long *cpu_bitmap); 159 const char *cpu_list, unsigned long *cpu_bitmap);
159 160
160void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full); 161void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
162
163struct perf_evsel_str_handler;
164
165int __perf_session__set_tracepoints_handlers(struct perf_session *session,
166 const struct perf_evsel_str_handler *assocs,
167 size_t nr_assocs);
168
169#define perf_session__set_tracepoints_handlers(session, array) \
170 __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
161#endif /* __PERF_SESSION_H */ 171#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index a27237430c5f..0f5a0a496bc4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -241,6 +241,54 @@ struct sort_entry sort_sym = {
241 .se_width_idx = HISTC_SYMBOL, 241 .se_width_idx = HISTC_SYMBOL,
242}; 242};
243 243
244/* --sort srcline */
245
246static int64_t
247sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
248{
249 return (int64_t)(right->ip - left->ip);
250}
251
252static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
253 size_t size, unsigned int width __used)
254{
255 FILE *fp;
256 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
257 size_t line_len;
258
259 if (path != NULL)
260 goto out_path;
261
262 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
263 self->ms.map->dso->long_name, self->ip);
264 fp = popen(cmd, "r");
265 if (!fp)
266 goto out_ip;
267
268 if (getline(&path, &line_len, fp) < 0 || !line_len)
269 goto out_ip;
270 fclose(fp);
271 self->srcline = strdup(path);
272 if (self->srcline == NULL)
273 goto out_ip;
274
275 nl = strchr(self->srcline, '\n');
276 if (nl != NULL)
277 *nl = '\0';
278 path = self->srcline;
279out_path:
280 return repsep_snprintf(bf, size, "%s", path);
281out_ip:
282 return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
283}
284
285struct sort_entry sort_srcline = {
286 .se_header = "Source:Line",
287 .se_cmp = sort__srcline_cmp,
288 .se_snprintf = hist_entry__srcline_snprintf,
289 .se_width_idx = HISTC_SRCLINE,
290};
291
244/* --sort parent */ 292/* --sort parent */
245 293
246static int64_t 294static int64_t
@@ -439,6 +487,7 @@ static struct sort_dimension sort_dimensions[] = {
439 DIM(SORT_PARENT, "parent", sort_parent), 487 DIM(SORT_PARENT, "parent", sort_parent),
440 DIM(SORT_CPU, "cpu", sort_cpu), 488 DIM(SORT_CPU, "cpu", sort_cpu),
441 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), 489 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
490 DIM(SORT_SRCLINE, "srcline", sort_srcline),
442}; 491};
443 492
444int sort_dimension__add(const char *tok) 493int sort_dimension__add(const char *tok)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 472aa5a63a58..e724b26acd51 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -71,6 +71,7 @@ struct hist_entry {
71 char level; 71 char level;
72 bool used; 72 bool used;
73 u8 filtered; 73 u8 filtered;
74 char *srcline;
74 struct symbol *parent; 75 struct symbol *parent;
75 union { 76 union {
76 unsigned long position; 77 unsigned long position;
@@ -93,6 +94,7 @@ enum sort_type {
93 SORT_SYM_FROM, 94 SORT_SYM_FROM,
94 SORT_SYM_TO, 95 SORT_SYM_TO,
95 SORT_MISPREDICT, 96 SORT_MISPREDICT,
97 SORT_SRCLINE,
96}; 98};
97 99
98/* 100/*
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d5836382ff2c..199bc4d8905d 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -313,3 +313,25 @@ int strtailcmp(const char *s1, const char *s2)
313 return 0; 313 return 0;
314} 314}
315 315
316/**
317 * rtrim - Removes trailing whitespace from @s.
318 * @s: The string to be stripped.
319 *
320 * Note that the first trailing whitespace is replaced with a %NUL-terminator
321 * in the given string @s. Returns @s.
322 */
323char *rtrim(char *s)
324{
325 size_t size = strlen(s);
326 char *end;
327
328 if (!size)
329 return s;
330
331 end = s + size - 1;
332 while (end >= s && isspace(*end))
333 end--;
334 *(end + 1) = '\0';
335
336 return s;
337}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 3e2e5ea0f03f..50958bbeb26a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1478 goto out; 1478 goto out;
1479 } 1479 }
1480 1480
1481 sec = elf_section_by_name(elf, &ehdr, &shdr, 1481 /*
1482 ".note.gnu.build-id", NULL); 1482 * Check following sections for notes:
1483 if (sec == NULL) { 1483 * '.note.gnu.build-id'
1484 * '.notes'
1485 * '.note' (VDSO specific)
1486 */
1487 do {
1488 sec = elf_section_by_name(elf, &ehdr, &shdr,
1489 ".note.gnu.build-id", NULL);
1490 if (sec)
1491 break;
1492
1484 sec = elf_section_by_name(elf, &ehdr, &shdr, 1493 sec = elf_section_by_name(elf, &ehdr, &shdr,
1485 ".notes", NULL); 1494 ".notes", NULL);
1486 if (sec == NULL) 1495 if (sec)
1487 goto out; 1496 break;
1488 } 1497
1498 sec = elf_section_by_name(elf, &ehdr, &shdr,
1499 ".note", NULL);
1500 if (sec)
1501 break;
1502
1503 return err;
1504
1505 } while (0);
1489 1506
1490 data = elf_getdata(sec, NULL); 1507 data = elf_getdata(sec, NULL);
1491 if (data == NULL) 1508 if (data == NULL)
@@ -1590,11 +1607,62 @@ out:
1590 return err; 1607 return err;
1591} 1608}
1592 1609
1610static int filename__read_debuglink(const char *filename,
1611 char *debuglink, size_t size)
1612{
1613 int fd, err = -1;
1614 Elf *elf;
1615 GElf_Ehdr ehdr;
1616 GElf_Shdr shdr;
1617 Elf_Data *data;
1618 Elf_Scn *sec;
1619 Elf_Kind ek;
1620
1621 fd = open(filename, O_RDONLY);
1622 if (fd < 0)
1623 goto out;
1624
1625 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1626 if (elf == NULL) {
1627 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1628 goto out_close;
1629 }
1630
1631 ek = elf_kind(elf);
1632 if (ek != ELF_K_ELF)
1633 goto out_close;
1634
1635 if (gelf_getehdr(elf, &ehdr) == NULL) {
1636 pr_err("%s: cannot get elf header.\n", __func__);
1637 goto out_close;
1638 }
1639
1640 sec = elf_section_by_name(elf, &ehdr, &shdr,
1641 ".gnu_debuglink", NULL);
1642 if (sec == NULL)
1643 goto out_close;
1644
1645 data = elf_getdata(sec, NULL);
1646 if (data == NULL)
1647 goto out_close;
1648
1649 /* the start of this section is a zero-terminated string */
1650 strncpy(debuglink, data->d_buf, size);
1651
1652 elf_end(elf);
1653
1654out_close:
1655 close(fd);
1656out:
1657 return err;
1658}
1659
1593char dso__symtab_origin(const struct dso *dso) 1660char dso__symtab_origin(const struct dso *dso)
1594{ 1661{
1595 static const char origin[] = { 1662 static const char origin[] = {
1596 [SYMTAB__KALLSYMS] = 'k', 1663 [SYMTAB__KALLSYMS] = 'k',
1597 [SYMTAB__JAVA_JIT] = 'j', 1664 [SYMTAB__JAVA_JIT] = 'j',
1665 [SYMTAB__DEBUGLINK] = 'l',
1598 [SYMTAB__BUILD_ID_CACHE] = 'B', 1666 [SYMTAB__BUILD_ID_CACHE] = 'B',
1599 [SYMTAB__FEDORA_DEBUGINFO] = 'f', 1667 [SYMTAB__FEDORA_DEBUGINFO] = 'f',
1600 [SYMTAB__UBUNTU_DEBUGINFO] = 'u', 1668 [SYMTAB__UBUNTU_DEBUGINFO] = 'u',
@@ -1662,10 +1730,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1662 */ 1730 */
1663 want_symtab = 1; 1731 want_symtab = 1;
1664restart: 1732restart:
1665 for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; 1733 for (dso->symtab_type = SYMTAB__DEBUGLINK;
1666 dso->symtab_type != SYMTAB__NOT_FOUND; 1734 dso->symtab_type != SYMTAB__NOT_FOUND;
1667 dso->symtab_type++) { 1735 dso->symtab_type++) {
1668 switch (dso->symtab_type) { 1736 switch (dso->symtab_type) {
1737 case SYMTAB__DEBUGLINK: {
1738 char *debuglink;
1739 strncpy(name, dso->long_name, size);
1740 debuglink = name + dso->long_name_len;
1741 while (debuglink != name && *debuglink != '/')
1742 debuglink--;
1743 if (*debuglink == '/')
1744 debuglink++;
1745 filename__read_debuglink(dso->long_name, debuglink,
1746 size - (debuglink - name));
1747 }
1748 break;
1669 case SYMTAB__BUILD_ID_CACHE: 1749 case SYMTAB__BUILD_ID_CACHE:
1670 /* skip the locally configured cache if a symfs is given */ 1750 /* skip the locally configured cache if a symfs is given */
1671 if (symbol_conf.symfs[0] || 1751 if (symbol_conf.symfs[0] ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index af0752b1aca1..a884b99017f0 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -257,6 +257,7 @@ enum symtab_type {
257 SYMTAB__KALLSYMS = 0, 257 SYMTAB__KALLSYMS = 0,
258 SYMTAB__GUEST_KALLSYMS, 258 SYMTAB__GUEST_KALLSYMS,
259 SYMTAB__JAVA_JIT, 259 SYMTAB__JAVA_JIT,
260 SYMTAB__DEBUGLINK,
260 SYMTAB__BUILD_ID_CACHE, 261 SYMTAB__BUILD_ID_CACHE,
261 SYMTAB__FEDORA_DEBUGINFO, 262 SYMTAB__FEDORA_DEBUGINFO,
262 SYMTAB__UBUNTU_DEBUGINFO, 263 SYMTAB__UBUNTU_DEBUGINFO,
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index abe0e8e95068..7eeebcee291c 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -65,7 +65,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
65 top->freq ? "Hz" : ""); 65 top->freq ? "Hz" : "");
66 } 66 }
67 67
68 ret += SNPRINTF(bf + ret, size - ret, "%s", event_name(top->sym_evsel)); 68 ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
69 69
70 ret += SNPRINTF(bf + ret, size - ret, "], "); 70 ret += SNPRINTF(bf + ret, size - ret, "], ");
71 71
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 5dd3b5ec8411..0715c843c2e7 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -32,29 +32,25 @@ int header_page_size_size;
32int header_page_ts_size; 32int header_page_ts_size;
33int header_page_data_offset; 33int header_page_data_offset;
34 34
35struct pevent *perf_pevent;
36static struct pevent *pevent;
37
38bool latency_format; 35bool latency_format;
39 36
40int read_trace_init(int file_bigendian, int host_bigendian) 37struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
41{ 38{
42 if (pevent) 39 struct pevent *pevent = pevent_alloc();
43 return 0;
44
45 perf_pevent = pevent_alloc();
46 pevent = perf_pevent;
47 40
48 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 41 if (pevent != NULL) {
49 pevent_set_file_bigendian(pevent, file_bigendian); 42 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
50 pevent_set_host_bigendian(pevent, host_bigendian); 43 pevent_set_file_bigendian(pevent, file_bigendian);
44 pevent_set_host_bigendian(pevent, host_bigendian);
45 }
51 46
52 return 0; 47 return pevent;
53} 48}
54 49
55static int get_common_field(struct scripting_context *context, 50static int get_common_field(struct scripting_context *context,
56 int *offset, int *size, const char *type) 51 int *offset, int *size, const char *type)
57{ 52{
53 struct pevent *pevent = context->pevent;
58 struct event_format *event; 54 struct event_format *event;
59 struct format_field *field; 55 struct format_field *field;
60 56
@@ -150,7 +146,7 @@ void *raw_field_ptr(struct event_format *event, const char *name, void *data)
150 return data + field->offset; 146 return data + field->offset;
151} 147}
152 148
153int trace_parse_common_type(void *data) 149int trace_parse_common_type(struct pevent *pevent, void *data)
154{ 150{
155 struct pevent_record record; 151 struct pevent_record record;
156 152
@@ -158,7 +154,7 @@ int trace_parse_common_type(void *data)
158 return pevent_data_type(pevent, &record); 154 return pevent_data_type(pevent, &record);
159} 155}
160 156
161int trace_parse_common_pid(void *data) 157int trace_parse_common_pid(struct pevent *pevent, void *data)
162{ 158{
163 struct pevent_record record; 159 struct pevent_record record;
164 160
@@ -166,27 +162,21 @@ int trace_parse_common_pid(void *data)
166 return pevent_data_pid(pevent, &record); 162 return pevent_data_pid(pevent, &record);
167} 163}
168 164
169unsigned long long read_size(void *ptr, int size) 165unsigned long long read_size(struct pevent *pevent, void *ptr, int size)
170{ 166{
171 return pevent_read_number(pevent, ptr, size); 167 return pevent_read_number(pevent, ptr, size);
172} 168}
173 169
174struct event_format *trace_find_event(int type) 170void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
175{
176 return pevent_find_event(pevent, type);
177}
178
179
180void print_trace_event(int cpu, void *data, int size)
181{ 171{
182 struct event_format *event; 172 struct event_format *event;
183 struct pevent_record record; 173 struct pevent_record record;
184 struct trace_seq s; 174 struct trace_seq s;
185 int type; 175 int type;
186 176
187 type = trace_parse_common_type(data); 177 type = trace_parse_common_type(pevent, data);
188 178
189 event = trace_find_event(type); 179 event = pevent_find_event(pevent, type);
190 if (!event) { 180 if (!event) {
191 warning("ug! no event found for type %d", type); 181 warning("ug! no event found for type %d", type);
192 return; 182 return;
@@ -202,8 +192,8 @@ void print_trace_event(int cpu, void *data, int size)
202 trace_seq_do_printf(&s); 192 trace_seq_do_printf(&s);
203} 193}
204 194
205void print_event(int cpu, void *data, int size, unsigned long long nsecs, 195void print_event(struct pevent *pevent, int cpu, void *data, int size,
206 char *comm) 196 unsigned long long nsecs, char *comm)
207{ 197{
208 struct pevent_record record; 198 struct pevent_record record;
209 struct trace_seq s; 199 struct trace_seq s;
@@ -226,7 +216,8 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
226 printf("\n"); 216 printf("\n");
227} 217}
228 218
229void parse_proc_kallsyms(char *file, unsigned int size __unused) 219void parse_proc_kallsyms(struct pevent *pevent,
220 char *file, unsigned int size __unused)
230{ 221{
231 unsigned long long addr; 222 unsigned long long addr;
232 char *func; 223 char *func;
@@ -257,7 +248,8 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
257 } 248 }
258} 249}
259 250
260void parse_ftrace_printk(char *file, unsigned int size __unused) 251void parse_ftrace_printk(struct pevent *pevent,
252 char *file, unsigned int size __unused)
261{ 253{
262 unsigned long long addr; 254 unsigned long long addr;
263 char *printk; 255 char *printk;
@@ -281,17 +273,19 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
281 } 273 }
282} 274}
283 275
284int parse_ftrace_file(char *buf, unsigned long size) 276int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
285{ 277{
286 return pevent_parse_event(pevent, buf, size, "ftrace"); 278 return pevent_parse_event(pevent, buf, size, "ftrace");
287} 279}
288 280
289int parse_event_file(char *buf, unsigned long size, char *sys) 281int parse_event_file(struct pevent *pevent,
282 char *buf, unsigned long size, char *sys)
290{ 283{
291 return pevent_parse_event(pevent, buf, size, sys); 284 return pevent_parse_event(pevent, buf, size, sys);
292} 285}
293 286
294struct event_format *trace_find_next_event(struct event_format *event) 287struct event_format *trace_find_next_event(struct pevent *pevent,
288 struct event_format *event)
295{ 289{
296 static int idx; 290 static int idx;
297 291
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f097e0dd6c5c..719ed74a8565 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -114,20 +114,20 @@ static void skip(int size)
114 }; 114 };
115} 115}
116 116
117static unsigned int read4(void) 117static unsigned int read4(struct pevent *pevent)
118{ 118{
119 unsigned int data; 119 unsigned int data;
120 120
121 read_or_die(&data, 4); 121 read_or_die(&data, 4);
122 return __data2host4(perf_pevent, data); 122 return __data2host4(pevent, data);
123} 123}
124 124
125static unsigned long long read8(void) 125static unsigned long long read8(struct pevent *pevent)
126{ 126{
127 unsigned long long data; 127 unsigned long long data;
128 128
129 read_or_die(&data, 8); 129 read_or_die(&data, 8);
130 return __data2host8(perf_pevent, data); 130 return __data2host8(pevent, data);
131} 131}
132 132
133static char *read_string(void) 133static char *read_string(void)
@@ -168,12 +168,12 @@ static char *read_string(void)
168 return str; 168 return str;
169} 169}
170 170
171static void read_proc_kallsyms(void) 171static void read_proc_kallsyms(struct pevent *pevent)
172{ 172{
173 unsigned int size; 173 unsigned int size;
174 char *buf; 174 char *buf;
175 175
176 size = read4(); 176 size = read4(pevent);
177 if (!size) 177 if (!size)
178 return; 178 return;
179 179
@@ -181,29 +181,29 @@ static void read_proc_kallsyms(void)
181 read_or_die(buf, size); 181 read_or_die(buf, size);
182 buf[size] = '\0'; 182 buf[size] = '\0';
183 183
184 parse_proc_kallsyms(buf, size); 184 parse_proc_kallsyms(pevent, buf, size);
185 185
186 free(buf); 186 free(buf);
187} 187}
188 188
189static void read_ftrace_printk(void) 189static void read_ftrace_printk(struct pevent *pevent)
190{ 190{
191 unsigned int size; 191 unsigned int size;
192 char *buf; 192 char *buf;
193 193
194 size = read4(); 194 size = read4(pevent);
195 if (!size) 195 if (!size)
196 return; 196 return;
197 197
198 buf = malloc_or_die(size); 198 buf = malloc_or_die(size);
199 read_or_die(buf, size); 199 read_or_die(buf, size);
200 200
201 parse_ftrace_printk(buf, size); 201 parse_ftrace_printk(pevent, buf, size);
202 202
203 free(buf); 203 free(buf);
204} 204}
205 205
206static void read_header_files(void) 206static void read_header_files(struct pevent *pevent)
207{ 207{
208 unsigned long long size; 208 unsigned long long size;
209 char *header_event; 209 char *header_event;
@@ -214,7 +214,7 @@ static void read_header_files(void)
214 if (memcmp(buf, "header_page", 12) != 0) 214 if (memcmp(buf, "header_page", 12) != 0)
215 die("did not read header page"); 215 die("did not read header page");
216 216
217 size = read8(); 217 size = read8(pevent);
218 skip(size); 218 skip(size);
219 219
220 /* 220 /*
@@ -227,47 +227,48 @@ static void read_header_files(void)
227 if (memcmp(buf, "header_event", 13) != 0) 227 if (memcmp(buf, "header_event", 13) != 0)
228 die("did not read header event"); 228 die("did not read header event");
229 229
230 size = read8(); 230 size = read8(pevent);
231 header_event = malloc_or_die(size); 231 header_event = malloc_or_die(size);
232 read_or_die(header_event, size); 232 read_or_die(header_event, size);
233 free(header_event); 233 free(header_event);
234} 234}
235 235
236static void read_ftrace_file(unsigned long long size) 236static void read_ftrace_file(struct pevent *pevent, unsigned long long size)
237{ 237{
238 char *buf; 238 char *buf;
239 239
240 buf = malloc_or_die(size); 240 buf = malloc_or_die(size);
241 read_or_die(buf, size); 241 read_or_die(buf, size);
242 parse_ftrace_file(buf, size); 242 parse_ftrace_file(pevent, buf, size);
243 free(buf); 243 free(buf);
244} 244}
245 245
246static void read_event_file(char *sys, unsigned long long size) 246static void read_event_file(struct pevent *pevent, char *sys,
247 unsigned long long size)
247{ 248{
248 char *buf; 249 char *buf;
249 250
250 buf = malloc_or_die(size); 251 buf = malloc_or_die(size);
251 read_or_die(buf, size); 252 read_or_die(buf, size);
252 parse_event_file(buf, size, sys); 253 parse_event_file(pevent, buf, size, sys);
253 free(buf); 254 free(buf);
254} 255}
255 256
256static void read_ftrace_files(void) 257static void read_ftrace_files(struct pevent *pevent)
257{ 258{
258 unsigned long long size; 259 unsigned long long size;
259 int count; 260 int count;
260 int i; 261 int i;
261 262
262 count = read4(); 263 count = read4(pevent);
263 264
264 for (i = 0; i < count; i++) { 265 for (i = 0; i < count; i++) {
265 size = read8(); 266 size = read8(pevent);
266 read_ftrace_file(size); 267 read_ftrace_file(pevent, size);
267 } 268 }
268} 269}
269 270
270static void read_event_files(void) 271static void read_event_files(struct pevent *pevent)
271{ 272{
272 unsigned long long size; 273 unsigned long long size;
273 char *sys; 274 char *sys;
@@ -275,15 +276,15 @@ static void read_event_files(void)
275 int count; 276 int count;
276 int i,x; 277 int i,x;
277 278
278 systems = read4(); 279 systems = read4(pevent);
279 280
280 for (i = 0; i < systems; i++) { 281 for (i = 0; i < systems; i++) {
281 sys = read_string(); 282 sys = read_string();
282 283
283 count = read4(); 284 count = read4(pevent);
284 for (x=0; x < count; x++) { 285 for (x=0; x < count; x++) {
285 size = read8(); 286 size = read8(pevent);
286 read_event_file(sys, size); 287 read_event_file(pevent, sys, size);
287 } 288 }
288 } 289 }
289} 290}
@@ -377,7 +378,7 @@ static int calc_index(void *ptr, int cpu)
377 return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page; 378 return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
378} 379}
379 380
380struct pevent_record *trace_peek_data(int cpu) 381struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu)
381{ 382{
382 struct pevent_record *data; 383 struct pevent_record *data;
383 void *page = cpu_data[cpu].page; 384 void *page = cpu_data[cpu].page;
@@ -399,15 +400,15 @@ struct pevent_record *trace_peek_data(int cpu)
399 /* FIXME: handle header page */ 400 /* FIXME: handle header page */
400 if (header_page_ts_size != 8) 401 if (header_page_ts_size != 8)
401 die("expected a long long type for timestamp"); 402 die("expected a long long type for timestamp");
402 cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr); 403 cpu_data[cpu].timestamp = data2host8(pevent, ptr);
403 ptr += 8; 404 ptr += 8;
404 switch (header_page_size_size) { 405 switch (header_page_size_size) {
405 case 4: 406 case 4:
406 cpu_data[cpu].page_size = data2host4(perf_pevent, ptr); 407 cpu_data[cpu].page_size = data2host4(pevent, ptr);
407 ptr += 4; 408 ptr += 4;
408 break; 409 break;
409 case 8: 410 case 8:
410 cpu_data[cpu].page_size = data2host8(perf_pevent, ptr); 411 cpu_data[cpu].page_size = data2host8(pevent, ptr);
411 ptr += 8; 412 ptr += 8;
412 break; 413 break;
413 default: 414 default:
@@ -421,10 +422,10 @@ read_again:
421 422
422 if (idx >= cpu_data[cpu].page_size) { 423 if (idx >= cpu_data[cpu].page_size) {
423 get_next_page(cpu); 424 get_next_page(cpu);
424 return trace_peek_data(cpu); 425 return trace_peek_data(pevent, cpu);
425 } 426 }
426 427
427 type_len_ts = data2host4(perf_pevent, ptr); 428 type_len_ts = data2host4(pevent, ptr);
428 ptr += 4; 429 ptr += 4;
429 430
430 type_len = type_len4host(type_len_ts); 431 type_len = type_len4host(type_len_ts);
@@ -434,14 +435,14 @@ read_again:
434 case RINGBUF_TYPE_PADDING: 435 case RINGBUF_TYPE_PADDING:
435 if (!delta) 436 if (!delta)
436 die("error, hit unexpected end of page"); 437 die("error, hit unexpected end of page");
437 length = data2host4(perf_pevent, ptr); 438 length = data2host4(pevent, ptr);
438 ptr += 4; 439 ptr += 4;
439 length *= 4; 440 length *= 4;
440 ptr += length; 441 ptr += length;
441 goto read_again; 442 goto read_again;
442 443
443 case RINGBUF_TYPE_TIME_EXTEND: 444 case RINGBUF_TYPE_TIME_EXTEND:
444 extend = data2host4(perf_pevent, ptr); 445 extend = data2host4(pevent, ptr);
445 ptr += 4; 446 ptr += 4;
446 extend <<= TS_SHIFT; 447 extend <<= TS_SHIFT;
447 extend += delta; 448 extend += delta;
@@ -452,7 +453,7 @@ read_again:
452 ptr += 12; 453 ptr += 12;
453 break; 454 break;
454 case 0: 455 case 0:
455 length = data2host4(perf_pevent, ptr); 456 length = data2host4(pevent, ptr);
456 ptr += 4; 457 ptr += 4;
457 die("here! length=%d", length); 458 die("here! length=%d", length);
458 break; 459 break;
@@ -477,17 +478,17 @@ read_again:
477 return data; 478 return data;
478} 479}
479 480
480struct pevent_record *trace_read_data(int cpu) 481struct pevent_record *trace_read_data(struct pevent *pevent, int cpu)
481{ 482{
482 struct pevent_record *data; 483 struct pevent_record *data;
483 484
484 data = trace_peek_data(cpu); 485 data = trace_peek_data(pevent, cpu);
485 cpu_data[cpu].next = NULL; 486 cpu_data[cpu].next = NULL;
486 487
487 return data; 488 return data;
488} 489}
489 490
490ssize_t trace_report(int fd, bool __repipe) 491ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
491{ 492{
492 char buf[BUFSIZ]; 493 char buf[BUFSIZ];
493 char test[] = { 23, 8, 68 }; 494 char test[] = { 23, 8, 68 };
@@ -519,30 +520,32 @@ ssize_t trace_report(int fd, bool __repipe)
519 file_bigendian = buf[0]; 520 file_bigendian = buf[0];
520 host_bigendian = bigendian(); 521 host_bigendian = bigendian();
521 522
522 read_trace_init(file_bigendian, host_bigendian); 523 *ppevent = read_trace_init(file_bigendian, host_bigendian);
524 if (*ppevent == NULL)
525 die("read_trace_init failed");
523 526
524 read_or_die(buf, 1); 527 read_or_die(buf, 1);
525 long_size = buf[0]; 528 long_size = buf[0];
526 529
527 page_size = read4(); 530 page_size = read4(*ppevent);
528 531
529 read_header_files(); 532 read_header_files(*ppevent);
530 533
531 read_ftrace_files(); 534 read_ftrace_files(*ppevent);
532 read_event_files(); 535 read_event_files(*ppevent);
533 read_proc_kallsyms(); 536 read_proc_kallsyms(*ppevent);
534 read_ftrace_printk(); 537 read_ftrace_printk(*ppevent);
535 538
536 size = calc_data_size - 1; 539 size = calc_data_size - 1;
537 calc_data_size = 0; 540 calc_data_size = 0;
538 repipe = false; 541 repipe = false;
539 542
540 if (show_funcs) { 543 if (show_funcs) {
541 pevent_print_funcs(perf_pevent); 544 pevent_print_funcs(*ppevent);
542 return size; 545 return size;
543 } 546 }
544 if (show_printk) { 547 if (show_printk) {
545 pevent_print_printk(perf_pevent); 548 pevent_print_printk(*ppevent);
546 return size; 549 return size;
547 } 550 }
548 551
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 18ae6c1831d3..474aa7a7df43 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -36,6 +36,7 @@ static int stop_script_unsupported(void)
36} 36}
37 37
38static void process_event_unsupported(union perf_event *event __unused, 38static void process_event_unsupported(union perf_event *event __unused,
39 struct pevent *pevent __unused,
39 struct perf_sample *sample __unused, 40 struct perf_sample *sample __unused,
40 struct perf_evsel *evsel __unused, 41 struct perf_evsel *evsel __unused,
41 struct machine *machine __unused, 42 struct machine *machine __unused,
@@ -61,7 +62,8 @@ static int python_start_script_unsupported(const char *script __unused,
61 return -1; 62 return -1;
62} 63}
63 64
64static int python_generate_script_unsupported(const char *outfile __unused) 65static int python_generate_script_unsupported(struct pevent *pevent __unused,
66 const char *outfile __unused)
65{ 67{
66 print_python_unsupported_msg(); 68 print_python_unsupported_msg();
67 69
@@ -122,7 +124,8 @@ static int perl_start_script_unsupported(const char *script __unused,
122 return -1; 124 return -1;
123} 125}
124 126
125static int perl_generate_script_unsupported(const char *outfile __unused) 127static int perl_generate_script_unsupported(struct pevent *pevent __unused,
128 const char *outfile __unused)
126{ 129{
127 print_perl_unsupported_msg(); 130 print_perl_unsupported_msg();
128 131
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 639852ac1117..8fef1d6687b7 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -8,6 +8,7 @@
8struct machine; 8struct machine;
9struct perf_sample; 9struct perf_sample;
10union perf_event; 10union perf_event;
11struct perf_tool;
11struct thread; 12struct thread;
12 13
13extern int header_page_size_size; 14extern int header_page_size_size;
@@ -29,35 +30,36 @@ enum {
29 30
30int bigendian(void); 31int bigendian(void);
31 32
32int read_trace_init(int file_bigendian, int host_bigendian); 33struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
33void print_trace_event(int cpu, void *data, int size); 34void print_trace_event(struct pevent *pevent, int cpu, void *data, int size);
34 35
35void print_event(int cpu, void *data, int size, unsigned long long nsecs, 36void print_event(struct pevent *pevent, int cpu, void *data, int size,
36 char *comm); 37 unsigned long long nsecs, char *comm);
37 38
38int parse_ftrace_file(char *buf, unsigned long size); 39int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
39int parse_event_file(char *buf, unsigned long size, char *sys); 40int parse_event_file(struct pevent *pevent,
41 char *buf, unsigned long size, char *sys);
40 42
41struct pevent_record *trace_peek_data(int cpu); 43struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
42struct event_format *trace_find_event(int type);
43 44
44unsigned long long 45unsigned long long
45raw_field_value(struct event_format *event, const char *name, void *data); 46raw_field_value(struct event_format *event, const char *name, void *data);
46void *raw_field_ptr(struct event_format *event, const char *name, void *data); 47void *raw_field_ptr(struct event_format *event, const char *name, void *data);
47 48
48void parse_proc_kallsyms(char *file, unsigned int size __unused); 49void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
49void parse_ftrace_printk(char *file, unsigned int size __unused); 50void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
50 51
51ssize_t trace_report(int fd, bool repipe); 52ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
52 53
53int trace_parse_common_type(void *data); 54int trace_parse_common_type(struct pevent *pevent, void *data);
54int trace_parse_common_pid(void *data); 55int trace_parse_common_pid(struct pevent *pevent, void *data);
55 56
56struct event_format *trace_find_next_event(struct event_format *event); 57struct event_format *trace_find_next_event(struct pevent *pevent,
57unsigned long long read_size(void *ptr, int size); 58 struct event_format *event);
59unsigned long long read_size(struct pevent *pevent, void *ptr, int size);
58unsigned long long eval_flag(const char *flag); 60unsigned long long eval_flag(const char *flag);
59 61
60struct pevent_record *trace_read_data(int cpu); 62struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
61int read_tracing_data(int fd, struct list_head *pattrs); 63int read_tracing_data(int fd, struct list_head *pattrs);
62 64
63struct tracing_data { 65struct tracing_data {
@@ -77,11 +79,12 @@ struct scripting_ops {
77 int (*start_script) (const char *script, int argc, const char **argv); 79 int (*start_script) (const char *script, int argc, const char **argv);
78 int (*stop_script) (void); 80 int (*stop_script) (void);
79 void (*process_event) (union perf_event *event, 81 void (*process_event) (union perf_event *event,
82 struct pevent *pevent,
80 struct perf_sample *sample, 83 struct perf_sample *sample,
81 struct perf_evsel *evsel, 84 struct perf_evsel *evsel,
82 struct machine *machine, 85 struct machine *machine,
83 struct thread *thread); 86 struct thread *thread);
84 int (*generate_script) (const char *outfile); 87 int (*generate_script) (struct pevent *pevent, const char *outfile);
85}; 88};
86 89
87int script_spec_register(const char *spec, struct scripting_ops *ops); 90int script_spec_register(const char *spec, struct scripting_ops *ops);
@@ -90,6 +93,7 @@ void setup_perl_scripting(void);
90void setup_python_scripting(void); 93void setup_python_scripting(void);
91 94
92struct scripting_context { 95struct scripting_context {
96 struct pevent *pevent;
93 void *event_data; 97 void *event_data;
94}; 98};
95 99
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2daaedb83d84..b13c7331eaf8 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -264,4 +264,6 @@ bool is_power_of_2(unsigned long n)
264 264
265size_t hex_width(u64 v); 265size_t hex_width(u64 v);
266 266
267char *rtrim(char *s);
268
267#endif 269#endif
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index 82d7c590c026..b0adb2710c02 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -425,7 +425,7 @@ int main (int argc, char **argv)
425 /* for easy use when hotplugging */ 425 /* for easy use when hotplugging */
426 device = getenv ("DEVICE"); 426 device = getenv ("DEVICE");
427 427
428 while ((c = getopt (argc, argv, "D:aA:c:g:hns:t:v:")) != EOF) 428 while ((c = getopt (argc, argv, "D:aA:c:g:hlns:t:v:")) != EOF)
429 switch (c) { 429 switch (c) {
430 case 'D': /* device, if only one */ 430 case 'D': /* device, if only one */
431 device = optarg; 431 device = optarg;
@@ -468,10 +468,21 @@ int main (int argc, char **argv)
468 case 'h': 468 case 'h':
469 default: 469 default:
470usage: 470usage:
471 fprintf (stderr, "usage: %s [-n] [-D dev | -a | -A usbfs-dir]\n" 471 fprintf (stderr,
472 "\t[-c iterations] [-t testnum]\n" 472 "usage: %s [options]\n"
473 "\t[-s packetsize] [-g sglen] [-v vary]\n", 473 "Options:\n"
474 argv [0]); 474 "\t-D dev only test specific device\n"
475 "\t-A usbfs-dir\n"
476 "\t-a test all recognized devices\n"
477 "\t-l loop forever(for stress test)\n"
478 "\t-t testnum only run specified case\n"
479 "\t-n no test running, show devices to be tested\n"
480 "Case arguments:\n"
481 "\t-c iterations default 1000\n"
482 "\t-s packetsize default 512\n"
483 "\t-g sglen default 32\n"
484 "\t-v vary default 512\n",
485 argv[0]);
475 return 1; 486 return 1;
476 } 487 }
477 if (optind != argc) 488 if (optind != argc)