aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-04-15 03:13:26 -0400
committerIngo Molnar <mingo@elte.hu>2010-04-15 03:13:26 -0400
commit84b13fd596522db47f9545d5124c30cc00dfdf5a (patch)
treec1f51b8fe43a59fb56ea43a18da88c0d0812dd7d
parentf92128193094c288bc315db1694fafeaeb7ee1d0 (diff)
parenta0cccc2e8e9fb16cbed3a117b30e3fbac3092ee3 (diff)
Merge branch 'perf/live' into perf/core
Conflicts: tools/perf/builtin-record.c Merge reason: add the live tracing feature, resolve conflict. Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-record.c68
-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/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-read.c89
-rw-r--r--tools/perf/util/trace-event.h4
35 files changed, 1184 insertions, 106 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ca2affc9233f..a1b99eeac3c0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -42,6 +42,7 @@ static unsigned int mmap_pages = 128;
42static unsigned int user_freq = UINT_MAX; 42static unsigned int user_freq = UINT_MAX;
43static int freq = 1000; 43static int freq = 1000;
44static int output; 44static int output;
45static int pipe_output = 0;
45static const char *output_name = "perf.data"; 46static const char *output_name = "perf.data";
46static int group = 0; 47static int group = 0;
47static unsigned int realtime_prio = 0; 48static unsigned int realtime_prio = 0;
@@ -109,6 +110,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
109 pc->data_tail = tail; 110 pc->data_tail = tail;
110} 111}
111 112
113static void advance_output(size_t size)
114{
115 bytes_written += size;
116}
117
112static void write_output(void *buf, size_t size) 118static void write_output(void *buf, size_t size)
113{ 119{
114 while (size) { 120 while (size) {
@@ -435,10 +441,19 @@ static int process_buildids(void)
435 441
436static void atexit_header(void) 442static void atexit_header(void)
437{ 443{
438 session->header.data_size += bytes_written; 444 if (!pipe_output) {
445 session->header.data_size += bytes_written;
439 446
440 process_buildids(); 447 process_buildids();
441 perf_header__write(&session->header, output, true); 448 perf_header__write(&session->header, output, true);
449 } else {
450 int err;
451
452 err = event__synthesize_build_ids(process_synthesized_event,
453 session);
454 if (err < 0)
455 pr_err("Couldn't synthesize build ids.\n");
456 }
442} 457}
443 458
444static int __cmd_record(int argc, const char **argv) 459static int __cmd_record(int argc, const char **argv)
@@ -464,7 +479,9 @@ static int __cmd_record(int argc, const char **argv)
464 exit(-1); 479 exit(-1);
465 } 480 }
466 481
467 if (!stat(output_name, &st) && st.st_size) { 482 if (!strcmp(output_name, "-"))
483 pipe_output = 1;
484 else if (!stat(output_name, &st) && st.st_size) {
468 if (write_mode == WRITE_FORCE) { 485 if (write_mode == WRITE_FORCE) {
469 char oldname[PATH_MAX]; 486 char oldname[PATH_MAX];
470 snprintf(oldname, sizeof(oldname), "%s.old", 487 snprintf(oldname, sizeof(oldname), "%s.old",
@@ -482,7 +499,10 @@ static int __cmd_record(int argc, const char **argv)
482 else 499 else
483 flags |= O_TRUNC; 500 flags |= O_TRUNC;
484 501
485 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);
486 if (output < 0) { 506 if (output < 0) {
487 perror("failed to create output file"); 507 perror("failed to create output file");
488 exit(-1); 508 exit(-1);
@@ -496,7 +516,7 @@ static int __cmd_record(int argc, const char **argv)
496 } 516 }
497 517
498 if (!file_new) { 518 if (!file_new) {
499 err = perf_header__read(&session->header, output); 519 err = perf_header__read(session, output);
500 if (err < 0) 520 if (err < 0)
501 return err; 521 return err;
502 } 522 }
@@ -522,6 +542,8 @@ static int __cmd_record(int argc, const char **argv)
522 } 542 }
523 543
524 if (!child_pid) { 544 if (!child_pid) {
545 if (pipe_output)
546 dup2(2, 1);
525 close(child_ready_pipe[0]); 547 close(child_ready_pipe[0]);
526 close(go_pipe[1]); 548 close(go_pipe[1]);
527 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 549 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
@@ -573,7 +595,11 @@ static int __cmd_record(int argc, const char **argv)
573 open_counters(cpumap[i]); 595 open_counters(cpumap[i]);
574 } 596 }
575 597
576 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) {
577 err = perf_header__write(&session->header, output, false); 603 err = perf_header__write(&session->header, output, false);
578 if (err < 0) 604 if (err < 0)
579 return err; 605 return err;
@@ -581,6 +607,34 @@ static int __cmd_record(int argc, const char **argv)
581 607
582 post_processing_offset = lseek(output, 0, SEEK_CUR); 608 post_processing_offset = lseek(output, 0, SEEK_CUR);
583 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
584 err = event__synthesize_kernel_mmap(process_synthesized_event, 638 err = event__synthesize_kernel_mmap(process_synthesized_event,
585 session, "_text"); 639 session, "_text");
586 if (err < 0) 640 if (err < 0)
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/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-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 {