xref: /openbmc/linux/tools/perf/builtin-record.c (revision cd10b289520577a56c5d369b9a2e7bbee5698a4b)
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  */
886470930SIngo Molnar #include "builtin.h"
986470930SIngo Molnar 
1086470930SIngo Molnar #include "perf.h"
1186470930SIngo Molnar 
126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1386470930SIngo Molnar #include "util/util.h"
1486470930SIngo Molnar #include "util/parse-options.h"
1586470930SIngo Molnar #include "util/parse-events.h"
1686470930SIngo Molnar 
178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
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"
29f5fc1412SJiri Olsa #include "util/data.h"
30ef149c25SAdrian Hunter #include "util/auxtrace.h"
317c6a1c65SPeter Zijlstra 
3286470930SIngo Molnar #include <unistd.h>
3386470930SIngo Molnar #include <sched.h>
34a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
3586470930SIngo Molnar 
3678da39faSBernhard Rosenkraenzer 
378c6f45a7SArnaldo Carvalho de Melo struct record {
3845694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
39b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
40d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
41f5fc1412SJiri Olsa 	struct perf_data_file	file;
42ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
43d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
44d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
45d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
46d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
47d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
48d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
49d20deb64SArnaldo Carvalho de Melo 	long			samples;
500f82ebc4SArnaldo Carvalho de Melo };
5186470930SIngo Molnar 
528c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
53f5970550SPeter Zijlstra {
54cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
554f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
568d3eca20SDavid Ahern 		return -1;
578d3eca20SDavid Ahern 	}
58f5970550SPeter Zijlstra 
59cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
608d3eca20SDavid Ahern 	return 0;
61f5970550SPeter Zijlstra }
62f5970550SPeter Zijlstra 
6345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
64d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
651d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
661d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
67234fbbf5SArnaldo Carvalho de Melo {
688c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
698c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
70234fbbf5SArnaldo Carvalho de Melo }
71234fbbf5SArnaldo Carvalho de Melo 
72e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
7386470930SIngo Molnar {
74e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
757b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
767b8283b5SDavid Ahern 	u64 old = md->prev;
77918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
7886470930SIngo Molnar 	unsigned long size;
7986470930SIngo Molnar 	void *buf;
808d3eca20SDavid Ahern 	int rc = 0;
8186470930SIngo Molnar 
82dc82009aSArnaldo Carvalho de Melo 	if (old == head)
838d3eca20SDavid Ahern 		return 0;
8486470930SIngo Molnar 
85d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
8686470930SIngo Molnar 
8786470930SIngo Molnar 	size = head - old;
8886470930SIngo Molnar 
8986470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
9086470930SIngo Molnar 		buf = &data[old & md->mask];
9186470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
9286470930SIngo Molnar 		old += size;
9386470930SIngo Molnar 
948c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
958d3eca20SDavid Ahern 			rc = -1;
968d3eca20SDavid Ahern 			goto out;
978d3eca20SDavid Ahern 		}
9886470930SIngo Molnar 	}
9986470930SIngo Molnar 
10086470930SIngo Molnar 	buf = &data[old & md->mask];
10186470930SIngo Molnar 	size = head - old;
10286470930SIngo Molnar 	old += size;
10386470930SIngo Molnar 
1048c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1058d3eca20SDavid Ahern 		rc = -1;
1068d3eca20SDavid Ahern 		goto out;
1078d3eca20SDavid Ahern 	}
10886470930SIngo Molnar 
10986470930SIngo Molnar 	md->prev = old;
110e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1118d3eca20SDavid Ahern out:
1128d3eca20SDavid Ahern 	return rc;
11386470930SIngo Molnar }
11486470930SIngo Molnar 
115ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
116ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
117ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
118ef149c25SAdrian Hunter {
119ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
12099fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
121ef149c25SAdrian Hunter 	size_t padding;
122ef149c25SAdrian Hunter 	u8 pad[8] = {0};
123ef149c25SAdrian Hunter 
12499fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
12599fa2984SAdrian Hunter 		off_t file_offset;
12699fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
12799fa2984SAdrian Hunter 		int err;
12899fa2984SAdrian Hunter 
12999fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
13099fa2984SAdrian Hunter 		if (file_offset == -1)
13199fa2984SAdrian Hunter 			return -1;
13299fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
13399fa2984SAdrian Hunter 						     event, file_offset);
13499fa2984SAdrian Hunter 		if (err)
13599fa2984SAdrian Hunter 			return err;
13699fa2984SAdrian Hunter 	}
13799fa2984SAdrian Hunter 
138ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
139ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
140ef149c25SAdrian Hunter 	if (padding)
141ef149c25SAdrian Hunter 		padding = 8 - padding;
142ef149c25SAdrian Hunter 
143ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
144ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
145ef149c25SAdrian Hunter 	if (len2)
146ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
147ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
148ef149c25SAdrian Hunter 
149ef149c25SAdrian Hunter 	return 0;
150ef149c25SAdrian Hunter }
151ef149c25SAdrian Hunter 
152ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
153ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
154ef149c25SAdrian Hunter {
155ef149c25SAdrian Hunter 	int ret;
156ef149c25SAdrian Hunter 
157ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
158ef149c25SAdrian Hunter 				  record__process_auxtrace);
159ef149c25SAdrian Hunter 	if (ret < 0)
160ef149c25SAdrian Hunter 		return ret;
161ef149c25SAdrian Hunter 
162ef149c25SAdrian Hunter 	if (ret)
163ef149c25SAdrian Hunter 		rec->samples++;
164ef149c25SAdrian Hunter 
165ef149c25SAdrian Hunter 	return 0;
166ef149c25SAdrian Hunter }
167ef149c25SAdrian Hunter 
16886470930SIngo Molnar static volatile int done = 0;
169f7b7c26eSPeter Zijlstra static volatile int signr = -1;
17033e49ea7SAndi Kleen static volatile int child_finished = 0;
17186470930SIngo Molnar 
17286470930SIngo Molnar static void sig_handler(int sig)
17386470930SIngo Molnar {
17433e49ea7SAndi Kleen 	if (sig == SIGCHLD)
17533e49ea7SAndi Kleen 		child_finished = 1;
17645604710SNamhyung Kim 	else
17745604710SNamhyung Kim 		signr = sig;
17833e49ea7SAndi Kleen 
17986470930SIngo Molnar 	done = 1;
180f7b7c26eSPeter Zijlstra }
181f7b7c26eSPeter Zijlstra 
18245604710SNamhyung Kim static void record__sig_exit(void)
183f7b7c26eSPeter Zijlstra {
18445604710SNamhyung Kim 	if (signr == -1)
185f7b7c26eSPeter Zijlstra 		return;
186f7b7c26eSPeter Zijlstra 
187f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
18845604710SNamhyung Kim 	raise(signr);
18986470930SIngo Molnar }
19086470930SIngo Molnar 
1918c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
192dd7927f4SArnaldo Carvalho de Melo {
19356e52e85SArnaldo Carvalho de Melo 	char msg[512];
1946a4bb04cSJiri Olsa 	struct perf_evsel *pos;
195d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
196d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
197b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
1988d3eca20SDavid Ahern 	int rc = 0;
199dd7927f4SArnaldo Carvalho de Melo 
200f77a9518SArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts);
201cac21425SJiri Olsa 
2020050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
2033da297a6SIngo Molnar try_again:
2046a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
20556e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
2063da297a6SIngo Molnar 				if (verbose)
207c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
2083da297a6SIngo Molnar 				goto try_again;
2093da297a6SIngo Molnar 			}
210ca6a4258SDavid Ahern 
21156e52e85SArnaldo Carvalho de Melo 			rc = -errno;
21256e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
21356e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
21456e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
2158d3eca20SDavid Ahern 			goto out;
2167c6a1c65SPeter Zijlstra 		}
2177c6a1c65SPeter Zijlstra 	}
2187c6a1c65SPeter Zijlstra 
21923d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
22023d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
22123d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
22235550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
2238d3eca20SDavid Ahern 		rc = -1;
2248d3eca20SDavid Ahern 		goto out;
2250a102479SFrederic Weisbecker 	}
2260a102479SFrederic Weisbecker 
227ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
228ef149c25SAdrian Hunter 				 opts->auxtrace_mmap_pages, false) < 0) {
2298d3eca20SDavid Ahern 		if (errno == EPERM) {
2308d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
23118e60939SNelson Elhage 			       "Consider increasing "
23218e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
23318e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
234ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
235ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
2368d3eca20SDavid Ahern 			rc = -errno;
2378d3eca20SDavid Ahern 		} else {
23835550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
23935550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
2408d3eca20SDavid Ahern 			rc = -errno;
2418d3eca20SDavid Ahern 		}
2428d3eca20SDavid Ahern 		goto out;
24318e60939SNelson Elhage 	}
2440a27d7f9SArnaldo Carvalho de Melo 
245a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
2467b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
2478d3eca20SDavid Ahern out:
2488d3eca20SDavid Ahern 	return rc;
249a91e5431SArnaldo Carvalho de Melo }
250a91e5431SArnaldo Carvalho de Melo 
251e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
252e3d59112SNamhyung Kim 				union perf_event *event,
253e3d59112SNamhyung Kim 				struct perf_sample *sample,
254e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
255e3d59112SNamhyung Kim 				struct machine *machine)
256e3d59112SNamhyung Kim {
257e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
258e3d59112SNamhyung Kim 
259e3d59112SNamhyung Kim 	rec->samples++;
260e3d59112SNamhyung Kim 
261e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
262e3d59112SNamhyung Kim }
263e3d59112SNamhyung Kim 
2648c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
2656122e4e4SArnaldo Carvalho de Melo {
266f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
267f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
2686122e4e4SArnaldo Carvalho de Melo 
26942aa276fSNamhyung Kim 	u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
2709f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
2719f591fd7SArnaldo Carvalho de Melo 		return 0;
2729f591fd7SArnaldo Carvalho de Melo 
2734ac30cf7SNamhyung Kim 	file->size = size;
2744ac30cf7SNamhyung Kim 
27500dc8657SNamhyung Kim 	/*
27600dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
27700dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
27800dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
27900dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
28000dc8657SNamhyung Kim 	 *
28100dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
28200dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
28300dc8657SNamhyung Kim 	 */
28400dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
28500dc8657SNamhyung Kim 
286b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
2876122e4e4SArnaldo Carvalho de Melo }
2886122e4e4SArnaldo Carvalho de Melo 
2898115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
290a1645ce1SZhang, Yanmin {
291a1645ce1SZhang, Yanmin 	int err;
29245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
293a1645ce1SZhang, Yanmin 	/*
294a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
295a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
296a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
297a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
298a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
299a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
300a1645ce1SZhang, Yanmin 	 */
30145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
302743eb868SArnaldo Carvalho de Melo 					     machine);
303a1645ce1SZhang, Yanmin 	if (err < 0)
304a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
30523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
306a1645ce1SZhang, Yanmin 
307a1645ce1SZhang, Yanmin 	/*
308a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
309a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
310a1645ce1SZhang, Yanmin 	 */
31145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
3120ae617beSAdrian Hunter 						 machine);
313a1645ce1SZhang, Yanmin 	if (err < 0)
314a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
31523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
316a1645ce1SZhang, Yanmin }
317a1645ce1SZhang, Yanmin 
31898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
31998402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
32098402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
32198402807SFrederic Weisbecker };
32298402807SFrederic Weisbecker 
3238c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
32498402807SFrederic Weisbecker {
325dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
3260e2e63ddSPeter Zijlstra 	int i;
3278d3eca20SDavid Ahern 	int rc = 0;
32898402807SFrederic Weisbecker 
329d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
330ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
331ef149c25SAdrian Hunter 
3328d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
333e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
3348d3eca20SDavid Ahern 				rc = -1;
3358d3eca20SDavid Ahern 				goto out;
3368d3eca20SDavid Ahern 			}
3378d3eca20SDavid Ahern 		}
338ef149c25SAdrian Hunter 
339ef149c25SAdrian Hunter 		if (mm->base &&
340ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
341ef149c25SAdrian Hunter 			rc = -1;
342ef149c25SAdrian Hunter 			goto out;
343ef149c25SAdrian Hunter 		}
34498402807SFrederic Weisbecker 	}
34598402807SFrederic Weisbecker 
346dcabb507SJiri Olsa 	/*
347dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
348dcabb507SJiri Olsa 	 * at least one event.
349dcabb507SJiri Olsa 	 */
350dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
3518c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
3528d3eca20SDavid Ahern 
3538d3eca20SDavid Ahern out:
3548d3eca20SDavid Ahern 	return rc;
35598402807SFrederic Weisbecker }
35698402807SFrederic Weisbecker 
3578c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
35857706abcSDavid Ahern {
35957706abcSDavid Ahern 	struct perf_session *session = rec->session;
36057706abcSDavid Ahern 	int feat;
36157706abcSDavid Ahern 
36257706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
36357706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
36457706abcSDavid Ahern 
36557706abcSDavid Ahern 	if (rec->no_buildid)
36657706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
36757706abcSDavid Ahern 
3683e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
36957706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
37057706abcSDavid Ahern 
37157706abcSDavid Ahern 	if (!rec->opts.branch_stack)
37257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
373ef149c25SAdrian Hunter 
374ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
375ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
37657706abcSDavid Ahern }
37757706abcSDavid Ahern 
378f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
379f33cbe72SArnaldo Carvalho de Melo 
380f33cbe72SArnaldo Carvalho de Melo /*
381f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
382f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
383f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
384f33cbe72SArnaldo Carvalho de Melo  */
38545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
38645604710SNamhyung Kim 					siginfo_t *info,
387f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
388f33cbe72SArnaldo Carvalho de Melo {
389f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
390f33cbe72SArnaldo Carvalho de Melo 	done = 1;
391f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
392f33cbe72SArnaldo Carvalho de Melo }
393f33cbe72SArnaldo Carvalho de Melo 
3948c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
39586470930SIngo Molnar {
39657706abcSDavid Ahern 	int err;
39745604710SNamhyung Kim 	int status = 0;
3988b412664SPeter Zijlstra 	unsigned long waking = 0;
39946be604bSZhang, Yanmin 	const bool forks = argc > 0;
40023346f21SArnaldo Carvalho de Melo 	struct machine *machine;
40145694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
402b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
403f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
404d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
4056dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
40642aa276fSNamhyung Kim 	int fd;
40786470930SIngo Molnar 
408d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
40933e49ea7SAndi Kleen 
41045604710SNamhyung Kim 	atexit(record__sig_exit);
411f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
412f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
413804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
414f5970550SPeter Zijlstra 
415b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
41694c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
417ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
418a9a70bbcSArnaldo Carvalho de Melo 		return -1;
419a9a70bbcSArnaldo Carvalho de Melo 	}
420a9a70bbcSArnaldo Carvalho de Melo 
42142aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
422d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
423d20deb64SArnaldo Carvalho de Melo 
4248c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
425330aa675SStephane Eranian 
426d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
4273e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
428f5fc1412SJiri Olsa 						    argv, file->is_pipe,
429735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
43035b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
43135b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
43245604710SNamhyung Kim 			status = err;
43335b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
434856e9660SPeter Zijlstra 		}
435856e9660SPeter Zijlstra 	}
436856e9660SPeter Zijlstra 
4378c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
4388d3eca20SDavid Ahern 		err = -1;
43945604710SNamhyung Kim 		goto out_child;
4408d3eca20SDavid Ahern 	}
44186470930SIngo Molnar 
4423e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
443a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
444a8bb559bSNamhyung Kim 
445f5fc1412SJiri Olsa 	if (file->is_pipe) {
44642aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
447529870e3STom Zanussi 		if (err < 0)
44845604710SNamhyung Kim 			goto out_child;
449563aecb2SJiri Olsa 	} else {
45042aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
451d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
45245604710SNamhyung Kim 			goto out_child;
453d5eed904SArnaldo Carvalho de Melo 	}
4547c6a1c65SPeter Zijlstra 
455d3665498SDavid Ahern 	if (!rec->no_buildid
456e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
457d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
458e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
4598d3eca20SDavid Ahern 		err = -1;
46045604710SNamhyung Kim 		goto out_child;
461e20960c0SRobert Richter 	}
462e20960c0SRobert Richter 
46334ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
464743eb868SArnaldo Carvalho de Melo 
465f5fc1412SJiri Olsa 	if (file->is_pipe) {
46645694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
467a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
4682c46dbb5STom Zanussi 		if (err < 0) {
4692c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
47045604710SNamhyung Kim 			goto out_child;
4712c46dbb5STom Zanussi 		}
472cd19a035STom Zanussi 
4733e2be2daSArnaldo Carvalho de Melo 		if (have_tracepoints(&rec->evlist->entries)) {
47463e0c771STom Zanussi 			/*
47563e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
47663e0c771STom Zanussi 			 * there were no tracepoints so its not really
47763e0c771STom Zanussi 			 * an error, just that we don't need to
47863e0c771STom Zanussi 			 * synthesize anything.  We really have to
47963e0c771STom Zanussi 			 * return this more properly and also
48063e0c771STom Zanussi 			 * propagate errors that now are calling die()
48163e0c771STom Zanussi 			 */
48242aa276fSNamhyung Kim 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
483743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
48463e0c771STom Zanussi 			if (err <= 0) {
48563e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
48645604710SNamhyung Kim 				goto out_child;
48763e0c771STom Zanussi 			}
488f34b9001SDavid Ahern 			rec->bytes_written += err;
4892c46dbb5STom Zanussi 		}
49063e0c771STom Zanussi 	}
4912c46dbb5STom Zanussi 
492ef149c25SAdrian Hunter 	if (rec->opts.full_auxtrace) {
493ef149c25SAdrian Hunter 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
494ef149c25SAdrian Hunter 					session, process_synthesized_event);
495ef149c25SAdrian Hunter 		if (err)
496ef149c25SAdrian Hunter 			goto out_delete_session;
497ef149c25SAdrian Hunter 	}
498ef149c25SAdrian Hunter 
49945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
5000ae617beSAdrian Hunter 						 machine);
501c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
502c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
503c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
504c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
50556b03f3cSArnaldo Carvalho de Melo 
50645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
507743eb868SArnaldo Carvalho de Melo 					     machine);
508c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
509c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
510c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
511c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
512c1a3a4b9SArnaldo Carvalho de Melo 
5137e383de4SArnaldo Carvalho de Melo 	if (perf_guest) {
514876650e6SArnaldo Carvalho de Melo 		machines__process_guests(&session->machines,
5157e383de4SArnaldo Carvalho de Melo 					 perf_event__synthesize_guest_os, tool);
5167e383de4SArnaldo Carvalho de Melo 	}
517b7cece76SArnaldo Carvalho de Melo 
5183e2be2daSArnaldo Carvalho de Melo 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
51958d925dcSArnaldo Carvalho de Melo 					    process_synthesized_event, opts->sample_address);
5208d3eca20SDavid Ahern 	if (err != 0)
52145604710SNamhyung Kim 		goto out_child;
5228d3eca20SDavid Ahern 
523d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
52486470930SIngo Molnar 		struct sched_param param;
52586470930SIngo Molnar 
526d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
52786470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
5286beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
5298d3eca20SDavid Ahern 			err = -1;
53045604710SNamhyung Kim 			goto out_child;
53186470930SIngo Molnar 		}
53286470930SIngo Molnar 	}
53386470930SIngo Molnar 
534774cb499SJiri Olsa 	/*
535774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
536774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
537774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
538774cb499SJiri Olsa 	 */
5396619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
5403e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
541764e16a3SDavid Ahern 
542856e9660SPeter Zijlstra 	/*
543856e9660SPeter Zijlstra 	 * Let the child rip
544856e9660SPeter Zijlstra 	 */
545735f7e0bSArnaldo Carvalho de Melo 	if (forks)
5463e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
547856e9660SPeter Zijlstra 
5486619a53eSAndi Kleen 	if (opts->initial_delay) {
5496619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
5506619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
5516619a53eSAndi Kleen 	}
5526619a53eSAndi Kleen 
553649c48a9SPeter Zijlstra 	for (;;) {
554d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
55586470930SIngo Molnar 
5568c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
5578d3eca20SDavid Ahern 			err = -1;
55845604710SNamhyung Kim 			goto out_child;
5598d3eca20SDavid Ahern 		}
56086470930SIngo Molnar 
561d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
5626dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
563649c48a9SPeter Zijlstra 				break;
564f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
565a515114fSJiri Olsa 			/*
566a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
567a515114fSJiri Olsa 			 * number of returned events and interrupt error.
568a515114fSJiri Olsa 			 */
569a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
57045604710SNamhyung Kim 				err = 0;
5718b412664SPeter Zijlstra 			waking++;
5726dcf45efSArnaldo Carvalho de Melo 
5736dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
5746dcf45efSArnaldo Carvalho de Melo 				draining = true;
5758b412664SPeter Zijlstra 		}
5768b412664SPeter Zijlstra 
577774cb499SJiri Olsa 		/*
578774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
579774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
580774cb499SJiri Olsa 		 * disable events in this case.
581774cb499SJiri Olsa 		 */
582602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
5833e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
5842711926aSJiri Olsa 			disabled = true;
5852711926aSJiri Olsa 		}
5868b412664SPeter Zijlstra 	}
5878b412664SPeter Zijlstra 
588f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
58935550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
590f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
591f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
592f33cbe72SArnaldo Carvalho de Melo 		err = -1;
59345604710SNamhyung Kim 		goto out_child;
594f33cbe72SArnaldo Carvalho de Melo 	}
595f33cbe72SArnaldo Carvalho de Melo 
596e3d59112SNamhyung Kim 	if (!quiet)
5978b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
59886470930SIngo Molnar 
59945604710SNamhyung Kim out_child:
60045604710SNamhyung Kim 	if (forks) {
60145604710SNamhyung Kim 		int exit_status;
60245604710SNamhyung Kim 
60345604710SNamhyung Kim 		if (!child_finished)
60445604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
60545604710SNamhyung Kim 
60645604710SNamhyung Kim 		wait(&exit_status);
60745604710SNamhyung Kim 
60845604710SNamhyung Kim 		if (err < 0)
60945604710SNamhyung Kim 			status = err;
61045604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
61145604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
61245604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
61345604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
61445604710SNamhyung Kim 	} else
61545604710SNamhyung Kim 		status = err;
61645604710SNamhyung Kim 
617e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
618e3d59112SNamhyung Kim 	rec->samples = 0;
619e3d59112SNamhyung Kim 
62045604710SNamhyung Kim 	if (!err && !file->is_pipe) {
62145604710SNamhyung Kim 		rec->session->header.data_size += rec->bytes_written;
62245604710SNamhyung Kim 
623*cd10b289SAdrian Hunter 		if (!rec->no_buildid) {
62445604710SNamhyung Kim 			process_buildids(rec);
625*cd10b289SAdrian Hunter 			/*
626*cd10b289SAdrian Hunter 			 * We take all buildids when the file contains
627*cd10b289SAdrian Hunter 			 * AUX area tracing data because we do not decode the
628*cd10b289SAdrian Hunter 			 * trace because it would take too long.
629*cd10b289SAdrian Hunter 			 */
630*cd10b289SAdrian Hunter 			if (rec->opts.full_auxtrace)
631*cd10b289SAdrian Hunter 				dsos__hit_all(rec->session);
632*cd10b289SAdrian Hunter 		}
63342aa276fSNamhyung Kim 		perf_session__write_header(rec->session, rec->evlist, fd, true);
63445604710SNamhyung Kim 	}
63539d17dacSArnaldo Carvalho de Melo 
636e3d59112SNamhyung Kim 	if (!err && !quiet) {
637e3d59112SNamhyung Kim 		char samples[128];
638e3d59112SNamhyung Kim 
639ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
640e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
641e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
642e3d59112SNamhyung Kim 		else
643e3d59112SNamhyung Kim 			samples[0] = '\0';
644e3d59112SNamhyung Kim 
645e3d59112SNamhyung Kim 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s ]\n",
646e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
647e3d59112SNamhyung Kim 			file->path, samples);
648e3d59112SNamhyung Kim 	}
649e3d59112SNamhyung Kim 
65039d17dacSArnaldo Carvalho de Melo out_delete_session:
65139d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
65245604710SNamhyung Kim 	return status;
65386470930SIngo Molnar }
65486470930SIngo Molnar 
655bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
656bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
657bdfebd84SRoberto Agostino Vitillo 
658bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
659bdfebd84SRoberto Agostino Vitillo 
660bdfebd84SRoberto Agostino Vitillo struct branch_mode {
661bdfebd84SRoberto Agostino Vitillo 	const char *name;
662bdfebd84SRoberto Agostino Vitillo 	int mode;
663bdfebd84SRoberto Agostino Vitillo };
664bdfebd84SRoberto Agostino Vitillo 
665bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
666bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
667bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
668bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
669bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
670bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
671bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
672bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
6730126d493SAndi Kleen 	BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
6740126d493SAndi Kleen 	BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
6750126d493SAndi Kleen 	BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
6760fffa5dfSAnshuman Khandual 	BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
677bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
678bdfebd84SRoberto Agostino Vitillo };
679bdfebd84SRoberto Agostino Vitillo 
680bdfebd84SRoberto Agostino Vitillo static int
681a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
682bdfebd84SRoberto Agostino Vitillo {
683bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
684bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
685bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
686bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
687bdfebd84SRoberto Agostino Vitillo 
688bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
689bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
690a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
691bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
692bdfebd84SRoberto Agostino Vitillo 
693a5aabdacSStephane Eranian 	if (unset)
694a5aabdacSStephane Eranian 		return 0;
695bdfebd84SRoberto Agostino Vitillo 
696a5aabdacSStephane Eranian 	/*
697a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
698a5aabdacSStephane Eranian 	 */
699a5aabdacSStephane Eranian 	if (*mode)
700a5aabdacSStephane Eranian 		return -1;
701a5aabdacSStephane Eranian 
702a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
703a5aabdacSStephane Eranian 	if (str) {
704bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
705bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
706bdfebd84SRoberto Agostino Vitillo 		if (!s)
707bdfebd84SRoberto Agostino Vitillo 			return -1;
708bdfebd84SRoberto Agostino Vitillo 
709bdfebd84SRoberto Agostino Vitillo 		for (;;) {
710bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
711bdfebd84SRoberto Agostino Vitillo 			if (p)
712bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
713bdfebd84SRoberto Agostino Vitillo 
714bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
715bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
716bdfebd84SRoberto Agostino Vitillo 					break;
717bdfebd84SRoberto Agostino Vitillo 			}
718a5aabdacSStephane Eranian 			if (!br->name) {
719a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
720a5aabdacSStephane Eranian 					    " check man page\n", s);
721bdfebd84SRoberto Agostino Vitillo 				goto error;
722a5aabdacSStephane Eranian 			}
723bdfebd84SRoberto Agostino Vitillo 
724bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
725bdfebd84SRoberto Agostino Vitillo 
726bdfebd84SRoberto Agostino Vitillo 			if (!p)
727bdfebd84SRoberto Agostino Vitillo 				break;
728bdfebd84SRoberto Agostino Vitillo 
729bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
730bdfebd84SRoberto Agostino Vitillo 		}
731a5aabdacSStephane Eranian 	}
732bdfebd84SRoberto Agostino Vitillo 	ret = 0;
733bdfebd84SRoberto Agostino Vitillo 
734a5aabdacSStephane Eranian 	/* default to any branch */
735bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
736a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
737bdfebd84SRoberto Agostino Vitillo 	}
738bdfebd84SRoberto Agostino Vitillo error:
739bdfebd84SRoberto Agostino Vitillo 	free(os);
740bdfebd84SRoberto Agostino Vitillo 	return ret;
741bdfebd84SRoberto Agostino Vitillo }
742bdfebd84SRoberto Agostino Vitillo 
74372a128aaSNamhyung Kim static void callchain_debug(void)
74409b0fd45SJiri Olsa {
745aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
746a601fdffSJiri Olsa 
74772a128aaSNamhyung Kim 	pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
74826d33022SJiri Olsa 
74972a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_DWARF)
75009b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
75172a128aaSNamhyung Kim 			 callchain_param.dump_size);
75209b0fd45SJiri Olsa }
75309b0fd45SJiri Olsa 
75472a128aaSNamhyung Kim int record_parse_callchain_opt(const struct option *opt __maybe_unused,
75509b0fd45SJiri Olsa 			       const char *arg,
75609b0fd45SJiri Olsa 			       int unset)
75709b0fd45SJiri Olsa {
75809b0fd45SJiri Olsa 	int ret;
75909b0fd45SJiri Olsa 
76072a128aaSNamhyung Kim 	callchain_param.enabled = !unset;
761eb853e80SJiri Olsa 
76209b0fd45SJiri Olsa 	/* --no-call-graph */
76309b0fd45SJiri Olsa 	if (unset) {
76472a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_NONE;
76509b0fd45SJiri Olsa 		pr_debug("callchain: disabled\n");
76609b0fd45SJiri Olsa 		return 0;
76709b0fd45SJiri Olsa 	}
76809b0fd45SJiri Olsa 
769f7f084f4SNamhyung Kim 	ret = parse_callchain_record_opt(arg);
77009b0fd45SJiri Olsa 	if (!ret)
77172a128aaSNamhyung Kim 		callchain_debug();
77209b0fd45SJiri Olsa 
77326d33022SJiri Olsa 	return ret;
77426d33022SJiri Olsa }
77526d33022SJiri Olsa 
77672a128aaSNamhyung Kim int record_callchain_opt(const struct option *opt __maybe_unused,
77709b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
77809b0fd45SJiri Olsa 			 int unset __maybe_unused)
77909b0fd45SJiri Olsa {
78072a128aaSNamhyung Kim 	callchain_param.enabled = true;
78109b0fd45SJiri Olsa 
78272a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_NONE)
78372a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_FP;
784eb853e80SJiri Olsa 
78572a128aaSNamhyung Kim 	callchain_debug();
78609b0fd45SJiri Olsa 	return 0;
78709b0fd45SJiri Olsa }
78809b0fd45SJiri Olsa 
789eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
790eb853e80SJiri Olsa {
791eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
7925a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
793eb853e80SJiri Olsa 
794eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
795eb853e80SJiri Olsa }
796eb853e80SJiri Olsa 
797814c8c38SPeter Zijlstra struct clockid_map {
798814c8c38SPeter Zijlstra 	const char *name;
799814c8c38SPeter Zijlstra 	int clockid;
800814c8c38SPeter Zijlstra };
801814c8c38SPeter Zijlstra 
802814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
803814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
804814c8c38SPeter Zijlstra 
805814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
806814c8c38SPeter Zijlstra 
807814c8c38SPeter Zijlstra 
808814c8c38SPeter Zijlstra /*
809814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
810814c8c38SPeter Zijlstra  */
811814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
812814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
813814c8c38SPeter Zijlstra #endif
814814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
815814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
816814c8c38SPeter Zijlstra #endif
817814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
818814c8c38SPeter Zijlstra #define CLOCK_TAI 11
819814c8c38SPeter Zijlstra #endif
820814c8c38SPeter Zijlstra 
821814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
822814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
823814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
824814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
825814c8c38SPeter Zijlstra 
826814c8c38SPeter Zijlstra 	/* available for some events */
827814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
828814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
829814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
830814c8c38SPeter Zijlstra 
831814c8c38SPeter Zijlstra 	/* available for the lazy */
832814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
833814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
834814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
835814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
836814c8c38SPeter Zijlstra 
837814c8c38SPeter Zijlstra 	CLOCKID_END,
838814c8c38SPeter Zijlstra };
839814c8c38SPeter Zijlstra 
840814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
841814c8c38SPeter Zijlstra {
842814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
843814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
844814c8c38SPeter Zijlstra 	const char *ostr = str;
845814c8c38SPeter Zijlstra 
846814c8c38SPeter Zijlstra 	if (unset) {
847814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
848814c8c38SPeter Zijlstra 		return 0;
849814c8c38SPeter Zijlstra 	}
850814c8c38SPeter Zijlstra 
851814c8c38SPeter Zijlstra 	/* no arg passed */
852814c8c38SPeter Zijlstra 	if (!str)
853814c8c38SPeter Zijlstra 		return 0;
854814c8c38SPeter Zijlstra 
855814c8c38SPeter Zijlstra 	/* no setting it twice */
856814c8c38SPeter Zijlstra 	if (opts->use_clockid)
857814c8c38SPeter Zijlstra 		return -1;
858814c8c38SPeter Zijlstra 
859814c8c38SPeter Zijlstra 	opts->use_clockid = true;
860814c8c38SPeter Zijlstra 
861814c8c38SPeter Zijlstra 	/* if its a number, we're done */
862814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
863814c8c38SPeter Zijlstra 		return 0;
864814c8c38SPeter Zijlstra 
865814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
866814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
867814c8c38SPeter Zijlstra 		str += 6;
868814c8c38SPeter Zijlstra 
869814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
870814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
871814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
872814c8c38SPeter Zijlstra 			return 0;
873814c8c38SPeter Zijlstra 		}
874814c8c38SPeter Zijlstra 	}
875814c8c38SPeter Zijlstra 
876814c8c38SPeter Zijlstra 	opts->use_clockid = false;
877814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
878814c8c38SPeter Zijlstra 	return -1;
879814c8c38SPeter Zijlstra }
880814c8c38SPeter Zijlstra 
881e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
882e9db1310SAdrian Hunter 				    const char *str,
883e9db1310SAdrian Hunter 				    int unset __maybe_unused)
884e9db1310SAdrian Hunter {
885e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
886e9db1310SAdrian Hunter 	char *s, *p;
887e9db1310SAdrian Hunter 	unsigned int mmap_pages;
888e9db1310SAdrian Hunter 	int ret;
889e9db1310SAdrian Hunter 
890e9db1310SAdrian Hunter 	if (!str)
891e9db1310SAdrian Hunter 		return -EINVAL;
892e9db1310SAdrian Hunter 
893e9db1310SAdrian Hunter 	s = strdup(str);
894e9db1310SAdrian Hunter 	if (!s)
895e9db1310SAdrian Hunter 		return -ENOMEM;
896e9db1310SAdrian Hunter 
897e9db1310SAdrian Hunter 	p = strchr(s, ',');
898e9db1310SAdrian Hunter 	if (p)
899e9db1310SAdrian Hunter 		*p = '\0';
900e9db1310SAdrian Hunter 
901e9db1310SAdrian Hunter 	if (*s) {
902e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
903e9db1310SAdrian Hunter 		if (ret)
904e9db1310SAdrian Hunter 			goto out_free;
905e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
906e9db1310SAdrian Hunter 	}
907e9db1310SAdrian Hunter 
908e9db1310SAdrian Hunter 	if (!p) {
909e9db1310SAdrian Hunter 		ret = 0;
910e9db1310SAdrian Hunter 		goto out_free;
911e9db1310SAdrian Hunter 	}
912e9db1310SAdrian Hunter 
913e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
914e9db1310SAdrian Hunter 	if (ret)
915e9db1310SAdrian Hunter 		goto out_free;
916e9db1310SAdrian Hunter 
917e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
918e9db1310SAdrian Hunter 
919e9db1310SAdrian Hunter out_free:
920e9db1310SAdrian Hunter 	free(s);
921e9db1310SAdrian Hunter 	return ret;
922e9db1310SAdrian Hunter }
923e9db1310SAdrian Hunter 
924e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
92586470930SIngo Molnar 	"perf record [<options>] [<command>]",
92686470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
92786470930SIngo Molnar 	NULL
92886470930SIngo Molnar };
929e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
93086470930SIngo Molnar 
931d20deb64SArnaldo Carvalho de Melo /*
9328c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
9338c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
934d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
935d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
936d20deb64SArnaldo Carvalho de Melo  *
937d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
938d20deb64SArnaldo Carvalho de Melo  *
939d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
940d20deb64SArnaldo Carvalho de Melo  */
9418c6f45a7SArnaldo Carvalho de Melo static struct record record = {
942d20deb64SArnaldo Carvalho de Melo 	.opts = {
9438affc2b8SAndi Kleen 		.sample_time	     = true,
944d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
945d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
946d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
947447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
948d1cb9fceSNamhyung Kim 		.target		     = {
949d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
9503aa5939dSAdrian Hunter 			.default_per_cpu = true,
951d1cb9fceSNamhyung Kim 		},
952d20deb64SArnaldo Carvalho de Melo 	},
953e3d59112SNamhyung Kim 	.tool = {
954e3d59112SNamhyung Kim 		.sample		= process_sample_event,
955e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
956e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
957e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
958e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
959e3d59112SNamhyung Kim 	},
960d20deb64SArnaldo Carvalho de Melo };
9617865e817SFrederic Weisbecker 
96209b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
96361eaa3beSArnaldo Carvalho de Melo 
9649ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT
965aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
96661eaa3beSArnaldo Carvalho de Melo #else
967aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
96861eaa3beSArnaldo Carvalho de Melo #endif
96961eaa3beSArnaldo Carvalho de Melo 
970d20deb64SArnaldo Carvalho de Melo /*
971d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
972d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
973b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
974d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
975d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
976d20deb64SArnaldo Carvalho de Melo  */
977e5b2c207SNamhyung Kim struct option __record_options[] = {
978d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
97986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
980f120f9d5SJiri Olsa 		     parse_events_option),
981d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
982c171b552SLi Zefan 		     "event filter", parse_filter),
983bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
984d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
985bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
986d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
987d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
98886470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
989509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
990acac03faSKirill Smelkov 		    "collect data without buffering"),
991d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
992daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
993bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
99486470930SIngo Molnar 			    "system-wide collection from all CPUs"),
995bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
996c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
997d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
998f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
99986470930SIngo Molnar 		    "output file name"),
100069e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
100169e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
10022e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1003d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1004e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1005e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1006e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1007d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
100843bece79SLin Ming 		    "put the counters into a counter group"),
100909b0fd45SJiri Olsa 	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
101009b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
101109b0fd45SJiri Olsa 			   &record_callchain_opt),
101209b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
101375d9a108SArnaldo Carvalho de Melo 		     "mode[,dump_size]", record_callchain_help,
101409b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1015c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
10163da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1017b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1018d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1019649c48a9SPeter Zijlstra 		    "per thread counts"),
1020d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
10214bba828dSAnton Blanchard 		    "Sample addresses"),
1022d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
10233e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
1024d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1025649c48a9SPeter Zijlstra 		    "don't sample"),
1026d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
1027a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
1028d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
1029baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
1030d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1031023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1032023695d9SStephane Eranian 		     parse_cgroups),
1033a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
10346619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1035bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1036bea03405SNamhyung Kim 		   "user to profile"),
1037a5aabdacSStephane Eranian 
1038a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1039a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1040a5aabdacSStephane Eranian 		     parse_branch_stack),
1041a5aabdacSStephane Eranian 
1042a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1043a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1044bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
104505484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
104605484298SAndi Kleen 		    "sample by weight (on special events only)"),
1047475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1048475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
10493aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
10503aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
10514b6c5177SStephane Eranian 	OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
10524b6c5177SStephane Eranian 		    "Sample machine registers on interrupt"),
105385c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
105485c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1055814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1056814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1057814c8c38SPeter Zijlstra 	parse_clockid),
105886470930SIngo Molnar 	OPT_END()
105986470930SIngo Molnar };
106086470930SIngo Molnar 
1061e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1062e5b2c207SNamhyung Kim 
10631d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
106486470930SIngo Molnar {
1065ef149c25SAdrian Hunter 	int err;
10668c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
106716ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
106886470930SIngo Molnar 
10693e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
10703e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1071361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1072361c99a6SArnaldo Carvalho de Melo 
1073eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1074eb853e80SJiri Olsa 
1075bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1076a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1077602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1078bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
107986470930SIngo Molnar 
1080bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
10813780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
1082023695d9SStephane Eranian 			  " system-wide mode\n");
1083023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
1084023695d9SStephane Eranian 	}
1085023695d9SStephane Eranian 
1086ef149c25SAdrian Hunter 	if (!rec->itr) {
1087ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1088ef149c25SAdrian Hunter 		if (err)
1089ef149c25SAdrian Hunter 			return err;
1090ef149c25SAdrian Hunter 	}
1091ef149c25SAdrian Hunter 
1092ef149c25SAdrian Hunter 	err = -ENOMEM;
1093ef149c25SAdrian Hunter 
10940a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1095baa2f6ceSArnaldo Carvalho de Melo 
1096ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1097646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1098646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1099ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1100646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1101646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1102646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1103646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1104646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1105ec80fde7SArnaldo Carvalho de Melo 
1106d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1107a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1108655000e7SArnaldo Carvalho de Melo 
11093e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
11103e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
111169aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
111269aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1113bbd36e5eSPeter Zijlstra 	}
111486470930SIngo Molnar 
111569e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
111669e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
111769e7e5b0SAdrian Hunter 
1118602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
111916ad2ffbSNamhyung Kim 	if (err) {
1120602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
112116ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
112216ad2ffbSNamhyung Kim 	}
11234bd0f2d2SNamhyung Kim 
1124602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
112516ad2ffbSNamhyung Kim 	if (err) {
112616ad2ffbSNamhyung Kim 		int saved_errno = errno;
112716ad2ffbSNamhyung Kim 
1128602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
11293780f488SNamhyung Kim 		ui__error("%s", errbuf);
113016ad2ffbSNamhyung Kim 
113116ad2ffbSNamhyung Kim 		err = -saved_errno;
11328fa60e1fSNamhyung Kim 		goto out_symbol_exit;
113316ad2ffbSNamhyung Kim 	}
11340d37aa34SArnaldo Carvalho de Melo 
113516ad2ffbSNamhyung Kim 	err = -ENOMEM;
11363e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1137dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
113869aad6f1SArnaldo Carvalho de Melo 
1139ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1140ef149c25SAdrian Hunter 	if (err)
1141ef149c25SAdrian Hunter 		goto out_symbol_exit;
1142ef149c25SAdrian Hunter 
1143b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
114439d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
114503ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
11467e4ff9e3SMike Galbraith 	}
11477e4ff9e3SMike Galbraith 
1148d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1149d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
115045604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1151d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1152ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
115339d17dacSArnaldo Carvalho de Melo 	return err;
115486470930SIngo Molnar }
1155