xref: /openbmc/linux/tools/perf/builtin-record.c (revision 6156681b73f2fffe56493e9a50518c0cbfcd8ba3)
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"
32f00898f4SAndi Kleen #include "util/parse-branch-options.h"
33bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3471dc2326SWang Nan #include "util/llvm-utils.h"
357c6a1c65SPeter Zijlstra 
3686470930SIngo Molnar #include <unistd.h>
3786470930SIngo Molnar #include <sched.h>
38a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
3986470930SIngo Molnar 
4078da39faSBernhard Rosenkraenzer 
418c6f45a7SArnaldo Carvalho de Melo struct record {
4245694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
43b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
44d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
45f5fc1412SJiri Olsa 	struct perf_data_file	file;
46ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
47d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
48d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
49d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
50d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
51d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
52d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
53*6156681bSNamhyung Kim 	bool			buildid_all;
549f065194SYang Shi 	unsigned long long	samples;
550f82ebc4SArnaldo Carvalho de Melo };
5686470930SIngo Molnar 
578c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
58f5970550SPeter Zijlstra {
59cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
604f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
618d3eca20SDavid Ahern 		return -1;
628d3eca20SDavid Ahern 	}
63f5970550SPeter Zijlstra 
64cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
658d3eca20SDavid Ahern 	return 0;
66f5970550SPeter Zijlstra }
67f5970550SPeter Zijlstra 
6845694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
69d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
701d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
711d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
72234fbbf5SArnaldo Carvalho de Melo {
738c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
748c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
75234fbbf5SArnaldo Carvalho de Melo }
76234fbbf5SArnaldo Carvalho de Melo 
77e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
7886470930SIngo Molnar {
79e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
807b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
817b8283b5SDavid Ahern 	u64 old = md->prev;
82918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
8386470930SIngo Molnar 	unsigned long size;
8486470930SIngo Molnar 	void *buf;
858d3eca20SDavid Ahern 	int rc = 0;
8686470930SIngo Molnar 
87dc82009aSArnaldo Carvalho de Melo 	if (old == head)
888d3eca20SDavid Ahern 		return 0;
8986470930SIngo Molnar 
90d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
9186470930SIngo Molnar 
9286470930SIngo Molnar 	size = head - old;
9386470930SIngo Molnar 
9486470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
9586470930SIngo Molnar 		buf = &data[old & md->mask];
9686470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
9786470930SIngo Molnar 		old += size;
9886470930SIngo Molnar 
998c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
1008d3eca20SDavid Ahern 			rc = -1;
1018d3eca20SDavid Ahern 			goto out;
1028d3eca20SDavid Ahern 		}
10386470930SIngo Molnar 	}
10486470930SIngo Molnar 
10586470930SIngo Molnar 	buf = &data[old & md->mask];
10686470930SIngo Molnar 	size = head - old;
10786470930SIngo Molnar 	old += size;
10886470930SIngo Molnar 
1098c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1108d3eca20SDavid Ahern 		rc = -1;
1118d3eca20SDavid Ahern 		goto out;
1128d3eca20SDavid Ahern 	}
11386470930SIngo Molnar 
11486470930SIngo Molnar 	md->prev = old;
115e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1168d3eca20SDavid Ahern out:
1178d3eca20SDavid Ahern 	return rc;
11886470930SIngo Molnar }
11986470930SIngo Molnar 
1202dd6d8a1SAdrian Hunter static volatile int done;
1212dd6d8a1SAdrian Hunter static volatile int signr = -1;
1222dd6d8a1SAdrian Hunter static volatile int child_finished;
1232dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled;
1242dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err;
1252dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1262dd6d8a1SAdrian Hunter 
1272dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1282dd6d8a1SAdrian Hunter {
1292dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1302dd6d8a1SAdrian Hunter 		child_finished = 1;
1312dd6d8a1SAdrian Hunter 	else
1322dd6d8a1SAdrian Hunter 		signr = sig;
1332dd6d8a1SAdrian Hunter 
1342dd6d8a1SAdrian Hunter 	done = 1;
1352dd6d8a1SAdrian Hunter }
1362dd6d8a1SAdrian Hunter 
1372dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1382dd6d8a1SAdrian Hunter {
1392dd6d8a1SAdrian Hunter 	if (signr == -1)
1402dd6d8a1SAdrian Hunter 		return;
1412dd6d8a1SAdrian Hunter 
1422dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1432dd6d8a1SAdrian Hunter 	raise(signr);
1442dd6d8a1SAdrian Hunter }
1452dd6d8a1SAdrian Hunter 
146e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
147e31f0d01SAdrian Hunter 
148ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
149ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
150ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
151ef149c25SAdrian Hunter {
152ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
15399fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
154ef149c25SAdrian Hunter 	size_t padding;
155ef149c25SAdrian Hunter 	u8 pad[8] = {0};
156ef149c25SAdrian Hunter 
15799fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
15899fa2984SAdrian Hunter 		off_t file_offset;
15999fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
16099fa2984SAdrian Hunter 		int err;
16199fa2984SAdrian Hunter 
16299fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
16399fa2984SAdrian Hunter 		if (file_offset == -1)
16499fa2984SAdrian Hunter 			return -1;
16599fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
16699fa2984SAdrian Hunter 						     event, file_offset);
16799fa2984SAdrian Hunter 		if (err)
16899fa2984SAdrian Hunter 			return err;
16999fa2984SAdrian Hunter 	}
17099fa2984SAdrian Hunter 
171ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
172ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
173ef149c25SAdrian Hunter 	if (padding)
174ef149c25SAdrian Hunter 		padding = 8 - padding;
175ef149c25SAdrian Hunter 
176ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
177ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
178ef149c25SAdrian Hunter 	if (len2)
179ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
180ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
181ef149c25SAdrian Hunter 
182ef149c25SAdrian Hunter 	return 0;
183ef149c25SAdrian Hunter }
184ef149c25SAdrian Hunter 
185ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
186ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
187ef149c25SAdrian Hunter {
188ef149c25SAdrian Hunter 	int ret;
189ef149c25SAdrian Hunter 
190ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
191ef149c25SAdrian Hunter 				  record__process_auxtrace);
192ef149c25SAdrian Hunter 	if (ret < 0)
193ef149c25SAdrian Hunter 		return ret;
194ef149c25SAdrian Hunter 
195ef149c25SAdrian Hunter 	if (ret)
196ef149c25SAdrian Hunter 		rec->samples++;
197ef149c25SAdrian Hunter 
198ef149c25SAdrian Hunter 	return 0;
199ef149c25SAdrian Hunter }
200ef149c25SAdrian Hunter 
2012dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2022dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2032dd6d8a1SAdrian Hunter {
2042dd6d8a1SAdrian Hunter 	int ret;
2052dd6d8a1SAdrian Hunter 
2062dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2072dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2082dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2092dd6d8a1SAdrian Hunter 	if (ret < 0)
2102dd6d8a1SAdrian Hunter 		return ret;
2112dd6d8a1SAdrian Hunter 
2122dd6d8a1SAdrian Hunter 	if (ret)
2132dd6d8a1SAdrian Hunter 		rec->samples++;
2142dd6d8a1SAdrian Hunter 
2152dd6d8a1SAdrian Hunter 	return 0;
2162dd6d8a1SAdrian Hunter }
2172dd6d8a1SAdrian Hunter 
2182dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2192dd6d8a1SAdrian Hunter {
2202dd6d8a1SAdrian Hunter 	int i;
2212dd6d8a1SAdrian Hunter 	int rc = 0;
2222dd6d8a1SAdrian Hunter 
2232dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2242dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2252dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2262dd6d8a1SAdrian Hunter 
2272dd6d8a1SAdrian Hunter 		if (!mm->base)
2282dd6d8a1SAdrian Hunter 			continue;
2292dd6d8a1SAdrian Hunter 
2302dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2312dd6d8a1SAdrian Hunter 			rc = -1;
2322dd6d8a1SAdrian Hunter 			goto out;
2332dd6d8a1SAdrian Hunter 		}
2342dd6d8a1SAdrian Hunter 	}
2352dd6d8a1SAdrian Hunter out:
2362dd6d8a1SAdrian Hunter 	return rc;
2372dd6d8a1SAdrian Hunter }
2382dd6d8a1SAdrian Hunter 
2392dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2402dd6d8a1SAdrian Hunter {
2412dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2422dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2432dd6d8a1SAdrian Hunter 		auxtrace_snapshot_err = -1;
2442dd6d8a1SAdrian Hunter 	} else {
2452dd6d8a1SAdrian Hunter 		auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr);
2462dd6d8a1SAdrian Hunter 		if (!auxtrace_snapshot_err)
2472dd6d8a1SAdrian Hunter 			auxtrace_snapshot_enabled = 1;
2482dd6d8a1SAdrian Hunter 	}
2492dd6d8a1SAdrian Hunter }
2502dd6d8a1SAdrian Hunter 
251e31f0d01SAdrian Hunter #else
252e31f0d01SAdrian Hunter 
253e31f0d01SAdrian Hunter static inline
254e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
255e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
256e31f0d01SAdrian Hunter {
257e31f0d01SAdrian Hunter 	return 0;
258e31f0d01SAdrian Hunter }
259e31f0d01SAdrian Hunter 
2602dd6d8a1SAdrian Hunter static inline
2612dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2622dd6d8a1SAdrian Hunter {
2632dd6d8a1SAdrian Hunter }
2642dd6d8a1SAdrian Hunter 
2652dd6d8a1SAdrian Hunter static inline
2662dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2672dd6d8a1SAdrian Hunter {
2682dd6d8a1SAdrian Hunter 	return 0;
2692dd6d8a1SAdrian Hunter }
2702dd6d8a1SAdrian Hunter 
271e31f0d01SAdrian Hunter #endif
272e31f0d01SAdrian Hunter 
2738c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
274dd7927f4SArnaldo Carvalho de Melo {
27556e52e85SArnaldo Carvalho de Melo 	char msg[512];
2766a4bb04cSJiri Olsa 	struct perf_evsel *pos;
277d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
278d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
279b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
2808d3eca20SDavid Ahern 	int rc = 0;
281dd7927f4SArnaldo Carvalho de Melo 
282f77a9518SArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts);
283cac21425SJiri Olsa 
2840050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
2853da297a6SIngo Molnar try_again:
286d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
28756e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
2883da297a6SIngo Molnar 				if (verbose)
289c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
2903da297a6SIngo Molnar 				goto try_again;
2913da297a6SIngo Molnar 			}
292ca6a4258SDavid Ahern 
29356e52e85SArnaldo Carvalho de Melo 			rc = -errno;
29456e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
29556e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
29656e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
2978d3eca20SDavid Ahern 			goto out;
2987c6a1c65SPeter Zijlstra 		}
2997c6a1c65SPeter Zijlstra 	}
3007c6a1c65SPeter Zijlstra 
30123d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
30223d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
30323d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
30435550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3058d3eca20SDavid Ahern 		rc = -1;
3068d3eca20SDavid Ahern 		goto out;
3070a102479SFrederic Weisbecker 	}
3080a102479SFrederic Weisbecker 
309ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3102dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3112dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3128d3eca20SDavid Ahern 		if (errno == EPERM) {
3138d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
31418e60939SNelson Elhage 			       "Consider increasing "
31518e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
31618e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
317ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
318ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3198d3eca20SDavid Ahern 			rc = -errno;
3208d3eca20SDavid Ahern 		} else {
32135550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
32235550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
3238d3eca20SDavid Ahern 			rc = -errno;
3248d3eca20SDavid Ahern 		}
3258d3eca20SDavid Ahern 		goto out;
32618e60939SNelson Elhage 	}
3270a27d7f9SArnaldo Carvalho de Melo 
328a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3297b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3308d3eca20SDavid Ahern out:
3318d3eca20SDavid Ahern 	return rc;
332a91e5431SArnaldo Carvalho de Melo }
333a91e5431SArnaldo Carvalho de Melo 
334e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
335e3d59112SNamhyung Kim 				union perf_event *event,
336e3d59112SNamhyung Kim 				struct perf_sample *sample,
337e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
338e3d59112SNamhyung Kim 				struct machine *machine)
339e3d59112SNamhyung Kim {
340e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
341e3d59112SNamhyung Kim 
342e3d59112SNamhyung Kim 	rec->samples++;
343e3d59112SNamhyung Kim 
344e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
345e3d59112SNamhyung Kim }
346e3d59112SNamhyung Kim 
3478c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
3486122e4e4SArnaldo Carvalho de Melo {
349f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
350f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
3516122e4e4SArnaldo Carvalho de Melo 
352457ae94aSHe Kuang 	if (file->size == 0)
3539f591fd7SArnaldo Carvalho de Melo 		return 0;
3549f591fd7SArnaldo Carvalho de Melo 
35500dc8657SNamhyung Kim 	/*
35600dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
35700dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
35800dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
35900dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
36000dc8657SNamhyung Kim 	 *
36100dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
36200dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
36300dc8657SNamhyung Kim 	 */
36400dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
36500dc8657SNamhyung Kim 
366*6156681bSNamhyung Kim 	/*
367*6156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
368*6156681bSNamhyung Kim 	 * so no need to process samples.
369*6156681bSNamhyung Kim 	 */
370*6156681bSNamhyung Kim 	if (rec->buildid_all)
371*6156681bSNamhyung Kim 		rec->tool.sample = NULL;
372*6156681bSNamhyung Kim 
373b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
3746122e4e4SArnaldo Carvalho de Melo }
3756122e4e4SArnaldo Carvalho de Melo 
3768115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
377a1645ce1SZhang, Yanmin {
378a1645ce1SZhang, Yanmin 	int err;
37945694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
380a1645ce1SZhang, Yanmin 	/*
381a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
382a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
383a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
384a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
385a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
386a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
387a1645ce1SZhang, Yanmin 	 */
38845694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
389743eb868SArnaldo Carvalho de Melo 					     machine);
390a1645ce1SZhang, Yanmin 	if (err < 0)
391a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
39223346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
393a1645ce1SZhang, Yanmin 
394a1645ce1SZhang, Yanmin 	/*
395a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
396a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
397a1645ce1SZhang, Yanmin 	 */
39845694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
3990ae617beSAdrian Hunter 						 machine);
400a1645ce1SZhang, Yanmin 	if (err < 0)
401a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
40223346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
403a1645ce1SZhang, Yanmin }
404a1645ce1SZhang, Yanmin 
40598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
40698402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
40798402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
40898402807SFrederic Weisbecker };
40998402807SFrederic Weisbecker 
4108c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
41198402807SFrederic Weisbecker {
412dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4130e2e63ddSPeter Zijlstra 	int i;
4148d3eca20SDavid Ahern 	int rc = 0;
41598402807SFrederic Weisbecker 
416d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
417ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
418ef149c25SAdrian Hunter 
4198d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
420e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4218d3eca20SDavid Ahern 				rc = -1;
4228d3eca20SDavid Ahern 				goto out;
4238d3eca20SDavid Ahern 			}
4248d3eca20SDavid Ahern 		}
425ef149c25SAdrian Hunter 
4262dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
427ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
428ef149c25SAdrian Hunter 			rc = -1;
429ef149c25SAdrian Hunter 			goto out;
430ef149c25SAdrian Hunter 		}
43198402807SFrederic Weisbecker 	}
43298402807SFrederic Weisbecker 
433dcabb507SJiri Olsa 	/*
434dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
435dcabb507SJiri Olsa 	 * at least one event.
436dcabb507SJiri Olsa 	 */
437dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
4388c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
4398d3eca20SDavid Ahern 
4408d3eca20SDavid Ahern out:
4418d3eca20SDavid Ahern 	return rc;
44298402807SFrederic Weisbecker }
44398402807SFrederic Weisbecker 
4448c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
44557706abcSDavid Ahern {
44657706abcSDavid Ahern 	struct perf_session *session = rec->session;
44757706abcSDavid Ahern 	int feat;
44857706abcSDavid Ahern 
44957706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
45057706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
45157706abcSDavid Ahern 
45257706abcSDavid Ahern 	if (rec->no_buildid)
45357706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
45457706abcSDavid Ahern 
4553e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
45657706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
45757706abcSDavid Ahern 
45857706abcSDavid Ahern 	if (!rec->opts.branch_stack)
45957706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
460ef149c25SAdrian Hunter 
461ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
462ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
463ffa517adSJiri Olsa 
464ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
46557706abcSDavid Ahern }
46657706abcSDavid Ahern 
467f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
468f33cbe72SArnaldo Carvalho de Melo 
469f33cbe72SArnaldo Carvalho de Melo /*
470f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
471f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
472f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
473f33cbe72SArnaldo Carvalho de Melo  */
47445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
47545604710SNamhyung Kim 					siginfo_t *info,
476f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
477f33cbe72SArnaldo Carvalho de Melo {
478f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
479f33cbe72SArnaldo Carvalho de Melo 	done = 1;
480f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
481f33cbe72SArnaldo Carvalho de Melo }
482f33cbe72SArnaldo Carvalho de Melo 
4832dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
4842dd6d8a1SAdrian Hunter 
4858c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
48686470930SIngo Molnar {
48757706abcSDavid Ahern 	int err;
48845604710SNamhyung Kim 	int status = 0;
4898b412664SPeter Zijlstra 	unsigned long waking = 0;
49046be604bSZhang, Yanmin 	const bool forks = argc > 0;
49123346f21SArnaldo Carvalho de Melo 	struct machine *machine;
49245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
493b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
494f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
495d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
4966dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
49742aa276fSNamhyung Kim 	int fd;
49886470930SIngo Molnar 
499d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
50033e49ea7SAndi Kleen 
50145604710SNamhyung Kim 	atexit(record__sig_exit);
502f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
503f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
504804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
5052dd6d8a1SAdrian Hunter 	if (rec->opts.auxtrace_snapshot_mode)
5062dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
5072dd6d8a1SAdrian Hunter 	else
5082dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
509f5970550SPeter Zijlstra 
510b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
51194c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
512ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
513a9a70bbcSArnaldo Carvalho de Melo 		return -1;
514a9a70bbcSArnaldo Carvalho de Melo 	}
515a9a70bbcSArnaldo Carvalho de Melo 
51642aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
517d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
518d20deb64SArnaldo Carvalho de Melo 
5198c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
520330aa675SStephane Eranian 
521d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
5223e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
523f5fc1412SJiri Olsa 						    argv, file->is_pipe,
524735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
52535b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
52635b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
52745604710SNamhyung Kim 			status = err;
52835b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
529856e9660SPeter Zijlstra 		}
530856e9660SPeter Zijlstra 	}
531856e9660SPeter Zijlstra 
5328c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
5338d3eca20SDavid Ahern 		err = -1;
53445604710SNamhyung Kim 		goto out_child;
5358d3eca20SDavid Ahern 	}
53686470930SIngo Molnar 
537cca8482cSAdrian Hunter 	/*
538cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
539cca8482cSAdrian Hunter 	 * evlist.
540cca8482cSAdrian Hunter 	 */
541cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
542cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
543cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
544cca8482cSAdrian Hunter 	}
545cca8482cSAdrian Hunter 
5463e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
547a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
548a8bb559bSNamhyung Kim 
549f5fc1412SJiri Olsa 	if (file->is_pipe) {
55042aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
551529870e3STom Zanussi 		if (err < 0)
55245604710SNamhyung Kim 			goto out_child;
553563aecb2SJiri Olsa 	} else {
55442aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
555d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
55645604710SNamhyung Kim 			goto out_child;
557d5eed904SArnaldo Carvalho de Melo 	}
5587c6a1c65SPeter Zijlstra 
559d3665498SDavid Ahern 	if (!rec->no_buildid
560e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
561d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
562e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
5638d3eca20SDavid Ahern 		err = -1;
56445604710SNamhyung Kim 		goto out_child;
565e20960c0SRobert Richter 	}
566e20960c0SRobert Richter 
56734ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
568743eb868SArnaldo Carvalho de Melo 
569f5fc1412SJiri Olsa 	if (file->is_pipe) {
57045694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
571a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
5722c46dbb5STom Zanussi 		if (err < 0) {
5732c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
57445604710SNamhyung Kim 			goto out_child;
5752c46dbb5STom Zanussi 		}
576cd19a035STom Zanussi 
5773e2be2daSArnaldo Carvalho de Melo 		if (have_tracepoints(&rec->evlist->entries)) {
57863e0c771STom Zanussi 			/*
57963e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
58063e0c771STom Zanussi 			 * there were no tracepoints so its not really
58163e0c771STom Zanussi 			 * an error, just that we don't need to
58263e0c771STom Zanussi 			 * synthesize anything.  We really have to
58363e0c771STom Zanussi 			 * return this more properly and also
58463e0c771STom Zanussi 			 * propagate errors that now are calling die()
58563e0c771STom Zanussi 			 */
58642aa276fSNamhyung Kim 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
587743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
58863e0c771STom Zanussi 			if (err <= 0) {
58963e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
59045604710SNamhyung Kim 				goto out_child;
59163e0c771STom Zanussi 			}
592f34b9001SDavid Ahern 			rec->bytes_written += err;
5932c46dbb5STom Zanussi 		}
59463e0c771STom Zanussi 	}
5952c46dbb5STom Zanussi 
596ef149c25SAdrian Hunter 	if (rec->opts.full_auxtrace) {
597ef149c25SAdrian Hunter 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
598ef149c25SAdrian Hunter 					session, process_synthesized_event);
599ef149c25SAdrian Hunter 		if (err)
600ef149c25SAdrian Hunter 			goto out_delete_session;
601ef149c25SAdrian Hunter 	}
602ef149c25SAdrian Hunter 
60345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
6040ae617beSAdrian Hunter 						 machine);
605c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
606c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
607c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
608c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
60956b03f3cSArnaldo Carvalho de Melo 
61045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
611743eb868SArnaldo Carvalho de Melo 					     machine);
612c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
613c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
614c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
615c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
616c1a3a4b9SArnaldo Carvalho de Melo 
6177e383de4SArnaldo Carvalho de Melo 	if (perf_guest) {
618876650e6SArnaldo Carvalho de Melo 		machines__process_guests(&session->machines,
6197e383de4SArnaldo Carvalho de Melo 					 perf_event__synthesize_guest_os, tool);
6207e383de4SArnaldo Carvalho de Melo 	}
621b7cece76SArnaldo Carvalho de Melo 
6223e2be2daSArnaldo Carvalho de Melo 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
6239d9cad76SKan Liang 					    process_synthesized_event, opts->sample_address,
6249d9cad76SKan Liang 					    opts->proc_map_timeout);
6258d3eca20SDavid Ahern 	if (err != 0)
62645604710SNamhyung Kim 		goto out_child;
6278d3eca20SDavid Ahern 
628d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
62986470930SIngo Molnar 		struct sched_param param;
63086470930SIngo Molnar 
631d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
63286470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6336beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
6348d3eca20SDavid Ahern 			err = -1;
63545604710SNamhyung Kim 			goto out_child;
63686470930SIngo Molnar 		}
63786470930SIngo Molnar 	}
63886470930SIngo Molnar 
639774cb499SJiri Olsa 	/*
640774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
641774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
642774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
643774cb499SJiri Olsa 	 */
6446619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
6453e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
646764e16a3SDavid Ahern 
647856e9660SPeter Zijlstra 	/*
648856e9660SPeter Zijlstra 	 * Let the child rip
649856e9660SPeter Zijlstra 	 */
650e803cf97SNamhyung Kim 	if (forks) {
651e5bed564SNamhyung Kim 		union perf_event *event;
652e5bed564SNamhyung Kim 
653e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
654e5bed564SNamhyung Kim 		if (event == NULL) {
655e5bed564SNamhyung Kim 			err = -ENOMEM;
656e5bed564SNamhyung Kim 			goto out_child;
657e5bed564SNamhyung Kim 		}
658e5bed564SNamhyung Kim 
659e803cf97SNamhyung Kim 		/*
660e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
661e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
662e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
663e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
664e803cf97SNamhyung Kim 		 */
665e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
666e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
667e803cf97SNamhyung Kim 					    process_synthesized_event,
668e803cf97SNamhyung Kim 					    machine);
669e5bed564SNamhyung Kim 		free(event);
670e803cf97SNamhyung Kim 
6713e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
672e803cf97SNamhyung Kim 	}
673856e9660SPeter Zijlstra 
6746619a53eSAndi Kleen 	if (opts->initial_delay) {
6756619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
6766619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
6776619a53eSAndi Kleen 	}
6786619a53eSAndi Kleen 
6792dd6d8a1SAdrian Hunter 	auxtrace_snapshot_enabled = 1;
680649c48a9SPeter Zijlstra 	for (;;) {
6819f065194SYang Shi 		unsigned long long hits = rec->samples;
68286470930SIngo Molnar 
6838c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
6842dd6d8a1SAdrian Hunter 			auxtrace_snapshot_enabled = 0;
6858d3eca20SDavid Ahern 			err = -1;
68645604710SNamhyung Kim 			goto out_child;
6878d3eca20SDavid Ahern 		}
68886470930SIngo Molnar 
6892dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
6902dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
6912dd6d8a1SAdrian Hunter 			if (!auxtrace_snapshot_err)
6922dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
6932dd6d8a1SAdrian Hunter 			if (auxtrace_snapshot_err) {
6942dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
6952dd6d8a1SAdrian Hunter 				err = -1;
6962dd6d8a1SAdrian Hunter 				goto out_child;
6972dd6d8a1SAdrian Hunter 			}
6982dd6d8a1SAdrian Hunter 		}
6992dd6d8a1SAdrian Hunter 
700d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
7016dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
702649c48a9SPeter Zijlstra 				break;
703f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
704a515114fSJiri Olsa 			/*
705a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
706a515114fSJiri Olsa 			 * number of returned events and interrupt error.
707a515114fSJiri Olsa 			 */
708a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
70945604710SNamhyung Kim 				err = 0;
7108b412664SPeter Zijlstra 			waking++;
7116dcf45efSArnaldo Carvalho de Melo 
7126dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
7136dcf45efSArnaldo Carvalho de Melo 				draining = true;
7148b412664SPeter Zijlstra 		}
7158b412664SPeter Zijlstra 
716774cb499SJiri Olsa 		/*
717774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
718774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
719774cb499SJiri Olsa 		 * disable events in this case.
720774cb499SJiri Olsa 		 */
721602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
7222dd6d8a1SAdrian Hunter 			auxtrace_snapshot_enabled = 0;
7233e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
7242711926aSJiri Olsa 			disabled = true;
7252711926aSJiri Olsa 		}
7268b412664SPeter Zijlstra 	}
7272dd6d8a1SAdrian Hunter 	auxtrace_snapshot_enabled = 0;
7288b412664SPeter Zijlstra 
729f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
73035550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
731f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
732f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
733f33cbe72SArnaldo Carvalho de Melo 		err = -1;
73445604710SNamhyung Kim 		goto out_child;
735f33cbe72SArnaldo Carvalho de Melo 	}
736f33cbe72SArnaldo Carvalho de Melo 
737e3d59112SNamhyung Kim 	if (!quiet)
7388b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
73986470930SIngo Molnar 
74045604710SNamhyung Kim out_child:
74145604710SNamhyung Kim 	if (forks) {
74245604710SNamhyung Kim 		int exit_status;
74345604710SNamhyung Kim 
74445604710SNamhyung Kim 		if (!child_finished)
74545604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
74645604710SNamhyung Kim 
74745604710SNamhyung Kim 		wait(&exit_status);
74845604710SNamhyung Kim 
74945604710SNamhyung Kim 		if (err < 0)
75045604710SNamhyung Kim 			status = err;
75145604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
75245604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
75345604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
75445604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
75545604710SNamhyung Kim 	} else
75645604710SNamhyung Kim 		status = err;
75745604710SNamhyung Kim 
758e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
759e3d59112SNamhyung Kim 	rec->samples = 0;
760e3d59112SNamhyung Kim 
76145604710SNamhyung Kim 	if (!err && !file->is_pipe) {
76245604710SNamhyung Kim 		rec->session->header.data_size += rec->bytes_written;
763457ae94aSHe Kuang 		file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
76445604710SNamhyung Kim 
765cd10b289SAdrian Hunter 		if (!rec->no_buildid) {
76645604710SNamhyung Kim 			process_buildids(rec);
767*6156681bSNamhyung Kim 
768*6156681bSNamhyung Kim 			if (rec->buildid_all)
769cd10b289SAdrian Hunter 				dsos__hit_all(rec->session);
770cd10b289SAdrian Hunter 		}
77142aa276fSNamhyung Kim 		perf_session__write_header(rec->session, rec->evlist, fd, true);
77245604710SNamhyung Kim 	}
77339d17dacSArnaldo Carvalho de Melo 
774e3d59112SNamhyung Kim 	if (!err && !quiet) {
775e3d59112SNamhyung Kim 		char samples[128];
776e3d59112SNamhyung Kim 
777ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
778e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
779e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
780e3d59112SNamhyung Kim 		else
781e3d59112SNamhyung Kim 			samples[0] = '\0';
782e3d59112SNamhyung Kim 
783e3d59112SNamhyung Kim 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s ]\n",
784e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
785e3d59112SNamhyung Kim 			file->path, samples);
786e3d59112SNamhyung Kim 	}
787e3d59112SNamhyung Kim 
78839d17dacSArnaldo Carvalho de Melo out_delete_session:
78939d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
79045604710SNamhyung Kim 	return status;
79186470930SIngo Molnar }
79286470930SIngo Molnar 
79372a128aaSNamhyung Kim static void callchain_debug(void)
79409b0fd45SJiri Olsa {
795aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
796a601fdffSJiri Olsa 
79772a128aaSNamhyung Kim 	pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
79826d33022SJiri Olsa 
79972a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_DWARF)
80009b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
80172a128aaSNamhyung Kim 			 callchain_param.dump_size);
80209b0fd45SJiri Olsa }
80309b0fd45SJiri Olsa 
804c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
80509b0fd45SJiri Olsa 			       const char *arg,
80609b0fd45SJiri Olsa 			       int unset)
80709b0fd45SJiri Olsa {
80809b0fd45SJiri Olsa 	int ret;
809c421e80bSKan Liang 	struct record_opts *record = (struct record_opts *)opt->value;
81009b0fd45SJiri Olsa 
811c421e80bSKan Liang 	record->callgraph_set = true;
81272a128aaSNamhyung Kim 	callchain_param.enabled = !unset;
813eb853e80SJiri Olsa 
81409b0fd45SJiri Olsa 	/* --no-call-graph */
81509b0fd45SJiri Olsa 	if (unset) {
81672a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_NONE;
81709b0fd45SJiri Olsa 		pr_debug("callchain: disabled\n");
81809b0fd45SJiri Olsa 		return 0;
81909b0fd45SJiri Olsa 	}
82009b0fd45SJiri Olsa 
821c3a6a8c4SKan Liang 	ret = parse_callchain_record_opt(arg, &callchain_param);
8225c0cf224SJiri Olsa 	if (!ret) {
8235c0cf224SJiri Olsa 		/* Enable data address sampling for DWARF unwind. */
8245c0cf224SJiri Olsa 		if (callchain_param.record_mode == CALLCHAIN_DWARF)
8255c0cf224SJiri Olsa 			record->sample_address = true;
82672a128aaSNamhyung Kim 		callchain_debug();
8275c0cf224SJiri Olsa 	}
82809b0fd45SJiri Olsa 
82926d33022SJiri Olsa 	return ret;
83026d33022SJiri Olsa }
83126d33022SJiri Olsa 
832c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
83309b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
83409b0fd45SJiri Olsa 			 int unset __maybe_unused)
83509b0fd45SJiri Olsa {
836c421e80bSKan Liang 	struct record_opts *record = (struct record_opts *)opt->value;
837c421e80bSKan Liang 
838c421e80bSKan Liang 	record->callgraph_set = true;
83972a128aaSNamhyung Kim 	callchain_param.enabled = true;
84009b0fd45SJiri Olsa 
84172a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_NONE)
84272a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_FP;
843eb853e80SJiri Olsa 
84472a128aaSNamhyung Kim 	callchain_debug();
84509b0fd45SJiri Olsa 	return 0;
84609b0fd45SJiri Olsa }
84709b0fd45SJiri Olsa 
848eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
849eb853e80SJiri Olsa {
8507a29c087SNamhyung Kim 	struct record *rec = cb;
8517a29c087SNamhyung Kim 
8527a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
8537a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
8547a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
8557a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
8567a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
8577a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
8587a29c087SNamhyung Kim 			rec->no_buildid = true;
8597a29c087SNamhyung Kim 		else
8607a29c087SNamhyung Kim 			return -1;
8617a29c087SNamhyung Kim 		return 0;
8627a29c087SNamhyung Kim 	}
863eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
8645a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
865eb853e80SJiri Olsa 
866eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
867eb853e80SJiri Olsa }
868eb853e80SJiri Olsa 
869814c8c38SPeter Zijlstra struct clockid_map {
870814c8c38SPeter Zijlstra 	const char *name;
871814c8c38SPeter Zijlstra 	int clockid;
872814c8c38SPeter Zijlstra };
873814c8c38SPeter Zijlstra 
874814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
875814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
876814c8c38SPeter Zijlstra 
877814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
878814c8c38SPeter Zijlstra 
879814c8c38SPeter Zijlstra 
880814c8c38SPeter Zijlstra /*
881814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
882814c8c38SPeter Zijlstra  */
883814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
884814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
885814c8c38SPeter Zijlstra #endif
886814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
887814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
888814c8c38SPeter Zijlstra #endif
889814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
890814c8c38SPeter Zijlstra #define CLOCK_TAI 11
891814c8c38SPeter Zijlstra #endif
892814c8c38SPeter Zijlstra 
893814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
894814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
895814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
896814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
897814c8c38SPeter Zijlstra 
898814c8c38SPeter Zijlstra 	/* available for some events */
899814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
900814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
901814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
902814c8c38SPeter Zijlstra 
903814c8c38SPeter Zijlstra 	/* available for the lazy */
904814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
905814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
906814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
907814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
908814c8c38SPeter Zijlstra 
909814c8c38SPeter Zijlstra 	CLOCKID_END,
910814c8c38SPeter Zijlstra };
911814c8c38SPeter Zijlstra 
912814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
913814c8c38SPeter Zijlstra {
914814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
915814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
916814c8c38SPeter Zijlstra 	const char *ostr = str;
917814c8c38SPeter Zijlstra 
918814c8c38SPeter Zijlstra 	if (unset) {
919814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
920814c8c38SPeter Zijlstra 		return 0;
921814c8c38SPeter Zijlstra 	}
922814c8c38SPeter Zijlstra 
923814c8c38SPeter Zijlstra 	/* no arg passed */
924814c8c38SPeter Zijlstra 	if (!str)
925814c8c38SPeter Zijlstra 		return 0;
926814c8c38SPeter Zijlstra 
927814c8c38SPeter Zijlstra 	/* no setting it twice */
928814c8c38SPeter Zijlstra 	if (opts->use_clockid)
929814c8c38SPeter Zijlstra 		return -1;
930814c8c38SPeter Zijlstra 
931814c8c38SPeter Zijlstra 	opts->use_clockid = true;
932814c8c38SPeter Zijlstra 
933814c8c38SPeter Zijlstra 	/* if its a number, we're done */
934814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
935814c8c38SPeter Zijlstra 		return 0;
936814c8c38SPeter Zijlstra 
937814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
938814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
939814c8c38SPeter Zijlstra 		str += 6;
940814c8c38SPeter Zijlstra 
941814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
942814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
943814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
944814c8c38SPeter Zijlstra 			return 0;
945814c8c38SPeter Zijlstra 		}
946814c8c38SPeter Zijlstra 	}
947814c8c38SPeter Zijlstra 
948814c8c38SPeter Zijlstra 	opts->use_clockid = false;
949814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
950814c8c38SPeter Zijlstra 	return -1;
951814c8c38SPeter Zijlstra }
952814c8c38SPeter Zijlstra 
953e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
954e9db1310SAdrian Hunter 				    const char *str,
955e9db1310SAdrian Hunter 				    int unset __maybe_unused)
956e9db1310SAdrian Hunter {
957e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
958e9db1310SAdrian Hunter 	char *s, *p;
959e9db1310SAdrian Hunter 	unsigned int mmap_pages;
960e9db1310SAdrian Hunter 	int ret;
961e9db1310SAdrian Hunter 
962e9db1310SAdrian Hunter 	if (!str)
963e9db1310SAdrian Hunter 		return -EINVAL;
964e9db1310SAdrian Hunter 
965e9db1310SAdrian Hunter 	s = strdup(str);
966e9db1310SAdrian Hunter 	if (!s)
967e9db1310SAdrian Hunter 		return -ENOMEM;
968e9db1310SAdrian Hunter 
969e9db1310SAdrian Hunter 	p = strchr(s, ',');
970e9db1310SAdrian Hunter 	if (p)
971e9db1310SAdrian Hunter 		*p = '\0';
972e9db1310SAdrian Hunter 
973e9db1310SAdrian Hunter 	if (*s) {
974e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
975e9db1310SAdrian Hunter 		if (ret)
976e9db1310SAdrian Hunter 			goto out_free;
977e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
978e9db1310SAdrian Hunter 	}
979e9db1310SAdrian Hunter 
980e9db1310SAdrian Hunter 	if (!p) {
981e9db1310SAdrian Hunter 		ret = 0;
982e9db1310SAdrian Hunter 		goto out_free;
983e9db1310SAdrian Hunter 	}
984e9db1310SAdrian Hunter 
985e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
986e9db1310SAdrian Hunter 	if (ret)
987e9db1310SAdrian Hunter 		goto out_free;
988e9db1310SAdrian Hunter 
989e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
990e9db1310SAdrian Hunter 
991e9db1310SAdrian Hunter out_free:
992e9db1310SAdrian Hunter 	free(s);
993e9db1310SAdrian Hunter 	return ret;
994e9db1310SAdrian Hunter }
995e9db1310SAdrian Hunter 
996e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
99786470930SIngo Molnar 	"perf record [<options>] [<command>]",
99886470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
99986470930SIngo Molnar 	NULL
100086470930SIngo Molnar };
1001e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
100286470930SIngo Molnar 
1003d20deb64SArnaldo Carvalho de Melo /*
10048c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
10058c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1006d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1007d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1008d20deb64SArnaldo Carvalho de Melo  *
1009d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1010d20deb64SArnaldo Carvalho de Melo  *
1011d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1012d20deb64SArnaldo Carvalho de Melo  */
10138c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1014d20deb64SArnaldo Carvalho de Melo 	.opts = {
10158affc2b8SAndi Kleen 		.sample_time	     = true,
1016d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1017d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1018d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1019447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1020d1cb9fceSNamhyung Kim 		.target		     = {
1021d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
10223aa5939dSAdrian Hunter 			.default_per_cpu = true,
1023d1cb9fceSNamhyung Kim 		},
10249d9cad76SKan Liang 		.proc_map_timeout     = 500,
1025d20deb64SArnaldo Carvalho de Melo 	},
1026e3d59112SNamhyung Kim 	.tool = {
1027e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1028e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1029cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1030e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1031e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1032e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1033cca8482cSAdrian Hunter 		.ordered_events	= true,
1034e3d59112SNamhyung Kim 	},
1035d20deb64SArnaldo Carvalho de Melo };
10367865e817SFrederic Weisbecker 
103776a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
103876a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
103961eaa3beSArnaldo Carvalho de Melo 
1040d20deb64SArnaldo Carvalho de Melo /*
1041d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1042d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1043b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1044d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1045d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1046d20deb64SArnaldo Carvalho de Melo  */
1047e5b2c207SNamhyung Kim struct option __record_options[] = {
1048d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
104986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1050f120f9d5SJiri Olsa 		     parse_events_option),
1051d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1052c171b552SLi Zefan 		     "event filter", parse_filter),
10534ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
10544ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
10554ba1faa1SWang Nan 			   exclude_perf),
1056bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1057d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1058bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1059d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1060d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
106186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1062509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1063acac03faSKirill Smelkov 		    "collect data without buffering"),
1064d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1065daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1066bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
106786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1068bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1069c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1070d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1071f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
107286470930SIngo Molnar 		    "output file name"),
107369e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
107469e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
10752e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1076d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1077e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1078e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1079e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1080d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
108143bece79SLin Ming 		    "put the counters into a counter group"),
108209b0fd45SJiri Olsa 	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
108309b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
108409b0fd45SJiri Olsa 			   &record_callchain_opt),
108509b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
108676a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
108709b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1088c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
10893da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1090b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1091d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1092649c48a9SPeter Zijlstra 		    "per thread counts"),
109356100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
10943abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
10953abebc55SAdrian Hunter 			&record.opts.sample_time_set,
10963abebc55SAdrian Hunter 			"Record the sample timestamps"),
109756100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1098d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1099649c48a9SPeter Zijlstra 		    "don't sample"),
1100d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
1101a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
1102d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
1103baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
1104d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1105023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1106023695d9SStephane Eranian 		     parse_cgroups),
1107a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
11086619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1109bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1110bea03405SNamhyung Kim 		   "user to profile"),
1111a5aabdacSStephane Eranian 
1112a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1113a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1114a5aabdacSStephane Eranian 		     parse_branch_stack),
1115a5aabdacSStephane Eranian 
1116a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1117a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1118bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
111905484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
112005484298SAndi Kleen 		    "sample by weight (on special events only)"),
1121475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1122475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
11233aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
11243aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1125bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1126bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1127bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
112885c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
112985c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1130814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1131814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1132814c8c38SPeter Zijlstra 	parse_clockid),
11332dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
11342dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
11359d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
11369d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1137b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1138b757bb09SAdrian Hunter 		    "Record context switch events"),
113971dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
114071dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
114171dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
114271dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
11437efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
11447efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
1145*6156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
1146*6156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
114786470930SIngo Molnar 	OPT_END()
114886470930SIngo Molnar };
114986470930SIngo Molnar 
1150e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1151e5b2c207SNamhyung Kim 
11521d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
115386470930SIngo Molnar {
1154ef149c25SAdrian Hunter 	int err;
11558c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
115616ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
115786470930SIngo Molnar 
115848e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
115948e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
116048e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
116148e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
116248e1cab1SWang Nan # undef set_nobuild
116348e1cab1SWang Nan #endif
116448e1cab1SWang Nan 
11657efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
11667efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
11677efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
11687efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
11697efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
11707efe0e03SHe Kuang # else
11717efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
11727efe0e03SHe Kuang # endif
11737efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
11747efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
11757efe0e03SHe Kuang # undef set_nobuild
11767efe0e03SHe Kuang # undef REASON
11777efe0e03SHe Kuang #endif
11787efe0e03SHe Kuang 
11793e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
11803e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1181361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1182361c99a6SArnaldo Carvalho de Melo 
1183eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1184eb853e80SJiri Olsa 
1185bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1186a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1187602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1188bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
118986470930SIngo Molnar 
1190bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1191c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1192c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1193c7118369SNamhyung Kim 
1194023695d9SStephane Eranian 	}
1195b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1196b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1197c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1198c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1199c7118369SNamhyung Kim 		return -EINVAL;
1200b757bb09SAdrian Hunter 	}
1201023695d9SStephane Eranian 
1202ef149c25SAdrian Hunter 	if (!rec->itr) {
1203ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1204ef149c25SAdrian Hunter 		if (err)
1205ef149c25SAdrian Hunter 			return err;
1206ef149c25SAdrian Hunter 	}
1207ef149c25SAdrian Hunter 
12082dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
12092dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
12102dd6d8a1SAdrian Hunter 	if (err)
12112dd6d8a1SAdrian Hunter 		return err;
12122dd6d8a1SAdrian Hunter 
1213ef149c25SAdrian Hunter 	err = -ENOMEM;
1214ef149c25SAdrian Hunter 
12150a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1216baa2f6ceSArnaldo Carvalho de Melo 
1217ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1218646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1219646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1220ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1221646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1222646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1223646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1224646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1225646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1226ec80fde7SArnaldo Carvalho de Melo 
1227d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1228a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1229655000e7SArnaldo Carvalho de Melo 
12303e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
12313e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
123269aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
123369aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1234bbd36e5eSPeter Zijlstra 	}
123586470930SIngo Molnar 
123669e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
123769e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
123869e7e5b0SAdrian Hunter 
1239602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
124016ad2ffbSNamhyung Kim 	if (err) {
1241602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
124216ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
124316ad2ffbSNamhyung Kim 	}
12444bd0f2d2SNamhyung Kim 
1245602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
124616ad2ffbSNamhyung Kim 	if (err) {
124716ad2ffbSNamhyung Kim 		int saved_errno = errno;
124816ad2ffbSNamhyung Kim 
1249602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
12503780f488SNamhyung Kim 		ui__error("%s", errbuf);
125116ad2ffbSNamhyung Kim 
125216ad2ffbSNamhyung Kim 		err = -saved_errno;
12538fa60e1fSNamhyung Kim 		goto out_symbol_exit;
125416ad2ffbSNamhyung Kim 	}
12550d37aa34SArnaldo Carvalho de Melo 
125616ad2ffbSNamhyung Kim 	err = -ENOMEM;
12573e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1258dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
125969aad6f1SArnaldo Carvalho de Melo 
1260ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1261ef149c25SAdrian Hunter 	if (err)
1262ef149c25SAdrian Hunter 		goto out_symbol_exit;
1263ef149c25SAdrian Hunter 
1264*6156681bSNamhyung Kim 	/*
1265*6156681bSNamhyung Kim 	 * We take all buildids when the file contains
1266*6156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
1267*6156681bSNamhyung Kim 	 * trace because it would take too long.
1268*6156681bSNamhyung Kim 	 */
1269*6156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
1270*6156681bSNamhyung Kim 		rec->buildid_all = true;
1271*6156681bSNamhyung Kim 
1272b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
127339d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
127403ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
12757e4ff9e3SMike Galbraith 	}
12767e4ff9e3SMike Galbraith 
1277d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1278d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
127945604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1280d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1281ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
128239d17dacSArnaldo Carvalho de Melo 	return err;
128386470930SIngo Molnar }
12842dd6d8a1SAdrian Hunter 
12852dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
12862dd6d8a1SAdrian Hunter {
12872dd6d8a1SAdrian Hunter 	if (!auxtrace_snapshot_enabled)
12882dd6d8a1SAdrian Hunter 		return;
12892dd6d8a1SAdrian Hunter 	auxtrace_snapshot_enabled = 0;
12902dd6d8a1SAdrian Hunter 	auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr);
12912dd6d8a1SAdrian Hunter 	auxtrace_record__snapshot_started = 1;
12922dd6d8a1SAdrian Hunter }
1293