diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ec96321eb9e4..b31e0ae4b8db 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1,8 +1,10 @@ | |||
1 | #include <sys/types.h> | 1 | #include <sys/types.h> |
2 | #include <byteswap.h> | ||
2 | #include <unistd.h> | 3 | #include <unistd.h> |
3 | #include <stdio.h> | 4 | #include <stdio.h> |
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
5 | #include <linux/list.h> | 6 | #include <linux/list.h> |
7 | #include <linux/kernel.h> | ||
6 | 8 | ||
7 | #include "util.h" | 9 | #include "util.h" |
8 | #include "header.h" | 10 | #include "header.h" |
@@ -464,8 +466,21 @@ static int do_read(int fd, void *buf, size_t size) | |||
464 | return 0; | 466 | return 0; |
465 | } | 467 | } |
466 | 468 | ||
469 | static int perf_header__getbuffer64(struct perf_header *self, | ||
470 | int fd, void *buf, size_t size) | ||
471 | { | ||
472 | if (do_read(fd, buf, size)) | ||
473 | return -1; | ||
474 | |||
475 | if (self->needs_swap) | ||
476 | mem_bswap_64(buf, size); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
467 | int perf_header__process_sections(struct perf_header *self, int fd, | 481 | int perf_header__process_sections(struct perf_header *self, int fd, |
468 | int (*process)(struct perf_file_section *self, | 482 | int (*process)(struct perf_file_section *self, |
483 | struct perf_header *ph, | ||
469 | int feat, int fd)) | 484 | int feat, int fd)) |
470 | { | 485 | { |
471 | struct perf_file_section *feat_sec; | 486 | struct perf_file_section *feat_sec; |
@@ -486,7 +501,7 @@ int perf_header__process_sections(struct perf_header *self, int fd, | |||
486 | 501 | ||
487 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 502 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); |
488 | 503 | ||
489 | if (do_read(fd, feat_sec, sec_size)) | 504 | if (perf_header__getbuffer64(self, fd, feat_sec, sec_size)) |
490 | goto out_free; | 505 | goto out_free; |
491 | 506 | ||
492 | err = 0; | 507 | err = 0; |
@@ -494,7 +509,7 @@ int perf_header__process_sections(struct perf_header *self, int fd, | |||
494 | if (perf_header__has_feat(self, feat)) { | 509 | if (perf_header__has_feat(self, feat)) { |
495 | struct perf_file_section *sec = &feat_sec[idx++]; | 510 | struct perf_file_section *sec = &feat_sec[idx++]; |
496 | 511 | ||
497 | err = process(sec, feat, fd); | 512 | err = process(sec, self, feat, fd); |
498 | if (err < 0) | 513 | if (err < 0) |
499 | break; | 514 | break; |
500 | } | 515 | } |
@@ -511,10 +526,20 @@ int perf_file_header__read(struct perf_file_header *self, | |||
511 | lseek(fd, 0, SEEK_SET); | 526 | lseek(fd, 0, SEEK_SET); |
512 | 527 | ||
513 | if (do_read(fd, self, sizeof(*self)) || | 528 | if (do_read(fd, self, sizeof(*self)) || |
514 | self->magic != PERF_MAGIC || | 529 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
515 | self->attr_size != sizeof(struct perf_file_attr)) | ||
516 | return -1; | 530 | return -1; |
517 | 531 | ||
532 | if (self->attr_size != sizeof(struct perf_file_attr)) { | ||
533 | u64 attr_size = bswap_64(self->attr_size); | ||
534 | |||
535 | if (attr_size != sizeof(struct perf_file_attr)) | ||
536 | return -1; | ||
537 | |||
538 | mem_bswap_64(self, offsetof(struct perf_file_header, | ||
539 | adds_features)); | ||
540 | ph->needs_swap = true; | ||
541 | } | ||
542 | |||
518 | if (self->size != sizeof(*self)) { | 543 | if (self->size != sizeof(*self)) { |
519 | /* Support the previous format */ | 544 | /* Support the previous format */ |
520 | if (self->size == offsetof(typeof(*self), adds_features)) | 545 | if (self->size == offsetof(typeof(*self), adds_features)) |
@@ -524,16 +549,28 @@ int perf_file_header__read(struct perf_file_header *self, | |||
524 | } | 549 | } |
525 | 550 | ||
526 | memcpy(&ph->adds_features, &self->adds_features, | 551 | memcpy(&ph->adds_features, &self->adds_features, |
527 | sizeof(self->adds_features)); | 552 | sizeof(ph->adds_features)); |
553 | /* | ||
554 | * FIXME: hack that assumes that if we need swap the perf.data file | ||
555 | * may be coming from an arch with a different word-size, ergo different | ||
556 | * DEFINE_BITMAP format, investigate more later, but for now its mostly | ||
557 | * safe to assume that we have a build-id section. Trace files probably | ||
558 | * have several other issues in this realm anyway... | ||
559 | */ | ||
560 | if (ph->needs_swap) { | ||
561 | memset(&ph->adds_features, 0, sizeof(ph->adds_features)); | ||
562 | perf_header__set_feat(ph, HEADER_BUILD_ID); | ||
563 | } | ||
528 | 564 | ||
529 | ph->event_offset = self->event_types.offset; | 565 | ph->event_offset = self->event_types.offset; |
530 | ph->event_size = self->event_types.size; | 566 | ph->event_size = self->event_types.size; |
531 | ph->data_offset = self->data.offset; | 567 | ph->data_offset = self->data.offset; |
532 | ph->data_size = self->data.size; | 568 | ph->data_size = self->data.size; |
533 | return 0; | 569 | return 0; |
534 | } | 570 | } |
535 | 571 | ||
536 | static int perf_file_section__process(struct perf_file_section *self, | 572 | static int perf_file_section__process(struct perf_file_section *self, |
573 | struct perf_header *ph, | ||
537 | int feat, int fd) | 574 | int feat, int fd) |
538 | { | 575 | { |
539 | if (lseek(fd, self->offset, SEEK_SET) < 0) { | 576 | if (lseek(fd, self->offset, SEEK_SET) < 0) { |
@@ -548,7 +585,7 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
548 | break; | 585 | break; |
549 | 586 | ||
550 | case HEADER_BUILD_ID: | 587 | case HEADER_BUILD_ID: |
551 | if (perf_header__read_build_ids(fd, self->offset, self->size)) | 588 | if (perf_header__read_build_ids(ph, fd, self->offset, self->size)) |
552 | pr_debug("Failed to read buildids, continuing...\n"); | 589 | pr_debug("Failed to read buildids, continuing...\n"); |
553 | break; | 590 | break; |
554 | default: | 591 | default: |
@@ -560,7 +597,7 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
560 | 597 | ||
561 | int perf_header__read(struct perf_header *self, int fd) | 598 | int perf_header__read(struct perf_header *self, int fd) |
562 | { | 599 | { |
563 | struct perf_file_header f_header; | 600 | struct perf_file_header f_header; |
564 | struct perf_file_attr f_attr; | 601 | struct perf_file_attr f_attr; |
565 | u64 f_id; | 602 | u64 f_id; |
566 | int nr_attrs, nr_ids, i, j; | 603 | int nr_attrs, nr_ids, i, j; |
@@ -577,8 +614,9 @@ int perf_header__read(struct perf_header *self, int fd) | |||
577 | struct perf_header_attr *attr; | 614 | struct perf_header_attr *attr; |
578 | off_t tmp; | 615 | off_t tmp; |
579 | 616 | ||
580 | if (do_read(fd, &f_attr, sizeof(f_attr))) | 617 | if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr))) |
581 | goto out_errno; | 618 | goto out_errno; |
619 | |||
582 | tmp = lseek(fd, 0, SEEK_CUR); | 620 | tmp = lseek(fd, 0, SEEK_CUR); |
583 | 621 | ||
584 | attr = perf_header_attr__new(&f_attr.attr); | 622 | attr = perf_header_attr__new(&f_attr.attr); |
@@ -589,7 +627,7 @@ int perf_header__read(struct perf_header *self, int fd) | |||
589 | lseek(fd, f_attr.ids.offset, SEEK_SET); | 627 | lseek(fd, f_attr.ids.offset, SEEK_SET); |
590 | 628 | ||
591 | for (j = 0; j < nr_ids; j++) { | 629 | for (j = 0; j < nr_ids; j++) { |
592 | if (do_read(fd, &f_id, sizeof(f_id))) | 630 | if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id))) |
593 | goto out_errno; | 631 | goto out_errno; |
594 | 632 | ||
595 | if (perf_header_attr__add_id(attr, f_id) < 0) { | 633 | if (perf_header_attr__add_id(attr, f_id) < 0) { |
@@ -610,7 +648,8 @@ int perf_header__read(struct perf_header *self, int fd) | |||
610 | events = malloc(f_header.event_types.size); | 648 | events = malloc(f_header.event_types.size); |
611 | if (events == NULL) | 649 | if (events == NULL) |
612 | return -ENOMEM; | 650 | return -ENOMEM; |
613 | if (do_read(fd, events, f_header.event_types.size)) | 651 | if (perf_header__getbuffer64(self, fd, events, |
652 | f_header.event_types.size)) | ||
614 | goto out_errno; | 653 | goto out_errno; |
615 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | 654 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); |
616 | } | 655 | } |