Linux Audio

Check our new training course

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