diff options
| -rw-r--r-- | tools/perf/builtin-record.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/event.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 78 | ||||
| -rw-r--r-- | tools/perf/util/header.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 135 | ||||
| -rw-r--r-- | tools/perf/util/session.h | 4 |
6 files changed, 202 insertions, 29 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 9a9513687235..d060fc50c8a4 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -487,7 +487,7 @@ static int __cmd_record(int argc, const char **argv) | |||
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | if (!file_new) { | 489 | if (!file_new) { |
| 490 | err = perf_header__read(&session->header, output); | 490 | err = perf_header__read(session, output); |
| 491 | if (err < 0) | 491 | if (err < 0) |
| 492 | return err; | 492 | return err; |
| 493 | } | 493 | } |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 7f7cf8539cfe..5c1eba671305 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
| @@ -83,6 +83,10 @@ struct build_id_event { | |||
| 83 | char filename[]; | 83 | char filename[]; |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | enum perf_header_event_type { /* above any possible kernel type */ | ||
| 87 | PERF_RECORD_HEADER_MAX = 64, | ||
| 88 | }; | ||
| 89 | |||
| 86 | typedef union event_union { | 90 | typedef union event_union { |
| 87 | struct perf_event_header header; | 91 | struct perf_event_header header; |
| 88 | struct ip_event ip; | 92 | struct ip_event ip; |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6c9aa16ee51f..8d05337d1a59 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -427,6 +427,25 @@ out_free: | |||
| 427 | return err; | 427 | return err; |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | int perf_header__write_pipe(int fd) | ||
| 431 | { | ||
| 432 | struct perf_pipe_file_header f_header; | ||
| 433 | int err; | ||
| 434 | |||
| 435 | f_header = (struct perf_pipe_file_header){ | ||
| 436 | .magic = PERF_MAGIC, | ||
| 437 | .size = sizeof(f_header), | ||
| 438 | }; | ||
| 439 | |||
| 440 | err = do_write(fd, &f_header, sizeof(f_header)); | ||
| 441 | if (err < 0) { | ||
| 442 | pr_debug("failed to write perf pipe header\n"); | ||
| 443 | return err; | ||
| 444 | } | ||
| 445 | |||
| 446 | return 0; | ||
| 447 | } | ||
| 448 | |||
| 430 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) | 449 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) |
| 431 | { | 450 | { |
| 432 | struct perf_file_header f_header; | 451 | struct perf_file_header f_header; |
| @@ -518,25 +537,10 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
| 518 | return 0; | 537 | return 0; |
| 519 | } | 538 | } |
| 520 | 539 | ||
| 521 | static 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 | |||
| 536 | static int perf_header__getbuffer64(struct perf_header *self, | 540 | static int perf_header__getbuffer64(struct perf_header *self, |
| 537 | int fd, void *buf, size_t size) | 541 | int fd, void *buf, size_t size) |
| 538 | { | 542 | { |
| 539 | if (do_read(fd, buf, size)) | 543 | if (do_read(fd, buf, size) <= 0) |
| 540 | return -1; | 544 | return -1; |
| 541 | 545 | ||
| 542 | if (self->needs_swap) | 546 | if (self->needs_swap) |
| @@ -592,7 +596,7 @@ int perf_file_header__read(struct perf_file_header *self, | |||
| 592 | { | 596 | { |
| 593 | lseek(fd, 0, SEEK_SET); | 597 | lseek(fd, 0, SEEK_SET); |
| 594 | 598 | ||
| 595 | if (do_read(fd, self, sizeof(*self)) || | 599 | if (do_read(fd, self, sizeof(*self)) <= 0 || |
| 596 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 600 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
| 597 | return -1; | 601 | return -1; |
| 598 | 602 | ||
| @@ -662,13 +666,51 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
| 662 | return 0; | 666 | return 0; |
| 663 | } | 667 | } |
| 664 | 668 | ||
| 665 | int perf_header__read(struct perf_header *self, int fd) | 669 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, |
| 670 | struct perf_header *ph, int fd) | ||
| 666 | { | 671 | { |
| 672 | if (do_read(fd, self, sizeof(*self)) <= 0 || | ||
| 673 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | ||
| 674 | return -1; | ||
| 675 | |||
| 676 | if (self->size != sizeof(*self)) { | ||
| 677 | u64 size = bswap_64(self->size); | ||
| 678 | |||
| 679 | if (size != sizeof(*self)) | ||
| 680 | return -1; | ||
| 681 | |||
| 682 | ph->needs_swap = true; | ||
| 683 | } | ||
| 684 | |||
| 685 | return 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | static int perf_header__read_pipe(struct perf_session *session, int fd) | ||
| 689 | { | ||
| 690 | struct perf_header *self = &session->header; | ||
| 691 | struct perf_pipe_file_header f_header; | ||
| 692 | |||
| 693 | if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { | ||
| 694 | pr_debug("incompatible file format\n"); | ||
| 695 | return -EINVAL; | ||
| 696 | } | ||
| 697 | |||
| 698 | session->fd = fd; | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | int perf_header__read(struct perf_session *session, int fd) | ||
| 704 | { | ||
| 705 | struct perf_header *self = &session->header; | ||
| 667 | struct perf_file_header f_header; | 706 | struct perf_file_header f_header; |
| 668 | struct perf_file_attr f_attr; | 707 | struct perf_file_attr f_attr; |
| 669 | u64 f_id; | 708 | u64 f_id; |
| 670 | int nr_attrs, nr_ids, i, j; | 709 | int nr_attrs, nr_ids, i, j; |
| 671 | 710 | ||
| 711 | if (session->fd_pipe) | ||
| 712 | return perf_header__read_pipe(session, fd); | ||
| 713 | |||
| 672 | if (perf_file_header__read(&f_header, self, fd) < 0) { | 714 | if (perf_file_header__read(&f_header, self, fd) < 0) { |
| 673 | pr_debug("incompatible file format\n"); | 715 | pr_debug("incompatible file format\n"); |
| 674 | return -EINVAL; | 716 | return -EINVAL; |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index c059f08cf877..6562ece67064 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 | ||
| 42 | struct perf_pipe_file_header { | ||
| 43 | u64 magic; | ||
| 44 | u64 size; | ||
| 45 | }; | ||
| 46 | |||
| 42 | struct perf_header; | 47 | struct perf_header; |
| 43 | 48 | ||
| 44 | int perf_file_header__read(struct perf_file_header *self, | 49 | int perf_file_header__read(struct perf_file_header *self, |
| @@ -60,8 +65,9 @@ struct perf_header { | |||
| 60 | int perf_header__init(struct perf_header *self); | 65 | int perf_header__init(struct perf_header *self); |
| 61 | void perf_header__exit(struct perf_header *self); | 66 | void perf_header__exit(struct perf_header *self); |
| 62 | 67 | ||
| 63 | int perf_header__read(struct perf_header *self, int fd); | 68 | int perf_header__read(struct perf_session *session, int fd); |
| 64 | int perf_header__write(struct perf_header *self, int fd, bool at_exit); | 69 | int perf_header__write(struct perf_header *self, int fd, bool at_exit); |
| 70 | int perf_header__write_pipe(int fd); | ||
| 65 | 71 | ||
| 66 | int perf_header__add_attr(struct perf_header *self, | 72 | int perf_header__add_attr(struct perf_header *self, |
| 67 | struct perf_header_attr *attr); | 73 | struct perf_header_attr *attr); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ddf288fca3eb..2c1277cb4ae4 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, "-")) { | ||
