|
@@ -695,13 +695,50 @@ out:
|
|
return err;
|
|
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,
|
|
static int perf_header__read_build_ids(struct perf_header *header,
|
|
int input, u64 offset, u64 size)
|
|
int input, u64 offset, u64 size)
|
|
{
|
|
{
|
|
struct perf_session *session = container_of(header, struct perf_session, header);
|
|
struct perf_session *session = container_of(header, struct perf_session, header);
|
|
struct build_id_event bev;
|
|
struct build_id_event bev;
|
|
char filename[PATH_MAX];
|
|
char filename[PATH_MAX];
|
|
- u64 limit = offset + size;
|
|
|
|
|
|
+ u64 limit = offset + size, orig_offset = offset;
|
|
int err = -1;
|
|
int err = -1;
|
|
|
|
|
|
while (offset < limit) {
|
|
while (offset < limit) {
|
|
@@ -716,6 +753,24 @@ static int perf_header__read_build_ids(struct perf_header *header,
|
|
len = bev.header.size - sizeof(bev);
|
|
len = bev.header.size - sizeof(bev);
|
|
if (read(input, filename, len) != len)
|
|
if (read(input, filename, len) != len)
|
|
goto out;
|
|
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);
|
|
__event_process_build_id(&bev, filename, session);
|
|
|
|
|