xref: /openbmc/linux/tools/perf/builtin-record.c (revision ef149c2548b82e75f7f9d138457ef4dc4ed97448)
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"
30*ef149c25SAdrian 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;
42*ef149c25SAdrian 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 
115*ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
116*ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
117*ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
118*ef149c25SAdrian Hunter {
119*ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
120*ef149c25SAdrian Hunter 	size_t padding;
121*ef149c25SAdrian Hunter 	u8 pad[8] = {0};
122*ef149c25SAdrian Hunter 
123*ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
124*ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
125*ef149c25SAdrian Hunter 	if (padding)
126*ef149c25SAdrian Hunter 		padding = 8 - padding;
127*ef149c25SAdrian Hunter 
128*ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
129*ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
130*ef149c25SAdrian Hunter 	if (len2)
131*ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
132*ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
133*ef149c25SAdrian Hunter 
134*ef149c25SAdrian Hunter 	return 0;
135*ef149c25SAdrian Hunter }
136*ef149c25SAdrian Hunter 
137*ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
138*ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
139*ef149c25SAdrian Hunter {
140*ef149c25SAdrian Hunter 	int ret;
141*ef149c25SAdrian Hunter 
142*ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
143*ef149c25SAdrian Hunter 				  record__process_auxtrace);
144*ef149c25SAdrian Hunter 	if (ret < 0)
145*ef149c25SAdrian Hunter 		return ret;
146*ef149c25SAdrian Hunter 
147*ef149c25SAdrian Hunter 	if (ret)
148*ef149c25SAdrian Hunter 		rec->samples++;
149*ef149c25SAdrian Hunter 
150*ef149c25SAdrian Hunter 	return 0;
151*ef149c25SAdrian Hunter }
152*ef149c25SAdrian Hunter 
15386470930SIngo Molnar static volatile int done = 0;
154f7b7c26eSPeter Zijlstra static volatile int signr = -1;
15533e49ea7SAndi Kleen static volatile int child_finished = 0;
15686470930SIngo Molnar 
15786470930SIngo Molnar static void sig_handler(int sig)
15886470930SIngo Molnar {
15933e49ea7SAndi Kleen 	if (sig == SIGCHLD)
16033e49ea7SAndi Kleen 		child_finished = 1;
16145604710SNamhyung Kim 	else
16245604710SNamhyung Kim 		signr = sig;
16333e49ea7SAndi Kleen 
16486470930SIngo Molnar 	done = 1;
165f7b7c26eSPeter Zijlstra }
166f7b7c26eSPeter Zijlstra 
16745604710SNamhyung Kim static void record__sig_exit(void)
168f7b7c26eSPeter Zijlstra {
16945604710SNamhyung Kim 	if (signr == -1)
170f7b7c26eSPeter Zijlstra 		return;
171f7b7c26eSPeter Zijlstra 
172f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
17345604710SNamhyung Kim 	raise(signr);
17486470930SIngo Molnar }
17586470930SIngo Molnar 
1768c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
177dd7927f4SArnaldo Carvalho de Melo {
17856e52e85SArnaldo Carvalho de Melo 	char msg[512];
1796a4bb04cSJiri Olsa 	struct perf_evsel *pos;
180d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
181d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
182b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
1838d3eca20SDavid Ahern 	int rc = 0;
184dd7927f4SArnaldo Carvalho de Melo 
185f77a9518SArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts);
186cac21425SJiri Olsa 
1870050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
1883da297a6SIngo Molnar try_again:
1896a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
19056e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
1913da297a6SIngo Molnar 				if (verbose)
192c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
1933da297a6SIngo Molnar 				goto try_again;
1943da297a6SIngo Molnar 			}
195ca6a4258SDavid Ahern 
19656e52e85SArnaldo Carvalho de Melo 			rc = -errno;
19756e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
19856e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
19956e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
2008d3eca20SDavid Ahern 			goto out;
2017c6a1c65SPeter Zijlstra 		}
2027c6a1c65SPeter Zijlstra 	}
2037c6a1c65SPeter Zijlstra 
20423d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
20523d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
20623d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
20735550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
2088d3eca20SDavid Ahern 		rc = -1;
2098d3eca20SDavid Ahern 		goto out;
2100a102479SFrederic Weisbecker 	}
2110a102479SFrederic Weisbecker 
212*ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
213*ef149c25SAdrian Hunter 				 opts->auxtrace_mmap_pages, false) < 0) {
2148d3eca20SDavid Ahern 		if (errno == EPERM) {
2158d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
21618e60939SNelson Elhage 			       "Consider increasing "
21718e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
21818e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
219*ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
220*ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
2218d3eca20SDavid Ahern 			rc = -errno;
2228d3eca20SDavid Ahern 		} else {
22335550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
22435550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
2258d3eca20SDavid Ahern 			rc = -errno;
2268d3eca20SDavid Ahern 		}
2278d3eca20SDavid Ahern 		goto out;
22818e60939SNelson Elhage 	}
2290a27d7f9SArnaldo Carvalho de Melo 
230a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
2317b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
2328d3eca20SDavid Ahern out:
2338d3eca20SDavid Ahern 	return rc;
234a91e5431SArnaldo Carvalho de Melo }
235a91e5431SArnaldo Carvalho de Melo 
236e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
237e3d59112SNamhyung Kim 				union perf_event *event,
238e3d59112SNamhyung Kim 				struct perf_sample *sample,
239e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
240e3d59112SNamhyung Kim 				struct machine *machine)
241e3d59112SNamhyung Kim {
242e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
243e3d59112SNamhyung Kim 
244e3d59112SNamhyung Kim 	rec->samples++;
245e3d59112SNamhyung Kim 
246e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
247e3d59112SNamhyung Kim }
248e3d59112SNamhyung Kim 
2498c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
2506122e4e4SArnaldo Carvalho de Melo {
251f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
252f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
2536122e4e4SArnaldo Carvalho de Melo 
25442aa276fSNamhyung Kim 	u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
2559f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
2569f591fd7SArnaldo Carvalho de Melo 		return 0;
2579f591fd7SArnaldo Carvalho de Melo 
2584ac30cf7SNamhyung Kim 	file->size = size;
2594ac30cf7SNamhyung Kim 
26000dc8657SNamhyung Kim 	/*
26100dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
26200dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
26300dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
26400dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
26500dc8657SNamhyung Kim 	 *
26600dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
26700dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
26800dc8657SNamhyung Kim 	 */
26900dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
27000dc8657SNamhyung Kim 
271b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
2726122e4e4SArnaldo Carvalho de Melo }
2736122e4e4SArnaldo Carvalho de Melo 
2748115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
275a1645ce1SZhang, Yanmin {
276a1645ce1SZhang, Yanmin 	int err;
27745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
278a1645ce1SZhang, Yanmin 	/*
279a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
280a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
281a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
282a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
283a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
284a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
285a1645ce1SZhang, Yanmin 	 */
28645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
287743eb868SArnaldo Carvalho de Melo 					     machine);
288a1645ce1SZhang, Yanmin 	if (err < 0)
289a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
29023346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
291a1645ce1SZhang, Yanmin 
292a1645ce1SZhang, Yanmin 	/*
293a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
294a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
295a1645ce1SZhang, Yanmin 	 */
29645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
2970ae617beSAdrian Hunter 						 machine);
298a1645ce1SZhang, Yanmin 	if (err < 0)
299a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
30023346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
301a1645ce1SZhang, Yanmin }
302a1645ce1SZhang, Yanmin 
30398402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
30498402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
30598402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
30698402807SFrederic Weisbecker };
30798402807SFrederic Weisbecker 
3088c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
30998402807SFrederic Weisbecker {
310dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
3110e2e63ddSPeter Zijlstra 	int i;
3128d3eca20SDavid Ahern 	int rc = 0;
31398402807SFrederic Weisbecker 
314d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
315*ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
316*ef149c25SAdrian Hunter 
3178d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
318e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
3198d3eca20SDavid Ahern 				rc = -1;
3208d3eca20SDavid Ahern 				goto out;
3218d3eca20SDavid Ahern 			}
3228d3eca20SDavid Ahern 		}
323*ef149c25SAdrian Hunter 
324*ef149c25SAdrian Hunter 		if (mm->base &&
325*ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
326*ef149c25SAdrian Hunter 			rc = -1;
327*ef149c25SAdrian Hunter 			goto out;
328*ef149c25SAdrian Hunter 		}
32998402807SFrederic Weisbecker 	}
33098402807SFrederic Weisbecker 
331dcabb507SJiri Olsa 	/*
332dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
333dcabb507SJiri Olsa 	 * at least one event.
334dcabb507SJiri Olsa 	 */
335dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
3368c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
3378d3eca20SDavid Ahern 
3388d3eca20SDavid Ahern out:
3398d3eca20SDavid Ahern 	return rc;
34098402807SFrederic Weisbecker }
34198402807SFrederic Weisbecker 
3428c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
34357706abcSDavid Ahern {
34457706abcSDavid Ahern 	struct perf_session *session = rec->session;
34557706abcSDavid Ahern 	int feat;
34657706abcSDavid Ahern 
34757706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
34857706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
34957706abcSDavid Ahern 
35057706abcSDavid Ahern 	if (rec->no_buildid)
35157706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
35257706abcSDavid Ahern 
3533e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
35457706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
35557706abcSDavid Ahern 
35657706abcSDavid Ahern 	if (!rec->opts.branch_stack)
35757706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
358*ef149c25SAdrian Hunter 
359*ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
360*ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
36157706abcSDavid Ahern }
36257706abcSDavid Ahern 
363f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
364f33cbe72SArnaldo Carvalho de Melo 
365f33cbe72SArnaldo Carvalho de Melo /*
366f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
367f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
368f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
369f33cbe72SArnaldo Carvalho de Melo  */
37045604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
37145604710SNamhyung Kim 					siginfo_t *info,
372f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
373f33cbe72SArnaldo Carvalho de Melo {
374f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
375f33cbe72SArnaldo Carvalho de Melo 	done = 1;
376f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
377f33cbe72SArnaldo Carvalho de Melo }
378f33cbe72SArnaldo Carvalho de Melo 
3798c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
38086470930SIngo Molnar {
38157706abcSDavid Ahern 	int err;
38245604710SNamhyung Kim 	int status = 0;
3838b412664SPeter Zijlstra 	unsigned long waking = 0;
38446be604bSZhang, Yanmin 	const bool forks = argc > 0;
38523346f21SArnaldo Carvalho de Melo 	struct machine *machine;
38645694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
387b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
388f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
389d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
3906dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
39142aa276fSNamhyung Kim 	int fd;
39286470930SIngo Molnar 
393d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
39433e49ea7SAndi Kleen 
39545604710SNamhyung Kim 	atexit(record__sig_exit);
396f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
397f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
398804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
399f5970550SPeter Zijlstra 
400b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
40194c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
402ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
403a9a70bbcSArnaldo Carvalho de Melo 		return -1;
404a9a70bbcSArnaldo Carvalho de Melo 	}
405a9a70bbcSArnaldo Carvalho de Melo 
40642aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
407d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
408d20deb64SArnaldo Carvalho de Melo 
4098c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
410330aa675SStephane Eranian 
411d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
4123e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
413f5fc1412SJiri Olsa 						    argv, file->is_pipe,
414735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
41535b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
41635b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
41745604710SNamhyung Kim 			status = err;
41835b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
419856e9660SPeter Zijlstra 		}
420856e9660SPeter Zijlstra 	}
421856e9660SPeter Zijlstra 
4228c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
4238d3eca20SDavid Ahern 		err = -1;
42445604710SNamhyung Kim 		goto out_child;
4258d3eca20SDavid Ahern 	}
42686470930SIngo Molnar 
4273e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
428a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
429a8bb559bSNamhyung Kim 
430f5fc1412SJiri Olsa 	if (file->is_pipe) {
43142aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
432529870e3STom Zanussi 		if (err < 0)
43345604710SNamhyung Kim 			goto out_child;
434563aecb2SJiri Olsa 	} else {
43542aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
436d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
43745604710SNamhyung Kim 			goto out_child;
438d5eed904SArnaldo Carvalho de Melo 	}
4397c6a1c65SPeter Zijlstra 
440d3665498SDavid Ahern 	if (!rec->no_buildid
441e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
442d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
443e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
4448d3eca20SDavid Ahern 		err = -1;
44545604710SNamhyung Kim 		goto out_child;
446e20960c0SRobert Richter 	}
447e20960c0SRobert Richter 
44834ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
449743eb868SArnaldo Carvalho de Melo 
450f5fc1412SJiri Olsa 	if (file->is_pipe) {
45145694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
452a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
4532c46dbb5STom Zanussi 		if (err < 0) {
4542c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
45545604710SNamhyung Kim 			goto out_child;
4562c46dbb5STom Zanussi 		}
457cd19a035STom Zanussi 
4583e2be2daSArnaldo Carvalho de Melo 		if (have_tracepoints(&rec->evlist->entries)) {
45963e0c771STom Zanussi 			/*
46063e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
46163e0c771STom Zanussi 			 * there were no tracepoints so its not really
46263e0c771STom Zanussi 			 * an error, just that we don't need to
46363e0c771STom Zanussi 			 * synthesize anything.  We really have to
46463e0c771STom Zanussi 			 * return this more properly and also
46563e0c771STom Zanussi 			 * propagate errors that now are calling die()
46663e0c771STom Zanussi 			 */
46742aa276fSNamhyung Kim 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
468743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
46963e0c771STom Zanussi 			if (err <= 0) {
47063e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
47145604710SNamhyung Kim 				goto out_child;
47263e0c771STom Zanussi 			}
473f34b9001SDavid Ahern 			rec->bytes_written += err;
4742c46dbb5STom Zanussi 		}
47563e0c771STom Zanussi 	}
4762c46dbb5STom Zanussi 
477*ef149c25SAdrian Hunter 	if (rec->opts.full_auxtrace) {
478*ef149c25SAdrian Hunter 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
479*ef149c25SAdrian Hunter 					session, process_synthesized_event);
480*ef149c25SAdrian Hunter 		if (err)
481*ef149c25SAdrian Hunter 			goto out_delete_session;
482*ef149c25SAdrian Hunter 	}
483*ef149c25SAdrian Hunter 
48445694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4850ae617beSAdrian Hunter 						 machine);
486c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
487c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
488c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
489c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
49056b03f3cSArnaldo Carvalho de Melo 
49145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
492743eb868SArnaldo Carvalho de Melo 					     machine);
493c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
494c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
495c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
496c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
497c1a3a4b9SArnaldo Carvalho de Melo 
4987e383de4SArnaldo Carvalho de Melo 	if (perf_guest) {
499876650e6SArnaldo Carvalho de Melo 		machines__process_guests(&session->machines,
5007e383de4SArnaldo Carvalho de Melo 					 perf_event__synthesize_guest_os, tool);
5017e383de4SArnaldo Carvalho de Melo 	}
502b7cece76SArnaldo Carvalho de Melo 
5033e2be2daSArnaldo Carvalho de Melo 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
50458d925dcSArnaldo Carvalho de Melo 					    process_synthesized_event, opts->sample_address);
5058d3eca20SDavid Ahern 	if (err != 0)
50645604710SNamhyung Kim 		goto out_child;
5078d3eca20SDavid Ahern 
508d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
50986470930SIngo Molnar 		struct sched_param param;
51086470930SIngo Molnar 
511d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
51286470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
5136beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
5148d3eca20SDavid Ahern 			err = -1;
51545604710SNamhyung Kim 			goto out_child;
51686470930SIngo Molnar 		}
51786470930SIngo Molnar 	}
51886470930SIngo Molnar 
519774cb499SJiri Olsa 	/*
520774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
521774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
522774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
523774cb499SJiri Olsa 	 */
5246619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
5253e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
526764e16a3SDavid Ahern 
527856e9660SPeter Zijlstra 	/*
528856e9660SPeter Zijlstra 	 * Let the child rip
529856e9660SPeter Zijlstra 	 */
530735f7e0bSArnaldo Carvalho de Melo 	if (forks)
5313e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
532856e9660SPeter Zijlstra 
5336619a53eSAndi Kleen 	if (opts->initial_delay) {
5346619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
5356619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
5366619a53eSAndi Kleen 	}
5376619a53eSAndi Kleen 
538649c48a9SPeter Zijlstra 	for (;;) {
539d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
54086470930SIngo Molnar 
5418c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
5428d3eca20SDavid Ahern 			err = -1;
54345604710SNamhyung Kim 			goto out_child;
5448d3eca20SDavid Ahern 		}
54586470930SIngo Molnar 
546d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
5476dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
548649c48a9SPeter Zijlstra 				break;
549f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
550a515114fSJiri Olsa 			/*
551a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
552a515114fSJiri Olsa 			 * number of returned events and interrupt error.
553a515114fSJiri Olsa 			 */
554a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
55545604710SNamhyung Kim 				err = 0;
5568b412664SPeter Zijlstra 			waking++;
5576dcf45efSArnaldo Carvalho de Melo 
5586dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
5596dcf45efSArnaldo Carvalho de Melo 				draining = true;
5608b412664SPeter Zijlstra 		}
5618b412664SPeter Zijlstra 
562774cb499SJiri Olsa 		/*
563774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
564774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
565774cb499SJiri Olsa 		 * disable events in this case.
566774cb499SJiri Olsa 		 */
567602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
5683e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
5692711926aSJiri Olsa 			disabled = true;
5702711926aSJiri Olsa 		}
5718b412664SPeter Zijlstra 	}
5728b412664SPeter Zijlstra 
573f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
57435550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
575f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
576f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
577f33cbe72SArnaldo Carvalho de Melo 		err = -1;
57845604710SNamhyung Kim 		goto out_child;
579f33cbe72SArnaldo Carvalho de Melo 	}
580f33cbe72SArnaldo Carvalho de Melo 
581e3d59112SNamhyung Kim 	if (!quiet)
5828b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
58386470930SIngo Molnar 
58445604710SNamhyung Kim out_child:
58545604710SNamhyung Kim 	if (forks) {
58645604710SNamhyung Kim 		int exit_status;
58745604710SNamhyung Kim 
58845604710SNamhyung Kim 		if (!child_finished)
58945604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
59045604710SNamhyung Kim 
59145604710SNamhyung Kim 		wait(&exit_status);
59245604710SNamhyung Kim 
59345604710SNamhyung Kim 		if (err < 0)
59445604710SNamhyung Kim 			status = err;
59545604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
59645604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
59745604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
59845604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
59945604710SNamhyung Kim 	} else
60045604710SNamhyung Kim 		status = err;
60145604710SNamhyung Kim 
602e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
603e3d59112SNamhyung Kim 	rec->samples = 0;
604e3d59112SNamhyung Kim 
60545604710SNamhyung Kim 	if (!err && !file->is_pipe) {
60645604710SNamhyung Kim 		rec->session->header.data_size += rec->bytes_written;
60745604710SNamhyung Kim 
60845604710SNamhyung Kim 		if (!rec->no_buildid)
60945604710SNamhyung Kim 			process_buildids(rec);
61042aa276fSNamhyung Kim 		perf_session__write_header(rec->session, rec->evlist, fd, true);
61145604710SNamhyung Kim 	}
61239d17dacSArnaldo Carvalho de Melo 
613e3d59112SNamhyung Kim 	if (!err && !quiet) {
614e3d59112SNamhyung Kim 		char samples[128];
615e3d59112SNamhyung Kim 
616*ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
617e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
618e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
619e3d59112SNamhyung Kim 		else
620e3d59112SNamhyung Kim 			samples[0] = '\0';
621e3d59112SNamhyung Kim 
622e3d59112SNamhyung Kim 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s ]\n",
623e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
624e3d59112SNamhyung Kim 			file->path, samples);
625e3d59112SNamhyung Kim 	}
626e3d59112SNamhyung Kim 
62739d17dacSArnaldo Carvalho de Melo out_delete_session:
62839d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
62945604710SNamhyung Kim 	return status;
63086470930SIngo Molnar }
63186470930SIngo Molnar 
632bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
633bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
634bdfebd84SRoberto Agostino Vitillo 
635bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
636bdfebd84SRoberto Agostino Vitillo 
637bdfebd84SRoberto Agostino Vitillo struct branch_mode {
638bdfebd84SRoberto Agostino Vitillo 	const char *name;
639bdfebd84SRoberto Agostino Vitillo 	int mode;
640bdfebd84SRoberto Agostino Vitillo };
641bdfebd84SRoberto Agostino Vitillo 
642bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
643bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
644bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
645bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
646bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
647bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
648bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
649bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
6500126d493SAndi Kleen 	BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
6510126d493SAndi Kleen 	BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
6520126d493SAndi Kleen 	BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
6530fffa5dfSAnshuman Khandual 	BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
654bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
655bdfebd84SRoberto Agostino Vitillo };
656bdfebd84SRoberto Agostino Vitillo 
657bdfebd84SRoberto Agostino Vitillo static int
658a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
659bdfebd84SRoberto Agostino Vitillo {
660bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
661bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
662bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
663bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
664bdfebd84SRoberto Agostino Vitillo 
665bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
666bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
667a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
668bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
669bdfebd84SRoberto Agostino Vitillo 
670a5aabdacSStephane Eranian 	if (unset)
671a5aabdacSStephane Eranian 		return 0;
672bdfebd84SRoberto Agostino Vitillo 
673a5aabdacSStephane Eranian 	/*
674a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
675a5aabdacSStephane Eranian 	 */
676a5aabdacSStephane Eranian 	if (*mode)
677a5aabdacSStephane Eranian 		return -1;
678a5aabdacSStephane Eranian 
679a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
680a5aabdacSStephane Eranian 	if (str) {
681bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
682bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
683bdfebd84SRoberto Agostino Vitillo 		if (!s)
684bdfebd84SRoberto Agostino Vitillo 			return -1;
685bdfebd84SRoberto Agostino Vitillo 
686bdfebd84SRoberto Agostino Vitillo 		for (;;) {
687bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
688bdfebd84SRoberto Agostino Vitillo 			if (p)
689bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
690bdfebd84SRoberto Agostino Vitillo 
691bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
692bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
693bdfebd84SRoberto Agostino Vitillo 					break;
694bdfebd84SRoberto Agostino Vitillo 			}
695a5aabdacSStephane Eranian 			if (!br->name) {
696a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
697a5aabdacSStephane Eranian 					    " check man page\n", s);
698bdfebd84SRoberto Agostino Vitillo 				goto error;
699a5aabdacSStephane Eranian 			}
700bdfebd84SRoberto Agostino Vitillo 
701bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
702bdfebd84SRoberto Agostino Vitillo 
703bdfebd84SRoberto Agostino Vitillo 			if (!p)
704bdfebd84SRoberto Agostino Vitillo 				break;
705bdfebd84SRoberto Agostino Vitillo 
706bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
707bdfebd84SRoberto Agostino Vitillo 		}
708a5aabdacSStephane Eranian 	}
709bdfebd84SRoberto Agostino Vitillo 	ret = 0;
710bdfebd84SRoberto Agostino Vitillo 
711a5aabdacSStephane Eranian 	/* default to any branch */
712bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
713a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
714bdfebd84SRoberto Agostino Vitillo 	}
715bdfebd84SRoberto Agostino Vitillo error:
716bdfebd84SRoberto Agostino Vitillo 	free(os);
717bdfebd84SRoberto Agostino Vitillo 	return ret;
718bdfebd84SRoberto Agostino Vitillo }
719bdfebd84SRoberto Agostino Vitillo 
72072a128aaSNamhyung Kim static void callchain_debug(void)
72109b0fd45SJiri Olsa {
722aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
723a601fdffSJiri Olsa 
72472a128aaSNamhyung Kim 	pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
72526d33022SJiri Olsa 
72672a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_DWARF)
72709b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
72872a128aaSNamhyung Kim 			 callchain_param.dump_size);
72909b0fd45SJiri Olsa }
73009b0fd45SJiri Olsa 
73172a128aaSNamhyung Kim int record_parse_callchain_opt(const struct option *opt __maybe_unused,
73209b0fd45SJiri Olsa 			       const char *arg,
73309b0fd45SJiri Olsa 			       int unset)
73409b0fd45SJiri Olsa {
73509b0fd45SJiri Olsa 	int ret;
73609b0fd45SJiri Olsa 
73772a128aaSNamhyung Kim 	callchain_param.enabled = !unset;
738eb853e80SJiri Olsa 
73909b0fd45SJiri Olsa 	/* --no-call-graph */
74009b0fd45SJiri Olsa 	if (unset) {
74172a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_NONE;
74209b0fd45SJiri Olsa 		pr_debug("callchain: disabled\n");
74309b0fd45SJiri Olsa 		return 0;
74409b0fd45SJiri Olsa 	}
74509b0fd45SJiri Olsa 
746f7f084f4SNamhyung Kim 	ret = parse_callchain_record_opt(arg);
74709b0fd45SJiri Olsa 	if (!ret)
74872a128aaSNamhyung Kim 		callchain_debug();
74909b0fd45SJiri Olsa 
75026d33022SJiri Olsa 	return ret;
75126d33022SJiri Olsa }
75226d33022SJiri Olsa 
75372a128aaSNamhyung Kim int record_callchain_opt(const struct option *opt __maybe_unused,
75409b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
75509b0fd45SJiri Olsa 			 int unset __maybe_unused)
75609b0fd45SJiri Olsa {
75772a128aaSNamhyung Kim 	callchain_param.enabled = true;
75809b0fd45SJiri Olsa 
75972a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_NONE)
76072a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_FP;
761eb853e80SJiri Olsa 
76272a128aaSNamhyung Kim 	callchain_debug();
76309b0fd45SJiri Olsa 	return 0;
76409b0fd45SJiri Olsa }
76509b0fd45SJiri Olsa 
766eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
767eb853e80SJiri Olsa {
768eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
7695a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
770eb853e80SJiri Olsa 
771eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
772eb853e80SJiri Olsa }
773eb853e80SJiri Olsa 
774814c8c38SPeter Zijlstra struct clockid_map {
775814c8c38SPeter Zijlstra 	const char *name;
776814c8c38SPeter Zijlstra 	int clockid;
777814c8c38SPeter Zijlstra };
778814c8c38SPeter Zijlstra 
779814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
780814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
781814c8c38SPeter Zijlstra 
782814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
783814c8c38SPeter Zijlstra 
784814c8c38SPeter Zijlstra 
785814c8c38SPeter Zijlstra /*
786814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
787814c8c38SPeter Zijlstra  */
788814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
789814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
790814c8c38SPeter Zijlstra #endif
791814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
792814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
793814c8c38SPeter Zijlstra #endif
794814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
795814c8c38SPeter Zijlstra #define CLOCK_TAI 11
796814c8c38SPeter Zijlstra #endif
797814c8c38SPeter Zijlstra 
798814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
799814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
800814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
801814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
802814c8c38SPeter Zijlstra 
803814c8c38SPeter Zijlstra 	/* available for some events */
804814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
805814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
806814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
807814c8c38SPeter Zijlstra 
808814c8c38SPeter Zijlstra 	/* available for the lazy */
809814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
810814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
811814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
812814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
813814c8c38SPeter Zijlstra 
814814c8c38SPeter Zijlstra 	CLOCKID_END,
815814c8c38SPeter Zijlstra };
816814c8c38SPeter Zijlstra 
817814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
818814c8c38SPeter Zijlstra {
819814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
820814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
821814c8c38SPeter Zijlstra 	const char *ostr = str;
822814c8c38SPeter Zijlstra 
823814c8c38SPeter Zijlstra 	if (unset) {
824814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
825814c8c38SPeter Zijlstra 		return 0;
826814c8c38SPeter Zijlstra 	}
827814c8c38SPeter Zijlstra 
828814c8c38SPeter Zijlstra 	/* no arg passed */
829814c8c38SPeter Zijlstra 	if (!str)
830814c8c38SPeter Zijlstra 		return 0;
831814c8c38SPeter Zijlstra 
832814c8c38SPeter Zijlstra 	/* no setting it twice */
833814c8c38SPeter Zijlstra 	if (opts->use_clockid)
834814c8c38SPeter Zijlstra 		return -1;
835814c8c38SPeter Zijlstra 
836814c8c38SPeter Zijlstra 	opts->use_clockid = true;
837814c8c38SPeter Zijlstra 
838814c8c38SPeter Zijlstra 	/* if its a number, we're done */
839814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
840814c8c38SPeter Zijlstra 		return 0;
841814c8c38SPeter Zijlstra 
842814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
843814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
844814c8c38SPeter Zijlstra 		str += 6;
845814c8c38SPeter Zijlstra 
846814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
847814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
848814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
849814c8c38SPeter Zijlstra 			return 0;
850814c8c38SPeter Zijlstra 		}
851814c8c38SPeter Zijlstra 	}
852814c8c38SPeter Zijlstra 
853814c8c38SPeter Zijlstra 	opts->use_clockid = false;
854814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
855814c8c38SPeter Zijlstra 	return -1;
856814c8c38SPeter Zijlstra }
857814c8c38SPeter Zijlstra 
858e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
85986470930SIngo Molnar 	"perf record [<options>] [<command>]",
86086470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
86186470930SIngo Molnar 	NULL
86286470930SIngo Molnar };
863e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
86486470930SIngo Molnar 
865d20deb64SArnaldo Carvalho de Melo /*
8668c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
8678c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
868d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
869d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
870d20deb64SArnaldo Carvalho de Melo  *
871d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
872d20deb64SArnaldo Carvalho de Melo  *
873d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
874d20deb64SArnaldo Carvalho de Melo  */
8758c6f45a7SArnaldo Carvalho de Melo static struct record record = {
876d20deb64SArnaldo Carvalho de Melo 	.opts = {
8778affc2b8SAndi Kleen 		.sample_time	     = true,
878d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
879d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
880d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
881447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
882d1cb9fceSNamhyung Kim 		.target		     = {
883d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
8843aa5939dSAdrian Hunter 			.default_per_cpu = true,
885d1cb9fceSNamhyung Kim 		},
886d20deb64SArnaldo Carvalho de Melo 	},
887e3d59112SNamhyung Kim 	.tool = {
888e3d59112SNamhyung Kim 		.sample		= process_sample_event,
889e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
890e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
891e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
892e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
893e3d59112SNamhyung Kim 	},
894d20deb64SArnaldo Carvalho de Melo };
8957865e817SFrederic Weisbecker 
89609b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
89761eaa3beSArnaldo Carvalho de Melo 
8989ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT
899aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
90061eaa3beSArnaldo Carvalho de Melo #else
901aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
90261eaa3beSArnaldo Carvalho de Melo #endif
90361eaa3beSArnaldo Carvalho de Melo 
904d20deb64SArnaldo Carvalho de Melo /*
905d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
906d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
907b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
908d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
909d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
910d20deb64SArnaldo Carvalho de Melo  */
911e5b2c207SNamhyung Kim struct option __record_options[] = {
912d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
91386470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
914f120f9d5SJiri Olsa 		     parse_events_option),
915d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
916c171b552SLi Zefan 		     "event filter", parse_filter),
917bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
918d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
919bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
920d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
921d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
92286470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
923509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
924acac03faSKirill Smelkov 		    "collect data without buffering"),
925d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
926daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
927bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
92886470930SIngo Molnar 			    "system-wide collection from all CPUs"),
929bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
930c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
931d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
932f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
93386470930SIngo Molnar 		    "output file name"),
93469e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
93569e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
9362e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
937d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
938994a1f78SJiri Olsa 	OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
939994a1f78SJiri Olsa 		     "number of mmap data pages",
940994a1f78SJiri Olsa 		     perf_evlist__parse_mmap_pages),
941d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
94243bece79SLin Ming 		    "put the counters into a counter group"),
94309b0fd45SJiri Olsa 	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
94409b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
94509b0fd45SJiri Olsa 			   &record_callchain_opt),
94609b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
94775d9a108SArnaldo Carvalho de Melo 		     "mode[,dump_size]", record_callchain_help,
94809b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
949c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
9503da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
951b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
952d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
953649c48a9SPeter Zijlstra 		    "per thread counts"),
954d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
9554bba828dSAnton Blanchard 		    "Sample addresses"),
956d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
9573e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
958d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
959649c48a9SPeter Zijlstra 		    "don't sample"),
960d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
961a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
962d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
963baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
964d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
965023695d9SStephane Eranian 		     "monitor event in cgroup name only",
966023695d9SStephane Eranian 		     parse_cgroups),
967a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
9686619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
969bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
970bea03405SNamhyung Kim 		   "user to profile"),
971a5aabdacSStephane Eranian 
972a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
973a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
974a5aabdacSStephane Eranian 		     parse_branch_stack),
975a5aabdacSStephane Eranian 
976a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
977a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
978bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
97905484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
98005484298SAndi Kleen 		    "sample by weight (on special events only)"),
981475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
982475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
9833aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
9843aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
9854b6c5177SStephane Eranian 	OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
9864b6c5177SStephane Eranian 		    "Sample machine registers on interrupt"),
98785c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
98885c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
989814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
990814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
991814c8c38SPeter Zijlstra 	parse_clockid),
99286470930SIngo Molnar 	OPT_END()
99386470930SIngo Molnar };
99486470930SIngo Molnar 
995e5b2c207SNamhyung Kim struct option *record_options = __record_options;
996e5b2c207SNamhyung Kim 
9971d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
99886470930SIngo Molnar {
999*ef149c25SAdrian Hunter 	int err;
10008c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
100116ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
100286470930SIngo Molnar 
10033e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
10043e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1005361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1006361c99a6SArnaldo Carvalho de Melo 
1007eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1008eb853e80SJiri Olsa 
1009bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1010a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1011602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1012bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
101386470930SIngo Molnar 
1014bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
10153780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
1016023695d9SStephane Eranian 			  " system-wide mode\n");
1017023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
1018023695d9SStephane Eranian 	}
1019023695d9SStephane Eranian 
1020*ef149c25SAdrian Hunter 	if (!rec->itr) {
1021*ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1022*ef149c25SAdrian Hunter 		if (err)
1023*ef149c25SAdrian Hunter 			return err;
1024*ef149c25SAdrian Hunter 	}
1025*ef149c25SAdrian Hunter 
1026*ef149c25SAdrian Hunter 	err = -ENOMEM;
1027*ef149c25SAdrian Hunter 
10280a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1029baa2f6ceSArnaldo Carvalho de Melo 
1030ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1031646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1032646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1033ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1034646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1035646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1036646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1037646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1038646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1039ec80fde7SArnaldo Carvalho de Melo 
1040d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1041a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1042655000e7SArnaldo Carvalho de Melo 
10433e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
10443e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
104569aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
104669aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1047bbd36e5eSPeter Zijlstra 	}
104886470930SIngo Molnar 
104969e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
105069e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
105169e7e5b0SAdrian Hunter 
1052602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
105316ad2ffbSNamhyung Kim 	if (err) {
1054602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
105516ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
105616ad2ffbSNamhyung Kim 	}
10574bd0f2d2SNamhyung Kim 
1058602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
105916ad2ffbSNamhyung Kim 	if (err) {
106016ad2ffbSNamhyung Kim 		int saved_errno = errno;
106116ad2ffbSNamhyung Kim 
1062602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
10633780f488SNamhyung Kim 		ui__error("%s", errbuf);
106416ad2ffbSNamhyung Kim 
106516ad2ffbSNamhyung Kim 		err = -saved_errno;
10668fa60e1fSNamhyung Kim 		goto out_symbol_exit;
106716ad2ffbSNamhyung Kim 	}
10680d37aa34SArnaldo Carvalho de Melo 
106916ad2ffbSNamhyung Kim 	err = -ENOMEM;
10703e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1071dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
107269aad6f1SArnaldo Carvalho de Melo 
1073*ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1074*ef149c25SAdrian Hunter 	if (err)
1075*ef149c25SAdrian Hunter 		goto out_symbol_exit;
1076*ef149c25SAdrian Hunter 
1077b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
107839d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
107903ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
10807e4ff9e3SMike Galbraith 	}
10817e4ff9e3SMike Galbraith 
1082d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1083d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
108445604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1085d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1086*ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
108739d17dacSArnaldo Carvalho de Melo 	return err;
108886470930SIngo Molnar }
1089