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