diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 588 |
1 files changed, 387 insertions, 201 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 14bb035c5fd..fcd9cf3ea63 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -63,9 +63,20 @@ char *perf_header__find_event(u64 id) | |||
63 | return NULL; | 63 | return NULL; |
64 | } | 64 | } |
65 | 65 | ||
66 | static const char *__perf_magic = "PERFFILE"; | 66 | /* |
67 | * magic2 = "PERFILE2" | ||
68 | * must be a numerical value to let the endianness | ||
69 | * determine the memory layout. That way we are able | ||
70 | * to detect endianness when reading the perf.data file | ||
71 | * back. | ||
72 | * | ||
73 | * we check for legacy (PERFFILE) format. | ||
74 | */ | ||
75 | static const char *__perf_magic1 = "PERFFILE"; | ||
76 | static const u64 __perf_magic2 = 0x32454c4946524550ULL; | ||
77 | static const u64 __perf_magic2_sw = 0x50455246494c4532ULL; | ||
67 | 78 | ||
68 | #define PERF_MAGIC (*(u64 *)__perf_magic) | 79 | #define PERF_MAGIC __perf_magic2 |
69 | 80 | ||
70 | struct perf_file_attr { | 81 | struct perf_file_attr { |
71 | struct perf_event_attr attr; | 82 | struct perf_event_attr attr; |
@@ -1012,6 +1023,12 @@ write_it: | |||
1012 | return do_write_string(fd, buffer); | 1023 | return do_write_string(fd, buffer); |
1013 | } | 1024 | } |
1014 | 1025 | ||
1026 | static int write_branch_stack(int fd __used, struct perf_header *h __used, | ||
1027 | struct perf_evlist *evlist __used) | ||
1028 | { | ||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
1015 | static void print_hostname(struct perf_header *ph, int fd, FILE *fp) | 1032 | static void print_hostname(struct perf_header *ph, int fd, FILE *fp) |
1016 | { | 1033 | { |
1017 | char *str = do_read_string(fd, ph); | 1034 | char *str = do_read_string(fd, ph); |
@@ -1133,8 +1150,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
1133 | uint64_t id; | 1150 | uint64_t id; |
1134 | void *buf = NULL; | 1151 | void *buf = NULL; |
1135 | char *str; | 1152 | char *str; |
1136 | u32 nre, sz, nr, i, j, msz; | 1153 | u32 nre, sz, nr, i, j; |
1137 | int ret; | 1154 | ssize_t ret; |
1155 | size_t msz; | ||
1138 | 1156 | ||
1139 | /* number of events */ | 1157 | /* number of events */ |
1140 | ret = read(fd, &nre, sizeof(nre)); | 1158 | ret = read(fd, &nre, sizeof(nre)); |
@@ -1151,25 +1169,23 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
1151 | if (ph->needs_swap) | 1169 | if (ph->needs_swap) |
1152 | sz = bswap_32(sz); | 1170 | sz = bswap_32(sz); |
1153 | 1171 | ||
1154 | /* | ||
1155 | * ensure it is at least to our ABI rev | ||
1156 | */ | ||
1157 | if (sz < (u32)sizeof(attr)) | ||
1158 | goto error; | ||
1159 | |||
1160 | memset(&attr, 0, sizeof(attr)); | 1172 | memset(&attr, 0, sizeof(attr)); |
1161 | 1173 | ||
1162 | /* read entire region to sync up to next field */ | 1174 | /* buffer to hold on file attr struct */ |
1163 | buf = malloc(sz); | 1175 | buf = malloc(sz); |
1164 | if (!buf) | 1176 | if (!buf) |
1165 | goto error; | 1177 | goto error; |
1166 | 1178 | ||
1167 | msz = sizeof(attr); | 1179 | msz = sizeof(attr); |
1168 | if (sz < msz) | 1180 | if (sz < (ssize_t)msz) |
1169 | msz = sz; | 1181 | msz = sz; |
1170 | 1182 | ||
1171 | for (i = 0 ; i < nre; i++) { | 1183 | for (i = 0 ; i < nre; i++) { |
1172 | 1184 | ||
1185 | /* | ||
1186 | * must read entire on-file attr struct to | ||
1187 | * sync up with layout. | ||
1188 | */ | ||
1173 | ret = read(fd, buf, sz); | 1189 | ret = read(fd, buf, sz); |
1174 | if (ret != (ssize_t)sz) | 1190 | if (ret != (ssize_t)sz) |
1175 | goto error; | 1191 | goto error; |
@@ -1305,25 +1321,204 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp) | |||
1305 | free(str); | 1321 | free(str); |
1306 | } | 1322 | } |
1307 | 1323 | ||
1324 | static void print_branch_stack(struct perf_header *ph __used, int fd __used, | ||
1325 | FILE *fp) | ||
1326 | { | ||
1327 | fprintf(fp, "# contains samples with branch stack\n"); | ||
1328 | } | ||
1329 | |||
1330 | static int __event_process_build_id(struct build_id_event *bev, | ||
1331 | char *filename, | ||
1332 | struct perf_session *session) | ||
1333 | { | ||
1334 | int err = -1; | ||
1335 | struct list_head *head; | ||
1336 | struct machine *machine; | ||
1337 | u16 misc; | ||
1338 | struct dso *dso; | ||
1339 | enum dso_kernel_type dso_type; | ||
1340 | |||
1341 | machine = perf_session__findnew_machine(session, bev->pid); | ||
1342 | if (!machine) | ||
1343 | goto out; | ||
1344 | |||
1345 | misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1346 | |||
1347 | switch (misc) { | ||
1348 | case PERF_RECORD_MISC_KERNEL: | ||
1349 | dso_type = DSO_TYPE_KERNEL; | ||
1350 | head = &machine->kernel_dsos; | ||
1351 | break; | ||
1352 | case PERF_RECORD_MISC_GUEST_KERNEL: | ||
1353 | dso_type = DSO_TYPE_GUEST_KERNEL; | ||
1354 | head = &machine->kernel_dsos; | ||
1355 | break; | ||
1356 | case PERF_RECORD_MISC_USER: | ||
1357 | case PERF_RECORD_MISC_GUEST_USER: | ||
1358 | dso_type = DSO_TYPE_USER; | ||
1359 | head = &machine->user_dsos; | ||
1360 | break; | ||
1361 | default: | ||
1362 | goto out; | ||
1363 | } | ||
1364 | |||
1365 | dso = __dsos__findnew(head, filename); | ||
1366 | if (dso != NULL) { | ||
1367 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
1368 | |||
1369 | dso__set_build_id(dso, &bev->build_id); | ||
1370 | |||
1371 | if (filename[0] == '[') | ||
1372 | dso->kernel = dso_type; | ||
1373 | |||
1374 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), | ||
1375 | sbuild_id); | ||
1376 | pr_debug("build id event received for %s: %s\n", | ||
1377 | dso->long_name, sbuild_id); | ||
1378 | } | ||
1379 | |||
1380 | err = 0; | ||
1381 | out: | ||
1382 | return err; | ||
1383 | } | ||
1384 | |||
1385 | static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, | ||
1386 | int input, u64 offset, u64 size) | ||
1387 | { | ||
1388 | struct perf_session *session = container_of(header, struct perf_session, header); | ||
1389 | struct { | ||
1390 | struct perf_event_header header; | ||
1391 | u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; | ||
1392 | char filename[0]; | ||
1393 | } old_bev; | ||
1394 | struct build_id_event bev; | ||
1395 | char filename[PATH_MAX]; | ||
1396 | u64 limit = offset + size; | ||
1397 | |||
1398 | while (offset < limit) { | ||
1399 | ssize_t len; | ||
1400 | |||
1401 | if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) | ||
1402 | return -1; | ||
1403 | |||
1404 | if (header->needs_swap) | ||
1405 | perf_event_header__bswap(&old_bev.header); | ||
1406 | |||
1407 | len = old_bev.header.size - sizeof(old_bev); | ||
1408 | if (read(input, filename, len) != len) | ||
1409 | return -1; | ||
1410 | |||
1411 | bev.header = old_bev.header; | ||
1412 | |||
1413 | /* | ||
1414 | * As the pid is the missing value, we need to fill | ||
1415 | * it properly. The header.misc value give us nice hint. | ||
1416 | */ | ||
1417 | bev.pid = HOST_KERNEL_ID; | ||
1418 | if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER || | ||
1419 | bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL) | ||
1420 | bev.pid = DEFAULT_GUEST_KERNEL_ID; | ||
1421 | |||
1422 | memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); | ||
1423 | __event_process_build_id(&bev, filename, session); | ||
1424 | |||
1425 | offset += bev.header.size; | ||
1426 | } | ||
1427 | |||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1431 | static int perf_header__read_build_ids(struct perf_header *header, | ||
1432 | int input, u64 offset, u64 size) | ||
1433 | { | ||
1434 | struct perf_session *session = container_of(header, struct perf_session, header); | ||
1435 | struct build_id_event bev; | ||
1436 | char filename[PATH_MAX]; | ||
1437 | u64 limit = offset + size, orig_offset = offset; | ||
1438 | int err = -1; | ||
1439 | |||
1440 | while (offset < limit) { | ||
1441 | ssize_t len; | ||
1442 | |||
1443 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | ||
1444 | goto out; | ||
1445 | |||
1446 | if (header->needs_swap) | ||
1447 | perf_event_header__bswap(&bev.header); | ||
1448 | |||
1449 | len = bev.header.size - sizeof(bev); | ||
1450 | if (read(input, filename, len) != len) | ||
1451 | goto out; | ||
1452 | /* | ||
1453 | * The a1645ce1 changeset: | ||
1454 | * | ||
1455 | * "perf: 'perf kvm' tool for monitoring guest performance from host" | ||
1456 | * | ||
1457 | * Added a field to struct build_id_event that broke the file | ||
1458 | * format. | ||
1459 | * | ||
1460 | * Since the kernel build-id is the first entry, process the | ||
1461 | * table using the old format if the well known | ||
1462 | * '[kernel.kallsyms]' string for the kernel build-id has the | ||
1463 | * first 4 characters chopped off (where the pid_t sits). | ||
1464 | */ | ||
1465 | if (memcmp(filename, "nel.kallsyms]", 13) == 0) { | ||
1466 | if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1) | ||
1467 | return -1; | ||
1468 | return perf_header__read_build_ids_abi_quirk(header, input, offset, size); | ||
1469 | } | ||
1470 | |||
1471 | __event_process_build_id(&bev, filename, session); | ||
1472 | |||
1473 | offset += bev.header.size; | ||
1474 | } | ||
1475 | err = 0; | ||
1476 | out: | ||
1477 | return err; | ||
1478 | } | ||
1479 | |||
1480 | static int process_trace_info(struct perf_file_section *section __unused, | ||
1481 | struct perf_header *ph __unused, | ||
1482 | int feat __unused, int fd) | ||
1483 | { | ||
1484 | trace_report(fd, false); | ||
1485 | return 0; | ||
1486 | } | ||
1487 | |||
1488 | static int process_build_id(struct perf_file_section *section, | ||
1489 | struct perf_header *ph, | ||
1490 | int feat __unused, int fd) | ||
1491 | { | ||
1492 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) | ||
1493 | pr_debug("Failed to read buildids, continuing...\n"); | ||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1308 | struct feature_ops { | 1497 | struct feature_ops { |
1309 | int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); | 1498 | int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); |
1310 | void (*print)(struct perf_header *h, int fd, FILE *fp); | 1499 | void (*print)(struct perf_header *h, int fd, FILE *fp); |
1500 | int (*process)(struct perf_file_section *section, | ||
1501 | struct perf_header *h, int feat, int fd); | ||
1311 | const char *name; | 1502 | const char *name; |
1312 | bool full_only; | 1503 | bool full_only; |
1313 | }; | 1504 | }; |
1314 | 1505 | ||
1315 | #define FEAT_OPA(n, func) \ | 1506 | #define FEAT_OPA(n, func) \ |
1316 | [n] = { .name = #n, .write = write_##func, .print = print_##func } | 1507 | [n] = { .name = #n, .write = write_##func, .print = print_##func } |
1508 | #define FEAT_OPP(n, func) \ | ||
1509 | [n] = { .name = #n, .write = write_##func, .print = print_##func, \ | ||
1510 | .process = process_##func } | ||
1317 | #define FEAT_OPF(n, func) \ | 1511 | #define FEAT_OPF(n, func) \ |
1318 | [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true } | 1512 | [n] = { .name = #n, .write = write_##func, .print = print_##func, \ |
1513 | .full_only = true } | ||
1319 | 1514 | ||
1320 | /* feature_ops not implemented: */ | 1515 | /* feature_ops not implemented: */ |
1321 | #define print_trace_info NULL | 1516 | #define print_trace_info NULL |
1322 | #define print_build_id NULL | 1517 | #define print_build_id NULL |
1323 | 1518 | ||
1324 | static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { | 1519 | static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { |
1325 | FEAT_OPA(HEADER_TRACE_INFO, trace_info), | 1520 | FEAT_OPP(HEADER_TRACE_INFO, trace_info), |
1326 | FEAT_OPA(HEADER_BUILD_ID, build_id), | 1521 | FEAT_OPP(HEADER_BUILD_ID, build_id), |
1327 | FEAT_OPA(HEADER_HOSTNAME, hostname), | 1522 | FEAT_OPA(HEADER_HOSTNAME, hostname), |
1328 | FEAT_OPA(HEADER_OSRELEASE, osrelease), | 1523 | FEAT_OPA(HEADER_OSRELEASE, osrelease), |
1329 | FEAT_OPA(HEADER_VERSION, version), | 1524 | FEAT_OPA(HEADER_VERSION, version), |
@@ -1336,6 +1531,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { | |||
1336 | FEAT_OPA(HEADER_CMDLINE, cmdline), | 1531 | FEAT_OPA(HEADER_CMDLINE, cmdline), |
1337 | FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), | 1532 | FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), |
1338 | FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), | 1533 | FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), |
1534 | FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), | ||
1339 | }; | 1535 | }; |
1340 | 1536 | ||
1341 | struct header_print_data { | 1537 | struct header_print_data { |
@@ -1620,24 +1816,128 @@ out_free: | |||
1620 | return err; | 1816 | return err; |
1621 | } | 1817 | } |
1622 | 1818 | ||
1819 | static const int attr_file_abi_sizes[] = { | ||
1820 | [0] = PERF_ATTR_SIZE_VER0, | ||
1821 | [1] = PERF_ATTR_SIZE_VER1, | ||
1822 | 0, | ||
1823 | }; | ||
1824 | |||
1825 | /* | ||
1826 | * In the legacy file format, the magic number is not used to encode endianness. | ||
1827 | * hdr_sz was used to encode endianness. But given that hdr_sz can vary based | ||
1828 | * on ABI revisions, we need to try all combinations for all endianness to | ||
1829 | * detect the endianness. | ||
1830 | */ | ||
1831 | static int try_all_file_abis(uint64_t hdr_sz, struct perf_header *ph) | ||
1832 | { | ||
1833 | uint64_t ref_size, attr_size; | ||
1834 | int i; | ||
1835 | |||
1836 | for (i = 0 ; attr_file_abi_sizes[i]; i++) { | ||
1837 | ref_size = attr_file_abi_sizes[i] | ||
1838 | + sizeof(struct perf_file_section); | ||
1839 | if (hdr_sz != ref_size) { | ||
1840 | attr_size = bswap_64(hdr_sz); | ||
1841 | if (attr_size != ref_size) | ||
1842 | continue; | ||
1843 | |||
1844 | ph->needs_swap = true; | ||
1845 | } | ||
1846 | pr_debug("ABI%d perf.data file detected, need_swap=%d\n", | ||
1847 | i, | ||
1848 | ph->needs_swap); | ||
1849 | return 0; | ||
1850 | } | ||
1851 | /* could not determine endianness */ | ||
1852 | return -1; | ||
1853 | } | ||
1854 | |||
1855 | #define PERF_PIPE_HDR_VER0 16 | ||
1856 | |||
1857 | static const size_t attr_pipe_abi_sizes[] = { | ||
1858 | [0] = PERF_PIPE_HDR_VER0, | ||
1859 | 0, | ||
1860 | }; | ||
1861 | |||
1862 | /* | ||
1863 | * In the legacy pipe format, there is an implicit assumption that endiannesss | ||
1864 | * between host recording the samples, and host parsing the samples is the | ||
1865 | * same. This is not always the case given that the pipe output may always be | ||
1866 | * redirected into a file and analyzed on a different machine with possibly a | ||
1867 | * different endianness and perf_event ABI revsions in the perf tool itself. | ||
1868 | */ | ||
1869 | static int try_all_pipe_abis(uint64_t hdr_sz, struct perf_header *ph) | ||
1870 | { | ||
1871 | u64 attr_size; | ||
1872 | int i; | ||
1873 | |||
1874 | for (i = 0 ; attr_pipe_abi_sizes[i]; i++) { | ||
1875 | if (hdr_sz != attr_pipe_abi_sizes[i]) { | ||
1876 | attr_size = bswap_64(hdr_sz); | ||
1877 | if (attr_size != hdr_sz) | ||
1878 | continue; | ||
1879 | |||
1880 | ph->needs_swap = true; | ||
1881 | } | ||
1882 | pr_debug("Pipe ABI%d perf.data file detected\n", i); | ||
1883 | return 0; | ||
1884 | } | ||
1885 | return -1; | ||
1886 | } | ||
1887 | |||
1888 | static int check_magic_endian(u64 magic, uint64_t hdr_sz, | ||
1889 | bool is_pipe, struct perf_header *ph) | ||
1890 | { | ||
1891 | int ret; | ||
1892 | |||
1893 | /* check for legacy format */ | ||
1894 | ret = memcmp(&magic, __perf_magic1, sizeof(magic)); | ||
1895 | if (ret == 0) { | ||
1896 | pr_debug("legacy perf.data format\n"); | ||
1897 | if (is_pipe) | ||
1898 | return try_all_pipe_abis(hdr_sz, ph); | ||
1899 | |||
1900 | return try_all_file_abis(hdr_sz, ph); | ||
1901 | } | ||
1902 | /* | ||
1903 | * the new magic number serves two purposes: | ||
1904 | * - unique number to identify actual perf.data files | ||
1905 | * - encode endianness of file | ||
1906 | */ | ||
1907 | |||
1908 | /* check magic number with one endianness */ | ||
1909 | if (magic == __perf_magic2) | ||
1910 | return 0; | ||
1911 | |||
1912 | /* check magic number with opposite endianness */ | ||
1913 | if (magic != __perf_magic2_sw) | ||
1914 | return -1; | ||
1915 | |||
1916 | ph->needs_swap = true; | ||
1917 | |||
1918 | return 0; | ||
1919 | } | ||
1920 | |||
1623 | int perf_file_header__read(struct perf_file_header *header, | 1921 | int perf_file_header__read(struct perf_file_header *header, |
1624 | struct perf_header *ph, int fd) | 1922 | struct perf_header *ph, int fd) |
1625 | { | 1923 | { |
1924 | int ret; | ||
1925 | |||
1626 | lseek(fd, 0, SEEK_SET); | 1926 | lseek(fd, 0, SEEK_SET); |
1627 | 1927 | ||
1628 | if (readn(fd, header, sizeof(*header)) <= 0 || | 1928 | ret = readn(fd, header, sizeof(*header)); |
1629 | memcmp(&header->magic, __perf_magic, sizeof(header->magic))) | 1929 | if (ret <= 0) |
1630 | return -1; | 1930 | return -1; |
1631 | 1931 | ||
1632 | if (header->attr_size != sizeof(struct perf_file_attr)) { | 1932 | if (check_magic_endian(header->magic, |
1633 | u64 attr_size = bswap_64(header->attr_size); | 1933 | header->attr_size, false, ph) < 0) { |
1634 | 1934 | pr_debug("magic/endian check failed\n"); | |
1635 | if (attr_size != sizeof(struct perf_file_attr)) | 1935 | return -1; |
1636 | return -1; | 1936 | } |
1637 | 1937 | ||
1938 | if (ph->needs_swap) { | ||
1638 | mem_bswap_64(header, offsetof(struct perf_file_header, | 1939 | mem_bswap_64(header, offsetof(struct perf_file_header, |
1639 | adds_features)); | 1940 | adds_features)); |
1640 | ph->needs_swap = true; | ||
1641 | } | 1941 | } |
1642 | 1942 | ||
1643 | if (header->size != sizeof(*header)) { | 1943 | if (header->size != sizeof(*header)) { |
@@ -1689,156 +1989,6 @@ int perf_file_header__read(struct perf_file_header *header, | |||
1689 | return 0; | 1989 | return 0; |
1690 | } | 1990 | } |
1691 | 1991 | ||
1692 | static int __event_process_build_id(struct build_id_event *bev, | ||
1693 | char *filename, | ||
1694 | struct perf_session *session) | ||
1695 | { | ||
1696 | int err = -1; | ||
1697 | struct list_head *head; | ||
1698 | struct machine *machine; | ||
1699 | u16 misc; | ||
1700 | struct dso *dso; | ||
1701 | enum dso_kernel_type dso_type; | ||
1702 | |||
1703 | machine = perf_session__findnew_machine(session, bev->pid); | ||
1704 | if (!machine) | ||
1705 | goto out; | ||
1706 | |||
1707 | misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1708 | |||
1709 | switch (misc) { | ||
1710 | case PERF_RECORD_MISC_KERNEL: | ||
1711 | dso_type = DSO_TYPE_KERNEL; | ||
1712 | head = &machine->kernel_dsos; | ||
1713 | break; | ||
1714 | case PERF_RECORD_MISC_GUEST_KERNEL: | ||
1715 | dso_type = DSO_TYPE_GUEST_KERNEL; | ||
1716 | head = &machine->kernel_dsos; | ||
1717 | break; | ||
1718 | case PERF_RECORD_MISC_USER: | ||
1719 | case PERF_RECORD_MISC_GUEST_USER: | ||
1720 | dso_type = DSO_TYPE_USER; | ||
1721 | head = &machine->user_dsos; | ||
1722 | break; | ||
1723 | default: | ||
1724 | goto out; | ||
1725 | } | ||
1726 | |||
1727 | dso = __dsos__findnew(head, filename); | ||
1728 | if (dso != NULL) { | ||
1729 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
1730 | |||
1731 | dso__set_build_id(dso, &bev->build_id); | ||
1732 | |||
1733 | if (filename[0] == '[') | ||
1734 | dso->kernel = dso_type; | ||
1735 | |||
1736 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), | ||
1737 | sbuild_id); | ||
1738 | pr_debug("build id event received for %s: %s\n", | ||
1739 | dso->long_name, sbuild_id); | ||
1740 | } | ||
1741 | |||
1742 | err = 0; | ||
1743 | out: | ||
1744 | return err; | ||
1745 | } | ||
1746 | |||
1747 | static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, | ||
1748 | int input, u64 offset, u64 size) | ||
1749 | { | ||
1750 | struct perf_session *session = container_of(header, struct perf_session, header); | ||
1751 | struct { | ||
1752 | struct perf_event_header header; | ||
1753 | u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; | ||
1754 | char filename[0]; | ||
1755 | } old_bev; | ||
1756 | struct build_id_event bev; | ||
1757 | char filename[PATH_MAX]; | ||
1758 | u64 limit = offset + size; | ||
1759 | |||
1760 | while (offset < limit) { | ||
1761 | ssize_t len; | ||
1762 | |||
1763 | if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) | ||
1764 | return -1; | ||
1765 | |||
1766 | if (header->needs_swap) | ||
1767 | perf_event_header__bswap(&old_bev.header); | ||
1768 | |||
1769 | len = old_bev.header.size - sizeof(old_bev); | ||
1770 | if (read(input, filename, len) != len) | ||
1771 | return -1; | ||
1772 | |||
1773 | bev.header = old_bev.header; | ||
1774 | |||
1775 | /* | ||
1776 | * As the pid is the missing value, we need to fill | ||
1777 | * it properly. The header.misc value give us nice hint. | ||
1778 | */ | ||
1779 | bev.pid = HOST_KERNEL_ID; | ||
1780 | if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER || | ||
1781 | bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL) | ||
1782 | bev.pid = DEFAULT_GUEST_KERNEL_ID; | ||
1783 | |||
1784 | memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); | ||
1785 | __event_process_build_id(&bev, filename, session); | ||
1786 | |||
1787 | offset += bev.header.size; | ||
1788 | } | ||
1789 | |||
1790 | return 0; | ||
1791 | } | ||
1792 | |||
1793 | static int perf_header__read_build_ids(struct perf_header *header, | ||
1794 | int input, u64 offset, u64 size) | ||
1795 | { | ||
1796 | struct perf_session *session = container_of(header, struct perf_session, header); | ||
1797 | struct build_id_event bev; | ||
1798 | char filename[PATH_MAX]; | ||
1799 | u64 limit = offset + size, orig_offset = offset; | ||
1800 | int err = -1; | ||
1801 | |||
1802 | while (offset < limit) { | ||
1803 | ssize_t len; | ||
1804 | |||
1805 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | ||
1806 | goto out; | ||
1807 | |||
1808 | if (header->needs_swap) | ||
1809 | perf_event_header__bswap(&bev.header); | ||
1810 | |||
1811 | len = bev.header.size - sizeof(bev); | ||
1812 | if (read(input, filename, len) != len) | ||
1813 | goto out; | ||
1814 | /* | ||
1815 | * The a1645ce1 changeset: | ||
1816 | * | ||
1817 | * "perf: 'perf kvm' tool for monitoring guest performance from host" | ||
1818 | * | ||
1819 | * Added a field to struct build_id_event that broke the file | ||
1820 | * format. | ||
1821 | * | ||
1822 | * Since the kernel build-id is the first entry, process the | ||
1823 | * table using the old format if the well known | ||
1824 | * '[kernel.kallsyms]' string for the kernel build-id has the | ||
1825 | * first 4 characters chopped off (where the pid_t sits). | ||
1826 | */ | ||
1827 | if (memcmp(filename, "nel.kallsyms]", 13) == 0) { | ||
1828 | if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1) | ||
1829 | return -1; | ||
1830 | return perf_header__read_build_ids_abi_quirk(header, input, offset, size); | ||
1831 | } | ||
1832 | |||
1833 | __event_process_build_id(&bev, filename, session); | ||
1834 | |||
1835 | offset += bev.header.size; | ||
1836 | } | ||
1837 | err = 0; | ||
1838 | out: | ||
1839 | return err; | ||
1840 | } | ||
1841 | |||
1842 | static int perf_file_section__process(struct perf_file_section *section, | 1992 | static int perf_file_section__process(struct perf_file_section *section, |
1843 | struct perf_header *ph, | 1993 | struct perf_header *ph, |
1844 | int feat, int fd, void *data __used) | 1994 | int feat, int fd, void *data __used) |
@@ -1854,40 +2004,32 @@ static int perf_file_section__process(struct perf_file_section *section, | |||
1854 | return 0; | 2004 | return 0; |
1855 | } | 2005 | } |
1856 | 2006 | ||
1857 | switch (feat) { | 2007 | if (!feat_ops[feat].process) |
1858 | case HEADER_TRACE_INFO: | 2008 | return 0; |
1859 | trace_report(fd, false); | ||
1860 | break; | ||
1861 | case HEADER_BUILD_ID: | ||
1862 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) | ||
1863 | pr_debug("Failed to read buildids, continuing...\n"); | ||
1864 | break; | ||
1865 | default: | ||
1866 | break; | ||
1867 | } | ||
1868 | 2009 | ||
1869 | return 0; | 2010 | return feat_ops[feat].process(section, ph, feat, fd); |
1870 | } | 2011 | } |
1871 | 2012 | ||
1872 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, | 2013 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, |
1873 | struct perf_header *ph, int fd, | 2014 | struct perf_header *ph, int fd, |
1874 | bool repipe) | 2015 | bool repipe) |
1875 | { | 2016 | { |
1876 | if (readn(fd, header, sizeof(*header)) <= 0 || | 2017 | int ret; |
1877 | memcmp(&header->magic, __perf_magic, sizeof(header->magic))) | ||
1878 | return -1; | ||
1879 | 2018 | ||
1880 | if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) | 2019 | ret = readn(fd, header, sizeof(*header)); |
2020 | if (ret <= 0) | ||
1881 | return -1; | 2021 | return -1; |
1882 | 2022 | ||
1883 | if (header->size != sizeof(*header)) { | 2023 | if (check_magic_endian(header->magic, header->size, true, ph) < 0) { |
1884 | u64 size = bswap_64(header->size); | 2024 | pr_debug("endian/magic failed\n"); |
2025 | return -1; | ||
2026 | } | ||
1885 | 2027 | ||
1886 | if (size != sizeof(*header)) | 2028 | if (ph->needs_swap) |
1887 | return -1; | 2029 | header->size = bswap_64(header->size); |
1888 | 2030 | ||
1889 | ph->needs_swap = true; | 2031 | if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) |
1890 | } | 2032 | return -1; |
1891 | 2033 | ||
1892 | return 0; | 2034 | return 0; |
1893 | } | 2035 | } |
@@ -1908,6 +2050,52 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) | |||
1908 | return 0; | 2050 | return 0; |
1909 | } | 2051 | } |
1910 | 2052 | ||
2053 | static int read_attr(int fd, struct perf_header *ph, | ||
2054 | struct perf_file_attr *f_attr) | ||
2055 | { | ||
2056 | struct perf_event_attr *attr = &f_attr->attr; | ||
2057 | size_t sz, left; | ||
2058 | size_t our_sz = sizeof(f_attr->attr); | ||
2059 | int ret; | ||
2060 | |||
2061 | memset(f_attr, 0, sizeof(*f_attr)); | ||
2062 | |||
2063 | /* read minimal guaranteed structure */ | ||
2064 | ret = readn(fd, attr, PERF_ATTR_SIZE_VER0); | ||
2065 | if (ret <= 0) { | ||
2066 | pr_debug("cannot read %d bytes of header attr\n", | ||
2067 | PERF_ATTR_SIZE_VER0); | ||
2068 | return -1; | ||
2069 | } | ||
2070 | |||
2071 | /* on file perf_event_attr size */ | ||
2072 | sz = attr->size; | ||
2073 | |||
2074 | if (ph->needs_swap) | ||
2075 | sz = bswap_32(sz); | ||
2076 | |||
2077 | if (sz == 0) { | ||
2078 | /* assume ABI0 */ | ||
2079 | sz = PERF_ATTR_SIZE_VER0; | ||
2080 | } else if (sz > our_sz) { | ||
2081 | pr_debug("file uses a more recent and unsupported ABI" | ||
2082 | " (%zu bytes extra)\n", sz - our_sz); | ||
2083 | return -1; | ||
2084 | } | ||
2085 | /* what we have not yet read and that we know about */ | ||
2086 | left = sz - PERF_ATTR_SIZE_VER0; | ||
2087 | if (left) { | ||
2088 | void *ptr = attr; | ||
2089 | ptr += PERF_ATTR_SIZE_VER0; | ||
2090 | |||
2091 | ret = readn(fd, ptr, left); | ||
2092 | } | ||
2093 | /* read perf_file_section, ids are read in caller */ | ||
2094 | ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids)); | ||
2095 | |||
2096 | return ret <= 0 ? -1 : 0; | ||
2097 | } | ||
2098 | |||
1911 | int perf_session__read_header(struct perf_session *session, int fd) | 2099 | int perf_session__read_header(struct perf_session *session, int fd) |
1912 | { | 2100 | { |
1913 | struct perf_header *header = &session->header; | 2101 | struct perf_header *header = &session->header; |
@@ -1923,19 +2111,17 @@ int perf_session__read_header(struct perf_session *session, int fd) | |||
1923 | if (session->fd_pipe) | 2111 | if (session->fd_pipe) |
1924 | return perf_header__read_pipe(session, fd); | 2112 | return perf_header__read_pipe(session, fd); |
1925 | 2113 | ||
1926 | if (perf_file_header__read(&f_header, header, fd) < 0) { | 2114 | if (perf_file_header__read(&f_header, header, fd) < 0) |
1927 | pr_debug("incompatible file format\n"); | ||
1928 | return -EINVAL; | 2115 | return -EINVAL; |
1929 | } | ||
1930 | 2116 | ||
1931 | nr_attrs = f_header.attrs.size / sizeof(f_attr); | 2117 | nr_attrs = f_header.attrs.size / f_header.attr_size; |
1932 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 2118 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
1933 | 2119 | ||
1934 | for (i = 0; i < nr_attrs; i++) { | 2120 | for (i = 0; i < nr_attrs; i++) { |
1935 | struct perf_evsel *evsel; | 2121 | struct perf_evsel *evsel; |
1936 | off_t tmp; | 2122 | off_t tmp; |
1937 | 2123 | ||
1938 | if (readn(fd, &f_attr, sizeof(f_attr)) <= 0) | 2124 | if (read_attr(fd, header, &f_attr) < 0) |
1939 | goto out_errno; | 2125 | goto out_errno; |
1940 | 2126 | ||
1941 | if (header->needs_swap) | 2127 | if (header->needs_swap) |