xref: /openbmc/linux/tools/perf/builtin-record.c (revision 0c21f736e0a37c50f66ab248d2a52f711b28a4e4)
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 
74d20deb64SArnaldo Carvalho de Melo static void 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 
79f5970550SPeter Zijlstra 		if (ret < 0)
80f5970550SPeter Zijlstra 			die("failed to write");
81f5970550SPeter Zijlstra 
82f5970550SPeter Zijlstra 		size -= ret;
83f5970550SPeter Zijlstra 		buf += ret;
84f5970550SPeter Zijlstra 
85d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written += ret;
86f5970550SPeter Zijlstra 	}
87f5970550SPeter Zijlstra }
88f5970550SPeter Zijlstra 
8945694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
90d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
918d50e5b4SArnaldo Carvalho de Melo 				     struct perf_sample *sample __used,
92743eb868SArnaldo Carvalho de Melo 				     struct machine *machine __used)
93234fbbf5SArnaldo Carvalho de Melo {
9445694aa7SArnaldo Carvalho de Melo 	struct perf_record *rec = container_of(tool, struct perf_record, tool);
95d20deb64SArnaldo Carvalho de Melo 	write_output(rec, event, event->header.size);
96234fbbf5SArnaldo Carvalho de Melo 	return 0;
97234fbbf5SArnaldo Carvalho de Melo }
98234fbbf5SArnaldo Carvalho de Melo 
99d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read(struct perf_record *rec,
100d20deb64SArnaldo Carvalho de Melo 				   struct perf_mmap *md)
10186470930SIngo Molnar {
102744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
10386470930SIngo Molnar 	unsigned int old = md->prev;
104d20deb64SArnaldo Carvalho de Melo 	unsigned char *data = md->base + rec->page_size;
10586470930SIngo Molnar 	unsigned long size;
10686470930SIngo Molnar 	void *buf;
10786470930SIngo Molnar 
108dc82009aSArnaldo Carvalho de Melo 	if (old == head)
109dc82009aSArnaldo Carvalho de Melo 		return;
11086470930SIngo Molnar 
111d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
11286470930SIngo Molnar 
11386470930SIngo Molnar 	size = head - old;
11486470930SIngo Molnar 
11586470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
11686470930SIngo Molnar 		buf = &data[old & md->mask];
11786470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
11886470930SIngo Molnar 		old += size;
11986470930SIngo Molnar 
120d20deb64SArnaldo Carvalho de Melo 		write_output(rec, buf, size);
12186470930SIngo Molnar 	}
12286470930SIngo Molnar 
12386470930SIngo Molnar 	buf = &data[old & md->mask];
12486470930SIngo Molnar 	size = head - old;
12586470930SIngo Molnar 	old += size;
12686470930SIngo Molnar 
127d20deb64SArnaldo Carvalho de Melo 	write_output(rec, buf, size);
12886470930SIngo Molnar 
12986470930SIngo Molnar 	md->prev = old;
130115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
13186470930SIngo Molnar }
13286470930SIngo Molnar 
13386470930SIngo Molnar static volatile int done = 0;
134f7b7c26eSPeter Zijlstra static volatile int signr = -1;
13533e49ea7SAndi Kleen static volatile int child_finished = 0;
13686470930SIngo Molnar 
13786470930SIngo Molnar static void sig_handler(int sig)
13886470930SIngo Molnar {
13933e49ea7SAndi Kleen 	if (sig == SIGCHLD)
14033e49ea7SAndi Kleen 		child_finished = 1;
14133e49ea7SAndi Kleen 
14286470930SIngo Molnar 	done = 1;
143f7b7c26eSPeter Zijlstra 	signr = sig;
144f7b7c26eSPeter Zijlstra }
145f7b7c26eSPeter Zijlstra 
146d20deb64SArnaldo Carvalho de Melo static void perf_record__sig_exit(int exit_status __used, void *arg)
147f7b7c26eSPeter Zijlstra {
148d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
14933e49ea7SAndi Kleen 	int status;
15033e49ea7SAndi Kleen 
151d20deb64SArnaldo Carvalho de Melo 	if (rec->evlist->workload.pid > 0) {
15233e49ea7SAndi Kleen 		if (!child_finished)
153d20deb64SArnaldo Carvalho de Melo 			kill(rec->evlist->workload.pid, SIGTERM);
154933da83aSChris Wilson 
15533e49ea7SAndi Kleen 		wait(&status);
15633e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
157d20deb64SArnaldo Carvalho de Melo 			psignal(WTERMSIG(status), rec->progname);
15833e49ea7SAndi Kleen 	}
15933e49ea7SAndi Kleen 
16018483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
161f7b7c26eSPeter Zijlstra 		return;
162f7b7c26eSPeter Zijlstra 
163f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
164f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
16586470930SIngo Molnar }
16686470930SIngo Molnar 
167a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
168a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
169a91e5431SArnaldo Carvalho de Melo {
170a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
171a91e5431SArnaldo Carvalho de Melo 
172a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
173a91e5431SArnaldo Carvalho de Melo 		return false;
174a91e5431SArnaldo Carvalho de Melo 
175*0c21f736SArnaldo Carvalho de Melo 	pair = perf_evlist__first(other);
176a91e5431SArnaldo Carvalho de Melo 
177a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
178a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
179a91e5431SArnaldo Carvalho de Melo 			return false;
180*0c21f736SArnaldo Carvalho de Melo 		pair = perf_evsel__next(pair);
181a91e5431SArnaldo Carvalho de Melo 	}
182a91e5431SArnaldo Carvalho de Melo 
183a91e5431SArnaldo Carvalho de Melo 	return true;
184a91e5431SArnaldo Carvalho de Melo }
185a91e5431SArnaldo Carvalho de Melo 
186d20deb64SArnaldo Carvalho de Melo static void perf_record__open(struct perf_record *rec)
187dd7927f4SArnaldo Carvalho de Melo {
1886a4bb04cSJiri Olsa 	struct perf_evsel *pos;
189d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
190d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
191d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
192dd7927f4SArnaldo Carvalho de Melo 
193d20deb64SArnaldo Carvalho de Melo 	perf_evlist__config_attrs(evlist, opts);
1940f82ebc4SArnaldo Carvalho de Melo 
1956a4bb04cSJiri Olsa 	if (opts->group)
19663dab225SArnaldo Carvalho de Melo 		perf_evlist__set_leader(evlist);
1976a4bb04cSJiri Olsa 
198dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
199dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
200dd7927f4SArnaldo Carvalho de Melo 		/*
201dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
202dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
203dd7927f4SArnaldo Carvalho de Melo 		 *
204dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
205dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
206dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
207dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
208dd7927f4SArnaldo Carvalho de Melo 		 *
209dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
210dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
211dd7927f4SArnaldo Carvalho de Melo 		 */
212dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
213dd7927f4SArnaldo Carvalho de Melo 
2140c978128SArnaldo Carvalho de Melo fallback_missing_features:
2150c978128SArnaldo Carvalho de Melo 		if (opts->exclude_guest_missing)
2160c978128SArnaldo Carvalho de Melo 			attr->exclude_guest = attr->exclude_host = 0;
2179c90a61cSArnaldo Carvalho de Melo retry_sample_id:
218808e1226SArnaldo Carvalho de Melo 		attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
2193da297a6SIngo Molnar try_again:
2206a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
22186470930SIngo Molnar 			int err = errno;
22286470930SIngo Molnar 
223c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
224b8631e6eSArnaldo Carvalho de Melo 				ui__error_paranoid();
225c286c419SArnaldo Carvalho de Melo 				exit(EXIT_FAILURE);
226bea03405SNamhyung Kim 			} else if (err ==  ENODEV && opts->target.cpu_list) {
227d6d901c2SZhang, Yanmin 				die("No such device - did you specify"
228d6d901c2SZhang, Yanmin 					" an out-of-range profile CPU?\n");
2290c978128SArnaldo Carvalho de Melo 			} else if (err == EINVAL) {
2300c978128SArnaldo Carvalho de Melo 				if (!opts->exclude_guest_missing &&
2310c978128SArnaldo Carvalho de Melo 				    (attr->exclude_guest || attr->exclude_host)) {
2320c978128SArnaldo Carvalho de Melo 					pr_debug("Old kernel, cannot exclude "
2330c978128SArnaldo Carvalho de Melo 						 "guest or host samples.\n");
2340c978128SArnaldo Carvalho de Melo 					opts->exclude_guest_missing = true;
2350c978128SArnaldo Carvalho de Melo 					goto fallback_missing_features;
236808e1226SArnaldo Carvalho de Melo 				} else if (!opts->sample_id_all_missing) {
2379c90a61cSArnaldo Carvalho de Melo 					/*
2389c90a61cSArnaldo Carvalho de Melo 					 * Old kernel, no attr->sample_id_type_all field
2399c90a61cSArnaldo Carvalho de Melo 					 */
240808e1226SArnaldo Carvalho de Melo 					opts->sample_id_all_missing = true;
241d20deb64SArnaldo Carvalho de Melo 					if (!opts->sample_time && !opts->raw_samples && !time_needed)
242eac23d1cSIan Munsie 						attr->sample_type &= ~PERF_SAMPLE_TIME;
243eac23d1cSIan Munsie 
2449c90a61cSArnaldo Carvalho de Melo 					goto retry_sample_id;
245d6d901c2SZhang, Yanmin 				}
2460c978128SArnaldo Carvalho de Melo 			}
2473da297a6SIngo Molnar 
2483da297a6SIngo Molnar 			/*
2493da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2503da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
251028d455bSDavid Ahern 			 * is always available even if no PMU support.
252028d455bSDavid Ahern 			 *
253028d455bSDavid Ahern 			 * PPC returns ENXIO until 2.6.37 (behavior changed
254028d455bSDavid Ahern 			 * with commit b0a873e).
2553da297a6SIngo Molnar 			 */
256028d455bSDavid Ahern 			if ((err == ENOENT || err == ENXIO)
257028d455bSDavid Ahern 					&& attr->type == PERF_TYPE_HARDWARE
258f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
2593da297a6SIngo Molnar 
2603da297a6SIngo Molnar 				if (verbose)
261ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
262ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
2633da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
264f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
265d1cae34dSDavid Ahern 				if (pos->name) {
266d1cae34dSDavid Ahern 					free(pos->name);
267d1cae34dSDavid Ahern 					pos->name = NULL;
268d1cae34dSDavid Ahern 				}
2693da297a6SIngo Molnar 				goto try_again;
2703da297a6SIngo Molnar 			}
271ca6a4258SDavid Ahern 
272ca6a4258SDavid Ahern 			if (err == ENOENT) {
2733780f488SNamhyung Kim 				ui__error("The %s event is not supported.\n",
2747289f83cSArnaldo Carvalho de Melo 					  perf_evsel__name(pos));
275ca6a4258SDavid Ahern 				exit(EXIT_FAILURE);
276ca6a4258SDavid Ahern 			}
277ca6a4258SDavid Ahern 
27830c806a0SIngo Molnar 			printf("\n");
279d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
280dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
281bfd45118SSimon Kaempflein 
282bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
283bfd45118SSimon Kaempflein 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
284d6d901c2SZhang, Yanmin 				die("No hardware sampling interrupt available."
285d6d901c2SZhang, Yanmin 				    " No APIC? If so then you can boot the kernel"
286d6d901c2SZhang, Yanmin 				    " with the \"lapic\" boot parameter to"
287d6d901c2SZhang, Yanmin 				    " force-enable it.\n");
288bfd45118SSimon Kaempflein #endif
289bfd45118SSimon Kaempflein 
290cdd6c482SIngo Molnar 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
2917c6a1c65SPeter Zijlstra 		}
2927c6a1c65SPeter Zijlstra 	}
2937c6a1c65SPeter Zijlstra 
2940a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
2950a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
2960a102479SFrederic Weisbecker 			strerror(errno));
2970a102479SFrederic Weisbecker 		exit(-1);
2980a102479SFrederic Weisbecker 	}
2990a102479SFrederic Weisbecker 
30018e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
30118e60939SNelson Elhage 		if (errno == EPERM)
30218e60939SNelson Elhage 			die("Permission error mapping pages.\n"
30318e60939SNelson Elhage 			    "Consider increasing "
30418e60939SNelson Elhage 			    "/proc/sys/kernel/perf_event_mlock_kb,\n"
30518e60939SNelson Elhage 			    "or try again with a smaller value of -m/--mmap_pages.\n"
30618e60939SNelson Elhage 			    "(current value: %d)\n", opts->mmap_pages);
30741d0d933SNelson Elhage 		else if (!is_power_of_2(opts->mmap_pages))
30841d0d933SNelson Elhage 			die("--mmap_pages/-m value must be a power of two.");
30941d0d933SNelson Elhage 
3100a27d7f9SArnaldo Carvalho de Melo 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
31118e60939SNelson Elhage 	}
3120a27d7f9SArnaldo Carvalho de Melo 
313d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
314a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
315a91e5431SArnaldo Carvalho de Melo 	else {
316a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
317a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
318a91e5431SArnaldo Carvalho de Melo 			exit(-1);
319dd7927f4SArnaldo Carvalho de Melo 		}
32086470930SIngo Molnar  	}
32186470930SIngo Molnar 
3227b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
323a91e5431SArnaldo Carvalho de Melo }
324a91e5431SArnaldo Carvalho de Melo 
325d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
3266122e4e4SArnaldo Carvalho de Melo {
327d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
3286122e4e4SArnaldo Carvalho de Melo 
3299f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3309f591fd7SArnaldo Carvalho de Melo 		return 0;
3319f591fd7SArnaldo Carvalho de Melo 
332d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
333d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
334d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
3356122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3366122e4e4SArnaldo Carvalho de Melo }
3376122e4e4SArnaldo Carvalho de Melo 
338d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg)
339f5970550SPeter Zijlstra {
340d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
341f5970550SPeter Zijlstra 
342d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
343d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
344d20deb64SArnaldo Carvalho de Melo 
345d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
346d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
347d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
348d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
349d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
350d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
351d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
352c7929e47STom Zanussi 	}
353f5970550SPeter Zijlstra }
354f5970550SPeter Zijlstra 
3558115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
356a1645ce1SZhang, Yanmin {
357a1645ce1SZhang, Yanmin 	int err;
35845694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
359a1645ce1SZhang, Yanmin 
36023346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
361a1645ce1SZhang, Yanmin 		return;
362a1645ce1SZhang, Yanmin 
363a1645ce1SZhang, Yanmin 	/*
364a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
365a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
366a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
367a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
368a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
369a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
370a1645ce1SZhang, Yanmin 	 */
37145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
372743eb868SArnaldo Carvalho de Melo 					     machine);
373a1645ce1SZhang, Yanmin 	if (err < 0)
374a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
37523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
376a1645ce1SZhang, Yanmin 
377a1645ce1SZhang, Yanmin 	/*
378a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
379a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
380a1645ce1SZhang, Yanmin 	 */
38145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
382743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
383a1645ce1SZhang, Yanmin 	if (err < 0)
38445694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
385743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
386a1645ce1SZhang, Yanmin 	if (err < 0)
387a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
38823346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
389a1645ce1SZhang, Yanmin }
390a1645ce1SZhang, Yanmin 
39198402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
39298402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
39398402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
39498402807SFrederic Weisbecker };
39598402807SFrederic Weisbecker 
396d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec)
39798402807SFrederic Weisbecker {
3980e2e63ddSPeter Zijlstra 	int i;
39998402807SFrederic Weisbecker 
400d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
401d20deb64SArnaldo Carvalho de Melo 		if (rec->evlist->mmap[i].base)
402d20deb64SArnaldo Carvalho de Melo 			perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
40398402807SFrederic Weisbecker 	}
40498402807SFrederic Weisbecker 
4052eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
406d20deb64SArnaldo Carvalho de Melo 		write_output(rec, &finished_round_event, sizeof(finished_round_event));
40798402807SFrederic Weisbecker }
40898402807SFrederic Weisbecker 
409d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
41086470930SIngo Molnar {
41186470930SIngo Molnar 	struct stat st;
41286470930SIngo Molnar 	int flags;
413781ba9d2SRobert Richter 	int err, output, feat;
4148b412664SPeter Zijlstra 	unsigned long waking = 0;
41546be604bSZhang, Yanmin 	const bool forks = argc > 0;
41623346f21SArnaldo Carvalho de Melo 	struct machine *machine;
41745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
418d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
419d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
420d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
421d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
42286470930SIngo Molnar 
423d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
42433e49ea7SAndi Kleen 
425d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
42686470930SIngo Molnar 
427d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
428f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
429f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
43018483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
431f5970550SPeter Zijlstra 
432d7065adbSFranck Bui-Huu 	if (!output_name) {
433d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
434d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
435d7065adbSFranck Bui-Huu 		else
436d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
437d7065adbSFranck Bui-Huu 	}
438d7065adbSFranck Bui-Huu 	if (output_name) {
439529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
440d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
441529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
442d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
443b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
444b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
445b38d3464SArnaldo Carvalho de Melo 					 output_name);
446b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
447b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
448b38d3464SArnaldo Carvalho de Melo 			}
449d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
450d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
451266e0e21SPierre Habouzit 		}
452d7065adbSFranck Bui-Huu 	}
45386470930SIngo Molnar 
454f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
455d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
456d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
45786470930SIngo Molnar 	else
45886470930SIngo Molnar 		flags |= O_TRUNC;
45986470930SIngo Molnar 
460d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
461529870e3STom Zanussi 		output = STDOUT_FILENO;
462529870e3STom Zanussi 	else
46386470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
46486470930SIngo Molnar 	if (output < 0) {
46586470930SIngo Molnar 		perror("failed to create output file");
46686470930SIngo Molnar 		exit(-1);
46786470930SIngo Molnar 	}
46886470930SIngo Molnar 
469d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
470d20deb64SArnaldo Carvalho de Melo 
4717865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
472d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
47394c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
474a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
475a9a70bbcSArnaldo Carvalho de Melo 		return -1;
476a9a70bbcSArnaldo Carvalho de Melo 	}
477a9a70bbcSArnaldo Carvalho de Melo 
478d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
479d20deb64SArnaldo Carvalho de Melo 
480781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
481781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
482781ba9d2SRobert Richter 
483781ba9d2SRobert Richter 	if (rec->no_buildid)
484781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
485781ba9d2SRobert Richter 
486781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
4872eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
488baa2f6ceSArnaldo Carvalho de Melo 
489330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
490330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
491330aa675SStephane Eranian 
492d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
493a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
4944dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
49539d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
4964dc0a04bSArnaldo Carvalho de Melo 	}
4974dc0a04bSArnaldo Carvalho de Melo 
498d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
499d20deb64SArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
50035b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
50135b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
50235b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
503856e9660SPeter Zijlstra 		}
504856e9660SPeter Zijlstra 	}
505856e9660SPeter Zijlstra 
506d20deb64SArnaldo Carvalho de Melo 	perf_record__open(rec);
50786470930SIngo Molnar 
508712a4b60SArnaldo Carvalho de Melo 	/*
509d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
510712a4b60SArnaldo Carvalho de Melo 	 */
511d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
512712a4b60SArnaldo Carvalho de Melo 
513d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
514529870e3STom Zanussi 		err = perf_header__write_pipe(output);
515529870e3STom Zanussi 		if (err < 0)
516529870e3STom Zanussi 			return err;
517d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
518a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
519361c99a6SArnaldo Carvalho de Melo 						 output, false);
520d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
521d5eed904SArnaldo Carvalho de Melo 			return err;
522d5eed904SArnaldo Carvalho de Melo 	}
5237c6a1c65SPeter Zijlstra 
524d3665498SDavid Ahern 	if (!rec->no_buildid
525e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
526d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
527e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
528e20960c0SRobert Richter 		return -1;
529e20960c0SRobert Richter 	}
530e20960c0SRobert Richter 
531d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
5326122e4e4SArnaldo Carvalho de Melo 
533743eb868SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
534743eb868SArnaldo Carvalho de Melo 	if (!machine) {
535743eb868SArnaldo Carvalho de Melo 		pr_err("Couldn't find native kernel information.\n");
536743eb868SArnaldo Carvalho de Melo 		return -1;
537743eb868SArnaldo Carvalho de Melo 	}
538743eb868SArnaldo Carvalho de Melo 
539d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
54045694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
541a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
5422c46dbb5STom Zanussi 		if (err < 0) {
5432c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
5442c46dbb5STom Zanussi 			return err;
5452c46dbb5STom Zanussi 		}
546cd19a035STom Zanussi 
54745694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
548743eb868SArnaldo Carvalho de Melo 							 machine);
549cd19a035STom Zanussi 		if (err < 0) {
550cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
551cd19a035STom Zanussi 			return err;
552cd19a035STom Zanussi 		}
5539215545eSTom Zanussi 
554361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
55563e0c771STom Zanussi 			/*
55663e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
55763e0c771STom Zanussi 			 * there were no tracepoints so its not really
55863e0c771STom Zanussi 			 * an error, just that we don't need to
55963e0c771STom Zanussi 			 * synthesize anything.  We really have to
56063e0c771STom Zanussi 			 * return this more properly and also
56163e0c771STom Zanussi 			 * propagate errors that now are calling die()
56263e0c771STom Zanussi 			 */
56345694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
564743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
56563e0c771STom Zanussi 			if (err <= 0) {
56663e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
56763e0c771STom Zanussi 				return err;
56863e0c771STom Zanussi 			}
569d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
5702c46dbb5STom Zanussi 		}
57163e0c771STom Zanussi 	}
5722c46dbb5STom Zanussi 
57345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
574743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
57570162138SArnaldo Carvalho de Melo 	if (err < 0)
57645694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
577743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
578c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
579c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
580c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
581c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
58256b03f3cSArnaldo Carvalho de Melo 
58345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
584743eb868SArnaldo Carvalho de Melo 					     machine);
585c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
586c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
587c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
588c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
589c1a3a4b9SArnaldo Carvalho de Melo 
590a1645ce1SZhang, Yanmin 	if (perf_guest)
59145694aa7SArnaldo Carvalho de Melo 		perf_session__process_machines(session, tool,
5928115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
593b7cece76SArnaldo Carvalho de Melo 
594bea03405SNamhyung Kim 	if (!opts->target.system_wide)
59545694aa7SArnaldo Carvalho de Melo 		perf_event__synthesize_thread_map(tool, evsel_list->threads,
5968115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
597743eb868SArnaldo Carvalho de Melo 						  machine);
598234fbbf5SArnaldo Carvalho de Melo 	else
59945694aa7SArnaldo Carvalho de Melo 		perf_event__synthesize_threads(tool, process_synthesized_event,
600743eb868SArnaldo Carvalho de Melo 					       machine);
6017c6a1c65SPeter Zijlstra 
602d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
60386470930SIngo Molnar 		struct sched_param param;
60486470930SIngo Molnar 
605d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
60686470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6076beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
60886470930SIngo Molnar 			exit(-1);
60986470930SIngo Molnar 		}
61086470930SIngo Molnar 	}
61186470930SIngo Molnar 
612764e16a3SDavid Ahern 	perf_evlist__enable(evsel_list);
613764e16a3SDavid Ahern 
614856e9660SPeter Zijlstra 	/*
615856e9660SPeter Zijlstra 	 * Let the child rip
616856e9660SPeter Zijlstra 	 */
617d4db3f16SArnaldo Carvalho de Melo 	if (forks)
61835b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
619856e9660SPeter Zijlstra 
620649c48a9SPeter Zijlstra 	for (;;) {
621d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
62286470930SIngo Molnar 
623d20deb64SArnaldo Carvalho de Melo 		perf_record__mmap_read_all(rec);
62486470930SIngo Molnar 
625d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
626649c48a9SPeter Zijlstra 			if (done)
627649c48a9SPeter Zijlstra 				break;
6285c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6298b412664SPeter Zijlstra 			waking++;
6308b412664SPeter Zijlstra 		}
6318b412664SPeter Zijlstra 
6324152ab37SArnaldo Carvalho de Melo 		if (done)
6334152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6348b412664SPeter Zijlstra 	}
6358b412664SPeter Zijlstra 
63618483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
637b44308f5SArnaldo Carvalho de Melo 		return 0;
638b44308f5SArnaldo Carvalho de Melo 
6398b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
64086470930SIngo Molnar 
64186470930SIngo Molnar 	/*
64286470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
64386470930SIngo Molnar 	 */
64486470930SIngo Molnar 	fprintf(stderr,
6459486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
646d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
64786470930SIngo Molnar 		output_name,
648d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
64986470930SIngo Molnar 
65086470930SIngo Molnar 	return 0;
65139d17dacSArnaldo Carvalho de Melo 
65239d17dacSArnaldo Carvalho de Melo out_delete_session:
65339d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
65439d17dacSArnaldo Carvalho de Melo 	return err;
65586470930SIngo Molnar }
65686470930SIngo Molnar 
657bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
658bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
659bdfebd84SRoberto Agostino Vitillo 
660bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
661bdfebd84SRoberto Agostino Vitillo 
662bdfebd84SRoberto Agostino Vitillo struct branch_mode {
663bdfebd84SRoberto Agostino Vitillo 	const char *name;
664bdfebd84SRoberto Agostino Vitillo 	int mode;
665bdfebd84SRoberto Agostino Vitillo };
666bdfebd84SRoberto Agostino Vitillo 
667bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
668bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
669bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
670bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
671bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
672bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
673bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
674bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
675bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
676bdfebd84SRoberto Agostino Vitillo };
677bdfebd84SRoberto Agostino Vitillo 
678bdfebd84SRoberto Agostino Vitillo static int
679a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
680bdfebd84SRoberto Agostino Vitillo {
681bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
682bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
683bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
684bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
685bdfebd84SRoberto Agostino Vitillo 
686bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
687bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
688a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
689bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
690bdfebd84SRoberto Agostino Vitillo 
691a5aabdacSStephane Eranian 	if (unset)
692a5aabdacSStephane Eranian 		return 0;
693bdfebd84SRoberto Agostino Vitillo 
694a5aabdacSStephane Eranian 	/*
695a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
696a5aabdacSStephane Eranian 	 */
697a5aabdacSStephane Eranian 	if (*mode)
698a5aabdacSStephane Eranian 		return -1;
699a5aabdacSStephane Eranian 
700a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
701a5aabdacSStephane Eranian 	if (str) {
702bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
703bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
704bdfebd84SRoberto Agostino Vitillo 		if (!s)
705bdfebd84SRoberto Agostino Vitillo 			return -1;
706bdfebd84SRoberto Agostino Vitillo 
707bdfebd84SRoberto Agostino Vitillo 		for (;;) {
708bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
709bdfebd84SRoberto Agostino Vitillo 			if (p)
710bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
711bdfebd84SRoberto Agostino Vitillo 
712bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
713bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
714bdfebd84SRoberto Agostino Vitillo 					break;
715bdfebd84SRoberto Agostino Vitillo 			}
716a5aabdacSStephane Eranian 			if (!br->name) {
717a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
718a5aabdacSStephane Eranian 					    " check man page\n", s);
719bdfebd84SRoberto Agostino Vitillo 				goto error;
720a5aabdacSStephane Eranian 			}
721bdfebd84SRoberto Agostino Vitillo 
722bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
723bdfebd84SRoberto Agostino Vitillo 
724bdfebd84SRoberto Agostino Vitillo 			if (!p)
725bdfebd84SRoberto Agostino Vitillo 				break;
726bdfebd84SRoberto Agostino Vitillo 
727bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
728bdfebd84SRoberto Agostino Vitillo 		}
729a5aabdacSStephane Eranian 	}
730bdfebd84SRoberto Agostino Vitillo 	ret = 0;
731bdfebd84SRoberto Agostino Vitillo 
732a5aabdacSStephane Eranian 	/* default to any branch */
733bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
734a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
735bdfebd84SRoberto Agostino Vitillo 	}
736bdfebd84SRoberto Agostino Vitillo error:
737bdfebd84SRoberto Agostino Vitillo 	free(os);
738bdfebd84SRoberto Agostino Vitillo 	return ret;
739bdfebd84SRoberto Agostino Vitillo }
740bdfebd84SRoberto Agostino Vitillo 
74126d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT
74226d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
74326d33022SJiri Olsa {
74426d33022SJiri Olsa 	char *endptr;
74526d33022SJiri Olsa 	unsigned long size;
74626d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
74726d33022SJiri Olsa 
74826d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
74926d33022SJiri Olsa 
75026d33022SJiri Olsa 	do {
75126d33022SJiri Olsa 		if (*endptr)
75226d33022SJiri Olsa 			break;
75326d33022SJiri Olsa 
75426d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
75526d33022SJiri Olsa 		if (!size || size > max_size)
75626d33022SJiri Olsa 			break;
75726d33022SJiri Olsa 
75826d33022SJiri Olsa 		*_size = size;
75926d33022SJiri Olsa 		return 0;
76026d33022SJiri Olsa 
76126d33022SJiri Olsa 	} while (0);
76226d33022SJiri Olsa 
76326d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
76426d33022SJiri Olsa 	       max_size, str);
76526d33022SJiri Olsa 	return -1;
76626d33022SJiri Olsa }
76726d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */
76826d33022SJiri Olsa 
76926d33022SJiri Olsa static int
77026d33022SJiri Olsa parse_callchain_opt(const struct option *opt __used, const char *arg,
77126d33022SJiri Olsa 		    int unset)
77226d33022SJiri Olsa {
77326d33022SJiri Olsa 	struct perf_record *rec = (struct perf_record *)opt->value;
77426d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
77526d33022SJiri Olsa 	char *buf;
77626d33022SJiri Olsa 	int ret = -1;
77726d33022SJiri Olsa 
77826d33022SJiri Olsa 	/* --no-call-graph */
77926d33022SJiri Olsa 	if (unset)
78026d33022SJiri Olsa 		return 0;
78126d33022SJiri Olsa 
78226d33022SJiri Olsa 	/* We specified default option if none is provided. */
78326d33022SJiri Olsa 	BUG_ON(!arg);
78426d33022SJiri Olsa 
78526d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
78626d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
78726d33022SJiri Olsa 	if (!buf)
78826d33022SJiri Olsa 		return -ENOMEM;
78926d33022SJiri Olsa 
79026d33022SJiri Olsa 	strcpy(buf, arg);
79126d33022SJiri Olsa 
79226d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
79326d33022SJiri Olsa 	name = tok ? : (char *)buf;
79426d33022SJiri Olsa 
79526d33022SJiri Olsa 	do {
79626d33022SJiri Olsa 		/* Framepointer style */
79726d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
79826d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
79926d33022SJiri Olsa 				rec->opts.call_graph = CALLCHAIN_FP;
80026d33022SJiri Olsa 				ret = 0;
80126d33022SJiri Olsa 			} else
80226d33022SJiri Olsa 				pr_err("callchain: No more arguments "
80326d33022SJiri Olsa 				       "needed for -g fp\n");
80426d33022SJiri Olsa 			break;
80526d33022SJiri Olsa 
80626d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT
80726d33022SJiri Olsa 		/* Dwarf style */
80826d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
80926d33022SJiri Olsa 			ret = 0;
81026d33022SJiri Olsa 			rec->opts.call_graph = CALLCHAIN_DWARF;
81126d33022SJiri Olsa 			rec->opts.stack_dump_size = default_stack_dump_size;
81226d33022SJiri Olsa 
81326d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
81426d33022SJiri Olsa 			if (tok) {
81526d33022SJiri Olsa 				unsigned long size = 0;
81626d33022SJiri Olsa 
81726d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
81826d33022SJiri Olsa 				rec->opts.stack_dump_size = size;
81926d33022SJiri Olsa 			}
82026d33022SJiri Olsa 
82126d33022SJiri Olsa 			if (!ret)
82226d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
82326d33022SJiri Olsa 					 rec->opts.stack_dump_size);
82426d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */
82526d33022SJiri Olsa 		} else {
82626d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
82726d33022SJiri Olsa 			       "value: %s\n", arg);
82826d33022SJiri Olsa 			break;
82926d33022SJiri Olsa 		}
83026d33022SJiri Olsa 
83126d33022SJiri Olsa 	} while (0);
83226d33022SJiri Olsa 
83326d33022SJiri Olsa 	free(buf);
83426d33022SJiri Olsa 
83526d33022SJiri Olsa 	if (!ret)
83626d33022SJiri Olsa 		pr_debug("callchain: type %d\n", rec->opts.call_graph);
83726d33022SJiri Olsa 
83826d33022SJiri Olsa 	return ret;
83926d33022SJiri Olsa }
84026d33022SJiri Olsa 
84186470930SIngo Molnar static const char * const record_usage[] = {
84286470930SIngo Molnar 	"perf record [<options>] [<command>]",
84386470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
84486470930SIngo Molnar 	NULL
84586470930SIngo Molnar };
84686470930SIngo Molnar 
847d20deb64SArnaldo Carvalho de Melo /*
848d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
849d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
850d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
851d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
852d20deb64SArnaldo Carvalho de Melo  *
853d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
854d20deb64SArnaldo Carvalho de Melo  *
855d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
856d20deb64SArnaldo Carvalho de Melo  */
857d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
858d20deb64SArnaldo Carvalho de Melo 	.opts = {
859d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
860d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
861d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
862447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
863d1cb9fceSNamhyung Kim 		.target		     = {
864d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
865d1cb9fceSNamhyung Kim 		},
866d20deb64SArnaldo Carvalho de Melo 	},
867d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
868d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
869d20deb64SArnaldo Carvalho de Melo };
8707865e817SFrederic Weisbecker 
871d20deb64SArnaldo Carvalho de Melo /*
872d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
873d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
874d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
875d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
876d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
877d20deb64SArnaldo Carvalho de Melo  */
878bca647aaSTom Zanussi const struct option record_options[] = {
879d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
88086470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
881f120f9d5SJiri Olsa 		     parse_events_option),
882d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
883c171b552SLi Zefan 		     "event filter", parse_filter),
884bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
885d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
886bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
887d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
888d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
88986470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
890d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
891acac03faSKirill Smelkov 		    "collect data without buffering"),
892d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
893daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
894bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
89586470930SIngo Molnar 			    "system-wide collection from all CPUs"),
896d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
89786470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
898bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
899c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
900d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
9017865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
902d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
903d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
90486470930SIngo Molnar 		    "output file name"),
905d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
9062e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
907d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
908d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
90901c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
910d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
91143bece79SLin Ming 		    "put the counters into a counter group"),
91226d33022SJiri Olsa 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
91326d33022SJiri Olsa 			     callchain_help, &parse_callchain_opt,
91426d33022SJiri Olsa 			     "fp"),
915c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
9163da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
917b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
918d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
919649c48a9SPeter Zijlstra 		    "per thread counts"),
920d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
9214bba828dSAnton Blanchard 		    "Sample addresses"),
922d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
9233e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
924d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
925649c48a9SPeter Zijlstra 		    "don't sample"),
926d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
927a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
928d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
929baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
930d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
931023695d9SStephane Eranian 		     "monitor event in cgroup name only",
932023695d9SStephane Eranian 		     parse_cgroups),
933bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
934bea03405SNamhyung Kim 		   "user to profile"),
935a5aabdacSStephane Eranian 
936a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
937a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
938a5aabdacSStephane Eranian 		     parse_branch_stack),
939a5aabdacSStephane Eranian 
940a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
941a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
942bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
94386470930SIngo Molnar 	OPT_END()
94486470930SIngo Molnar };
94586470930SIngo Molnar 
946f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used)
94786470930SIngo Molnar {
94869aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
94969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
950d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
951d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
95216ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
95386470930SIngo Molnar 
9547e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
955361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
956361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
957361c99a6SArnaldo Carvalho de Melo 
958d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
959d20deb64SArnaldo Carvalho de Melo 
960bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
961a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
962d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
963bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
96486470930SIngo Molnar 
965d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
9663780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
9677865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
968bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
969d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
970d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
9717865e817SFrederic Weisbecker 	} else {
972d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
9737865e817SFrederic Weisbecker 	}
9747865e817SFrederic Weisbecker 
975bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
9763780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
977023695d9SStephane Eranian 			  " system-wide mode\n");
978023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
979023695d9SStephane Eranian 	}
980023695d9SStephane Eranian 
981655000e7SArnaldo Carvalho de Melo 	symbol__init();
982baa2f6ceSArnaldo Carvalho de Melo 
983ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
984646aaea6SArnaldo Carvalho de Melo 		pr_warning(
985646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
986ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
987646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
988646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
989646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
990646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
991646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
992ec80fde7SArnaldo Carvalho de Melo 
993d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
994a1ac1d3cSStephane Eranian 		disable_buildid_cache();
995655000e7SArnaldo Carvalho de Melo 
996361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
997361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
99869aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
99969aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1000bbd36e5eSPeter Zijlstra 	}
100186470930SIngo Molnar 
100216ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
100316ad2ffbSNamhyung Kim 	if (err) {
100416ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
100516ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
100616ad2ffbSNamhyung Kim 	}
10074bd0f2d2SNamhyung Kim 
100816ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
100916ad2ffbSNamhyung Kim 	if (err) {
101016ad2ffbSNamhyung Kim 		int saved_errno = errno;
101116ad2ffbSNamhyung Kim 
101216ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
10133780f488SNamhyung Kim 		ui__error("%s", errbuf);
101416ad2ffbSNamhyung Kim 
101516ad2ffbSNamhyung Kim 		err = -saved_errno;
10160d37aa34SArnaldo Carvalho de Melo 		goto out_free_fd;
101716ad2ffbSNamhyung Kim 	}
10180d37aa34SArnaldo Carvalho de Melo 
101916ad2ffbSNamhyung Kim 	err = -ENOMEM;
1020b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1021dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
102269aad6f1SArnaldo Carvalho de Melo 
1023361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
10247289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1025ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1026d6d901c2SZhang, Yanmin 	}
10275c581041SArnaldo Carvalho de Melo 
1028d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1029d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1030d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1031d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1032f9212819SFrederic Weisbecker 
10337e4ff9e3SMike Galbraith 	/*
10347e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
10357e4ff9e3SMike Galbraith 	 */
1036d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1037d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1038d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1039d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
10407e4ff9e3SMike Galbraith 	} else {
10413780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
104239d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
10435c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
10447e4ff9e3SMike Galbraith 	}
10457e4ff9e3SMike Galbraith 
1046d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
104739d17dacSArnaldo Carvalho de Melo out_free_fd:
10487e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1049d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1050d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
105139d17dacSArnaldo Carvalho de Melo 	return err;
105286470930SIngo Molnar }
1053