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.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e5230c0ef95b..93862a8027ea 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -695,13 +695,50 @@ out:
695 return err; 695 return err;
696} 696}
697 697
698static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
699 int input, u64 offset, u64 size)
700{
701 struct perf_session *session = container_of(header, struct perf_session, header);
702 struct {
703 struct perf_event_header header;
704 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
705 char filename[0];
706 } old_bev;
707 struct build_id_event bev;
708 char filename[PATH_MAX];
709 u64 limit = offset + size;
710
711 while (offset < limit) {
712 ssize_t len;
713
714 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
715 return -1;
716
717 if (header->needs_swap)
718 perf_event_header__bswap(&old_bev.header);
719
720 len = old_bev.header.size - sizeof(old_bev);
721 if (read(input, filename, len) != len)
722 return -1;
723
724 bev.header = old_bev.header;
725 bev.pid = 0;
726 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
727 __event_process_build_id(&bev, filename, session);
728
729 offset += bev.header.size;
730 }
731
732 return 0;
733}
734
698static int perf_header__read_build_ids(struct perf_header *header, 735static int perf_header__read_build_ids(struct perf_header *header,
699 int input, u64 offset, u64 size) 736 int input, u64 offset, u64 size)
700{ 737{
701 struct perf_session *session = container_of(header, struct perf_session, header); 738 struct perf_session *session = container_of(header, struct perf_session, header);
702 struct build_id_event bev; 739 struct build_id_event bev;
703 char filename[PATH_MAX]; 740 char filename[PATH_MAX];
704 u64 limit = offset + size; 741 u64 limit = offset + size, orig_offset = offset;
705 int err = -1; 742 int err = -1;
706 743
707 while (offset < limit) { 744 while (offset < limit) {
@@ -716,6 +753,24 @@ static int perf_header__read_build_ids(struct perf_header *header,
716 len = bev.header.size - sizeof(bev); 753 len = bev.header.size - sizeof(bev);
717 if (read(input, filename, len) != len) 754 if (read(input, filename, len) != len)
718 goto out; 755 goto out;
756 /*
757 * The a1645ce1 changeset:
758 *
759 * "perf: 'perf kvm' tool for monitoring guest performance from host"
760 *
761 * Added a field to struct build_id_event that broke the file
762 * format.
763 *
764 * Since the kernel build-id is the first entry, process the
765 * table using the old format if the well known
766 * '[kernel.kallsyms]' string for the kernel build-id has the
767 * first 4 characters chopped off (where the pid_t sits).
768 */
769 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
770 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
771 return -1;
772 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
773 }
719 774
720 __event_process_build_id(&bev, filename, session); 775 __event_process_build_id(&bev, filename, session);
721 776