aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/perf_event.c60
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/builtin-record.c144
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/builtin-trace.c75
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm6
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-record2
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-report8
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-record3
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-report8
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-report2
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-record2
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-report23
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-record2
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-report2
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-record2
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-report2
-rw-r--r--tools/perf/scripts/perl/rwtop.pl177
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py3
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-report8
-rw-r--r--tools/perf/scripts/python/bin/sctop-record2
-rw-r--r--tools/perf/scripts/python/bin/sctop-report24
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-report8
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-report8
-rw-r--r--tools/perf/scripts/python/sctop.py78
-rw-r--r--tools/perf/util/event.h35
-rw-r--r--tools/perf/util/header.c361
-rw-r--r--tools/perf/util/header.h38
-rw-r--r--tools/perf/util/parse-events.c16
-rw-r--r--tools/perf/util/session.c192
-rw-r--r--tools/perf/util/session.h10
-rw-r--r--tools/perf/util/trace-event-info.c24
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/trace-event-read.c89
-rw-r--r--tools/perf/util/trace-event.h4
39 files changed, 1270 insertions, 178 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 095101d685bc..07b7a435bf03 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -4313,36 +4313,6 @@ static const struct pmu perf_ops_task_clock = {
4313 .read = task_clock_perf_event_read, 4313 .read = task_clock_perf_event_read,
4314}; 4314};
4315 4315
4316#ifdef CONFIG_EVENT_TRACING
4317
4318void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4319 int entry_size, struct pt_regs *regs)
4320{
4321 struct perf_sample_data data;
4322 struct perf_raw_record raw = {
4323 .size = entry_size,
4324 .data = record,
4325 };
4326
4327 perf_sample_data_init(&data, addr);
4328 data.raw = &raw;
4329
4330 /* Trace events already protected against recursion */
4331 do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
4332 &data, regs);
4333}
4334EXPORT_SYMBOL_GPL(perf_tp_event);
4335
4336static int perf_tp_event_match(struct perf_event *event,
4337 struct perf_sample_data *data)
4338{
4339 void *record = data->raw->data;
4340
4341 if (likely(!event->filter) || filter_match_preds(event->filter, record))
4342 return 1;
4343 return 0;
4344}
4345
4346static void swevent_hlist_release_rcu(struct rcu_head *rcu_head) 4316static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
4347{ 4317{
4348 struct swevent_hlist *hlist; 4318 struct swevent_hlist *hlist;
@@ -4442,6 +4412,36 @@ static int swevent_hlist_get(struct perf_event *event)
4442 return err; 4412 return err;
4443} 4413}
4444 4414
4415#ifdef CONFIG_EVENT_TRACING
4416
4417void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4418 int entry_size, struct pt_regs *regs)
4419{
4420 struct perf_sample_data data;
4421 struct perf_raw_record raw = {
4422 .size = entry_size,
4423 .data = record,
4424 };
4425
4426 perf_sample_data_init(&data, addr);
4427 data.raw = &raw;
4428
4429 /* Trace events already protected against recursion */
4430 do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
4431 &data, regs);
4432}
4433EXPORT_SYMBOL_GPL(perf_tp_event);
4434
4435static int perf_tp_event_match(struct perf_event *event,
4436 struct perf_sample_data *data)
4437{
4438 void *record = data->raw->data;
4439
4440 if (likely(!event->filter) || filter_match_preds(event->filter, record))
4441 return 1;
4442 return 0;
4443}
4444
4445static void tp_perf_event_destroy(struct perf_event *event) 4445static void tp_perf_event_destroy(struct perf_event *event)
4446{ 4446{
4447 perf_trace_disable(event->attr.config); 4447 perf_trace_disable(event->attr.config);
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index fc46c0b40f6e..020d871c7934 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -58,7 +58,7 @@ OPTIONS
58 58
59-f:: 59-f::
60--force:: 60--force::
61 Overwrite existing data file. 61 Overwrite existing data file. (deprecated)
62 62
63-c:: 63-c::
64--count=:: 64--count=::
@@ -101,7 +101,7 @@ OPTIONS
101 101
102-R:: 102-R::
103--raw-samples:: 103--raw-samples::
104Collect raw sample records from all opened counters (typically for tracepoint counters). 104Collect raw sample records from all opened counters (default for tracepoint counters).
105 105
106SEE ALSO 106SEE ALSO
107-------- 107--------
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9a9513687235..a1b99eeac3c0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -26,15 +26,23 @@
26#include <unistd.h> 26#include <unistd.h>
27#include <sched.h> 27#include <sched.h>
28 28
29enum write_mode_t {
30 WRITE_FORCE,
31 WRITE_APPEND
32};
33
29static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; 34static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
30 35
36static unsigned int user_interval = UINT_MAX;
31static long default_interval = 0; 37static long default_interval = 0;
32 38
33static int nr_cpus = 0; 39static int nr_cpus = 0;
34static unsigned int page_size; 40static unsigned int page_size;
35static unsigned int mmap_pages = 128; 41static unsigned int mmap_pages = 128;
42static unsigned int user_freq = UINT_MAX;
36static int freq = 1000; 43static int freq = 1000;
37static int output; 44static int output;
45static int pipe_output = 0;
38static const char *output_name = "perf.data"; 46static const char *output_name = "perf.data";
39static int group = 0; 47static int group = 0;
40static unsigned int realtime_prio = 0; 48static unsigned int realtime_prio = 0;
@@ -47,8 +55,7 @@ static pid_t *all_tids = NULL;
47static int thread_num = 0; 55static int thread_num = 0;
48static pid_t child_pid = -1; 56static pid_t child_pid = -1;
49static bool inherit = true; 57static bool inherit = true;
50static bool force = false; 58static enum write_mode_t write_mode = WRITE_FORCE;
51static bool append_file = false;
52static bool call_graph = false; 59static bool call_graph = false;
53static bool inherit_stat = false; 60static bool inherit_stat = false;
54static bool no_samples = false; 61static bool no_samples = false;
@@ -103,6 +110,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
103 pc->data_tail = tail; 110 pc->data_tail = tail;
104} 111}
105 112
113static void advance_output(size_t size)
114{
115 bytes_written += size;
116}
117
106static void write_output(void *buf, size_t size) 118static void write_output(void *buf, size_t size)
107{ 119{
108 while (size) { 120 while (size) {
@@ -251,10 +263,19 @@ static void create_counter(int counter, int cpu)
251 if (nr_counters > 1) 263 if (nr_counters > 1)
252 attr->sample_type |= PERF_SAMPLE_ID; 264 attr->sample_type |= PERF_SAMPLE_ID;
253 265
254 if (freq) { 266 /*
255 attr->sample_type |= PERF_SAMPLE_PERIOD; 267 * We default some events to a 1 default interval. But keep
256 attr->freq = 1; 268 * it a weak assumption overridable by the user.
257 attr->sample_freq = freq; 269 */
270 if (!attr->sample_period || (user_freq != UINT_MAX &&
271 user_interval != UINT_MAX)) {
272 if (freq) {
273 attr->sample_type |= PERF_SAMPLE_PERIOD;
274 attr->freq = 1;
275 attr->sample_freq = freq;
276 } else {
277 attr->sample_period = default_interval;
278 }
258 } 279 }
259 280
260 if (no_samples) 281 if (no_samples)
@@ -420,10 +441,19 @@ static int process_buildids(void)
420 441
421static void atexit_header(void) 442static void atexit_header(void)
422{ 443{
423 session->header.data_size += bytes_written; 444 if (!pipe_output) {
445 session->header.data_size += bytes_written;
446
447 process_buildids();
448 perf_header__write(&session->header, output, true);
449 } else {
450 int err;
424 451
425 process_buildids(); 452 err = event__synthesize_build_ids(process_synthesized_event,
426 perf_header__write(&session->header, output, true); 453 session);
454 if (err < 0)
455 pr_err("Couldn't synthesize build ids.\n");
456 }
427} 457}
428 458
429static int __cmd_record(int argc, const char **argv) 459static int __cmd_record(int argc, const char **argv)
@@ -449,45 +479,44 @@ static int __cmd_record(int argc, const char **argv)
449 exit(-1); 479 exit(-1);
450 } 480 }
451 481
452 if (!stat(output_name, &st) && st.st_size) { 482 if (!strcmp(output_name, "-"))
453 if (!force) { 483 pipe_output = 1;
454 if (!append_file) { 484 else if (!stat(output_name, &st) && st.st_size) {
455 pr_err("Error, output file %s exists, use -A " 485 if (write_mode == WRITE_FORCE) {
456 "to append or -f to overwrite.\n",
457 output_name);
458 exit(-1);
459 }
460 } else {
461 char oldname[PATH_MAX]; 486 char oldname[PATH_MAX];
462 snprintf(oldname, sizeof(oldname), "%s.old", 487 snprintf(oldname, sizeof(oldname), "%s.old",
463 output_name); 488 output_name);
464 unlink(oldname); 489 unlink(oldname);
465 rename(output_name, oldname); 490 rename(output_name, oldname);
466 } 491 }
467 } else { 492 } else if (write_mode == WRITE_APPEND) {
468 append_file = false; 493 write_mode = WRITE_FORCE;
469 } 494 }
470 495
471 flags = O_CREAT|O_RDWR; 496 flags = O_CREAT|O_RDWR;
472 if (append_file) 497 if (write_mode == WRITE_APPEND)
473 file_new = 0; 498 file_new = 0;
474 else 499 else
475 flags |= O_TRUNC; 500 flags |= O_TRUNC;
476 501
477 output = open(output_name, flags, S_IRUSR|S_IWUSR); 502 if (pipe_output)
503 output = STDOUT_FILENO;
504 else
505 output = open(output_name, flags, S_IRUSR | S_IWUSR);
478 if (output < 0) { 506 if (output < 0) {
479 perror("failed to create output file"); 507 perror("failed to create output file");
480 exit(-1); 508 exit(-1);
481 } 509 }
482 510
483 session = perf_session__new(output_name, O_WRONLY, force); 511 session = perf_session__new(output_name, O_WRONLY,
512 write_mode == WRITE_FORCE);
484 if (session == NULL) { 513 if (session == NULL) {
485 pr_err("Not enough memory for reading perf file header\n"); 514 pr_err("Not enough memory for reading perf file header\n");
486 return -1; 515 return -1;
487 } 516 }
488 517
489 if (!file_new) { 518 if (!file_new) {
490 err = perf_header__read(&session->header, output); 519 err = perf_header__read(session, output);
491 if (err < 0) 520 if (err < 0)
492 return err; 521 return err;
493 } 522 }
@@ -513,6 +542,8 @@ static int __cmd_record(int argc, const char **argv)
513 } 542 }
514 543
515 if (!child_pid) { 544 if (!child_pid) {
545 if (pipe_output)
546 dup2(2, 1);
516 close(child_ready_pipe[0]); 547 close(child_ready_pipe[0]);
517 close(go_pipe[1]); 548 close(go_pipe[1]);
518 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 549 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
@@ -564,7 +595,11 @@ static int __cmd_record(int argc, const char **argv)
564 open_counters(cpumap[i]); 595 open_counters(cpumap[i]);
565 } 596 }
566 597
567 if (file_new) { 598 if (pipe_output) {
599 err = perf_header__write_pipe(output);
600 if (err < 0)
601 return err;
602 } else if (file_new) {
568 err = perf_header__write(&session->header, output, false); 603 err = perf_header__write(&session->header, output, false);
569 if (err < 0) 604 if (err < 0)
570 return err; 605 return err;
@@ -572,6 +607,34 @@ static int __cmd_record(int argc, const char **argv)
572 607
573 post_processing_offset = lseek(output, 0, SEEK_CUR); 608 post_processing_offset = lseek(output, 0, SEEK_CUR);
574 609
610 if (pipe_output) {
611 err = event__synthesize_attrs(&session->header,
612 process_synthesized_event,
613 session);
614 if (err < 0) {
615 pr_err("Couldn't synthesize attrs.\n");
616 return err;
617 }
618
619 err = event__synthesize_event_types(process_synthesized_event,
620 session);
621 if (err < 0) {
622 pr_err("Couldn't synthesize event_types.\n");
623 return err;
624 }
625
626 err = event__synthesize_tracing_data(output, attrs,
627 nr_counters,
628 process_synthesized_event,
629 session);
630 if (err <= 0) {
631 pr_err("Couldn't record tracing data.\n");
632 return err;
633 }
634
635 advance_output(err);
636 }
637
575 err = event__synthesize_kernel_mmap(process_synthesized_event, 638 err = event__synthesize_kernel_mmap(process_synthesized_event,
576 session, "_text"); 639 session, "_text");
577 if (err < 0) 640 if (err < 0)
@@ -667,6 +730,8 @@ static const char * const record_usage[] = {
667 NULL 730 NULL
668}; 731};
669 732
733static bool force, append_file;
734
670static const struct option options[] = { 735static const struct option options[] = {
671 OPT_CALLBACK('e', "event", NULL, "event", 736 OPT_CALLBACK('e', "event", NULL, "event",
672 "event selector. use 'perf list' to list available events", 737 "event selector. use 'perf list' to list available events",
@@ -688,14 +753,14 @@ static const struct option options[] = {
688 OPT_INTEGER('C', "profile_cpu", &profile_cpu, 753 OPT_INTEGER('C', "profile_cpu", &profile_cpu,
689 "CPU to profile on"), 754 "CPU to profile on"),
690 OPT_BOOLEAN('f', "force", &force, 755 OPT_BOOLEAN('f', "force", &force,
691 "overwrite existing data file"), 756 "overwrite existing data file (deprecated)"),
692 OPT_LONG('c', "count", &default_interval, 757 OPT_LONG('c', "count", &user_interval,
693 "event period to sample"), 758 "event period to sample"),
694 OPT_STRING('o', "output", &output_name, "file", 759 OPT_STRING('o', "output", &output_name, "file",
695 "output file name"), 760 "output file name"),
696 OPT_BOOLEAN('i', "inherit", &inherit, 761 OPT_BOOLEAN('i', "inherit", &inherit,
697 "child tasks inherit counters"), 762 "child tasks inherit counters"),
698 OPT_INTEGER('F', "freq", &freq, 763 OPT_INTEGER('F', "freq", &user_freq,
699 "profile at this frequency"), 764 "profile at this frequency"),
700 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 765 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
701 "number of mmap data pages"), 766 "number of mmap data pages"),
@@ -716,7 +781,6 @@ static const struct option options[] = {
716 781
717int cmd_record(int argc, const char **argv, const char *prefix __used) 782int cmd_record(int argc, const char **argv, const char *prefix __used)
718{ 783{
719 int counter;
720 int i,j; 784 int i,j;
721 785
722 argc = parse_options(argc, argv, options, record_usage, 786 argc = parse_options(argc, argv, options, record_usage,
@@ -725,6 +789,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
725 !system_wide && profile_cpu == -1) 789 !system_wide && profile_cpu == -1)
726 usage_with_options(record_usage, options); 790 usage_with_options(record_usage, options);
727 791
792 if (force && append_file) {
793 fprintf(stderr, "Can't overwrite and append at the same time."
794 " You need to choose between -f and -A");
795 usage_with_options(record_usage, options);
796 } else if (append_file) {
797 write_mode = WRITE_APPEND;
798 } else {
799 write_mode = WRITE_FORCE;
800 }
801
728 symbol__init(); 802 symbol__init();
729 803
730 if (!nr_counters) { 804 if (!nr_counters) {
@@ -764,6 +838,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
764 if (!event_array) 838 if (!event_array)
765 return -ENOMEM; 839 return -ENOMEM;
766 840
841 if (user_interval != UINT_MAX)
842 default_interval = user_interval;
843 if (user_freq != UINT_MAX)
844 freq = user_freq;
845
767 /* 846 /*
768 * User specified count overrides default frequency. 847 * User specified count overrides default frequency.
769 */ 848 */
@@ -776,12 +855,5 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
776 exit(EXIT_FAILURE); 855 exit(EXIT_FAILURE);
777 } 856 }
778 857
779 for (counter = 0; counter < nr_counters; counter++) {
780 if (attrs[counter].sample_period)
781 continue;
782
783 attrs[counter].sample_period = default_interval;
784 }
785
786 return __cmd_record(argc, argv); 858 return __cmd_record(argc, argv);
787} 859}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index daee082ab42b..7da5fb365264 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -267,8 +267,19 @@ static struct perf_event_ops event_ops = {
267 .fork = event__process_task, 267 .fork = event__process_task,
268 .lost = event__process_lost, 268 .lost = event__process_lost,
269 .read = process_read_event, 269 .read = process_read_event,
270 .attr = event__process_attr,
271 .event_type = event__process_event_type,
272 .tracing_data = event__process_tracing_data,
273 .build_id = event__process_build_id,
270}; 274};
271 275
276extern volatile int session_done;
277
278static void sig_handler(int sig __attribute__((__unused__)))
279{
280 session_done = 1;
281}
282
272static int __cmd_report(void) 283static int __cmd_report(void)
273{ 284{
274 int ret = -EINVAL; 285 int ret = -EINVAL;
@@ -276,6 +287,8 @@ static int __cmd_report(void)
276 struct rb_node *next; 287 struct rb_node *next;
277 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 288 const char *help = "For a higher level overview, try: perf report --sort comm,dso";
278 289
290 signal(SIGINT, sig_handler);
291
279 session = perf_session__new(input_name, O_RDONLY, force); 292 session = perf_session__new(input_name, O_RDONLY, force);
280 if (session == NULL) 293 if (session == NULL)
281 return -ENOMEM; 294 return -ENOMEM;
@@ -465,7 +478,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
465{ 478{
466 argc = parse_options(argc, argv, options, report_usage, 0); 479 argc = parse_options(argc, argv, options, report_usage, 0);
467 480
468 setup_browser(); 481 if (strcmp(input_name, "-") != 0)
482 setup_browser();
469 483
470 if (symbol__init() < 0) 484 if (symbol__init() < 0)
471 return -1; 485 return -1;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8fc50d831540..2eefb33c9679 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -104,10 +104,23 @@ static int process_sample_event(event_t *event, struct perf_session *session)
104static struct perf_event_ops event_ops = { 104static struct perf_event_ops event_ops = {
105 .sample = process_sample_event, 105 .sample = process_sample_event,
106 .comm = event__process_comm, 106 .comm = event__process_comm,
107 .attr = event__process_attr,
108 .event_type = event__process_event_type,
109 .tracing_data = event__process_tracing_data,
110 .build_id = event__process_build_id,
107}; 111};
108 112
113extern volatile int session_done;
114
115static void sig_handler(int sig __unused)
116{
117 session_done = 1;
118}
119
109static int __cmd_trace(struct perf_session *session) 120static int __cmd_trace(struct perf_session *session)
110{ 121{
122 signal(SIGINT, sig_handler);
123
111 return perf_session__process_events(session, &event_ops); 124 return perf_session__process_events(session, &event_ops);
112} 125}
113 126
@@ -548,6 +561,65 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
548 suffix = REPORT_SUFFIX; 561 suffix = REPORT_SUFFIX;
549 } 562 }
550 563
564 if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) {
565 char *record_script_path, *report_script_path;
566 int live_pipe[2];
567 pid_t pid;
568
569 record_script_path = get_script_path(argv[1], RECORD_SUFFIX);
570 if (!record_script_path) {
571 fprintf(stderr, "record script not found\n");
572 return -1;
573 }
574
575 report_script_path = get_script_path(argv[1], REPORT_SUFFIX);
576 if (!report_script_path) {
577 fprintf(stderr, "report script not found\n");
578 return -1;
579 }
580
581 if (pipe(live_pipe) < 0) {
582 perror("failed to create pipe");
583 exit(-1);
584 }
585
586 pid = fork();
587 if (pid < 0) {
588 perror("failed to fork");
589 exit(-1);
590 }
591
592 if (!pid) {
593 dup2(live_pipe[1], 1);
594 close(live_pipe[0]);
595
596 __argv = malloc(5 * sizeof(const char *));
597 __argv[0] = "/bin/sh";
598 __argv[1] = record_script_path;
599 __argv[2] = "-o";
600 __argv[3] = "-";
601 __argv[4] = NULL;
602
603 execvp("/bin/sh", (char **)__argv);
604 exit(-1);
605 }
606
607 dup2(live_pipe[0], 0);
608 close(live_pipe[1]);
609
610 __argv = malloc((argc + 3) * sizeof(const char *));
611 __argv[0] = "/bin/sh";
612 __argv[1] = report_script_path;
613 for (i = 2; i < argc; i++)
614 __argv[i] = argv[i];
615 __argv[i++] = "-i";
616 __argv[i++] = "-";
617 __argv[i++] = NULL;
618
619 execvp("/bin/sh", (char **)__argv);
620 exit(-1);
621 }
622
551 if (suffix) { 623 if (suffix) {
552 script_path = get_script_path(argv[2], suffix); 624 script_path = get_script_path(argv[2], suffix);
553 if (!script_path) { 625 if (!script_path) {
@@ -580,7 +652,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
580 if (session == NULL) 652 if (session == NULL)
581 return -ENOMEM; 653 return -ENOMEM;
582 654
583 if (!perf_session__has_traces(session, "record -R")) 655 if (strcmp(input_name, "-") &&
656 !perf_session__has_traces(session, "record -R"))
584 return -EINVAL; 657 return -EINVAL;
585 658
586 if (generate_script_lang) { 659 if (generate_script_lang) {
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
index f869c48dc9b0..d94b40c8ac85 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
@@ -15,6 +15,7 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
15 15
16our @EXPORT = qw( 16our @EXPORT = qw(
17avg nsecs nsecs_secs nsecs_nsecs nsecs_usecs print_nsecs 17avg nsecs nsecs_secs nsecs_nsecs nsecs_usecs print_nsecs
18clear_term
18); 19);
19 20
20our $VERSION = '0.01'; 21our $VERSION = '0.01';
@@ -55,6 +56,11 @@ sub nsecs_str {
55 return $str; 56 return $str;
56} 57}
57 58
59sub clear_term
60{
61 print "\x1b[H\x1b[2J";
62}
63
581; 641;
59__END__ 65__END__
60=head1 NAME 66=head1 NAME
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record
index f8885d389e6f..6ad9b8f5f009 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-record
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit 2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report
index 8bfc660e5056..f6346082a8fc 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-report
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-report
@@ -1,4 +1,10 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide failed syscalls 2# description: system-wide failed syscalls
3# args: [comm] 3# args: [comm]
4perf trace -s ~/libexec/perf-core/scripts/perl/failed-syscalls.pl $1 4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" ; then
6 comm=$1
7 shift
8 fi
9fi
10perf trace $@ -s ~/libexec/perf-core/scripts/perl/failed-syscalls.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record
index b25056ebf963..a828679837a8 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-record
+++ b/tools/perf/scripts/perl/bin/rw-by-file-record
@@ -1,2 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write 2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@
3
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
index eddb9ccce6a5..d83070b7eeb5 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-report
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -1,7 +1,13 @@
1#!/bin/bash 1#!/bin/bash
2# description: r/w activity for a program, by file 2# description: r/w activity for a program, by file
3# args: <comm> 3# args: <comm>
4perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl $1 4if [ $# -lt 1 ] ; then
5 echo "usage: rw-by-file <comm>"
6 exit
7fi
8comm=$1
9shift
10perf trace $@ -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl $comm
5 11
6 12
7 13
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record
index 8903979c5b6c..63976bf11e8b 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-record
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write 2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
index 7f44c25cc857..7ef46983f62f 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-report
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -1,6 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide r/w activity 2# description: system-wide r/w activity
3perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl 3perf trace $@ -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl
4 4
5 5
6 6
diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record
new file mode 100644
index 000000000000..63976bf11e8b
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rwtop-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rwtop-report b/tools/perf/scripts/perl/bin/rwtop-report
new file mode 100644
index 000000000000..93e698cd3f38
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rwtop-report
@@ -0,0 +1,23 @@
1#!/bin/bash
2# description: system-wide r/w top
3# args: [interval]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 1 ] ; then
13 echo "usage: rwtop-report [interval]"
14 exit
15fi
16if [ "$n_args" -gt 0 ] ; then
17 interval=$1
18 shift
19fi
20perf trace $@ -s ~/libexec/perf-core/scripts/perl/rwtop.pl $interval
21
22
23
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record
index 6abedda911a4..9c0cf588ff8c 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-record
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-record
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup 2perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup $@
3 3
4 4
5 5
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
index fce3adcb3249..a0d898f9ca1d 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-report
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -1,6 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide min/max/avg wakeup latency 2# description: system-wide min/max/avg wakeup latency
3perf trace -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl 3perf trace $@ -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl
4 4
5 5
6 6
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
index fce6637b19ba..c2a1a9421133 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-record
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion 2perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
index 71cfbd182fb9..35081132ef97 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-report
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -1,6 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2# description: workqueue stats (ins/exe/create/destroy) 2# description: workqueue stats (ins/exe/create/destroy)
3perf trace -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl 3perf trace $@ -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl
4 4
5 5
6 6
diff --git a/tools/perf/scripts/perl/rwtop.pl b/tools/perf/scripts/perl/rwtop.pl
new file mode 100644
index 000000000000..ec2ab49a6f25
--- /dev/null
+++ b/tools/perf/scripts/perl/rwtop.pl
@@ -0,0 +1,177 @@
1#!/usr/bin/perl -w
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4
5# read/write top
6#
7# Periodically displays system-wide r/w call activity, broken down by
8# pid. If an [interval] arg is specified, the display will be
9# refreshed every [interval] seconds. The default interval is 3
10# seconds.
11
12use 5.010000;
13use strict;
14use warnings;
15
16use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
17use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core;
19use Perf::Trace::Util;
20
21my $default_interval = 3;
22my $nlines = 20;
23my $print_thread;
24
25my %reads;
26my %writes;
27
28my $interval = shift;
29if (!$interval) {
30 $interval = $default_interval;
31}
32
33sub syscalls::sys_exit_read
34{
35 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
36 $common_pid, $common_comm,
37 $nr, $ret) = @_;
38
39 if ($ret > 0) {
40 $reads{$common_pid}{bytes_read} += $ret;
41 } else {
42 if (!defined ($reads{$common_pid}{bytes_read})) {
43 $reads{$common_pid}{bytes_read} = 0;
44 }
45 $reads{$common_pid}{errors}{$ret}++;
46 }
47}
48
49sub syscalls::sys_enter_read
50{
51 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
52 $common_pid, $common_comm,
53 $nr, $fd, $buf, $count) = @_;
54
55 $reads{$common_pid}{bytes_requested} += $count;
56 $reads{$common_pid}{total_reads}++;
57 $reads{$common_pid}{comm} = $common_comm;
58}
59
60sub syscalls::sys_exit_write
61{
62 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
63 $common_pid, $common_comm,
64 $nr, $ret) = @_;
65
66 if ($ret <= 0) {
67 $writes{$common_pid}{errors}{$ret}++;
68 }
69}
70
71sub syscalls::sys_enter_write
72{
73 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
74 $common_pid, $common_comm,
75 $nr, $fd, $buf, $count) = @_;
76
77 $writes{$common_pid}{bytes_written} += $count;
78 $writes{$common_pid}{total_writes}++;
79 $writes{$common_pid}{comm} = $common_comm;
80}
81
82sub trace_begin
83{
84 $SIG{ALRM} = \&print_totals;
85 alarm 1;
86}
87
88sub trace_end
89{
90 print_unhandled();
91 print_totals();
92}
93
94sub print_totals
95{
96 my $count;
97
98 $count = 0;
99
100 clear_term();
101
102 printf("\nread counts by pid:\n\n");
103
104 printf("%6s %20s %10s %10s %10s\n", "pid", "comm",
105 "# reads", "bytes_req", "bytes_read");
106 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------",
107 "----------", "----------", "----------");
108
109 foreach my $pid (sort {$reads{$b}{bytes_read} <=>
110 $reads{$a}{bytes_read}} keys %reads) {
111 my $comm = $reads{$pid}{comm};
112 my $total_reads = $reads{$pid}{total_reads};
113 my $bytes_requested = $reads{$pid}{bytes_requested};
114 my $bytes_read = $reads{$pid}{bytes_read};
115
116 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm,
117 $total_reads, $bytes_requested, $bytes_read);
118
119 if (++$count == $nlines) {
120 last;
121 }
122 }
123
124 $count = 0;
125
126 printf("\nwrite counts by pid:\n\n");
127
128 printf("%6s %20s %10s %13s\n", "pid", "comm",
129 "# writes", "bytes_written");
130 printf("%6s %-20s %10s %13s\n", "------", "--------------------",
131 "----------", "-------------");
132
133 foreach my $pid (sort {$writes{$b}{bytes_written} <=>
134 $writes{$a}{bytes_written}} keys %writes) {
135 my $comm = $writes{$pid}{comm};
136 my $total_writes = $writes{$pid}{total_writes};
137 my $bytes_written = $writes{$pid}{bytes_written};
138
139 printf("%6s %-20s %10s %13s\n", $pid, $comm,
140 $total_writes, $bytes_written);
141
142 if (++$count == $nlines) {
143 last;
144 }
145 }
146
147 %reads = ();
148 %writes = ();
149 alarm $interval;
150}
151
152my %unhandled;
153
154sub print_unhandled
155{
156 if ((scalar keys %unhandled) == 0) {
157 return;
158 }
159
160 print "\nunhandled events:\n\n";
161
162 printf("%-40s %10s\n", "event", "count");
163 printf("%-40s %10s\n", "----------------------------------------",
164 "-----------");
165
166 foreach my $event_name (keys %unhandled) {
167 printf("%-40s %10d\n", $event_name, $unhandled{$event_name});
168 }
169}
170
171sub trace_unhandled
172{
173 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
174 $common_pid, $common_comm) = @_;
175
176 $unhandled{$event_name}++;
177}
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
index 83e91435ed09..9689bc0acd9f 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
@@ -23,3 +23,6 @@ def nsecs_nsecs(nsecs):
23def nsecs_str(nsecs): 23def nsecs_str(nsecs):
24 str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)), 24 str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)),
25 return str 25 return str
26
27def clear_term():
28 print("\x1b[H\x1b[2J")
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
index f8885d389e6f..6ad9b8f5f009 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit 2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
index 1e0c0a860c87..8c128eff9c0a 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
@@ -1,4 +1,10 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide failed syscalls, by pid 2# description: system-wide failed syscalls, by pid
3# args: [comm] 3# args: [comm]
4perf trace -s ~/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py $1 4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" ; then
6 comm=$1
7 shift
8 fi
9fi
10perf trace $@ -s ~/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
new file mode 100644
index 000000000000..27ccffa26ab4
--- /dev/null
+++ b/tools/perf/scripts/python/bin/sctop-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report
new file mode 100644
index 000000000000..b01c842ae7b4
--- /dev/null
+++ b/tools/perf/scripts/python/bin/sctop-report
@@ -0,0 +1,24 @@
1#!/bin/bash
2# description: syscall top
3# args: [comm] [interval]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 2 ] ; then
13 echo "usage: sctop-report [comm] [interval]"
14 exit
15fi
16if [ "$n_args" -gt 1 ] ; then
17 comm=$1
18 interval=$2
19 shift 2
20elif [ "$n_args" -gt 0 ] ; then
21 interval=$1
22 shift
23fi
24perf trace $@ -s ~/libexec/perf-core/scripts/python/sctop.py $comm $interval
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
index 45a8c50359da..27ccffa26ab4 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter 2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
index f8044d192271..c53362e48602 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
@@ -1,4 +1,10 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide syscall counts, by pid 2# description: system-wide syscall counts, by pid
3# args: [comm] 3# args: [comm]
4perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts-by-pid.py $1 4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" ; then
6 comm=$1
7 shift
8 fi
9fi
10perf trace $@ -s ~/libexec/perf-core/scripts/python/syscall-counts-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
index 45a8c50359da..27ccffa26ab4 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter 2perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report
index a366aa61612f..8c21552b3cdc 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-report
@@ -1,4 +1,10 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide syscall counts 2# description: system-wide syscall counts
3# args: [comm] 3# args: [comm]
4perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts.py $1 4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" ; then
6 comm=$1
7 shift
8 fi
9fi
10perf trace $@ -s ~/libexec/perf-core/scripts/python/syscall-counts.py $comm
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
new file mode 100644
index 000000000000..6cafad40c296
--- /dev/null
+++ b/tools/perf/scripts/python/sctop.py
@@ -0,0 +1,78 @@
1# system call top
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Periodically displays system-wide system call totals, broken down by
6# syscall. If a [comm] arg is specified, only syscalls called by
7# [comm] are displayed. If an [interval] arg is specified, the display
8# will be refreshed every [interval] seconds. The default interval is
9# 3 seconds.
10
11import thread
12import time
13import os
14import sys
15
16sys.path.append(os.environ['PERF_EXEC_PATH'] + \
17 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
18
19from perf_trace_context import *
20from Core import *
21from Util import *
22
23usage = "perf trace -s syscall-counts.py [comm] [interval]\n";
24
25for_comm = None
26default_interval = 3
27interval = default_interval
28
29if len(sys.argv) > 3:
30 sys.exit(usage)
31
32if len(sys.argv) > 2:
33 for_comm = sys.argv[1]
34 interval = int(sys.argv[2])
35elif len(sys.argv) > 1:
36 try:
37 interval = int(sys.argv[1])
38 except ValueError:
39 for_comm = sys.argv[1]
40 interval = default_interval
41
42syscalls = autodict()
43
44def trace_begin():
45 thread.start_new_thread(print_syscall_totals, (interval,))
46 pass
47
48def raw_syscalls__sys_enter(event_name, context, common_cpu,
49 common_secs, common_nsecs, common_pid, common_comm,
50 id, args):
51 if for_comm is not None:
52 if common_comm != for_comm:
53 return
54 try:
55 syscalls[id] += 1
56 except TypeError:
57 syscalls[id] = 1
58
59def print_syscall_totals(interval):
60 while 1:
61 clear_term()
62 if for_comm is not None:
63 print "\nsyscall events for %s:\n\n" % (for_comm),
64 else:
65 print "\nsyscall events:\n\n",
66
67 print "%-40s %10s\n" % ("event", "count"),
68 print "%-40s %10s\n" % ("----------------------------------------", \
69 "----------"),
70
71 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
72 reverse = True):
73 try:
74 print "%-40d %10d\n" % (id, val),
75 except TypeError:
76 pass
77 syscalls.clear()
78 time.sleep(interval)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 7f7cf8539cfe..e5740ea140ab 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -83,6 +83,37 @@ struct build_id_event {
83 char filename[]; 83 char filename[];
84}; 84};
85 85
86enum perf_header_event_type { /* above any possible kernel type */
87 PERF_RECORD_HEADER_ATTR = 64,
88 PERF_RECORD_HEADER_EVENT_TYPE = 65,
89 PERF_RECORD_HEADER_TRACING_DATA = 66,
90 PERF_RECORD_HEADER_BUILD_ID = 67,
91 PERF_RECORD_HEADER_MAX
92};
93
94struct attr_event {
95 struct perf_event_header header;
96 struct perf_event_attr attr;
97 u64 id[];
98};
99
100#define MAX_EVENT_NAME 64
101
102struct perf_trace_event_type {
103 u64 event_id;
104 char name[MAX_EVENT_NAME];
105};
106
107struct event_type_event {
108 struct perf_event_header header;
109 struct perf_trace_event_type event_type;
110};
111
112struct tracing_data_event {
113 struct perf_event_header header;
114 u32 size;
115};
116
86typedef union event_union { 117typedef union event_union {
87 struct perf_event_header header; 118 struct perf_event_header header;
88 struct ip_event ip; 119 struct ip_event ip;
@@ -92,6 +123,10 @@ typedef union event_union {
92 struct lost_event lost; 123 struct lost_event lost;
93 struct read_event read; 124 struct read_event read;
94 struct sample_event sample; 125 struct sample_event sample;
126 struct attr_event attr;
127 struct event_type_event event_type;
128 struct tracing_data_event tracing_data;
129 struct build_id_event build_id;
95} event_t; 130} event_t;
96 131
97struct events_stats { 132struct events_stats {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6c9aa16ee51f..628173ba689e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -99,13 +99,6 @@ int perf_header__add_attr(struct perf_header *self,
99 return 0; 99 return 0;
100} 100}
101 101
102#define MAX_EVENT_NAME 64
103
104struct perf_trace_event_type {
105 u64 event_id;
106 char name[MAX_EVENT_NAME];
107};
108
109static int event_count; 102static int event_count;
110static struct perf_trace_event_type *events; 103static struct perf_trace_event_type *events;
111 104
@@ -427,6 +420,25 @@ out_free:
427 return err; 420 return err;
428} 421}
429 422
423int perf_header__write_pipe(int fd)
424{
425 struct perf_pipe_file_header f_header;
426 int err;
427
428 f_header = (struct perf_pipe_file_header){
429 .magic = PERF_MAGIC,
430 .size = sizeof(f_header),
431 };
432
433 err = do_write(fd, &f_header, sizeof(f_header));
434 if (err < 0) {
435 pr_debug("failed to write perf pipe header\n");
436 return err;
437 }
438
439 return 0;
440}
441
430int perf_header__write(struct perf_header *self, int fd, bool at_exit) 442int perf_header__write(struct perf_header *self, int fd, bool at_exit)
431{ 443{
432 struct perf_file_header f_header; 444 struct perf_file_header f_header;
@@ -518,25 +530,10 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
518 return 0; 530 return 0;
519} 531}
520 532
521static int do_read(int fd, void *buf, size_t size)
522{
523 while (size) {
524 int ret = read(fd, buf, size);
525
526 if (ret <= 0)
527 return -1;
528
529 size -= ret;
530 buf += ret;
531 }
532
533 return 0;
534}
535
536static int perf_header__getbuffer64(struct perf_header *self, 533static int perf_header__getbuffer64(struct perf_header *self,
537 int fd, void *buf, size_t size) 534 int fd, void *buf, size_t size)
538{ 535{
539 if (do_read(fd, buf, size)) 536 if (do_read(fd, buf, size) <= 0)
540 return -1; 537 return -1;
541 538
542 if (self->needs_swap) 539 if (self->needs_swap)
@@ -592,7 +589,7 @@ int perf_file_header__read(struct perf_file_header *self,
592{ 589{
593 lseek(fd, 0, SEEK_SET); 590 lseek(fd, 0, SEEK_SET);
594 591
595 if (do_read(fd, self, sizeof(*self)) || 592 if (do_read(fd, self, sizeof(*self)) <= 0 ||
596 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 593 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
597 return -1; 594 return -1;
598 595
@@ -662,13 +659,51 @@ static int perf_file_section__process(struct perf_file_section *self,
662 return 0; 659 return 0;
663} 660}
664 661
665int perf_header__read(struct perf_header *self, int fd) 662static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
663 struct perf_header *ph, int fd)
664{
665 if (do_read(fd, self, sizeof(*self)) <= 0 ||
666 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
667 return -1;
668
669 if (self->size != sizeof(*self)) {
670 u64 size = bswap_64(self->size);
671
672 if (size != sizeof(*self))
673 return -1;
674
675 ph->needs_swap = true;
676 }
677
678 return 0;
679}
680
681static int perf_header__read_pipe(struct perf_session *session, int fd)
682{
683 struct perf_header *self = &session->header;
684 struct perf_pipe_file_header f_header;
685
686 if (perf_file_header__read_pipe(&f_header, self, fd) < 0) {
687 pr_debug("incompatible file format\n");
688 return -EINVAL;
689 }
690
691 session->fd = fd;
692
693 return 0;
694}
695
696int perf_header__read(struct perf_session *session, int fd)
666{ 697{
698 struct perf_header *self = &session->header;
667 struct perf_file_header f_header; 699 struct perf_file_header f_header;
668 struct perf_file_attr f_attr; 700 struct perf_file_attr f_attr;
669 u64 f_id; 701 u64 f_id;
670 int nr_attrs, nr_ids, i, j; 702 int nr_attrs, nr_ids, i, j;
671 703
704 if (session->fd_pipe)
705 return perf_header__read_pipe(session, fd);
706
672 if (perf_file_header__read(&f_header, self, fd) < 0) { 707 if (perf_file_header__read(&f_header, self, fd) < 0) {
673 pr_debug("incompatible file format\n"); 708 pr_debug("incompatible file format\n");
674 return -EINVAL; 709 return -EINVAL;
@@ -765,3 +800,279 @@ perf_header__find_attr(u64 id, struct perf_header *header)
765 800
766 return NULL; 801 return NULL;
767} 802}
803
804int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
805 event__handler_t process,
806 struct perf_session *session)
807{
808 event_t *ev;
809 size_t size;
810 int err;
811
812 size = sizeof(struct perf_event_attr);
813 size = ALIGN(size, sizeof(u64));
814 size += sizeof(struct perf_event_header);
815 size += ids * sizeof(u64);
816
817 ev = malloc(size);
818
819 ev->attr.attr = *attr;
820 memcpy(ev->attr.id, id, ids * sizeof(u64));
821
822 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
823 ev->attr.header.size = size;
824
825 err = process(ev, session);
826
827 free(ev);
828
829 return err;
830}
831
832int event__synthesize_attrs(struct perf_header *self,
833 event__handler_t process,
834 struct perf_session *session)
835{
836 struct perf_header_attr *attr;
837 int i, err = 0;
838
839 for (i = 0; i < self->attrs; i++) {
840 attr = self->attr[i];
841
842 err = event__synthesize_attr(&attr->attr, attr->ids, attr->id,
843 process, session);
844 if (err) {
845 pr_debug("failed to create perf header attribute\n");
846 return err;
847 }
848 }
849
850 return err;
851}
852
853int event__process_attr(event_t *self, struct perf_session *session)
854{
855 struct perf_header_attr *attr;
856 unsigned int i, ids, n_ids;
857
858 attr = perf_header_attr__new(&self->attr.attr);
859 if (attr == NULL)
860 return -ENOMEM;
861
862 ids = self->header.size;
863 ids -= (void *)&self->attr.id - (void *)self;
864 n_ids = ids / sizeof(u64);
865
866 for (i = 0; i < n_ids; i++) {
867 if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) {
868 perf_header_attr__delete(attr);
869 return -ENOMEM;
870 }
871 }
872
873 if (perf_header__add_attr(&session->header, attr) < 0) {
874 perf_header_attr__delete(attr);
875 return -ENOMEM;
876 }
877
878 perf_session__update_sample_type(session);
879
880 return 0;
881}
882
883int event__synthesize_event_type(u64 event_id, char *name,
884 event__handler_t process,
885 struct perf_session *session)
886{
887 event_t ev;
888 size_t size = 0;
889 int err = 0;
890
891 memset(&ev, 0, sizeof(ev));
892
893 ev.event_type.event_type.event_id = event_id;
894 memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME);
895 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
896
897 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
898 size = strlen(name);
899 size = ALIGN(size, sizeof(u64));
900 ev.event_type.header.size = sizeof(ev.event_type) -
901 (sizeof(ev.event_type.event_type.name) - size);
902
903 err = process(&ev, session);
904
905 return err;
906}
907
908int event__synthesize_event_types(event__handler_t process,
909 struct perf_session *session)
910{
911 struct perf_trace_event_type *type;
912 int i, err = 0;
913
914 for (i = 0; i < event_count; i++) {
915 type = &events[i];
916
917 err = event__synthesize_event_type(type->event_id, type->name,
918 process, session);
919 if (err) {
920 pr_debug("failed to create perf header event type\n");
921 return err;
922 }
923 }
924
925 return err;
926}
927
928int event__process_event_type(event_t *self,
929 struct perf_session *session __unused)
930{
931 if (perf_header__push_event(self->event_type.event_type.event_id,
932 self->event_type.event_type.name) < 0)
933 return -ENOMEM;
934
935 return 0;
936}
937
938int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
939 int nb_events,
940 event__handler_t process,
941 struct perf_session *session __unused)
942{
943 event_t ev;
944 ssize_t size = 0, aligned_size = 0, padding;
945 int err = 0;
946
947 memset(&ev, 0, sizeof(ev));
948
949 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
950 size = read_tracing_data_size(fd, pattrs, nb_events);
951 if (size <= 0)
952 return size;
953 aligned_size = ALIGN(size, sizeof(u64));
954 padding = aligned_size - size;
955 ev.tracing_data.header.size = sizeof(ev.tracing_data);
956 ev.tracing_data.size = aligned_size;
957
958 process(&ev, session);
959
960 err = read_tracing_data(fd, pattrs, nb_events);
961 write_padded(fd, NULL, 0, padding);
962
963 return aligned_size;
964}
965
966int event__process_tracing_data(event_t *self,
967 struct perf_session *session)
968{
969 ssize_t size_read, padding, size = self->tracing_data.size;
970 off_t offset = lseek(session->fd, 0, SEEK_CUR);
971 char buf[BUFSIZ];
972
973 /* setup for reading amidst mmap */
974 lseek(session->fd, offset + sizeof(struct tracing_data_event),
975 SEEK_SET);
976
977 size_read = trace_report(session->fd);
978
979 padding = ALIGN(size_read, sizeof(u64)) - size_read;
980
981 if (read(session->fd, buf, padding) < 0)
982 die("reading input file");
983
984 if (size_read + padding != size)
985 die("tracing data size mismatch");
986
987 return size_read + padding;
988}
989
990int event__synthesize_build_id(struct dso *pos, u16 misc,
991 event__handler_t process,
992 struct perf_session *session)
993{
994 event_t ev;
995 size_t len;
996 int err = 0;
997
998 if (!pos->hit)
999 return err;
1000
1001 memset(&ev, 0, sizeof(ev));
1002
1003 len = pos->long_name_len + 1;
1004 len = ALIGN(len, NAME_ALIGN);
1005 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
1006 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
1007 ev.build_id.header.misc = misc;
1008 ev.build_id.header.size = sizeof(ev.build_id) + len;
1009 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
1010
1011 err = process(&ev, session);
1012
1013 return err;
1014}
1015
1016static int __event_synthesize_build_ids(struct list_head *head, u16 misc,
1017 event__handler_t process,
1018 struct perf_session *session)
1019{
1020 struct dso *pos;
1021
1022 dsos__for_each_with_build_id(pos, head) {
1023 int err;
1024 if (!pos->hit)
1025 continue;
1026
1027 err = event__synthesize_build_id(pos, misc, process, session);
1028 if (err < 0)
1029 return err;
1030 }
1031
1032 return 0;
1033}
1034
1035int event__synthesize_build_ids(event__handler_t process,
1036 struct perf_session *session)
1037{
1038 int err;
1039
1040 if (!dsos__read_build_ids(true))
1041 return 0;
1042
1043 err = __event_synthesize_build_ids(&dsos__kernel,
1044 PERF_RECORD_MISC_KERNEL,
1045 process, session);
1046 if (err == 0)
1047 err = __event_synthesize_build_ids(&dsos__user,
1048 PERF_RECORD_MISC_USER,
1049 process, session);
1050
1051 if (err < 0) {
1052 pr_debug("failed to synthesize build ids\n");
1053 return err;
1054 }
1055
1056 dsos__cache_build_ids();
1057
1058 return 0;
1059}
1060
1061int event__process_build_id(event_t *self,
1062 struct perf_session *session __unused)
1063{
1064 struct list_head *head = &dsos__user;
1065 struct dso *dso;
1066
1067 if (self->build_id.header.misc & PERF_RECORD_MISC_KERNEL)
1068 head = &dsos__kernel;
1069
1070 dso = __dsos__findnew(head, self->build_id.filename);
1071 if (dso != NULL) {
1072 dso__set_build_id(dso, &self->build_id.build_id);
1073 if (head == &dsos__kernel && self->build_id.filename[0] == '[')
1074 dso->kernel = 1;
1075 }
1076
1077 return 0;
1078}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index c059f08cf877..4214e2375650 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -39,6 +39,11 @@ struct perf_file_header {
39 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); 39 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
40}; 40};
41 41
42struct perf_pipe_file_header {
43 u64 magic;
44 u64 size;
45};
46
42struct perf_header; 47struct perf_header;
43 48
44int perf_file_header__read(struct perf_file_header *self, 49int perf_file_header__read(struct perf_file_header *self,
@@ -60,8 +65,9 @@ struct perf_header {
60int perf_header__init(struct perf_header *self); 65int perf_header__init(struct perf_header *self);
61void perf_header__exit(struct perf_header *self); 66void perf_header__exit(struct perf_header *self);
62 67
63int perf_header__read(struct perf_header *self, int fd); 68int perf_header__read(struct perf_session *session, int fd);
64int perf_header__write(struct perf_header *self, int fd, bool at_exit); 69int perf_header__write(struct perf_header *self, int fd, bool at_exit);
70int perf_header__write_pipe(int fd);
65 71
66int perf_header__add_attr(struct perf_header *self, 72int perf_header__add_attr(struct perf_header *self,
67 struct perf_header_attr *attr); 73 struct perf_header_attr *attr);
@@ -89,4 +95,34 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
89 const char *name, bool is_kallsyms); 95 const char *name, bool is_kallsyms);
90int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 96int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
91 97
98int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
99 event__handler_t process,
100 struct perf_session *session);
101int event__synthesize_attrs(struct perf_header *self,
102 event__handler_t process,
103 struct perf_session *session);
104int event__process_attr(event_t *self, struct perf_session *session);
105
106int event__synthesize_event_type(u64 event_id, char *name,
107 event__handler_t process,
108 struct perf_session *session);
109int event__synthesize_event_types(event__handler_t process,
110 struct perf_session *session);
111int event__process_event_type(event_t *self,
112 struct perf_session *session);
113
114int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
115 int nb_events,
116 event__handler_t process,
117 struct perf_session *session);
118int event__process_tracing_data(event_t *self,
119 struct perf_session *session);
120
121int event__synthesize_build_id(struct dso *pos, u16 misc,
122 event__handler_t process,
123 struct perf_session *session);
124int event__synthesize_build_ids(event__handler_t process,
125 struct perf_session *session);
126int event__process_build_id(event_t *self, struct perf_session *session);
127
92#endif /* __PERF_HEADER_H */ 128#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 435781e0c205..3b4ec6797565 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -410,7 +410,6 @@ static enum event_result
410parse_single_tracepoint_event(char *sys_name, 410parse_single_tracepoint_event(char *sys_name,
411 const char *evt_name, 411 const char *evt_name,
412 unsigned int evt_length, 412 unsigned int evt_length,
413 char *flags,
414 struct perf_event_attr *attr, 413 struct perf_event_attr *attr,
415 const char **strp) 414 const char **strp)
416{ 415{
@@ -419,13 +418,11 @@ parse_single_tracepoint_event(char *sys_name,
419 u64 id; 418 u64 id;
420 int fd; 419 int fd;
421 420
422 if (flags) { 421 attr->sample_type |= PERF_SAMPLE_RAW;
423 if (!strncmp(flags, "record", strlen(flags))) { 422 attr->sample_type |= PERF_SAMPLE_TIME;
424 attr->sample_type |= PERF_SAMPLE_RAW; 423 attr->sample_type |= PERF_SAMPLE_CPU;
425 attr->sample_type |= PERF_SAMPLE_TIME; 424
426 attr->sample_type |= PERF_SAMPLE_CPU; 425 attr->sample_period = 1;
427 }
428 }
429 426
430 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 427 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
431 sys_name, evt_name); 428 sys_name, evt_name);
@@ -533,8 +530,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
533 flags); 530 flags);
534 } else 531 } else
535 return parse_single_tracepoint_event(sys_name, evt_name, 532 return parse_single_tracepoint_event(sys_name, evt_name,
536 evt_length, flags, 533 evt_length, attr, strp);
537 attr, strp);
538} 534}
539 535
540static enum event_result 536static enum event_result
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ddf288fca3eb..0fdf3ebef1e9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,16 @@ static int perf_session__open(struct perf_session *self, bool force)
14{ 14{
15 struct stat input_stat; 15 struct stat input_stat;
16 16
17 if (!strcmp(self->filename, "-")) {
18 self->fd_pipe = true;
19 self->fd = STDIN_FILENO;
20
21 if (perf_header__read(self, self->fd) < 0)
22 pr_err("incompatible file format");
23
24 return 0;
25 }
26
17 self->fd = open(self->filename, O_RDONLY); 27 self->fd = open(self->filename, O_RDONLY);
18 if (self->fd < 0) { 28 if (self->fd < 0) {
19 pr_err("failed to open file: %s", self->filename); 29 pr_err("failed to open file: %s", self->filename);
@@ -38,7 +48,7 @@ static int perf_session__open(struct perf_session *self, bool force)
38 goto out_close; 48 goto out_close;
39 } 49 }
40 50
41 if (perf_header__read(&self->header, self->fd) < 0) { 51 if (perf_header__read(self, self->fd) < 0) {
42 pr_err("incompatible file format"); 52 pr_err("incompatible file format");
43 goto out_close; 53 goto out_close;
44 } 54 }
@@ -52,6 +62,11 @@ out_close:
52 return -1; 62 return -1;
53} 63}
54 64
65void perf_session__update_sample_type(struct perf_session *self)
66{
67 self->sample_type = perf_header__sample_type(&self->header);
68}
69
55struct perf_session *perf_session__new(const char *filename, int mode, bool force) 70struct perf_session *perf_session__new(const char *filename, int mode, bool force)
56{ 71{
57 size_t len = filename ? strlen(filename) + 1 : 0; 72 size_t len = filename ? strlen(filename) + 1 : 0;
@@ -85,7 +100,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
85 goto out_delete; 100 goto out_delete;
86 } 101 }
87 102
88 self->sample_type = perf_header__sample_type(&self->header); 103 perf_session__update_sample_type(self);
89out: 104out:
90 return self; 105 return self;
91out_free: 106out_free:
@@ -185,6 +200,14 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
185 handler->throttle = process_event_stub; 200 handler->throttle = process_event_stub;
186 if (handler->unthrottle == NULL) 201 if (handler->unthrottle == NULL)
187 handler->unthrottle = process_event_stub; 202 handler->unthrottle = process_event_stub;
203 if (handler->attr == NULL)
204 handler->attr = process_event_stub;
205 if (handler->event_type == NULL)
206 handler->event_type = process_event_stub;
207 if (handler->tracing_data == NULL)
208 handler->tracing_data = process_event_stub;
209 if (handler->build_id == NULL)
210 handler->build_id = process_event_stub;
188} 211}
189 212
190static const char *event__name[] = { 213static const char *event__name[] = {
@@ -198,16 +221,23 @@ static const char *event__name[] = {
198 [PERF_RECORD_FORK] = "FORK", 221 [PERF_RECORD_FORK] = "FORK",
199 [PERF_RECORD_READ] = "READ", 222 [PERF_RECORD_READ] = "READ",
200 [PERF_RECORD_SAMPLE] = "SAMPLE", 223 [PERF_RECORD_SAMPLE] = "SAMPLE",
224 [PERF_RECORD_HEADER_ATTR] = "ATTR",
225 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
226 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
227 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
201}; 228};
202 229
203unsigned long event__total[PERF_RECORD_MAX]; 230unsigned long event__total[PERF_RECORD_HEADER_MAX];
204 231
205void event__print_totals(void) 232void event__print_totals(void)
206{ 233{
207 int i; 234 int i;
208 for (i = 0; i < PERF_RECORD_MAX; ++i) 235 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
236 if (!event__name[i])
237 continue;
209 pr_info("%10s events: %10ld\n", 238 pr_info("%10s events: %10ld\n",
210 event__name[i], event__total[i]); 239 event__name[i], event__total[i]);
240 }
211} 241}
212 242
213void mem_bswap_64(void *src, int byte_size) 243void mem_bswap_64(void *src, int byte_size)
@@ -261,6 +291,37 @@ static void event__read_swap(event_t *self)
261 self->read.id = bswap_64(self->read.id); 291 self->read.id = bswap_64(self->read.id);
262} 292}
263 293
294static void event__attr_swap(event_t *self)
295{
296 size_t size;
297
298 self->attr.attr.type = bswap_32(self->attr.attr.type);
299 self->attr.attr.size = bswap_32(self->attr.attr.size);
300 self->attr.attr.config = bswap_64(self->attr.attr.config);
301 self->attr.attr.sample_period = bswap_64(self->attr.attr.sample_period);
302 self->attr.attr.sample_type = bswap_64(self->attr.attr.sample_type);
303 self->attr.attr.read_format = bswap_64(self->attr.attr.read_format);
304 self->attr.attr.wakeup_events = bswap_32(self->attr.attr.wakeup_events);
305 self->attr.attr.bp_type = bswap_32(self->attr.attr.bp_type);
306 self->attr.attr.bp_addr = bswap_64(self->attr.attr.bp_addr);
307 self->attr.attr.bp_len = bswap_64(self->attr.attr.bp_len);
308
309 size = self->header.size;
310 size -= (void *)&self->attr.id - (void *)self;
311 mem_bswap_64(self->attr.id, size);
312}
313
314static void event__event_type_swap(event_t *self)
315{
316 self->event_type.event_type.event_id =
317 bswap_64(self->event_type.event_type.event_id);
318}
319
320static void event__tracing_data_swap(event_t *self)
321{
322 self->tracing_data.size = bswap_32(self->tracing_data.size);
323}
324
264typedef void (*event__swap_op)(event_t *self); 325typedef void (*event__swap_op)(event_t *self);
265 326
266static event__swap_op event__swap_ops[] = { 327static event__swap_op event__swap_ops[] = {
@@ -271,7 +332,11 @@ static event__swap_op event__swap_ops[] = {
271 [PERF_RECORD_LOST] = event__all64_swap, 332 [PERF_RECORD_LOST] = event__all64_swap,
272 [PERF_RECORD_READ] = event__read_swap, 333 [PERF_RECORD_READ] = event__read_swap,
273 [PERF_RECORD_SAMPLE] = event__all64_swap, 334 [PERF_RECORD_SAMPLE] = event__all64_swap,
274 [PERF_RECORD_MAX] = NULL, 335 [PERF_RECORD_HEADER_ATTR] = event__attr_swap,
336 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap,
337 [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap,
338 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
339 [PERF_RECORD_HEADER_MAX] = NULL,
275}; 340};
276 341
277static int perf_session__process_event(struct perf_session *self, 342static int perf_session__process_event(struct perf_session *self,
@@ -281,7 +346,7 @@ static int perf_session__process_event(struct perf_session *self,
281{ 346{
282 trace_event(event); 347 trace_event(event);
283 348
284 if (event->header.type < PERF_RECORD_MAX) { 349 if (event->header.type < PERF_RECORD_HEADER_MAX) {
285 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 350 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
286 offset + head, event->header.size, 351 offset + head, event->header.size,
287 event__name[event->header.type]); 352 event__name[event->header.type]);
@@ -311,6 +376,16 @@ static int perf_session__process_event(struct perf_session *self,
311 return ops->throttle(event, self); 376 return ops->throttle(event, self);
312 case PERF_RECORD_UNTHROTTLE: 377 case PERF_RECORD_UNTHROTTLE:
313 return ops->unthrottle(event, self); 378 return ops->unthrottle(event, self);
379 case PERF_RECORD_HEADER_ATTR:
380 return ops->attr(event, self);
381 case PERF_RECORD_HEADER_EVENT_TYPE:
382 return ops->event_type(event, self);
383 case PERF_RECORD_HEADER_TRACING_DATA:
384 /* setup for reading amidst mmap */
385 lseek(self->fd, offset + head, SEEK_SET);
386 return ops->tracing_data(event, self);
387 case PERF_RECORD_HEADER_BUILD_ID:
388 return ops->build_id(event, self);
314 default: 389 default:
315 self->unknown_events++; 390 self->unknown_events++;
316 return -1; 391 return -1;
@@ -376,6 +451,101 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
376 return thread; 451 return thread;
377} 452}
378 453
454int do_read(int fd, void *buf, size_t size)
455{
456 void *buf_start = buf;
457
458 while (size) {
459 int ret = read(fd, buf, size);
460
461 if (ret <= 0)
462 return ret;
463
464 size -= ret;
465 buf += ret;
466 }
467
468 return buf - buf_start;
469}
470
471#define session_done() (*(volatile int *)(&session_done))
472volatile int session_done;
473
474static int __perf_session__process_pipe_events(struct perf_session *self,
475 struct perf_event_ops *ops)
476{
477 event_t event;
478 uint32_t size;
479 int skip = 0;
480 u64 head;
481 int err;
482 void *p;
483
484 perf_event_ops__fill_defaults(ops);
485
486 head = 0;
487more:
488 err = do_read(self->fd, &event, sizeof(struct perf_event_header));
489 if (err <= 0) {
490 if (err == 0)
491 goto done;
492
493 pr_err("failed to read event header\n");
494 goto out_err;
495 }
496
497 if (self->header.needs_swap)
498 perf_event_header__bswap(&event.header);
499
500 size = event.header.size;
501 if (size == 0)
502 size = 8;
503
504 p = &event;
505 p += sizeof(struct perf_event_header);
506
507 err = do_read(self->fd, p, size - sizeof(struct perf_event_header));
508 if (err <= 0) {
509 if (err == 0) {
510 pr_err("unexpected end of event stream\n");
511 goto done;
512 }
513
514 pr_err("failed to read event data\n");
515 goto out_err;
516 }
517
518 if (size == 0 ||
519 (skip = perf_session__process_event(self, &event, ops,
520 0, head)) < 0) {
521 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
522 head, event.header.size, event.header.type);
523 /*
524 * assume we lost track of the stream, check alignment, and
525 * increment a single u64 in the hope to catch on again 'soon'.
526 */
527 if (unlikely(head & 7))
528 head &= ~7ULL;
529
530 size = 8;
531 }
532
533 head += size;
534
535 dump_printf("\n%#Lx [%#x]: event: %d\n",
536 head, event.header.size, event.header.type);
537
538 if (skip > 0)
539 head += skip;
540
541 if (!session_done())
542 goto more;
543done:
544 err = 0;
545out_err:
546 return err;
547}
548
379int __perf_session__process_events(struct perf_session *self, 549int __perf_session__process_events(struct perf_session *self,
380 u64 data_offset, u64 data_size, 550 u64 data_offset, u64 data_size,
381 u64 file_size, struct perf_event_ops *ops) 551 u64 file_size, struct perf_event_ops *ops)
@@ -499,9 +669,13 @@ out_getcwd_err:
499 self->cwdlen = strlen(self->cwd); 669 self->cwdlen = strlen(self->cwd);
500 } 670 }
501 671
502 err = __perf_session__process_events(self, self->header.data_offset, 672 if (!self->fd_pipe)
503 self->header.data_size, 673 err = __perf_session__process_events(self,
504 self->size, ops); 674 self->header.data_offset,
675 self->header.data_size,
676 self->size, ops);
677 else
678 err = __perf_session__process_pipe_events(self, ops);
505out_err: 679out_err:
506 return err; 680 return err;
507} 681}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 27f4c2dc715b..0ac14d42dc28 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -27,6 +27,7 @@ struct perf_session {
27 u64 sample_type; 27 u64 sample_type;
28 struct ref_reloc_sym ref_reloc_sym; 28 struct ref_reloc_sym ref_reloc_sym;
29 int fd; 29 int fd;
30 bool fd_pipe;
30 int cwdlen; 31 int cwdlen;
31 char *cwd; 32 char *cwd;
32 char filename[0]; 33 char filename[0];
@@ -43,7 +44,11 @@ struct perf_event_ops {
43 lost, 44 lost,
44 read, 45 read,
45 throttle, 46 throttle,
46 unthrottle; 47 unthrottle,
48 attr,
49 event_type,
50 tracing_data,
51 build_id;
47}; 52};
48 53
49struct perf_session *perf_session__new(const char *filename, int mode, bool force); 54struct perf_session *perf_session__new(const char *filename, int mode, bool force);
@@ -92,6 +97,9 @@ static inline struct map *
92 return map_groups__new_module(&self->kmaps, start, filename); 97 return map_groups__new_module(&self->kmaps, start, filename);
93} 98}
94 99
100int do_read(int fd, void *buf, size_t size);
101void perf_session__update_sample_type(struct perf_session *self);
102
95#ifdef NO_NEWT_SUPPORT 103#ifdef NO_NEWT_SUPPORT
96static inline int perf_session__browse_hists(struct rb_root *hists __used, 104static inline int perf_session__browse_hists(struct rb_root *hists __used,
97 u64 nr_hists __used, 105 u64 nr_hists __used,
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 5ea8973ad331..30cd9b575953 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -154,10 +154,17 @@ static void put_tracing_file(char *file)
154 free(file); 154 free(file);
155} 155}
156 156
157static ssize_t calc_data_size;
158
157static ssize_t write_or_die(const void *buf, size_t len) 159static ssize_t write_or_die(const void *buf, size_t len)
158{ 160{
159 int ret; 161 int ret;
160 162
163 if (calc_data_size) {
164 calc_data_size += len;
165 return len;
166 }
167
161 ret = write(output_fd, buf, len); 168 ret = write(output_fd, buf, len);
162 if (ret < 0) 169 if (ret < 0)
163 die("writing to '%s'", output_file); 170 die("writing to '%s'", output_file);
@@ -526,3 +533,20 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
526 533
527 return 0; 534 return 0;
528} 535}
536
537ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
538 int nb_events)
539{
540 ssize_t size;
541 int err = 0;
542
543 calc_data_size = 1;
544 err = read_tracing_data(fd, pattrs, nb_events);
545 size = calc_data_size - 1;
546 calc_data_size = 0;
547
548 if (err < 0)
549 return err;
550
551 return size;
552}
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 17d6d66ed766..d6ef414075a6 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -761,7 +761,7 @@ static int field_is_string(struct format_field *field)
761 761
762static int field_is_dynamic(struct format_field *field) 762static int field_is_dynamic(struct format_field *field)
763{ 763{
764 if (!strcmp(field->type, "__data_loc")) 764 if (!strncmp(field->type, "__data_loc", 10))
765 return 1; 765 return 1;
766 766
767 return 0; 767 return 0;
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 7cd1193918c7..44889c9b5630 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -50,14 +50,37 @@ static int long_size;
50 50
51static unsigned long page_size; 51static unsigned long page_size;
52 52
53static ssize_t calc_data_size;
54
55static int do_read(int fd, void *buf, int size)
56{
57 int rsize = size;
58
59 while (size) {
60 int ret = read(fd, buf, size);
61
62 if (ret <= 0)
63 return -1;
64
65 size -= ret;
66 buf += ret;
67 }
68
69 return rsize;
70}
71
53static int read_or_die(void *data, int size) 72static int read_or_die(void *data, int size)
54{ 73{
55 int r; 74 int r;
56 75
57 r = read(input_fd, data, size); 76 r = do_read(input_fd, data, size);
58 if (r != size) 77 if (r <= 0)
59 die("reading input file (size expected=%d received=%d)", 78 die("reading input file (size expected=%d received=%d)",
60 size, r); 79 size, r);
80
81 if (calc_data_size)
82 calc_data_size += r;
83
61 return r; 84 return r;
62} 85}
63 86
@@ -82,56 +105,28 @@ static char *read_string(void)
82 char buf[BUFSIZ]; 105 char buf[BUFSIZ];
83 char *str = NULL; 106 char *str = NULL;
84 int size = 0; 107 int size = 0;
85 int i;
86 off_t r; 108 off_t r;
109 char c;
87 110
88 for (;;) { 111 for (;;) {
89 r = read(input_fd, buf, BUFSIZ); 112 r = read(input_fd, &c, 1);
90 if (r < 0) 113 if (r < 0)
91 die("reading input file"); 114 die("reading input file");
92 115
93 if (!r) 116 if (!r)
94 die("no data"); 117 die("no data");
95 118
96 for (i = 0; i < r; i++) { 119 buf[size++] = c;
97 if (!buf[i])
98 break;
99 }
100 if (i < r)
101 break;
102 120
103 if (str) { 121 if (!c)
104 size += BUFSIZ; 122 break;
105 str = realloc(str, size);
106 if (!str)
107 die("malloc of size %d", size);
108 memcpy(str + (size - BUFSIZ), buf, BUFSIZ);
109 } else {
110 size = BUFSIZ;
111 str = malloc_or_die(size);
112 memcpy(str, buf, size);
113 }
114 } 123 }
115 124
116 /* trailing \0: */ 125 if (calc_data_size)
117 i++; 126 calc_data_size += size;
118 127
119 /* move the file descriptor to the end of the string */ 128 str = malloc_or_die(size);
120 r = lseek(input_fd, -(r - i), SEEK_CUR); 129 memcpy(str, buf, size);
121 if (r == (off_t)-1)
122 die("lseek");
123
124 if (str) {
125 size += i;
126 str = realloc(str, size);
127 if (!str)
128 die("malloc of size %d", size);
129 memcpy(str + (size - i), buf, i);
130 } else {
131 size = i;
132 str = malloc_or_die(i);
133 memcpy(str, buf, i);
134 }
135 130
136 return str; 131 return str;
137} 132}
@@ -459,7 +454,7 @@ struct record *trace_read_data(int cpu)
459 return data; 454 return data;
460} 455}
461 456
462void trace_report(int fd) 457ssize_t trace_report(int fd)
463{ 458{
464 char buf[BUFSIZ]; 459 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 460 char test[] = { 23, 8, 68 };
@@ -467,6 +462,9 @@ void trace_report(int fd)
467 int show_version = 0; 462 int show_version = 0;
468 int show_funcs = 0; 463 int show_funcs = 0;
469 int show_printk = 0; 464 int show_printk = 0;
465 ssize_t size;
466
467 calc_data_size = 1;
470 468
471 input_fd = fd; 469 input_fd = fd;
472 470
@@ -499,14 +497,17 @@ void trace_report(int fd)
499 read_proc_kallsyms(); 497 read_proc_kallsyms();
500 read_ftrace_printk(); 498 read_ftrace_printk();
501 499
500 size = calc_data_size - 1;
501 calc_data_size = 0;
502
502 if (show_funcs) { 503 if (show_funcs) {
503 print_funcs(); 504 print_funcs();
504 return; 505 return size;
505 } 506 }
506 if (show_printk) { 507 if (show_printk) {
507 print_printk(); 508 print_printk();
508 return; 509 return size;
509 } 510 }
510 511
511 return; 512 return size;
512} 513}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 81f2fd20a0ea..1f45d468fd9a 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -163,7 +163,7 @@ struct record *trace_read_data(int cpu);
163 163
164void parse_set_info(int nr_cpus, int long_sz); 164void parse_set_info(int nr_cpus, int long_sz);
165 165
166void trace_report(int fd); 166ssize_t trace_report(int fd);
167 167
168void *malloc_or_die(unsigned int size); 168void *malloc_or_die(unsigned int size);
169 169
@@ -259,6 +259,8 @@ void *raw_field_ptr(struct event *event, const char *name, void *data);
259unsigned long long eval_flag(const char *flag); 259unsigned long long eval_flag(const char *flag);
260 260
261int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); 261int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
262ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
263 int nb_events);
262 264
263/* taken from kernel/trace/trace.h */ 265/* taken from kernel/trace/trace.h */
264enum trace_flag_type { 266enum trace_flag_type {