xref: /openbmc/linux/tools/perf/builtin-record.c (revision 161f4089)
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, &param)) {
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