diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-03-22 12:36:45 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-03-23 18:29:40 -0400 |
| commit | b25114817a73bbd2b84ce9dba02ee1ef8989a947 (patch) | |
| tree | 8eaad3eaa307a607f87b8ea631c5f1fc76ce4a82 /tools | |
| parent | 9e69c210822c4035708a6111567c96364ca244d5 (diff) | |
perf build-id: Add quirk to deal with perf.data file format breakage
The a1645ce1 changeset:
"perf: 'perf kvm' tool for monitoring guest performance from host"
Added a field to struct build_id_event that broke the file format.
Since the kernel build-id is the first entry, process the table using
the old format if the well known '[kernel.kallsyms]' string for the
kernel build-id has the first 4 characters chopped off (where the pid_t
sits).
Reported-by: Han Pingtian <phan@redhat.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Cc: stable@kernel.org
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/util/header.c | 57 |
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 | ||
| 698 | static 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 | |||
| 698 | static int perf_header__read_build_ids(struct perf_header *header, | 735 | static 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 | ||
