xref: /openbmc/linux/tools/perf/builtin-record.c (revision be7b0c9e376e93a00b6c8631e2721e9dc7c6a1fa)
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"
144b6ab94eSJosh Poimboeuf #include <subcmd/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"
30bcc84ec6SStephane Eranian #include "util/perf_regs.h"
31ef149c25SAdrian Hunter #include "util/auxtrace.h"
3246bc29b9SAdrian Hunter #include "util/tsc.h"
33f00898f4SAndi Kleen #include "util/parse-branch-options.h"
34bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3571dc2326SWang Nan #include "util/llvm-utils.h"
368690a2a7SWang Nan #include "util/bpf-loader.h"
375f9cf599SWang Nan #include "util/trigger.h"
38d8871ea7SWang Nan #include "asm/bug.h"
397c6a1c65SPeter Zijlstra 
4086470930SIngo Molnar #include <unistd.h>
4186470930SIngo Molnar #include <sched.h>
42a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
4386470930SIngo Molnar 
4478da39faSBernhard Rosenkraenzer 
458c6f45a7SArnaldo Carvalho de Melo struct record {
4645694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
47b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
48d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
49f5fc1412SJiri Olsa 	struct perf_data_file	file;
50ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
51d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
52d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
53d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
54d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
55d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
56d2db9a98SWang Nan 	bool			no_buildid_set;
57d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
58d2db9a98SWang Nan 	bool			no_buildid_cache_set;
596156681bSNamhyung Kim 	bool			buildid_all;
60ecfd7a9cSWang Nan 	bool			timestamp_filename;
613c1cb7e3SWang Nan 	bool			switch_output;
629f065194SYang Shi 	unsigned long long	samples;
630f82ebc4SArnaldo Carvalho de Melo };
6486470930SIngo Molnar 
658c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
66f5970550SPeter Zijlstra {
67cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
684f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
698d3eca20SDavid Ahern 		return -1;
708d3eca20SDavid Ahern 	}
71f5970550SPeter Zijlstra 
72cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
738d3eca20SDavid Ahern 	return 0;
74f5970550SPeter Zijlstra }
75f5970550SPeter Zijlstra 
7645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
77d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
781d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
791d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
80234fbbf5SArnaldo Carvalho de Melo {
818c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
828c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
83234fbbf5SArnaldo Carvalho de Melo }
84234fbbf5SArnaldo Carvalho de Melo 
85e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
8686470930SIngo Molnar {
87e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
887b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
897b8283b5SDavid Ahern 	u64 old = md->prev;
90918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
9186470930SIngo Molnar 	unsigned long size;
9286470930SIngo Molnar 	void *buf;
938d3eca20SDavid Ahern 	int rc = 0;
9486470930SIngo Molnar 
95dc82009aSArnaldo Carvalho de Melo 	if (old == head)
968d3eca20SDavid Ahern 		return 0;
9786470930SIngo Molnar 
98d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
9986470930SIngo Molnar 
10086470930SIngo Molnar 	size = head - old;
10186470930SIngo Molnar 
10286470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
10386470930SIngo Molnar 		buf = &data[old & md->mask];
10486470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
10586470930SIngo Molnar 		old += size;
10686470930SIngo Molnar 
1078c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
1088d3eca20SDavid Ahern 			rc = -1;
1098d3eca20SDavid Ahern 			goto out;
1108d3eca20SDavid Ahern 		}
11186470930SIngo Molnar 	}
11286470930SIngo Molnar 
11386470930SIngo Molnar 	buf = &data[old & md->mask];
11486470930SIngo Molnar 	size = head - old;
11586470930SIngo Molnar 	old += size;
11686470930SIngo Molnar 
1178c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1188d3eca20SDavid Ahern 		rc = -1;
1198d3eca20SDavid Ahern 		goto out;
1208d3eca20SDavid Ahern 	}
12186470930SIngo Molnar 
12286470930SIngo Molnar 	md->prev = old;
123e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1248d3eca20SDavid Ahern out:
1258d3eca20SDavid Ahern 	return rc;
12686470930SIngo Molnar }
12786470930SIngo Molnar 
1282dd6d8a1SAdrian Hunter static volatile int done;
1292dd6d8a1SAdrian Hunter static volatile int signr = -1;
1302dd6d8a1SAdrian Hunter static volatile int child_finished;
131c0bdc1c4SWang Nan 
1322dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1335f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
1343c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger);
1352dd6d8a1SAdrian Hunter 
1362dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1372dd6d8a1SAdrian Hunter {
1382dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1392dd6d8a1SAdrian Hunter 		child_finished = 1;
1402dd6d8a1SAdrian Hunter 	else
1412dd6d8a1SAdrian Hunter 		signr = sig;
1422dd6d8a1SAdrian Hunter 
1432dd6d8a1SAdrian Hunter 	done = 1;
1442dd6d8a1SAdrian Hunter }
1452dd6d8a1SAdrian Hunter 
1462dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1472dd6d8a1SAdrian Hunter {
1482dd6d8a1SAdrian Hunter 	if (signr == -1)
1492dd6d8a1SAdrian Hunter 		return;
1502dd6d8a1SAdrian Hunter 
1512dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1522dd6d8a1SAdrian Hunter 	raise(signr);
1532dd6d8a1SAdrian Hunter }
1542dd6d8a1SAdrian Hunter 
155e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
156e31f0d01SAdrian Hunter 
157ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
158ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
159ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
160ef149c25SAdrian Hunter {
161ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
16299fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
163ef149c25SAdrian Hunter 	size_t padding;
164ef149c25SAdrian Hunter 	u8 pad[8] = {0};
165ef149c25SAdrian Hunter 
16699fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
16799fa2984SAdrian Hunter 		off_t file_offset;
16899fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
16999fa2984SAdrian Hunter 		int err;
17099fa2984SAdrian Hunter 
17199fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
17299fa2984SAdrian Hunter 		if (file_offset == -1)
17399fa2984SAdrian Hunter 			return -1;
17499fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
17599fa2984SAdrian Hunter 						     event, file_offset);
17699fa2984SAdrian Hunter 		if (err)
17799fa2984SAdrian Hunter 			return err;
17899fa2984SAdrian Hunter 	}
17999fa2984SAdrian Hunter 
180ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
181ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
182ef149c25SAdrian Hunter 	if (padding)
183ef149c25SAdrian Hunter 		padding = 8 - padding;
184ef149c25SAdrian Hunter 
185ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
186ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
187ef149c25SAdrian Hunter 	if (len2)
188ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
189ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
190ef149c25SAdrian Hunter 
191ef149c25SAdrian Hunter 	return 0;
192ef149c25SAdrian Hunter }
193ef149c25SAdrian Hunter 
194ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
195ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
196ef149c25SAdrian Hunter {
197ef149c25SAdrian Hunter 	int ret;
198ef149c25SAdrian Hunter 
199ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
200ef149c25SAdrian Hunter 				  record__process_auxtrace);
201ef149c25SAdrian Hunter 	if (ret < 0)
202ef149c25SAdrian Hunter 		return ret;
203ef149c25SAdrian Hunter 
204ef149c25SAdrian Hunter 	if (ret)
205ef149c25SAdrian Hunter 		rec->samples++;
206ef149c25SAdrian Hunter 
207ef149c25SAdrian Hunter 	return 0;
208ef149c25SAdrian Hunter }
209ef149c25SAdrian Hunter 
2102dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2112dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2122dd6d8a1SAdrian Hunter {
2132dd6d8a1SAdrian Hunter 	int ret;
2142dd6d8a1SAdrian Hunter 
2152dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2162dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2172dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2182dd6d8a1SAdrian Hunter 	if (ret < 0)
2192dd6d8a1SAdrian Hunter 		return ret;
2202dd6d8a1SAdrian Hunter 
2212dd6d8a1SAdrian Hunter 	if (ret)
2222dd6d8a1SAdrian Hunter 		rec->samples++;
2232dd6d8a1SAdrian Hunter 
2242dd6d8a1SAdrian Hunter 	return 0;
2252dd6d8a1SAdrian Hunter }
2262dd6d8a1SAdrian Hunter 
2272dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2282dd6d8a1SAdrian Hunter {
2292dd6d8a1SAdrian Hunter 	int i;
2302dd6d8a1SAdrian Hunter 	int rc = 0;
2312dd6d8a1SAdrian Hunter 
2322dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2332dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2342dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2352dd6d8a1SAdrian Hunter 
2362dd6d8a1SAdrian Hunter 		if (!mm->base)
2372dd6d8a1SAdrian Hunter 			continue;
2382dd6d8a1SAdrian Hunter 
2392dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2402dd6d8a1SAdrian Hunter 			rc = -1;
2412dd6d8a1SAdrian Hunter 			goto out;
2422dd6d8a1SAdrian Hunter 		}
2432dd6d8a1SAdrian Hunter 	}
2442dd6d8a1SAdrian Hunter out:
2452dd6d8a1SAdrian Hunter 	return rc;
2462dd6d8a1SAdrian Hunter }
2472dd6d8a1SAdrian Hunter 
2482dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2492dd6d8a1SAdrian Hunter {
2502dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2512dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2525f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
2532dd6d8a1SAdrian Hunter 	} else {
2545f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
2555f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
2565f9cf599SWang Nan 		else
2575f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
2582dd6d8a1SAdrian Hunter 	}
2592dd6d8a1SAdrian Hunter }
2602dd6d8a1SAdrian Hunter 
261e31f0d01SAdrian Hunter #else
262e31f0d01SAdrian Hunter 
263e31f0d01SAdrian Hunter static inline
264e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
265e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
266e31f0d01SAdrian Hunter {
267e31f0d01SAdrian Hunter 	return 0;
268e31f0d01SAdrian Hunter }
269e31f0d01SAdrian Hunter 
2702dd6d8a1SAdrian Hunter static inline
2712dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2722dd6d8a1SAdrian Hunter {
2732dd6d8a1SAdrian Hunter }
2742dd6d8a1SAdrian Hunter 
2752dd6d8a1SAdrian Hunter static inline
2762dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2772dd6d8a1SAdrian Hunter {
2782dd6d8a1SAdrian Hunter 	return 0;
2792dd6d8a1SAdrian Hunter }
2802dd6d8a1SAdrian Hunter 
281e31f0d01SAdrian Hunter #endif
282e31f0d01SAdrian Hunter 
2838c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
284dd7927f4SArnaldo Carvalho de Melo {
28556e52e85SArnaldo Carvalho de Melo 	char msg[512];
2866a4bb04cSJiri Olsa 	struct perf_evsel *pos;
287d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
288d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
289b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
2908d3eca20SDavid Ahern 	int rc = 0;
291dd7927f4SArnaldo Carvalho de Melo 
292e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
293cac21425SJiri Olsa 
2940050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
2953da297a6SIngo Molnar try_again:
296d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
29756e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
2983da297a6SIngo Molnar 				if (verbose)
299c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3003da297a6SIngo Molnar 				goto try_again;
3013da297a6SIngo Molnar 			}
302ca6a4258SDavid Ahern 
30356e52e85SArnaldo Carvalho de Melo 			rc = -errno;
30456e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
30556e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
30656e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3078d3eca20SDavid Ahern 			goto out;
3087c6a1c65SPeter Zijlstra 		}
3097c6a1c65SPeter Zijlstra 	}
3107c6a1c65SPeter Zijlstra 
31123d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
31223d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
31323d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
31435550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3158d3eca20SDavid Ahern 		rc = -1;
3168d3eca20SDavid Ahern 		goto out;
3170a102479SFrederic Weisbecker 	}
3180a102479SFrederic Weisbecker 
319ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3202dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3212dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3228d3eca20SDavid Ahern 		if (errno == EPERM) {
3238d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
32418e60939SNelson Elhage 			       "Consider increasing "
32518e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
32618e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
327ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
328ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3298d3eca20SDavid Ahern 			rc = -errno;
3308d3eca20SDavid Ahern 		} else {
33135550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
33235550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
33395c36561SWang Nan 			if (errno)
3348d3eca20SDavid Ahern 				rc = -errno;
33595c36561SWang Nan 			else
33695c36561SWang Nan 				rc = -EINVAL;
3378d3eca20SDavid Ahern 		}
3388d3eca20SDavid Ahern 		goto out;
33918e60939SNelson Elhage 	}
3400a27d7f9SArnaldo Carvalho de Melo 
341a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3427b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3438d3eca20SDavid Ahern out:
3448d3eca20SDavid Ahern 	return rc;
345a91e5431SArnaldo Carvalho de Melo }
346a91e5431SArnaldo Carvalho de Melo 
347e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
348e3d59112SNamhyung Kim 				union perf_event *event,
349e3d59112SNamhyung Kim 				struct perf_sample *sample,
350e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
351e3d59112SNamhyung Kim 				struct machine *machine)
352e3d59112SNamhyung Kim {
353e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
354e3d59112SNamhyung Kim 
355e3d59112SNamhyung Kim 	rec->samples++;
356e3d59112SNamhyung Kim 
357e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
358e3d59112SNamhyung Kim }
359e3d59112SNamhyung Kim 
3608c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
3616122e4e4SArnaldo Carvalho de Melo {
362f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
363f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
3646122e4e4SArnaldo Carvalho de Melo 
365457ae94aSHe Kuang 	if (file->size == 0)
3669f591fd7SArnaldo Carvalho de Melo 		return 0;
3679f591fd7SArnaldo Carvalho de Melo 
36800dc8657SNamhyung Kim 	/*
36900dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
37000dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
37100dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
37200dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
37300dc8657SNamhyung Kim 	 *
37400dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
37500dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
37600dc8657SNamhyung Kim 	 */
37700dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
37800dc8657SNamhyung Kim 
3796156681bSNamhyung Kim 	/*
3806156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
3816156681bSNamhyung Kim 	 * so no need to process samples.
3826156681bSNamhyung Kim 	 */
3836156681bSNamhyung Kim 	if (rec->buildid_all)
3846156681bSNamhyung Kim 		rec->tool.sample = NULL;
3856156681bSNamhyung Kim 
386b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
3876122e4e4SArnaldo Carvalho de Melo }
3886122e4e4SArnaldo Carvalho de Melo 
3898115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
390a1645ce1SZhang, Yanmin {
391a1645ce1SZhang, Yanmin 	int err;
39245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
393a1645ce1SZhang, Yanmin 	/*
394a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
395a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
396a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
397a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
398a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
399a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
400a1645ce1SZhang, Yanmin 	 */
40145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
402743eb868SArnaldo Carvalho de Melo 					     machine);
403a1645ce1SZhang, Yanmin 	if (err < 0)
404a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
40523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
406a1645ce1SZhang, Yanmin 
407a1645ce1SZhang, Yanmin 	/*
408a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
409a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
410a1645ce1SZhang, Yanmin 	 */
41145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4120ae617beSAdrian Hunter 						 machine);
413a1645ce1SZhang, Yanmin 	if (err < 0)
414a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
416a1645ce1SZhang, Yanmin }
417a1645ce1SZhang, Yanmin 
41898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
41998402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
42098402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
42198402807SFrederic Weisbecker };
42298402807SFrederic Weisbecker 
4238c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
42498402807SFrederic Weisbecker {
425dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4260e2e63ddSPeter Zijlstra 	int i;
4278d3eca20SDavid Ahern 	int rc = 0;
42898402807SFrederic Weisbecker 
429d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
430ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
431ef149c25SAdrian Hunter 
4328d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
433e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4348d3eca20SDavid Ahern 				rc = -1;
4358d3eca20SDavid Ahern 				goto out;
4368d3eca20SDavid Ahern 			}
4378d3eca20SDavid Ahern 		}
438ef149c25SAdrian Hunter 
4392dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
440ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
441ef149c25SAdrian Hunter 			rc = -1;
442ef149c25SAdrian Hunter 			goto out;
443ef149c25SAdrian Hunter 		}
44498402807SFrederic Weisbecker 	}
44598402807SFrederic Weisbecker 
446dcabb507SJiri Olsa 	/*
447dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
448dcabb507SJiri Olsa 	 * at least one event.
449dcabb507SJiri Olsa 	 */
450dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
4518c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
4528d3eca20SDavid Ahern 
4538d3eca20SDavid Ahern out:
4548d3eca20SDavid Ahern 	return rc;
45598402807SFrederic Weisbecker }
45698402807SFrederic Weisbecker 
4578c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
45857706abcSDavid Ahern {
45957706abcSDavid Ahern 	struct perf_session *session = rec->session;
46057706abcSDavid Ahern 	int feat;
46157706abcSDavid Ahern 
46257706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
46357706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
46457706abcSDavid Ahern 
46557706abcSDavid Ahern 	if (rec->no_buildid)
46657706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
46757706abcSDavid Ahern 
4683e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
46957706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
47057706abcSDavid Ahern 
47157706abcSDavid Ahern 	if (!rec->opts.branch_stack)
47257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
473ef149c25SAdrian Hunter 
474ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
475ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
476ffa517adSJiri Olsa 
477ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
47857706abcSDavid Ahern }
47957706abcSDavid Ahern 
480e1ab48baSWang Nan static void
481e1ab48baSWang Nan record__finish_output(struct record *rec)
482e1ab48baSWang Nan {
483e1ab48baSWang Nan 	struct perf_data_file *file = &rec->file;
484e1ab48baSWang Nan 	int fd = perf_data_file__fd(file);
485e1ab48baSWang Nan 
486e1ab48baSWang Nan 	if (file->is_pipe)
487e1ab48baSWang Nan 		return;
488e1ab48baSWang Nan 
489e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
490e1ab48baSWang Nan 	file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
491e1ab48baSWang Nan 
492e1ab48baSWang Nan 	if (!rec->no_buildid) {
493e1ab48baSWang Nan 		process_buildids(rec);
494e1ab48baSWang Nan 
495e1ab48baSWang Nan 		if (rec->buildid_all)
496e1ab48baSWang Nan 			dsos__hit_all(rec->session);
497e1ab48baSWang Nan 	}
498e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
499e1ab48baSWang Nan 
500e1ab48baSWang Nan 	return;
501e1ab48baSWang Nan }
502e1ab48baSWang Nan 
503*be7b0c9eSWang Nan static int record__synthesize_workload(struct record *rec)
504*be7b0c9eSWang Nan {
505*be7b0c9eSWang Nan 	struct {
506*be7b0c9eSWang Nan 		struct thread_map map;
507*be7b0c9eSWang Nan 		struct thread_map_data map_data;
508*be7b0c9eSWang Nan 	} thread_map;
509*be7b0c9eSWang Nan 
510*be7b0c9eSWang Nan 	thread_map.map.nr = 1;
511*be7b0c9eSWang Nan 	thread_map.map.map[0].pid = rec->evlist->workload.pid;
512*be7b0c9eSWang Nan 	thread_map.map.map[0].comm = NULL;
513*be7b0c9eSWang Nan 	return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
514*be7b0c9eSWang Nan 						 process_synthesized_event,
515*be7b0c9eSWang Nan 						 &rec->session->machines.host,
516*be7b0c9eSWang Nan 						 rec->opts.sample_address,
517*be7b0c9eSWang Nan 						 rec->opts.proc_map_timeout);
518*be7b0c9eSWang Nan }
519*be7b0c9eSWang Nan 
5203c1cb7e3SWang Nan static int record__synthesize(struct record *rec);
5213c1cb7e3SWang Nan 
522ecfd7a9cSWang Nan static int
523ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
524ecfd7a9cSWang Nan {
525ecfd7a9cSWang Nan 	struct perf_data_file *file = &rec->file;
526ecfd7a9cSWang Nan 	int fd, err;
527ecfd7a9cSWang Nan 
528ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
529ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
530ecfd7a9cSWang Nan 
531ecfd7a9cSWang Nan 	rec->samples = 0;
532ecfd7a9cSWang Nan 	record__finish_output(rec);
533ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
534ecfd7a9cSWang Nan 	if (err) {
535ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
536ecfd7a9cSWang Nan 		return -EINVAL;
537ecfd7a9cSWang Nan 	}
538ecfd7a9cSWang Nan 
539ecfd7a9cSWang Nan 	fd = perf_data_file__switch(file, timestamp,
540ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
541ecfd7a9cSWang Nan 				    at_exit);
542ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
543ecfd7a9cSWang Nan 		rec->bytes_written = 0;
544ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
545ecfd7a9cSWang Nan 	}
546ecfd7a9cSWang Nan 
547ecfd7a9cSWang Nan 	if (!quiet)
548ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
549ecfd7a9cSWang Nan 			file->path, timestamp);
5503c1cb7e3SWang Nan 
5513c1cb7e3SWang Nan 	/* Output tracking events */
552*be7b0c9eSWang Nan 	if (!at_exit) {
5533c1cb7e3SWang Nan 		record__synthesize(rec);
5543c1cb7e3SWang Nan 
555*be7b0c9eSWang Nan 		/*
556*be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
557*be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
558*be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
559*be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
560*be7b0c9eSWang Nan 		 * contain map and comm information.
561*be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
562*be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
563*be7b0c9eSWang Nan 		 */
564*be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
565*be7b0c9eSWang Nan 			record__synthesize_workload(rec);
566*be7b0c9eSWang Nan 	}
567ecfd7a9cSWang Nan 	return fd;
568ecfd7a9cSWang Nan }
569ecfd7a9cSWang Nan 
570f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
571f33cbe72SArnaldo Carvalho de Melo 
572f33cbe72SArnaldo Carvalho de Melo /*
573f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
574f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
575f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
576f33cbe72SArnaldo Carvalho de Melo  */
57745604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
57845604710SNamhyung Kim 					siginfo_t *info,
579f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
580f33cbe72SArnaldo Carvalho de Melo {
581f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
582f33cbe72SArnaldo Carvalho de Melo 	done = 1;
583f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
584f33cbe72SArnaldo Carvalho de Melo }
585f33cbe72SArnaldo Carvalho de Melo 
5862dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
5872dd6d8a1SAdrian Hunter 
58846bc29b9SAdrian Hunter int __weak
58946bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
59046bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
59146bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
59246bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
59346bc29b9SAdrian Hunter {
59446bc29b9SAdrian Hunter 	return 0;
59546bc29b9SAdrian Hunter }
59646bc29b9SAdrian Hunter 
597c45c86ebSWang Nan static int record__synthesize(struct record *rec)
598c45c86ebSWang Nan {
599c45c86ebSWang Nan 	struct perf_session *session = rec->session;
600c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
601c45c86ebSWang Nan 	struct perf_data_file *file = &rec->file;
602c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
603c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
604c45c86ebSWang Nan 	int fd = perf_data_file__fd(file);
605c45c86ebSWang Nan 	int err = 0;
606c45c86ebSWang Nan 
607c45c86ebSWang Nan 	if (file->is_pipe) {
608c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
609c45c86ebSWang Nan 						   process_synthesized_event);
610c45c86ebSWang Nan 		if (err < 0) {
611c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
612c45c86ebSWang Nan 			goto out;
613c45c86ebSWang Nan 		}
614c45c86ebSWang Nan 
615c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
616c45c86ebSWang Nan 			/*
617c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
618c45c86ebSWang Nan 			 * there were no tracepoints so its not really
619c45c86ebSWang Nan 			 * an error, just that we don't need to
620c45c86ebSWang Nan 			 * synthesize anything.  We really have to
621c45c86ebSWang Nan 			 * return this more properly and also
622c45c86ebSWang Nan 			 * propagate errors that now are calling die()
623c45c86ebSWang Nan 			 */
624c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
625c45c86ebSWang Nan 								  process_synthesized_event);
626c45c86ebSWang Nan 			if (err <= 0) {
627c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
628c45c86ebSWang Nan 				goto out;
629c45c86ebSWang Nan 			}
630c45c86ebSWang Nan 			rec->bytes_written += err;
631c45c86ebSWang Nan 		}
632c45c86ebSWang Nan 	}
633c45c86ebSWang Nan 
63446bc29b9SAdrian Hunter 	err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
63546bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
63646bc29b9SAdrian Hunter 	if (err)
63746bc29b9SAdrian Hunter 		goto out;
63846bc29b9SAdrian Hunter 
639c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
640c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
641c45c86ebSWang Nan 					session, process_synthesized_event);
642c45c86ebSWang Nan 		if (err)
643c45c86ebSWang Nan 			goto out;
644c45c86ebSWang Nan 	}
645c45c86ebSWang Nan 
646c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
647c45c86ebSWang Nan 						 machine);
648c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
649c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
650c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
651c45c86ebSWang Nan 
652c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
653c45c86ebSWang Nan 					     machine);
654c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
655c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
656c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
657c45c86ebSWang Nan 
658c45c86ebSWang Nan 	if (perf_guest) {
659c45c86ebSWang Nan 		machines__process_guests(&session->machines,
660c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
661c45c86ebSWang Nan 	}
662c45c86ebSWang Nan 
663c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
664c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
665c45c86ebSWang Nan 					    opts->proc_map_timeout);
666c45c86ebSWang Nan out:
667c45c86ebSWang Nan 	return err;
668c45c86ebSWang Nan }
669c45c86ebSWang Nan 
6708c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
67186470930SIngo Molnar {
67257706abcSDavid Ahern 	int err;
67345604710SNamhyung Kim 	int status = 0;
6748b412664SPeter Zijlstra 	unsigned long waking = 0;
67546be604bSZhang, Yanmin 	const bool forks = argc > 0;
67623346f21SArnaldo Carvalho de Melo 	struct machine *machine;
67745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
678b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
679f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
680d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
6816dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
68242aa276fSNamhyung Kim 	int fd;
68386470930SIngo Molnar 
684d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
68533e49ea7SAndi Kleen 
68645604710SNamhyung Kim 	atexit(record__sig_exit);
687f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
688f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
689804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
690c0bdc1c4SWang Nan 
6913c1cb7e3SWang Nan 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
6922dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
6933c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
6945f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
6953c1cb7e3SWang Nan 		if (rec->switch_output)
6963c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
697c0bdc1c4SWang Nan 	} else {
6982dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
699c0bdc1c4SWang Nan 	}
700f5970550SPeter Zijlstra 
701b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
70294c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
703ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
704a9a70bbcSArnaldo Carvalho de Melo 		return -1;
705a9a70bbcSArnaldo Carvalho de Melo 	}
706a9a70bbcSArnaldo Carvalho de Melo 
70742aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
708d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
709d20deb64SArnaldo Carvalho de Melo 
7108c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
711330aa675SStephane Eranian 
712d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
7133e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
714f5fc1412SJiri Olsa 						    argv, file->is_pipe,
715735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
71635b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
71735b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
71845604710SNamhyung Kim 			status = err;
71935b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
720856e9660SPeter Zijlstra 		}
721856e9660SPeter Zijlstra 	}
722856e9660SPeter Zijlstra 
7238c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
7248d3eca20SDavid Ahern 		err = -1;
72545604710SNamhyung Kim 		goto out_child;
7268d3eca20SDavid Ahern 	}
72786470930SIngo Molnar 
7288690a2a7SWang Nan 	err = bpf__apply_obj_config();
7298690a2a7SWang Nan 	if (err) {
7308690a2a7SWang Nan 		char errbuf[BUFSIZ];
7318690a2a7SWang Nan 
7328690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
7338690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
7348690a2a7SWang Nan 			 errbuf);
7358690a2a7SWang Nan 		goto out_child;
7368690a2a7SWang Nan 	}
7378690a2a7SWang Nan 
738cca8482cSAdrian Hunter 	/*
739cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
740cca8482cSAdrian Hunter 	 * evlist.
741cca8482cSAdrian Hunter 	 */
742cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
743cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
744cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
745cca8482cSAdrian Hunter 	}
746cca8482cSAdrian Hunter 
7473e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
748a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
749a8bb559bSNamhyung Kim 
750f5fc1412SJiri Olsa 	if (file->is_pipe) {
75142aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
752529870e3STom Zanussi 		if (err < 0)
75345604710SNamhyung Kim 			goto out_child;
754563aecb2SJiri Olsa 	} else {
75542aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
756d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
75745604710SNamhyung Kim 			goto out_child;
758d5eed904SArnaldo Carvalho de Melo 	}
7597c6a1c65SPeter Zijlstra 
760d3665498SDavid Ahern 	if (!rec->no_buildid
761e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
762d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
763e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
7648d3eca20SDavid Ahern 		err = -1;
76545604710SNamhyung Kim 		goto out_child;
766e20960c0SRobert Richter 	}
767e20960c0SRobert Richter 
76834ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
769743eb868SArnaldo Carvalho de Melo 
770c45c86ebSWang Nan 	err = record__synthesize(rec);
771c45c86ebSWang Nan 	if (err < 0)
77245604710SNamhyung Kim 		goto out_child;
7738d3eca20SDavid Ahern 
774d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
77586470930SIngo Molnar 		struct sched_param param;
77686470930SIngo Molnar 
777d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
77886470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
7796beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
7808d3eca20SDavid Ahern 			err = -1;
78145604710SNamhyung Kim 			goto out_child;
78286470930SIngo Molnar 		}
78386470930SIngo Molnar 	}
78486470930SIngo Molnar 
785774cb499SJiri Olsa 	/*
786774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
787774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
788774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
789774cb499SJiri Olsa 	 */
7906619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
7913e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
792764e16a3SDavid Ahern 
793856e9660SPeter Zijlstra 	/*
794856e9660SPeter Zijlstra 	 * Let the child rip
795856e9660SPeter Zijlstra 	 */
796e803cf97SNamhyung Kim 	if (forks) {
797e5bed564SNamhyung Kim 		union perf_event *event;
798e5bed564SNamhyung Kim 
799e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
800e5bed564SNamhyung Kim 		if (event == NULL) {
801e5bed564SNamhyung Kim 			err = -ENOMEM;
802e5bed564SNamhyung Kim 			goto out_child;
803e5bed564SNamhyung Kim 		}
804e5bed564SNamhyung Kim 
805e803cf97SNamhyung Kim 		/*
806e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
807e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
808e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
809e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
810e803cf97SNamhyung Kim 		 */
811e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
812e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
813e803cf97SNamhyung Kim 					    process_synthesized_event,
814e803cf97SNamhyung Kim 					    machine);
815e5bed564SNamhyung Kim 		free(event);
816e803cf97SNamhyung Kim 
8173e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
818e803cf97SNamhyung Kim 	}
819856e9660SPeter Zijlstra 
8206619a53eSAndi Kleen 	if (opts->initial_delay) {
8216619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
8226619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
8236619a53eSAndi Kleen 	}
8246619a53eSAndi Kleen 
8255f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
8263c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
827649c48a9SPeter Zijlstra 	for (;;) {
8289f065194SYang Shi 		unsigned long long hits = rec->samples;
82986470930SIngo Molnar 
8308c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
8315f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
8323c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
8338d3eca20SDavid Ahern 			err = -1;
83445604710SNamhyung Kim 			goto out_child;
8358d3eca20SDavid Ahern 		}
83686470930SIngo Molnar 
8372dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
8382dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
8395f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
8402dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
8415f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
8422dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
8432dd6d8a1SAdrian Hunter 				err = -1;
8442dd6d8a1SAdrian Hunter 				goto out_child;
8452dd6d8a1SAdrian Hunter 			}
8462dd6d8a1SAdrian Hunter 		}
8472dd6d8a1SAdrian Hunter 
8483c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
8493c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
8503c1cb7e3SWang Nan 
8513c1cb7e3SWang Nan 			if (!quiet)
8523c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
8533c1cb7e3SWang Nan 					waking);
8543c1cb7e3SWang Nan 			waking = 0;
8553c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
8563c1cb7e3SWang Nan 			if (fd < 0) {
8573c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
8583c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
8593c1cb7e3SWang Nan 				err = fd;
8603c1cb7e3SWang Nan 				goto out_child;
8613c1cb7e3SWang Nan 			}
8623c1cb7e3SWang Nan 		}
8633c1cb7e3SWang Nan 
864d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
8656dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
866649c48a9SPeter Zijlstra 				break;
867f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
868a515114fSJiri Olsa 			/*
869a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
870a515114fSJiri Olsa 			 * number of returned events and interrupt error.
871a515114fSJiri Olsa 			 */
872a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
87345604710SNamhyung Kim 				err = 0;
8748b412664SPeter Zijlstra 			waking++;
8756dcf45efSArnaldo Carvalho de Melo 
8766dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
8776dcf45efSArnaldo Carvalho de Melo 				draining = true;
8788b412664SPeter Zijlstra 		}
8798b412664SPeter Zijlstra 
880774cb499SJiri Olsa 		/*
881774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
882774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
883774cb499SJiri Olsa 		 * disable events in this case.
884774cb499SJiri Olsa 		 */
885602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
8865f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
8873e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
8882711926aSJiri Olsa 			disabled = true;
8892711926aSJiri Olsa 		}
8908b412664SPeter Zijlstra 	}
8915f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
8923c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
8938b412664SPeter Zijlstra 
894f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
89535550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
896f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
897f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
898f33cbe72SArnaldo Carvalho de Melo 		err = -1;
89945604710SNamhyung Kim 		goto out_child;
900f33cbe72SArnaldo Carvalho de Melo 	}
901f33cbe72SArnaldo Carvalho de Melo 
902e3d59112SNamhyung Kim 	if (!quiet)
9038b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
90486470930SIngo Molnar 
90545604710SNamhyung Kim out_child:
90645604710SNamhyung Kim 	if (forks) {
90745604710SNamhyung Kim 		int exit_status;
90845604710SNamhyung Kim 
90945604710SNamhyung Kim 		if (!child_finished)
91045604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
91145604710SNamhyung Kim 
91245604710SNamhyung Kim 		wait(&exit_status);
91345604710SNamhyung Kim 
91445604710SNamhyung Kim 		if (err < 0)
91545604710SNamhyung Kim 			status = err;
91645604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
91745604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
91845604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
91945604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
92045604710SNamhyung Kim 	} else
92145604710SNamhyung Kim 		status = err;
92245604710SNamhyung Kim 
923e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
924e3d59112SNamhyung Kim 	rec->samples = 0;
925e3d59112SNamhyung Kim 
926ecfd7a9cSWang Nan 	if (!err) {
927ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
928e1ab48baSWang Nan 			record__finish_output(rec);
929ecfd7a9cSWang Nan 		} else {
930ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
931ecfd7a9cSWang Nan 			if (fd < 0) {
932ecfd7a9cSWang Nan 				status = fd;
933ecfd7a9cSWang Nan 				goto out_delete_session;
934ecfd7a9cSWang Nan 			}
935ecfd7a9cSWang Nan 		}
936ecfd7a9cSWang Nan 	}
93739d17dacSArnaldo Carvalho de Melo 
938e3d59112SNamhyung Kim 	if (!err && !quiet) {
939e3d59112SNamhyung Kim 		char samples[128];
940ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
941ecfd7a9cSWang Nan 					".<timestamp>" : "";
942e3d59112SNamhyung Kim 
943ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
944e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
945e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
946e3d59112SNamhyung Kim 		else
947e3d59112SNamhyung Kim 			samples[0] = '\0';
948e3d59112SNamhyung Kim 
949ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
950e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
951ecfd7a9cSWang Nan 			file->path, postfix, samples);
952e3d59112SNamhyung Kim 	}
953e3d59112SNamhyung Kim 
95439d17dacSArnaldo Carvalho de Melo out_delete_session:
95539d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
95645604710SNamhyung Kim 	return status;
95786470930SIngo Molnar }
95886470930SIngo Molnar 
9590883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
96009b0fd45SJiri Olsa {
961aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
962a601fdffSJiri Olsa 
9630883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
96426d33022SJiri Olsa 
9650883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
96609b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
9670883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
9680883e820SArnaldo Carvalho de Melo }
9690883e820SArnaldo Carvalho de Melo 
9700883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
9710883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
9720883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
9730883e820SArnaldo Carvalho de Melo {
9740883e820SArnaldo Carvalho de Melo 	int ret;
9750883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
9760883e820SArnaldo Carvalho de Melo 
9770883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
9780883e820SArnaldo Carvalho de Melo 	if (unset) {
9790883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
9800883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
9810883e820SArnaldo Carvalho de Melo 		return 0;
9820883e820SArnaldo Carvalho de Melo 	}
9830883e820SArnaldo Carvalho de Melo 
9840883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
9850883e820SArnaldo Carvalho de Melo 	if (!ret) {
9860883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
9870883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
9880883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
9890883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
9900883e820SArnaldo Carvalho de Melo 	}
9910883e820SArnaldo Carvalho de Melo 
9920883e820SArnaldo Carvalho de Melo 	return ret;
99309b0fd45SJiri Olsa }
99409b0fd45SJiri Olsa 
995c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
99609b0fd45SJiri Olsa 			       const char *arg,
99709b0fd45SJiri Olsa 			       int unset)
99809b0fd45SJiri Olsa {
9990883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
100026d33022SJiri Olsa }
100126d33022SJiri Olsa 
1002c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
100309b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
100409b0fd45SJiri Olsa 			 int unset __maybe_unused)
100509b0fd45SJiri Olsa {
10062ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1007c421e80bSKan Liang 
10082ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
100909b0fd45SJiri Olsa 
10102ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
10112ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1012eb853e80SJiri Olsa 
10132ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
101409b0fd45SJiri Olsa 	return 0;
101509b0fd45SJiri Olsa }
101609b0fd45SJiri Olsa 
1017eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1018eb853e80SJiri Olsa {
10197a29c087SNamhyung Kim 	struct record *rec = cb;
10207a29c087SNamhyung Kim 
10217a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
10227a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
10237a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
10247a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
10257a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
10267a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
10277a29c087SNamhyung Kim 			rec->no_buildid = true;
10287a29c087SNamhyung Kim 		else
10297a29c087SNamhyung Kim 			return -1;
10307a29c087SNamhyung Kim 		return 0;
10317a29c087SNamhyung Kim 	}
1032eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
10335a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
1034eb853e80SJiri Olsa 
1035eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
1036eb853e80SJiri Olsa }
1037eb853e80SJiri Olsa 
1038814c8c38SPeter Zijlstra struct clockid_map {
1039814c8c38SPeter Zijlstra 	const char *name;
1040814c8c38SPeter Zijlstra 	int clockid;
1041814c8c38SPeter Zijlstra };
1042814c8c38SPeter Zijlstra 
1043814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1044814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1045814c8c38SPeter Zijlstra 
1046814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1047814c8c38SPeter Zijlstra 
1048814c8c38SPeter Zijlstra 
1049814c8c38SPeter Zijlstra /*
1050814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1051814c8c38SPeter Zijlstra  */
1052814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1053814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1054814c8c38SPeter Zijlstra #endif
1055814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1056814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1057814c8c38SPeter Zijlstra #endif
1058814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1059814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1060814c8c38SPeter Zijlstra #endif
1061814c8c38SPeter Zijlstra 
1062814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1063814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1064814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1065814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1066814c8c38SPeter Zijlstra 
1067814c8c38SPeter Zijlstra 	/* available for some events */
1068814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1069814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1070814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1071814c8c38SPeter Zijlstra 
1072814c8c38SPeter Zijlstra 	/* available for the lazy */
1073814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1074814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1075814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1076814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1077814c8c38SPeter Zijlstra 
1078814c8c38SPeter Zijlstra 	CLOCKID_END,
1079814c8c38SPeter Zijlstra };
1080814c8c38SPeter Zijlstra 
1081814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1082814c8c38SPeter Zijlstra {
1083814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1084814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1085814c8c38SPeter Zijlstra 	const char *ostr = str;
1086814c8c38SPeter Zijlstra 
1087814c8c38SPeter Zijlstra 	if (unset) {
1088814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1089814c8c38SPeter Zijlstra 		return 0;
1090814c8c38SPeter Zijlstra 	}
1091814c8c38SPeter Zijlstra 
1092814c8c38SPeter Zijlstra 	/* no arg passed */
1093814c8c38SPeter Zijlstra 	if (!str)
1094814c8c38SPeter Zijlstra 		return 0;
1095814c8c38SPeter Zijlstra 
1096814c8c38SPeter Zijlstra 	/* no setting it twice */
1097814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1098814c8c38SPeter Zijlstra 		return -1;
1099814c8c38SPeter Zijlstra 
1100814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1101814c8c38SPeter Zijlstra 
1102814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1103814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1104814c8c38SPeter Zijlstra 		return 0;
1105814c8c38SPeter Zijlstra 
1106814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1107814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1108814c8c38SPeter Zijlstra 		str += 6;
1109814c8c38SPeter Zijlstra 
1110814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1111814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1112814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1113814c8c38SPeter Zijlstra 			return 0;
1114814c8c38SPeter Zijlstra 		}
1115814c8c38SPeter Zijlstra 	}
1116814c8c38SPeter Zijlstra 
1117814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1118814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1119814c8c38SPeter Zijlstra 	return -1;
1120814c8c38SPeter Zijlstra }
1121814c8c38SPeter Zijlstra 
1122e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1123e9db1310SAdrian Hunter 				    const char *str,
1124e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1125e9db1310SAdrian Hunter {
1126e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1127e9db1310SAdrian Hunter 	char *s, *p;
1128e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1129e9db1310SAdrian Hunter 	int ret;
1130e9db1310SAdrian Hunter 
1131e9db1310SAdrian Hunter 	if (!str)
1132e9db1310SAdrian Hunter 		return -EINVAL;
1133e9db1310SAdrian Hunter 
1134e9db1310SAdrian Hunter 	s = strdup(str);
1135e9db1310SAdrian Hunter 	if (!s)
1136e9db1310SAdrian Hunter 		return -ENOMEM;
1137e9db1310SAdrian Hunter 
1138e9db1310SAdrian Hunter 	p = strchr(s, ',');
1139e9db1310SAdrian Hunter 	if (p)
1140e9db1310SAdrian Hunter 		*p = '\0';
1141e9db1310SAdrian Hunter 
1142e9db1310SAdrian Hunter 	if (*s) {
1143e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1144e9db1310SAdrian Hunter 		if (ret)
1145e9db1310SAdrian Hunter 			goto out_free;
1146e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1147e9db1310SAdrian Hunter 	}
1148e9db1310SAdrian Hunter 
1149e9db1310SAdrian Hunter 	if (!p) {
1150e9db1310SAdrian Hunter 		ret = 0;
1151e9db1310SAdrian Hunter 		goto out_free;
1152e9db1310SAdrian Hunter 	}
1153e9db1310SAdrian Hunter 
1154e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1155e9db1310SAdrian Hunter 	if (ret)
1156e9db1310SAdrian Hunter 		goto out_free;
1157e9db1310SAdrian Hunter 
1158e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1159e9db1310SAdrian Hunter 
1160e9db1310SAdrian Hunter out_free:
1161e9db1310SAdrian Hunter 	free(s);
1162e9db1310SAdrian Hunter 	return ret;
1163e9db1310SAdrian Hunter }
1164e9db1310SAdrian Hunter 
1165e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
116686470930SIngo Molnar 	"perf record [<options>] [<command>]",
116786470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
116886470930SIngo Molnar 	NULL
116986470930SIngo Molnar };
1170e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
117186470930SIngo Molnar 
1172d20deb64SArnaldo Carvalho de Melo /*
11738c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
11748c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1175d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1176d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1177d20deb64SArnaldo Carvalho de Melo  *
1178d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1179d20deb64SArnaldo Carvalho de Melo  *
1180d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1181d20deb64SArnaldo Carvalho de Melo  */
11828c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1183d20deb64SArnaldo Carvalho de Melo 	.opts = {
11848affc2b8SAndi Kleen 		.sample_time	     = true,
1185d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1186d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1187d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1188447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1189d1cb9fceSNamhyung Kim 		.target		     = {
1190d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
11913aa5939dSAdrian Hunter 			.default_per_cpu = true,
1192d1cb9fceSNamhyung Kim 		},
11939d9cad76SKan Liang 		.proc_map_timeout     = 500,
1194d20deb64SArnaldo Carvalho de Melo 	},
1195e3d59112SNamhyung Kim 	.tool = {
1196e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1197e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1198cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1199e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1200e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1201e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1202cca8482cSAdrian Hunter 		.ordered_events	= true,
1203e3d59112SNamhyung Kim 	},
1204d20deb64SArnaldo Carvalho de Melo };
12057865e817SFrederic Weisbecker 
120676a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
120776a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
120861eaa3beSArnaldo Carvalho de Melo 
1209d20deb64SArnaldo Carvalho de Melo /*
1210d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1211d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1212b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1213d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1214d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1215d20deb64SArnaldo Carvalho de Melo  */
1216e5b2c207SNamhyung Kim struct option __record_options[] = {
1217d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
121886470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1219f120f9d5SJiri Olsa 		     parse_events_option),
1220d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1221c171b552SLi Zefan 		     "event filter", parse_filter),
12224ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
12234ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
12244ba1faa1SWang Nan 			   exclude_perf),
1225bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1226d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1227bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1228d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1229d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
123086470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1231509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1232acac03faSKirill Smelkov 		    "collect data without buffering"),
1233d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1234daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1235bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
123686470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1237bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1238c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1239d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1240f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
124186470930SIngo Molnar 		    "output file name"),
124269e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
124369e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
12442e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1245d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1246e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1247e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1248e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1249d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
125043bece79SLin Ming 		    "put the counters into a counter group"),
12512ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
125209b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
125309b0fd45SJiri Olsa 			   &record_callchain_opt),
125409b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
125576a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
125609b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1257c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
12583da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1259b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1260d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1261649c48a9SPeter Zijlstra 		    "per thread counts"),
126256100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
12633abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
12643abebc55SAdrian Hunter 			&record.opts.sample_time_set,
12653abebc55SAdrian Hunter 			"Record the sample timestamps"),
126656100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1267d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1268649c48a9SPeter Zijlstra 		    "don't sample"),
1269d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1270d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1271a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1272d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1273d2db9a98SWang Nan 			&record.no_buildid_set,
1274baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1275d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1276023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1277023695d9SStephane Eranian 		     parse_cgroups),
1278a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
12796619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1280bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1281bea03405SNamhyung Kim 		   "user to profile"),
1282a5aabdacSStephane Eranian 
1283a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1284a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1285a5aabdacSStephane Eranian 		     parse_branch_stack),
1286a5aabdacSStephane Eranian 
1287a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1288a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1289bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
129005484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
129105484298SAndi Kleen 		    "sample by weight (on special events only)"),
1292475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1293475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
12943aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
12953aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1296bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1297bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1298bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
129985c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
130085c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1301814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1302814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1303814c8c38SPeter Zijlstra 	parse_clockid),
13042dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
13052dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
13069d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
13079d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1308b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1309b757bb09SAdrian Hunter 		    "Record context switch events"),
131085723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
131185723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
131285723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
131385723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
131485723885SJiri Olsa 			 "Configure all used events to run in user space.",
131585723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
131671dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
131771dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
131871dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
131971dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
13207efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
13217efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
13226156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
13236156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1324ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1325ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
13263c1cb7e3SWang Nan 	OPT_BOOLEAN(0, "switch-output", &record.switch_output,
13273c1cb7e3SWang Nan 		    "Switch output when receive SIGUSR2"),
132886470930SIngo Molnar 	OPT_END()
132986470930SIngo Molnar };
133086470930SIngo Molnar 
1331e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1332e5b2c207SNamhyung Kim 
13331d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
133486470930SIngo Molnar {
1335ef149c25SAdrian Hunter 	int err;
13368c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
133716ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
133886470930SIngo Molnar 
133948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
134048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
134148e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
134248e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
134348e1cab1SWang Nan # undef set_nobuild
134448e1cab1SWang Nan #endif
134548e1cab1SWang Nan 
13467efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
13477efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
13487efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
13497efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
13507efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
13517efe0e03SHe Kuang # else
13527efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
13537efe0e03SHe Kuang # endif
13547efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
13557efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
13567efe0e03SHe Kuang # undef set_nobuild
13577efe0e03SHe Kuang # undef REASON
13587efe0e03SHe Kuang #endif
13597efe0e03SHe Kuang 
13603e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
13613e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1362361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1363361c99a6SArnaldo Carvalho de Melo 
1364eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1365eb853e80SJiri Olsa 
1366bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1367a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1368602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1369bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
137086470930SIngo Molnar 
1371bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1372c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1373c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1374c7118369SNamhyung Kim 
1375023695d9SStephane Eranian 	}
1376b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1377b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1378c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1379c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1380c7118369SNamhyung Kim 		return -EINVAL;
1381b757bb09SAdrian Hunter 	}
1382023695d9SStephane Eranian 
1383eca857abSWang Nan 	if (rec->switch_output)
1384eca857abSWang Nan 		rec->timestamp_filename = true;
1385eca857abSWang Nan 
1386ef149c25SAdrian Hunter 	if (!rec->itr) {
1387ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1388ef149c25SAdrian Hunter 		if (err)
1389ef149c25SAdrian Hunter 			return err;
1390ef149c25SAdrian Hunter 	}
1391ef149c25SAdrian Hunter 
13922dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
13932dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
13942dd6d8a1SAdrian Hunter 	if (err)
13952dd6d8a1SAdrian Hunter 		return err;
13962dd6d8a1SAdrian Hunter 
1397d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1398d7888573SWang Nan 	if (err) {
1399d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1400d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1401d7888573SWang Nan 			 errbuf);
1402d7888573SWang Nan 		return err;
1403d7888573SWang Nan 	}
1404d7888573SWang Nan 
1405ef149c25SAdrian Hunter 	err = -ENOMEM;
1406ef149c25SAdrian Hunter 
14070a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1408baa2f6ceSArnaldo Carvalho de Melo 
1409ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1410646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1411646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1412ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1413646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1414646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1415646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1416646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1417646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1418ec80fde7SArnaldo Carvalho de Melo 
14190c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
1420a1ac1d3cSStephane Eranian 		disable_buildid_cache();
14210c1d46a8SWang Nan 	} else if (rec->switch_output) {
14220c1d46a8SWang Nan 		/*
14230c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
14240c1d46a8SWang Nan 		 * generation by default to reduce data file switching
14250c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
14260c1d46a8SWang Nan 		 * explicitly using
14270c1d46a8SWang Nan 		 *
14280c1d46a8SWang Nan 		 *  perf record --signal-trigger --no-no-buildid \
14290c1d46a8SWang Nan 		 *              --no-no-buildid-cache
14300c1d46a8SWang Nan 		 *
14310c1d46a8SWang Nan 		 * Following code equals to:
14320c1d46a8SWang Nan 		 *
14330c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
14340c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
14350c1d46a8SWang Nan 		 *         disable_buildid_cache();
14360c1d46a8SWang Nan 		 */
14370c1d46a8SWang Nan 		bool disable = true;
14380c1d46a8SWang Nan 
14390c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
14400c1d46a8SWang Nan 			disable = false;
14410c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
14420c1d46a8SWang Nan 			disable = false;
14430c1d46a8SWang Nan 		if (disable) {
14440c1d46a8SWang Nan 			rec->no_buildid = true;
14450c1d46a8SWang Nan 			rec->no_buildid_cache = true;
14460c1d46a8SWang Nan 			disable_buildid_cache();
14470c1d46a8SWang Nan 		}
14480c1d46a8SWang Nan 	}
1449655000e7SArnaldo Carvalho de Melo 
14503e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
14513e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
145269aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
145369aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1454bbd36e5eSPeter Zijlstra 	}
145586470930SIngo Molnar 
145669e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
145769e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
145869e7e5b0SAdrian Hunter 
1459602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
146016ad2ffbSNamhyung Kim 	if (err) {
1461602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
146216ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
146316ad2ffbSNamhyung Kim 	}
14644bd0f2d2SNamhyung Kim 
1465602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
146616ad2ffbSNamhyung Kim 	if (err) {
146716ad2ffbSNamhyung Kim 		int saved_errno = errno;
146816ad2ffbSNamhyung Kim 
1469602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
14703780f488SNamhyung Kim 		ui__error("%s", errbuf);
147116ad2ffbSNamhyung Kim 
147216ad2ffbSNamhyung Kim 		err = -saved_errno;
14738fa60e1fSNamhyung Kim 		goto out_symbol_exit;
147416ad2ffbSNamhyung Kim 	}
14750d37aa34SArnaldo Carvalho de Melo 
147616ad2ffbSNamhyung Kim 	err = -ENOMEM;
14773e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1478dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
147969aad6f1SArnaldo Carvalho de Melo 
1480ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1481ef149c25SAdrian Hunter 	if (err)
1482ef149c25SAdrian Hunter 		goto out_symbol_exit;
1483ef149c25SAdrian Hunter 
14846156681bSNamhyung Kim 	/*
14856156681bSNamhyung Kim 	 * We take all buildids when the file contains
14866156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
14876156681bSNamhyung Kim 	 * trace because it would take too long.
14886156681bSNamhyung Kim 	 */
14896156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
14906156681bSNamhyung Kim 		rec->buildid_all = true;
14916156681bSNamhyung Kim 
1492b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
149339d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
149403ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
14957e4ff9e3SMike Galbraith 	}
14967e4ff9e3SMike Galbraith 
1497d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1498d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
149945604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1500d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1501ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
150239d17dacSArnaldo Carvalho de Melo 	return err;
150386470930SIngo Molnar }
15042dd6d8a1SAdrian Hunter 
15052dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
15062dd6d8a1SAdrian Hunter {
15075f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
15085f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
15092dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
15105f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
15115f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
15125f9cf599SWang Nan 	}
15133c1cb7e3SWang Nan 
15143c1cb7e3SWang Nan 	if (trigger_is_ready(&switch_output_trigger))
15153c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
15162dd6d8a1SAdrian Hunter }
1517