xref: /openbmc/linux/tools/perf/builtin-record.c (revision e1ab48ba63ee6b2494a67bb60bf99692ecdaca7c)
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"
358690a2a7SWang Nan #include "util/bpf-loader.h"
36d8871ea7SWang Nan #include "asm/bug.h"
377c6a1c65SPeter Zijlstra 
3886470930SIngo Molnar #include <unistd.h>
3986470930SIngo Molnar #include <sched.h>
40a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
4186470930SIngo Molnar 
4278da39faSBernhard Rosenkraenzer 
438c6f45a7SArnaldo Carvalho de Melo struct record {
4445694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
45b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
46d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
47f5fc1412SJiri Olsa 	struct perf_data_file	file;
48ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
49d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
50d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
51d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
52d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
53d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
54d2db9a98SWang Nan 	bool			no_buildid_set;
55d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
56d2db9a98SWang Nan 	bool			no_buildid_cache_set;
576156681bSNamhyung Kim 	bool			buildid_all;
589f065194SYang Shi 	unsigned long long	samples;
590f82ebc4SArnaldo Carvalho de Melo };
6086470930SIngo Molnar 
618c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
62f5970550SPeter Zijlstra {
63cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
644f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
658d3eca20SDavid Ahern 		return -1;
668d3eca20SDavid Ahern 	}
67f5970550SPeter Zijlstra 
68cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
698d3eca20SDavid Ahern 	return 0;
70f5970550SPeter Zijlstra }
71f5970550SPeter Zijlstra 
7245694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
73d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
741d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
751d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
76234fbbf5SArnaldo Carvalho de Melo {
778c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
788c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
79234fbbf5SArnaldo Carvalho de Melo }
80234fbbf5SArnaldo Carvalho de Melo 
81e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
8286470930SIngo Molnar {
83e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
847b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
857b8283b5SDavid Ahern 	u64 old = md->prev;
86918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
8786470930SIngo Molnar 	unsigned long size;
8886470930SIngo Molnar 	void *buf;
898d3eca20SDavid Ahern 	int rc = 0;
9086470930SIngo Molnar 
91dc82009aSArnaldo Carvalho de Melo 	if (old == head)
928d3eca20SDavid Ahern 		return 0;
9386470930SIngo Molnar 
94d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
9586470930SIngo Molnar 
9686470930SIngo Molnar 	size = head - old;
9786470930SIngo Molnar 
9886470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
9986470930SIngo Molnar 		buf = &data[old & md->mask];
10086470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
10186470930SIngo Molnar 		old += size;
10286470930SIngo Molnar 
1038c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
1048d3eca20SDavid Ahern 			rc = -1;
1058d3eca20SDavid Ahern 			goto out;
1068d3eca20SDavid Ahern 		}
10786470930SIngo Molnar 	}
10886470930SIngo Molnar 
10986470930SIngo Molnar 	buf = &data[old & md->mask];
11086470930SIngo Molnar 	size = head - old;
11186470930SIngo Molnar 	old += size;
11286470930SIngo Molnar 
1138c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1148d3eca20SDavid Ahern 		rc = -1;
1158d3eca20SDavid Ahern 		goto out;
1168d3eca20SDavid Ahern 	}
11786470930SIngo Molnar 
11886470930SIngo Molnar 	md->prev = old;
119e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1208d3eca20SDavid Ahern out:
1218d3eca20SDavid Ahern 	return rc;
12286470930SIngo Molnar }
12386470930SIngo Molnar 
1242dd6d8a1SAdrian Hunter static volatile int done;
1252dd6d8a1SAdrian Hunter static volatile int signr = -1;
1262dd6d8a1SAdrian Hunter static volatile int child_finished;
1272dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled;
1282dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err;
1292dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1302dd6d8a1SAdrian Hunter 
1312dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1322dd6d8a1SAdrian Hunter {
1332dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1342dd6d8a1SAdrian Hunter 		child_finished = 1;
1352dd6d8a1SAdrian Hunter 	else
1362dd6d8a1SAdrian Hunter 		signr = sig;
1372dd6d8a1SAdrian Hunter 
1382dd6d8a1SAdrian Hunter 	done = 1;
1392dd6d8a1SAdrian Hunter }
1402dd6d8a1SAdrian Hunter 
1412dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1422dd6d8a1SAdrian Hunter {
1432dd6d8a1SAdrian Hunter 	if (signr == -1)
1442dd6d8a1SAdrian Hunter 		return;
1452dd6d8a1SAdrian Hunter 
1462dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1472dd6d8a1SAdrian Hunter 	raise(signr);
1482dd6d8a1SAdrian Hunter }
1492dd6d8a1SAdrian Hunter 
150e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
151e31f0d01SAdrian Hunter 
152ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
153ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
154ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
155ef149c25SAdrian Hunter {
156ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
15799fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
158ef149c25SAdrian Hunter 	size_t padding;
159ef149c25SAdrian Hunter 	u8 pad[8] = {0};
160ef149c25SAdrian Hunter 
16199fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
16299fa2984SAdrian Hunter 		off_t file_offset;
16399fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
16499fa2984SAdrian Hunter 		int err;
16599fa2984SAdrian Hunter 
16699fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
16799fa2984SAdrian Hunter 		if (file_offset == -1)
16899fa2984SAdrian Hunter 			return -1;
16999fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
17099fa2984SAdrian Hunter 						     event, file_offset);
17199fa2984SAdrian Hunter 		if (err)
17299fa2984SAdrian Hunter 			return err;
17399fa2984SAdrian Hunter 	}
17499fa2984SAdrian Hunter 
175ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
176ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
177ef149c25SAdrian Hunter 	if (padding)
178ef149c25SAdrian Hunter 		padding = 8 - padding;
179ef149c25SAdrian Hunter 
180ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
181ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
182ef149c25SAdrian Hunter 	if (len2)
183ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
184ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
185ef149c25SAdrian Hunter 
186ef149c25SAdrian Hunter 	return 0;
187ef149c25SAdrian Hunter }
188ef149c25SAdrian Hunter 
189ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
190ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
191ef149c25SAdrian Hunter {
192ef149c25SAdrian Hunter 	int ret;
193ef149c25SAdrian Hunter 
194ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
195ef149c25SAdrian Hunter 				  record__process_auxtrace);
196ef149c25SAdrian Hunter 	if (ret < 0)
197ef149c25SAdrian Hunter 		return ret;
198ef149c25SAdrian Hunter 
199ef149c25SAdrian Hunter 	if (ret)
200ef149c25SAdrian Hunter 		rec->samples++;
201ef149c25SAdrian Hunter 
202ef149c25SAdrian Hunter 	return 0;
203ef149c25SAdrian Hunter }
204ef149c25SAdrian Hunter 
2052dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2062dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2072dd6d8a1SAdrian Hunter {
2082dd6d8a1SAdrian Hunter 	int ret;
2092dd6d8a1SAdrian Hunter 
2102dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2112dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2122dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2132dd6d8a1SAdrian Hunter 	if (ret < 0)
2142dd6d8a1SAdrian Hunter 		return ret;
2152dd6d8a1SAdrian Hunter 
2162dd6d8a1SAdrian Hunter 	if (ret)
2172dd6d8a1SAdrian Hunter 		rec->samples++;
2182dd6d8a1SAdrian Hunter 
2192dd6d8a1SAdrian Hunter 	return 0;
2202dd6d8a1SAdrian Hunter }
2212dd6d8a1SAdrian Hunter 
2222dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2232dd6d8a1SAdrian Hunter {
2242dd6d8a1SAdrian Hunter 	int i;
2252dd6d8a1SAdrian Hunter 	int rc = 0;
2262dd6d8a1SAdrian Hunter 
2272dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2282dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2292dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2302dd6d8a1SAdrian Hunter 
2312dd6d8a1SAdrian Hunter 		if (!mm->base)
2322dd6d8a1SAdrian Hunter 			continue;
2332dd6d8a1SAdrian Hunter 
2342dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2352dd6d8a1SAdrian Hunter 			rc = -1;
2362dd6d8a1SAdrian Hunter 			goto out;
2372dd6d8a1SAdrian Hunter 		}
2382dd6d8a1SAdrian Hunter 	}
2392dd6d8a1SAdrian Hunter out:
2402dd6d8a1SAdrian Hunter 	return rc;
2412dd6d8a1SAdrian Hunter }
2422dd6d8a1SAdrian Hunter 
2432dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2442dd6d8a1SAdrian Hunter {
2452dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2462dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2472dd6d8a1SAdrian Hunter 		auxtrace_snapshot_err = -1;
2482dd6d8a1SAdrian Hunter 	} else {
2492dd6d8a1SAdrian Hunter 		auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr);
2502dd6d8a1SAdrian Hunter 		if (!auxtrace_snapshot_err)
2512dd6d8a1SAdrian Hunter 			auxtrace_snapshot_enabled = 1;
2522dd6d8a1SAdrian Hunter 	}
2532dd6d8a1SAdrian Hunter }
2542dd6d8a1SAdrian Hunter 
255e31f0d01SAdrian Hunter #else
256e31f0d01SAdrian Hunter 
257e31f0d01SAdrian Hunter static inline
258e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
259e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
260e31f0d01SAdrian Hunter {
261e31f0d01SAdrian Hunter 	return 0;
262e31f0d01SAdrian Hunter }
263e31f0d01SAdrian Hunter 
2642dd6d8a1SAdrian Hunter static inline
2652dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2662dd6d8a1SAdrian Hunter {
2672dd6d8a1SAdrian Hunter }
2682dd6d8a1SAdrian Hunter 
2692dd6d8a1SAdrian Hunter static inline
2702dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2712dd6d8a1SAdrian Hunter {
2722dd6d8a1SAdrian Hunter 	return 0;
2732dd6d8a1SAdrian Hunter }
2742dd6d8a1SAdrian Hunter 
275e31f0d01SAdrian Hunter #endif
276e31f0d01SAdrian Hunter 
2778c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
278dd7927f4SArnaldo Carvalho de Melo {
27956e52e85SArnaldo Carvalho de Melo 	char msg[512];
2806a4bb04cSJiri Olsa 	struct perf_evsel *pos;
281d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
282d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
283b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
2848d3eca20SDavid Ahern 	int rc = 0;
285dd7927f4SArnaldo Carvalho de Melo 
286f77a9518SArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts);
287cac21425SJiri Olsa 
2880050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
2893da297a6SIngo Molnar try_again:
290d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
29156e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
2923da297a6SIngo Molnar 				if (verbose)
293c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
2943da297a6SIngo Molnar 				goto try_again;
2953da297a6SIngo Molnar 			}
296ca6a4258SDavid Ahern 
29756e52e85SArnaldo Carvalho de Melo 			rc = -errno;
29856e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
29956e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
30056e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3018d3eca20SDavid Ahern 			goto out;
3027c6a1c65SPeter Zijlstra 		}
3037c6a1c65SPeter Zijlstra 	}
3047c6a1c65SPeter Zijlstra 
30523d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
30623d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
30723d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
30835550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3098d3eca20SDavid Ahern 		rc = -1;
3108d3eca20SDavid Ahern 		goto out;
3110a102479SFrederic Weisbecker 	}
3120a102479SFrederic Weisbecker 
313ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3142dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3152dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3168d3eca20SDavid Ahern 		if (errno == EPERM) {
3178d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
31818e60939SNelson Elhage 			       "Consider increasing "
31918e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
32018e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
321ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
322ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3238d3eca20SDavid Ahern 			rc = -errno;
3248d3eca20SDavid Ahern 		} else {
32535550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
32635550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
3278d3eca20SDavid Ahern 			rc = -errno;
3288d3eca20SDavid Ahern 		}
3298d3eca20SDavid Ahern 		goto out;
33018e60939SNelson Elhage 	}
3310a27d7f9SArnaldo Carvalho de Melo 
332a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3337b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3348d3eca20SDavid Ahern out:
3358d3eca20SDavid Ahern 	return rc;
336a91e5431SArnaldo Carvalho de Melo }
337a91e5431SArnaldo Carvalho de Melo 
338e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
339e3d59112SNamhyung Kim 				union perf_event *event,
340e3d59112SNamhyung Kim 				struct perf_sample *sample,
341e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
342e3d59112SNamhyung Kim 				struct machine *machine)
343e3d59112SNamhyung Kim {
344e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
345e3d59112SNamhyung Kim 
346e3d59112SNamhyung Kim 	rec->samples++;
347e3d59112SNamhyung Kim 
348e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
349e3d59112SNamhyung Kim }
350e3d59112SNamhyung Kim 
3518c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
3526122e4e4SArnaldo Carvalho de Melo {
353f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
354f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
3556122e4e4SArnaldo Carvalho de Melo 
356457ae94aSHe Kuang 	if (file->size == 0)
3579f591fd7SArnaldo Carvalho de Melo 		return 0;
3589f591fd7SArnaldo Carvalho de Melo 
35900dc8657SNamhyung Kim 	/*
36000dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
36100dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
36200dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
36300dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
36400dc8657SNamhyung Kim 	 *
36500dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
36600dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
36700dc8657SNamhyung Kim 	 */
36800dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
36900dc8657SNamhyung Kim 
3706156681bSNamhyung Kim 	/*
3716156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
3726156681bSNamhyung Kim 	 * so no need to process samples.
3736156681bSNamhyung Kim 	 */
3746156681bSNamhyung Kim 	if (rec->buildid_all)
3756156681bSNamhyung Kim 		rec->tool.sample = NULL;
3766156681bSNamhyung Kim 
377b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
3786122e4e4SArnaldo Carvalho de Melo }
3796122e4e4SArnaldo Carvalho de Melo 
3808115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
381a1645ce1SZhang, Yanmin {
382a1645ce1SZhang, Yanmin 	int err;
38345694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
384a1645ce1SZhang, Yanmin 	/*
385a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
386a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
387a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
388a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
389a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
390a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
391a1645ce1SZhang, Yanmin 	 */
39245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
393743eb868SArnaldo Carvalho de Melo 					     machine);
394a1645ce1SZhang, Yanmin 	if (err < 0)
395a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
39623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
397a1645ce1SZhang, Yanmin 
398a1645ce1SZhang, Yanmin 	/*
399a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
400a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
401a1645ce1SZhang, Yanmin 	 */
40245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4030ae617beSAdrian Hunter 						 machine);
404a1645ce1SZhang, Yanmin 	if (err < 0)
405a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
40623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
407a1645ce1SZhang, Yanmin }
408a1645ce1SZhang, Yanmin 
40998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
41098402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
41198402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
41298402807SFrederic Weisbecker };
41398402807SFrederic Weisbecker 
4148c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
41598402807SFrederic Weisbecker {
416dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4170e2e63ddSPeter Zijlstra 	int i;
4188d3eca20SDavid Ahern 	int rc = 0;
41998402807SFrederic Weisbecker 
420d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
421ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
422ef149c25SAdrian Hunter 
4238d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
424e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4258d3eca20SDavid Ahern 				rc = -1;
4268d3eca20SDavid Ahern 				goto out;
4278d3eca20SDavid Ahern 			}
4288d3eca20SDavid Ahern 		}
429ef149c25SAdrian Hunter 
4302dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
431ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
432ef149c25SAdrian Hunter 			rc = -1;
433ef149c25SAdrian Hunter 			goto out;
434ef149c25SAdrian Hunter 		}
43598402807SFrederic Weisbecker 	}
43698402807SFrederic Weisbecker 
437dcabb507SJiri Olsa 	/*
438dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
439dcabb507SJiri Olsa 	 * at least one event.
440dcabb507SJiri Olsa 	 */
441dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
4428c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
4438d3eca20SDavid Ahern 
4448d3eca20SDavid Ahern out:
4458d3eca20SDavid Ahern 	return rc;
44698402807SFrederic Weisbecker }
44798402807SFrederic Weisbecker 
4488c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
44957706abcSDavid Ahern {
45057706abcSDavid Ahern 	struct perf_session *session = rec->session;
45157706abcSDavid Ahern 	int feat;
45257706abcSDavid Ahern 
45357706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
45457706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
45557706abcSDavid Ahern 
45657706abcSDavid Ahern 	if (rec->no_buildid)
45757706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
45857706abcSDavid Ahern 
4593e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
46057706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
46157706abcSDavid Ahern 
46257706abcSDavid Ahern 	if (!rec->opts.branch_stack)
46357706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
464ef149c25SAdrian Hunter 
465ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
466ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
467ffa517adSJiri Olsa 
468ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
46957706abcSDavid Ahern }
47057706abcSDavid Ahern 
471*e1ab48baSWang Nan static void
472*e1ab48baSWang Nan record__finish_output(struct record *rec)
473*e1ab48baSWang Nan {
474*e1ab48baSWang Nan 	struct perf_data_file *file = &rec->file;
475*e1ab48baSWang Nan 	int fd = perf_data_file__fd(file);
476*e1ab48baSWang Nan 
477*e1ab48baSWang Nan 	if (file->is_pipe)
478*e1ab48baSWang Nan 		return;
479*e1ab48baSWang Nan 
480*e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
481*e1ab48baSWang Nan 	file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
482*e1ab48baSWang Nan 
483*e1ab48baSWang Nan 	if (!rec->no_buildid) {
484*e1ab48baSWang Nan 		process_buildids(rec);
485*e1ab48baSWang Nan 
486*e1ab48baSWang Nan 		if (rec->buildid_all)
487*e1ab48baSWang Nan 			dsos__hit_all(rec->session);
488*e1ab48baSWang Nan 	}
489*e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
490*e1ab48baSWang Nan 
491*e1ab48baSWang Nan 	return;
492*e1ab48baSWang Nan }
493*e1ab48baSWang Nan 
494f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
495f33cbe72SArnaldo Carvalho de Melo 
496f33cbe72SArnaldo Carvalho de Melo /*
497f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
498f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
499f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
500f33cbe72SArnaldo Carvalho de Melo  */
50145604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
50245604710SNamhyung Kim 					siginfo_t *info,
503f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
504f33cbe72SArnaldo Carvalho de Melo {
505f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
506f33cbe72SArnaldo Carvalho de Melo 	done = 1;
507f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
508f33cbe72SArnaldo Carvalho de Melo }
509f33cbe72SArnaldo Carvalho de Melo 
5102dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
5112dd6d8a1SAdrian Hunter 
512c45c86ebSWang Nan static int record__synthesize(struct record *rec)
513c45c86ebSWang Nan {
514c45c86ebSWang Nan 	struct perf_session *session = rec->session;
515c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
516c45c86ebSWang Nan 	struct perf_data_file *file = &rec->file;
517c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
518c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
519c45c86ebSWang Nan 	int fd = perf_data_file__fd(file);
520c45c86ebSWang Nan 	int err = 0;
521c45c86ebSWang Nan 
522c45c86ebSWang Nan 	if (file->is_pipe) {
523c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
524c45c86ebSWang Nan 						   process_synthesized_event);
525c45c86ebSWang Nan 		if (err < 0) {
526c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
527c45c86ebSWang Nan 			goto out;
528c45c86ebSWang Nan 		}
529c45c86ebSWang Nan 
530c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
531c45c86ebSWang Nan 			/*
532c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
533c45c86ebSWang Nan 			 * there were no tracepoints so its not really
534c45c86ebSWang Nan 			 * an error, just that we don't need to
535c45c86ebSWang Nan 			 * synthesize anything.  We really have to
536c45c86ebSWang Nan 			 * return this more properly and also
537c45c86ebSWang Nan 			 * propagate errors that now are calling die()
538c45c86ebSWang Nan 			 */
539c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
540c45c86ebSWang Nan 								  process_synthesized_event);
541c45c86ebSWang Nan 			if (err <= 0) {
542c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
543c45c86ebSWang Nan 				goto out;
544c45c86ebSWang Nan 			}
545c45c86ebSWang Nan 			rec->bytes_written += err;
546c45c86ebSWang Nan 		}
547c45c86ebSWang Nan 	}
548c45c86ebSWang Nan 
549c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
550c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
551c45c86ebSWang Nan 					session, process_synthesized_event);
552c45c86ebSWang Nan 		if (err)
553c45c86ebSWang Nan 			goto out;
554c45c86ebSWang Nan 	}
555c45c86ebSWang Nan 
556c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
557c45c86ebSWang Nan 						 machine);
558c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
559c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
560c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
561c45c86ebSWang Nan 
562c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
563c45c86ebSWang Nan 					     machine);
564c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
565c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
566c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
567c45c86ebSWang Nan 
568c45c86ebSWang Nan 	if (perf_guest) {
569c45c86ebSWang Nan 		machines__process_guests(&session->machines,
570c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
571c45c86ebSWang Nan 	}
572c45c86ebSWang Nan 
573c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
574c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
575c45c86ebSWang Nan 					    opts->proc_map_timeout);
576c45c86ebSWang Nan out:
577c45c86ebSWang Nan 	return err;
578c45c86ebSWang Nan }
579c45c86ebSWang Nan 
5808c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
58186470930SIngo Molnar {
58257706abcSDavid Ahern 	int err;
58345604710SNamhyung Kim 	int status = 0;
5848b412664SPeter Zijlstra 	unsigned long waking = 0;
58546be604bSZhang, Yanmin 	const bool forks = argc > 0;
58623346f21SArnaldo Carvalho de Melo 	struct machine *machine;
58745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
588b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
589f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
590d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
5916dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
59242aa276fSNamhyung Kim 	int fd;
59386470930SIngo Molnar 
594d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
59533e49ea7SAndi Kleen 
59645604710SNamhyung Kim 	atexit(record__sig_exit);
597f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
598f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
599804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
6002dd6d8a1SAdrian Hunter 	if (rec->opts.auxtrace_snapshot_mode)
6012dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
6022dd6d8a1SAdrian Hunter 	else
6032dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
604f5970550SPeter Zijlstra 
605b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
60694c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
607ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
608a9a70bbcSArnaldo Carvalho de Melo 		return -1;
609a9a70bbcSArnaldo Carvalho de Melo 	}
610a9a70bbcSArnaldo Carvalho de Melo 
61142aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
612d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
613d20deb64SArnaldo Carvalho de Melo 
6148c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
615330aa675SStephane Eranian 
616d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
6173e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
618f5fc1412SJiri Olsa 						    argv, file->is_pipe,
619735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
62035b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
62135b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
62245604710SNamhyung Kim 			status = err;
62335b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
624856e9660SPeter Zijlstra 		}
625856e9660SPeter Zijlstra 	}
626856e9660SPeter Zijlstra 
6278c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
6288d3eca20SDavid Ahern 		err = -1;
62945604710SNamhyung Kim 		goto out_child;
6308d3eca20SDavid Ahern 	}
63186470930SIngo Molnar 
6328690a2a7SWang Nan 	err = bpf__apply_obj_config();
6338690a2a7SWang Nan 	if (err) {
6348690a2a7SWang Nan 		char errbuf[BUFSIZ];
6358690a2a7SWang Nan 
6368690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
6378690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
6388690a2a7SWang Nan 			 errbuf);
6398690a2a7SWang Nan 		goto out_child;
6408690a2a7SWang Nan 	}
6418690a2a7SWang Nan 
642cca8482cSAdrian Hunter 	/*
643cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
644cca8482cSAdrian Hunter 	 * evlist.
645cca8482cSAdrian Hunter 	 */
646cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
647cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
648cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
649cca8482cSAdrian Hunter 	}
650cca8482cSAdrian Hunter 
6513e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
652a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
653a8bb559bSNamhyung Kim 
654f5fc1412SJiri Olsa 	if (file->is_pipe) {
65542aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
656529870e3STom Zanussi 		if (err < 0)
65745604710SNamhyung Kim 			goto out_child;
658563aecb2SJiri Olsa 	} else {
65942aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
660d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
66145604710SNamhyung Kim 			goto out_child;
662d5eed904SArnaldo Carvalho de Melo 	}
6637c6a1c65SPeter Zijlstra 
664d3665498SDavid Ahern 	if (!rec->no_buildid
665e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
666d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
667e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
6688d3eca20SDavid Ahern 		err = -1;
66945604710SNamhyung Kim 		goto out_child;
670e20960c0SRobert Richter 	}
671e20960c0SRobert Richter 
67234ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
673743eb868SArnaldo Carvalho de Melo 
674c45c86ebSWang Nan 	err = record__synthesize(rec);
675c45c86ebSWang Nan 	if (err < 0)
67645604710SNamhyung Kim 		goto out_child;
6778d3eca20SDavid Ahern 
678d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
67986470930SIngo Molnar 		struct sched_param param;
68086470930SIngo Molnar 
681d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
68286470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6836beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
6848d3eca20SDavid Ahern 			err = -1;
68545604710SNamhyung Kim 			goto out_child;
68686470930SIngo Molnar 		}
68786470930SIngo Molnar 	}
68886470930SIngo Molnar 
689774cb499SJiri Olsa 	/*
690774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
691774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
692774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
693774cb499SJiri Olsa 	 */
6946619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
6953e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
696764e16a3SDavid Ahern 
697856e9660SPeter Zijlstra 	/*
698856e9660SPeter Zijlstra 	 * Let the child rip
699856e9660SPeter Zijlstra 	 */
700e803cf97SNamhyung Kim 	if (forks) {
701e5bed564SNamhyung Kim 		union perf_event *event;
702e5bed564SNamhyung Kim 
703e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
704e5bed564SNamhyung Kim 		if (event == NULL) {
705e5bed564SNamhyung Kim 			err = -ENOMEM;
706e5bed564SNamhyung Kim 			goto out_child;
707e5bed564SNamhyung Kim 		}
708e5bed564SNamhyung Kim 
709e803cf97SNamhyung Kim 		/*
710e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
711e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
712e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
713e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
714e803cf97SNamhyung Kim 		 */
715e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
716e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
717e803cf97SNamhyung Kim 					    process_synthesized_event,
718e803cf97SNamhyung Kim 					    machine);
719e5bed564SNamhyung Kim 		free(event);
720e803cf97SNamhyung Kim 
7213e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
722e803cf97SNamhyung Kim 	}
723856e9660SPeter Zijlstra 
7246619a53eSAndi Kleen 	if (opts->initial_delay) {
7256619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
7266619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
7276619a53eSAndi Kleen 	}
7286619a53eSAndi Kleen 
7292dd6d8a1SAdrian Hunter 	auxtrace_snapshot_enabled = 1;
730649c48a9SPeter Zijlstra 	for (;;) {
7319f065194SYang Shi 		unsigned long long hits = rec->samples;
73286470930SIngo Molnar 
7338c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
7342dd6d8a1SAdrian Hunter 			auxtrace_snapshot_enabled = 0;
7358d3eca20SDavid Ahern 			err = -1;
73645604710SNamhyung Kim 			goto out_child;
7378d3eca20SDavid Ahern 		}
73886470930SIngo Molnar 
7392dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
7402dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
7412dd6d8a1SAdrian Hunter 			if (!auxtrace_snapshot_err)
7422dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
7432dd6d8a1SAdrian Hunter 			if (auxtrace_snapshot_err) {
7442dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
7452dd6d8a1SAdrian Hunter 				err = -1;
7462dd6d8a1SAdrian Hunter 				goto out_child;
7472dd6d8a1SAdrian Hunter 			}
7482dd6d8a1SAdrian Hunter 		}
7492dd6d8a1SAdrian Hunter 
750d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
7516dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
752649c48a9SPeter Zijlstra 				break;
753f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
754a515114fSJiri Olsa 			/*
755a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
756a515114fSJiri Olsa 			 * number of returned events and interrupt error.
757a515114fSJiri Olsa 			 */
758a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
75945604710SNamhyung Kim 				err = 0;
7608b412664SPeter Zijlstra 			waking++;
7616dcf45efSArnaldo Carvalho de Melo 
7626dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
7636dcf45efSArnaldo Carvalho de Melo 				draining = true;
7648b412664SPeter Zijlstra 		}
7658b412664SPeter Zijlstra 
766774cb499SJiri Olsa 		/*
767774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
768774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
769774cb499SJiri Olsa 		 * disable events in this case.
770774cb499SJiri Olsa 		 */
771602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
7722dd6d8a1SAdrian Hunter 			auxtrace_snapshot_enabled = 0;
7733e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
7742711926aSJiri Olsa 			disabled = true;
7752711926aSJiri Olsa 		}
7768b412664SPeter Zijlstra 	}
7772dd6d8a1SAdrian Hunter 	auxtrace_snapshot_enabled = 0;
7788b412664SPeter Zijlstra 
779f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
78035550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
781f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
782f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
783f33cbe72SArnaldo Carvalho de Melo 		err = -1;
78445604710SNamhyung Kim 		goto out_child;
785f33cbe72SArnaldo Carvalho de Melo 	}
786f33cbe72SArnaldo Carvalho de Melo 
787e3d59112SNamhyung Kim 	if (!quiet)
7888b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
78986470930SIngo Molnar 
79045604710SNamhyung Kim out_child:
79145604710SNamhyung Kim 	if (forks) {
79245604710SNamhyung Kim 		int exit_status;
79345604710SNamhyung Kim 
79445604710SNamhyung Kim 		if (!child_finished)
79545604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
79645604710SNamhyung Kim 
79745604710SNamhyung Kim 		wait(&exit_status);
79845604710SNamhyung Kim 
79945604710SNamhyung Kim 		if (err < 0)
80045604710SNamhyung Kim 			status = err;
80145604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
80245604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
80345604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
80445604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
80545604710SNamhyung Kim 	} else
80645604710SNamhyung Kim 		status = err;
80745604710SNamhyung Kim 
808e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
809e3d59112SNamhyung Kim 	rec->samples = 0;
810e3d59112SNamhyung Kim 
811*e1ab48baSWang Nan 	if (!err)
812*e1ab48baSWang Nan 		record__finish_output(rec);
81339d17dacSArnaldo Carvalho de Melo 
814e3d59112SNamhyung Kim 	if (!err && !quiet) {
815e3d59112SNamhyung Kim 		char samples[128];
816e3d59112SNamhyung Kim 
817ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
818e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
819e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
820e3d59112SNamhyung Kim 		else
821e3d59112SNamhyung Kim 			samples[0] = '\0';
822e3d59112SNamhyung Kim 
823e3d59112SNamhyung Kim 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s ]\n",
824e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
825e3d59112SNamhyung Kim 			file->path, samples);
826e3d59112SNamhyung Kim 	}
827e3d59112SNamhyung Kim 
82839d17dacSArnaldo Carvalho de Melo out_delete_session:
82939d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
83045604710SNamhyung Kim 	return status;
83186470930SIngo Molnar }
83286470930SIngo Molnar 
83372a128aaSNamhyung Kim static void callchain_debug(void)
83409b0fd45SJiri Olsa {
835aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
836a601fdffSJiri Olsa 
83772a128aaSNamhyung Kim 	pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
83826d33022SJiri Olsa 
83972a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_DWARF)
84009b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
84172a128aaSNamhyung Kim 			 callchain_param.dump_size);
84209b0fd45SJiri Olsa }
84309b0fd45SJiri Olsa 
844c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
84509b0fd45SJiri Olsa 			       const char *arg,
84609b0fd45SJiri Olsa 			       int unset)
84709b0fd45SJiri Olsa {
84809b0fd45SJiri Olsa 	int ret;
849c421e80bSKan Liang 	struct record_opts *record = (struct record_opts *)opt->value;
85009b0fd45SJiri Olsa 
851c421e80bSKan Liang 	record->callgraph_set = true;
85272a128aaSNamhyung Kim 	callchain_param.enabled = !unset;
853eb853e80SJiri Olsa 
85409b0fd45SJiri Olsa 	/* --no-call-graph */
85509b0fd45SJiri Olsa 	if (unset) {
85672a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_NONE;
85709b0fd45SJiri Olsa 		pr_debug("callchain: disabled\n");
85809b0fd45SJiri Olsa 		return 0;
85909b0fd45SJiri Olsa 	}
86009b0fd45SJiri Olsa 
861c3a6a8c4SKan Liang 	ret = parse_callchain_record_opt(arg, &callchain_param);
8625c0cf224SJiri Olsa 	if (!ret) {
8635c0cf224SJiri Olsa 		/* Enable data address sampling for DWARF unwind. */
8645c0cf224SJiri Olsa 		if (callchain_param.record_mode == CALLCHAIN_DWARF)
8655c0cf224SJiri Olsa 			record->sample_address = true;
86672a128aaSNamhyung Kim 		callchain_debug();
8675c0cf224SJiri Olsa 	}
86809b0fd45SJiri Olsa 
86926d33022SJiri Olsa 	return ret;
87026d33022SJiri Olsa }
87126d33022SJiri Olsa 
872c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
87309b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
87409b0fd45SJiri Olsa 			 int unset __maybe_unused)
87509b0fd45SJiri Olsa {
876c421e80bSKan Liang 	struct record_opts *record = (struct record_opts *)opt->value;
877c421e80bSKan Liang 
878c421e80bSKan Liang 	record->callgraph_set = true;
87972a128aaSNamhyung Kim 	callchain_param.enabled = true;
88009b0fd45SJiri Olsa 
88172a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_NONE)
88272a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_FP;
883eb853e80SJiri Olsa 
88472a128aaSNamhyung Kim 	callchain_debug();
88509b0fd45SJiri Olsa 	return 0;
88609b0fd45SJiri Olsa }
88709b0fd45SJiri Olsa 
888eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
889eb853e80SJiri Olsa {
8907a29c087SNamhyung Kim 	struct record *rec = cb;
8917a29c087SNamhyung Kim 
8927a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
8937a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
8947a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
8957a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
8967a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
8977a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
8987a29c087SNamhyung Kim 			rec->no_buildid = true;
8997a29c087SNamhyung Kim 		else
9007a29c087SNamhyung Kim 			return -1;
9017a29c087SNamhyung Kim 		return 0;
9027a29c087SNamhyung Kim 	}
903eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
9045a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
905eb853e80SJiri Olsa 
906eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
907eb853e80SJiri Olsa }
908eb853e80SJiri Olsa 
909814c8c38SPeter Zijlstra struct clockid_map {
910814c8c38SPeter Zijlstra 	const char *name;
911814c8c38SPeter Zijlstra 	int clockid;
912814c8c38SPeter Zijlstra };
913814c8c38SPeter Zijlstra 
914814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
915814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
916814c8c38SPeter Zijlstra 
917814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
918814c8c38SPeter Zijlstra 
919814c8c38SPeter Zijlstra 
920814c8c38SPeter Zijlstra /*
921814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
922814c8c38SPeter Zijlstra  */
923814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
924814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
925814c8c38SPeter Zijlstra #endif
926814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
927814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
928814c8c38SPeter Zijlstra #endif
929814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
930814c8c38SPeter Zijlstra #define CLOCK_TAI 11
931814c8c38SPeter Zijlstra #endif
932814c8c38SPeter Zijlstra 
933814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
934814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
935814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
936814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
937814c8c38SPeter Zijlstra 
938814c8c38SPeter Zijlstra 	/* available for some events */
939814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
940814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
941814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
942814c8c38SPeter Zijlstra 
943814c8c38SPeter Zijlstra 	/* available for the lazy */
944814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
945814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
946814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
947814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
948814c8c38SPeter Zijlstra 
949814c8c38SPeter Zijlstra 	CLOCKID_END,
950814c8c38SPeter Zijlstra };
951814c8c38SPeter Zijlstra 
952814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
953814c8c38SPeter Zijlstra {
954814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
955814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
956814c8c38SPeter Zijlstra 	const char *ostr = str;
957814c8c38SPeter Zijlstra 
958814c8c38SPeter Zijlstra 	if (unset) {
959814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
960814c8c38SPeter Zijlstra 		return 0;
961814c8c38SPeter Zijlstra 	}
962814c8c38SPeter Zijlstra 
963814c8c38SPeter Zijlstra 	/* no arg passed */
964814c8c38SPeter Zijlstra 	if (!str)
965814c8c38SPeter Zijlstra 		return 0;
966814c8c38SPeter Zijlstra 
967814c8c38SPeter Zijlstra 	/* no setting it twice */
968814c8c38SPeter Zijlstra 	if (opts->use_clockid)
969814c8c38SPeter Zijlstra 		return -1;
970814c8c38SPeter Zijlstra 
971814c8c38SPeter Zijlstra 	opts->use_clockid = true;
972814c8c38SPeter Zijlstra 
973814c8c38SPeter Zijlstra 	/* if its a number, we're done */
974814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
975814c8c38SPeter Zijlstra 		return 0;
976814c8c38SPeter Zijlstra 
977814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
978814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
979814c8c38SPeter Zijlstra 		str += 6;
980814c8c38SPeter Zijlstra 
981814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
982814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
983814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
984814c8c38SPeter Zijlstra 			return 0;
985814c8c38SPeter Zijlstra 		}
986814c8c38SPeter Zijlstra 	}
987814c8c38SPeter Zijlstra 
988814c8c38SPeter Zijlstra 	opts->use_clockid = false;
989814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
990814c8c38SPeter Zijlstra 	return -1;
991814c8c38SPeter Zijlstra }
992814c8c38SPeter Zijlstra 
993e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
994e9db1310SAdrian Hunter 				    const char *str,
995e9db1310SAdrian Hunter 				    int unset __maybe_unused)
996e9db1310SAdrian Hunter {
997e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
998e9db1310SAdrian Hunter 	char *s, *p;
999e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1000e9db1310SAdrian Hunter 	int ret;
1001e9db1310SAdrian Hunter 
1002e9db1310SAdrian Hunter 	if (!str)
1003e9db1310SAdrian Hunter 		return -EINVAL;
1004e9db1310SAdrian Hunter 
1005e9db1310SAdrian Hunter 	s = strdup(str);
1006e9db1310SAdrian Hunter 	if (!s)
1007e9db1310SAdrian Hunter 		return -ENOMEM;
1008e9db1310SAdrian Hunter 
1009e9db1310SAdrian Hunter 	p = strchr(s, ',');
1010e9db1310SAdrian Hunter 	if (p)
1011e9db1310SAdrian Hunter 		*p = '\0';
1012e9db1310SAdrian Hunter 
1013e9db1310SAdrian Hunter 	if (*s) {
1014e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1015e9db1310SAdrian Hunter 		if (ret)
1016e9db1310SAdrian Hunter 			goto out_free;
1017e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1018e9db1310SAdrian Hunter 	}
1019e9db1310SAdrian Hunter 
1020e9db1310SAdrian Hunter 	if (!p) {
1021e9db1310SAdrian Hunter 		ret = 0;
1022e9db1310SAdrian Hunter 		goto out_free;
1023e9db1310SAdrian Hunter 	}
1024e9db1310SAdrian Hunter 
1025e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1026e9db1310SAdrian Hunter 	if (ret)
1027e9db1310SAdrian Hunter 		goto out_free;
1028e9db1310SAdrian Hunter 
1029e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1030e9db1310SAdrian Hunter 
1031e9db1310SAdrian Hunter out_free:
1032e9db1310SAdrian Hunter 	free(s);
1033e9db1310SAdrian Hunter 	return ret;
1034e9db1310SAdrian Hunter }
1035e9db1310SAdrian Hunter 
1036e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
103786470930SIngo Molnar 	"perf record [<options>] [<command>]",
103886470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
103986470930SIngo Molnar 	NULL
104086470930SIngo Molnar };
1041e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
104286470930SIngo Molnar 
1043d20deb64SArnaldo Carvalho de Melo /*
10448c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
10458c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1046d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1047d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1048d20deb64SArnaldo Carvalho de Melo  *
1049d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1050d20deb64SArnaldo Carvalho de Melo  *
1051d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1052d20deb64SArnaldo Carvalho de Melo  */
10538c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1054d20deb64SArnaldo Carvalho de Melo 	.opts = {
10558affc2b8SAndi Kleen 		.sample_time	     = true,
1056d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1057d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1058d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1059447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1060d1cb9fceSNamhyung Kim 		.target		     = {
1061d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
10623aa5939dSAdrian Hunter 			.default_per_cpu = true,
1063d1cb9fceSNamhyung Kim 		},
10649d9cad76SKan Liang 		.proc_map_timeout     = 500,
1065d20deb64SArnaldo Carvalho de Melo 	},
1066e3d59112SNamhyung Kim 	.tool = {
1067e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1068e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1069cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1070e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1071e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1072e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1073cca8482cSAdrian Hunter 		.ordered_events	= true,
1074e3d59112SNamhyung Kim 	},
1075d20deb64SArnaldo Carvalho de Melo };
10767865e817SFrederic Weisbecker 
107776a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
107876a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
107961eaa3beSArnaldo Carvalho de Melo 
1080d20deb64SArnaldo Carvalho de Melo /*
1081d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1082d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1083b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1084d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1085d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1086d20deb64SArnaldo Carvalho de Melo  */
1087e5b2c207SNamhyung Kim struct option __record_options[] = {
1088d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
108986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1090f120f9d5SJiri Olsa 		     parse_events_option),
1091d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1092c171b552SLi Zefan 		     "event filter", parse_filter),
10934ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
10944ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
10954ba1faa1SWang Nan 			   exclude_perf),
1096bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1097d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1098bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1099d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1100d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
110186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1102509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1103acac03faSKirill Smelkov 		    "collect data without buffering"),
1104d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1105daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1106bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
110786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1108bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1109c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1110d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1111f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
111286470930SIngo Molnar 		    "output file name"),
111369e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
111469e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
11152e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1116d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1117e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1118e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1119e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1120d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
112143bece79SLin Ming 		    "put the counters into a counter group"),
112209b0fd45SJiri Olsa 	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
112309b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
112409b0fd45SJiri Olsa 			   &record_callchain_opt),
112509b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
112676a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
112709b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1128c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
11293da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1130b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1131d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1132649c48a9SPeter Zijlstra 		    "per thread counts"),
113356100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
11343abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
11353abebc55SAdrian Hunter 			&record.opts.sample_time_set,
11363abebc55SAdrian Hunter 			"Record the sample timestamps"),
113756100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1138d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1139649c48a9SPeter Zijlstra 		    "don't sample"),
1140d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1141d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1142a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1143d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1144d2db9a98SWang Nan 			&record.no_buildid_set,
1145baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1146d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1147023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1148023695d9SStephane Eranian 		     parse_cgroups),
1149a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
11506619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1151bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1152bea03405SNamhyung Kim 		   "user to profile"),
1153a5aabdacSStephane Eranian 
1154a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1155a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1156a5aabdacSStephane Eranian 		     parse_branch_stack),
1157a5aabdacSStephane Eranian 
1158a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1159a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1160bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
116105484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
116205484298SAndi Kleen 		    "sample by weight (on special events only)"),
1163475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1164475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
11653aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
11663aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1167bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1168bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1169bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
117085c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
117185c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1172814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1173814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1174814c8c38SPeter Zijlstra 	parse_clockid),
11752dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
11762dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
11779d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
11789d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1179b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1180b757bb09SAdrian Hunter 		    "Record context switch events"),
118185723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
118285723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
118385723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
118485723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
118585723885SJiri Olsa 			 "Configure all used events to run in user space.",
118685723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
118771dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
118871dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
118971dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
119071dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
11917efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
11927efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
11936156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
11946156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
119586470930SIngo Molnar 	OPT_END()
119686470930SIngo Molnar };
119786470930SIngo Molnar 
1198e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1199e5b2c207SNamhyung Kim 
12001d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
120186470930SIngo Molnar {
1202ef149c25SAdrian Hunter 	int err;
12038c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
120416ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
120586470930SIngo Molnar 
120648e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
120748e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
120848e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
120948e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
121048e1cab1SWang Nan # undef set_nobuild
121148e1cab1SWang Nan #endif
121248e1cab1SWang Nan 
12137efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
12147efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
12157efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
12167efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
12177efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
12187efe0e03SHe Kuang # else
12197efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
12207efe0e03SHe Kuang # endif
12217efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
12227efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
12237efe0e03SHe Kuang # undef set_nobuild
12247efe0e03SHe Kuang # undef REASON
12257efe0e03SHe Kuang #endif
12267efe0e03SHe Kuang 
12273e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
12283e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1229361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1230361c99a6SArnaldo Carvalho de Melo 
1231eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1232eb853e80SJiri Olsa 
1233bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1234a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1235602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1236bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
123786470930SIngo Molnar 
1238bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1239c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1240c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1241c7118369SNamhyung Kim 
1242023695d9SStephane Eranian 	}
1243b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1244b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1245c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1246c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1247c7118369SNamhyung Kim 		return -EINVAL;
1248b757bb09SAdrian Hunter 	}
1249023695d9SStephane Eranian 
1250ef149c25SAdrian Hunter 	if (!rec->itr) {
1251ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1252ef149c25SAdrian Hunter 		if (err)
1253ef149c25SAdrian Hunter 			return err;
1254ef149c25SAdrian Hunter 	}
1255ef149c25SAdrian Hunter 
12562dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
12572dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
12582dd6d8a1SAdrian Hunter 	if (err)
12592dd6d8a1SAdrian Hunter 		return err;
12602dd6d8a1SAdrian Hunter 
1261ef149c25SAdrian Hunter 	err = -ENOMEM;
1262ef149c25SAdrian Hunter 
12630a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1264baa2f6ceSArnaldo Carvalho de Melo 
1265ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1266646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1267646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1268ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1269646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1270646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1271646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1272646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1273646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1274ec80fde7SArnaldo Carvalho de Melo 
1275d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1276a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1277655000e7SArnaldo Carvalho de Melo 
12783e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
12793e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
128069aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
128169aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1282bbd36e5eSPeter Zijlstra 	}
128386470930SIngo Molnar 
128469e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
128569e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
128669e7e5b0SAdrian Hunter 
1287602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
128816ad2ffbSNamhyung Kim 	if (err) {
1289602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
129016ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
129116ad2ffbSNamhyung Kim 	}
12924bd0f2d2SNamhyung Kim 
1293602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
129416ad2ffbSNamhyung Kim 	if (err) {
129516ad2ffbSNamhyung Kim 		int saved_errno = errno;
129616ad2ffbSNamhyung Kim 
1297602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
12983780f488SNamhyung Kim 		ui__error("%s", errbuf);
129916ad2ffbSNamhyung Kim 
130016ad2ffbSNamhyung Kim 		err = -saved_errno;
13018fa60e1fSNamhyung Kim 		goto out_symbol_exit;
130216ad2ffbSNamhyung Kim 	}
13030d37aa34SArnaldo Carvalho de Melo 
130416ad2ffbSNamhyung Kim 	err = -ENOMEM;
13053e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1306dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
130769aad6f1SArnaldo Carvalho de Melo 
1308ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1309ef149c25SAdrian Hunter 	if (err)
1310ef149c25SAdrian Hunter 		goto out_symbol_exit;
1311ef149c25SAdrian Hunter 
13126156681bSNamhyung Kim 	/*
13136156681bSNamhyung Kim 	 * We take all buildids when the file contains
13146156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
13156156681bSNamhyung Kim 	 * trace because it would take too long.
13166156681bSNamhyung Kim 	 */
13176156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
13186156681bSNamhyung Kim 		rec->buildid_all = true;
13196156681bSNamhyung Kim 
1320b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
132139d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
132203ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
13237e4ff9e3SMike Galbraith 	}
13247e4ff9e3SMike Galbraith 
1325d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1326d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
132745604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1328d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1329ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
133039d17dacSArnaldo Carvalho de Melo 	return err;
133186470930SIngo Molnar }
13322dd6d8a1SAdrian Hunter 
13332dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
13342dd6d8a1SAdrian Hunter {
13352dd6d8a1SAdrian Hunter 	if (!auxtrace_snapshot_enabled)
13362dd6d8a1SAdrian Hunter 		return;
13372dd6d8a1SAdrian Hunter 	auxtrace_snapshot_enabled = 0;
13382dd6d8a1SAdrian Hunter 	auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr);
13392dd6d8a1SAdrian Hunter 	auxtrace_record__snapshot_started = 1;
13402dd6d8a1SAdrian Hunter }
1341