1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include "util/cgroup.h" 4 #include "util/data.h" 5 #include "util/debug.h" 6 #include "util/dso.h" 7 #include "util/event.h" 8 #include "util/evlist.h" 9 #include "util/machine.h" 10 #include "util/map.h" 11 #include "util/map_symbol.h" 12 #include "util/branch.h" 13 #include "util/memswap.h" 14 #include "util/namespaces.h" 15 #include "util/session.h" 16 #include "util/stat.h" 17 #include "util/symbol.h" 18 #include "util/synthetic-events.h" 19 #include "util/target.h" 20 #include "util/time-utils.h" 21 #include <linux/bitops.h> 22 #include <linux/kernel.h> 23 #include <linux/string.h> 24 #include <linux/zalloc.h> 25 #include <linux/perf_event.h> 26 #include <asm/bug.h> 27 #include <perf/evsel.h> 28 #include <perf/cpumap.h> 29 #include <internal/lib.h> // page_size 30 #include <internal/threadmap.h> 31 #include <perf/threadmap.h> 32 #include <symbol/kallsyms.h> 33 #include <dirent.h> 34 #include <errno.h> 35 #include <inttypes.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 39 #include <api/fs/fs.h> 40 #include <api/io.h> 41 #include <api/io_dir.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <fcntl.h> 45 #include <unistd.h> 46 47 #define DEFAULT_PROC_MAP_PARSE_TIMEOUT 500 48 49 unsigned int proc_map_timeout = DEFAULT_PROC_MAP_PARSE_TIMEOUT; 50 51 int perf_tool__process_synth_event(const struct perf_tool *tool, 52 union perf_event *event, 53 struct machine *machine, 54 perf_event__handler_t process) 55 { 56 struct perf_sample synth_sample = { 57 .pid = -1, 58 .tid = -1, 59 .time = -1, 60 .stream_id = -1, 61 .cpu = -1, 62 .period = 1, 63 .cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK, 64 }; 65 66 return process(tool, event, &synth_sample, machine); 67 }; 68 69 /* 70 * Assumes that the first 4095 bytes of /proc/pid/stat contains 71 * the comm, tgid and ppid. 72 */ 73 static int perf_event__get_comm_ids(pid_t pid, pid_t tid, char *comm, size_t len, 74 pid_t *tgid, pid_t *ppid, bool *kernel) 75 { 76 char bf[4096]; 77 int fd; 78 size_t size = 0; 79 ssize_t n; 80 char *name, *tgids, *ppids, *vmpeak, *threads; 81 82 *tgid = -1; 83 *ppid = -1; 84 85 if (pid) 86 snprintf(bf, sizeof(bf), "/proc/%d/task/%d/status", pid, tid); 87 else 88 snprintf(bf, sizeof(bf), "/proc/%d/status", tid); 89 90 fd = open(bf, O_RDONLY); 91 if (fd < 0) { 92 pr_debug("couldn't open %s\n", bf); 93 return -1; 94 } 95 96 n = read(fd, bf, sizeof(bf) - 1); 97 close(fd); 98 if (n <= 0) { 99 pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n", 100 tid); 101 return -1; 102 } 103 bf[n] = '\0'; 104 105 name = strstr(bf, "Name:"); 106 tgids = strstr(name ?: bf, "Tgid:"); 107 ppids = strstr(tgids ?: bf, "PPid:"); 108 vmpeak = strstr(ppids ?: bf, "VmPeak:"); 109 110 if (vmpeak) 111 threads = NULL; 112 else 113 threads = strstr(ppids ?: bf, "Threads:"); 114 115 if (name) { 116 char *nl; 117 118 name = skip_spaces(name + 5); /* strlen("Name:") */ 119 nl = strchr(name, '\n'); 120 if (nl) 121 *nl = '\0'; 122 123 size = strlen(name); 124 if (size >= len) 125 size = len - 1; 126 memcpy(comm, name, size); 127 comm[size] = '\0'; 128 } else { 129 pr_debug("Name: string not found for pid %d\n", tid); 130 } 131 132 if (tgids) { 133 tgids += 5; /* strlen("Tgid:") */ 134 *tgid = atoi(tgids); 135 } else { 136 pr_debug("Tgid: string not found for pid %d\n", tid); 137 } 138 139 if (ppids) { 140 ppids += 5; /* strlen("PPid:") */ 141 *ppid = atoi(ppids); 142 } else { 143 pr_debug("PPid: string not found for pid %d\n", tid); 144 } 145 146 if (!vmpeak && threads) 147 *kernel = true; 148 else 149 *kernel = false; 150 151 return 0; 152 } 153 154 static int perf_event__prepare_comm(union perf_event *event, pid_t pid, pid_t tid, 155 struct machine *machine, 156 pid_t *tgid, pid_t *ppid, bool *kernel) 157 { 158 size_t size; 159 160 *ppid = -1; 161 162 memset(&event->comm, 0, sizeof(event->comm)); 163 164 if (machine__is_host(machine)) { 165 if (perf_event__get_comm_ids(pid, tid, event->comm.comm, 166 sizeof(event->comm.comm), 167 tgid, ppid, kernel) != 0) { 168 return -1; 169 } 170 } else { 171 *tgid = machine->pid; 172 } 173 174 if (*tgid < 0) 175 return -1; 176 177 event->comm.pid = *tgid; 178 event->comm.header.type = PERF_RECORD_COMM; 179 180 size = strlen(event->comm.comm) + 1; 181 size = PERF_ALIGN(size, sizeof(u64)); 182 memset((char *)event + offsetof(struct perf_record_comm, comm) + size, 183 0, machine->id_hdr_size); 184 event->comm.header.size = (sizeof(event->comm) - 185 (sizeof(event->comm.comm) - size) + 186 machine->id_hdr_size); 187 event->comm.tid = tid; 188 189 return 0; 190 } 191 192 pid_t perf_event__synthesize_comm(const struct perf_tool *tool, 193 union perf_event *event, pid_t pid, 194 perf_event__handler_t process, 195 struct machine *machine) 196 { 197 pid_t tgid, ppid; 198 bool kernel_thread; 199 200 if (perf_event__prepare_comm(event, 0, pid, machine, &tgid, &ppid, 201 &kernel_thread) != 0) 202 return -1; 203 204 if (perf_tool__process_synth_event(tool, event, machine, process) != 0) 205 return -1; 206 207 return tgid; 208 } 209 210 static void perf_event__get_ns_link_info(pid_t pid, const char *ns, 211 struct perf_ns_link_info *ns_link_info) 212 { 213 struct stat64 st; 214 char proc_ns[128]; 215 216 sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns); 217 if (stat64(proc_ns, &st) == 0) { 218 ns_link_info->dev = st.st_dev; 219 ns_link_info->ino = st.st_ino; 220 } 221 } 222 223 int perf_event__synthesize_namespaces(const struct perf_tool *tool, 224 union perf_event *event, 225 pid_t pid, pid_t tgid, 226 perf_event__handler_t process, 227 struct machine *machine) 228 { 229 u32 idx; 230 struct perf_ns_link_info *ns_link_info; 231 232 if (!tool || !tool->namespace_events) 233 return 0; 234 235 memset(&event->namespaces, 0, (sizeof(event->namespaces) + 236 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 237 machine->id_hdr_size)); 238 239 event->namespaces.pid = tgid; 240 event->namespaces.tid = pid; 241 242 event->namespaces.nr_namespaces = NR_NAMESPACES; 243 244 ns_link_info = event->namespaces.link_info; 245 246 for (idx = 0; idx < event->namespaces.nr_namespaces; idx++) 247 perf_event__get_ns_link_info(pid, perf_ns__name(idx), 248 &ns_link_info[idx]); 249 250 event->namespaces.header.type = PERF_RECORD_NAMESPACES; 251 252 event->namespaces.header.size = (sizeof(event->namespaces) + 253 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 254 machine->id_hdr_size); 255 256 if (perf_tool__process_synth_event(tool, event, machine, process) != 0) 257 return -1; 258 259 return 0; 260 } 261 262 static int perf_event__synthesize_fork(const struct perf_tool *tool, 263 union perf_event *event, 264 pid_t pid, pid_t tgid, pid_t ppid, 265 perf_event__handler_t process, 266 struct machine *machine) 267 { 268 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 269 270 /* 271 * for main thread set parent to ppid from status file. For other 272 * threads set parent pid to main thread. ie., assume main thread 273 * spawns all threads in a process 274 */ 275 if (tgid == pid) { 276 event->fork.ppid = ppid; 277 event->fork.ptid = ppid; 278 } else { 279 event->fork.ppid = tgid; 280 event->fork.ptid = tgid; 281 } 282 event->fork.pid = tgid; 283 event->fork.tid = pid; 284 event->fork.header.type = PERF_RECORD_FORK; 285 event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC; 286 287 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); 288 289 if (perf_tool__process_synth_event(tool, event, machine, process) != 0) 290 return -1; 291 292 return 0; 293 } 294 295 static void io__drain_line(struct io *io, int ch) 296 { 297 if (ch == '\n') 298 return; 299 if (ch == -2 && io->data > io->buf && io->data[-1] == '\n') 300 return; 301 302 do { 303 ch = io__get_char(io); 304 } while (ch >= 0 && ch != '\n'); 305 } 306 307 static bool read_proc_maps_line(struct io *io, __u64 *start, __u64 *end, 308 u32 *prot, u32 *flags, __u64 *offset, 309 u32 *maj, u32 *min, 310 __u64 *inode, 311 ssize_t pathname_size, char *pathname) 312 { 313 __u64 temp; 314 int ch; 315 size_t written = 0; 316 bool overflowed = false; 317 318 ch = io__get_hex(io, start); 319 if (ch != '-') { 320 if (!io->eof) 321 io__drain_line(io, ch); 322 return false; 323 } 324 ch = io__get_hex(io, end); 325 if (ch != ' ') { 326 if (!io->eof) 327 io__drain_line(io, ch); 328 return false; 329 } 330 331 /* map protection and flags bits */ 332 *prot = 0; 333 ch = io__get_char(io); 334 if (ch == 'r') 335 *prot |= PROT_READ; 336 else if (ch != '-') { 337 if (!io->eof) 338 io__drain_line(io, ch); 339 return false; 340 } 341 ch = io__get_char(io); 342 if (ch == 'w') 343 *prot |= PROT_WRITE; 344 else if (ch != '-') { 345 if (!io->eof) 346 io__drain_line(io, ch); 347 return false; 348 } 349 ch = io__get_char(io); 350 if (ch == 'x') 351 *prot |= PROT_EXEC; 352 else if (ch != '-') { 353 if (!io->eof) 354 io__drain_line(io, ch); 355 return false; 356 } 357 ch = io__get_char(io); 358 if (ch == 's') 359 *flags = MAP_SHARED; 360 else if (ch == 'p') 361 *flags = MAP_PRIVATE; 362 else { 363 if (!io->eof) 364 io__drain_line(io, ch); 365 return false; 366 } 367 ch = io__get_char(io); 368 if (ch != ' ') { 369 if (!io->eof) 370 io__drain_line(io, ch); 371 return false; 372 } 373 374 ch = io__get_hex(io, offset); 375 if (ch != ' ') { 376 if (!io->eof) 377 io__drain_line(io, ch); 378 return false; 379 } 380 381 ch = io__get_hex(io, &temp); 382 if (ch != ':') { 383 if (!io->eof) 384 io__drain_line(io, ch); 385 return false; 386 } 387 *maj = temp; 388 ch = io__get_hex(io, &temp); 389 if (ch != ' ') { 390 if (!io->eof) 391 io__drain_line(io, ch); 392 return false; 393 } 394 *min = temp; 395 396 ch = io__get_dec(io, inode); 397 if (ch != ' ') { 398 if (ch == '\n') { 399 pathname[0] = '\0'; 400 return true; 401 } 402 if (!io->eof) 403 io__drain_line(io, ch); 404 return false; 405 } 406 407 do { 408 ch = io__get_char(io); 409 } while (ch == ' '); 410 411 while (true) { 412 if (ch < 0) { 413 if (overflowed) { 414 strlcpy(pathname, "//toolong", pathname_size); 415 return true; 416 } 417 pathname[written] = '\0'; 418 return written > 0; 419 } 420 if (ch == '\0' || ch == '\n') 421 break; 422 423 if (written < (size_t)pathname_size - 1) 424 pathname[written++] = (char)ch; 425 else 426 overflowed = true; 427 ch = io__get_char(io); 428 } 429 430 if (overflowed) 431 strlcpy(pathname, "//toolong", pathname_size); 432 else 433 pathname[written] = '\0'; 434 435 return true; 436 } 437 438 static void perf_record_mmap2__read_build_id(struct perf_record_mmap2 *event, 439 struct machine *machine, 440 bool is_kernel) 441 { 442 struct build_id bid = { .size = 0, }; 443 struct nsinfo *nsi; 444 struct nscookie nc; 445 struct dso *dso = NULL; 446 struct dso_id dso_id = dso_id_empty; 447 int rc; 448 449 if (is_kernel) { 450 rc = sysfs__read_build_id("/sys/kernel/notes", &bid); 451 goto out; 452 } 453 454 if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) { 455 build_id__init(&dso_id.build_id, event->build_id, event->build_id_size); 456 } else { 457 dso_id.maj = event->maj; 458 dso_id.min = event->min; 459 dso_id.ino = event->ino; 460 dso_id.ino_generation = event->ino_generation; 461 dso_id.mmap2_valid = true; 462 dso_id.mmap2_ino_generation_valid = true; 463 } 464 465 dso = dsos__findnew_id(&machine->dsos, event->filename, &dso_id); 466 if (dso && dso__has_build_id(dso)) { 467 bid = *dso__bid(dso); 468 rc = 0; 469 goto out; 470 } 471 472 nsi = nsinfo__new(event->pid); 473 nsinfo__mountns_enter(nsi, &nc); 474 475 rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1; 476 477 nsinfo__mountns_exit(&nc); 478 nsinfo__put(nsi); 479 480 out: 481 if (rc == 0) { 482 memcpy(event->build_id, bid.data, sizeof(bid.data)); 483 event->build_id_size = (u8) bid.size; 484 event->header.misc |= PERF_RECORD_MISC_MMAP_BUILD_ID; 485 event->__reserved_1 = 0; 486 event->__reserved_2 = 0; 487 488 if (dso && !dso__has_build_id(dso)) 489 dso__set_build_id(dso, &bid); 490 } else { 491 if (event->filename[0] == '/') { 492 pr_debug2("Failed to read build ID for %s\n", 493 event->filename); 494 } 495 } 496 dso__put(dso); 497 } 498 499 int perf_event__synthesize_mmap_events(const struct perf_tool *tool, 500 union perf_event *event, 501 pid_t pid, pid_t tgid, 502 perf_event__handler_t process, 503 struct machine *machine, 504 bool mmap_data) 505 { 506 unsigned long long t; 507 char bf[BUFSIZ]; 508 struct io io; 509 bool truncation = false; 510 unsigned long long timeout = proc_map_timeout * 1000000ULL; 511 int rc = 0; 512 const char *hugetlbfs_mnt = hugetlbfs__mountpoint(); 513 int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0; 514 515 if (machine__is_default_guest(machine)) 516 return 0; 517 518 snprintf(bf, sizeof(bf), "%s/proc/%d/task/%d/maps", 519 machine->root_dir, pid, pid); 520 521 io.fd = open(bf, O_RDONLY, 0); 522 if (io.fd < 0) { 523 /* 524 * We raced with a task exiting - just return: 525 */ 526 pr_debug("couldn't open %s\n", bf); 527 return -1; 528 } 529 io__init(&io, io.fd, bf, sizeof(bf)); 530 531 event->header.type = PERF_RECORD_MMAP2; 532 t = rdclock(); 533 534 while (!io.eof) { 535 static const char anonstr[] = "//anon"; 536 size_t size, aligned_size; 537 __u64 start, end, pgoff, ino; 538 u32 prot, flags, maj, min; 539 540 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 541 /* Read directly into event->mmap2.filename, clamping for id_hdr_size! */ 542 if (!read_proc_maps_line(&io, &start, &end, 543 &prot, &flags, &pgoff, 544 &maj, &min, &ino, 545 sizeof(event->mmap2.filename) - machine->id_hdr_size, 546 event->mmap2.filename)) { 547 if (io.eof) 548 break; 549 continue; 550 } 551 552 if (!strcmp(event->mmap2.filename, "")) 553 strcpy(event->mmap2.filename, anonstr); 554 555 if (hugetlbfs_mnt_len && 556 !strncmp(event->mmap2.filename, hugetlbfs_mnt, hugetlbfs_mnt_len)) { 557 strcpy(event->mmap2.filename, anonstr); 558 flags |= MAP_HUGETLB; 559 } 560 561 size = strlen(event->mmap2.filename) + 1; 562 aligned_size = PERF_ALIGN(size, sizeof(u64)); 563 564 event->mmap2.header.type = PERF_RECORD_MMAP2; 565 566 /* 567 * Just like the kernel, see perf_misc_flags() in 568 * kernel/events/core.c 569 */ 570 if (machine__is_host(machine)) 571 event->header.misc = PERF_RECORD_MISC_USER; 572 else 573 event->header.misc = PERF_RECORD_MISC_GUEST_USER; 574 575 if ((rdclock() - t) > timeout) { 576 pr_warning("Reading %s/proc/%d/task/%d/maps time out. You may want to increase the time limit by --proc-map-timeout\n", 577 machine->root_dir, pid, pid); 578 truncation = true; 579 goto out; 580 } 581 582 if ((prot & PROT_EXEC) == 0) { 583 if (!mmap_data || (prot & PROT_READ) == 0) 584 continue; 585 586 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; 587 } 588 589 out: 590 if (truncation) 591 event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT; 592 593 event->mmap2.header.size = 594 offsetof(struct perf_record_mmap2, filename) + 595 aligned_size; 596 597 /* Zero the padding and ID header trailer safely! */ 598 memset((char *)event + offsetof(struct perf_record_mmap2, filename) + size, 0, 599 (aligned_size - size) + machine->id_hdr_size); 600 601 event->mmap2.header.size += machine->id_hdr_size; 602 event->mmap2.start = start; 603 event->mmap2.len = end - start; 604 event->mmap2.pgoff = pgoff; 605 event->mmap2.maj = maj; 606 event->mmap2.min = min; 607 event->mmap2.ino = ino; 608 event->mmap2.ino_generation = 0; 609 event->mmap2.pid = tgid; 610 event->mmap2.tid = pid; 611 event->mmap2.prot = prot; 612 event->mmap2.flags = flags; 613 614 if (!symbol_conf.no_buildid_mmap2) 615 perf_record_mmap2__read_build_id(&event->mmap2, machine, false); 616 617 if (perf_tool__process_synth_event(tool, event, machine, process) != 0) { 618 rc = -1; 619 break; 620 } 621 622 if (truncation) 623 break; 624 } 625 626 close(io.fd); 627 return rc; 628 } 629 630 #ifdef HAVE_FILE_HANDLE 631 static int perf_event__synthesize_cgroup(const struct perf_tool *tool, 632 union perf_event *event, 633 char *path, size_t mount_len, 634 perf_event__handler_t process, 635 struct machine *machine) 636 { 637 size_t event_size = sizeof(event->cgroup) - sizeof(event->cgroup.path); 638 size_t raw_path_len, path_len, max_path_len; 639 struct { 640 struct file_handle fh; 641 uint64_t cgroup_id; 642 } handle; 643 int mount_id; 644 645 if (strlen(path) < mount_len) 646 return -1; 647 648 max_path_len = sizeof(event->cgroup.path) - machine->id_hdr_size; 649 raw_path_len = strlen(path) - mount_len + 1; 650 if (raw_path_len > max_path_len) 651 raw_path_len = max_path_len; 652 653 path_len = PERF_ALIGN(raw_path_len, sizeof(u64)); 654 655 memset(&event->cgroup, 0, event_size); 656 657 event->cgroup.header.type = PERF_RECORD_CGROUP; 658 event->cgroup.header.size = event_size + path_len + machine->id_hdr_size; 659 660 handle.fh.handle_bytes = sizeof(handle.cgroup_id); 661 if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0) { 662 pr_debug("stat failed: %s\n", path); 663 return -1; 664 } 665 666 event->cgroup.id = handle.cgroup_id; 667 strlcpy(event->cgroup.path, path + mount_len, raw_path_len); 668 memset((char *)event + offsetof(struct perf_record_cgroup, path) + raw_path_len, 669 0, (path_len - raw_path_len) + machine->id_hdr_size); 670 671 if (perf_tool__process_synth_event(tool, event, machine, process) < 0) { 672 pr_debug("process synth event failed\n"); 673 return -1; 674 } 675 676 return 0; 677 } 678 679 static int perf_event__walk_cgroup_tree(const struct perf_tool *tool, 680 union perf_event *event, 681 char *path, size_t mount_len, 682 perf_event__handler_t process, 683 struct machine *machine) 684 { 685 size_t pos = strlen(path); 686 DIR *d; 687 struct dirent *dent; 688 int ret = 0; 689 690 if (perf_event__synthesize_cgroup(tool, event, path, mount_len, 691 process, machine) < 0) 692 return -1; 693 694 d = opendir(path); 695 if (d == NULL) { 696 pr_debug("failed to open directory: %s\n", path); 697 return -1; 698 } 699 700 while ((dent = readdir(d)) != NULL) { 701 if (dent->d_type != DT_DIR) 702 continue; 703 if (!strcmp(dent->d_name, ".") || 704 !strcmp(dent->d_name, "..")) 705 continue; 706 707 /* any sane path should be less than PATH_MAX */ 708 if (strlen(path) + strlen(dent->d_name) + 1 >= PATH_MAX) 709 continue; 710 711 if (path[pos - 1] != '/') 712 strcat(path, "/"); 713 strcat(path, dent->d_name); 714 715 ret = perf_event__walk_cgroup_tree(tool, event, path, 716 mount_len, process, machine); 717 if (ret < 0) 718 break; 719 720 path[pos] = '\0'; 721 } 722 723 closedir(d); 724 return ret; 725 } 726 727 int perf_event__synthesize_cgroups(const struct perf_tool *tool, 728 perf_event__handler_t process, 729 struct machine *machine) 730 { 731 union perf_event event; 732 char cgrp_root[PATH_MAX]; 733 size_t mount_len; /* length of mount point in the path */ 734 735 if (!tool || !tool->cgroup_events) 736 return 0; 737 738 if (cgroupfs_find_mountpoint(cgrp_root, PATH_MAX, "perf_event") < 0) { 739 pr_debug("cannot find cgroup mount point\n"); 740 return -1; 741 } 742 743 mount_len = strlen(cgrp_root); 744 /* make sure the path starts with a slash (after mount point) */ 745 strcat(cgrp_root, "/"); 746 747 if (perf_event__walk_cgroup_tree(tool, &event, cgrp_root, mount_len, 748 process, machine) < 0) 749 return -1; 750 751 return 0; 752 } 753 #else 754 int perf_event__synthesize_cgroups(const struct perf_tool *tool __maybe_unused, 755 perf_event__handler_t process __maybe_unused, 756 struct machine *machine __maybe_unused) 757 { 758 return -1; 759 } 760 #endif 761 762 struct perf_event__synthesize_modules_maps_cb_args { 763 const struct perf_tool *tool; 764 perf_event__handler_t process; 765 struct machine *machine; 766 union perf_event *event; 767 u16 misc; 768 }; 769 770 static int perf_event__synthesize_modules_maps_cb(struct map *map, void *data) 771 { 772 struct perf_event__synthesize_modules_maps_cb_args *args = data; 773 union perf_event *event = args->event; 774 struct dso *dso; 775 size_t size, aligned_size; 776 int rc = 0; 777 778 if (!__map__is_kmodule(map)) 779 return 0; 780 781 dso = map__dso(map); 782 if (!symbol_conf.no_buildid_mmap2) { 783 const char *long_name = dso__long_name(dso); 784 785 size = strlen(long_name); 786 if (size >= sizeof(event->mmap2.filename) - args->machine->id_hdr_size) 787 size = sizeof(event->mmap2.filename) - args->machine->id_hdr_size - 1; 788 789 strlcpy(event->mmap2.filename, long_name, 790 sizeof(event->mmap2.filename) - args->machine->id_hdr_size); 791 792 aligned_size = PERF_ALIGN(size + 1, sizeof(u64)); 793 event->mmap2.header.type = PERF_RECORD_MMAP2; 794 event->mmap2.header.misc = args->misc; 795 event->mmap2.header.size = 796 offsetof(struct perf_record_mmap2, filename) + 797 aligned_size; 798 799 /* Zero the padding and ID header trailer safely! */ 800 memset((char *)event + offsetof(struct perf_record_mmap2, filename) + size, 0, 801 (aligned_size - size) + args->machine->id_hdr_size); 802 803 event->mmap2.header.size += args->machine->id_hdr_size; 804 event->mmap2.start = map__start(map); 805 event->mmap2.len = map__size(map); 806 event->mmap2.pid = args->machine->pid; 807 808 /* Clear stale build ID and entire union from previous module iteration */ 809 event->mmap2.header.misc &= ~PERF_RECORD_MISC_MMAP_BUILD_ID; 810 memset(event->mmap2.build_id, 0, sizeof(event->mmap2.build_id)); 811 event->mmap2.build_id_size = 0; 812 event->mmap2.__reserved_1 = 0; 813 event->mmap2.__reserved_2 = 0; 814 815 perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false); 816 } else { 817 const char *long_name = dso__long_name(dso); 818 819 size = strlen(long_name); 820 if (size >= sizeof(event->mmap.filename) - args->machine->id_hdr_size) 821 size = sizeof(event->mmap.filename) - args->machine->id_hdr_size - 1; 822 823 strlcpy(event->mmap.filename, long_name, 824 sizeof(event->mmap.filename) - args->machine->id_hdr_size); 825 826 aligned_size = PERF_ALIGN(size + 1, sizeof(u64)); 827 event->mmap.header.type = PERF_RECORD_MMAP; 828 event->mmap.header.misc = args->misc; 829 event->mmap.header.size = 830 offsetof(struct perf_record_mmap, filename) + 831 aligned_size; 832 833 /* Zero the padding and ID header trailer safely! */ 834 memset((char *)event + offsetof(struct perf_record_mmap, filename) + size, 0, 835 (aligned_size - size) + args->machine->id_hdr_size); 836 837 event->mmap.header.size += args->machine->id_hdr_size; 838 event->mmap.start = map__start(map); 839 event->mmap.len = map__size(map); 840 event->mmap.pid = args->machine->pid; 841 } 842 843 if (perf_tool__process_synth_event(args->tool, event, args->machine, args->process) != 0) 844 rc = -1; 845 846 return rc; 847 } 848 849 int perf_event__synthesize_modules(const struct perf_tool *tool, perf_event__handler_t process, 850 struct machine *machine) 851 { 852 int rc; 853 struct maps *maps = machine__kernel_maps(machine); 854 struct perf_event__synthesize_modules_maps_cb_args args = { 855 .tool = tool, 856 .process = process, 857 .machine = machine, 858 }; 859 size_t size = symbol_conf.no_buildid_mmap2 860 ? sizeof(args.event->mmap) 861 : sizeof(args.event->mmap2); 862 863 args.event = zalloc(size + machine->id_hdr_size); 864 if (args.event == NULL) { 865 pr_debug("Not enough memory synthesizing mmap event " 866 "for kernel modules\n"); 867 return -1; 868 } 869 870 /* 871 * Just like the kernel, see perf_misc_flags() in 872 * kernel/events/core.c 873 */ 874 if (machine__is_host(machine)) 875 args.misc = PERF_RECORD_MISC_KERNEL; 876 else 877 args.misc = PERF_RECORD_MISC_GUEST_KERNEL; 878 879 rc = maps__for_each_map(maps, perf_event__synthesize_modules_maps_cb, &args); 880 881 free(args.event); 882 return rc; 883 } 884 885 static int filter_task(const struct dirent *dirent) 886 { 887 return isdigit(dirent->d_name[0]); 888 } 889 890 static int __event__synthesize_thread(union perf_event *comm_event, 891 union perf_event *mmap_event, 892 union perf_event *fork_event, 893 union perf_event *namespaces_event, 894 pid_t pid, int full, perf_event__handler_t process, 895 const struct perf_tool *tool, struct machine *machine, 896 bool needs_mmap, bool mmap_data) 897 { 898 char filename[PATH_MAX]; 899 struct io_dir iod; 900 struct io_dirent64 *dent; 901 pid_t tgid, ppid; 902 int rc = 0; 903 904 /* special case: only send one comm event using passed in pid */ 905 if (!full) { 906 tgid = perf_event__synthesize_comm(tool, comm_event, pid, 907 process, machine); 908 909 if (tgid == -1) 910 return -1; 911 912 if (perf_event__synthesize_namespaces(tool, namespaces_event, pid, 913 tgid, process, machine) < 0) 914 return -1; 915 916 /* 917 * send mmap only for thread group leader 918 * see thread__init_maps() 919 */ 920 if (pid == tgid && needs_mmap && 921 perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 922 process, machine, mmap_data)) 923 return -1; 924 925 return 0; 926 } 927 928 if (machine__is_default_guest(machine)) 929 return 0; 930 931 snprintf(filename, sizeof(filename), "%s/proc/%d/task", 932 machine->root_dir, pid); 933 934 io_dir__init(&iod, open(filename, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); 935 if (iod.dirfd < 0) 936 return -1; 937 938 while ((dent = io_dir__readdir(&iod)) != NULL) { 939 char *end; 940 pid_t _pid; 941 bool kernel_thread = false; 942 943 if (!isdigit(dent->d_name[0])) 944 continue; 945 946 _pid = strtol(dent->d_name, &end, 10); 947 if (*end) 948 continue; 949 950 /* some threads may exit just after scan, ignore it */ 951 if (perf_event__prepare_comm(comm_event, pid, _pid, machine, 952 &tgid, &ppid, &kernel_thread) != 0) 953 continue; 954 955 rc = -1; 956 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, 957 ppid, process, machine) < 0) 958 break; 959 960 if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid, 961 tgid, process, machine) < 0) 962 break; 963 964 /* 965 * Send the prepared comm event 966 */ 967 if (perf_tool__process_synth_event(tool, comm_event, machine, process) != 0) 968 break; 969 970 rc = 0; 971 if (_pid == pid && !kernel_thread && needs_mmap) { 972 /* process the parent's maps too */ 973 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 974 process, machine, mmap_data); 975 if (rc) 976 break; 977 } 978 } 979 980 close(iod.dirfd); 981 982 return rc; 983 } 984 985 int perf_event__synthesize_thread_map(const struct perf_tool *tool, 986 struct perf_thread_map *threads, 987 perf_event__handler_t process, 988 struct machine *machine, 989 bool needs_mmap, bool mmap_data) 990 { 991 union perf_event *comm_event, *mmap_event, *fork_event; 992 union perf_event *namespaces_event; 993 int err = -1, thread, j; 994 995 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 996 if (comm_event == NULL) 997 goto out; 998 999 mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size); 1000 if (mmap_event == NULL) 1001 goto out_free_comm; 1002 1003 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size); 1004 if (fork_event == NULL) 1005 goto out_free_mmap; 1006 1007 namespaces_event = malloc(sizeof(namespaces_event->namespaces) + 1008 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1009 machine->id_hdr_size); 1010 if (namespaces_event == NULL) 1011 goto out_free_fork; 1012 1013 err = 0; 1014 for (thread = 0; thread < threads->nr; ++thread) { 1015 if (__event__synthesize_thread(comm_event, mmap_event, 1016 fork_event, namespaces_event, 1017 perf_thread_map__pid(threads, thread), 0, 1018 process, tool, machine, 1019 needs_mmap, mmap_data)) { 1020 err = -1; 1021 break; 1022 } 1023 1024 /* 1025 * comm.pid is set to thread group id by 1026 * perf_event__synthesize_comm 1027 */ 1028 if ((int) comm_event->comm.pid != perf_thread_map__pid(threads, thread)) { 1029 bool need_leader = true; 1030 1031 /* is thread group leader in thread_map? */ 1032 for (j = 0; j < threads->nr; ++j) { 1033 if ((int) comm_event->comm.pid == perf_thread_map__pid(threads, j)) { 1034 need_leader = false; 1035 break; 1036 } 1037 } 1038 1039 /* if not, generate events for it */ 1040 if (need_leader && 1041 __event__synthesize_thread(comm_event, mmap_event, 1042 fork_event, namespaces_event, 1043 comm_event->comm.pid, 0, 1044 process, tool, machine, 1045 needs_mmap, mmap_data)) { 1046 err = -1; 1047 break; 1048 } 1049 } 1050 } 1051 free(namespaces_event); 1052 out_free_fork: 1053 free(fork_event); 1054 out_free_mmap: 1055 free(mmap_event); 1056 out_free_comm: 1057 free(comm_event); 1058 out: 1059 return err; 1060 } 1061 1062 static int __perf_event__synthesize_threads(const struct perf_tool *tool, 1063 perf_event__handler_t process, 1064 struct machine *machine, 1065 bool needs_mmap, 1066 bool mmap_data, 1067 struct dirent **dirent, 1068 int start, 1069 int num) 1070 { 1071 union perf_event *comm_event, *mmap_event, *fork_event; 1072 union perf_event *namespaces_event; 1073 int err = -1; 1074 char *end; 1075 pid_t pid; 1076 int i; 1077 1078 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 1079 if (comm_event == NULL) 1080 goto out; 1081 1082 mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size); 1083 if (mmap_event == NULL) 1084 goto out_free_comm; 1085 1086 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size); 1087 if (fork_event == NULL) 1088 goto out_free_mmap; 1089 1090 namespaces_event = malloc(sizeof(namespaces_event->namespaces) + 1091 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1092 machine->id_hdr_size); 1093 if (namespaces_event == NULL) 1094 goto out_free_fork; 1095 1096 for (i = start; i < start + num; i++) { 1097 if (!isdigit(dirent[i]->d_name[0])) 1098 continue; 1099 1100 pid = (pid_t)strtol(dirent[i]->d_name, &end, 10); 1101 /* only interested in proper numerical dirents */ 1102 if (*end) 1103 continue; 1104 /* 1105 * We may race with exiting thread, so don't stop just because 1106 * one thread couldn't be synthesized. 1107 */ 1108 __event__synthesize_thread(comm_event, mmap_event, fork_event, 1109 namespaces_event, pid, 1, process, 1110 tool, machine, needs_mmap, mmap_data); 1111 } 1112 err = 0; 1113 1114 free(namespaces_event); 1115 out_free_fork: 1116 free(fork_event); 1117 out_free_mmap: 1118 free(mmap_event); 1119 out_free_comm: 1120 free(comm_event); 1121 out: 1122 return err; 1123 } 1124 1125 struct synthesize_threads_arg { 1126 const struct perf_tool *tool; 1127 perf_event__handler_t process; 1128 struct machine *machine; 1129 bool needs_mmap; 1130 bool mmap_data; 1131 struct dirent **dirent; 1132 int num; 1133 int start; 1134 }; 1135 1136 static void *synthesize_threads_worker(void *arg) 1137 { 1138 struct synthesize_threads_arg *args = arg; 1139 1140 __perf_event__synthesize_threads(args->tool, args->process, 1141 args->machine, 1142 args->needs_mmap, args->mmap_data, 1143 args->dirent, 1144 args->start, args->num); 1145 return NULL; 1146 } 1147 1148 int perf_event__synthesize_threads(const struct perf_tool *tool, 1149 perf_event__handler_t process, 1150 struct machine *machine, 1151 bool needs_mmap, bool mmap_data, 1152 unsigned int nr_threads_synthesize) 1153 { 1154 struct synthesize_threads_arg *args = NULL; 1155 pthread_t *synthesize_threads = NULL; 1156 char proc_path[PATH_MAX]; 1157 struct dirent **dirent; 1158 int num_per_thread; 1159 int m, n, i, j; 1160 int thread_nr; 1161 int base = 0; 1162 int err = -1; 1163 1164 1165 if (machine__is_default_guest(machine)) 1166 return 0; 1167 1168 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); 1169 n = scandir(proc_path, &dirent, filter_task, NULL); 1170 if (n < 0) 1171 return err; 1172 1173 if (nr_threads_synthesize == UINT_MAX) 1174 thread_nr = sysconf(_SC_NPROCESSORS_ONLN); 1175 else 1176 thread_nr = nr_threads_synthesize; 1177 1178 if (thread_nr <= 1 || n <= 1) { 1179 err = __perf_event__synthesize_threads(tool, process, 1180 machine, 1181 needs_mmap, mmap_data, 1182 dirent, base, n); 1183 goto free_dirent; 1184 } 1185 if (thread_nr > n) 1186 thread_nr = n; 1187 1188 synthesize_threads = calloc(thread_nr, sizeof(pthread_t)); 1189 if (synthesize_threads == NULL) 1190 goto free_dirent; 1191 1192 args = calloc(thread_nr, sizeof(*args)); 1193 if (args == NULL) 1194 goto free_threads; 1195 1196 num_per_thread = n / thread_nr; 1197 m = n % thread_nr; 1198 for (i = 0; i < thread_nr; i++) { 1199 args[i].tool = tool; 1200 args[i].process = process; 1201 args[i].machine = machine; 1202 args[i].needs_mmap = needs_mmap; 1203 args[i].mmap_data = mmap_data; 1204 args[i].dirent = dirent; 1205 } 1206 for (i = 0; i < m; i++) { 1207 args[i].num = num_per_thread + 1; 1208 args[i].start = i * args[i].num; 1209 } 1210 if (i != 0) 1211 base = args[i-1].start + args[i-1].num; 1212 for (j = i; j < thread_nr; j++) { 1213 args[j].num = num_per_thread; 1214 args[j].start = base + (j - i) * args[i].num; 1215 } 1216 1217 for (i = 0; i < thread_nr; i++) { 1218 if (pthread_create(&synthesize_threads[i], NULL, 1219 synthesize_threads_worker, &args[i])) 1220 goto out_join; 1221 } 1222 err = 0; 1223 out_join: 1224 for (j = 0; j < i; j++) 1225 pthread_join(synthesize_threads[j], NULL); 1226 free(args); 1227 free_threads: 1228 free(synthesize_threads); 1229 free_dirent: 1230 for (i = 0; i < n; i++) 1231 zfree(&dirent[i]); 1232 free(dirent); 1233 1234 return err; 1235 } 1236 1237 int __weak perf_event__synthesize_extra_kmaps(const struct perf_tool *tool __maybe_unused, 1238 perf_event__handler_t process __maybe_unused, 1239 struct machine *machine __maybe_unused) 1240 { 1241 return 0; 1242 } 1243 1244 static int __perf_event__synthesize_kernel_mmap(const struct perf_tool *tool, 1245 perf_event__handler_t process, 1246 struct machine *machine) 1247 { 1248 union perf_event *event; 1249 size_t size = symbol_conf.no_buildid_mmap2 ? 1250 sizeof(event->mmap) : sizeof(event->mmap2); 1251 struct map *map = machine__kernel_map(machine); 1252 struct kmap *kmap; 1253 int err; 1254 1255 if (map == NULL) 1256 return -1; 1257 1258 kmap = map__kmap(map); 1259 if (!kmap->ref_reloc_sym) 1260 return -1; 1261 1262 /* 1263 * We should get this from /sys/kernel/sections/.text, but till that is 1264 * available use this, and after it is use this as a fallback for older 1265 * kernels. 1266 */ 1267 event = zalloc(size + machine->id_hdr_size); 1268 if (event == NULL) { 1269 pr_debug("Not enough memory synthesizing mmap event " 1270 "for kernel modules\n"); 1271 return -1; 1272 } 1273 1274 if (machine__is_host(machine)) { 1275 /* 1276 * kernel uses PERF_RECORD_MISC_USER for user space maps, 1277 * see kernel/perf_event.c __perf_event_mmap 1278 */ 1279 event->header.misc = PERF_RECORD_MISC_KERNEL; 1280 } else { 1281 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 1282 } 1283 1284 if (!symbol_conf.no_buildid_mmap2) { 1285 size = snprintf(event->mmap2.filename, sizeof(event->mmap2.filename), 1286 "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1; 1287 size = PERF_ALIGN(size, sizeof(u64)); 1288 event->mmap2.header.type = PERF_RECORD_MMAP2; 1289 event->mmap2.header.size = (sizeof(event->mmap2) - 1290 (sizeof(event->mmap2.filename) - size) + machine->id_hdr_size); 1291 event->mmap2.pgoff = kmap->ref_reloc_sym->addr; 1292 event->mmap2.start = map__start(map); 1293 event->mmap2.len = map__end(map) - event->mmap.start; 1294 event->mmap2.pid = machine->pid; 1295 1296 perf_record_mmap2__read_build_id(&event->mmap2, machine, true); 1297 } else { 1298 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 1299 "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1; 1300 size = PERF_ALIGN(size, sizeof(u64)); 1301 event->mmap.header.type = PERF_RECORD_MMAP; 1302 event->mmap.header.size = (sizeof(event->mmap) - 1303 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); 1304 event->mmap.pgoff = kmap->ref_reloc_sym->addr; 1305 event->mmap.start = map__start(map); 1306 event->mmap.len = map__end(map) - event->mmap.start; 1307 event->mmap.pid = machine->pid; 1308 } 1309 1310 err = perf_tool__process_synth_event(tool, event, machine, process); 1311 free(event); 1312 1313 return err; 1314 } 1315 1316 int perf_event__synthesize_kernel_mmap(const struct perf_tool *tool, 1317 perf_event__handler_t process, 1318 struct machine *machine) 1319 { 1320 int err; 1321 1322 err = __perf_event__synthesize_kernel_mmap(tool, process, machine); 1323 if (err < 0) 1324 return err; 1325 1326 return perf_event__synthesize_extra_kmaps(tool, process, machine); 1327 } 1328 1329 int perf_event__synthesize_thread_map2(const struct perf_tool *tool, 1330 struct perf_thread_map *threads, 1331 perf_event__handler_t process, 1332 struct machine *machine) 1333 { 1334 union perf_event *event; 1335 int i, err, size; 1336 1337 size = sizeof(event->thread_map); 1338 size += threads->nr * sizeof(event->thread_map.entries[0]); 1339 1340 event = zalloc(size); 1341 if (!event) 1342 return -ENOMEM; 1343 1344 event->header.type = PERF_RECORD_THREAD_MAP; 1345 event->header.size = size; 1346 event->thread_map.nr = threads->nr; 1347 1348 for (i = 0; i < threads->nr; i++) { 1349 struct perf_record_thread_map_entry *entry = &event->thread_map.entries[i]; 1350 char *comm = perf_thread_map__comm(threads, i); 1351 1352 if (!comm) 1353 comm = (char *) ""; 1354 1355 entry->pid = perf_thread_map__pid(threads, i); 1356 strncpy((char *) &entry->comm, comm, sizeof(entry->comm)); 1357 } 1358 1359 err = process(tool, event, NULL, machine); 1360 1361 free(event); 1362 return err; 1363 } 1364 1365 struct synthesize_cpu_map_data { 1366 const struct perf_cpu_map *map; 1367 int nr; 1368 int min_cpu; 1369 int max_cpu; 1370 int has_any_cpu; 1371 int type; 1372 size_t size; 1373 struct perf_record_cpu_map_data *data; 1374 }; 1375 1376 static void synthesize_cpus(struct synthesize_cpu_map_data *data) 1377 { 1378 data->data->type = PERF_CPU_MAP__CPUS; 1379 data->data->cpus_data.nr = data->nr; 1380 for (int i = 0; i < data->nr; i++) 1381 data->data->cpus_data.cpu[i] = perf_cpu_map__cpu(data->map, i).cpu; 1382 } 1383 1384 static void synthesize_mask(struct synthesize_cpu_map_data *data) 1385 { 1386 unsigned int idx; 1387 struct perf_cpu cpu; 1388 1389 /* Due to padding, the 4bytes per entry mask variant is always smaller. */ 1390 data->data->type = PERF_CPU_MAP__MASK; 1391 data->data->mask32_data.nr = BITS_TO_U32(data->max_cpu); 1392 data->data->mask32_data.long_size = 4; 1393 1394 perf_cpu_map__for_each_cpu(cpu, idx, data->map) { 1395 int bit_word = cpu.cpu / 32; 1396 u32 bit_mask = 1U << (cpu.cpu & 31); 1397 1398 data->data->mask32_data.mask[bit_word] |= bit_mask; 1399 } 1400 } 1401 1402 static void synthesize_range_cpus(struct synthesize_cpu_map_data *data) 1403 { 1404 data->data->type = PERF_CPU_MAP__RANGE_CPUS; 1405 data->data->range_cpu_data.any_cpu = data->has_any_cpu; 1406 data->data->range_cpu_data.start_cpu = data->min_cpu; 1407 data->data->range_cpu_data.end_cpu = data->max_cpu; 1408 } 1409 1410 static void *cpu_map_data__alloc(struct synthesize_cpu_map_data *syn_data, 1411 size_t header_size) 1412 { 1413 size_t size_cpus, size_mask; 1414 1415 syn_data->nr = perf_cpu_map__nr(syn_data->map); 1416 syn_data->has_any_cpu = (perf_cpu_map__cpu(syn_data->map, 0).cpu == -1) ? 1 : 0; 1417 1418 syn_data->min_cpu = perf_cpu_map__cpu(syn_data->map, syn_data->has_any_cpu).cpu; 1419 syn_data->max_cpu = perf_cpu_map__max(syn_data->map).cpu; 1420 if (syn_data->max_cpu - syn_data->min_cpu + 1 == syn_data->nr - syn_data->has_any_cpu) { 1421 /* A consecutive range of CPUs can be encoded using a range. */ 1422 assert(sizeof(u16) + sizeof(struct perf_record_range_cpu_map) == sizeof(u64)); 1423 syn_data->type = PERF_CPU_MAP__RANGE_CPUS; 1424 syn_data->size = header_size + sizeof(u64); 1425 return zalloc(syn_data->size); 1426 } 1427 1428 size_cpus = sizeof(u16) + sizeof(struct cpu_map_entries) + syn_data->nr * sizeof(u16); 1429 /* Due to padding, the 4bytes per entry mask variant is always smaller. */ 1430 size_mask = sizeof(u16) + sizeof(struct perf_record_mask_cpu_map32) + 1431 BITS_TO_U32(syn_data->max_cpu) * sizeof(__u32); 1432 if (syn_data->has_any_cpu || size_cpus < size_mask) { 1433 /* Follow the CPU map encoding. */ 1434 syn_data->type = PERF_CPU_MAP__CPUS; 1435 syn_data->size = header_size + PERF_ALIGN(size_cpus, sizeof(u64)); 1436 return zalloc(syn_data->size); 1437 } 1438 /* Encode using a bitmask. */ 1439 syn_data->type = PERF_CPU_MAP__MASK; 1440 syn_data->size = header_size + PERF_ALIGN(size_mask, sizeof(u64)); 1441 return zalloc(syn_data->size); 1442 } 1443 1444 static void cpu_map_data__synthesize(struct synthesize_cpu_map_data *data) 1445 { 1446 switch (data->type) { 1447 case PERF_CPU_MAP__CPUS: 1448 synthesize_cpus(data); 1449 break; 1450 case PERF_CPU_MAP__MASK: 1451 synthesize_mask(data); 1452 break; 1453 case PERF_CPU_MAP__RANGE_CPUS: 1454 synthesize_range_cpus(data); 1455 break; 1456 default: 1457 break; 1458 } 1459 } 1460 1461 static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cpu_map *map) 1462 { 1463 struct synthesize_cpu_map_data syn_data = { .map = map }; 1464 struct perf_record_cpu_map *event; 1465 1466 1467 event = cpu_map_data__alloc(&syn_data, sizeof(struct perf_event_header)); 1468 if (!event) 1469 return NULL; 1470 1471 syn_data.data = &event->data; 1472 event->header.type = PERF_RECORD_CPU_MAP; 1473 event->header.size = syn_data.size; 1474 cpu_map_data__synthesize(&syn_data); 1475 return event; 1476 } 1477 1478 1479 int perf_event__synthesize_cpu_map(const struct perf_tool *tool, 1480 const struct perf_cpu_map *map, 1481 perf_event__handler_t process, 1482 struct machine *machine) 1483 { 1484 struct perf_record_cpu_map *event; 1485 int err; 1486 1487 event = cpu_map_event__new(map); 1488 if (!event) 1489 return -ENOMEM; 1490 1491 err = process(tool, (union perf_event *) event, NULL, machine); 1492 1493 free(event); 1494 return err; 1495 } 1496 1497 int perf_event__synthesize_stat_config(const struct perf_tool *tool, 1498 struct perf_stat_config *config, 1499 perf_event__handler_t process, 1500 struct machine *machine) 1501 { 1502 struct perf_record_stat_config *event; 1503 int size, i = 0, err; 1504 1505 size = sizeof(*event); 1506 size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0])); 1507 1508 event = zalloc(size); 1509 if (!event) 1510 return -ENOMEM; 1511 1512 event->header.type = PERF_RECORD_STAT_CONFIG; 1513 event->header.size = size; 1514 event->nr = PERF_STAT_CONFIG_TERM__MAX; 1515 1516 #define ADD(__term, __val) \ 1517 event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term; \ 1518 event->data[i].val = __val; \ 1519 i++; 1520 1521 ADD(AGGR_MODE, config->aggr_mode) 1522 ADD(INTERVAL, config->interval) 1523 ADD(SCALE, config->scale) 1524 ADD(AGGR_LEVEL, config->aggr_level) 1525 1526 WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX, 1527 "stat config terms unbalanced\n"); 1528 #undef ADD 1529 1530 err = process(tool, (union perf_event *) event, NULL, machine); 1531 1532 free(event); 1533 return err; 1534 } 1535 1536 int perf_event__synthesize_stat(const struct perf_tool *tool, 1537 struct perf_cpu cpu, u32 thread, u64 id, 1538 struct perf_counts_values *count, 1539 perf_event__handler_t process, 1540 struct machine *machine) 1541 { 1542 struct perf_record_stat event; 1543 1544 event.header.type = PERF_RECORD_STAT; 1545 event.header.size = sizeof(event); 1546 event.header.misc = 0; 1547 1548 event.id = id; 1549 event.cpu = cpu.cpu; 1550 event.thread = thread; 1551 event.val = count->val; 1552 event.ena = count->ena; 1553 event.run = count->run; 1554 1555 return process(tool, (union perf_event *) &event, NULL, machine); 1556 } 1557 1558 int perf_event__synthesize_stat_round(const struct perf_tool *tool, 1559 u64 evtime, u64 type, 1560 perf_event__handler_t process, 1561 struct machine *machine) 1562 { 1563 struct perf_record_stat_round event; 1564 1565 event.header.type = PERF_RECORD_STAT_ROUND; 1566 event.header.size = sizeof(event); 1567 event.header.misc = 0; 1568 1569 event.time = evtime; 1570 event.type = type; 1571 1572 return process(tool, (union perf_event *) &event, NULL, machine); 1573 } 1574 1575 size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format, 1576 u64 branch_sample_type) 1577 { 1578 size_t sz, result = sizeof(struct perf_record_sample); 1579 1580 if (type & PERF_SAMPLE_IDENTIFIER) 1581 result += sizeof(u64); 1582 1583 if (type & PERF_SAMPLE_IP) 1584 result += sizeof(u64); 1585 1586 if (type & PERF_SAMPLE_TID) 1587 result += sizeof(u64); 1588 1589 if (type & PERF_SAMPLE_TIME) 1590 result += sizeof(u64); 1591 1592 if (type & PERF_SAMPLE_ADDR) 1593 result += sizeof(u64); 1594 1595 if (type & PERF_SAMPLE_ID) 1596 result += sizeof(u64); 1597 1598 if (type & PERF_SAMPLE_STREAM_ID) 1599 result += sizeof(u64); 1600 1601 if (type & PERF_SAMPLE_CPU) 1602 result += sizeof(u64); 1603 1604 if (type & PERF_SAMPLE_PERIOD) 1605 result += sizeof(u64); 1606 1607 if (type & PERF_SAMPLE_READ) { 1608 result += sizeof(u64); 1609 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 1610 result += sizeof(u64); 1611 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 1612 result += sizeof(u64); 1613 /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ 1614 if (read_format & PERF_FORMAT_GROUP) { 1615 sz = sample_read_value_size(read_format); 1616 result += sz * sample->read.group.nr; 1617 } else { 1618 result += sizeof(u64); 1619 if (read_format & PERF_FORMAT_LOST) 1620 result += sizeof(u64); 1621 } 1622 } 1623 1624 if (type & PERF_SAMPLE_CALLCHAIN) { 1625 sz = (sample->callchain->nr + 1) * sizeof(u64); 1626 result += sz; 1627 } 1628 1629 if (type & PERF_SAMPLE_RAW) { 1630 result += sizeof(u32); 1631 result += sample->raw_size; 1632 } 1633 1634 if (type & PERF_SAMPLE_BRANCH_STACK) { 1635 sz = sample->branch_stack->nr * sizeof(struct branch_entry); 1636 /* nr */ 1637 sz += sizeof(u64); 1638 if (branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) 1639 sz += sizeof(u64); 1640 result += sz; 1641 } 1642 1643 if (type & PERF_SAMPLE_REGS_USER) { 1644 if (sample->user_regs && sample->user_regs->abi) { 1645 result += sizeof(u64); 1646 sz = hweight64(sample->user_regs->mask) * sizeof(u64); 1647 result += sz; 1648 } else { 1649 result += sizeof(u64); 1650 } 1651 } 1652 1653 if (type & PERF_SAMPLE_STACK_USER) { 1654 sz = sample->user_stack.size; 1655 result += sizeof(u64); 1656 if (sz) { 1657 result += sz; 1658 result += sizeof(u64); 1659 } 1660 } 1661 1662 if (type & PERF_SAMPLE_WEIGHT_TYPE) 1663 result += sizeof(u64); 1664 1665 if (type & PERF_SAMPLE_DATA_SRC) 1666 result += sizeof(u64); 1667 1668 if (type & PERF_SAMPLE_TRANSACTION) 1669 result += sizeof(u64); 1670 1671 if (type & PERF_SAMPLE_REGS_INTR) { 1672 if (sample->intr_regs && sample->intr_regs->abi) { 1673 result += sizeof(u64); 1674 sz = hweight64(sample->intr_regs->mask) * sizeof(u64); 1675 result += sz; 1676 } else { 1677 result += sizeof(u64); 1678 } 1679 } 1680 1681 if (type & PERF_SAMPLE_PHYS_ADDR) 1682 result += sizeof(u64); 1683 1684 if (type & PERF_SAMPLE_CGROUP) 1685 result += sizeof(u64); 1686 1687 if (type & PERF_SAMPLE_DATA_PAGE_SIZE) 1688 result += sizeof(u64); 1689 1690 if (type & PERF_SAMPLE_CODE_PAGE_SIZE) 1691 result += sizeof(u64); 1692 1693 if (type & PERF_SAMPLE_AUX) { 1694 result += sizeof(u64); 1695 result += sample->aux_sample.size; 1696 } 1697 1698 return result; 1699 } 1700 1701 static void perf_synthesize_sample_weight(const struct perf_sample *data, 1702 __u64 *array, u64 type __maybe_unused) 1703 { 1704 *array = data->weight; 1705 1706 if (type & PERF_SAMPLE_WEIGHT_STRUCT) { 1707 *array &= 0xffffffff; 1708 *array |= ((u64)data->ins_lat << 32); 1709 *array |= ((u64)data->weight3 << 48); 1710 } 1711 } 1712 1713 static __u64 *copy_read_group_values(__u64 *array, __u64 read_format, 1714 const struct perf_sample *sample) 1715 { 1716 size_t sz = sample_read_value_size(read_format); 1717 struct sample_read_value *v = sample->read.group.values; 1718 1719 sample_read_group__for_each(v, sample->read.group.nr, read_format) { 1720 /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ 1721 memcpy(array, v, sz); 1722 array = (void *)array + sz; 1723 } 1724 return array; 1725 } 1726 1727 int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, 1728 u64 branch_sample_type, const struct perf_sample *sample) 1729 { 1730 __u64 *array; 1731 size_t sz; 1732 /* 1733 * used for cross-endian analysis. See git commit 65014ab3 1734 * for why this goofiness is needed. 1735 */ 1736 union u64_swap u; 1737 1738 array = event->sample.array; 1739 1740 if (type & PERF_SAMPLE_IDENTIFIER) { 1741 *array = sample->id; 1742 array++; 1743 } 1744 1745 if (type & PERF_SAMPLE_IP) { 1746 *array = sample->ip; 1747 array++; 1748 } 1749 1750 if (type & PERF_SAMPLE_TID) { 1751 u.val32[0] = sample->pid; 1752 u.val32[1] = sample->tid; 1753 *array = u.val64; 1754 array++; 1755 } 1756 1757 if (type & PERF_SAMPLE_TIME) { 1758 *array = sample->time; 1759 array++; 1760 } 1761 1762 if (type & PERF_SAMPLE_ADDR) { 1763 *array = sample->addr; 1764 array++; 1765 } 1766 1767 if (type & PERF_SAMPLE_ID) { 1768 *array = sample->id; 1769 array++; 1770 } 1771 1772 if (type & PERF_SAMPLE_STREAM_ID) { 1773 *array = sample->stream_id; 1774 array++; 1775 } 1776 1777 if (type & PERF_SAMPLE_CPU) { 1778 u.val32[0] = sample->cpu; 1779 u.val32[1] = 0; 1780 *array = u.val64; 1781 array++; 1782 } 1783 1784 if (type & PERF_SAMPLE_PERIOD) { 1785 *array = sample->period; 1786 array++; 1787 } 1788 1789 if (type & PERF_SAMPLE_READ) { 1790 if (read_format & PERF_FORMAT_GROUP) 1791 *array = sample->read.group.nr; 1792 else 1793 *array = sample->read.one.value; 1794 array++; 1795 1796 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 1797 *array = sample->read.time_enabled; 1798 array++; 1799 } 1800 1801 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { 1802 *array = sample->read.time_running; 1803 array++; 1804 } 1805 1806 /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ 1807 if (read_format & PERF_FORMAT_GROUP) { 1808 array = copy_read_group_values(array, read_format, 1809 sample); 1810 } else { 1811 *array = sample->read.one.id; 1812 array++; 1813 1814 if (read_format & PERF_FORMAT_LOST) { 1815 *array = sample->read.one.lost; 1816 array++; 1817 } 1818 } 1819 } 1820 1821 if (type & PERF_SAMPLE_CALLCHAIN) { 1822 sz = (sample->callchain->nr + 1) * sizeof(u64); 1823 memcpy(array, sample->callchain, sz); 1824 array = (void *)array + sz; 1825 } 1826 1827 if (type & PERF_SAMPLE_RAW) { 1828 u32 *array32 = (void *)array; 1829 1830 *array32 = sample->raw_size; 1831 array32++; 1832 1833 memcpy(array32, sample->raw_data, sample->raw_size); 1834 array = (void *)(array32 + (sample->raw_size / sizeof(u32))); 1835 1836 /* make sure the array is 64-bit aligned */ 1837 BUG_ON(((long)array) % sizeof(u64)); 1838 } 1839 1840 if (type & PERF_SAMPLE_BRANCH_STACK) { 1841 sz = sample->branch_stack->nr * sizeof(struct branch_entry); 1842 1843 *array++ = sample->branch_stack->nr; 1844 1845 if (branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) { 1846 if (sample->no_hw_idx) 1847 *array++ = 0; 1848 else 1849 *array++ = sample->branch_stack->hw_idx; 1850 } 1851 1852 memcpy(array, perf_sample__branch_entries((struct perf_sample *)sample), sz); 1853 array = (void *)array + sz; 1854 } 1855 1856 if (type & PERF_SAMPLE_REGS_USER) { 1857 if (sample->user_regs && sample->user_regs->abi) { 1858 *array++ = sample->user_regs->abi; 1859 sz = hweight64(sample->user_regs->mask) * sizeof(u64); 1860 memcpy(array, sample->user_regs->regs, sz); 1861 array = (void *)array + sz; 1862 } else { 1863 *array++ = 0; 1864 } 1865 } 1866 1867 if (type & PERF_SAMPLE_STACK_USER) { 1868 sz = sample->user_stack.size; 1869 *array++ = sz; 1870 if (sz) { 1871 memcpy(array, sample->user_stack.data, sz); 1872 array = (void *)array + sz; 1873 *array++ = sz; 1874 } 1875 } 1876 1877 if (type & PERF_SAMPLE_WEIGHT_TYPE) { 1878 perf_synthesize_sample_weight(sample, array, type); 1879 array++; 1880 } 1881 1882 if (type & PERF_SAMPLE_DATA_SRC) { 1883 *array = sample->data_src; 1884 array++; 1885 } 1886 1887 if (type & PERF_SAMPLE_TRANSACTION) { 1888 *array = sample->transaction; 1889 array++; 1890 } 1891 1892 if (type & PERF_SAMPLE_REGS_INTR) { 1893 if (sample->intr_regs && sample->intr_regs->abi) { 1894 *array++ = sample->intr_regs->abi; 1895 sz = hweight64(sample->intr_regs->mask) * sizeof(u64); 1896 memcpy(array, sample->intr_regs->regs, sz); 1897 array = (void *)array + sz; 1898 } else { 1899 *array++ = 0; 1900 } 1901 } 1902 1903 if (type & PERF_SAMPLE_PHYS_ADDR) { 1904 *array = sample->phys_addr; 1905 array++; 1906 } 1907 1908 if (type & PERF_SAMPLE_CGROUP) { 1909 *array = sample->cgroup; 1910 array++; 1911 } 1912 1913 if (type & PERF_SAMPLE_DATA_PAGE_SIZE) { 1914 *array = sample->data_page_size; 1915 array++; 1916 } 1917 1918 if (type & PERF_SAMPLE_CODE_PAGE_SIZE) { 1919 *array = sample->code_page_size; 1920 array++; 1921 } 1922 1923 if (type & PERF_SAMPLE_AUX) { 1924 sz = sample->aux_sample.size; 1925 *array++ = sz; 1926 memcpy(array, sample->aux_sample.data, sz); 1927 array = (void *)array + sz; 1928 } 1929 1930 return 0; 1931 } 1932 1933 int perf_event__synthesize_id_sample(__u64 *array, u64 type, const struct perf_sample *sample) 1934 { 1935 __u64 *start = array; 1936 1937 /* 1938 * used for cross-endian analysis. See git commit 65014ab3 1939 * for why this goofiness is needed. 1940 */ 1941 union u64_swap u; 1942 1943 if (type & PERF_SAMPLE_TID) { 1944 u.val32[0] = sample->pid; 1945 u.val32[1] = sample->tid; 1946 *array = u.val64; 1947 array++; 1948 } 1949 1950 if (type & PERF_SAMPLE_TIME) { 1951 *array = sample->time; 1952 array++; 1953 } 1954 1955 if (type & PERF_SAMPLE_ID) { 1956 *array = sample->id; 1957 array++; 1958 } 1959 1960 if (type & PERF_SAMPLE_STREAM_ID) { 1961 *array = sample->stream_id; 1962 array++; 1963 } 1964 1965 if (type & PERF_SAMPLE_CPU) { 1966 u.val32[0] = sample->cpu; 1967 u.val32[1] = 0; 1968 *array = u.val64; 1969 array++; 1970 } 1971 1972 if (type & PERF_SAMPLE_IDENTIFIER) { 1973 *array = sample->id; 1974 array++; 1975 } 1976 1977 return (void *)array - (void *)start; 1978 } 1979 1980 int __perf_event__synthesize_id_index(const struct perf_tool *tool, perf_event__handler_t process, 1981 struct evlist *evlist, struct machine *machine, size_t from) 1982 { 1983 union perf_event *ev; 1984 struct evsel *evsel; 1985 size_t nr = 0, i = 0, sz, max_nr, n, pos; 1986 size_t e1_sz = sizeof(struct id_index_entry); 1987 size_t e2_sz = sizeof(struct id_index_entry_2); 1988 size_t etot_sz = e1_sz + e2_sz; 1989 bool e2_needed = false; 1990 int err; 1991 1992 max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) / etot_sz; 1993 1994 pos = 0; 1995 evlist__for_each_entry(evlist, evsel) { 1996 if (pos++ < from) 1997 continue; 1998 nr += evsel->core.ids; 1999 } 2000 2001 if (!nr) 2002 return 0; 2003 2004 pr_debug2("Synthesizing id index\n"); 2005 2006 n = nr > max_nr ? max_nr : nr; 2007 sz = sizeof(struct perf_record_id_index) + n * etot_sz; 2008 ev = zalloc(sz); 2009 if (!ev) 2010 return -ENOMEM; 2011 2012 sz = sizeof(struct perf_record_id_index) + n * e1_sz; 2013 2014 ev->id_index.header.type = PERF_RECORD_ID_INDEX; 2015 ev->id_index.nr = n; 2016 2017 pos = 0; 2018 evlist__for_each_entry(evlist, evsel) { 2019 u32 j; 2020 2021 if (pos++ < from) 2022 continue; 2023 for (j = 0; j < evsel->core.ids; j++, i++) { 2024 struct id_index_entry *e; 2025 struct id_index_entry_2 *e2; 2026 struct perf_sample_id *sid; 2027 2028 if (i >= n) { 2029 ev->id_index.header.size = sz + (e2_needed ? n * e2_sz : 0); 2030 err = process(tool, ev, NULL, machine); 2031 if (err) 2032 goto out_err; 2033 nr -= n; 2034 i = 0; 2035 e2_needed = false; 2036 } 2037 2038 e = &ev->id_index.entries[i]; 2039 2040 e->id = evsel->core.id[j]; 2041 2042 sid = evlist__id2sid(evlist, e->id); 2043 if (!sid) { 2044 free(ev); 2045 return -ENOENT; 2046 } 2047 2048 e->idx = sid->idx; 2049 e->cpu = sid->cpu.cpu; 2050 e->tid = sid->tid; 2051 2052 if (sid->machine_pid) 2053 e2_needed = true; 2054 2055 e2 = (void *)ev + sz; 2056 e2[i].machine_pid = sid->machine_pid; 2057 e2[i].vcpu = sid->vcpu.cpu; 2058 } 2059 } 2060 2061 sz = sizeof(struct perf_record_id_index) + nr * e1_sz; 2062 ev->id_index.header.size = sz + (e2_needed ? nr * e2_sz : 0); 2063 ev->id_index.nr = nr; 2064 2065 err = process(tool, ev, NULL, machine); 2066 out_err: 2067 free(ev); 2068 2069 return err; 2070 } 2071 2072 int perf_event__synthesize_id_index(const struct perf_tool *tool, perf_event__handler_t process, 2073 struct evlist *evlist, struct machine *machine) 2074 { 2075 return __perf_event__synthesize_id_index(tool, process, evlist, machine, 0); 2076 } 2077 2078 int __machine__synthesize_threads(struct machine *machine, const struct perf_tool *tool, 2079 struct target *target, struct perf_thread_map *threads, 2080 perf_event__handler_t process, bool needs_mmap, 2081 bool data_mmap, unsigned int nr_threads_synthesize) 2082 { 2083 /* 2084 * When perf runs in non-root PID namespace, and the namespace's proc FS 2085 * is not mounted, nsinfo__is_in_root_namespace() returns false. 2086 * In this case, the proc FS is coming for the parent namespace, thus 2087 * perf tool will wrongly gather process info from its parent PID 2088 * namespace. 2089 * 2090 * To avoid the confusion that the perf tool runs in a child PID 2091 * namespace but it synthesizes thread info from its parent PID 2092 * namespace, returns failure with warning. 2093 */ 2094 if (!nsinfo__is_in_root_namespace()) { 2095 pr_err("Perf runs in non-root PID namespace but it tries to "); 2096 pr_err("gather process info from its parent PID namespace.\n"); 2097 pr_err("Please mount the proc file system properly, e.g. "); 2098 pr_err("add the option '--mount-proc' for unshare command.\n"); 2099 return -EPERM; 2100 } 2101 2102 if (target__has_task(target)) 2103 return perf_event__synthesize_thread_map(tool, threads, process, machine, 2104 needs_mmap, data_mmap); 2105 else if (target__has_cpu(target)) 2106 return perf_event__synthesize_threads(tool, process, machine, 2107 needs_mmap, data_mmap, 2108 nr_threads_synthesize); 2109 /* command specified */ 2110 return 0; 2111 } 2112 2113 int machine__synthesize_threads(struct machine *machine, struct target *target, 2114 struct perf_thread_map *threads, bool needs_mmap, 2115 bool data_mmap, unsigned int nr_threads_synthesize) 2116 { 2117 return __machine__synthesize_threads(machine, NULL, target, threads, 2118 perf_event__process, needs_mmap, 2119 data_mmap, nr_threads_synthesize); 2120 } 2121 2122 static struct perf_record_event_update *event_update_event__new(size_t size, u64 type, u64 id) 2123 { 2124 struct perf_record_event_update *ev; 2125 2126 size += sizeof(*ev); 2127 size = PERF_ALIGN(size, sizeof(u64)); 2128 2129 ev = zalloc(size); 2130 if (ev) { 2131 ev->header.type = PERF_RECORD_EVENT_UPDATE; 2132 ev->header.size = (u16)size; 2133 ev->type = type; 2134 ev->id = id; 2135 } 2136 return ev; 2137 } 2138 2139 int perf_event__synthesize_event_update_unit(const struct perf_tool *tool, struct evsel *evsel, 2140 perf_event__handler_t process) 2141 { 2142 size_t size = strlen(evsel->unit); 2143 struct perf_record_event_update *ev; 2144 int err; 2145 2146 ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->core.id[0]); 2147 if (ev == NULL) 2148 return -ENOMEM; 2149 2150 strlcpy(ev->unit, evsel->unit, size + 1); 2151 err = process(tool, (union perf_event *)ev, NULL, NULL); 2152 free(ev); 2153 return err; 2154 } 2155 2156 int perf_event__synthesize_event_update_scale(const struct perf_tool *tool, struct evsel *evsel, 2157 perf_event__handler_t process) 2158 { 2159 struct perf_record_event_update *ev; 2160 struct perf_record_event_update_scale *ev_data; 2161 int err; 2162 2163 ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->core.id[0]); 2164 if (ev == NULL) 2165 return -ENOMEM; 2166 2167 ev->scale.scale = evsel->scale; 2168 err = process(tool, (union perf_event *)ev, NULL, NULL); 2169 free(ev); 2170 return err; 2171 } 2172 2173 int perf_event__synthesize_event_update_name(const struct perf_tool *tool, struct evsel *evsel, 2174 perf_event__handler_t process) 2175 { 2176 struct perf_record_event_update *ev; 2177 size_t len = strlen(evsel__name(evsel)); 2178 int err; 2179 2180 ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->core.id[0]); 2181 if (ev == NULL) 2182 return -ENOMEM; 2183 2184 strlcpy(ev->name, evsel->name, len + 1); 2185 err = process(tool, (union perf_event *)ev, NULL, NULL); 2186 free(ev); 2187 return err; 2188 } 2189 2190 int perf_event__synthesize_event_update_cpus(const struct perf_tool *tool, struct evsel *evsel, 2191 perf_event__handler_t process) 2192 { 2193 struct synthesize_cpu_map_data syn_data = { .map = evsel->core.pmu_cpus }; 2194 struct perf_record_event_update *ev; 2195 int err; 2196 2197 ev = cpu_map_data__alloc(&syn_data, sizeof(struct perf_event_header) + 2 * sizeof(u64)); 2198 if (!ev) 2199 return -ENOMEM; 2200 2201 syn_data.data = &ev->cpus.cpus; 2202 ev->header.type = PERF_RECORD_EVENT_UPDATE; 2203 ev->header.size = (u16)syn_data.size; 2204 ev->type = PERF_EVENT_UPDATE__CPUS; 2205 ev->id = evsel->core.id[0]; 2206 cpu_map_data__synthesize(&syn_data); 2207 2208 err = process(tool, (union perf_event *)ev, NULL, NULL); 2209 free(ev); 2210 return err; 2211 } 2212 2213 int perf_event__synthesize_attrs(const struct perf_tool *tool, struct evlist *evlist, 2214 perf_event__handler_t process) 2215 { 2216 struct evsel *evsel; 2217 int err = 0; 2218 2219 evlist__for_each_entry(evlist, evsel) { 2220 err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->core.ids, 2221 evsel->core.id, process); 2222 if (err) { 2223 pr_debug("failed to create perf header attribute\n"); 2224 return err; 2225 } 2226 } 2227 2228 return err; 2229 } 2230 2231 static bool has_unit(struct evsel *evsel) 2232 { 2233 return evsel->unit && *evsel->unit; 2234 } 2235 2236 static bool has_scale(struct evsel *evsel) 2237 { 2238 return evsel->scale != 1; 2239 } 2240 2241 int perf_event__synthesize_extra_attr(const struct perf_tool *tool, struct evlist *evsel_list, 2242 perf_event__handler_t process, bool is_pipe) 2243 { 2244 struct evsel *evsel; 2245 int err; 2246 2247 /* 2248 * Synthesize other events stuff not carried within 2249 * attr event - unit, scale, name 2250 */ 2251 evlist__for_each_entry(evsel_list, evsel) { 2252 if (!evsel->supported) 2253 continue; 2254 2255 /* 2256 * Synthesize unit and scale only if it's defined. 2257 */ 2258 if (has_unit(evsel)) { 2259 err = perf_event__synthesize_event_update_unit(tool, evsel, process); 2260 if (err < 0) { 2261 pr_err("Couldn't synthesize evsel unit.\n"); 2262 return err; 2263 } 2264 } 2265 2266 if (has_scale(evsel)) { 2267 err = perf_event__synthesize_event_update_scale(tool, evsel, process); 2268 if (err < 0) { 2269 pr_err("Couldn't synthesize evsel evsel.\n"); 2270 return err; 2271 } 2272 } 2273 2274 if (evsel->core.pmu_cpus) { 2275 err = perf_event__synthesize_event_update_cpus(tool, evsel, process); 2276 if (err < 0) { 2277 pr_err("Couldn't synthesize evsel cpus.\n"); 2278 return err; 2279 } 2280 } 2281 2282 /* 2283 * Name is needed only for pipe output, 2284 * perf.data carries event names. 2285 */ 2286 if (is_pipe) { 2287 err = perf_event__synthesize_event_update_name(tool, evsel, process); 2288 if (err < 0) { 2289 pr_err("Couldn't synthesize evsel name.\n"); 2290 return err; 2291 } 2292 } 2293 } 2294 return 0; 2295 } 2296 2297 int perf_event__synthesize_attr(const struct perf_tool *tool, struct perf_event_attr *attr, 2298 u32 ids, u64 *id, perf_event__handler_t process) 2299 { 2300 union perf_event *ev; 2301 size_t attr_size, size; 2302 int err; 2303 2304 /* 2305 * Use attr->size for the event layout, not the compiled 2306 * sizeof(struct perf_event_attr), so that synthesized events 2307 * match the source perf.data layout. This matters for perf 2308 * inject, which re-synthesizes attrs from a file that may 2309 * have been recorded by a different version of perf. 2310 * perf_record_header_attr_id() locates the ID array at 2311 * attr->size bytes past the attr. 2312 */ 2313 attr_size = attr->size ?: sizeof(struct perf_event_attr); 2314 2315 size = PERF_ALIGN(attr_size, sizeof(u64)); 2316 size += sizeof(struct perf_event_header); 2317 size += ids * sizeof(u64); 2318 2319 ev = zalloc(size); 2320 2321 if (ev == NULL) 2322 return -ENOMEM; 2323 2324 /* 2325 * Copy only the bytes we understand; zalloc ensures that any 2326 * extra bytes between sizeof(struct perf_event_attr) and 2327 * attr_size are zero when the source file uses a newer, larger 2328 * struct. 2329 */ 2330 memcpy(&ev->attr.attr, attr, min(sizeof(struct perf_event_attr), attr_size)); 2331 ev->attr.attr.size = attr_size; 2332 memcpy(perf_record_header_attr_id(ev), id, ids * sizeof(u64)); 2333 2334 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 2335 ev->attr.header.size = (u16)size; 2336 2337 if (ev->attr.header.size == size) 2338 err = process(tool, ev, NULL, NULL); 2339 else 2340 err = -E2BIG; 2341 2342 free(ev); 2343 2344 return err; 2345 } 2346 2347 #ifdef HAVE_LIBTRACEEVENT 2348 int perf_event__synthesize_tracing_data(const struct perf_tool *tool, int fd, struct evlist *evlist, 2349 perf_event__handler_t process) 2350 { 2351 union perf_event ev; 2352 struct tracing_data *tdata; 2353 ssize_t size = 0, aligned_size = 0, padding; 2354 struct feat_fd ff; 2355 2356 /* 2357 * We are going to store the size of the data followed 2358 * by the data contents. Since the fd descriptor is a pipe, 2359 * we cannot seek back to store the size of the data once 2360 * we know it. Instead we: 2361 * 2362 * - write the tracing data to the temp file 2363 * - get/write the data size to pipe 2364 * - write the tracing data from the temp file 2365 * to the pipe 2366 */ 2367 tdata = tracing_data_get(&evlist__core(evlist)->entries, fd, true); 2368 if (!tdata) 2369 return -1; 2370 2371 memset(&ev, 0, sizeof(ev.tracing_data)); 2372 2373 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 2374 size = tdata->size; 2375 aligned_size = PERF_ALIGN(size, sizeof(u64)); 2376 padding = aligned_size - size; 2377 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2378 ev.tracing_data.size = aligned_size; 2379 2380 process(tool, &ev, NULL, NULL); 2381 2382 /* 2383 * The put function will copy all the tracing data 2384 * stored in temp file to the pipe. 2385 */ 2386 tracing_data_put(tdata); 2387 2388 ff = (struct feat_fd){ .fd = fd }; 2389 if (write_padded(&ff, NULL, 0, padding)) 2390 return -1; 2391 2392 return aligned_size; 2393 } 2394 #endif 2395 2396 int perf_event__synthesize_build_id(const struct perf_tool *tool, 2397 struct perf_sample *sample, 2398 struct machine *machine, 2399 perf_event__handler_t process, 2400 __u16 misc, 2401 const struct build_id *bid, 2402 const char *filename) 2403 { 2404 union perf_event ev; 2405 size_t len, filename_len = strlen(filename); 2406 u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0; 2407 void *array = &ev; 2408 int ret; 2409 2410 if (filename_len >= PATH_MAX) 2411 return -EINVAL; 2412 2413 len = sizeof(ev.build_id) + filename_len + 1; 2414 len = PERF_ALIGN(len, sizeof(u64)); 2415 2416 if (len + MAX_ID_HDR_ENTRIES * sizeof(__u64) > sizeof(ev)) 2417 return -E2BIG; 2418 2419 memset(&ev, 0, len); 2420 2421 ev.build_id.size = bid->size; 2422 if (ev.build_id.size > sizeof(ev.build_id.build_id)) 2423 ev.build_id.size = sizeof(ev.build_id.build_id); 2424 memcpy(ev.build_id.build_id, bid->data, ev.build_id.size); 2425 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; 2426 ev.build_id.header.misc = misc | PERF_RECORD_MISC_BUILD_ID_SIZE; 2427 ev.build_id.pid = machine->pid; 2428 ev.build_id.header.size = len; 2429 strcpy(ev.build_id.filename, filename); 2430 2431 array += ev.header.size; 2432 ret = perf_event__synthesize_id_sample(array, sample_type, sample); 2433 if (ret < 0) 2434 return ret; 2435 2436 if (ret & 7) { 2437 pr_err("Bad id sample size %d\n", ret); 2438 return -EINVAL; 2439 } 2440 2441 ev.header.size += ret; 2442 return process(tool, &ev, sample, machine); 2443 } 2444 2445 int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool, 2446 struct perf_sample *sample, 2447 struct machine *machine, 2448 perf_event__handler_t process, 2449 __u16 misc, 2450 __u32 pid, __u32 tid, 2451 __u64 start, __u64 len, __u64 pgoff, 2452 const struct build_id *bid, 2453 __u32 prot, __u32 flags, 2454 const char *filename) 2455 { 2456 union perf_event ev; 2457 size_t filename_len = strlen(filename); 2458 size_t ev_len; 2459 u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0; 2460 void *array = &ev; 2461 int ret; 2462 size_t max_filename_len; 2463 2464 max_filename_len = min(sizeof(ev.mmap2.filename) - 1, 2465 sizeof(ev) - (MAX_ID_HDR_ENTRIES * sizeof(__u64)) - 2466 offsetof(struct perf_record_mmap2, filename) - 1); 2467 2468 if (filename_len > max_filename_len) 2469 filename_len = max_filename_len; 2470 2471 ev_len = offsetof(struct perf_record_mmap2, filename) + filename_len + 1; 2472 ev_len = PERF_ALIGN(ev_len, sizeof(u64)); 2473 2474 if (ev_len + MAX_ID_HDR_ENTRIES * sizeof(__u64) > sizeof(ev)) 2475 return -E2BIG; 2476 2477 memset(&ev, 0, ev_len); 2478 2479 ev.mmap2.header.type = PERF_RECORD_MMAP2; 2480 ev.mmap2.header.misc = misc | PERF_RECORD_MISC_MMAP_BUILD_ID; 2481 ev.mmap2.header.size = ev_len; 2482 2483 ev.mmap2.pid = pid; 2484 ev.mmap2.tid = tid; 2485 ev.mmap2.start = start; 2486 ev.mmap2.len = len; 2487 ev.mmap2.pgoff = pgoff; 2488 2489 ev.mmap2.build_id_size = bid->size; 2490 if (ev.mmap2.build_id_size > sizeof(ev.mmap2.build_id)) 2491 ev.mmap2.build_id_size = sizeof(ev.mmap2.build_id); 2492 memcpy(ev.mmap2.build_id, bid->data, ev.mmap2.build_id_size); 2493 2494 ev.mmap2.prot = prot; 2495 ev.mmap2.flags = flags; 2496 2497 strlcpy(ev.mmap2.filename, filename, filename_len + 1); 2498 2499 array = (void *)((char *)&ev + ev.header.size); 2500 ret = perf_event__synthesize_id_sample(array, sample_type, sample); 2501 if (ret < 0) 2502 return ret; 2503 2504 if (ret & 7) { 2505 pr_err("Bad id sample size %d\n", ret); 2506 return -EINVAL; 2507 } 2508 2509 ev.header.size += ret; 2510 2511 return process(tool, &ev, sample, machine); 2512 } 2513 2514 int perf_event__synthesize_stat_events(struct perf_stat_config *config, const struct perf_tool *tool, 2515 struct evlist *evlist, perf_event__handler_t process, bool attrs) 2516 { 2517 int err; 2518 2519 if (attrs) { 2520 err = perf_event__synthesize_attrs(tool, evlist, process); 2521 if (err < 0) { 2522 pr_err("Couldn't synthesize attrs.\n"); 2523 return err; 2524 } 2525 } 2526 2527 err = perf_event__synthesize_extra_attr(tool, evlist, process, attrs); 2528 err = perf_event__synthesize_thread_map2(tool, evlist__core(evlist)->threads, 2529 process, /*machine=*/NULL); 2530 if (err < 0) { 2531 pr_err("Couldn't synthesize thread map.\n"); 2532 return err; 2533 } 2534 2535 err = perf_event__synthesize_cpu_map(tool, 2536 evlist__core(evlist)->user_requested_cpus, 2537 process, /*machine=*/NULL); 2538 if (err < 0) { 2539 pr_err("Couldn't synthesize thread map.\n"); 2540 return err; 2541 } 2542 2543 err = perf_event__synthesize_stat_config(tool, config, process, NULL); 2544 if (err < 0) { 2545 pr_err("Couldn't synthesize config.\n"); 2546 return err; 2547 } 2548 2549 return 0; 2550 } 2551 2552 extern const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE]; 2553 2554 int perf_event__synthesize_features(const struct perf_tool *tool, struct perf_session *session, 2555 struct evlist *evlist, perf_event__handler_t process) 2556 { 2557 struct perf_header *header = &session->header; 2558 struct perf_record_header_feature *fe; 2559 struct feat_fd ff; 2560 size_t sz, sz_hdr; 2561 int feat, ret; 2562 2563 sz_hdr = sizeof(fe->header); 2564 sz = sizeof(union perf_event); 2565 /* get a nice alignment */ 2566 sz = PERF_ALIGN(sz, page_size); 2567 2568 memset(&ff, 0, sizeof(ff)); 2569 2570 ff.buf = malloc(sz); 2571 if (!ff.buf) 2572 return -ENOMEM; 2573 2574 ff.size = sz - sz_hdr; 2575 ff.ph = &session->header; 2576 2577 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { 2578 if (!feat_ops[feat].synthesize) { 2579 pr_debug("No record header feature for header :%d\n", feat); 2580 continue; 2581 } 2582 2583 ff.offset = sizeof(*fe); 2584 2585 ret = feat_ops[feat].write(&ff, evlist); 2586 if (ret || ff.offset <= (ssize_t)sizeof(*fe)) { 2587 pr_debug("Error writing feature\n"); 2588 continue; 2589 } 2590 /* ff.buf may have changed due to realloc in do_write() */ 2591 fe = ff.buf; 2592 memset(fe, 0, sizeof(*fe)); 2593 2594 fe->feat_id = feat; 2595 fe->header.type = PERF_RECORD_HEADER_FEATURE; 2596 fe->header.size = ff.offset; 2597 2598 ret = process(tool, ff.buf, NULL, NULL); 2599 if (ret) { 2600 free(ff.buf); 2601 return ret; 2602 } 2603 } 2604 2605 /* Send HEADER_LAST_FEATURE mark. */ 2606 fe = ff.buf; 2607 fe->feat_id = HEADER_LAST_FEATURE; 2608 fe->header.type = PERF_RECORD_HEADER_FEATURE; 2609 fe->header.size = sizeof(*fe); 2610 2611 ret = process(tool, ff.buf, NULL, NULL); 2612 2613 free(ff.buf); 2614 return ret; 2615 } 2616 2617 int perf_event__synthesize_for_pipe(const struct perf_tool *tool, 2618 struct perf_session *session, 2619 struct perf_data *data, 2620 perf_event__handler_t process) 2621 { 2622 int err; 2623 int ret = 0; 2624 struct evlist *evlist = session->evlist; 2625 2626 /* 2627 * We need to synthesize events first, because some 2628 * features works on top of them (on report side). 2629 */ 2630 err = perf_event__synthesize_attrs(tool, evlist, process); 2631 if (err < 0) { 2632 pr_err("Couldn't synthesize attrs.\n"); 2633 return err; 2634 } 2635 ret += err; 2636 2637 err = perf_event__synthesize_features(tool, session, evlist, process); 2638 if (err < 0) { 2639 pr_err("Couldn't synthesize features.\n"); 2640 return err; 2641 } 2642 ret += err; 2643 2644 #ifdef HAVE_LIBTRACEEVENT 2645 if (have_tracepoints(&evlist__core(evlist)->entries)) { 2646 int fd = perf_data__fd(data); 2647 2648 /* 2649 * FIXME err <= 0 here actually means that 2650 * there were no tracepoints so its not really 2651 * an error, just that we don't need to 2652 * synthesize anything. We really have to 2653 * return this more properly and also 2654 * propagate errors that now are calling die() 2655 */ 2656 err = perf_event__synthesize_tracing_data(tool, fd, evlist, 2657 process); 2658 if (err <= 0) { 2659 pr_err("Couldn't record tracing data.\n"); 2660 return err; 2661 } 2662 ret += err; 2663 } 2664 #else 2665 (void)data; 2666 #endif 2667 2668 return ret; 2669 } 2670 2671 int parse_synth_opt(char *synth) 2672 { 2673 char *p, *q; 2674 int ret = 0; 2675 2676 if (synth == NULL) 2677 return -1; 2678 2679 for (q = synth; (p = strsep(&q, ",")); p = q) { 2680 if (!strcasecmp(p, "no") || !strcasecmp(p, "none")) 2681 return 0; 2682 2683 if (!strcasecmp(p, "all")) 2684 return PERF_SYNTH_ALL; 2685 2686 if (!strcasecmp(p, "task")) 2687 ret |= PERF_SYNTH_TASK; 2688 else if (!strcasecmp(p, "mmap")) 2689 ret |= PERF_SYNTH_TASK | PERF_SYNTH_MMAP; 2690 else if (!strcasecmp(p, "cgroup")) 2691 ret |= PERF_SYNTH_CGROUP; 2692 else 2693 return -1; 2694 } 2695 2696 return ret; 2697 } 2698 2699 static union perf_event *__synthesize_schedstat_cpu(struct io *io, __u16 version, 2700 __u64 *cpu, __u64 timestamp) 2701 { 2702 struct perf_record_schedstat_cpu *cs; 2703 union perf_event *event; 2704 size_t size; 2705 char ch; 2706 2707 size = sizeof(*cs); 2708 size = PERF_ALIGN(size, sizeof(u64)); 2709 event = zalloc(size); 2710 2711 if (!event) 2712 return NULL; 2713 2714 cs = &event->schedstat_cpu; 2715 cs->header.type = PERF_RECORD_SCHEDSTAT_CPU; 2716 cs->header.size = size; 2717 cs->timestamp = timestamp; 2718 2719 if (io__get_char(io) != 'p' || io__get_char(io) != 'u') 2720 goto out_cpu; 2721 2722 if (io__get_dec(io, (__u64 *)cpu) != ' ') 2723 goto out_cpu; 2724 2725 #define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ 2726 do { \ 2727 __u64 _tmp; \ 2728 ch = io__get_dec(io, &_tmp); \ 2729 if (ch != ' ' && ch != '\n') \ 2730 goto out_cpu; \ 2731 cs->_ver._name = _tmp; \ 2732 } while (0) 2733 2734 if (version == 15) { 2735 #include <perf/schedstat-v15.h> 2736 } else if (version == 16) { 2737 #include <perf/schedstat-v16.h> 2738 } else if (version == 17) { 2739 #include <perf/schedstat-v17.h> 2740 } 2741 #undef CPU_FIELD 2742 2743 cs->cpu = *cpu; 2744 cs->version = version; 2745 2746 return event; 2747 out_cpu: 2748 free(event); 2749 return NULL; 2750 } 2751 2752 static union perf_event *__synthesize_schedstat_domain(struct io *io, __u16 version, 2753 __u64 cpu, __u64 timestamp) 2754 { 2755 struct perf_record_schedstat_domain *ds; 2756 union perf_event *event = NULL; 2757 __u64 d_num; 2758 size_t size; 2759 char ch; 2760 2761 if (io__get_char(io) != 'o' || io__get_char(io) != 'm' || io__get_char(io) != 'a' || 2762 io__get_char(io) != 'i' || io__get_char(io) != 'n') 2763 return NULL; 2764 2765 ch = io__get_dec(io, &d_num); 2766 if (version >= 17) { 2767 /* Skip domain name as it can be extracted from perf header */ 2768 while (io__get_char(io) != ' ') 2769 continue; 2770 } 2771 2772 /* Skip cpumask as it can be extracted from perf header */ 2773 while (io__get_char(io) != ' ') 2774 continue; 2775 2776 size = sizeof(*ds); 2777 size = PERF_ALIGN(size, sizeof(u64)); 2778 event = zalloc(size); 2779 2780 ds = &event->schedstat_domain; 2781 ds->header.type = PERF_RECORD_SCHEDSTAT_DOMAIN; 2782 ds->header.size = size; 2783 ds->version = version; 2784 ds->timestamp = timestamp; 2785 ds->domain = d_num; 2786 2787 #define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ 2788 do { \ 2789 __u64 _tmp; \ 2790 ch = io__get_dec(io, &_tmp); \ 2791 if (ch != ' ' && ch != '\n') \ 2792 goto out_domain; \ 2793 ds->_ver._name = _tmp; \ 2794 } while (0) 2795 2796 if (version == 15) { 2797 #include <perf/schedstat-v15.h> 2798 } else if (version == 16) { 2799 #include <perf/schedstat-v16.h> 2800 } else if (version == 17) { 2801 #include <perf/schedstat-v17.h> 2802 } 2803 #undef DOMAIN_FIELD 2804 2805 ds->cpu = cpu; 2806 goto out; 2807 2808 out_domain: 2809 free(event); 2810 event = NULL; 2811 out: 2812 return event; 2813 } 2814 2815 int perf_event__synthesize_schedstat(const struct perf_tool *tool, 2816 perf_event__handler_t process, 2817 struct perf_cpu_map *user_requested_cpus) 2818 { 2819 char *line = NULL, path[PATH_MAX]; 2820 union perf_event *event = NULL; 2821 size_t line_len = 0; 2822 char bf[BUFSIZ]; 2823 __u64 timestamp; 2824 __u64 cpu = -1; 2825 __u16 version; 2826 struct io io; 2827 int ret = -1; 2828 char ch; 2829 2830 snprintf(path, PATH_MAX, "%s/schedstat", procfs__mountpoint()); 2831 io.fd = open(path, O_RDONLY, 0); 2832 if (io.fd < 0) { 2833 pr_err("Failed to open %s. Possibly CONFIG_SCHEDSTAT is disabled.\n", path); 2834 return -1; 2835 } 2836 io__init(&io, io.fd, bf, sizeof(bf)); 2837 2838 if (io__getline(&io, &line, &line_len) < 0 || !line_len) 2839 goto out; 2840 2841 if (!strcmp(line, "version 15\n")) { 2842 version = 15; 2843 } else if (!strcmp(line, "version 16\n")) { 2844 version = 16; 2845 } else if (!strcmp(line, "version 17\n")) { 2846 version = 17; 2847 } else { 2848 pr_err("Unsupported %s version: %s", path, line + 8); 2849 goto out_free_line; 2850 } 2851 2852 if (io__getline(&io, &line, &line_len) < 0 || !line_len) 2853 goto out_free_line; 2854 timestamp = atol(line + 10); 2855 2856 /* 2857 * FIXME: Can be optimized a bit by not synthesizing domain samples 2858 * for filtered out cpus. 2859 */ 2860 for (ch = io__get_char(&io); !io.eof; ch = io__get_char(&io)) { 2861 struct perf_cpu this_cpu; 2862 2863 if (ch == 'c') { 2864 event = __synthesize_schedstat_cpu(&io, version, 2865 &cpu, timestamp); 2866 } else if (ch == 'd') { 2867 event = __synthesize_schedstat_domain(&io, version, 2868 cpu, timestamp); 2869 } 2870 if (!event) 2871 goto out_free_line; 2872 2873 this_cpu.cpu = cpu; 2874 2875 if (user_requested_cpus && !perf_cpu_map__has(user_requested_cpus, this_cpu)) 2876 continue; 2877 2878 if (process(tool, event, NULL, NULL) < 0) { 2879 free(event); 2880 goto out_free_line; 2881 } 2882 2883 free(event); 2884 } 2885 2886 ret = 0; 2887 2888 out_free_line: 2889 free(line); 2890 out: 2891 close(io.fd); 2892 return ret; 2893 } 2894