aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r--tools/perf/util/header.c63
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
469static 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
467int perf_header__process_sections(struct perf_header *self, int fd, 481int 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
536static int perf_file_section__process(struct perf_file_section *self, 572static 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
561int perf_header__read(struct perf_header *self, int fd) 598int 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 }