aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-12-11 18:24:02 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-12 01:42:12 -0500
commit94c744b6c0c6c5802a85ebfebbec429ac5851f2b (patch)
treee34dcaca54f1d7752ab1e7974bb73f94ff3cf94c /tools/perf
parentea08d8cbd162fe3756e3e2298efbe0b8b12f92d1 (diff)
perf tools: Introduce perf_session class
That does all the initialization boilerplate, opening the file, reading the header, checking if it is valid, etc. And that will as well have the threads list, kmap (now) global variable, etc, so that we can handle two (or more) perf.data files describing sessions to compare. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1260573842-19720-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile3
-rw-r--r--tools/perf/builtin-annotate.c15
-rw-r--r--tools/perf/builtin-buildid-list.c55
-rw-r--r--tools/perf/builtin-kmem.c13
-rw-r--r--tools/perf/builtin-record.c25
-rw-r--r--tools/perf/builtin-report.c20
-rw-r--r--tools/perf/builtin-sched.c13
-rw-r--r--tools/perf/builtin-timechart.c15
-rw-r--r--tools/perf/builtin-trace.c20
-rw-r--r--tools/perf/util/data_map.c71
-rw-r--r--tools/perf/util/data_map.h9
-rw-r--r--tools/perf/util/header.c28
-rw-r--r--tools/perf/util/header.h4
-rw-r--r--tools/perf/util/session.c80
-rw-r--r--tools/perf/util/session.h16
15 files changed, 206 insertions, 181 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e2ee3b589af7..406999668cab 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -356,7 +356,9 @@ LIB_H += util/parse-options.h
356LIB_H += util/parse-events.h 356LIB_H += util/parse-events.h
357LIB_H += util/quote.h 357LIB_H += util/quote.h
358LIB_H += util/util.h 358LIB_H += util/util.h
359LIB_H += util/header.h
359LIB_H += util/help.h 360LIB_H += util/help.h
361LIB_H += util/session.h
360LIB_H += util/strbuf.h 362LIB_H += util/strbuf.h
361LIB_H += util/string.h 363LIB_H += util/string.h
362LIB_H += util/strlist.h 364LIB_H += util/strlist.h
@@ -405,6 +407,7 @@ LIB_OBJS += util/callchain.o
405LIB_OBJS += util/values.o 407LIB_OBJS += util/values.o
406LIB_OBJS += util/debug.o 408LIB_OBJS += util/debug.o
407LIB_OBJS += util/map.o 409LIB_OBJS += util/map.o
410LIB_OBJS += util/session.o
408LIB_OBJS += util/thread.o 411LIB_OBJS += util/thread.o
409LIB_OBJS += util/trace-event-parse.o 412LIB_OBJS += util/trace-event-parse.o
410LIB_OBJS += util/trace-event-read.o 413LIB_OBJS += util/trace-event-read.o
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 0bf2e8f9af57..21a78d30d53d 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -25,6 +25,7 @@
25#include "util/thread.h" 25#include "util/thread.h"
26#include "util/sort.h" 26#include "util/sort.h"
27#include "util/hist.h" 27#include "util/hist.h"
28#include "util/session.h"
28#include "util/data_map.h" 29#include "util/data_map.h"
29 30
30static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
@@ -462,21 +463,23 @@ static struct perf_file_handler file_handler = {
462 463
463static int __cmd_annotate(void) 464static int __cmd_annotate(void)
464{ 465{
465 struct perf_header *header; 466 struct perf_session *session = perf_session__new(input_name, O_RDONLY, force);
466 struct thread *idle; 467 struct thread *idle;
467 int ret; 468 int ret;
468 469
470 if (session == NULL)
471 return -ENOMEM;
472
469 idle = register_idle_thread(); 473 idle = register_idle_thread();
470 register_perf_file_handler(&file_handler); 474 register_perf_file_handler(&file_handler);
471 475
472 ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, 476 ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
473 &event__cwdlen, &event__cwd);
474 if (ret) 477 if (ret)
475 return ret; 478 goto out_delete;
476 479
477 if (dump_trace) { 480 if (dump_trace) {
478 event__print_totals(); 481 event__print_totals();
479 return 0; 482 goto out_delete;
480 } 483 }
481 484
482 if (verbose > 3) 485 if (verbose > 3)
@@ -489,6 +492,8 @@ static int __cmd_annotate(void)
489 output__resort(event__total[0]); 492 output__resort(event__total[0]);
490 493
491 find_annotations(); 494 find_annotations();
495out_delete:
496 perf_session__delete(session);
492 497
493 return ret; 498 return ret;
494} 499}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index dcb6143a0002..bfd16a1594e4 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -11,8 +11,8 @@
11#include "util/cache.h" 11#include "util/cache.h"
12#include "util/data_map.h" 12#include "util/data_map.h"
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/header.h"
15#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/session.h"
16#include "util/symbol.h" 16#include "util/symbol.h"
17 17
18static char const *input_name = "perf.data"; 18static char const *input_name = "perf.data";
@@ -55,56 +55,17 @@ static int perf_file_section__process_buildids(struct perf_file_section *self,
55static int __cmd_buildid_list(void) 55static int __cmd_buildid_list(void)
56{ 56{
57 int err = -1; 57 int err = -1;
58 struct perf_header *header; 58 struct perf_session *session = perf_session__new(input_name, O_RDONLY, force);
59 struct perf_file_header f_header;
60 struct stat input_stat;
61 int input = open(input_name, O_RDONLY);
62 59
63 if (input < 0) { 60 if (session == NULL)
64 pr_err("failed to open file: %s", input_name); 61 return -1;
65 if (!strcmp(input_name, "perf.data"))
66 pr_err(" (try 'perf record' first)");
67 pr_err("\n");
68 goto out;
69 }
70
71 err = fstat(input, &input_stat);
72 if (err < 0) {
73 perror("failed to stat file");
74 goto out_close;
75 }
76
77 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
78 pr_err("file %s not owned by current user or root\n",
79 input_name);
80 goto out_close;
81 }
82
83 if (!input_stat.st_size) {
84 pr_info("zero-sized file, nothing to do!\n");
85 goto out_close;
86 }
87
88 err = -1;
89 header = perf_header__new();
90 if (header == NULL)
91 goto out_close;
92
93 if (perf_file_header__read(&f_header, header, input) < 0) {
94 pr_warning("incompatible file format");
95 goto out_close;
96 }
97 62
98 err = perf_header__process_sections(header, input, 63 err = perf_header__process_sections(&session->header, session->fd,
99 perf_file_section__process_buildids); 64 perf_file_section__process_buildids);
65 if (err >= 0)
66 dsos__fprintf_buildid(stdout);
100 67
101 if (err < 0) 68 perf_session__delete(session);
102 goto out_close;
103
104 dsos__fprintf_buildid(stdout);
105out_close:
106 close(input);
107out:
108 return err; 69 return err;
109} 70}
110 71
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index fe73435192b3..2071d2485913 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -6,6 +6,7 @@
6#include "util/symbol.h" 6#include "util/symbol.h"
7#include "util/thread.h" 7#include "util/thread.h"
8#include "util/header.h" 8#include "util/header.h"
9#include "util/session.h"
9 10
10#include "util/parse-options.h" 11#include "util/parse-options.h"
11#include "util/trace-event.h" 12#include "util/trace-event.h"
@@ -20,7 +21,6 @@ typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
20 21
21static char const *input_name = "perf.data"; 22static char const *input_name = "perf.data";
22 23
23static struct perf_header *header;
24static u64 sample_type; 24static u64 sample_type;
25 25
26static int alloc_flag; 26static int alloc_flag;
@@ -367,11 +367,18 @@ static struct perf_file_handler file_handler = {
367 367
368static int read_events(void) 368static int read_events(void)
369{ 369{
370 int err;
371 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
372
373 if (session == NULL)
374 return -ENOMEM;
375
370 register_idle_thread(); 376 register_idle_thread();
371 register_perf_file_handler(&file_handler); 377 register_perf_file_handler(&file_handler);
372 378
373 return mmap_dispatch_perf_file(&header, input_name, 0, 0, 379 err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
374 &event__cwdlen, &event__cwd); 380 perf_session__delete(session);
381 return err;
375} 382}
376 383
377static double fragmentation(unsigned long n_req, unsigned long n_alloc) 384static double fragmentation(unsigned long n_req, unsigned long n_alloc)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0e519c667e3a..4decbd14eaed 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -17,6 +17,7 @@
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h" 18#include "util/event.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/session.h"
20#include "util/symbol.h" 21#include "util/symbol.h"
21 22
22#include <unistd.h> 23#include <unistd.h>
@@ -62,7 +63,7 @@ static int nr_cpu = 0;
62 63
63static int file_new = 1; 64static int file_new = 1;
64 65
65struct perf_header *header = NULL; 66static struct perf_session *session;
66 67
67struct mmap_data { 68struct mmap_data {
68 int counter; 69 int counter;
@@ -216,12 +217,12 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
216{ 217{
217 struct perf_header_attr *h_attr; 218 struct perf_header_attr *h_attr;
218 219
219 if (nr < header->attrs) { 220 if (nr < session->header.attrs) {
220 h_attr = header->attr[nr]; 221 h_attr = session->header.attr[nr];
221 } else { 222 } else {
222 h_attr = perf_header_attr__new(a); 223 h_attr = perf_header_attr__new(a);
223 if (h_attr != NULL) 224 if (h_attr != NULL)
224 if (perf_header__add_attr(header, h_attr) < 0) { 225 if (perf_header__add_attr(&session->header, h_attr) < 0) {
225 perf_header_attr__delete(h_attr); 226 perf_header_attr__delete(h_attr);
226 h_attr = NULL; 227 h_attr = NULL;
227 } 228 }
@@ -395,9 +396,9 @@ static void open_counters(int cpu, pid_t pid)
395 396
396static void atexit_header(void) 397static void atexit_header(void)
397{ 398{
398 header->data_size += bytes_written; 399 session->header.data_size += bytes_written;
399 400
400 perf_header__write(header, output, true); 401 perf_header__write(&session->header, output, true);
401} 402}
402 403
403static int __cmd_record(int argc, const char **argv) 404static int __cmd_record(int argc, const char **argv)
@@ -440,24 +441,24 @@ static int __cmd_record(int argc, const char **argv)
440 exit(-1); 441 exit(-1);
441 } 442 }
442 443
443 header = perf_header__new(); 444 session = perf_session__new(output_name, O_WRONLY, force);
444 if (header == NULL) { 445 if (session == NULL) {
445 pr_err("Not enough memory for reading perf file header\n"); 446 pr_err("Not enough memory for reading perf file header\n");
446 return -1; 447 return -1;
447 } 448 }
448 449
449 if (!file_new) { 450 if (!file_new) {
450 err = perf_header__read(header, output); 451 err = perf_header__read(&session->header, output);
451 if (err < 0) 452 if (err < 0)
452 return err; 453 return err;
453 } 454 }
454 455
455 if (raw_samples) { 456 if (raw_samples) {
456 perf_header__set_feat(header, HEADER_TRACE_INFO); 457 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
457 } else { 458 } else {
458 for (i = 0; i < nr_counters; i++) { 459 for (i = 0; i < nr_counters; i++) {
459 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 460 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
460 perf_header__set_feat(header, HEADER_TRACE_INFO); 461 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
461 break; 462 break;
462 } 463 }
463 } 464 }
@@ -481,7 +482,7 @@ static int __cmd_record(int argc, const char **argv)
481 } 482 }
482 483
483 if (file_new) { 484 if (file_new) {
484 err = perf_header__write(header, output, false); 485 err = perf_header__write(&session->header, output, false);
485 if (err < 0) 486 if (err < 0)
486 return err; 487 return err;
487 } 488 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2b9eb3a553ed..e2ec49a9b731 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -22,6 +22,7 @@
22#include "perf.h" 22#include "perf.h"
23#include "util/debug.h" 23#include "util/debug.h"
24#include "util/header.h" 24#include "util/header.h"
25#include "util/session.h"
25 26
26#include "util/parse-options.h" 27#include "util/parse-options.h"
27#include "util/parse-events.h" 28#include "util/parse-events.h"
@@ -52,7 +53,7 @@ static int exclude_other = 1;
52 53
53static char callchain_default_opt[] = "fractal,0.5"; 54static char callchain_default_opt[] = "fractal,0.5";
54 55
55static struct perf_header *header; 56static struct perf_session *session;
56 57
57static u64 sample_type; 58static u64 sample_type;
58 59
@@ -701,7 +702,7 @@ static int process_read_event(event_t *event)
701{ 702{
702 struct perf_event_attr *attr; 703 struct perf_event_attr *attr;
703 704
704 attr = perf_header__find_attr(event->read.id, header); 705 attr = perf_header__find_attr(event->read.id, &session->header);
705 706
706 if (show_threads) { 707 if (show_threads) {
707 const char *name = attr ? __event_name(attr->type, attr->config) 708 const char *name = attr ? __event_name(attr->type, attr->config)
@@ -766,6 +767,10 @@ static int __cmd_report(void)
766 struct thread *idle; 767 struct thread *idle;
767 int ret; 768 int ret;
768 769
770 session = perf_session__new(input_name, O_RDONLY, force);
771 if (session == NULL)
772 return -ENOMEM;
773
769 idle = register_idle_thread(); 774 idle = register_idle_thread();
770 thread__comm_adjust(idle); 775 thread__comm_adjust(idle);
771 776
@@ -774,14 +779,14 @@ static int __cmd_report(void)
774 779
775 register_perf_file_handler(&file_handler); 780 register_perf_file_handler(&file_handler);
776 781
777 ret = mmap_dispatch_perf_file(&header, input_name, force, 782 ret = perf_session__process_events(session, full_paths,
778 full_paths, &event__cwdlen, &event__cwd); 783 &event__cwdlen, &event__cwd);
779 if (ret) 784 if (ret)
780 return ret; 785 goto out_delete;
781 786
782 if (dump_trace) { 787 if (dump_trace) {
783 event__print_totals(); 788 event__print_totals();
784 return 0; 789 goto out_delete;
785 } 790 }
786 791
787 if (verbose > 3) 792 if (verbose > 3)
@@ -796,7 +801,8 @@ static int __cmd_report(void)
796 801
797 if (show_threads) 802 if (show_threads)
798 perf_read_values_destroy(&show_threads_values); 803 perf_read_values_destroy(&show_threads_values);
799 804out_delete:
805 perf_session__delete(session);
800 return ret; 806 return ret;
801} 807}
802 808
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 7cca7c15b40a..65021fe1361e 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -6,6 +6,7 @@
6#include "util/symbol.h" 6#include "util/symbol.h"
7#include "util/thread.h" 7#include "util/thread.h"
8#include "util/header.h" 8#include "util/header.h"
9#include "util/session.h"
9 10
10#include "util/parse-options.h" 11#include "util/parse-options.h"
11#include "util/trace-event.h" 12#include "util/trace-event.h"
@@ -21,7 +22,6 @@
21 22
22static char const *input_name = "perf.data"; 23static char const *input_name = "perf.data";
23 24
24static struct perf_header *header;
25static u64 sample_type; 25static u64 sample_type;
26 26
27static char default_sort_order[] = "avg, max, switch, runtime"; 27static char default_sort_order[] = "avg, max, switch, runtime";
@@ -1663,11 +1663,18 @@ static struct perf_file_handler file_handler = {
1663 1663
1664static int read_events(void) 1664static int read_events(void)
1665{ 1665{
1666 int err;
1667 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
1668
1669 if (session == NULL)
1670 return -ENOMEM;
1671
1666 register_idle_thread(); 1672 register_idle_thread();
1667 register_perf_file_handler(&file_handler); 1673 register_perf_file_handler(&file_handler);
1668 1674
1669 return mmap_dispatch_perf_file(&header, input_name, 0, 0, 1675 err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
1670 &event__cwdlen, &event__cwd); 1676 perf_session__delete(session);
1677 return err;
1671} 1678}
1672 1679
1673static void print_bad_events(void) 1680static void print_bad_events(void)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index f472df9561ee..759dd2b35fdb 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1059,15 +1059,17 @@ static struct perf_file_handler file_handler = {
1059 1059
1060static int __cmd_timechart(void) 1060static int __cmd_timechart(void)
1061{ 1061{
1062 struct perf_header *header; 1062 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
1063 int ret; 1063 int ret;
1064 1064
1065 if (session == NULL)
1066 return -ENOMEM;
1067
1065 register_perf_file_handler(&file_handler); 1068 register_perf_file_handler(&file_handler);
1066 1069
1067 ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, 1070 ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
1068 &event__cwdlen, &event__cwd);
1069 if (ret) 1071 if (ret)
1070 return EXIT_FAILURE; 1072 goto out_delete;
1071 1073
1072 process_samples(); 1074 process_samples();
1073 1075
@@ -1079,8 +1081,9 @@ static int __cmd_timechart(void)
1079 1081
1080 pr_info("Written %2.1f seconds of trace to %s.\n", 1082 pr_info("Written %2.1f seconds of trace to %s.\n",
1081 (last_time - first_time) / 1000000000.0, output_name); 1083 (last_time - first_time) / 1000000000.0, output_name);
1082 1084out_delete:
1083 return EXIT_SUCCESS; 1085 perf_session__delete(session);
1086 return ret;
1084} 1087}
1085 1088
1086static const char * const timechart_usage[] = { 1089static const char * const timechart_usage[] = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c2fcc34486f5..0756664666f1 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -7,6 +7,7 @@
7#include "util/header.h" 7#include "util/header.h"
8#include "util/exec_cmd.h" 8#include "util/exec_cmd.h"
9#include "util/trace-event.h" 9#include "util/trace-event.h"
10#include "util/session.h"
10 11
11static char const *script_name; 12static char const *script_name;
12static char const *generate_script_lang; 13static char const *generate_script_lang;
@@ -61,7 +62,7 @@ static int cleanup_scripting(void)
61 62
62static char const *input_name = "perf.data"; 63static char const *input_name = "perf.data";
63 64
64static struct perf_header *header; 65static struct perf_session *session;
65static u64 sample_type; 66static u64 sample_type;
66 67
67static int process_sample_event(event_t *event) 68static int process_sample_event(event_t *event)
@@ -126,11 +127,18 @@ static struct perf_file_handler file_handler = {
126 127
127static int __cmd_trace(void) 128static int __cmd_trace(void)
128{ 129{
130 int err;
131
132 session = perf_session__new(input_name, O_RDONLY, 0);
133 if (session == NULL)
134 return -ENOMEM;
135
129 register_idle_thread(); 136 register_idle_thread();
130 register_perf_file_handler(&file_handler); 137 register_perf_file_handler(&file_handler);
131 138
132 return mmap_dispatch_perf_file(&header, input_name, 139 err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
133 0, 0, &event__cwdlen, &event__cwd); 140 perf_session__delete(session);
141 return err;
134} 142}
135 143
136struct script_spec { 144struct script_spec {
@@ -348,11 +356,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
348 return -1; 356 return -1;
349 } 357 }
350 358
351 header = perf_header__new(); 359 perf_header__read(&session->header, input);
352 if (header == NULL)
353 return -1;
354
355 perf_header__read(header, input);
356 err = scripting_ops->generate_script("perf-trace"); 360 err = scripting_ops->generate_script("perf-trace");
357 goto out; 361 goto out;
358 } 362 }
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index 59b65d0bd7c1..6d46dda53a29 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -129,23 +129,16 @@ out:
129 return err; 129 return err;
130} 130}
131 131
132int mmap_dispatch_perf_file(struct perf_header **pheader, 132int perf_session__process_events(struct perf_session *self,
133 const char *input_name, 133 int full_paths, int *cwdlen, char **cwd)
134 int force,
135 int full_paths,
136 int *cwdlen,
137 char **cwd)
138{ 134{
139 int err; 135 int err;
140 struct perf_header *header;
141 unsigned long head, shift; 136 unsigned long head, shift;
142 unsigned long offset = 0; 137 unsigned long offset = 0;
143 struct stat input_stat;
144 size_t page_size; 138 size_t page_size;
145 u64 sample_type; 139 u64 sample_type;
146 event_t *event; 140 event_t *event;
147 uint32_t size; 141 uint32_t size;
148 int input;
149 char *buf; 142 char *buf;
150 143
151 if (curr_handler == NULL) { 144 if (curr_handler == NULL) {
@@ -155,56 +148,19 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
155 148
156 page_size = getpagesize(); 149 page_size = getpagesize();
157 150
158 input = open(input_name, O_RDONLY); 151 head = self->header.data_offset;
159 if (input < 0) { 152 sample_type = perf_header__sample_type(&self->header);
160 pr_err("Failed to open file: %s", input_name);
161 if (!strcmp(input_name, "perf.data"))
162 pr_err(" (try 'perf record' first)");
163 pr_err("\n");
164 return -errno;
165 }
166
167 if (fstat(input, &input_stat) < 0) {
168 pr_err("failed to stat file");
169 err = -errno;
170 goto out_close;
171 }
172
173 err = -EACCES;
174 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
175 pr_err("file: %s not owned by current user or root\n",
176 input_name);
177 goto out_close;
178 }
179
180 if (input_stat.st_size == 0) {
181 pr_info("zero-sized file, nothing to do!\n");
182 goto done;
183 }
184
185 err = -ENOMEM;
186 header = perf_header__new();
187 if (header == NULL)
188 goto out_close;
189
190 err = perf_header__read(header, input);
191 if (err < 0)
192 goto out_delete;
193 *pheader = header;
194 head = header->data_offset;
195
196 sample_type = perf_header__sample_type(header);
197 153
198 err = -EINVAL; 154 err = -EINVAL;
199 if (curr_handler->sample_type_check && 155 if (curr_handler->sample_type_check &&
200 curr_handler->sample_type_check(sample_type) < 0) 156 curr_handler->sample_type_check(sample_type) < 0)
201 goto out_delete; 157 goto out_err;
202 158
203 if (!full_paths) { 159 if (!full_paths) {
204 if (getcwd(__cwd, sizeof(__cwd)) == NULL) { 160 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
205 pr_err("failed to get the current directory\n"); 161 pr_err("failed to get the current directory\n");
206 err = -errno; 162 err = -errno;
207 goto out_delete; 163 goto out_err;
208 } 164 }
209 *cwd = __cwd; 165 *cwd = __cwd;
210 *cwdlen = strlen(*cwd); 166 *cwdlen = strlen(*cwd);
@@ -219,11 +175,11 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
219 175
220remap: 176remap:
221 buf = mmap(NULL, page_size * mmap_window, PROT_READ, 177 buf = mmap(NULL, page_size * mmap_window, PROT_READ,
222 MAP_SHARED, input, offset); 178 MAP_SHARED, self->fd, offset);
223 if (buf == MAP_FAILED) { 179 if (buf == MAP_FAILED) {
224 pr_err("failed to mmap file\n"); 180 pr_err("failed to mmap file\n");
225 err = -errno; 181 err = -errno;
226 goto out_delete; 182 goto out_err;
227 } 183 }
228 184
229more: 185more:
@@ -273,19 +229,14 @@ more:
273 229
274 head += size; 230 head += size;
275 231
276 if (offset + head >= header->data_offset + header->data_size) 232 if (offset + head >= self->header.data_offset + self->header.data_size)
277 goto done; 233 goto done;
278 234
279 if (offset + head < (unsigned long)input_stat.st_size) 235 if (offset + head < self->size)
280 goto more; 236 goto more;
281 237
282done: 238done:
283 err = 0; 239 err = 0;
284out_close: 240out_err:
285 close(input);
286
287 return err; 241 return err;
288out_delete:
289 perf_header__delete(header);
290 goto out_close;
291} 242}
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index 258a87bcc4fb..98c5b823388c 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -3,6 +3,7 @@
3 3
4#include "event.h" 4#include "event.h"
5#include "header.h" 5#include "header.h"
6#include "session.h"
6 7
7typedef int (*event_type_handler_t)(event_t *); 8typedef int (*event_type_handler_t)(event_t *);
8 9
@@ -21,12 +22,8 @@ struct perf_file_handler {
21}; 22};
22 23
23void register_perf_file_handler(struct perf_file_handler *handler); 24void register_perf_file_handler(struct perf_file_handler *handler);
24int mmap_dispatch_perf_file(struct perf_header **pheader, 25int perf_session__process_events(struct perf_session *self,
25 const char *input_name, 26 int full_paths, int *cwdlen, char **cwd);
26 int force,
27 int full_paths,
28 int *cwdlen,
29 char **cwd);
30int perf_header__read_build_ids(int input, u64 offset, u64 file_size); 27int perf_header__read_build_ids(int input, u64 offset, u64 file_size);
31 28
32#endif 29#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 59a9c0b3033e..f2e8d8715111 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -58,35 +58,19 @@ int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
58 return 0; 58 return 0;
59} 59}
60 60
61/* 61int perf_header__init(struct perf_header *self)
62 * Create new perf.data header:
63 */
64struct perf_header *perf_header__new(void)
65{ 62{
66 struct perf_header *self = zalloc(sizeof(*self)); 63 self->size = 1;
67 64 self->attr = malloc(sizeof(void *));
68 if (self != NULL) { 65 return self->attr == NULL ? -ENOMEM : 0;
69 self->size = 1;
70 self->attr = malloc(sizeof(void *));
71
72 if (self->attr == NULL) {
73 free(self);
74 self = NULL;
75 }
76 }
77
78 return self;
79} 66}
80 67
81void perf_header__delete(struct perf_header *self) 68void perf_header__exit(struct perf_header *self)
82{ 69{
83 int i; 70 int i;
84
85 for (i = 0; i < self->attrs; ++i) 71 for (i = 0; i < self->attrs; ++i)
86 perf_header_attr__delete(self->attr[i]); 72 perf_header_attr__delete(self->attr[i]);
87
88 free(self->attr); 73 free(self->attr);
89 free(self);
90} 74}
91 75
92int perf_header__add_attr(struct perf_header *self, 76int perf_header__add_attr(struct perf_header *self,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d1dbe2b79c42..d118d05d3abe 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -55,8 +55,8 @@ struct perf_header {
55 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); 55 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
56}; 56};
57 57
58struct perf_header *perf_header__new(void); 58int perf_header__init(struct perf_header *self);
59void perf_header__delete(struct perf_header *self); 59void perf_header__exit(struct perf_header *self);
60 60
61int perf_header__read(struct perf_header *self, int fd); 61int perf_header__read(struct perf_header *self, int fd);
62int perf_header__write(struct perf_header *self, int fd, bool at_exit); 62int perf_header__write(struct perf_header *self, int fd, bool at_exit);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
new file mode 100644
index 000000000000..707ce1cb1621
--- /dev/null
+++ b/tools/perf/util/session.c
@@ -0,0 +1,80 @@
1#include <linux/kernel.h>
2
3#include <unistd.h>
4#include <sys/types.h>
5
6#include "session.h"
7#include "util.h"
8
9static int perf_session__open(struct perf_session *self, bool force)
10{
11 struct stat input_stat;
12
13 self->fd = open(self->filename, O_RDONLY);
14 if (self->fd < 0) {
15 pr_err("failed to open file: %s", self->filename);
16 if (!strcmp(self->filename, "perf.data"))
17 pr_err(" (try 'perf record' first)");
18 pr_err("\n");
19 return -errno;
20 }
21
22 if (fstat(self->fd, &input_stat) < 0)
23 goto out_close;
24
25 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
26 pr_err("file %s not owned by current user or root\n",
27 self->filename);
28 goto out_close;
29 }
30
31 if (!input_stat.st_size) {
32 pr_info("zero-sized file (%s), nothing to do!\n",
33 self->filename);
34 goto out_close;
35 }
36
37 if (perf_header__read(&self->header, self->fd) < 0) {
38 pr_err("incompatible file format");
39 goto out_close;
40 }
41
42 self->size = input_stat.st_size;
43 return 0;
44
45out_close:
46 close(self->fd);
47 self->fd = -1;
48 return -1;
49}
50
51struct perf_session *perf_session__new(const char *filename, int mode, bool force)
52{
53 size_t len = strlen(filename) + 1;
54 struct perf_session *self = zalloc(sizeof(*self) + len);
55
56 if (self == NULL)
57 goto out;
58
59 if (perf_header__init(&self->header) < 0)
60 goto out_delete;
61
62 memcpy(self->filename, filename, len);
63
64 if (mode == O_RDONLY && perf_session__open(self, force) < 0) {
65 perf_session__delete(self);
66 self = NULL;
67 }
68out:
69 return self;
70out_delete:
71 free(self);
72 return NULL;
73}
74
75void perf_session__delete(struct perf_session *self)
76{
77 perf_header__exit(&self->header);
78 close(self->fd);
79 free(self);
80}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
new file mode 100644
index 000000000000..f3699c8c8ed4
--- /dev/null
+++ b/tools/perf/util/session.h
@@ -0,0 +1,16 @@
1#ifndef __PERF_SESSION_H
2#define __PERF_SESSION_H
3
4#include "header.h"
5
6struct perf_session {
7 struct perf_header header;
8 unsigned long size;
9 int fd;
10 char filename[0];
11};
12
13struct perf_session *perf_session__new(const char *filename, int mode, bool force);
14void perf_session__delete(struct perf_session *self);
15
16#endif /* __PERF_SESSION_H */