Skip to content

Commit

Permalink
perf build-id: Add quirk to deal with perf.data file format breakage
Browse files Browse the repository at this point in the history
The a1645ce 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]>
  • Loading branch information
acmel committed Mar 23, 2011
1 parent 9e69c21 commit b251148
Showing 1 changed file with 56 additions and 1 deletion.
57 changes: 56 additions & 1 deletion tools/perf/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,13 +695,50 @@ static int __event_process_build_id(struct build_id_event *bev,
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) {
Expand All @@ -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);

Expand Down

0 comments on commit b251148

Please sign in to comment.