1 /* 2 * builtin-record.c 3 * 4 * Builtin record command: Record the profile of a workload 5 * (or a CPU, or a PID) into the perf.data output file - for 6 * later analysis via perf report. 7 */ 8 #include "builtin.h" 9 10 #include "perf.h" 11 12 #include "util/build-id.h" 13 #include "util/util.h" 14 #include "util/parse-options.h" 15 #include "util/parse-events.h" 16 17 #include "util/header.h" 18 #include "util/event.h" 19 #include "util/evlist.h" 20 #include "util/evsel.h" 21 #include "util/debug.h" 22 #include "util/session.h" 23 #include "util/tool.h" 24 #include "util/symbol.h" 25 #include "util/cpumap.h" 26 #include "util/thread_map.h" 27 #include "util/data.h" 28 29 #include <unistd.h> 30 #include <sched.h> 31 #include <sys/mman.h> 32 33 #ifndef HAVE_ON_EXIT_SUPPORT 34 #ifndef ATEXIT_MAX 35 #define ATEXIT_MAX 32 36 #endif 37 static int __on_exit_count = 0; 38 typedef void (*on_exit_func_t) (int, void *); 39 static on_exit_func_t __on_exit_funcs[ATEXIT_MAX]; 40 static void *__on_exit_args[ATEXIT_MAX]; 41 static int __exitcode = 0; 42 static void __handle_on_exit_funcs(void); 43 static int on_exit(on_exit_func_t function, void *arg); 44 #define exit(x) (exit)(__exitcode = (x)) 45 46 static int on_exit(on_exit_func_t function, void *arg) 47 { 48 if (__on_exit_count == ATEXIT_MAX) 49 return -ENOMEM; 50 else if (__on_exit_count == 0) 51 atexit(__handle_on_exit_funcs); 52 __on_exit_funcs[__on_exit_count] = function; 53 __on_exit_args[__on_exit_count++] = arg; 54 return 0; 55 } 56 57 static void __handle_on_exit_funcs(void) 58 { 59 int i; 60 for (i = 0; i < __on_exit_count; i++) 61 __on_exit_funcs[i] (__exitcode, __on_exit_args[i]); 62 } 63 #endif 64 65 struct perf_record { 66 struct perf_tool tool; 67 struct perf_record_opts opts; 68 u64 bytes_written; 69 struct perf_data_file file; 70 struct perf_evlist *evlist; 71 struct perf_session *session; 72 const char *progname; 73 int realtime_prio; 74 bool no_buildid; 75 bool no_buildid_cache; 76 long samples; 77 }; 78 79 static int write_output(struct perf_record *rec, void *buf, size_t size) 80 { 81 struct perf_data_file *file = &rec->file; 82 83 while (size) { 84 int ret = write(file->fd, buf, size); 85 86 if (ret < 0) { 87 pr_err("failed to write perf data, error: %m\n"); 88 return -1; 89 } 90 91 size -= ret; 92 buf += ret; 93 94 rec->bytes_written += ret; 95 } 96 97 return 0; 98 } 99 100 static int process_synthesized_event(struct perf_tool *tool, 101 union perf_event *event, 102 struct perf_sample *sample __maybe_unused, 103 struct machine *machine __maybe_unused) 104 { 105 struct perf_record *rec = container_of(tool, struct perf_record, tool); 106 if (write_output(rec, event, event->header.size) < 0) 107 return -1; 108 109 return 0; 110 } 111 112 static int perf_record__mmap_read(struct perf_record *rec, 113 struct perf_mmap *md) 114 { 115 unsigned int head = perf_mmap__read_head(md); 116 unsigned int old = md->prev; 117 unsigned char *data = md->base + page_size; 118 unsigned long size; 119 void *buf; 120 int rc = 0; 121 122 if (old == head) 123 return 0; 124 125 rec->samples++; 126 127 size = head - old; 128 129 if ((old & md->mask) + size != (head & md->mask)) { 130 buf = &data[old & md->mask]; 131 size = md->mask + 1 - (old & md->mask); 132 old += size; 133 134 if (write_output(rec, buf, size) < 0) { 135 rc = -1; 136 goto out; 137 } 138 } 139 140 buf = &data[old & md->mask]; 141 size = head - old; 142 old += size; 143 144 if (write_output(rec, buf, size) < 0) { 145 rc = -1; 146 goto out; 147 } 148 149 md->prev = old; 150 perf_mmap__write_tail(md, old); 151 152 out: 153 return rc; 154 } 155 156 static volatile int done = 0; 157 static volatile int signr = -1; 158 static volatile int child_finished = 0; 159 160 static void sig_handler(int sig) 161 { 162 if (sig == SIGCHLD) 163 child_finished = 1; 164 165 done = 1; 166 signr = sig; 167 } 168 169 static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 170 { 171 struct perf_record *rec = arg; 172 int status; 173 174 if (rec->evlist->workload.pid > 0) { 175 if (!child_finished) 176 kill(rec->evlist->workload.pid, SIGTERM); 177 178 wait(&status); 179 if (WIFSIGNALED(status)) 180 psignal(WTERMSIG(status), rec->progname); 181 } 182 183 if (signr == -1 || signr == SIGUSR1) 184 return; 185 186 signal(signr, SIG_DFL); 187 } 188 189 static int perf_record__open(struct perf_record *rec) 190 { 191 char msg[512]; 192 struct perf_evsel *pos; 193 struct perf_evlist *evlist = rec->evlist; 194 struct perf_session *session = rec->session; 195 struct perf_record_opts *opts = &rec->opts; 196 int rc = 0; 197 198 perf_evlist__config(evlist, opts); 199 200 list_for_each_entry(pos, &evlist->entries, node) { 201 try_again: 202 if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 203 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 204 if (verbose) 205 ui__warning("%s\n", msg); 206 goto try_again; 207 } 208 209 rc = -errno; 210 perf_evsel__open_strerror(pos, &opts->target, 211 errno, msg, sizeof(msg)); 212 ui__error("%s\n", msg); 213 goto out; 214 } 215 } 216 217 if (perf_evlist__apply_filters(evlist)) { 218 error("failed to set filter with %d (%s)\n", errno, 219 strerror(errno)); 220 rc = -1; 221 goto out; 222 } 223 224 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 225 if (errno == EPERM) { 226 pr_err("Permission error mapping pages.\n" 227 "Consider increasing " 228 "/proc/sys/kernel/perf_event_mlock_kb,\n" 229 "or try again with a smaller value of -m/--mmap_pages.\n" 230 "(current value: %d)\n", opts->mmap_pages); 231 rc = -errno; 232 } else { 233 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 234 rc = -errno; 235 } 236 goto out; 237 } 238 239 session->evlist = evlist; 240 perf_session__set_id_hdr_size(session); 241 out: 242 return rc; 243 } 244 245 static int process_buildids(struct perf_record *rec) 246 { 247 struct perf_data_file *file = &rec->file; 248 struct perf_session *session = rec->session; 249 u64 start = session->header.data_offset; 250 251 u64 size = lseek(file->fd, 0, SEEK_CUR); 252 if (size == 0) 253 return 0; 254 255 return __perf_session__process_events(session, start, 256 size - start, 257 size, &build_id__mark_dso_hit_ops); 258 } 259 260 static void perf_record__exit(int status, void *arg) 261 { 262 struct perf_record *rec = arg; 263 struct perf_data_file *file = &rec->file; 264 265 if (status != 0) 266 return; 267 268 if (!file->is_pipe) { 269 rec->session->header.data_size += rec->bytes_written; 270 271 if (!rec->no_buildid) 272 process_buildids(rec); 273 perf_session__write_header(rec->session, rec->evlist, 274 file->fd, true); 275 perf_session__delete(rec->session); 276 perf_evlist__delete(rec->evlist); 277 symbol__exit(); 278 } 279 } 280 281 static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 282 { 283 int err; 284 struct perf_tool *tool = data; 285 /* 286 *As for guest kernel when processing subcommand record&report, 287 *we arrange module mmap prior to guest kernel mmap and trigger 288 *a preload dso because default guest module symbols are loaded 289 *from guest kallsyms instead of /lib/modules/XXX/XXX. This 290 *method is used to avoid symbol missing when the first addr is 291 *in module instead of in guest kernel. 292 */ 293 err = perf_event__synthesize_modules(tool, process_synthesized_event, 294 machine); 295 if (err < 0) 296 pr_err("Couldn't record guest kernel [%d]'s reference" 297 " relocation symbol.\n", machine->pid); 298 299 /* 300 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 301 * have no _text sometimes. 302 */ 303 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 304 machine, "_text"); 305 if (err < 0) 306 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 307 machine, "_stext"); 308 if (err < 0) 309 pr_err("Couldn't record guest kernel [%d]'s reference" 310 " relocation symbol.\n", machine->pid); 311 } 312 313 static struct perf_event_header finished_round_event = { 314 .size = sizeof(struct perf_event_header), 315 .type = PERF_RECORD_FINISHED_ROUND, 316 }; 317 318 static int perf_record__mmap_read_all(struct perf_record *rec) 319 { 320 int i; 321 int rc = 0; 322 323 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 324 if (rec->evlist->mmap[i].base) { 325 if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 326 rc = -1; 327 goto out; 328 } 329 } 330 } 331 332 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 333 rc = write_output(rec, &finished_round_event, 334 sizeof(finished_round_event)); 335 336 out: 337 return rc; 338 } 339 340 static void perf_record__init_features(struct perf_record *rec) 341 { 342 struct perf_evlist *evsel_list = rec->evlist; 343 struct perf_session *session = rec->session; 344 int feat; 345 346 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 347 perf_header__set_feat(&session->header, feat); 348 349 if (rec->no_buildid) 350 perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 351 352 if (!have_tracepoints(&evsel_list->entries)) 353 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 354 355 if (!rec->opts.branch_stack) 356 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 357 } 358 359 static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 360 { 361 int err; 362 unsigned long waking = 0; 363 const bool forks = argc > 0; 364 struct machine *machine; 365 struct perf_tool *tool = &rec->tool; 366 struct perf_record_opts *opts = &rec->opts; 367 struct perf_evlist *evsel_list = rec->evlist; 368 struct perf_data_file *file = &rec->file; 369 struct perf_session *session; 370 bool disabled = false; 371 372 rec->progname = argv[0]; 373 374 on_exit(perf_record__sig_exit, rec); 375 signal(SIGCHLD, sig_handler); 376 signal(SIGINT, sig_handler); 377 signal(SIGUSR1, sig_handler); 378 signal(SIGTERM, sig_handler); 379 380 session = perf_session__new(file, false, NULL); 381 if (session == NULL) { 382 pr_err("Not enough memory for reading perf file header\n"); 383 return -1; 384 } 385 386 rec->session = session; 387 388 perf_record__init_features(rec); 389 390 if (forks) { 391 err = perf_evlist__prepare_workload(evsel_list, &opts->target, 392 argv, file->is_pipe, 393 true); 394 if (err < 0) { 395 pr_err("Couldn't run the workload!\n"); 396 goto out_delete_session; 397 } 398 } 399 400 if (perf_record__open(rec) != 0) { 401 err = -1; 402 goto out_delete_session; 403 } 404 405 if (!evsel_list->nr_groups) 406 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 407 408 /* 409 * perf_session__delete(session) will be called at perf_record__exit() 410 */ 411 on_exit(perf_record__exit, rec); 412 413 if (file->is_pipe) { 414 err = perf_header__write_pipe(file->fd); 415 if (err < 0) 416 goto out_delete_session; 417 } else { 418 err = perf_session__write_header(session, evsel_list, 419 file->fd, false); 420 if (err < 0) 421 goto out_delete_session; 422 } 423 424 if (!rec->no_buildid 425 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 426 pr_err("Couldn't generate buildids. " 427 "Use --no-buildid to profile anyway.\n"); 428 err = -1; 429 goto out_delete_session; 430 } 431 432 machine = &session->machines.host; 433 434 if (file->is_pipe) { 435 err = perf_event__synthesize_attrs(tool, session, 436 process_synthesized_event); 437 if (err < 0) { 438 pr_err("Couldn't synthesize attrs.\n"); 439 goto out_delete_session; 440 } 441 442 if (have_tracepoints(&evsel_list->entries)) { 443 /* 444 * FIXME err <= 0 here actually means that 445 * there were no tracepoints so its not really 446 * an error, just that we don't need to 447 * synthesize anything. We really have to 448 * return this more properly and also 449 * propagate errors that now are calling die() 450 */ 451 err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, 452 process_synthesized_event); 453 if (err <= 0) { 454 pr_err("Couldn't record tracing data.\n"); 455 goto out_delete_session; 456 } 457 rec->bytes_written += err; 458 } 459 } 460 461 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 462 machine, "_text"); 463 if (err < 0) 464 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 465 machine, "_stext"); 466 if (err < 0) 467 pr_err("Couldn't record kernel reference relocation symbol\n" 468 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 469 "Check /proc/kallsyms permission or run as root.\n"); 470 471 err = perf_event__synthesize_modules(tool, process_synthesized_event, 472 machine); 473 if (err < 0) 474 pr_err("Couldn't record kernel module information.\n" 475 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 476 "Check /proc/modules permission or run as root.\n"); 477 478 if (perf_guest) { 479 machines__process_guests(&session->machines, 480 perf_event__synthesize_guest_os, tool); 481 } 482 483 if (perf_target__has_task(&opts->target)) 484 err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 485 process_synthesized_event, 486 machine); 487 else if (perf_target__has_cpu(&opts->target)) 488 err = perf_event__synthesize_threads(tool, process_synthesized_event, 489 machine); 490 else /* command specified */ 491 err = 0; 492 493 if (err != 0) 494 goto out_delete_session; 495 496 if (rec->realtime_prio) { 497 struct sched_param param; 498 499 param.sched_priority = rec->realtime_prio; 500 if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 501 pr_err("Could not set realtime priority.\n"); 502 err = -1; 503 goto out_delete_session; 504 } 505 } 506 507 /* 508 * When perf is starting the traced process, all the events 509 * (apart from group members) have enable_on_exec=1 set, 510 * so don't spoil it by prematurely enabling them. 511 */ 512 if (!perf_target__none(&opts->target)) 513 perf_evlist__enable(evsel_list); 514 515 /* 516 * Let the child rip 517 */ 518 if (forks) 519 perf_evlist__start_workload(evsel_list); 520 521 for (;;) { 522 int hits = rec->samples; 523 524 if (perf_record__mmap_read_all(rec) < 0) { 525 err = -1; 526 goto out_delete_session; 527 } 528 529 if (hits == rec->samples) { 530 if (done) 531 break; 532 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 533 waking++; 534 } 535 536 /* 537 * When perf is starting the traced process, at the end events 538 * die with the process and we wait for that. Thus no need to 539 * disable events in this case. 540 */ 541 if (done && !disabled && !perf_target__none(&opts->target)) { 542 perf_evlist__disable(evsel_list); 543 disabled = true; 544 } 545 } 546 547 if (quiet || signr == SIGUSR1) 548 return 0; 549 550 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 551 552 /* 553 * Approximate RIP event size: 24 bytes. 554 */ 555 fprintf(stderr, 556 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 557 (double)rec->bytes_written / 1024.0 / 1024.0, 558 file->path, 559 rec->bytes_written / 24); 560 561 return 0; 562 563 out_delete_session: 564 perf_session__delete(session); 565 return err; 566 } 567 568 #define BRANCH_OPT(n, m) \ 569 { .name = n, .mode = (m) } 570 571 #define BRANCH_END { .name = NULL } 572 573 struct branch_mode { 574 const char *name; 575 int mode; 576 }; 577 578 static const struct branch_mode branch_modes[] = { 579 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 580 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 581 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 582 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 583 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 584 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 585 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 586 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 587 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 588 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 589 BRANCH_END 590 }; 591 592 static int 593 parse_branch_stack(const struct option *opt, const char *str, int unset) 594 { 595 #define ONLY_PLM \ 596 (PERF_SAMPLE_BRANCH_USER |\ 597 PERF_SAMPLE_BRANCH_KERNEL |\ 598 PERF_SAMPLE_BRANCH_HV) 599 600 uint64_t *mode = (uint64_t *)opt->value; 601 const struct branch_mode *br; 602 char *s, *os = NULL, *p; 603 int ret = -1; 604 605 if (unset) 606 return 0; 607 608 /* 609 * cannot set it twice, -b + --branch-filter for instance 610 */ 611 if (*mode) 612 return -1; 613 614 /* str may be NULL in case no arg is passed to -b */ 615 if (str) { 616 /* because str is read-only */ 617 s = os = strdup(str); 618 if (!s) 619 return -1; 620 621 for (;;) { 622 p = strchr(s, ','); 623 if (p) 624 *p = '\0'; 625 626 for (br = branch_modes; br->name; br++) { 627 if (!strcasecmp(s, br->name)) 628 break; 629 } 630 if (!br->name) { 631 ui__warning("unknown branch filter %s," 632 " check man page\n", s); 633 goto error; 634 } 635 636 *mode |= br->mode; 637 638 if (!p) 639 break; 640 641 s = p + 1; 642 } 643 } 644 ret = 0; 645 646 /* default to any branch */ 647 if ((*mode & ~ONLY_PLM) == 0) { 648 *mode = PERF_SAMPLE_BRANCH_ANY; 649 } 650 error: 651 free(os); 652 return ret; 653 } 654 655 #ifdef HAVE_LIBUNWIND_SUPPORT 656 static int get_stack_size(char *str, unsigned long *_size) 657 { 658 char *endptr; 659 unsigned long size; 660 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 661 662 size = strtoul(str, &endptr, 0); 663 664 do { 665 if (*endptr) 666 break; 667 668 size = round_up(size, sizeof(u64)); 669 if (!size || size > max_size) 670 break; 671 672 *_size = size; 673 return 0; 674 675 } while (0); 676 677 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 678 max_size, str); 679 return -1; 680 } 681 #endif /* HAVE_LIBUNWIND_SUPPORT */ 682 683 int record_parse_callchain(const char *arg, struct perf_record_opts *opts) 684 { 685 char *tok, *name, *saveptr = NULL; 686 char *buf; 687 int ret = -1; 688 689 /* We need buffer that we know we can write to. */ 690 buf = malloc(strlen(arg) + 1); 691 if (!buf) 692 return -ENOMEM; 693 694 strcpy(buf, arg); 695 696 tok = strtok_r((char *)buf, ",", &saveptr); 697 name = tok ? : (char *)buf; 698 699 do { 700 /* Framepointer style */ 701 if (!strncmp(name, "fp", sizeof("fp"))) { 702 if (!strtok_r(NULL, ",", &saveptr)) { 703 opts->call_graph = CALLCHAIN_FP; 704 ret = 0; 705 } else 706 pr_err("callchain: No more arguments " 707 "needed for -g fp\n"); 708 break; 709 710 #ifdef HAVE_LIBUNWIND_SUPPORT 711 /* Dwarf style */ 712 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 713 const unsigned long default_stack_dump_size = 8192; 714 715 ret = 0; 716 opts->call_graph = CALLCHAIN_DWARF; 717 opts->stack_dump_size = default_stack_dump_size; 718 719 tok = strtok_r(NULL, ",", &saveptr); 720 if (tok) { 721 unsigned long size = 0; 722 723 ret = get_stack_size(tok, &size); 724 opts->stack_dump_size = size; 725 } 726 #endif /* HAVE_LIBUNWIND_SUPPORT */ 727 } else { 728 pr_err("callchain: Unknown --call-graph option " 729 "value: %s\n", arg); 730 break; 731 } 732 733 } while (0); 734 735 free(buf); 736 return ret; 737 } 738 739 static void callchain_debug(struct perf_record_opts *opts) 740 { 741 pr_debug("callchain: type %d\n", opts->call_graph); 742 743 if (opts->call_graph == CALLCHAIN_DWARF) 744 pr_debug("callchain: stack dump size %d\n", 745 opts->stack_dump_size); 746 } 747 748 int record_parse_callchain_opt(const struct option *opt, 749 const char *arg, 750 int unset) 751 { 752 struct perf_record_opts *opts = opt->value; 753 int ret; 754 755 /* --no-call-graph */ 756 if (unset) { 757 opts->call_graph = CALLCHAIN_NONE; 758 pr_debug("callchain: disabled\n"); 759 return 0; 760 } 761 762 ret = record_parse_callchain(arg, opts); 763 if (!ret) 764 callchain_debug(opts); 765 766 return ret; 767 } 768 769 int record_callchain_opt(const struct option *opt, 770 const char *arg __maybe_unused, 771 int unset __maybe_unused) 772 { 773 struct perf_record_opts *opts = opt->value; 774 775 if (opts->call_graph == CALLCHAIN_NONE) 776 opts->call_graph = CALLCHAIN_FP; 777 778 callchain_debug(opts); 779 return 0; 780 } 781 782 static const char * const record_usage[] = { 783 "perf record [<options>] [<command>]", 784 "perf record [<options>] -- <command> [<options>]", 785 NULL 786 }; 787 788 /* 789 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 790 * because we need to have access to it in perf_record__exit, that is called 791 * after cmd_record() exits, but since record_options need to be accessible to 792 * builtin-script, leave it here. 793 * 794 * At least we don't ouch it in all the other functions here directly. 795 * 796 * Just say no to tons of global variables, sigh. 797 */ 798 static struct perf_record record = { 799 .opts = { 800 .mmap_pages = UINT_MAX, 801 .user_freq = UINT_MAX, 802 .user_interval = ULLONG_MAX, 803 .freq = 4000, 804 .target = { 805 .uses_mmap = true, 806 }, 807 }, 808 }; 809 810 #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 811 812 #ifdef HAVE_LIBUNWIND_SUPPORT 813 const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 814 #else 815 const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 816 #endif 817 818 /* 819 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 820 * with it and switch to use the library functions in perf_evlist that came 821 * from builtin-record.c, i.e. use perf_record_opts, 822 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 823 * using pipes, etc. 824 */ 825 const struct option record_options[] = { 826 OPT_CALLBACK('e', "event", &record.evlist, "event", 827 "event selector. use 'perf list' to list available events", 828 parse_events_option), 829 OPT_CALLBACK(0, "filter", &record.evlist, "filter", 830 "event filter", parse_filter), 831 OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 832 "record events on existing process id"), 833 OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 834 "record events on existing thread id"), 835 OPT_INTEGER('r', "realtime", &record.realtime_prio, 836 "collect data with this RT SCHED_FIFO priority"), 837 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 838 "collect data without buffering"), 839 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 840 "collect raw sample records from all opened counters"), 841 OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 842 "system-wide collection from all CPUs"), 843 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 844 "list of cpus to monitor"), 845 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 846 OPT_STRING('o', "output", &record.file.path, "file", 847 "output file name"), 848 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 849 "child tasks do not inherit counters"), 850 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 851 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 852 "number of mmap data pages", 853 perf_evlist__parse_mmap_pages), 854 OPT_BOOLEAN(0, "group", &record.opts.group, 855 "put the counters into a counter group"), 856 OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 857 NULL, "enables call-graph recording" , 858 &record_callchain_opt), 859 OPT_CALLBACK(0, "call-graph", &record.opts, 860 "mode[,dump_size]", record_callchain_help, 861 &record_parse_callchain_opt), 862 OPT_INCR('v', "verbose", &verbose, 863 "be more verbose (show counter open errors, etc)"), 864 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 865 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 866 "per thread counts"), 867 OPT_BOOLEAN('d', "data", &record.opts.sample_address, 868 "Sample addresses"), 869 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 870 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 871 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 872 "don't sample"), 873 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 874 "do not update the buildid cache"), 875 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 876 "do not collect buildids in perf.data"), 877 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 878 "monitor event in cgroup name only", 879 parse_cgroups), 880 OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 881 "user to profile"), 882 883 OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 884 "branch any", "sample any taken branches", 885 parse_branch_stack), 886 887 OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 888 "branch filter mask", "branch stack filter modes", 889 parse_branch_stack), 890 OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 891 "sample by weight (on special events only)"), 892 OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 893 "sample transaction flags (special events only)"), 894 OPT_END() 895 }; 896 897 int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 898 { 899 int err = -ENOMEM; 900 struct perf_evlist *evsel_list; 901 struct perf_record *rec = &record; 902 char errbuf[BUFSIZ]; 903 904 evsel_list = perf_evlist__new(); 905 if (evsel_list == NULL) 906 return -ENOMEM; 907 908 rec->evlist = evsel_list; 909 910 argc = parse_options(argc, argv, record_options, record_usage, 911 PARSE_OPT_STOP_AT_NON_OPTION); 912 if (!argc && perf_target__none(&rec->opts.target)) 913 usage_with_options(record_usage, record_options); 914 915 if (nr_cgroups && !rec->opts.target.system_wide) { 916 ui__error("cgroup monitoring only available in" 917 " system-wide mode\n"); 918 usage_with_options(record_usage, record_options); 919 } 920 921 symbol__init(); 922 923 if (symbol_conf.kptr_restrict) 924 pr_warning( 925 "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 926 "check /proc/sys/kernel/kptr_restrict.\n\n" 927 "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 928 "file is not found in the buildid cache or in the vmlinux path.\n\n" 929 "Samples in kernel modules won't be resolved at all.\n\n" 930 "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 931 "even with a suitable vmlinux or kallsyms file.\n\n"); 932 933 if (rec->no_buildid_cache || rec->no_buildid) 934 disable_buildid_cache(); 935 936 if (evsel_list->nr_entries == 0 && 937 perf_evlist__add_default(evsel_list) < 0) { 938 pr_err("Not enough memory for event selector list\n"); 939 goto out_symbol_exit; 940 } 941 942 err = perf_target__validate(&rec->opts.target); 943 if (err) { 944 perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 945 ui__warning("%s", errbuf); 946 } 947 948 err = perf_target__parse_uid(&rec->opts.target); 949 if (err) { 950 int saved_errno = errno; 951 952 perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 953 ui__error("%s", errbuf); 954 955 err = -saved_errno; 956 goto out_symbol_exit; 957 } 958 959 err = -ENOMEM; 960 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 961 usage_with_options(record_usage, record_options); 962 963 if (perf_record_opts__config(&rec->opts)) { 964 err = -EINVAL; 965 goto out_free_fd; 966 } 967 968 err = __cmd_record(&record, argc, argv); 969 970 perf_evlist__munmap(evsel_list); 971 perf_evlist__close(evsel_list); 972 out_free_fd: 973 perf_evlist__delete_maps(evsel_list); 974 out_symbol_exit: 975 symbol__exit(); 976 return err; 977 } 978