diff options
| -rw-r--r-- | tools/perf/Makefile | 3 | ||||
| -rw-r--r-- | tools/perf/builtin-annotate.c | 15 | ||||
| -rw-r--r-- | tools/perf/builtin-buildid-list.c | 55 | ||||
| -rw-r--r-- | tools/perf/builtin-kmem.c | 13 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 25 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 20 | ||||
| -rw-r--r-- | tools/perf/builtin-sched.c | 13 | ||||
| -rw-r--r-- | tools/perf/builtin-timechart.c | 15 | ||||
| -rw-r--r-- | tools/perf/builtin-trace.c | 20 | ||||
| -rw-r--r-- | tools/perf/util/data_map.c | 71 | ||||
| -rw-r--r-- | tools/perf/util/data_map.h | 9 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 28 | ||||
| -rw-r--r-- | tools/perf/util/header.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 80 | ||||
| -rw-r--r-- | tools/perf/util/session.h | 16 |
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 | |||
| 356 | LIB_H += util/parse-events.h | 356 | LIB_H += util/parse-events.h |
| 357 | LIB_H += util/quote.h | 357 | LIB_H += util/quote.h |
| 358 | LIB_H += util/util.h | 358 | LIB_H += util/util.h |
| 359 | LIB_H += util/header.h | ||
| 359 | LIB_H += util/help.h | 360 | LIB_H += util/help.h |
| 361 | LIB_H += util/session.h | ||
| 360 | LIB_H += util/strbuf.h | 362 | LIB_H += util/strbuf.h |
| 361 | LIB_H += util/string.h | 363 | LIB_H += util/string.h |
| 362 | LIB_H += util/strlist.h | 364 | LIB_H += util/strlist.h |
| @@ -405,6 +407,7 @@ LIB_OBJS += util/callchain.o | |||
| 405 | LIB_OBJS += util/values.o | 407 | LIB_OBJS += util/values.o |
| 406 | LIB_OBJS += util/debug.o | 408 | LIB_OBJS += util/debug.o |
| 407 | LIB_OBJS += util/map.o | 409 | LIB_OBJS += util/map.o |
| 410 | LIB_OBJS += util/session.o | ||
| 408 | LIB_OBJS += util/thread.o | 411 | LIB_OBJS += util/thread.o |
| 409 | LIB_OBJS += util/trace-event-parse.o | 412 | LIB_OBJS += util/trace-event-parse.o |
| 410 | LIB_OBJS += util/trace-event-read.o | 413 | LIB_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 | ||
| 30 | static char const *input_name = "perf.data"; | 31 | static char const *input_name = "perf.data"; |
| @@ -462,21 +463,23 @@ static struct perf_file_handler file_handler = { | |||
| 462 | 463 | ||
| 463 | static int __cmd_annotate(void) | 464 | static 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(); |
| 495 | out_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 | ||
| 18 | static char const *input_name = "perf.data"; | 18 | static char const *input_name = "perf.data"; |
| @@ -55,56 +55,17 @@ static int perf_file_section__process_buildids(struct perf_file_section *self, | |||
| 55 | static int __cmd_buildid_list(void) | 55 | static 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); | ||
| 105 | out_close: | ||
| 106 | close(input); | ||
| 107 | out: | ||
| 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 | ||
| 21 | static char const *input_name = "perf.data"; | 22 | static char const *input_name = "perf.data"; |
| 22 | 23 | ||
| 23 | static struct perf_header *header; | ||
| 24 | static u64 sample_type; | 24 | static u64 sample_type; |
| 25 | 25 | ||
| 26 | static int alloc_flag; | 26 | static int alloc_flag; |
| @@ -367,11 +367,18 @@ static struct perf_file_handler file_handler = { | |||
| 367 | 367 | ||
| 368 | static int read_events(void) | 368 | static 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 | ||
| 377 | static double fragmentation(unsigned long n_req, unsigned long n_alloc) | 384 | static 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 | ||
| 63 | static int file_new = 1; | 64 | static int file_new = 1; |
| 64 | 65 | ||
| 65 | struct perf_header *header = NULL; | 66 | static struct perf_session *session; |
| 66 | 67 | ||
| 67 | struct mmap_data { | 68 | struct 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 | ||
| 396 | static void atexit_header(void) | 397 | static 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 | ||
| 403 | static int __cmd_record(int argc, const char **argv) | 404 | static 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 | ||
| 53 | static char callchain_default_opt[] = "fractal,0.5"; | 54 | static char callchain_default_opt[] = "fractal,0.5"; |
| 54 | 55 | ||
| 55 | static struct perf_header *header; | 56 | static struct perf_session *session; |
| 56 | 57 | ||
| 57 | static u64 sample_type; | 58 | static 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 | 804 | out_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 | ||
| 22 | static char const *input_name = "perf.data"; | 23 | static char const *input_name = "perf.data"; |
| 23 | 24 | ||
| 24 | static struct perf_header *header; | ||
| 25 | static u64 sample_type; | 25 | static u64 sample_type; |
| 26 | 26 | ||
| 27 | static char default_sort_order[] = "avg, max, switch, runtime"; | 27 | static char default_sort_order[] = "avg, max, switch, runtime"; |
| @@ -1663,11 +1663,18 @@ static struct perf_file_handler file_handler = { | |||
| 1663 | 1663 | ||
| 1664 | static int read_events(void) | 1664 | static 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 | ||
| 1673 | static void print_bad_events(void) | 1680 | static 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 | ||
| 1060 | static int __cmd_timechart(void) | 1060 | static 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 | 1084 | out_delete: | |
| 1083 | return EXIT_SUCCESS; | 1085 | perf_session__delete(session); |
| 1086 | return ret; | ||
| 1084 | } | 1087 | } |
| 1085 | 1088 | ||
| 1086 | static const char * const timechart_usage[] = { | 1089 | static 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 | ||
| 11 | static char const *script_name; | 12 | static char const *script_name; |
| 12 | static char const *generate_script_lang; | 13 | static char const *generate_script_lang; |
| @@ -61,7 +62,7 @@ static int cleanup_scripting(void) | |||
| 61 | 62 | ||
| 62 | static char const *input_name = "perf.data"; | 63 | static char const *input_name = "perf.data"; |
| 63 | 64 | ||
| 64 | static struct perf_header *header; | 65 | static struct perf_session *session; |
| 65 | static u64 sample_type; | 66 | static u64 sample_type; |
| 66 | 67 | ||
| 67 | static int process_sample_event(event_t *event) | 68 | static int process_sample_event(event_t *event) |
| @@ -126,11 +127,18 @@ static struct perf_file_handler file_handler = { | |||
| 126 | 127 | ||
| 127 | static int __cmd_trace(void) | 128 | static 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 | ||
| 136 | struct script_spec { | 144 | struct 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 | ||
| 132 | int mmap_dispatch_perf_file(struct perf_header **pheader, | 132 | int 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 | ||
| 220 | remap: | 176 | remap: |
| 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 | ||
| 229 | more: | 185 | more: |
| @@ -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 | ||
| 282 | done: | 238 | done: |
| 283 | err = 0; | 239 | err = 0; |
| 284 | out_close: | 240 | out_err: |
| 285 | close(input); | ||
| 286 | |||
| 287 | return err; | 241 | return err; |
| 288 | out_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 | ||
| 7 | typedef int (*event_type_handler_t)(event_t *); | 8 | typedef int (*event_type_handler_t)(event_t *); |
| 8 | 9 | ||
| @@ -21,12 +22,8 @@ struct perf_file_handler { | |||
| 21 | }; | 22 | }; |
| 22 | 23 | ||
| 23 | void register_perf_file_handler(struct perf_file_handler *handler); | 24 | void register_perf_file_handler(struct perf_file_handler *handler); |
| 24 | int mmap_dispatch_perf_file(struct perf_header **pheader, | 25 | int 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); | ||
| 30 | int perf_header__read_build_ids(int input, u64 offset, u64 file_size); | 27 | int 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 | /* | 61 | int perf_header__init(struct perf_header *self) |
| 62 | * Create new perf.data header: | ||
| 63 | */ | ||
| 64 | struct 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 | ||
| 81 | void perf_header__delete(struct perf_header *self) | 68 | void 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 | ||
| 92 | int perf_header__add_attr(struct perf_header *self, | 76 | int 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 | ||
| 58 | struct perf_header *perf_header__new(void); | 58 | int perf_header__init(struct perf_header *self); |
| 59 | void perf_header__delete(struct perf_header *self); | 59 | void perf_header__exit(struct perf_header *self); |
| 60 | 60 | ||
| 61 | int perf_header__read(struct perf_header *self, int fd); | 61 | int perf_header__read(struct perf_header *self, int fd); |
| 62 | int perf_header__write(struct perf_header *self, int fd, bool at_exit); | 62 | int 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 | |||
| 9 | static 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 | |||
| 45 | out_close: | ||
| 46 | close(self->fd); | ||
| 47 | self->fd = -1; | ||
| 48 | return -1; | ||
| 49 | } | ||
| 50 | |||
| 51 | struct 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 | } | ||
| 68 | out: | ||
| 69 | return self; | ||
| 70 | out_delete: | ||
| 71 | free(self); | ||
| 72 | return NULL; | ||
| 73 | } | ||
| 74 | |||
| 75 | void 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 | |||
| 6 | struct perf_session { | ||
| 7 | struct perf_header header; | ||
| 8 | unsigned long size; | ||
| 9 | int fd; | ||
| 10 | char filename[0]; | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct perf_session *perf_session__new(const char *filename, int mode, bool force); | ||
| 14 | void perf_session__delete(struct perf_session *self); | ||
| 15 | |||
| 16 | #endif /* __PERF_SESSION_H */ | ||
