xref: /openbmc/linux/tools/perf/builtin-record.c (revision 8fa60e1fbaecd2e652abe41f68a934c1759663f3)
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 
3478da39faSBernhard Rosenkraenzer #ifndef HAVE_ON_EXIT
3578da39faSBernhard Rosenkraenzer #ifndef ATEXIT_MAX
3678da39faSBernhard Rosenkraenzer #define ATEXIT_MAX 32
3778da39faSBernhard Rosenkraenzer #endif
3878da39faSBernhard Rosenkraenzer static int __on_exit_count = 0;
3978da39faSBernhard Rosenkraenzer typedef void (*on_exit_func_t) (int, void *);
4078da39faSBernhard Rosenkraenzer static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
4178da39faSBernhard Rosenkraenzer static void *__on_exit_args[ATEXIT_MAX];
4278da39faSBernhard Rosenkraenzer static int __exitcode = 0;
4378da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void);
4478da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg);
4578da39faSBernhard Rosenkraenzer #define exit(x) (exit)(__exitcode = (x))
4678da39faSBernhard Rosenkraenzer 
4778da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg)
4878da39faSBernhard Rosenkraenzer {
4978da39faSBernhard Rosenkraenzer 	if (__on_exit_count == ATEXIT_MAX)
5078da39faSBernhard Rosenkraenzer 		return -ENOMEM;
5178da39faSBernhard Rosenkraenzer 	else if (__on_exit_count == 0)
5278da39faSBernhard Rosenkraenzer 		atexit(__handle_on_exit_funcs);
5378da39faSBernhard Rosenkraenzer 	__on_exit_funcs[__on_exit_count] = function;
5478da39faSBernhard Rosenkraenzer 	__on_exit_args[__on_exit_count++] = arg;
5578da39faSBernhard Rosenkraenzer 	return 0;
5678da39faSBernhard Rosenkraenzer }
5778da39faSBernhard Rosenkraenzer 
5878da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void)
5978da39faSBernhard Rosenkraenzer {
6078da39faSBernhard Rosenkraenzer 	int i;
6178da39faSBernhard Rosenkraenzer 	for (i = 0; i < __on_exit_count; i++)
6278da39faSBernhard Rosenkraenzer 		__on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
6378da39faSBernhard Rosenkraenzer }
6478da39faSBernhard Rosenkraenzer #endif
6578da39faSBernhard Rosenkraenzer 
667865e817SFrederic Weisbecker enum write_mode_t {
677865e817SFrederic Weisbecker 	WRITE_FORCE,
687865e817SFrederic Weisbecker 	WRITE_APPEND
697865e817SFrederic Weisbecker };
707865e817SFrederic Weisbecker 
71d20deb64SArnaldo Carvalho de Melo struct perf_record {
7245694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
73d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts	opts;
74d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
75d20deb64SArnaldo Carvalho de Melo 	const char		*output_name;
76d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
77d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
78d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
79d20deb64SArnaldo Carvalho de Melo 	int			output;
80d20deb64SArnaldo Carvalho de Melo 	unsigned int		page_size;
81d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
82d20deb64SArnaldo Carvalho de Melo 	enum write_mode_t	write_mode;
83d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
84d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
85d20deb64SArnaldo Carvalho de Melo 	bool			force;
86d20deb64SArnaldo Carvalho de Melo 	bool			file_new;
87d20deb64SArnaldo Carvalho de Melo 	bool			append_file;
88d20deb64SArnaldo Carvalho de Melo 	long			samples;
89d20deb64SArnaldo Carvalho de Melo 	off_t			post_processing_offset;
900f82ebc4SArnaldo Carvalho de Melo };
9186470930SIngo Molnar 
92d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size)
939215545eSTom Zanussi {
94d20deb64SArnaldo Carvalho de Melo 	rec->bytes_written += size;
959215545eSTom Zanussi }
969215545eSTom Zanussi 
978d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size)
98f5970550SPeter Zijlstra {
99f5970550SPeter Zijlstra 	while (size) {
100d20deb64SArnaldo Carvalho de Melo 		int ret = write(rec->output, buf, size);
101f5970550SPeter Zijlstra 
1028d3eca20SDavid Ahern 		if (ret < 0) {
1038d3eca20SDavid Ahern 			pr_err("failed to write\n");
1048d3eca20SDavid Ahern 			return -1;
1058d3eca20SDavid Ahern 		}
106f5970550SPeter Zijlstra 
107f5970550SPeter Zijlstra 		size -= ret;
108f5970550SPeter Zijlstra 		buf += ret;
109f5970550SPeter Zijlstra 
110d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written += ret;
111f5970550SPeter Zijlstra 	}
1128d3eca20SDavid Ahern 
1138d3eca20SDavid Ahern 	return 0;
114f5970550SPeter Zijlstra }
115f5970550SPeter Zijlstra 
11645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
117d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
1181d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
1191d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
120234fbbf5SArnaldo Carvalho de Melo {
12145694aa7SArnaldo Carvalho de Melo 	struct perf_record *rec = container_of(tool, struct perf_record, tool);
1228d3eca20SDavid Ahern 	if (write_output(rec, event, event->header.size) < 0)
1238d3eca20SDavid Ahern 		return -1;
1248d3eca20SDavid Ahern 
125234fbbf5SArnaldo Carvalho de Melo 	return 0;
126234fbbf5SArnaldo Carvalho de Melo }
127234fbbf5SArnaldo Carvalho de Melo 
1288d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec,
129d20deb64SArnaldo Carvalho de Melo 				   struct perf_mmap *md)
13086470930SIngo Molnar {
131744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
13286470930SIngo Molnar 	unsigned int old = md->prev;
133d20deb64SArnaldo Carvalho de Melo 	unsigned char *data = md->base + rec->page_size;
13486470930SIngo Molnar 	unsigned long size;
13586470930SIngo Molnar 	void *buf;
1368d3eca20SDavid Ahern 	int rc = 0;
13786470930SIngo Molnar 
138dc82009aSArnaldo Carvalho de Melo 	if (old == head)
1398d3eca20SDavid Ahern 		return 0;
14086470930SIngo Molnar 
141d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
14286470930SIngo Molnar 
14386470930SIngo Molnar 	size = head - old;
14486470930SIngo Molnar 
14586470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
14686470930SIngo Molnar 		buf = &data[old & md->mask];
14786470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
14886470930SIngo Molnar 		old += size;
14986470930SIngo Molnar 
1508d3eca20SDavid Ahern 		if (write_output(rec, buf, size) < 0) {
1518d3eca20SDavid Ahern 			rc = -1;
1528d3eca20SDavid Ahern 			goto out;
1538d3eca20SDavid Ahern 		}
15486470930SIngo Molnar 	}
15586470930SIngo Molnar 
15686470930SIngo Molnar 	buf = &data[old & md->mask];
15786470930SIngo Molnar 	size = head - old;
15886470930SIngo Molnar 	old += size;
15986470930SIngo Molnar 
1608d3eca20SDavid Ahern 	if (write_output(rec, buf, size) < 0) {
1618d3eca20SDavid Ahern 		rc = -1;
1628d3eca20SDavid Ahern 		goto out;
1638d3eca20SDavid Ahern 	}
16486470930SIngo Molnar 
16586470930SIngo Molnar 	md->prev = old;
166115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
1678d3eca20SDavid Ahern 
1688d3eca20SDavid Ahern out:
1698d3eca20SDavid Ahern 	return rc;
17086470930SIngo Molnar }
17186470930SIngo Molnar 
17286470930SIngo Molnar static volatile int done = 0;
173f7b7c26eSPeter Zijlstra static volatile int signr = -1;
17433e49ea7SAndi Kleen static volatile int child_finished = 0;
17586470930SIngo Molnar 
17686470930SIngo Molnar static void sig_handler(int sig)
17786470930SIngo Molnar {
17833e49ea7SAndi Kleen 	if (sig == SIGCHLD)
17933e49ea7SAndi Kleen 		child_finished = 1;
18033e49ea7SAndi Kleen 
18186470930SIngo Molnar 	done = 1;
182f7b7c26eSPeter Zijlstra 	signr = sig;
183f7b7c26eSPeter Zijlstra }
184f7b7c26eSPeter Zijlstra 
1851d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
186f7b7c26eSPeter Zijlstra {
187d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
18833e49ea7SAndi Kleen 	int status;
18933e49ea7SAndi Kleen 
190d20deb64SArnaldo Carvalho de Melo 	if (rec->evlist->workload.pid > 0) {
19133e49ea7SAndi Kleen 		if (!child_finished)
192d20deb64SArnaldo Carvalho de Melo 			kill(rec->evlist->workload.pid, SIGTERM);
193933da83aSChris Wilson 
19433e49ea7SAndi Kleen 		wait(&status);
19533e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
196d20deb64SArnaldo Carvalho de Melo 			psignal(WTERMSIG(status), rec->progname);
19733e49ea7SAndi Kleen 	}
19833e49ea7SAndi Kleen 
19918483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
200f7b7c26eSPeter Zijlstra 		return;
201f7b7c26eSPeter Zijlstra 
202f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
203f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
20486470930SIngo Molnar }
20586470930SIngo Molnar 
206a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
207a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
208a91e5431SArnaldo Carvalho de Melo {
209a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
210a91e5431SArnaldo Carvalho de Melo 
211a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
212a91e5431SArnaldo Carvalho de Melo 		return false;
213a91e5431SArnaldo Carvalho de Melo 
2140c21f736SArnaldo Carvalho de Melo 	pair = perf_evlist__first(other);
215a91e5431SArnaldo Carvalho de Melo 
216a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
217a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
218a91e5431SArnaldo Carvalho de Melo 			return false;
2190c21f736SArnaldo Carvalho de Melo 		pair = perf_evsel__next(pair);
220a91e5431SArnaldo Carvalho de Melo 	}
221a91e5431SArnaldo Carvalho de Melo 
222a91e5431SArnaldo Carvalho de Melo 	return true;
223a91e5431SArnaldo Carvalho de Melo }
224a91e5431SArnaldo Carvalho de Melo 
2258d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec)
226dd7927f4SArnaldo Carvalho de Melo {
22756e52e85SArnaldo Carvalho de Melo 	char msg[512];
2286a4bb04cSJiri Olsa 	struct perf_evsel *pos;
229d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
230d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
231d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
2328d3eca20SDavid Ahern 	int rc = 0;
233dd7927f4SArnaldo Carvalho de Melo 
234f77a9518SArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts);
235cac21425SJiri Olsa 
236dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
2373da297a6SIngo Molnar try_again:
2386a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
23956e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
2403da297a6SIngo Molnar 				if (verbose)
241c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
2423da297a6SIngo Molnar 				goto try_again;
2433da297a6SIngo Molnar 			}
244ca6a4258SDavid Ahern 
24556e52e85SArnaldo Carvalho de Melo 			rc = -errno;
24656e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
24756e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
24856e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
2498d3eca20SDavid Ahern 			goto out;
2507c6a1c65SPeter Zijlstra 		}
2517c6a1c65SPeter Zijlstra 	}
2527c6a1c65SPeter Zijlstra 
2531491a632SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist)) {
2540a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
2550a102479SFrederic Weisbecker 			strerror(errno));
2568d3eca20SDavid Ahern 		rc = -1;
2578d3eca20SDavid Ahern 		goto out;
2580a102479SFrederic Weisbecker 	}
2590a102479SFrederic Weisbecker 
26018e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
2618d3eca20SDavid Ahern 		if (errno == EPERM) {
2628d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
26318e60939SNelson Elhage 			       "Consider increasing "
26418e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
26518e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
26618e60939SNelson Elhage 			       "(current value: %d)\n", opts->mmap_pages);
2678d3eca20SDavid Ahern 			rc = -errno;
2680089fa98SJiri Olsa 		} else if (!is_power_of_2(opts->mmap_pages) &&
2690089fa98SJiri Olsa 			   (opts->mmap_pages != UINT_MAX)) {
2708d3eca20SDavid Ahern 			pr_err("--mmap_pages/-m value must be a power of two.");
2718d3eca20SDavid Ahern 			rc = -EINVAL;
2728d3eca20SDavid Ahern 		} else {
2738d3eca20SDavid Ahern 			pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
2748d3eca20SDavid Ahern 			rc = -errno;
2758d3eca20SDavid Ahern 		}
2768d3eca20SDavid Ahern 		goto out;
27718e60939SNelson Elhage 	}
2780a27d7f9SArnaldo Carvalho de Melo 
279d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
280a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
281a91e5431SArnaldo Carvalho de Melo 	else {
282a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
283a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
2848d3eca20SDavid Ahern 			rc = -1;
2858d3eca20SDavid Ahern 			goto out;
286dd7927f4SArnaldo Carvalho de Melo 		}
28786470930SIngo Molnar  	}
28886470930SIngo Molnar 
2897b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
2908d3eca20SDavid Ahern out:
2918d3eca20SDavid Ahern 	return rc;
292a91e5431SArnaldo Carvalho de Melo }
293a91e5431SArnaldo Carvalho de Melo 
294d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
2956122e4e4SArnaldo Carvalho de Melo {
296d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
2976122e4e4SArnaldo Carvalho de Melo 
2989f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
2999f591fd7SArnaldo Carvalho de Melo 		return 0;
3009f591fd7SArnaldo Carvalho de Melo 
301d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
302d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
303d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
3046122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3056122e4e4SArnaldo Carvalho de Melo }
3066122e4e4SArnaldo Carvalho de Melo 
3078d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg)
308f5970550SPeter Zijlstra {
309d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
310f5970550SPeter Zijlstra 
3118d3eca20SDavid Ahern 	if (status != 0)
3128d3eca20SDavid Ahern 		return;
3138d3eca20SDavid Ahern 
314d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
315d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
316d20deb64SArnaldo Carvalho de Melo 
317d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
318d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
319d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
320d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
321d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
322d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
323d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
324c7929e47STom Zanussi 	}
325f5970550SPeter Zijlstra }
326f5970550SPeter Zijlstra 
3278115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
328a1645ce1SZhang, Yanmin {
329a1645ce1SZhang, Yanmin 	int err;
33045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
331a1645ce1SZhang, Yanmin 	/*
332a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
333a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
334a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
335a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
336a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
337a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
338a1645ce1SZhang, Yanmin 	 */
33945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
340743eb868SArnaldo Carvalho de Melo 					     machine);
341a1645ce1SZhang, Yanmin 	if (err < 0)
342a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
34323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
344a1645ce1SZhang, Yanmin 
345a1645ce1SZhang, Yanmin 	/*
346a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
347a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
348a1645ce1SZhang, Yanmin 	 */
34945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
350743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
351a1645ce1SZhang, Yanmin 	if (err < 0)
35245694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
353743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
354a1645ce1SZhang, Yanmin 	if (err < 0)
355a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
35623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
357a1645ce1SZhang, Yanmin }
358a1645ce1SZhang, Yanmin 
35998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
36098402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
36198402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
36298402807SFrederic Weisbecker };
36398402807SFrederic Weisbecker 
3648d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec)
36598402807SFrederic Weisbecker {
3660e2e63ddSPeter Zijlstra 	int i;
3678d3eca20SDavid Ahern 	int rc = 0;
36898402807SFrederic Weisbecker 
369d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
3708d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
3718d3eca20SDavid Ahern 			if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
3728d3eca20SDavid Ahern 				rc = -1;
3738d3eca20SDavid Ahern 				goto out;
3748d3eca20SDavid Ahern 			}
3758d3eca20SDavid Ahern 		}
37698402807SFrederic Weisbecker 	}
37798402807SFrederic Weisbecker 
3782eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
3798d3eca20SDavid Ahern 		rc = write_output(rec, &finished_round_event,
3808d3eca20SDavid Ahern 				  sizeof(finished_round_event));
3818d3eca20SDavid Ahern 
3828d3eca20SDavid Ahern out:
3838d3eca20SDavid Ahern 	return rc;
38498402807SFrederic Weisbecker }
38598402807SFrederic Weisbecker 
386d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
38786470930SIngo Molnar {
38886470930SIngo Molnar 	struct stat st;
38986470930SIngo Molnar 	int flags;
390781ba9d2SRobert Richter 	int err, output, feat;
3918b412664SPeter Zijlstra 	unsigned long waking = 0;
39246be604bSZhang, Yanmin 	const bool forks = argc > 0;
39323346f21SArnaldo Carvalho de Melo 	struct machine *machine;
39445694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
395d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
396d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
397d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
398d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
3992711926aSJiri Olsa 	bool disabled = false;
40086470930SIngo Molnar 
401d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
40233e49ea7SAndi Kleen 
403d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
40486470930SIngo Molnar 
405d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
406f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
407f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
40818483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
409f5970550SPeter Zijlstra 
410d7065adbSFranck Bui-Huu 	if (!output_name) {
411d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
412d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
413d7065adbSFranck Bui-Huu 		else
414d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
415d7065adbSFranck Bui-Huu 	}
416d7065adbSFranck Bui-Huu 	if (output_name) {
417529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
418d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
419529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
420d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
421b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
422b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
423b38d3464SArnaldo Carvalho de Melo 					 output_name);
424b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
425b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
426b38d3464SArnaldo Carvalho de Melo 			}
427d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
428d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
429266e0e21SPierre Habouzit 		}
430d7065adbSFranck Bui-Huu 	}
43186470930SIngo Molnar 
432f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
433d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
434d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
43586470930SIngo Molnar 	else
43686470930SIngo Molnar 		flags |= O_TRUNC;
43786470930SIngo Molnar 
438d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
439529870e3STom Zanussi 		output = STDOUT_FILENO;
440529870e3STom Zanussi 	else
44186470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
44286470930SIngo Molnar 	if (output < 0) {
44386470930SIngo Molnar 		perror("failed to create output file");
4448d3eca20SDavid Ahern 		return -1;
44586470930SIngo Molnar 	}
44686470930SIngo Molnar 
447d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
448d20deb64SArnaldo Carvalho de Melo 
4497865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
450d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
45194c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
452a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
453a9a70bbcSArnaldo Carvalho de Melo 		return -1;
454a9a70bbcSArnaldo Carvalho de Melo 	}
455a9a70bbcSArnaldo Carvalho de Melo 
456d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
457d20deb64SArnaldo Carvalho de Melo 
458781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
459781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
460781ba9d2SRobert Richter 
461781ba9d2SRobert Richter 	if (rec->no_buildid)
462781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
463781ba9d2SRobert Richter 
464781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
4652eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
466baa2f6ceSArnaldo Carvalho de Melo 
467330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
468330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
469330aa675SStephane Eranian 
470d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
471a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
4724dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
47339d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
4744dc0a04bSArnaldo Carvalho de Melo 	}
4754dc0a04bSArnaldo Carvalho de Melo 
476d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
4776ef73ec4SNamhyung Kim 		err = perf_evlist__prepare_workload(evsel_list, &opts->target,
47855e162eaSNamhyung Kim 						    argv, opts->pipe_output,
47955e162eaSNamhyung Kim 						    true);
48035b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
48135b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
48235b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
483856e9660SPeter Zijlstra 		}
484856e9660SPeter Zijlstra 	}
485856e9660SPeter Zijlstra 
4868d3eca20SDavid Ahern 	if (perf_record__open(rec) != 0) {
4878d3eca20SDavid Ahern 		err = -1;
4888d3eca20SDavid Ahern 		goto out_delete_session;
4898d3eca20SDavid Ahern 	}
49086470930SIngo Molnar 
491a8bb559bSNamhyung Kim 	if (!evsel_list->nr_groups)
492a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
493a8bb559bSNamhyung Kim 
494712a4b60SArnaldo Carvalho de Melo 	/*
495d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
496712a4b60SArnaldo Carvalho de Melo 	 */
497d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
498712a4b60SArnaldo Carvalho de Melo 
499d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
500529870e3STom Zanussi 		err = perf_header__write_pipe(output);
501529870e3STom Zanussi 		if (err < 0)
5028d3eca20SDavid Ahern 			goto out_delete_session;
503d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
504a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
505361c99a6SArnaldo Carvalho de Melo 						 output, false);
506d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
5078d3eca20SDavid Ahern 			goto out_delete_session;
508d5eed904SArnaldo Carvalho de Melo 	}
5097c6a1c65SPeter Zijlstra 
510d3665498SDavid Ahern 	if (!rec->no_buildid
511e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
512d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
513e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
5148d3eca20SDavid Ahern 		err = -1;
5158d3eca20SDavid Ahern 		goto out_delete_session;
516e20960c0SRobert Richter 	}
517e20960c0SRobert Richter 
518d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
5196122e4e4SArnaldo Carvalho de Melo 
52034ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
521743eb868SArnaldo Carvalho de Melo 
522d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
52345694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
524a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
5252c46dbb5STom Zanussi 		if (err < 0) {
5262c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
5278d3eca20SDavid Ahern 			goto out_delete_session;
5282c46dbb5STom Zanussi 		}
529cd19a035STom Zanussi 
53045694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
531743eb868SArnaldo Carvalho de Melo 							 machine);
532cd19a035STom Zanussi 		if (err < 0) {
533cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
5348d3eca20SDavid Ahern 			goto out_delete_session;
535cd19a035STom Zanussi 		}
5369215545eSTom Zanussi 
537361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
53863e0c771STom Zanussi 			/*
53963e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
54063e0c771STom Zanussi 			 * there were no tracepoints so its not really
54163e0c771STom Zanussi 			 * an error, just that we don't need to
54263e0c771STom Zanussi 			 * synthesize anything.  We really have to
54363e0c771STom Zanussi 			 * return this more properly and also
54463e0c771STom Zanussi 			 * propagate errors that now are calling die()
54563e0c771STom Zanussi 			 */
54645694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
547743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
54863e0c771STom Zanussi 			if (err <= 0) {
54963e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
5508d3eca20SDavid Ahern 				goto out_delete_session;
55163e0c771STom Zanussi 			}
552d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
5532c46dbb5STom Zanussi 		}
55463e0c771STom Zanussi 	}
5552c46dbb5STom Zanussi 
55645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
557743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
55870162138SArnaldo Carvalho de Melo 	if (err < 0)
55945694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
560743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
561c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
562c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
563c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
564c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
56556b03f3cSArnaldo Carvalho de Melo 
56645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
567743eb868SArnaldo Carvalho de Melo 					     machine);
568c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
569c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
570c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
571c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
572c1a3a4b9SArnaldo Carvalho de Melo 
5737e383de4SArnaldo Carvalho de Melo 	if (perf_guest) {
574876650e6SArnaldo Carvalho de Melo 		machines__process_guests(&session->machines,
5757e383de4SArnaldo Carvalho de Melo 					 perf_event__synthesize_guest_os, tool);
5767e383de4SArnaldo Carvalho de Melo 	}
577b7cece76SArnaldo Carvalho de Melo 
578e4dd45feSJiri Olsa 	if (perf_target__has_task(&opts->target))
5798d3eca20SDavid Ahern 		err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
5808115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
581743eb868SArnaldo Carvalho de Melo 						  machine);
582e4dd45feSJiri Olsa 	else if (perf_target__has_cpu(&opts->target))
5838d3eca20SDavid Ahern 		err = perf_event__synthesize_threads(tool, process_synthesized_event,
584743eb868SArnaldo Carvalho de Melo 					       machine);
585e4dd45feSJiri Olsa 	else /* command specified */
586e4dd45feSJiri Olsa 		err = 0;
5877c6a1c65SPeter Zijlstra 
5888d3eca20SDavid Ahern 	if (err != 0)
5898d3eca20SDavid Ahern 		goto out_delete_session;
5908d3eca20SDavid Ahern 
591d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
59286470930SIngo Molnar 		struct sched_param param;
59386470930SIngo Molnar 
594d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
59586470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
5966beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
5978d3eca20SDavid Ahern 			err = -1;
5988d3eca20SDavid Ahern 			goto out_delete_session;
59986470930SIngo Molnar 		}
60086470930SIngo Molnar 	}
60186470930SIngo Molnar 
602774cb499SJiri Olsa 	/*
603774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
604774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
605774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
606774cb499SJiri Olsa 	 */
607774cb499SJiri Olsa 	if (!perf_target__none(&opts->target))
608764e16a3SDavid Ahern 		perf_evlist__enable(evsel_list);
609764e16a3SDavid Ahern 
610856e9660SPeter Zijlstra 	/*
611856e9660SPeter Zijlstra 	 * Let the child rip
612856e9660SPeter Zijlstra 	 */
613d4db3f16SArnaldo Carvalho de Melo 	if (forks)
61435b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
615856e9660SPeter Zijlstra 
616649c48a9SPeter Zijlstra 	for (;;) {
617d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
61886470930SIngo Molnar 
6198d3eca20SDavid Ahern 		if (perf_record__mmap_read_all(rec) < 0) {
6208d3eca20SDavid Ahern 			err = -1;
6218d3eca20SDavid Ahern 			goto out_delete_session;
6228d3eca20SDavid Ahern 		}
62386470930SIngo Molnar 
624d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
625649c48a9SPeter Zijlstra 			if (done)
626649c48a9SPeter Zijlstra 				break;
6275c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6288b412664SPeter Zijlstra 			waking++;
6298b412664SPeter Zijlstra 		}
6308b412664SPeter Zijlstra 
631774cb499SJiri Olsa 		/*
632774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
633774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
634774cb499SJiri Olsa 		 * disable events in this case.
635774cb499SJiri Olsa 		 */
6362711926aSJiri Olsa 		if (done && !disabled && !perf_target__none(&opts->target)) {
6374152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6382711926aSJiri Olsa 			disabled = true;
6392711926aSJiri Olsa 		}
6408b412664SPeter Zijlstra 	}
6418b412664SPeter Zijlstra 
64218483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
643b44308f5SArnaldo Carvalho de Melo 		return 0;
644b44308f5SArnaldo Carvalho de Melo 
6458b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
64686470930SIngo Molnar 
64786470930SIngo Molnar 	/*
64886470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
64986470930SIngo Molnar 	 */
65086470930SIngo Molnar 	fprintf(stderr,
6519486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
652d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
65386470930SIngo Molnar 		output_name,
654d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
65586470930SIngo Molnar 
65686470930SIngo Molnar 	return 0;
65739d17dacSArnaldo Carvalho de Melo 
65839d17dacSArnaldo Carvalho de Melo out_delete_session:
65939d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
66039d17dacSArnaldo Carvalho de Melo 	return err;
66186470930SIngo Molnar }
66286470930SIngo Molnar 
663bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
664bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
665bdfebd84SRoberto Agostino Vitillo 
666bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
667bdfebd84SRoberto Agostino Vitillo 
668bdfebd84SRoberto Agostino Vitillo struct branch_mode {
669bdfebd84SRoberto Agostino Vitillo 	const char *name;
670bdfebd84SRoberto Agostino Vitillo 	int mode;
671bdfebd84SRoberto Agostino Vitillo };
672bdfebd84SRoberto Agostino Vitillo 
673bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
674bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
675bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
676bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
677bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
678bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
679bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
680bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
681bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
682bdfebd84SRoberto Agostino Vitillo };
683bdfebd84SRoberto Agostino Vitillo 
684bdfebd84SRoberto Agostino Vitillo static int
685a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
686bdfebd84SRoberto Agostino Vitillo {
687bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
688bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
689bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
690bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
691bdfebd84SRoberto Agostino Vitillo 
692bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
693bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
694a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
695bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
696bdfebd84SRoberto Agostino Vitillo 
697a5aabdacSStephane Eranian 	if (unset)
698a5aabdacSStephane Eranian 		return 0;
699bdfebd84SRoberto Agostino Vitillo 
700a5aabdacSStephane Eranian 	/*
701a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
702a5aabdacSStephane Eranian 	 */
703a5aabdacSStephane Eranian 	if (*mode)
704a5aabdacSStephane Eranian 		return -1;
705a5aabdacSStephane Eranian 
706a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
707a5aabdacSStephane Eranian 	if (str) {
708bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
709bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
710bdfebd84SRoberto Agostino Vitillo 		if (!s)
711bdfebd84SRoberto Agostino Vitillo 			return -1;
712bdfebd84SRoberto Agostino Vitillo 
713bdfebd84SRoberto Agostino Vitillo 		for (;;) {
714bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
715bdfebd84SRoberto Agostino Vitillo 			if (p)
716bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
717bdfebd84SRoberto Agostino Vitillo 
718bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
719bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
720bdfebd84SRoberto Agostino Vitillo 					break;
721bdfebd84SRoberto Agostino Vitillo 			}
722a5aabdacSStephane Eranian 			if (!br->name) {
723a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
724a5aabdacSStephane Eranian 					    " check man page\n", s);
725bdfebd84SRoberto Agostino Vitillo 				goto error;
726a5aabdacSStephane Eranian 			}
727bdfebd84SRoberto Agostino Vitillo 
728bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
729bdfebd84SRoberto Agostino Vitillo 
730bdfebd84SRoberto Agostino Vitillo 			if (!p)
731bdfebd84SRoberto Agostino Vitillo 				break;
732bdfebd84SRoberto Agostino Vitillo 
733bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
734bdfebd84SRoberto Agostino Vitillo 		}
735a5aabdacSStephane Eranian 	}
736bdfebd84SRoberto Agostino Vitillo 	ret = 0;
737bdfebd84SRoberto Agostino Vitillo 
738a5aabdacSStephane Eranian 	/* default to any branch */
739bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
740a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
741bdfebd84SRoberto Agostino Vitillo 	}
742bdfebd84SRoberto Agostino Vitillo error:
743bdfebd84SRoberto Agostino Vitillo 	free(os);
744bdfebd84SRoberto Agostino Vitillo 	return ret;
745bdfebd84SRoberto Agostino Vitillo }
746bdfebd84SRoberto Agostino Vitillo 
74795485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
74826d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
74926d33022SJiri Olsa {
75026d33022SJiri Olsa 	char *endptr;
75126d33022SJiri Olsa 	unsigned long size;
75226d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
75326d33022SJiri Olsa 
75426d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
75526d33022SJiri Olsa 
75626d33022SJiri Olsa 	do {
75726d33022SJiri Olsa 		if (*endptr)
75826d33022SJiri Olsa 			break;
75926d33022SJiri Olsa 
76026d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
76126d33022SJiri Olsa 		if (!size || size > max_size)
76226d33022SJiri Olsa 			break;
76326d33022SJiri Olsa 
76426d33022SJiri Olsa 		*_size = size;
76526d33022SJiri Olsa 		return 0;
76626d33022SJiri Olsa 
76726d33022SJiri Olsa 	} while (0);
76826d33022SJiri Olsa 
76926d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
77026d33022SJiri Olsa 	       max_size, str);
77126d33022SJiri Olsa 	return -1;
77226d33022SJiri Olsa }
77395485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
77426d33022SJiri Olsa 
77575d9a108SArnaldo Carvalho de Melo int record_parse_callchain_opt(const struct option *opt,
77675d9a108SArnaldo Carvalho de Melo 			       const char *arg, int unset)
77726d33022SJiri Olsa {
778c5ff78c3SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = opt->value;
77926d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
78026d33022SJiri Olsa 	char *buf;
78126d33022SJiri Olsa 	int ret = -1;
78226d33022SJiri Olsa 
78326d33022SJiri Olsa 	/* --no-call-graph */
78426d33022SJiri Olsa 	if (unset)
78526d33022SJiri Olsa 		return 0;
78626d33022SJiri Olsa 
78726d33022SJiri Olsa 	/* We specified default option if none is provided. */
78826d33022SJiri Olsa 	BUG_ON(!arg);
78926d33022SJiri Olsa 
79026d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
79126d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
79226d33022SJiri Olsa 	if (!buf)
79326d33022SJiri Olsa 		return -ENOMEM;
79426d33022SJiri Olsa 
79526d33022SJiri Olsa 	strcpy(buf, arg);
79626d33022SJiri Olsa 
79726d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
79826d33022SJiri Olsa 	name = tok ? : (char *)buf;
79926d33022SJiri Olsa 
80026d33022SJiri Olsa 	do {
80126d33022SJiri Olsa 		/* Framepointer style */
80226d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
80326d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
804c5ff78c3SArnaldo Carvalho de Melo 				opts->call_graph = CALLCHAIN_FP;
80526d33022SJiri Olsa 				ret = 0;
80626d33022SJiri Olsa 			} else
80726d33022SJiri Olsa 				pr_err("callchain: No more arguments "
80826d33022SJiri Olsa 				       "needed for -g fp\n");
80926d33022SJiri Olsa 			break;
81026d33022SJiri Olsa 
81195485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
81226d33022SJiri Olsa 		/* Dwarf style */
81326d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
81461eaa3beSArnaldo Carvalho de Melo 			const unsigned long default_stack_dump_size = 8192;
81561eaa3beSArnaldo Carvalho de Melo 
81626d33022SJiri Olsa 			ret = 0;
817c5ff78c3SArnaldo Carvalho de Melo 			opts->call_graph = CALLCHAIN_DWARF;
818c5ff78c3SArnaldo Carvalho de Melo 			opts->stack_dump_size = default_stack_dump_size;
81926d33022SJiri Olsa 
82026d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
82126d33022SJiri Olsa 			if (tok) {
82226d33022SJiri Olsa 				unsigned long size = 0;
82326d33022SJiri Olsa 
82426d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
825c5ff78c3SArnaldo Carvalho de Melo 				opts->stack_dump_size = size;
82626d33022SJiri Olsa 			}
82726d33022SJiri Olsa 
82826d33022SJiri Olsa 			if (!ret)
82926d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
830c5ff78c3SArnaldo Carvalho de Melo 					 opts->stack_dump_size);
83195485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
83226d33022SJiri Olsa 		} else {
83326d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
83426d33022SJiri Olsa 			       "value: %s\n", arg);
83526d33022SJiri Olsa 			break;
83626d33022SJiri Olsa 		}
83726d33022SJiri Olsa 
83826d33022SJiri Olsa 	} while (0);
83926d33022SJiri Olsa 
84026d33022SJiri Olsa 	free(buf);
84126d33022SJiri Olsa 
84226d33022SJiri Olsa 	if (!ret)
843c5ff78c3SArnaldo Carvalho de Melo 		pr_debug("callchain: type %d\n", opts->call_graph);
84426d33022SJiri Olsa 
84526d33022SJiri Olsa 	return ret;
84626d33022SJiri Olsa }
84726d33022SJiri Olsa 
84886470930SIngo Molnar static const char * const record_usage[] = {
84986470930SIngo Molnar 	"perf record [<options>] [<command>]",
85086470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
85186470930SIngo Molnar 	NULL
85286470930SIngo Molnar };
85386470930SIngo Molnar 
854d20deb64SArnaldo Carvalho de Melo /*
855d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
856d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
857d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
858d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
859d20deb64SArnaldo Carvalho de Melo  *
860d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
861d20deb64SArnaldo Carvalho de Melo  *
862d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
863d20deb64SArnaldo Carvalho de Melo  */
864d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
865d20deb64SArnaldo Carvalho de Melo 	.opts = {
866d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
867d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
868d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
869447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
870d1cb9fceSNamhyung Kim 		.target		     = {
871d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
872d1cb9fceSNamhyung Kim 		},
873d20deb64SArnaldo Carvalho de Melo 	},
874d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
875d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
876d20deb64SArnaldo Carvalho de Melo };
8777865e817SFrederic Weisbecker 
87861eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
87961eaa3beSArnaldo Carvalho de Melo 
88061eaa3beSArnaldo Carvalho de Melo #ifdef LIBUNWIND_SUPPORT
88175d9a108SArnaldo Carvalho de Melo const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
88261eaa3beSArnaldo Carvalho de Melo #else
88375d9a108SArnaldo Carvalho de Melo const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
88461eaa3beSArnaldo Carvalho de Melo #endif
88561eaa3beSArnaldo Carvalho de Melo 
886d20deb64SArnaldo Carvalho de Melo /*
887d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
888d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
889d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
890d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
891d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
892d20deb64SArnaldo Carvalho de Melo  */
893bca647aaSTom Zanussi const struct option record_options[] = {
894d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
89586470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
896f120f9d5SJiri Olsa 		     parse_events_option),
897d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
898c171b552SLi Zefan 		     "event filter", parse_filter),
899bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
900d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
901bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
902d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
903d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
90486470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
905d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
906acac03faSKirill Smelkov 		    "collect data without buffering"),
907d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
908daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
909bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
91086470930SIngo Molnar 			    "system-wide collection from all CPUs"),
911d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
91286470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
913bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
914c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
915d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
9167865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
917d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
918d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
91986470930SIngo Molnar 		    "output file name"),
920d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
9212e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
922d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
923d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
92401c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
925d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
92643bece79SLin Ming 		    "put the counters into a counter group"),
927c5ff78c3SArnaldo Carvalho de Melo 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
92875d9a108SArnaldo Carvalho de Melo 			     "mode[,dump_size]", record_callchain_help,
92975d9a108SArnaldo Carvalho de Melo 			     &record_parse_callchain_opt, "fp"),
930c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
9313da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
932b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
933d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
934649c48a9SPeter Zijlstra 		    "per thread counts"),
935d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
9364bba828dSAnton Blanchard 		    "Sample addresses"),
937d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
9383e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
939d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
940649c48a9SPeter Zijlstra 		    "don't sample"),
941d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
942a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
943d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
944baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
945d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
946023695d9SStephane Eranian 		     "monitor event in cgroup name only",
947023695d9SStephane Eranian 		     parse_cgroups),
948bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
949bea03405SNamhyung Kim 		   "user to profile"),
950a5aabdacSStephane Eranian 
951a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
952a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
953a5aabdacSStephane Eranian 		     parse_branch_stack),
954a5aabdacSStephane Eranian 
955a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
956a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
957bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
95886470930SIngo Molnar 	OPT_END()
95986470930SIngo Molnar };
96086470930SIngo Molnar 
9611d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
96286470930SIngo Molnar {
96369aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
96469aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
965d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
966d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
96716ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
96886470930SIngo Molnar 
969334fe7a3SNamhyung Kim 	evsel_list = perf_evlist__new();
970361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
971361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
972361c99a6SArnaldo Carvalho de Melo 
973d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
974d20deb64SArnaldo Carvalho de Melo 
975bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
976a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
977d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
978bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
97986470930SIngo Molnar 
980d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
9813780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
9827865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
983bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
984d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
985d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
9867865e817SFrederic Weisbecker 	} else {
987d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
9887865e817SFrederic Weisbecker 	}
9897865e817SFrederic Weisbecker 
990bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
9913780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
992023695d9SStephane Eranian 			  " system-wide mode\n");
993023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
994023695d9SStephane Eranian 	}
995023695d9SStephane Eranian 
996655000e7SArnaldo Carvalho de Melo 	symbol__init();
997baa2f6ceSArnaldo Carvalho de Melo 
998ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
999646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1000646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1001ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1002646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1003646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1004646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1005646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1006646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1007ec80fde7SArnaldo Carvalho de Melo 
1008d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1009a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1010655000e7SArnaldo Carvalho de Melo 
1011361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
1012361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
101369aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
101469aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1015bbd36e5eSPeter Zijlstra 	}
101686470930SIngo Molnar 
101716ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
101816ad2ffbSNamhyung Kim 	if (err) {
101916ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
102016ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
102116ad2ffbSNamhyung Kim 	}
10224bd0f2d2SNamhyung Kim 
102316ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
102416ad2ffbSNamhyung Kim 	if (err) {
102516ad2ffbSNamhyung Kim 		int saved_errno = errno;
102616ad2ffbSNamhyung Kim 
102716ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
10283780f488SNamhyung Kim 		ui__error("%s", errbuf);
102916ad2ffbSNamhyung Kim 
103016ad2ffbSNamhyung Kim 		err = -saved_errno;
1031*8fa60e1fSNamhyung Kim 		goto out_symbol_exit;
103216ad2ffbSNamhyung Kim 	}
10330d37aa34SArnaldo Carvalho de Melo 
103416ad2ffbSNamhyung Kim 	err = -ENOMEM;
1035b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1036dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
103769aad6f1SArnaldo Carvalho de Melo 
1038361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
10397289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1040ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1041d6d901c2SZhang, Yanmin 	}
10425c581041SArnaldo Carvalho de Melo 
1043d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1044d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1045d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1046d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1047f9212819SFrederic Weisbecker 
10487e4ff9e3SMike Galbraith 	/*
10497e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
10507e4ff9e3SMike Galbraith 	 */
1051d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1052d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1053d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1054d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
10557e4ff9e3SMike Galbraith 	} else {
10563780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
105739d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
10585c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
10597e4ff9e3SMike Galbraith 	}
10607e4ff9e3SMike Galbraith 
1061d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1062*8fa60e1fSNamhyung Kim 
1063*8fa60e1fSNamhyung Kim 	perf_evlist__munmap(evsel_list);
1064*8fa60e1fSNamhyung Kim 	perf_evlist__close(evsel_list);
106539d17dacSArnaldo Carvalho de Melo out_free_fd:
10667e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1067d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1068d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
106939d17dacSArnaldo Carvalho de Melo 	return err;
107086470930SIngo Molnar }
1071