xref: /openbmc/linux/tools/perf/builtin-record.c (revision 95485b1cda827e4db7102ad5fde1791087a0f4c5)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-record.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin record command: Record the profile of a workload
586470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
686470930SIngo Molnar  * later analysis via perf report.
786470930SIngo Molnar  */
8b8f46c5aSXiao Guangrong #define _FILE_OFFSET_BITS 64
9b8f46c5aSXiao Guangrong 
1086470930SIngo Molnar #include "builtin.h"
1186470930SIngo Molnar 
1286470930SIngo Molnar #include "perf.h"
1386470930SIngo Molnar 
146122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1586470930SIngo Molnar #include "util/util.h"
1686470930SIngo Molnar #include "util/parse-options.h"
1786470930SIngo Molnar #include "util/parse-events.h"
1886470930SIngo Molnar 
197c6a1c65SPeter Zijlstra #include "util/header.h"
2066e274f3SFrederic Weisbecker #include "util/event.h"
21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
238f28827aSFrederic Weisbecker #include "util/debug.h"
2494c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
27a12b51c4SPaul Mackerras #include "util/cpumap.h"
28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
297c6a1c65SPeter Zijlstra 
3086470930SIngo Molnar #include <unistd.h>
3186470930SIngo Molnar #include <sched.h>
32a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
3386470930SIngo Molnar 
3426d33022SJiri Olsa #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
3526d33022SJiri Olsa 
36*95485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
3726d33022SJiri Olsa static unsigned long default_stack_dump_size = 8192;
3826d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
39*95485b1cSNamhyung Kim #else
40*95485b1cSNamhyung Kim static char callchain_help[] = CALLCHAIN_HELP "[fp]";
4126d33022SJiri Olsa #endif
4226d33022SJiri Olsa 
437865e817SFrederic Weisbecker enum write_mode_t {
447865e817SFrederic Weisbecker 	WRITE_FORCE,
457865e817SFrederic Weisbecker 	WRITE_APPEND
467865e817SFrederic Weisbecker };
477865e817SFrederic Weisbecker 
48d20deb64SArnaldo Carvalho de Melo struct perf_record {
4945694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
50d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts	opts;
51d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
52d20deb64SArnaldo Carvalho de Melo 	const char		*output_name;
53d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
54d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
55d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
56d20deb64SArnaldo Carvalho de Melo 	int			output;
57d20deb64SArnaldo Carvalho de Melo 	unsigned int		page_size;
58d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
59d20deb64SArnaldo Carvalho de Melo 	enum write_mode_t	write_mode;
60d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
61d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
62d20deb64SArnaldo Carvalho de Melo 	bool			force;
63d20deb64SArnaldo Carvalho de Melo 	bool			file_new;
64d20deb64SArnaldo Carvalho de Melo 	bool			append_file;
65d20deb64SArnaldo Carvalho de Melo 	long			samples;
66d20deb64SArnaldo Carvalho de Melo 	off_t			post_processing_offset;
670f82ebc4SArnaldo Carvalho de Melo };
6886470930SIngo Molnar 
69d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size)
709215545eSTom Zanussi {
71d20deb64SArnaldo Carvalho de Melo 	rec->bytes_written += size;
729215545eSTom Zanussi }
739215545eSTom Zanussi 
748d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size)
75f5970550SPeter Zijlstra {
76f5970550SPeter Zijlstra 	while (size) {
77d20deb64SArnaldo Carvalho de Melo 		int ret = write(rec->output, buf, size);
78f5970550SPeter Zijlstra 
798d3eca20SDavid Ahern 		if (ret < 0) {
808d3eca20SDavid Ahern 			pr_err("failed to write\n");
818d3eca20SDavid Ahern 			return -1;
828d3eca20SDavid Ahern 		}
83f5970550SPeter Zijlstra 
84f5970550SPeter Zijlstra 		size -= ret;
85f5970550SPeter Zijlstra 		buf += ret;
86f5970550SPeter Zijlstra 
87d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written += ret;
88f5970550SPeter Zijlstra 	}
898d3eca20SDavid Ahern 
908d3eca20SDavid Ahern 	return 0;
91f5970550SPeter Zijlstra }
92f5970550SPeter Zijlstra 
9345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
94d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
951d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
961d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
97234fbbf5SArnaldo Carvalho de Melo {
9845694aa7SArnaldo Carvalho de Melo 	struct perf_record *rec = container_of(tool, struct perf_record, tool);
998d3eca20SDavid Ahern 	if (write_output(rec, event, event->header.size) < 0)
1008d3eca20SDavid Ahern 		return -1;
1018d3eca20SDavid Ahern 
102234fbbf5SArnaldo Carvalho de Melo 	return 0;
103234fbbf5SArnaldo Carvalho de Melo }
104234fbbf5SArnaldo Carvalho de Melo 
1058d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec,
106d20deb64SArnaldo Carvalho de Melo 				   struct perf_mmap *md)
10786470930SIngo Molnar {
108744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
10986470930SIngo Molnar 	unsigned int old = md->prev;
110d20deb64SArnaldo Carvalho de Melo 	unsigned char *data = md->base + rec->page_size;
11186470930SIngo Molnar 	unsigned long size;
11286470930SIngo Molnar 	void *buf;
1138d3eca20SDavid Ahern 	int rc = 0;
11486470930SIngo Molnar 
115dc82009aSArnaldo Carvalho de Melo 	if (old == head)
1168d3eca20SDavid Ahern 		return 0;
11786470930SIngo Molnar 
118d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
11986470930SIngo Molnar 
12086470930SIngo Molnar 	size = head - old;
12186470930SIngo Molnar 
12286470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
12386470930SIngo Molnar 		buf = &data[old & md->mask];
12486470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
12586470930SIngo Molnar 		old += size;
12686470930SIngo Molnar 
1278d3eca20SDavid Ahern 		if (write_output(rec, buf, size) < 0) {
1288d3eca20SDavid Ahern 			rc = -1;
1298d3eca20SDavid Ahern 			goto out;
1308d3eca20SDavid Ahern 		}
13186470930SIngo Molnar 	}
13286470930SIngo Molnar 
13386470930SIngo Molnar 	buf = &data[old & md->mask];
13486470930SIngo Molnar 	size = head - old;
13586470930SIngo Molnar 	old += size;
13686470930SIngo Molnar 
1378d3eca20SDavid Ahern 	if (write_output(rec, buf, size) < 0) {
1388d3eca20SDavid Ahern 		rc = -1;
1398d3eca20SDavid Ahern 		goto out;
1408d3eca20SDavid Ahern 	}
14186470930SIngo Molnar 
14286470930SIngo Molnar 	md->prev = old;
143115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
1448d3eca20SDavid Ahern 
1458d3eca20SDavid Ahern out:
1468d3eca20SDavid Ahern 	return rc;
14786470930SIngo Molnar }
14886470930SIngo Molnar 
14986470930SIngo Molnar static volatile int done = 0;
150f7b7c26eSPeter Zijlstra static volatile int signr = -1;
15133e49ea7SAndi Kleen static volatile int child_finished = 0;
15286470930SIngo Molnar 
15386470930SIngo Molnar static void sig_handler(int sig)
15486470930SIngo Molnar {
15533e49ea7SAndi Kleen 	if (sig == SIGCHLD)
15633e49ea7SAndi Kleen 		child_finished = 1;
15733e49ea7SAndi Kleen 
15886470930SIngo Molnar 	done = 1;
159f7b7c26eSPeter Zijlstra 	signr = sig;
160f7b7c26eSPeter Zijlstra }
161f7b7c26eSPeter Zijlstra 
1621d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
163f7b7c26eSPeter Zijlstra {
164d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
16533e49ea7SAndi Kleen 	int status;
16633e49ea7SAndi Kleen 
167d20deb64SArnaldo Carvalho de Melo 	if (rec->evlist->workload.pid > 0) {
16833e49ea7SAndi Kleen 		if (!child_finished)
169d20deb64SArnaldo Carvalho de Melo 			kill(rec->evlist->workload.pid, SIGTERM);
170933da83aSChris Wilson 
17133e49ea7SAndi Kleen 		wait(&status);
17233e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
173d20deb64SArnaldo Carvalho de Melo 			psignal(WTERMSIG(status), rec->progname);
17433e49ea7SAndi Kleen 	}
17533e49ea7SAndi Kleen 
17618483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
177f7b7c26eSPeter Zijlstra 		return;
178f7b7c26eSPeter Zijlstra 
179f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
180f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
18186470930SIngo Molnar }
18286470930SIngo Molnar 
183a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
184a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
185a91e5431SArnaldo Carvalho de Melo {
186a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
187a91e5431SArnaldo Carvalho de Melo 
188a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
189a91e5431SArnaldo Carvalho de Melo 		return false;
190a91e5431SArnaldo Carvalho de Melo 
1910c21f736SArnaldo Carvalho de Melo 	pair = perf_evlist__first(other);
192a91e5431SArnaldo Carvalho de Melo 
193a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
194a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
195a91e5431SArnaldo Carvalho de Melo 			return false;
1960c21f736SArnaldo Carvalho de Melo 		pair = perf_evsel__next(pair);
197a91e5431SArnaldo Carvalho de Melo 	}
198a91e5431SArnaldo Carvalho de Melo 
199a91e5431SArnaldo Carvalho de Melo 	return true;
200a91e5431SArnaldo Carvalho de Melo }
201a91e5431SArnaldo Carvalho de Melo 
2028d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec)
203dd7927f4SArnaldo Carvalho de Melo {
2046a4bb04cSJiri Olsa 	struct perf_evsel *pos;
205d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
206d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
207d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
2088d3eca20SDavid Ahern 	int rc = 0;
209dd7927f4SArnaldo Carvalho de Melo 
210d20deb64SArnaldo Carvalho de Melo 	perf_evlist__config_attrs(evlist, opts);
2110f82ebc4SArnaldo Carvalho de Melo 
2126a4bb04cSJiri Olsa 	if (opts->group)
21363dab225SArnaldo Carvalho de Melo 		perf_evlist__set_leader(evlist);
2146a4bb04cSJiri Olsa 
215dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
216dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
217dd7927f4SArnaldo Carvalho de Melo 		/*
218dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
219dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
220dd7927f4SArnaldo Carvalho de Melo 		 *
221dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
222dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
223dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
224dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
225dd7927f4SArnaldo Carvalho de Melo 		 *
226dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
227dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
228dd7927f4SArnaldo Carvalho de Melo 		 */
229dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
230dd7927f4SArnaldo Carvalho de Melo 
2310c978128SArnaldo Carvalho de Melo fallback_missing_features:
2320c978128SArnaldo Carvalho de Melo 		if (opts->exclude_guest_missing)
2330c978128SArnaldo Carvalho de Melo 			attr->exclude_guest = attr->exclude_host = 0;
2349c90a61cSArnaldo Carvalho de Melo retry_sample_id:
235808e1226SArnaldo Carvalho de Melo 		attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
2363da297a6SIngo Molnar try_again:
2376a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
23886470930SIngo Molnar 			int err = errno;
23986470930SIngo Molnar 
240c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
241b8631e6eSArnaldo Carvalho de Melo 				ui__error_paranoid();
2428d3eca20SDavid Ahern 				rc = -err;
2438d3eca20SDavid Ahern 				goto out;
244bea03405SNamhyung Kim 			} else if (err ==  ENODEV && opts->target.cpu_list) {
2458d3eca20SDavid Ahern 				pr_err("No such device - did you specify"
246d6d901c2SZhang, Yanmin 				       " an out-of-range profile CPU?\n");
2478d3eca20SDavid Ahern 				rc = -err;
2488d3eca20SDavid Ahern 				goto out;
2490c978128SArnaldo Carvalho de Melo 			} else if (err == EINVAL) {
2500c978128SArnaldo Carvalho de Melo 				if (!opts->exclude_guest_missing &&
2510c978128SArnaldo Carvalho de Melo 				    (attr->exclude_guest || attr->exclude_host)) {
2520c978128SArnaldo Carvalho de Melo 					pr_debug("Old kernel, cannot exclude "
2530c978128SArnaldo Carvalho de Melo 						 "guest or host samples.\n");
2540c978128SArnaldo Carvalho de Melo 					opts->exclude_guest_missing = true;
2550c978128SArnaldo Carvalho de Melo 					goto fallback_missing_features;
256808e1226SArnaldo Carvalho de Melo 				} else if (!opts->sample_id_all_missing) {
2579c90a61cSArnaldo Carvalho de Melo 					/*
2589c90a61cSArnaldo Carvalho de Melo 					 * Old kernel, no attr->sample_id_type_all field
2599c90a61cSArnaldo Carvalho de Melo 					 */
260808e1226SArnaldo Carvalho de Melo 					opts->sample_id_all_missing = true;
261d20deb64SArnaldo Carvalho de Melo 					if (!opts->sample_time && !opts->raw_samples && !time_needed)
262eac23d1cSIan Munsie 						attr->sample_type &= ~PERF_SAMPLE_TIME;
263eac23d1cSIan Munsie 
2649c90a61cSArnaldo Carvalho de Melo 					goto retry_sample_id;
265d6d901c2SZhang, Yanmin 				}
2660c978128SArnaldo Carvalho de Melo 			}
2673da297a6SIngo Molnar 
2683da297a6SIngo Molnar 			/*
2693da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2703da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
271028d455bSDavid Ahern 			 * is always available even if no PMU support.
272028d455bSDavid Ahern 			 *
273028d455bSDavid Ahern 			 * PPC returns ENXIO until 2.6.37 (behavior changed
274028d455bSDavid Ahern 			 * with commit b0a873e).
2753da297a6SIngo Molnar 			 */
276028d455bSDavid Ahern 			if ((err == ENOENT || err == ENXIO)
277028d455bSDavid Ahern 					&& attr->type == PERF_TYPE_HARDWARE
278f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
2793da297a6SIngo Molnar 
2803da297a6SIngo Molnar 				if (verbose)
281ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
282ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
2833da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
284f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
285d1cae34dSDavid Ahern 				if (pos->name) {
286d1cae34dSDavid Ahern 					free(pos->name);
287d1cae34dSDavid Ahern 					pos->name = NULL;
288d1cae34dSDavid Ahern 				}
2893da297a6SIngo Molnar 				goto try_again;
2903da297a6SIngo Molnar 			}
291ca6a4258SDavid Ahern 
292ca6a4258SDavid Ahern 			if (err == ENOENT) {
2933780f488SNamhyung Kim 				ui__error("The %s event is not supported.\n",
2947289f83cSArnaldo Carvalho de Melo 					  perf_evsel__name(pos));
2958d3eca20SDavid Ahern 				rc = -err;
2968d3eca20SDavid Ahern 				goto out;
297ca6a4258SDavid Ahern 			}
298ca6a4258SDavid Ahern 
29930c806a0SIngo Molnar 			printf("\n");
3001863fbbbSStephane Eranian 			error("sys_perf_event_open() syscall returned with %d "
3011863fbbbSStephane Eranian 			      "(%s) for event %s. /bin/dmesg may provide "
3021863fbbbSStephane Eranian 			      "additional information.\n",
3031863fbbbSStephane Eranian 			      err, strerror(err), perf_evsel__name(pos));
304bfd45118SSimon Kaempflein 
305bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
3068d3eca20SDavid Ahern 			if (attr->type == PERF_TYPE_HARDWARE &&
3078d3eca20SDavid Ahern 			    err == EOPNOTSUPP) {
3088d3eca20SDavid Ahern 				pr_err("No hardware sampling interrupt available."
309d6d901c2SZhang, Yanmin 				       " No APIC? If so then you can boot the kernel"
310d6d901c2SZhang, Yanmin 				       " with the \"lapic\" boot parameter to"
311d6d901c2SZhang, Yanmin 				       " force-enable it.\n");
3128d3eca20SDavid Ahern 				rc = -err;
3138d3eca20SDavid Ahern 				goto out;
3148d3eca20SDavid Ahern 			}
315bfd45118SSimon Kaempflein #endif
316bfd45118SSimon Kaempflein 
3178d3eca20SDavid Ahern 			pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3188d3eca20SDavid Ahern 			rc = -err;
3198d3eca20SDavid Ahern 			goto out;
3207c6a1c65SPeter Zijlstra 		}
3217c6a1c65SPeter Zijlstra 	}
3227c6a1c65SPeter Zijlstra 
3231491a632SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist)) {
3240a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3250a102479SFrederic Weisbecker 			strerror(errno));
3268d3eca20SDavid Ahern 		rc = -1;
3278d3eca20SDavid Ahern 		goto out;
3280a102479SFrederic Weisbecker 	}
3290a102479SFrederic Weisbecker 
33018e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
3318d3eca20SDavid Ahern 		if (errno == EPERM) {
3328d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
33318e60939SNelson Elhage 			       "Consider increasing "
33418e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
33518e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
33618e60939SNelson Elhage 			       "(current value: %d)\n", opts->mmap_pages);
3378d3eca20SDavid Ahern 			rc = -errno;
3388d3eca20SDavid Ahern 		} else if (!is_power_of_2(opts->mmap_pages)) {
3398d3eca20SDavid Ahern 			pr_err("--mmap_pages/-m value must be a power of two.");
3408d3eca20SDavid Ahern 			rc = -EINVAL;
3418d3eca20SDavid Ahern 		} else {
3428d3eca20SDavid Ahern 			pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
3438d3eca20SDavid Ahern 			rc = -errno;
3448d3eca20SDavid Ahern 		}
3458d3eca20SDavid Ahern 		goto out;
34618e60939SNelson Elhage 	}
3470a27d7f9SArnaldo Carvalho de Melo 
348d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
349a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
350a91e5431SArnaldo Carvalho de Melo 	else {
351a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
352a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
3538d3eca20SDavid Ahern 			rc = -1;
3548d3eca20SDavid Ahern 			goto out;
355dd7927f4SArnaldo Carvalho de Melo 		}
35686470930SIngo Molnar  	}
35786470930SIngo Molnar 
3587b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3598d3eca20SDavid Ahern out:
3608d3eca20SDavid Ahern 	return rc;
361a91e5431SArnaldo Carvalho de Melo }
362a91e5431SArnaldo Carvalho de Melo 
363d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
3646122e4e4SArnaldo Carvalho de Melo {
365d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
3666122e4e4SArnaldo Carvalho de Melo 
3679f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3689f591fd7SArnaldo Carvalho de Melo 		return 0;
3699f591fd7SArnaldo Carvalho de Melo 
370d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
371d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
372d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
3736122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3746122e4e4SArnaldo Carvalho de Melo }
3756122e4e4SArnaldo Carvalho de Melo 
3768d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg)
377f5970550SPeter Zijlstra {
378d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
379f5970550SPeter Zijlstra 
3808d3eca20SDavid Ahern 	if (status != 0)
3818d3eca20SDavid Ahern 		return;
3828d3eca20SDavid Ahern 
383d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
384d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
385d20deb64SArnaldo Carvalho de Melo 
386d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
387d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
388d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
389d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
390d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
391d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
392d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
393c7929e47STom Zanussi 	}
394f5970550SPeter Zijlstra }
395f5970550SPeter Zijlstra 
3968115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
397a1645ce1SZhang, Yanmin {
398a1645ce1SZhang, Yanmin 	int err;
39945694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
400a1645ce1SZhang, Yanmin 
40123346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
402a1645ce1SZhang, Yanmin 		return;
403a1645ce1SZhang, Yanmin 
404a1645ce1SZhang, Yanmin 	/*
405a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
406a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
407a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
408a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
409a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
410a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
411a1645ce1SZhang, Yanmin 	 */
41245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
413743eb868SArnaldo Carvalho de Melo 					     machine);
414a1645ce1SZhang, Yanmin 	if (err < 0)
415a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
417a1645ce1SZhang, Yanmin 
418a1645ce1SZhang, Yanmin 	/*
419a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
420a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
421a1645ce1SZhang, Yanmin 	 */
42245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
423743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
424a1645ce1SZhang, Yanmin 	if (err < 0)
42545694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
426743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
427a1645ce1SZhang, Yanmin 	if (err < 0)
428a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
42923346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
430a1645ce1SZhang, Yanmin }
431a1645ce1SZhang, Yanmin 
43298402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
43398402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
43498402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
43598402807SFrederic Weisbecker };
43698402807SFrederic Weisbecker 
4378d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec)
43898402807SFrederic Weisbecker {
4390e2e63ddSPeter Zijlstra 	int i;
4408d3eca20SDavid Ahern 	int rc = 0;
44198402807SFrederic Weisbecker 
442d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
4438d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
4448d3eca20SDavid Ahern 			if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
4458d3eca20SDavid Ahern 				rc = -1;
4468d3eca20SDavid Ahern 				goto out;
4478d3eca20SDavid Ahern 			}
4488d3eca20SDavid Ahern 		}
44998402807SFrederic Weisbecker 	}
45098402807SFrederic Weisbecker 
4512eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
4528d3eca20SDavid Ahern 		rc = write_output(rec, &finished_round_event,
4538d3eca20SDavid Ahern 				  sizeof(finished_round_event));
4548d3eca20SDavid Ahern 
4558d3eca20SDavid Ahern out:
4568d3eca20SDavid Ahern 	return rc;
45798402807SFrederic Weisbecker }
45898402807SFrederic Weisbecker 
459d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
46086470930SIngo Molnar {
46186470930SIngo Molnar 	struct stat st;
46286470930SIngo Molnar 	int flags;
463781ba9d2SRobert Richter 	int err, output, feat;
4648b412664SPeter Zijlstra 	unsigned long waking = 0;
46546be604bSZhang, Yanmin 	const bool forks = argc > 0;
46623346f21SArnaldo Carvalho de Melo 	struct machine *machine;
46745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
468d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
469d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
470d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
471d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
47286470930SIngo Molnar 
473d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
47433e49ea7SAndi Kleen 
475d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
47686470930SIngo Molnar 
477d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
478f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
479f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
48018483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
481f5970550SPeter Zijlstra 
482d7065adbSFranck Bui-Huu 	if (!output_name) {
483d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
484d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
485d7065adbSFranck Bui-Huu 		else
486d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
487d7065adbSFranck Bui-Huu 	}
488d7065adbSFranck Bui-Huu 	if (output_name) {
489529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
490d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
491529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
492d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
493b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
494b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
495b38d3464SArnaldo Carvalho de Melo 					 output_name);
496b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
497b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
498b38d3464SArnaldo Carvalho de Melo 			}
499d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
500d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
501266e0e21SPierre Habouzit 		}
502d7065adbSFranck Bui-Huu 	}
50386470930SIngo Molnar 
504f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
505d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
506d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
50786470930SIngo Molnar 	else
50886470930SIngo Molnar 		flags |= O_TRUNC;
50986470930SIngo Molnar 
510d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
511529870e3STom Zanussi 		output = STDOUT_FILENO;
512529870e3STom Zanussi 	else
51386470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
51486470930SIngo Molnar 	if (output < 0) {
51586470930SIngo Molnar 		perror("failed to create output file");
5168d3eca20SDavid Ahern 		return -1;
51786470930SIngo Molnar 	}
51886470930SIngo Molnar 
519d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
520d20deb64SArnaldo Carvalho de Melo 
5217865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
522d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
52394c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
524a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
525a9a70bbcSArnaldo Carvalho de Melo 		return -1;
526a9a70bbcSArnaldo Carvalho de Melo 	}
527a9a70bbcSArnaldo Carvalho de Melo 
528d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
529d20deb64SArnaldo Carvalho de Melo 
530781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
531781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
532781ba9d2SRobert Richter 
533781ba9d2SRobert Richter 	if (rec->no_buildid)
534781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
535781ba9d2SRobert Richter 
536781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
5372eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
538baa2f6ceSArnaldo Carvalho de Melo 
539330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
540330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
541330aa675SStephane Eranian 
542d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
543a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5444dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
54539d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5464dc0a04bSArnaldo Carvalho de Melo 	}
5474dc0a04bSArnaldo Carvalho de Melo 
548d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
549d20deb64SArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
55035b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
55135b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
55235b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
553856e9660SPeter Zijlstra 		}
554856e9660SPeter Zijlstra 	}
555856e9660SPeter Zijlstra 
5568d3eca20SDavid Ahern 	if (perf_record__open(rec) != 0) {
5578d3eca20SDavid Ahern 		err = -1;
5588d3eca20SDavid Ahern 		goto out_delete_session;
5598d3eca20SDavid Ahern 	}
56086470930SIngo Molnar 
561712a4b60SArnaldo Carvalho de Melo 	/*
562d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
563712a4b60SArnaldo Carvalho de Melo 	 */
564d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
565712a4b60SArnaldo Carvalho de Melo 
566d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
567529870e3STom Zanussi 		err = perf_header__write_pipe(output);
568529870e3STom Zanussi 		if (err < 0)
5698d3eca20SDavid Ahern 			goto out_delete_session;
570d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
571a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
572361c99a6SArnaldo Carvalho de Melo 						 output, false);
573d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
5748d3eca20SDavid Ahern 			goto out_delete_session;
575d5eed904SArnaldo Carvalho de Melo 	}
5767c6a1c65SPeter Zijlstra 
577d3665498SDavid Ahern 	if (!rec->no_buildid
578e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
579d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
580e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
5818d3eca20SDavid Ahern 		err = -1;
5828d3eca20SDavid Ahern 		goto out_delete_session;
583e20960c0SRobert Richter 	}
584e20960c0SRobert Richter 
585d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
5866122e4e4SArnaldo Carvalho de Melo 
587743eb868SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
588743eb868SArnaldo Carvalho de Melo 	if (!machine) {
589743eb868SArnaldo Carvalho de Melo 		pr_err("Couldn't find native kernel information.\n");
5908d3eca20SDavid Ahern 		err = -1;
5918d3eca20SDavid Ahern 		goto out_delete_session;
592743eb868SArnaldo Carvalho de Melo 	}
593743eb868SArnaldo Carvalho de Melo 
594d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
59545694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
596a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
5972c46dbb5STom Zanussi 		if (err < 0) {
5982c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
5998d3eca20SDavid Ahern 			goto out_delete_session;
6002c46dbb5STom Zanussi 		}
601cd19a035STom Zanussi 
60245694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
603743eb868SArnaldo Carvalho de Melo 							 machine);
604cd19a035STom Zanussi 		if (err < 0) {
605cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
6068d3eca20SDavid Ahern 			goto out_delete_session;
607cd19a035STom Zanussi 		}
6089215545eSTom Zanussi 
609361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
61063e0c771STom Zanussi 			/*
61163e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
61263e0c771STom Zanussi 			 * there were no tracepoints so its not really
61363e0c771STom Zanussi 			 * an error, just that we don't need to
61463e0c771STom Zanussi 			 * synthesize anything.  We really have to
61563e0c771STom Zanussi 			 * return this more properly and also
61663e0c771STom Zanussi 			 * propagate errors that now are calling die()
61763e0c771STom Zanussi 			 */
61845694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
619743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
62063e0c771STom Zanussi 			if (err <= 0) {
62163e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
6228d3eca20SDavid Ahern 				goto out_delete_session;
62363e0c771STom Zanussi 			}
624d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
6252c46dbb5STom Zanussi 		}
62663e0c771STom Zanussi 	}
6272c46dbb5STom Zanussi 
62845694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
629743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
63070162138SArnaldo Carvalho de Melo 	if (err < 0)
63145694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
632743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
633c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
634c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
635c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
636c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
63756b03f3cSArnaldo Carvalho de Melo 
63845694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
639743eb868SArnaldo Carvalho de Melo 					     machine);
640c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
641c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
642c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
643c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
644c1a3a4b9SArnaldo Carvalho de Melo 
645a1645ce1SZhang, Yanmin 	if (perf_guest)
64645694aa7SArnaldo Carvalho de Melo 		perf_session__process_machines(session, tool,
6478115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
648b7cece76SArnaldo Carvalho de Melo 
649bea03405SNamhyung Kim 	if (!opts->target.system_wide)
6508d3eca20SDavid Ahern 		err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
6518115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
652743eb868SArnaldo Carvalho de Melo 						  machine);
653234fbbf5SArnaldo Carvalho de Melo 	else
6548d3eca20SDavid Ahern 		err = perf_event__synthesize_threads(tool, process_synthesized_event,
655743eb868SArnaldo Carvalho de Melo 					       machine);
6567c6a1c65SPeter Zijlstra 
6578d3eca20SDavid Ahern 	if (err != 0)
6588d3eca20SDavid Ahern 		goto out_delete_session;
6598d3eca20SDavid Ahern 
660d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
66186470930SIngo Molnar 		struct sched_param param;
66286470930SIngo Molnar 
663d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
66486470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6656beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
6668d3eca20SDavid Ahern 			err = -1;
6678d3eca20SDavid Ahern 			goto out_delete_session;
66886470930SIngo Molnar 		}
66986470930SIngo Molnar 	}
67086470930SIngo Molnar 
671764e16a3SDavid Ahern 	perf_evlist__enable(evsel_list);
672764e16a3SDavid Ahern 
673856e9660SPeter Zijlstra 	/*
674856e9660SPeter Zijlstra 	 * Let the child rip
675856e9660SPeter Zijlstra 	 */
676d4db3f16SArnaldo Carvalho de Melo 	if (forks)
67735b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
678856e9660SPeter Zijlstra 
679649c48a9SPeter Zijlstra 	for (;;) {
680d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
68186470930SIngo Molnar 
6828d3eca20SDavid Ahern 		if (perf_record__mmap_read_all(rec) < 0) {
6838d3eca20SDavid Ahern 			err = -1;
6848d3eca20SDavid Ahern 			goto out_delete_session;
6858d3eca20SDavid Ahern 		}
68686470930SIngo Molnar 
687d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
688649c48a9SPeter Zijlstra 			if (done)
689649c48a9SPeter Zijlstra 				break;
6905c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6918b412664SPeter Zijlstra 			waking++;
6928b412664SPeter Zijlstra 		}
6938b412664SPeter Zijlstra 
6944152ab37SArnaldo Carvalho de Melo 		if (done)
6954152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6968b412664SPeter Zijlstra 	}
6978b412664SPeter Zijlstra 
69818483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
699b44308f5SArnaldo Carvalho de Melo 		return 0;
700b44308f5SArnaldo Carvalho de Melo 
7018b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
70286470930SIngo Molnar 
70386470930SIngo Molnar 	/*
70486470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
70586470930SIngo Molnar 	 */
70686470930SIngo Molnar 	fprintf(stderr,
7079486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
708d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
70986470930SIngo Molnar 		output_name,
710d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
71186470930SIngo Molnar 
71286470930SIngo Molnar 	return 0;
71339d17dacSArnaldo Carvalho de Melo 
71439d17dacSArnaldo Carvalho de Melo out_delete_session:
71539d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
71639d17dacSArnaldo Carvalho de Melo 	return err;
71786470930SIngo Molnar }
71886470930SIngo Molnar 
719bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
720bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
721bdfebd84SRoberto Agostino Vitillo 
722bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
723bdfebd84SRoberto Agostino Vitillo 
724bdfebd84SRoberto Agostino Vitillo struct branch_mode {
725bdfebd84SRoberto Agostino Vitillo 	const char *name;
726bdfebd84SRoberto Agostino Vitillo 	int mode;
727bdfebd84SRoberto Agostino Vitillo };
728bdfebd84SRoberto Agostino Vitillo 
729bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
730bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
731bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
732bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
733bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
734bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
735bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
736bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
737bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
738bdfebd84SRoberto Agostino Vitillo };
739bdfebd84SRoberto Agostino Vitillo 
740bdfebd84SRoberto Agostino Vitillo static int
741a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
742bdfebd84SRoberto Agostino Vitillo {
743bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
744bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
745bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
746bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
747bdfebd84SRoberto Agostino Vitillo 
748bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
749bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
750a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
751bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
752bdfebd84SRoberto Agostino Vitillo 
753a5aabdacSStephane Eranian 	if (unset)
754a5aabdacSStephane Eranian 		return 0;
755bdfebd84SRoberto Agostino Vitillo 
756a5aabdacSStephane Eranian 	/*
757a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
758a5aabdacSStephane Eranian 	 */
759a5aabdacSStephane Eranian 	if (*mode)
760a5aabdacSStephane Eranian 		return -1;
761a5aabdacSStephane Eranian 
762a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
763a5aabdacSStephane Eranian 	if (str) {
764bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
765bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
766bdfebd84SRoberto Agostino Vitillo 		if (!s)
767bdfebd84SRoberto Agostino Vitillo 			return -1;
768bdfebd84SRoberto Agostino Vitillo 
769bdfebd84SRoberto Agostino Vitillo 		for (;;) {
770bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
771bdfebd84SRoberto Agostino Vitillo 			if (p)
772bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
773bdfebd84SRoberto Agostino Vitillo 
774bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
775bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
776bdfebd84SRoberto Agostino Vitillo 					break;
777bdfebd84SRoberto Agostino Vitillo 			}
778a5aabdacSStephane Eranian 			if (!br->name) {
779a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
780a5aabdacSStephane Eranian 					    " check man page\n", s);
781bdfebd84SRoberto Agostino Vitillo 				goto error;
782a5aabdacSStephane Eranian 			}
783bdfebd84SRoberto Agostino Vitillo 
784bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
785bdfebd84SRoberto Agostino Vitillo 
786bdfebd84SRoberto Agostino Vitillo 			if (!p)
787bdfebd84SRoberto Agostino Vitillo 				break;
788bdfebd84SRoberto Agostino Vitillo 
789bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
790bdfebd84SRoberto Agostino Vitillo 		}
791a5aabdacSStephane Eranian 	}
792bdfebd84SRoberto Agostino Vitillo 	ret = 0;
793bdfebd84SRoberto Agostino Vitillo 
794a5aabdacSStephane Eranian 	/* default to any branch */
795bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
796a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
797bdfebd84SRoberto Agostino Vitillo 	}
798bdfebd84SRoberto Agostino Vitillo error:
799bdfebd84SRoberto Agostino Vitillo 	free(os);
800bdfebd84SRoberto Agostino Vitillo 	return ret;
801bdfebd84SRoberto Agostino Vitillo }
802bdfebd84SRoberto Agostino Vitillo 
803*95485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
80426d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
80526d33022SJiri Olsa {
80626d33022SJiri Olsa 	char *endptr;
80726d33022SJiri Olsa 	unsigned long size;
80826d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
80926d33022SJiri Olsa 
81026d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
81126d33022SJiri Olsa 
81226d33022SJiri Olsa 	do {
81326d33022SJiri Olsa 		if (*endptr)
81426d33022SJiri Olsa 			break;
81526d33022SJiri Olsa 
81626d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
81726d33022SJiri Olsa 		if (!size || size > max_size)
81826d33022SJiri Olsa 			break;
81926d33022SJiri Olsa 
82026d33022SJiri Olsa 		*_size = size;
82126d33022SJiri Olsa 		return 0;
82226d33022SJiri Olsa 
82326d33022SJiri Olsa 	} while (0);
82426d33022SJiri Olsa 
82526d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
82626d33022SJiri Olsa 	       max_size, str);
82726d33022SJiri Olsa 	return -1;
82826d33022SJiri Olsa }
829*95485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
83026d33022SJiri Olsa 
83126d33022SJiri Olsa static int
8321d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
83326d33022SJiri Olsa 		    int unset)
83426d33022SJiri Olsa {
83526d33022SJiri Olsa 	struct perf_record *rec = (struct perf_record *)opt->value;
83626d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
83726d33022SJiri Olsa 	char *buf;
83826d33022SJiri Olsa 	int ret = -1;
83926d33022SJiri Olsa 
84026d33022SJiri Olsa 	/* --no-call-graph */
84126d33022SJiri Olsa 	if (unset)
84226d33022SJiri Olsa 		return 0;
84326d33022SJiri Olsa 
84426d33022SJiri Olsa 	/* We specified default option if none is provided. */
84526d33022SJiri Olsa 	BUG_ON(!arg);
84626d33022SJiri Olsa 
84726d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
84826d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
84926d33022SJiri Olsa 	if (!buf)
85026d33022SJiri Olsa 		return -ENOMEM;
85126d33022SJiri Olsa 
85226d33022SJiri Olsa 	strcpy(buf, arg);
85326d33022SJiri Olsa 
85426d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
85526d33022SJiri Olsa 	name = tok ? : (char *)buf;
85626d33022SJiri Olsa 
85726d33022SJiri Olsa 	do {
85826d33022SJiri Olsa 		/* Framepointer style */
85926d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
86026d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
86126d33022SJiri Olsa 				rec->opts.call_graph = CALLCHAIN_FP;
86226d33022SJiri Olsa 				ret = 0;
86326d33022SJiri Olsa 			} else
86426d33022SJiri Olsa 				pr_err("callchain: No more arguments "
86526d33022SJiri Olsa 				       "needed for -g fp\n");
86626d33022SJiri Olsa 			break;
86726d33022SJiri Olsa 
868*95485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
86926d33022SJiri Olsa 		/* Dwarf style */
87026d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
87126d33022SJiri Olsa 			ret = 0;
87226d33022SJiri Olsa 			rec->opts.call_graph = CALLCHAIN_DWARF;
87326d33022SJiri Olsa 			rec->opts.stack_dump_size = default_stack_dump_size;
87426d33022SJiri Olsa 
87526d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
87626d33022SJiri Olsa 			if (tok) {
87726d33022SJiri Olsa 				unsigned long size = 0;
87826d33022SJiri Olsa 
87926d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
88026d33022SJiri Olsa 				rec->opts.stack_dump_size = size;
88126d33022SJiri Olsa 			}
88226d33022SJiri Olsa 
88326d33022SJiri Olsa 			if (!ret)
88426d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
88526d33022SJiri Olsa 					 rec->opts.stack_dump_size);
886*95485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
88726d33022SJiri Olsa 		} else {
88826d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
88926d33022SJiri Olsa 			       "value: %s\n", arg);
89026d33022SJiri Olsa 			break;
89126d33022SJiri Olsa 		}
89226d33022SJiri Olsa 
89326d33022SJiri Olsa 	} while (0);
89426d33022SJiri Olsa 
89526d33022SJiri Olsa 	free(buf);
89626d33022SJiri Olsa 
89726d33022SJiri Olsa 	if (!ret)
89826d33022SJiri Olsa 		pr_debug("callchain: type %d\n", rec->opts.call_graph);
89926d33022SJiri Olsa 
90026d33022SJiri Olsa 	return ret;
90126d33022SJiri Olsa }
90226d33022SJiri Olsa 
90386470930SIngo Molnar static const char * const record_usage[] = {
90486470930SIngo Molnar 	"perf record [<options>] [<command>]",
90586470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
90686470930SIngo Molnar 	NULL
90786470930SIngo Molnar };
90886470930SIngo Molnar 
909d20deb64SArnaldo Carvalho de Melo /*
910d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
911d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
912d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
913d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
914d20deb64SArnaldo Carvalho de Melo  *
915d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
916d20deb64SArnaldo Carvalho de Melo  *
917d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
918d20deb64SArnaldo Carvalho de Melo  */
919d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
920d20deb64SArnaldo Carvalho de Melo 	.opts = {
921d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
922d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
923d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
924447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
925d1cb9fceSNamhyung Kim 		.target		     = {
926d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
927d1cb9fceSNamhyung Kim 		},
928d20deb64SArnaldo Carvalho de Melo 	},
929d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
930d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
931d20deb64SArnaldo Carvalho de Melo };
9327865e817SFrederic Weisbecker 
933d20deb64SArnaldo Carvalho de Melo /*
934d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
935d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
936d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
937d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
938d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
939d20deb64SArnaldo Carvalho de Melo  */
940bca647aaSTom Zanussi const struct option record_options[] = {
941d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
94286470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
943f120f9d5SJiri Olsa 		     parse_events_option),
944d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
945c171b552SLi Zefan 		     "event filter", parse_filter),
946bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
947d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
948bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
949d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
950d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
95186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
952d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
953acac03faSKirill Smelkov 		    "collect data without buffering"),
954d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
955daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
956bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
95786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
958d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
95986470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
960bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
961c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
962d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
9637865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
964d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
965d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
96686470930SIngo Molnar 		    "output file name"),
967d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
9682e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
969d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
970d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
97101c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
972d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
97343bece79SLin Ming 		    "put the counters into a counter group"),
97426d33022SJiri Olsa 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
97526d33022SJiri Olsa 			     callchain_help, &parse_callchain_opt,
97626d33022SJiri Olsa 			     "fp"),
977c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
9783da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
979b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
980d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
981649c48a9SPeter Zijlstra 		    "per thread counts"),
982d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
9834bba828dSAnton Blanchard 		    "Sample addresses"),
984d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
9853e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
986d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
987649c48a9SPeter Zijlstra 		    "don't sample"),
988d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
989a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
990d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
991baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
992d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
993023695d9SStephane Eranian 		     "monitor event in cgroup name only",
994023695d9SStephane Eranian 		     parse_cgroups),
995bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
996bea03405SNamhyung Kim 		   "user to profile"),
997a5aabdacSStephane Eranian 
998a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
999a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1000a5aabdacSStephane Eranian 		     parse_branch_stack),
1001a5aabdacSStephane Eranian 
1002a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1003a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1004bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
100586470930SIngo Molnar 	OPT_END()
100686470930SIngo Molnar };
100786470930SIngo Molnar 
10081d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
100986470930SIngo Molnar {
101069aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
101169aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
1012d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
1013d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
101416ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
101586470930SIngo Molnar 
10167e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
1017361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
1018361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1019361c99a6SArnaldo Carvalho de Melo 
1020d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
1021d20deb64SArnaldo Carvalho de Melo 
1022bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1023a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1024d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
1025bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
102686470930SIngo Molnar 
1027d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
10283780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
10297865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
1030bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
1031d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
1032d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
10337865e817SFrederic Weisbecker 	} else {
1034d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
10357865e817SFrederic Weisbecker 	}
10367865e817SFrederic Weisbecker 
1037bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
10383780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
1039023695d9SStephane Eranian 			  " system-wide mode\n");
1040023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
1041023695d9SStephane Eranian 	}
1042023695d9SStephane Eranian 
1043655000e7SArnaldo Carvalho de Melo 	symbol__init();
1044baa2f6ceSArnaldo Carvalho de Melo 
1045ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1046646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1047646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1048ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1049646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1050646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1051646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1052646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1053646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1054ec80fde7SArnaldo Carvalho de Melo 
1055d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1056a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1057655000e7SArnaldo Carvalho de Melo 
1058361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
1059361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
106069aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
106169aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1062bbd36e5eSPeter Zijlstra 	}
106386470930SIngo Molnar 
106416ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
106516ad2ffbSNamhyung Kim 	if (err) {
106616ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
106716ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
106816ad2ffbSNamhyung Kim 	}
10694bd0f2d2SNamhyung Kim 
107016ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
107116ad2ffbSNamhyung Kim 	if (err) {
107216ad2ffbSNamhyung Kim 		int saved_errno = errno;
107316ad2ffbSNamhyung Kim 
107416ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
10753780f488SNamhyung Kim 		ui__error("%s", errbuf);
107616ad2ffbSNamhyung Kim 
107716ad2ffbSNamhyung Kim 		err = -saved_errno;
10780d37aa34SArnaldo Carvalho de Melo 		goto out_free_fd;
107916ad2ffbSNamhyung Kim 	}
10800d37aa34SArnaldo Carvalho de Melo 
108116ad2ffbSNamhyung Kim 	err = -ENOMEM;
1082b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1083dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
108469aad6f1SArnaldo Carvalho de Melo 
1085361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
10867289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1087ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1088d6d901c2SZhang, Yanmin 	}
10895c581041SArnaldo Carvalho de Melo 
1090d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1091d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1092d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1093d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1094f9212819SFrederic Weisbecker 
10957e4ff9e3SMike Galbraith 	/*
10967e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
10977e4ff9e3SMike Galbraith 	 */
1098d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1099d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1100d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1101d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
11027e4ff9e3SMike Galbraith 	} else {
11033780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
110439d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
11055c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
11067e4ff9e3SMike Galbraith 	}
11077e4ff9e3SMike Galbraith 
1108d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
110939d17dacSArnaldo Carvalho de Melo out_free_fd:
11107e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1111d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1112d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
111339d17dacSArnaldo Carvalho de Melo 	return err;
111486470930SIngo Molnar }
1115