perf build-id: Add quirk to deal with perf.data file format breakage
Commit-ID: b25114817a73bbd2b84ce9dba02ee1ef8989a947 Gitweb: http://git.kernel.org/tip/b25114817a73bbd2b84ce9dba02ee1ef8989a947 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Tue, 22 Mar 2011 13:36:45 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 23 Mar 2011 19:29:40 -0300
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 <[email protected]>
Cc Avi Kivity <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Mike Galbraith <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
Cc Tom Zanussi <[email protected]>
Cc Zhang Yanmin <[email protected]>
LKML-Reference: <new-submission>
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>
--- tools/perf/util/header.c | 57 +++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 56 insertions(+), 1 deletions(-)
tools/perf/util/header.c +56 -1
@@ -695,13 +695,50 @@ out:return err; } +static int perf_header__read_build_ids_abi_quirk (struct perf_header *header, +int input,u64 offset,u64 size) +{ + struct perf_session *session = container_of(header, struct perf_session, header); +struct { +struct perf_event_header header; +u8 build_id[ALIGN (BUILD_ID_SIZE ,sizeof (u64))]; +char filename[0 ]; + } old_bev; +struct build_id_event bev; +char filename[PATH_MAX ]; +u64 limit = offset + size; + +while (offset < limit) { +ssize_t len; + +if (read (input, &old_bev,sizeof (old_bev)) !=sizeof (old_bev)) +return -1 ; + +if (header->needs_swap) +perf_event_header__bswap (&old_bev.header); + + len = old_bev.header.size -sizeof (old_bev); +if (read (input, filename, len) != len) +return -1 ; + + bev.header = old_bev.header; + bev.pid =0 ; +memcpy (bev.build_id, old_bev.build_id,sizeof (bev.build_id)); +__event_process_build_id (&bev, filename, session); + + offset += bev.header.size; + } + +return 0 ; +} +static int perf_header__read_build_ids (struct perf_header *header,int input,u64 offset,u64 size) { struct perf_session *session = container_of(header, struct perf_session, header);struct build_id_event bev;char filename[PATH_MAX ]; -u64 limit = offset + size; +u64 limit = offset + size, orig_offset = offset;int err =-1 ;while (offset < limit) {
@@ -716,6 +753,24 @@ static int perf_header__read_build_ids(struct perf_header *header, len = bev.header.size -sizeof (bev);if (read (input, filename, len) != len) goto out; +/* +* 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). +*/ +if (memcmp (filename,"nel.kallsyms]" ,13 ) ==0 ) { +if (lseek (input, orig_offset,SEEK_SET ) == (off_t)-1 ) +return -1 ; +return perf_header__read_build_ids_abi_quirk (header, input, offset, size); + }__event_process_build_id (&bev, filename, session);