commit: b25114817a73bbd2b84ce9dba02ee1ef8989a947
From: Arnaldo Carvalho de Melo <[email protected]>
Date: Tue, 22 Mar 2011 13:36:45 -0300
Subject: [PATCH] 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]>
Cc: [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(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e5230c0..93862a8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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);
 

_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to