xref: /openbmc/linux/tools/perf/builtin-record.c (revision 1d037ca1648b775277fc96401ec2aa233724906c)
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 
3626d33022SJiri Olsa #ifdef NO_LIBUNWIND_SUPPORT
3726d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp]";
3826d33022SJiri Olsa #else
3926d33022SJiri Olsa static unsigned long default_stack_dump_size = 8192;
4026d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
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,
95*1d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
96*1d037ca1SIrina 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 
162*1d037ca1SIrina 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");
300d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
301dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
302bfd45118SSimon Kaempflein 
303bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
3048d3eca20SDavid Ahern 			if (attr->type == PERF_TYPE_HARDWARE &&
3058d3eca20SDavid Ahern 			    err == EOPNOTSUPP) {
3068d3eca20SDavid Ahern 				pr_err("No hardware sampling interrupt available."
307d6d901c2SZhang, Yanmin 				       " No APIC? If so then you can boot the kernel"
308d6d901c2SZhang, Yanmin 				       " with the \"lapic\" boot parameter to"
309d6d901c2SZhang, Yanmin 				       " force-enable it.\n");
3108d3eca20SDavid Ahern 				rc = -err;
3118d3eca20SDavid Ahern 				goto out;
3128d3eca20SDavid Ahern 			}
313bfd45118SSimon Kaempflein #endif
314bfd45118SSimon Kaempflein 
3158d3eca20SDavid Ahern 			pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3168d3eca20SDavid Ahern 			rc = -err;
3178d3eca20SDavid Ahern 			goto out;
3187c6a1c65SPeter Zijlstra 		}
3197c6a1c65SPeter Zijlstra 	}
3207c6a1c65SPeter Zijlstra 
3210a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
3220a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3230a102479SFrederic Weisbecker 			strerror(errno));
3248d3eca20SDavid Ahern 		rc = -1;
3258d3eca20SDavid Ahern 		goto out;
3260a102479SFrederic Weisbecker 	}
3270a102479SFrederic Weisbecker 
32818e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
3298d3eca20SDavid Ahern 		if (errno == EPERM) {
3308d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
33118e60939SNelson Elhage 			       "Consider increasing "
33218e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
33318e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
33418e60939SNelson Elhage 			       "(current value: %d)\n", opts->mmap_pages);
3358d3eca20SDavid Ahern 			rc = -errno;
3368d3eca20SDavid Ahern 		} else if (!is_power_of_2(opts->mmap_pages)) {
3378d3eca20SDavid Ahern 			pr_err("--mmap_pages/-m value must be a power of two.");
3388d3eca20SDavid Ahern 			rc = -EINVAL;
3398d3eca20SDavid Ahern 		} else {
3408d3eca20SDavid Ahern 			pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
3418d3eca20SDavid Ahern 			rc = -errno;
3428d3eca20SDavid Ahern 		}
3438d3eca20SDavid Ahern 		goto out;
34418e60939SNelson Elhage 	}
3450a27d7f9SArnaldo Carvalho de Melo 
346d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
347a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
348a91e5431SArnaldo Carvalho de Melo 	else {
349a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
350a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
3518d3eca20SDavid Ahern 			rc = -1;
3528d3eca20SDavid Ahern 			goto out;
353dd7927f4SArnaldo Carvalho de Melo 		}
35486470930SIngo Molnar  	}
35586470930SIngo Molnar 
3567b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3578d3eca20SDavid Ahern out:
3588d3eca20SDavid Ahern 	return rc;
359a91e5431SArnaldo Carvalho de Melo }
360a91e5431SArnaldo Carvalho de Melo 
361d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
3626122e4e4SArnaldo Carvalho de Melo {
363d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
3646122e4e4SArnaldo Carvalho de Melo 
3659f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3669f591fd7SArnaldo Carvalho de Melo 		return 0;
3679f591fd7SArnaldo Carvalho de Melo 
368d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
369d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
370d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
3716122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3726122e4e4SArnaldo Carvalho de Melo }
3736122e4e4SArnaldo Carvalho de Melo 
3748d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg)
375f5970550SPeter Zijlstra {
376d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
377f5970550SPeter Zijlstra 
3788d3eca20SDavid Ahern 	if (status != 0)
3798d3eca20SDavid Ahern 		return;
3808d3eca20SDavid Ahern 
381d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
382d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
383d20deb64SArnaldo Carvalho de Melo 
384d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
385d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
386d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
387d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
388d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
389d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
390d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
391c7929e47STom Zanussi 	}
392f5970550SPeter Zijlstra }
393f5970550SPeter Zijlstra 
3948115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
395a1645ce1SZhang, Yanmin {
396a1645ce1SZhang, Yanmin 	int err;
39745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
398a1645ce1SZhang, Yanmin 
39923346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
400a1645ce1SZhang, Yanmin 		return;
401a1645ce1SZhang, Yanmin 
402a1645ce1SZhang, Yanmin 	/*
403a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
404a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
405a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
406a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
407a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
408a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
409a1645ce1SZhang, Yanmin 	 */
41045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
411743eb868SArnaldo Carvalho de Melo 					     machine);
412a1645ce1SZhang, Yanmin 	if (err < 0)
413a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
415a1645ce1SZhang, Yanmin 
416a1645ce1SZhang, Yanmin 	/*
417a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
418a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
419a1645ce1SZhang, Yanmin 	 */
42045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
421743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
422a1645ce1SZhang, Yanmin 	if (err < 0)
42345694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
424743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
425a1645ce1SZhang, Yanmin 	if (err < 0)
426a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
42723346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
428a1645ce1SZhang, Yanmin }
429a1645ce1SZhang, Yanmin 
43098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
43198402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
43298402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
43398402807SFrederic Weisbecker };
43498402807SFrederic Weisbecker 
4358d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec)
43698402807SFrederic Weisbecker {
4370e2e63ddSPeter Zijlstra 	int i;
4388d3eca20SDavid Ahern 	int rc = 0;
43998402807SFrederic Weisbecker 
440d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
4418d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
4428d3eca20SDavid Ahern 			if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
4438d3eca20SDavid Ahern 				rc = -1;
4448d3eca20SDavid Ahern 				goto out;
4458d3eca20SDavid Ahern 			}
4468d3eca20SDavid Ahern 		}
44798402807SFrederic Weisbecker 	}
44898402807SFrederic Weisbecker 
4492eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
4508d3eca20SDavid Ahern 		rc = write_output(rec, &finished_round_event,
4518d3eca20SDavid Ahern 				  sizeof(finished_round_event));
4528d3eca20SDavid Ahern 
4538d3eca20SDavid Ahern out:
4548d3eca20SDavid Ahern 	return rc;
45598402807SFrederic Weisbecker }
45698402807SFrederic Weisbecker 
457d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
45886470930SIngo Molnar {
45986470930SIngo Molnar 	struct stat st;
46086470930SIngo Molnar 	int flags;
461781ba9d2SRobert Richter 	int err, output, feat;
4628b412664SPeter Zijlstra 	unsigned long waking = 0;
46346be604bSZhang, Yanmin 	const bool forks = argc > 0;
46423346f21SArnaldo Carvalho de Melo 	struct machine *machine;
46545694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
466d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
467d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
468d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
469d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
47086470930SIngo Molnar 
471d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
47233e49ea7SAndi Kleen 
473d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
47486470930SIngo Molnar 
475d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
476f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
477f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
47818483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
479f5970550SPeter Zijlstra 
480d7065adbSFranck Bui-Huu 	if (!output_name) {
481d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
482d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
483d7065adbSFranck Bui-Huu 		else
484d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
485d7065adbSFranck Bui-Huu 	}
486d7065adbSFranck Bui-Huu 	if (output_name) {
487529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
488d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
489529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
490d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
491b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
492b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
493b38d3464SArnaldo Carvalho de Melo 					 output_name);
494b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
495b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
496b38d3464SArnaldo Carvalho de Melo 			}
497d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
498d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
499266e0e21SPierre Habouzit 		}
500d7065adbSFranck Bui-Huu 	}
50186470930SIngo Molnar 
502f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
503d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
504d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
50586470930SIngo Molnar 	else
50686470930SIngo Molnar 		flags |= O_TRUNC;
50786470930SIngo Molnar 
508d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
509529870e3STom Zanussi 		output = STDOUT_FILENO;
510529870e3STom Zanussi 	else
51186470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
51286470930SIngo Molnar 	if (output < 0) {
51386470930SIngo Molnar 		perror("failed to create output file");
5148d3eca20SDavid Ahern 		return -1;
51586470930SIngo Molnar 	}
51686470930SIngo Molnar 
517d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
518d20deb64SArnaldo Carvalho de Melo 
5197865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
520d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
52194c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
522a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
523a9a70bbcSArnaldo Carvalho de Melo 		return -1;
524a9a70bbcSArnaldo Carvalho de Melo 	}
525a9a70bbcSArnaldo Carvalho de Melo 
526d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
527d20deb64SArnaldo Carvalho de Melo 
528781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
529781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
530781ba9d2SRobert Richter 
531781ba9d2SRobert Richter 	if (rec->no_buildid)
532781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
533781ba9d2SRobert Richter 
534781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
5352eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
536baa2f6ceSArnaldo Carvalho de Melo 
537330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
538330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
539330aa675SStephane Eranian 
540d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
541a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5424dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
54339d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5444dc0a04bSArnaldo Carvalho de Melo 	}
5454dc0a04bSArnaldo Carvalho de Melo 
546d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
547d20deb64SArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
54835b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
54935b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
55035b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
551856e9660SPeter Zijlstra 		}
552856e9660SPeter Zijlstra 	}
553856e9660SPeter Zijlstra 
5548d3eca20SDavid Ahern 	if (perf_record__open(rec) != 0) {
5558d3eca20SDavid Ahern 		err = -1;
5568d3eca20SDavid Ahern 		goto out_delete_session;
5578d3eca20SDavid Ahern 	}
55886470930SIngo Molnar 
559712a4b60SArnaldo Carvalho de Melo 	/*
560d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
561712a4b60SArnaldo Carvalho de Melo 	 */
562d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
563712a4b60SArnaldo Carvalho de Melo 
564d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
565529870e3STom Zanussi 		err = perf_header__write_pipe(output);
566529870e3STom Zanussi 		if (err < 0)
5678d3eca20SDavid Ahern 			goto out_delete_session;
568d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
569a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
570361c99a6SArnaldo Carvalho de Melo 						 output, false);
571d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
5728d3eca20SDavid Ahern 			goto out_delete_session;
573d5eed904SArnaldo Carvalho de Melo 	}
5747c6a1c65SPeter Zijlstra 
575d3665498SDavid Ahern 	if (!rec->no_buildid
576e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
577d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
578e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
5798d3eca20SDavid Ahern 		err = -1;
5808d3eca20SDavid Ahern 		goto out_delete_session;
581e20960c0SRobert Richter 	}
582e20960c0SRobert Richter 
583d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
5846122e4e4SArnaldo Carvalho de Melo 
585743eb868SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
586743eb868SArnaldo Carvalho de Melo 	if (!machine) {
587743eb868SArnaldo Carvalho de Melo 		pr_err("Couldn't find native kernel information.\n");
5888d3eca20SDavid Ahern 		err = -1;
5898d3eca20SDavid Ahern 		goto out_delete_session;
590743eb868SArnaldo Carvalho de Melo 	}
591743eb868SArnaldo Carvalho de Melo 
592d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
59345694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
594a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
5952c46dbb5STom Zanussi 		if (err < 0) {
5962c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
5978d3eca20SDavid Ahern 			goto out_delete_session;
5982c46dbb5STom Zanussi 		}
599cd19a035STom Zanussi 
60045694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
601743eb868SArnaldo Carvalho de Melo 							 machine);
602cd19a035STom Zanussi 		if (err < 0) {
603cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
6048d3eca20SDavid Ahern 			goto out_delete_session;
605cd19a035STom Zanussi 		}
6069215545eSTom Zanussi 
607361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
60863e0c771STom Zanussi 			/*
60963e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
61063e0c771STom Zanussi 			 * there were no tracepoints so its not really
61163e0c771STom Zanussi 			 * an error, just that we don't need to
61263e0c771STom Zanussi 			 * synthesize anything.  We really have to
61363e0c771STom Zanussi 			 * return this more properly and also
61463e0c771STom Zanussi 			 * propagate errors that now are calling die()
61563e0c771STom Zanussi 			 */
61645694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
617743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
61863e0c771STom Zanussi 			if (err <= 0) {
61963e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
6208d3eca20SDavid Ahern 				goto out_delete_session;
62163e0c771STom Zanussi 			}
622d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
6232c46dbb5STom Zanussi 		}
62463e0c771STom Zanussi 	}
6252c46dbb5STom Zanussi 
62645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
627743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
62870162138SArnaldo Carvalho de Melo 	if (err < 0)
62945694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
630743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
631c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
632c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
633c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
634c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
63556b03f3cSArnaldo Carvalho de Melo 
63645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
637743eb868SArnaldo Carvalho de Melo 					     machine);
638c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
639c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
640c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
641c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
642c1a3a4b9SArnaldo Carvalho de Melo 
643a1645ce1SZhang, Yanmin 	if (perf_guest)
64445694aa7SArnaldo Carvalho de Melo 		perf_session__process_machines(session, tool,
6458115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
646b7cece76SArnaldo Carvalho de Melo 
647bea03405SNamhyung Kim 	if (!opts->target.system_wide)
6488d3eca20SDavid Ahern 		err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
6498115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
650743eb868SArnaldo Carvalho de Melo 						  machine);
651234fbbf5SArnaldo Carvalho de Melo 	else
6528d3eca20SDavid Ahern 		err = perf_event__synthesize_threads(tool, process_synthesized_event,
653743eb868SArnaldo Carvalho de Melo 					       machine);
6547c6a1c65SPeter Zijlstra 
6558d3eca20SDavid Ahern 	if (err != 0)
6568d3eca20SDavid Ahern 		goto out_delete_session;
6578d3eca20SDavid Ahern 
658d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
65986470930SIngo Molnar 		struct sched_param param;
66086470930SIngo Molnar 
661d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
66286470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6636beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
6648d3eca20SDavid Ahern 			err = -1;
6658d3eca20SDavid Ahern 			goto out_delete_session;
66686470930SIngo Molnar 		}
66786470930SIngo Molnar 	}
66886470930SIngo Molnar 
669764e16a3SDavid Ahern 	perf_evlist__enable(evsel_list);
670764e16a3SDavid Ahern 
671856e9660SPeter Zijlstra 	/*
672856e9660SPeter Zijlstra 	 * Let the child rip
673856e9660SPeter Zijlstra 	 */
674d4db3f16SArnaldo Carvalho de Melo 	if (forks)
67535b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
676856e9660SPeter Zijlstra 
677649c48a9SPeter Zijlstra 	for (;;) {
678d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
67986470930SIngo Molnar 
6808d3eca20SDavid Ahern 		if (perf_record__mmap_read_all(rec) < 0) {
6818d3eca20SDavid Ahern 			err = -1;
6828d3eca20SDavid Ahern 			goto out_delete_session;
6838d3eca20SDavid Ahern 		}
68486470930SIngo Molnar 
685d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
686649c48a9SPeter Zijlstra 			if (done)
687649c48a9SPeter Zijlstra 				break;
6885c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6898b412664SPeter Zijlstra 			waking++;
6908b412664SPeter Zijlstra 		}
6918b412664SPeter Zijlstra 
6924152ab37SArnaldo Carvalho de Melo 		if (done)
6934152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6948b412664SPeter Zijlstra 	}
6958b412664SPeter Zijlstra 
69618483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
697b44308f5SArnaldo Carvalho de Melo 		return 0;
698b44308f5SArnaldo Carvalho de Melo 
6998b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
70086470930SIngo Molnar 
70186470930SIngo Molnar 	/*
70286470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
70386470930SIngo Molnar 	 */
70486470930SIngo Molnar 	fprintf(stderr,
7059486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
706d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
70786470930SIngo Molnar 		output_name,
708d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
70986470930SIngo Molnar 
71086470930SIngo Molnar 	return 0;
71139d17dacSArnaldo Carvalho de Melo 
71239d17dacSArnaldo Carvalho de Melo out_delete_session:
71339d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
71439d17dacSArnaldo Carvalho de Melo 	return err;
71586470930SIngo Molnar }
71686470930SIngo Molnar 
717bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
718bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
719bdfebd84SRoberto Agostino Vitillo 
720bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
721bdfebd84SRoberto Agostino Vitillo 
722bdfebd84SRoberto Agostino Vitillo struct branch_mode {
723bdfebd84SRoberto Agostino Vitillo 	const char *name;
724bdfebd84SRoberto Agostino Vitillo 	int mode;
725bdfebd84SRoberto Agostino Vitillo };
726bdfebd84SRoberto Agostino Vitillo 
727bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
728bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
729bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
730bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
731bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
732bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
733bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
734bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
735bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
736bdfebd84SRoberto Agostino Vitillo };
737bdfebd84SRoberto Agostino Vitillo 
738bdfebd84SRoberto Agostino Vitillo static int
739a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
740bdfebd84SRoberto Agostino Vitillo {
741bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
742bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
743bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
744bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
745bdfebd84SRoberto Agostino Vitillo 
746bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
747bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
748a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
749bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
750bdfebd84SRoberto Agostino Vitillo 
751a5aabdacSStephane Eranian 	if (unset)
752a5aabdacSStephane Eranian 		return 0;
753bdfebd84SRoberto Agostino Vitillo 
754a5aabdacSStephane Eranian 	/*
755a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
756a5aabdacSStephane Eranian 	 */
757a5aabdacSStephane Eranian 	if (*mode)
758a5aabdacSStephane Eranian 		return -1;
759a5aabdacSStephane Eranian 
760a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
761a5aabdacSStephane Eranian 	if (str) {
762bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
763bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
764bdfebd84SRoberto Agostino Vitillo 		if (!s)
765bdfebd84SRoberto Agostino Vitillo 			return -1;
766bdfebd84SRoberto Agostino Vitillo 
767bdfebd84SRoberto Agostino Vitillo 		for (;;) {
768bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
769bdfebd84SRoberto Agostino Vitillo 			if (p)
770bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
771bdfebd84SRoberto Agostino Vitillo 
772bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
773bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
774bdfebd84SRoberto Agostino Vitillo 					break;
775bdfebd84SRoberto Agostino Vitillo 			}
776a5aabdacSStephane Eranian 			if (!br->name) {
777a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
778a5aabdacSStephane Eranian 					    " check man page\n", s);
779bdfebd84SRoberto Agostino Vitillo 				goto error;
780a5aabdacSStephane Eranian 			}
781bdfebd84SRoberto Agostino Vitillo 
782bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
783bdfebd84SRoberto Agostino Vitillo 
784bdfebd84SRoberto Agostino Vitillo 			if (!p)
785bdfebd84SRoberto Agostino Vitillo 				break;
786bdfebd84SRoberto Agostino Vitillo 
787bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
788bdfebd84SRoberto Agostino Vitillo 		}
789a5aabdacSStephane Eranian 	}
790bdfebd84SRoberto Agostino Vitillo 	ret = 0;
791bdfebd84SRoberto Agostino Vitillo 
792a5aabdacSStephane Eranian 	/* default to any branch */
793bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
794a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
795bdfebd84SRoberto Agostino Vitillo 	}
796bdfebd84SRoberto Agostino Vitillo error:
797bdfebd84SRoberto Agostino Vitillo 	free(os);
798bdfebd84SRoberto Agostino Vitillo 	return ret;
799bdfebd84SRoberto Agostino Vitillo }
800bdfebd84SRoberto Agostino Vitillo 
80126d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT
80226d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
80326d33022SJiri Olsa {
80426d33022SJiri Olsa 	char *endptr;
80526d33022SJiri Olsa 	unsigned long size;
80626d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
80726d33022SJiri Olsa 
80826d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
80926d33022SJiri Olsa 
81026d33022SJiri Olsa 	do {
81126d33022SJiri Olsa 		if (*endptr)
81226d33022SJiri Olsa 			break;
81326d33022SJiri Olsa 
81426d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
81526d33022SJiri Olsa 		if (!size || size > max_size)
81626d33022SJiri Olsa 			break;
81726d33022SJiri Olsa 
81826d33022SJiri Olsa 		*_size = size;
81926d33022SJiri Olsa 		return 0;
82026d33022SJiri Olsa 
82126d33022SJiri Olsa 	} while (0);
82226d33022SJiri Olsa 
82326d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
82426d33022SJiri Olsa 	       max_size, str);
82526d33022SJiri Olsa 	return -1;
82626d33022SJiri Olsa }
82726d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */
82826d33022SJiri Olsa 
82926d33022SJiri Olsa static int
830*1d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
83126d33022SJiri Olsa 		    int unset)
83226d33022SJiri Olsa {
83326d33022SJiri Olsa 	struct perf_record *rec = (struct perf_record *)opt->value;
83426d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
83526d33022SJiri Olsa 	char *buf;
83626d33022SJiri Olsa 	int ret = -1;
83726d33022SJiri Olsa 
83826d33022SJiri Olsa 	/* --no-call-graph */
83926d33022SJiri Olsa 	if (unset)
84026d33022SJiri Olsa 		return 0;
84126d33022SJiri Olsa 
84226d33022SJiri Olsa 	/* We specified default option if none is provided. */
84326d33022SJiri Olsa 	BUG_ON(!arg);
84426d33022SJiri Olsa 
84526d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
84626d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
84726d33022SJiri Olsa 	if (!buf)
84826d33022SJiri Olsa 		return -ENOMEM;
84926d33022SJiri Olsa 
85026d33022SJiri Olsa 	strcpy(buf, arg);
85126d33022SJiri Olsa 
85226d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
85326d33022SJiri Olsa 	name = tok ? : (char *)buf;
85426d33022SJiri Olsa 
85526d33022SJiri Olsa 	do {
85626d33022SJiri Olsa 		/* Framepointer style */
85726d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
85826d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
85926d33022SJiri Olsa 				rec->opts.call_graph = CALLCHAIN_FP;
86026d33022SJiri Olsa 				ret = 0;
86126d33022SJiri Olsa 			} else
86226d33022SJiri Olsa 				pr_err("callchain: No more arguments "
86326d33022SJiri Olsa 				       "needed for -g fp\n");
86426d33022SJiri Olsa 			break;
86526d33022SJiri Olsa 
86626d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT
86726d33022SJiri Olsa 		/* Dwarf style */
86826d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
86926d33022SJiri Olsa 			ret = 0;
87026d33022SJiri Olsa 			rec->opts.call_graph = CALLCHAIN_DWARF;
87126d33022SJiri Olsa 			rec->opts.stack_dump_size = default_stack_dump_size;
87226d33022SJiri Olsa 
87326d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
87426d33022SJiri Olsa 			if (tok) {
87526d33022SJiri Olsa 				unsigned long size = 0;
87626d33022SJiri Olsa 
87726d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
87826d33022SJiri Olsa 				rec->opts.stack_dump_size = size;
87926d33022SJiri Olsa 			}
88026d33022SJiri Olsa 
88126d33022SJiri Olsa 			if (!ret)
88226d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
88326d33022SJiri Olsa 					 rec->opts.stack_dump_size);
88426d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */
88526d33022SJiri Olsa 		} else {
88626d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
88726d33022SJiri Olsa 			       "value: %s\n", arg);
88826d33022SJiri Olsa 			break;
88926d33022SJiri Olsa 		}
89026d33022SJiri Olsa 
89126d33022SJiri Olsa 	} while (0);
89226d33022SJiri Olsa 
89326d33022SJiri Olsa 	free(buf);
89426d33022SJiri Olsa 
89526d33022SJiri Olsa 	if (!ret)
89626d33022SJiri Olsa 		pr_debug("callchain: type %d\n", rec->opts.call_graph);
89726d33022SJiri Olsa 
89826d33022SJiri Olsa 	return ret;
89926d33022SJiri Olsa }
90026d33022SJiri Olsa 
90186470930SIngo Molnar static const char * const record_usage[] = {
90286470930SIngo Molnar 	"perf record [<options>] [<command>]",
90386470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
90486470930SIngo Molnar 	NULL
90586470930SIngo Molnar };
90686470930SIngo Molnar 
907d20deb64SArnaldo Carvalho de Melo /*
908d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
909d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
910d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
911d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
912d20deb64SArnaldo Carvalho de Melo  *
913d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
914d20deb64SArnaldo Carvalho de Melo  *
915d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
916d20deb64SArnaldo Carvalho de Melo  */
917d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
918d20deb64SArnaldo Carvalho de Melo 	.opts = {
919d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
920d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
921d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
922447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
923d1cb9fceSNamhyung Kim 		.target		     = {
924d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
925d1cb9fceSNamhyung Kim 		},
926d20deb64SArnaldo Carvalho de Melo 	},
927d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
928d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
929d20deb64SArnaldo Carvalho de Melo };
9307865e817SFrederic Weisbecker 
931d20deb64SArnaldo Carvalho de Melo /*
932d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
933d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
934d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
935d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
936d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
937d20deb64SArnaldo Carvalho de Melo  */
938bca647aaSTom Zanussi const struct option record_options[] = {
939d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
94086470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
941f120f9d5SJiri Olsa 		     parse_events_option),
942d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
943c171b552SLi Zefan 		     "event filter", parse_filter),
944bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
945d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
946bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
947d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
948d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
94986470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
950d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
951acac03faSKirill Smelkov 		    "collect data without buffering"),
952d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
953daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
954bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
95586470930SIngo Molnar 			    "system-wide collection from all CPUs"),
956d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
95786470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
958bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
959c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
960d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
9617865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
962d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
963d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
96486470930SIngo Molnar 		    "output file name"),
965d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
9662e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
967d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
968d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
96901c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
970d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
97143bece79SLin Ming 		    "put the counters into a counter group"),
97226d33022SJiri Olsa 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
97326d33022SJiri Olsa 			     callchain_help, &parse_callchain_opt,
97426d33022SJiri Olsa 			     "fp"),
975c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
9763da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
977b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
978d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
979649c48a9SPeter Zijlstra 		    "per thread counts"),
980d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
9814bba828dSAnton Blanchard 		    "Sample addresses"),
982d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
9833e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
984d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
985649c48a9SPeter Zijlstra 		    "don't sample"),
986d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
987a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
988d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
989baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
990d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
991023695d9SStephane Eranian 		     "monitor event in cgroup name only",
992023695d9SStephane Eranian 		     parse_cgroups),
993bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
994bea03405SNamhyung Kim 		   "user to profile"),
995a5aabdacSStephane Eranian 
996a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
997a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
998a5aabdacSStephane Eranian 		     parse_branch_stack),
999a5aabdacSStephane Eranian 
1000a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1001a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1002bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
100386470930SIngo Molnar 	OPT_END()
100486470930SIngo Molnar };
100586470930SIngo Molnar 
1006*1d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
100786470930SIngo Molnar {
100869aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
100969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
1010d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
1011d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
101216ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
101386470930SIngo Molnar 
10147e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
1015361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
1016361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1017361c99a6SArnaldo Carvalho de Melo 
1018d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
1019d20deb64SArnaldo Carvalho de Melo 
1020bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1021a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1022d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
1023bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
102486470930SIngo Molnar 
1025d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
10263780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
10277865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
1028bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
1029d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
1030d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
10317865e817SFrederic Weisbecker 	} else {
1032d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
10337865e817SFrederic Weisbecker 	}
10347865e817SFrederic Weisbecker 
1035bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
10363780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
1037023695d9SStephane Eranian 			  " system-wide mode\n");
1038023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
1039023695d9SStephane Eranian 	}
1040023695d9SStephane Eranian 
1041655000e7SArnaldo Carvalho de Melo 	symbol__init();
1042baa2f6ceSArnaldo Carvalho de Melo 
1043ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1044646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1045646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1046ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1047646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1048646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1049646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1050646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1051646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1052ec80fde7SArnaldo Carvalho de Melo 
1053d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1054a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1055655000e7SArnaldo Carvalho de Melo 
1056361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
1057361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
105869aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
105969aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1060bbd36e5eSPeter Zijlstra 	}
106186470930SIngo Molnar 
106216ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
106316ad2ffbSNamhyung Kim 	if (err) {
106416ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
106516ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
106616ad2ffbSNamhyung Kim 	}
10674bd0f2d2SNamhyung Kim 
106816ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
106916ad2ffbSNamhyung Kim 	if (err) {
107016ad2ffbSNamhyung Kim 		int saved_errno = errno;
107116ad2ffbSNamhyung Kim 
107216ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
10733780f488SNamhyung Kim 		ui__error("%s", errbuf);
107416ad2ffbSNamhyung Kim 
107516ad2ffbSNamhyung Kim 		err = -saved_errno;
10760d37aa34SArnaldo Carvalho de Melo 		goto out_free_fd;
107716ad2ffbSNamhyung Kim 	}
10780d37aa34SArnaldo Carvalho de Melo 
107916ad2ffbSNamhyung Kim 	err = -ENOMEM;
1080b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1081dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
108269aad6f1SArnaldo Carvalho de Melo 
1083361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
10847289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1085ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1086d6d901c2SZhang, Yanmin 	}
10875c581041SArnaldo Carvalho de Melo 
1088d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1089d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1090d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1091d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1092f9212819SFrederic Weisbecker 
10937e4ff9e3SMike Galbraith 	/*
10947e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
10957e4ff9e3SMike Galbraith 	 */
1096d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1097d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1098d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1099d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
11007e4ff9e3SMike Galbraith 	} else {
11013780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
110239d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
11035c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
11047e4ff9e3SMike Galbraith 	}
11057e4ff9e3SMike Galbraith 
1106d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
110739d17dacSArnaldo Carvalho de Melo out_free_fd:
11087e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1109d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1110d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
111139d17dacSArnaldo Carvalho de Melo 	return err;
111286470930SIngo Molnar }
1113