xref: /openbmc/linux/tools/perf/builtin-record.c (revision 41840d211c518e6af6e327b03e09323824e563bf)
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"
16*41840d21STaeung Song #include "util/config.h"
1786470930SIngo Molnar 
188f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
19f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
207c6a1c65SPeter Zijlstra #include "util/header.h"
2166e274f3SFrederic Weisbecker #include "util/event.h"
22361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2369aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
248f28827aSFrederic Weisbecker #include "util/debug.h"
2594c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2645694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
278d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
28a12b51c4SPaul Mackerras #include "util/cpumap.h"
29fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
30f5fc1412SJiri Olsa #include "util/data.h"
31bcc84ec6SStephane Eranian #include "util/perf_regs.h"
32ef149c25SAdrian Hunter #include "util/auxtrace.h"
3346bc29b9SAdrian Hunter #include "util/tsc.h"
34f00898f4SAndi Kleen #include "util/parse-branch-options.h"
35bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3671dc2326SWang Nan #include "util/llvm-utils.h"
378690a2a7SWang Nan #include "util/bpf-loader.h"
385f9cf599SWang Nan #include "util/trigger.h"
39d8871ea7SWang Nan #include "asm/bug.h"
407c6a1c65SPeter Zijlstra 
4186470930SIngo Molnar #include <unistd.h>
4286470930SIngo Molnar #include <sched.h>
43a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
442d11c650SWang Nan #include <asm/bug.h>
4586470930SIngo Molnar 
4678da39faSBernhard Rosenkraenzer 
478c6f45a7SArnaldo Carvalho de Melo struct record {
4845694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
49b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
50d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
51f5fc1412SJiri Olsa 	struct perf_data_file	file;
52ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
53d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
54d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
55d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
56d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
57d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
58d2db9a98SWang Nan 	bool			no_buildid_set;
59d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
60d2db9a98SWang Nan 	bool			no_buildid_cache_set;
616156681bSNamhyung Kim 	bool			buildid_all;
62ecfd7a9cSWang Nan 	bool			timestamp_filename;
633c1cb7e3SWang Nan 	bool			switch_output;
649f065194SYang Shi 	unsigned long long	samples;
650f82ebc4SArnaldo Carvalho de Melo };
6686470930SIngo Molnar 
678c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
68f5970550SPeter Zijlstra {
69cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
704f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
718d3eca20SDavid Ahern 		return -1;
728d3eca20SDavid Ahern 	}
73f5970550SPeter Zijlstra 
74cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
758d3eca20SDavid Ahern 	return 0;
76f5970550SPeter Zijlstra }
77f5970550SPeter Zijlstra 
7845694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
79d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
801d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
811d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
82234fbbf5SArnaldo Carvalho de Melo {
838c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
848c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
85234fbbf5SArnaldo Carvalho de Melo }
86234fbbf5SArnaldo Carvalho de Melo 
873a62a7b8SWang Nan static int
883a62a7b8SWang Nan backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
893a62a7b8SWang Nan {
903a62a7b8SWang Nan 	struct perf_event_header *pheader;
913a62a7b8SWang Nan 	u64 evt_head = head;
923a62a7b8SWang Nan 	int size = mask + 1;
933a62a7b8SWang Nan 
943a62a7b8SWang Nan 	pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
953a62a7b8SWang Nan 	pheader = (struct perf_event_header *)(buf + (head & mask));
963a62a7b8SWang Nan 	*start = head;
973a62a7b8SWang Nan 	while (true) {
983a62a7b8SWang Nan 		if (evt_head - head >= (unsigned int)size) {
993a62a7b8SWang Nan 			pr_debug("Finshed reading backward ring buffer: rewind\n");
1003a62a7b8SWang Nan 			if (evt_head - head > (unsigned int)size)
1013a62a7b8SWang Nan 				evt_head -= pheader->size;
1023a62a7b8SWang Nan 			*end = evt_head;
1033a62a7b8SWang Nan 			return 0;
1043a62a7b8SWang Nan 		}
1053a62a7b8SWang Nan 
1063a62a7b8SWang Nan 		pheader = (struct perf_event_header *)(buf + (evt_head & mask));
1073a62a7b8SWang Nan 
1083a62a7b8SWang Nan 		if (pheader->size == 0) {
1093a62a7b8SWang Nan 			pr_debug("Finshed reading backward ring buffer: get start\n");
1103a62a7b8SWang Nan 			*end = evt_head;
1113a62a7b8SWang Nan 			return 0;
1123a62a7b8SWang Nan 		}
1133a62a7b8SWang Nan 
1143a62a7b8SWang Nan 		evt_head += pheader->size;
1153a62a7b8SWang Nan 		pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
1163a62a7b8SWang Nan 	}
1173a62a7b8SWang Nan 	WARN_ONCE(1, "Shouldn't get here\n");
1183a62a7b8SWang Nan 	return -1;
1193a62a7b8SWang Nan }
1203a62a7b8SWang Nan 
1213a62a7b8SWang Nan static int
1223a62a7b8SWang Nan rb_find_range(struct perf_evlist *evlist,
1233a62a7b8SWang Nan 	      void *data, int mask, u64 head, u64 old,
1243a62a7b8SWang Nan 	      u64 *start, u64 *end)
1253a62a7b8SWang Nan {
1263a62a7b8SWang Nan 	if (!evlist->backward) {
1273a62a7b8SWang Nan 		*start = old;
1283a62a7b8SWang Nan 		*end = head;
1293a62a7b8SWang Nan 		return 0;
1303a62a7b8SWang Nan 	}
1313a62a7b8SWang Nan 
1323a62a7b8SWang Nan 	return backward_rb_find_range(data, mask, head, start, end);
1333a62a7b8SWang Nan }
1343a62a7b8SWang Nan 
135e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
13686470930SIngo Molnar {
137e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
1387b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
1397b8283b5SDavid Ahern 	u64 old = md->prev;
14009fa4f40SWang Nan 	u64 end = head, start = old;
141918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
14286470930SIngo Molnar 	unsigned long size;
14386470930SIngo Molnar 	void *buf;
1448d3eca20SDavid Ahern 	int rc = 0;
14586470930SIngo Molnar 
1463a62a7b8SWang Nan 	if (rb_find_range(rec->evlist, data, md->mask, head,
1473a62a7b8SWang Nan 			  old, &start, &end))
1483a62a7b8SWang Nan 		return -1;
1493a62a7b8SWang Nan 
15009fa4f40SWang Nan 	if (start == end)
1518d3eca20SDavid Ahern 		return 0;
15286470930SIngo Molnar 
153d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
15486470930SIngo Molnar 
15509fa4f40SWang Nan 	size = end - start;
1562d11c650SWang Nan 	if (size > (unsigned long)(md->mask) + 1) {
1572d11c650SWang Nan 		WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
1582d11c650SWang Nan 
1592d11c650SWang Nan 		md->prev = head;
1602d11c650SWang Nan 		perf_evlist__mmap_consume(rec->evlist, idx);
1612d11c650SWang Nan 		return 0;
1622d11c650SWang Nan 	}
16386470930SIngo Molnar 
16409fa4f40SWang Nan 	if ((start & md->mask) + size != (end & md->mask)) {
16509fa4f40SWang Nan 		buf = &data[start & md->mask];
16609fa4f40SWang Nan 		size = md->mask + 1 - (start & md->mask);
16709fa4f40SWang Nan 		start += size;
16886470930SIngo Molnar 
1698c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
1708d3eca20SDavid Ahern 			rc = -1;
1718d3eca20SDavid Ahern 			goto out;
1728d3eca20SDavid Ahern 		}
17386470930SIngo Molnar 	}
17486470930SIngo Molnar 
17509fa4f40SWang Nan 	buf = &data[start & md->mask];
17609fa4f40SWang Nan 	size = end - start;
17709fa4f40SWang Nan 	start += size;
17886470930SIngo Molnar 
1798c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1808d3eca20SDavid Ahern 		rc = -1;
1818d3eca20SDavid Ahern 		goto out;
1828d3eca20SDavid Ahern 	}
18386470930SIngo Molnar 
18409fa4f40SWang Nan 	md->prev = head;
185e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1868d3eca20SDavid Ahern out:
1878d3eca20SDavid Ahern 	return rc;
18886470930SIngo Molnar }
18986470930SIngo Molnar 
1902dd6d8a1SAdrian Hunter static volatile int done;
1912dd6d8a1SAdrian Hunter static volatile int signr = -1;
1922dd6d8a1SAdrian Hunter static volatile int child_finished;
193c0bdc1c4SWang Nan 
1942dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1955f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
1963c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger);
1972dd6d8a1SAdrian Hunter 
1982dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1992dd6d8a1SAdrian Hunter {
2002dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
2012dd6d8a1SAdrian Hunter 		child_finished = 1;
2022dd6d8a1SAdrian Hunter 	else
2032dd6d8a1SAdrian Hunter 		signr = sig;
2042dd6d8a1SAdrian Hunter 
2052dd6d8a1SAdrian Hunter 	done = 1;
2062dd6d8a1SAdrian Hunter }
2072dd6d8a1SAdrian Hunter 
2082dd6d8a1SAdrian Hunter static void record__sig_exit(void)
2092dd6d8a1SAdrian Hunter {
2102dd6d8a1SAdrian Hunter 	if (signr == -1)
2112dd6d8a1SAdrian Hunter 		return;
2122dd6d8a1SAdrian Hunter 
2132dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
2142dd6d8a1SAdrian Hunter 	raise(signr);
2152dd6d8a1SAdrian Hunter }
2162dd6d8a1SAdrian Hunter 
217e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
218e31f0d01SAdrian Hunter 
219ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
220ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
221ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
222ef149c25SAdrian Hunter {
223ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
22499fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
225ef149c25SAdrian Hunter 	size_t padding;
226ef149c25SAdrian Hunter 	u8 pad[8] = {0};
227ef149c25SAdrian Hunter 
22899fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
22999fa2984SAdrian Hunter 		off_t file_offset;
23099fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
23199fa2984SAdrian Hunter 		int err;
23299fa2984SAdrian Hunter 
23399fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
23499fa2984SAdrian Hunter 		if (file_offset == -1)
23599fa2984SAdrian Hunter 			return -1;
23699fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
23799fa2984SAdrian Hunter 						     event, file_offset);
23899fa2984SAdrian Hunter 		if (err)
23999fa2984SAdrian Hunter 			return err;
24099fa2984SAdrian Hunter 	}
24199fa2984SAdrian Hunter 
242ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
243ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
244ef149c25SAdrian Hunter 	if (padding)
245ef149c25SAdrian Hunter 		padding = 8 - padding;
246ef149c25SAdrian Hunter 
247ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
248ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
249ef149c25SAdrian Hunter 	if (len2)
250ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
251ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
252ef149c25SAdrian Hunter 
253ef149c25SAdrian Hunter 	return 0;
254ef149c25SAdrian Hunter }
255ef149c25SAdrian Hunter 
256ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
257ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
258ef149c25SAdrian Hunter {
259ef149c25SAdrian Hunter 	int ret;
260ef149c25SAdrian Hunter 
261ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
262ef149c25SAdrian Hunter 				  record__process_auxtrace);
263ef149c25SAdrian Hunter 	if (ret < 0)
264ef149c25SAdrian Hunter 		return ret;
265ef149c25SAdrian Hunter 
266ef149c25SAdrian Hunter 	if (ret)
267ef149c25SAdrian Hunter 		rec->samples++;
268ef149c25SAdrian Hunter 
269ef149c25SAdrian Hunter 	return 0;
270ef149c25SAdrian Hunter }
271ef149c25SAdrian Hunter 
2722dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2732dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2742dd6d8a1SAdrian Hunter {
2752dd6d8a1SAdrian Hunter 	int ret;
2762dd6d8a1SAdrian Hunter 
2772dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2782dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2792dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2802dd6d8a1SAdrian Hunter 	if (ret < 0)
2812dd6d8a1SAdrian Hunter 		return ret;
2822dd6d8a1SAdrian Hunter 
2832dd6d8a1SAdrian Hunter 	if (ret)
2842dd6d8a1SAdrian Hunter 		rec->samples++;
2852dd6d8a1SAdrian Hunter 
2862dd6d8a1SAdrian Hunter 	return 0;
2872dd6d8a1SAdrian Hunter }
2882dd6d8a1SAdrian Hunter 
2892dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2902dd6d8a1SAdrian Hunter {
2912dd6d8a1SAdrian Hunter 	int i;
2922dd6d8a1SAdrian Hunter 	int rc = 0;
2932dd6d8a1SAdrian Hunter 
2942dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2952dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2962dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2972dd6d8a1SAdrian Hunter 
2982dd6d8a1SAdrian Hunter 		if (!mm->base)
2992dd6d8a1SAdrian Hunter 			continue;
3002dd6d8a1SAdrian Hunter 
3012dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
3022dd6d8a1SAdrian Hunter 			rc = -1;
3032dd6d8a1SAdrian Hunter 			goto out;
3042dd6d8a1SAdrian Hunter 		}
3052dd6d8a1SAdrian Hunter 	}
3062dd6d8a1SAdrian Hunter out:
3072dd6d8a1SAdrian Hunter 	return rc;
3082dd6d8a1SAdrian Hunter }
3092dd6d8a1SAdrian Hunter 
3102dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
3112dd6d8a1SAdrian Hunter {
3122dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
3132dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
3145f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
3152dd6d8a1SAdrian Hunter 	} else {
3165f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
3175f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
3185f9cf599SWang Nan 		else
3195f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
3202dd6d8a1SAdrian Hunter 	}
3212dd6d8a1SAdrian Hunter }
3222dd6d8a1SAdrian Hunter 
323e31f0d01SAdrian Hunter #else
324e31f0d01SAdrian Hunter 
325e31f0d01SAdrian Hunter static inline
326e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
327e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
328e31f0d01SAdrian Hunter {
329e31f0d01SAdrian Hunter 	return 0;
330e31f0d01SAdrian Hunter }
331e31f0d01SAdrian Hunter 
3322dd6d8a1SAdrian Hunter static inline
3332dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
3342dd6d8a1SAdrian Hunter {
3352dd6d8a1SAdrian Hunter }
3362dd6d8a1SAdrian Hunter 
3372dd6d8a1SAdrian Hunter static inline
3382dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
3392dd6d8a1SAdrian Hunter {
3402dd6d8a1SAdrian Hunter 	return 0;
3412dd6d8a1SAdrian Hunter }
3422dd6d8a1SAdrian Hunter 
343e31f0d01SAdrian Hunter #endif
344e31f0d01SAdrian Hunter 
3458c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
346dd7927f4SArnaldo Carvalho de Melo {
34756e52e85SArnaldo Carvalho de Melo 	char msg[512];
3486a4bb04cSJiri Olsa 	struct perf_evsel *pos;
349d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
350d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
351b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
3528d3eca20SDavid Ahern 	int rc = 0;
353dd7927f4SArnaldo Carvalho de Melo 
354e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
355cac21425SJiri Olsa 
3560050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
3573da297a6SIngo Molnar try_again:
358d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
35956e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
3603da297a6SIngo Molnar 				if (verbose)
361c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3623da297a6SIngo Molnar 				goto try_again;
3633da297a6SIngo Molnar 			}
364ca6a4258SDavid Ahern 
36556e52e85SArnaldo Carvalho de Melo 			rc = -errno;
36656e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
36756e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
36856e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3698d3eca20SDavid Ahern 			goto out;
3707c6a1c65SPeter Zijlstra 		}
3717c6a1c65SPeter Zijlstra 	}
3727c6a1c65SPeter Zijlstra 
37323d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
37423d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
37523d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
37635550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3778d3eca20SDavid Ahern 		rc = -1;
3788d3eca20SDavid Ahern 		goto out;
3790a102479SFrederic Weisbecker 	}
3800a102479SFrederic Weisbecker 
381ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3822dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3832dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3848d3eca20SDavid Ahern 		if (errno == EPERM) {
3858d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
38618e60939SNelson Elhage 			       "Consider increasing "
38718e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
38818e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
389ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
390ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3918d3eca20SDavid Ahern 			rc = -errno;
3928d3eca20SDavid Ahern 		} else {
39335550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
39435550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
39595c36561SWang Nan 			if (errno)
3968d3eca20SDavid Ahern 				rc = -errno;
39795c36561SWang Nan 			else
39895c36561SWang Nan 				rc = -EINVAL;
3998d3eca20SDavid Ahern 		}
4008d3eca20SDavid Ahern 		goto out;
40118e60939SNelson Elhage 	}
4020a27d7f9SArnaldo Carvalho de Melo 
403a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
4047b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
4058d3eca20SDavid Ahern out:
4068d3eca20SDavid Ahern 	return rc;
407a91e5431SArnaldo Carvalho de Melo }
408a91e5431SArnaldo Carvalho de Melo 
409e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
410e3d59112SNamhyung Kim 				union perf_event *event,
411e3d59112SNamhyung Kim 				struct perf_sample *sample,
412e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
413e3d59112SNamhyung Kim 				struct machine *machine)
414e3d59112SNamhyung Kim {
415e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
416e3d59112SNamhyung Kim 
417e3d59112SNamhyung Kim 	rec->samples++;
418e3d59112SNamhyung Kim 
419e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
420e3d59112SNamhyung Kim }
421e3d59112SNamhyung Kim 
4228c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
4236122e4e4SArnaldo Carvalho de Melo {
424f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
425f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
4266122e4e4SArnaldo Carvalho de Melo 
427457ae94aSHe Kuang 	if (file->size == 0)
4289f591fd7SArnaldo Carvalho de Melo 		return 0;
4299f591fd7SArnaldo Carvalho de Melo 
43000dc8657SNamhyung Kim 	/*
43100dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
43200dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
43300dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
43400dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
43500dc8657SNamhyung Kim 	 *
43600dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
43700dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
43800dc8657SNamhyung Kim 	 */
43900dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
44000dc8657SNamhyung Kim 
4416156681bSNamhyung Kim 	/*
4426156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
4436156681bSNamhyung Kim 	 * so no need to process samples.
4446156681bSNamhyung Kim 	 */
4456156681bSNamhyung Kim 	if (rec->buildid_all)
4466156681bSNamhyung Kim 		rec->tool.sample = NULL;
4476156681bSNamhyung Kim 
448b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
4496122e4e4SArnaldo Carvalho de Melo }
4506122e4e4SArnaldo Carvalho de Melo 
4518115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
452a1645ce1SZhang, Yanmin {
453a1645ce1SZhang, Yanmin 	int err;
45445694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
455a1645ce1SZhang, Yanmin 	/*
456a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
457a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
458a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
459a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
460a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
461a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
462a1645ce1SZhang, Yanmin 	 */
46345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
464743eb868SArnaldo Carvalho de Melo 					     machine);
465a1645ce1SZhang, Yanmin 	if (err < 0)
466a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
46723346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
468a1645ce1SZhang, Yanmin 
469a1645ce1SZhang, Yanmin 	/*
470a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
471a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
472a1645ce1SZhang, Yanmin 	 */
47345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4740ae617beSAdrian Hunter 						 machine);
475a1645ce1SZhang, Yanmin 	if (err < 0)
476a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
47723346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
478a1645ce1SZhang, Yanmin }
479a1645ce1SZhang, Yanmin 
48098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
48198402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
48298402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
48398402807SFrederic Weisbecker };
48498402807SFrederic Weisbecker 
4858c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
48698402807SFrederic Weisbecker {
487dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4880e2e63ddSPeter Zijlstra 	int i;
4898d3eca20SDavid Ahern 	int rc = 0;
49098402807SFrederic Weisbecker 
491d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
492ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
493ef149c25SAdrian Hunter 
4948d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
495e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4968d3eca20SDavid Ahern 				rc = -1;
4978d3eca20SDavid Ahern 				goto out;
4988d3eca20SDavid Ahern 			}
4998d3eca20SDavid Ahern 		}
500ef149c25SAdrian Hunter 
5012dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
502ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
503ef149c25SAdrian Hunter 			rc = -1;
504ef149c25SAdrian Hunter 			goto out;
505ef149c25SAdrian Hunter 		}
50698402807SFrederic Weisbecker 	}
50798402807SFrederic Weisbecker 
508dcabb507SJiri Olsa 	/*
509dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
510dcabb507SJiri Olsa 	 * at least one event.
511dcabb507SJiri Olsa 	 */
512dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
5138c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
5148d3eca20SDavid Ahern 
5158d3eca20SDavid Ahern out:
5168d3eca20SDavid Ahern 	return rc;
51798402807SFrederic Weisbecker }
51898402807SFrederic Weisbecker 
5198c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
52057706abcSDavid Ahern {
52157706abcSDavid Ahern 	struct perf_session *session = rec->session;
52257706abcSDavid Ahern 	int feat;
52357706abcSDavid Ahern 
52457706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
52557706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
52657706abcSDavid Ahern 
52757706abcSDavid Ahern 	if (rec->no_buildid)
52857706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
52957706abcSDavid Ahern 
5303e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
53157706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
53257706abcSDavid Ahern 
53357706abcSDavid Ahern 	if (!rec->opts.branch_stack)
53457706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
535ef149c25SAdrian Hunter 
536ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
537ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
538ffa517adSJiri Olsa 
539ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
54057706abcSDavid Ahern }
54157706abcSDavid Ahern 
542e1ab48baSWang Nan static void
543e1ab48baSWang Nan record__finish_output(struct record *rec)
544e1ab48baSWang Nan {
545e1ab48baSWang Nan 	struct perf_data_file *file = &rec->file;
546e1ab48baSWang Nan 	int fd = perf_data_file__fd(file);
547e1ab48baSWang Nan 
548e1ab48baSWang Nan 	if (file->is_pipe)
549e1ab48baSWang Nan 		return;
550e1ab48baSWang Nan 
551e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
552e1ab48baSWang Nan 	file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
553e1ab48baSWang Nan 
554e1ab48baSWang Nan 	if (!rec->no_buildid) {
555e1ab48baSWang Nan 		process_buildids(rec);
556e1ab48baSWang Nan 
557e1ab48baSWang Nan 		if (rec->buildid_all)
558e1ab48baSWang Nan 			dsos__hit_all(rec->session);
559e1ab48baSWang Nan 	}
560e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
561e1ab48baSWang Nan 
562e1ab48baSWang Nan 	return;
563e1ab48baSWang Nan }
564e1ab48baSWang Nan 
565be7b0c9eSWang Nan static int record__synthesize_workload(struct record *rec)
566be7b0c9eSWang Nan {
567be7b0c9eSWang Nan 	struct {
568be7b0c9eSWang Nan 		struct thread_map map;
569be7b0c9eSWang Nan 		struct thread_map_data map_data;
570be7b0c9eSWang Nan 	} thread_map;
571be7b0c9eSWang Nan 
572be7b0c9eSWang Nan 	thread_map.map.nr = 1;
573be7b0c9eSWang Nan 	thread_map.map.map[0].pid = rec->evlist->workload.pid;
574be7b0c9eSWang Nan 	thread_map.map.map[0].comm = NULL;
575be7b0c9eSWang Nan 	return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
576be7b0c9eSWang Nan 						 process_synthesized_event,
577be7b0c9eSWang Nan 						 &rec->session->machines.host,
578be7b0c9eSWang Nan 						 rec->opts.sample_address,
579be7b0c9eSWang Nan 						 rec->opts.proc_map_timeout);
580be7b0c9eSWang Nan }
581be7b0c9eSWang Nan 
5823c1cb7e3SWang Nan static int record__synthesize(struct record *rec);
5833c1cb7e3SWang Nan 
584ecfd7a9cSWang Nan static int
585ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
586ecfd7a9cSWang Nan {
587ecfd7a9cSWang Nan 	struct perf_data_file *file = &rec->file;
588ecfd7a9cSWang Nan 	int fd, err;
589ecfd7a9cSWang Nan 
590ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
591ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
592ecfd7a9cSWang Nan 
593ecfd7a9cSWang Nan 	rec->samples = 0;
594ecfd7a9cSWang Nan 	record__finish_output(rec);
595ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
596ecfd7a9cSWang Nan 	if (err) {
597ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
598ecfd7a9cSWang Nan 		return -EINVAL;
599ecfd7a9cSWang Nan 	}
600ecfd7a9cSWang Nan 
601ecfd7a9cSWang Nan 	fd = perf_data_file__switch(file, timestamp,
602ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
603ecfd7a9cSWang Nan 				    at_exit);
604ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
605ecfd7a9cSWang Nan 		rec->bytes_written = 0;
606ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
607ecfd7a9cSWang Nan 	}
608ecfd7a9cSWang Nan 
609ecfd7a9cSWang Nan 	if (!quiet)
610ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
611ecfd7a9cSWang Nan 			file->path, timestamp);
6123c1cb7e3SWang Nan 
6133c1cb7e3SWang Nan 	/* Output tracking events */
614be7b0c9eSWang Nan 	if (!at_exit) {
6153c1cb7e3SWang Nan 		record__synthesize(rec);
6163c1cb7e3SWang Nan 
617be7b0c9eSWang Nan 		/*
618be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
619be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
620be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
621be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
622be7b0c9eSWang Nan 		 * contain map and comm information.
623be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
624be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
625be7b0c9eSWang Nan 		 */
626be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
627be7b0c9eSWang Nan 			record__synthesize_workload(rec);
628be7b0c9eSWang Nan 	}
629ecfd7a9cSWang Nan 	return fd;
630ecfd7a9cSWang Nan }
631ecfd7a9cSWang Nan 
632f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
633f33cbe72SArnaldo Carvalho de Melo 
634f33cbe72SArnaldo Carvalho de Melo /*
635f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
636f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
637f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
638f33cbe72SArnaldo Carvalho de Melo  */
63945604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
64045604710SNamhyung Kim 					siginfo_t *info,
641f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
642f33cbe72SArnaldo Carvalho de Melo {
643f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
644f33cbe72SArnaldo Carvalho de Melo 	done = 1;
645f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
646f33cbe72SArnaldo Carvalho de Melo }
647f33cbe72SArnaldo Carvalho de Melo 
6482dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
6492dd6d8a1SAdrian Hunter 
65046bc29b9SAdrian Hunter int __weak
65146bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
65246bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
65346bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
65446bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
65546bc29b9SAdrian Hunter {
65646bc29b9SAdrian Hunter 	return 0;
65746bc29b9SAdrian Hunter }
65846bc29b9SAdrian Hunter 
659c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
660c45628b0SWang Nan {
661c45628b0SWang Nan 	if (rec->evlist && rec->evlist->mmap && rec->evlist->mmap[0].base)
662c45628b0SWang Nan 		return rec->evlist->mmap[0].base;
663c45628b0SWang Nan 	return NULL;
664c45628b0SWang Nan }
665c45628b0SWang Nan 
666c45c86ebSWang Nan static int record__synthesize(struct record *rec)
667c45c86ebSWang Nan {
668c45c86ebSWang Nan 	struct perf_session *session = rec->session;
669c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
670c45c86ebSWang Nan 	struct perf_data_file *file = &rec->file;
671c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
672c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
673c45c86ebSWang Nan 	int fd = perf_data_file__fd(file);
674c45c86ebSWang Nan 	int err = 0;
675c45c86ebSWang Nan 
676c45c86ebSWang Nan 	if (file->is_pipe) {
677c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
678c45c86ebSWang Nan 						   process_synthesized_event);
679c45c86ebSWang Nan 		if (err < 0) {
680c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
681c45c86ebSWang Nan 			goto out;
682c45c86ebSWang Nan 		}
683c45c86ebSWang Nan 
684c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
685c45c86ebSWang Nan 			/*
686c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
687c45c86ebSWang Nan 			 * there were no tracepoints so its not really
688c45c86ebSWang Nan 			 * an error, just that we don't need to
689c45c86ebSWang Nan 			 * synthesize anything.  We really have to
690c45c86ebSWang Nan 			 * return this more properly and also
691c45c86ebSWang Nan 			 * propagate errors that now are calling die()
692c45c86ebSWang Nan 			 */
693c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
694c45c86ebSWang Nan 								  process_synthesized_event);
695c45c86ebSWang Nan 			if (err <= 0) {
696c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
697c45c86ebSWang Nan 				goto out;
698c45c86ebSWang Nan 			}
699c45c86ebSWang Nan 			rec->bytes_written += err;
700c45c86ebSWang Nan 		}
701c45c86ebSWang Nan 	}
702c45c86ebSWang Nan 
703c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
70446bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
70546bc29b9SAdrian Hunter 	if (err)
70646bc29b9SAdrian Hunter 		goto out;
70746bc29b9SAdrian Hunter 
708c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
709c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
710c45c86ebSWang Nan 					session, process_synthesized_event);
711c45c86ebSWang Nan 		if (err)
712c45c86ebSWang Nan 			goto out;
713c45c86ebSWang Nan 	}
714c45c86ebSWang Nan 
715c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
716c45c86ebSWang Nan 						 machine);
717c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
718c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
719c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
720c45c86ebSWang Nan 
721c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
722c45c86ebSWang Nan 					     machine);
723c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
724c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
725c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
726c45c86ebSWang Nan 
727c45c86ebSWang Nan 	if (perf_guest) {
728c45c86ebSWang Nan 		machines__process_guests(&session->machines,
729c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
730c45c86ebSWang Nan 	}
731c45c86ebSWang Nan 
732c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
733c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
734c45c86ebSWang Nan 					    opts->proc_map_timeout);
735c45c86ebSWang Nan out:
736c45c86ebSWang Nan 	return err;
737c45c86ebSWang Nan }
738c45c86ebSWang Nan 
7398c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
74086470930SIngo Molnar {
74157706abcSDavid Ahern 	int err;
74245604710SNamhyung Kim 	int status = 0;
7438b412664SPeter Zijlstra 	unsigned long waking = 0;
74446be604bSZhang, Yanmin 	const bool forks = argc > 0;
74523346f21SArnaldo Carvalho de Melo 	struct machine *machine;
74645694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
747b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
748f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
749d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
7506dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
75142aa276fSNamhyung Kim 	int fd;
75286470930SIngo Molnar 
753d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
75433e49ea7SAndi Kleen 
75545604710SNamhyung Kim 	atexit(record__sig_exit);
756f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
757f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
758804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
759c0bdc1c4SWang Nan 
7603c1cb7e3SWang Nan 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
7612dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
7623c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
7635f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
7643c1cb7e3SWang Nan 		if (rec->switch_output)
7653c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
766c0bdc1c4SWang Nan 	} else {
7672dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
768c0bdc1c4SWang Nan 	}
769f5970550SPeter Zijlstra 
770b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
77194c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
772ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
773a9a70bbcSArnaldo Carvalho de Melo 		return -1;
774a9a70bbcSArnaldo Carvalho de Melo 	}
775a9a70bbcSArnaldo Carvalho de Melo 
77642aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
777d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
778d20deb64SArnaldo Carvalho de Melo 
7798c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
780330aa675SStephane Eranian 
781d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
7823e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
783f5fc1412SJiri Olsa 						    argv, file->is_pipe,
784735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
78535b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
78635b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
78745604710SNamhyung Kim 			status = err;
78835b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
789856e9660SPeter Zijlstra 		}
790856e9660SPeter Zijlstra 	}
791856e9660SPeter Zijlstra 
7928c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
7938d3eca20SDavid Ahern 		err = -1;
79445604710SNamhyung Kim 		goto out_child;
7958d3eca20SDavid Ahern 	}
79686470930SIngo Molnar 
7978690a2a7SWang Nan 	err = bpf__apply_obj_config();
7988690a2a7SWang Nan 	if (err) {
7998690a2a7SWang Nan 		char errbuf[BUFSIZ];
8008690a2a7SWang Nan 
8018690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
8028690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
8038690a2a7SWang Nan 			 errbuf);
8048690a2a7SWang Nan 		goto out_child;
8058690a2a7SWang Nan 	}
8068690a2a7SWang Nan 
807cca8482cSAdrian Hunter 	/*
808cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
809cca8482cSAdrian Hunter 	 * evlist.
810cca8482cSAdrian Hunter 	 */
811cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
812cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
813cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
814cca8482cSAdrian Hunter 	}
815cca8482cSAdrian Hunter 
8163e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
817a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
818a8bb559bSNamhyung Kim 
819f5fc1412SJiri Olsa 	if (file->is_pipe) {
82042aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
821529870e3STom Zanussi 		if (err < 0)
82245604710SNamhyung Kim 			goto out_child;
823563aecb2SJiri Olsa 	} else {
82442aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
825d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
82645604710SNamhyung Kim 			goto out_child;
827d5eed904SArnaldo Carvalho de Melo 	}
8287c6a1c65SPeter Zijlstra 
829d3665498SDavid Ahern 	if (!rec->no_buildid
830e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
831d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
832e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
8338d3eca20SDavid Ahern 		err = -1;
83445604710SNamhyung Kim 		goto out_child;
835e20960c0SRobert Richter 	}
836e20960c0SRobert Richter 
83734ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
838743eb868SArnaldo Carvalho de Melo 
839c45c86ebSWang Nan 	err = record__synthesize(rec);
840c45c86ebSWang Nan 	if (err < 0)
84145604710SNamhyung Kim 		goto out_child;
8428d3eca20SDavid Ahern 
843d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
84486470930SIngo Molnar 		struct sched_param param;
84586470930SIngo Molnar 
846d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
84786470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
8486beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
8498d3eca20SDavid Ahern 			err = -1;
85045604710SNamhyung Kim 			goto out_child;
85186470930SIngo Molnar 		}
85286470930SIngo Molnar 	}
85386470930SIngo Molnar 
854774cb499SJiri Olsa 	/*
855774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
856774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
857774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
858774cb499SJiri Olsa 	 */
8596619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
8603e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
861764e16a3SDavid Ahern 
862856e9660SPeter Zijlstra 	/*
863856e9660SPeter Zijlstra 	 * Let the child rip
864856e9660SPeter Zijlstra 	 */
865e803cf97SNamhyung Kim 	if (forks) {
866e5bed564SNamhyung Kim 		union perf_event *event;
867e5bed564SNamhyung Kim 
868e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
869e5bed564SNamhyung Kim 		if (event == NULL) {
870e5bed564SNamhyung Kim 			err = -ENOMEM;
871e5bed564SNamhyung Kim 			goto out_child;
872e5bed564SNamhyung Kim 		}
873e5bed564SNamhyung Kim 
874e803cf97SNamhyung Kim 		/*
875e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
876e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
877e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
878e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
879e803cf97SNamhyung Kim 		 */
880e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
881e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
882e803cf97SNamhyung Kim 					    process_synthesized_event,
883e803cf97SNamhyung Kim 					    machine);
884e5bed564SNamhyung Kim 		free(event);
885e803cf97SNamhyung Kim 
8863e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
887e803cf97SNamhyung Kim 	}
888856e9660SPeter Zijlstra 
8896619a53eSAndi Kleen 	if (opts->initial_delay) {
8906619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
8916619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
8926619a53eSAndi Kleen 	}
8936619a53eSAndi Kleen 
8945f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
8953c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
896649c48a9SPeter Zijlstra 	for (;;) {
8979f065194SYang Shi 		unsigned long long hits = rec->samples;
89886470930SIngo Molnar 
8998c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
9005f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
9013c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
9028d3eca20SDavid Ahern 			err = -1;
90345604710SNamhyung Kim 			goto out_child;
9048d3eca20SDavid Ahern 		}
90586470930SIngo Molnar 
9062dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
9072dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
9085f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
9092dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
9105f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
9112dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
9122dd6d8a1SAdrian Hunter 				err = -1;
9132dd6d8a1SAdrian Hunter 				goto out_child;
9142dd6d8a1SAdrian Hunter 			}
9152dd6d8a1SAdrian Hunter 		}
9162dd6d8a1SAdrian Hunter 
9173c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
9183c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
9193c1cb7e3SWang Nan 
9203c1cb7e3SWang Nan 			if (!quiet)
9213c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
9223c1cb7e3SWang Nan 					waking);
9233c1cb7e3SWang Nan 			waking = 0;
9243c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
9253c1cb7e3SWang Nan 			if (fd < 0) {
9263c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
9273c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
9283c1cb7e3SWang Nan 				err = fd;
9293c1cb7e3SWang Nan 				goto out_child;
9303c1cb7e3SWang Nan 			}
9313c1cb7e3SWang Nan 		}
9323c1cb7e3SWang Nan 
933d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
9346dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
935649c48a9SPeter Zijlstra 				break;
936f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
937a515114fSJiri Olsa 			/*
938a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
939a515114fSJiri Olsa 			 * number of returned events and interrupt error.
940a515114fSJiri Olsa 			 */
941a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
94245604710SNamhyung Kim 				err = 0;
9438b412664SPeter Zijlstra 			waking++;
9446dcf45efSArnaldo Carvalho de Melo 
9456dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
9466dcf45efSArnaldo Carvalho de Melo 				draining = true;
9478b412664SPeter Zijlstra 		}
9488b412664SPeter Zijlstra 
949774cb499SJiri Olsa 		/*
950774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
951774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
952774cb499SJiri Olsa 		 * disable events in this case.
953774cb499SJiri Olsa 		 */
954602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
9555f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
9563e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
9572711926aSJiri Olsa 			disabled = true;
9582711926aSJiri Olsa 		}
9598b412664SPeter Zijlstra 	}
9605f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
9613c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
9628b412664SPeter Zijlstra 
963f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
96435550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
965f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
966f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
967f33cbe72SArnaldo Carvalho de Melo 		err = -1;
96845604710SNamhyung Kim 		goto out_child;
969f33cbe72SArnaldo Carvalho de Melo 	}
970f33cbe72SArnaldo Carvalho de Melo 
971e3d59112SNamhyung Kim 	if (!quiet)
9728b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
97386470930SIngo Molnar 
97445604710SNamhyung Kim out_child:
97545604710SNamhyung Kim 	if (forks) {
97645604710SNamhyung Kim 		int exit_status;
97745604710SNamhyung Kim 
97845604710SNamhyung Kim 		if (!child_finished)
97945604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
98045604710SNamhyung Kim 
98145604710SNamhyung Kim 		wait(&exit_status);
98245604710SNamhyung Kim 
98345604710SNamhyung Kim 		if (err < 0)
98445604710SNamhyung Kim 			status = err;
98545604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
98645604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
98745604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
98845604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
98945604710SNamhyung Kim 	} else
99045604710SNamhyung Kim 		status = err;
99145604710SNamhyung Kim 
992e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
993e3d59112SNamhyung Kim 	rec->samples = 0;
994e3d59112SNamhyung Kim 
995ecfd7a9cSWang Nan 	if (!err) {
996ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
997e1ab48baSWang Nan 			record__finish_output(rec);
998ecfd7a9cSWang Nan 		} else {
999ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1000ecfd7a9cSWang Nan 			if (fd < 0) {
1001ecfd7a9cSWang Nan 				status = fd;
1002ecfd7a9cSWang Nan 				goto out_delete_session;
1003ecfd7a9cSWang Nan 			}
1004ecfd7a9cSWang Nan 		}
1005ecfd7a9cSWang Nan 	}
100639d17dacSArnaldo Carvalho de Melo 
1007e3d59112SNamhyung Kim 	if (!err && !quiet) {
1008e3d59112SNamhyung Kim 		char samples[128];
1009ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1010ecfd7a9cSWang Nan 					".<timestamp>" : "";
1011e3d59112SNamhyung Kim 
1012ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1013e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1014e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1015e3d59112SNamhyung Kim 		else
1016e3d59112SNamhyung Kim 			samples[0] = '\0';
1017e3d59112SNamhyung Kim 
1018ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
1019e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
1020ecfd7a9cSWang Nan 			file->path, postfix, samples);
1021e3d59112SNamhyung Kim 	}
1022e3d59112SNamhyung Kim 
102339d17dacSArnaldo Carvalho de Melo out_delete_session:
102439d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
102545604710SNamhyung Kim 	return status;
102686470930SIngo Molnar }
102786470930SIngo Molnar 
10280883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
102909b0fd45SJiri Olsa {
1030aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1031a601fdffSJiri Olsa 
10320883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
103326d33022SJiri Olsa 
10340883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
103509b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
10360883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
10370883e820SArnaldo Carvalho de Melo }
10380883e820SArnaldo Carvalho de Melo 
10390883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
10400883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
10410883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
10420883e820SArnaldo Carvalho de Melo {
10430883e820SArnaldo Carvalho de Melo 	int ret;
10440883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
10450883e820SArnaldo Carvalho de Melo 
10460883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
10470883e820SArnaldo Carvalho de Melo 	if (unset) {
10480883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
10490883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
10500883e820SArnaldo Carvalho de Melo 		return 0;
10510883e820SArnaldo Carvalho de Melo 	}
10520883e820SArnaldo Carvalho de Melo 
10530883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
10540883e820SArnaldo Carvalho de Melo 	if (!ret) {
10550883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
10560883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
10570883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
10580883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
10590883e820SArnaldo Carvalho de Melo 	}
10600883e820SArnaldo Carvalho de Melo 
10610883e820SArnaldo Carvalho de Melo 	return ret;
106209b0fd45SJiri Olsa }
106309b0fd45SJiri Olsa 
1064c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
106509b0fd45SJiri Olsa 			       const char *arg,
106609b0fd45SJiri Olsa 			       int unset)
106709b0fd45SJiri Olsa {
10680883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
106926d33022SJiri Olsa }
107026d33022SJiri Olsa 
1071c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
107209b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
107309b0fd45SJiri Olsa 			 int unset __maybe_unused)
107409b0fd45SJiri Olsa {
10752ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1076c421e80bSKan Liang 
10772ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
107809b0fd45SJiri Olsa 
10792ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
10802ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1081eb853e80SJiri Olsa 
10822ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
108309b0fd45SJiri Olsa 	return 0;
108409b0fd45SJiri Olsa }
108509b0fd45SJiri Olsa 
1086eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1087eb853e80SJiri Olsa {
10887a29c087SNamhyung Kim 	struct record *rec = cb;
10897a29c087SNamhyung Kim 
10907a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
10917a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
10927a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
10937a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
10947a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
10957a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
10967a29c087SNamhyung Kim 			rec->no_buildid = true;
10977a29c087SNamhyung Kim 		else
10987a29c087SNamhyung Kim 			return -1;
10997a29c087SNamhyung Kim 		return 0;
11007a29c087SNamhyung Kim 	}
1101eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
11025a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
1103eb853e80SJiri Olsa 
1104eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
1105eb853e80SJiri Olsa }
1106eb853e80SJiri Olsa 
1107814c8c38SPeter Zijlstra struct clockid_map {
1108814c8c38SPeter Zijlstra 	const char *name;
1109814c8c38SPeter Zijlstra 	int clockid;
1110814c8c38SPeter Zijlstra };
1111814c8c38SPeter Zijlstra 
1112814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1113814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1114814c8c38SPeter Zijlstra 
1115814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1116814c8c38SPeter Zijlstra 
1117814c8c38SPeter Zijlstra 
1118814c8c38SPeter Zijlstra /*
1119814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1120814c8c38SPeter Zijlstra  */
1121814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1122814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1123814c8c38SPeter Zijlstra #endif
1124814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1125814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1126814c8c38SPeter Zijlstra #endif
1127814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1128814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1129814c8c38SPeter Zijlstra #endif
1130814c8c38SPeter Zijlstra 
1131814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1132814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1133814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1134814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1135814c8c38SPeter Zijlstra 
1136814c8c38SPeter Zijlstra 	/* available for some events */
1137814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1138814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1139814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1140814c8c38SPeter Zijlstra 
1141814c8c38SPeter Zijlstra 	/* available for the lazy */
1142814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1143814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1144814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1145814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1146814c8c38SPeter Zijlstra 
1147814c8c38SPeter Zijlstra 	CLOCKID_END,
1148814c8c38SPeter Zijlstra };
1149814c8c38SPeter Zijlstra 
1150814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1151814c8c38SPeter Zijlstra {
1152814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1153814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1154814c8c38SPeter Zijlstra 	const char *ostr = str;
1155814c8c38SPeter Zijlstra 
1156814c8c38SPeter Zijlstra 	if (unset) {
1157814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1158814c8c38SPeter Zijlstra 		return 0;
1159814c8c38SPeter Zijlstra 	}
1160814c8c38SPeter Zijlstra 
1161814c8c38SPeter Zijlstra 	/* no arg passed */
1162814c8c38SPeter Zijlstra 	if (!str)
1163814c8c38SPeter Zijlstra 		return 0;
1164814c8c38SPeter Zijlstra 
1165814c8c38SPeter Zijlstra 	/* no setting it twice */
1166814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1167814c8c38SPeter Zijlstra 		return -1;
1168814c8c38SPeter Zijlstra 
1169814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1170814c8c38SPeter Zijlstra 
1171814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1172814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1173814c8c38SPeter Zijlstra 		return 0;
1174814c8c38SPeter Zijlstra 
1175814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1176814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1177814c8c38SPeter Zijlstra 		str += 6;
1178814c8c38SPeter Zijlstra 
1179814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1180814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1181814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1182814c8c38SPeter Zijlstra 			return 0;
1183814c8c38SPeter Zijlstra 		}
1184814c8c38SPeter Zijlstra 	}
1185814c8c38SPeter Zijlstra 
1186814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1187814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1188814c8c38SPeter Zijlstra 	return -1;
1189814c8c38SPeter Zijlstra }
1190814c8c38SPeter Zijlstra 
1191e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1192e9db1310SAdrian Hunter 				    const char *str,
1193e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1194e9db1310SAdrian Hunter {
1195e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1196e9db1310SAdrian Hunter 	char *s, *p;
1197e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1198e9db1310SAdrian Hunter 	int ret;
1199e9db1310SAdrian Hunter 
1200e9db1310SAdrian Hunter 	if (!str)
1201e9db1310SAdrian Hunter 		return -EINVAL;
1202e9db1310SAdrian Hunter 
1203e9db1310SAdrian Hunter 	s = strdup(str);
1204e9db1310SAdrian Hunter 	if (!s)
1205e9db1310SAdrian Hunter 		return -ENOMEM;
1206e9db1310SAdrian Hunter 
1207e9db1310SAdrian Hunter 	p = strchr(s, ',');
1208e9db1310SAdrian Hunter 	if (p)
1209e9db1310SAdrian Hunter 		*p = '\0';
1210e9db1310SAdrian Hunter 
1211e9db1310SAdrian Hunter 	if (*s) {
1212e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1213e9db1310SAdrian Hunter 		if (ret)
1214e9db1310SAdrian Hunter 			goto out_free;
1215e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1216e9db1310SAdrian Hunter 	}
1217e9db1310SAdrian Hunter 
1218e9db1310SAdrian Hunter 	if (!p) {
1219e9db1310SAdrian Hunter 		ret = 0;
1220e9db1310SAdrian Hunter 		goto out_free;
1221e9db1310SAdrian Hunter 	}
1222e9db1310SAdrian Hunter 
1223e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1224e9db1310SAdrian Hunter 	if (ret)
1225e9db1310SAdrian Hunter 		goto out_free;
1226e9db1310SAdrian Hunter 
1227e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1228e9db1310SAdrian Hunter 
1229e9db1310SAdrian Hunter out_free:
1230e9db1310SAdrian Hunter 	free(s);
1231e9db1310SAdrian Hunter 	return ret;
1232e9db1310SAdrian Hunter }
1233e9db1310SAdrian Hunter 
1234e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
123586470930SIngo Molnar 	"perf record [<options>] [<command>]",
123686470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
123786470930SIngo Molnar 	NULL
123886470930SIngo Molnar };
1239e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
124086470930SIngo Molnar 
1241d20deb64SArnaldo Carvalho de Melo /*
12428c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
12438c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1244d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1245d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1246d20deb64SArnaldo Carvalho de Melo  *
1247d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1248d20deb64SArnaldo Carvalho de Melo  *
1249d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1250d20deb64SArnaldo Carvalho de Melo  */
12518c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1252d20deb64SArnaldo Carvalho de Melo 	.opts = {
12538affc2b8SAndi Kleen 		.sample_time	     = true,
1254d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1255d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1256d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1257447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1258d1cb9fceSNamhyung Kim 		.target		     = {
1259d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
12603aa5939dSAdrian Hunter 			.default_per_cpu = true,
1261d1cb9fceSNamhyung Kim 		},
12629d9cad76SKan Liang 		.proc_map_timeout     = 500,
1263d20deb64SArnaldo Carvalho de Melo 	},
1264e3d59112SNamhyung Kim 	.tool = {
1265e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1266e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1267cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1268e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1269e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1270e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1271cca8482cSAdrian Hunter 		.ordered_events	= true,
1272e3d59112SNamhyung Kim 	},
1273d20deb64SArnaldo Carvalho de Melo };
12747865e817SFrederic Weisbecker 
127576a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
127676a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
127761eaa3beSArnaldo Carvalho de Melo 
12780aab2136SWang Nan static bool dry_run;
12790aab2136SWang Nan 
1280d20deb64SArnaldo Carvalho de Melo /*
1281d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1282d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1283b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1284d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1285d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1286d20deb64SArnaldo Carvalho de Melo  */
1287e5b2c207SNamhyung Kim struct option __record_options[] = {
1288d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
128986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1290f120f9d5SJiri Olsa 		     parse_events_option),
1291d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1292c171b552SLi Zefan 		     "event filter", parse_filter),
12934ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
12944ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
12954ba1faa1SWang Nan 			   exclude_perf),
1296bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1297d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1298bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1299d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1300d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
130186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1302509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1303acac03faSKirill Smelkov 		    "collect data without buffering"),
1304d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1305daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1306bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
130786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1308bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1309c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1310d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1311f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
131286470930SIngo Molnar 		    "output file name"),
131369e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
131469e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
13152e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1316d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1317e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1318e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1319e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1320d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
132143bece79SLin Ming 		    "put the counters into a counter group"),
13222ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
132309b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
132409b0fd45SJiri Olsa 			   &record_callchain_opt),
132509b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
132676a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
132709b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1328c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
13293da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1330b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1331d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1332649c48a9SPeter Zijlstra 		    "per thread counts"),
133356100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
13343abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
13353abebc55SAdrian Hunter 			&record.opts.sample_time_set,
13363abebc55SAdrian Hunter 			"Record the sample timestamps"),
133756100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1338d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1339649c48a9SPeter Zijlstra 		    "don't sample"),
1340d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1341d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1342a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1343d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1344d2db9a98SWang Nan 			&record.no_buildid_set,
1345baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1346d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1347023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1348023695d9SStephane Eranian 		     parse_cgroups),
1349a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
13506619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1351bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1352bea03405SNamhyung Kim 		   "user to profile"),
1353a5aabdacSStephane Eranian 
1354a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1355a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1356a5aabdacSStephane Eranian 		     parse_branch_stack),
1357a5aabdacSStephane Eranian 
1358a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1359a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1360bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
136105484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
136205484298SAndi Kleen 		    "sample by weight (on special events only)"),
1363475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1364475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
13653aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
13663aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1367bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1368bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1369bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
137085c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
137185c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1372814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1373814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1374814c8c38SPeter Zijlstra 	parse_clockid),
13752dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
13762dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
13779d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
13789d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1379b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1380b757bb09SAdrian Hunter 		    "Record context switch events"),
138185723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
138285723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
138385723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
138485723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
138585723885SJiri Olsa 			 "Configure all used events to run in user space.",
138685723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
138771dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
138871dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
138971dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
139071dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
13917efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
13927efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
13936156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
13946156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1395ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1396ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
13973c1cb7e3SWang Nan 	OPT_BOOLEAN(0, "switch-output", &record.switch_output,
13983c1cb7e3SWang Nan 		    "Switch output when receive SIGUSR2"),
13990aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
14000aab2136SWang Nan 		    "Parse options then exit"),
140186470930SIngo Molnar 	OPT_END()
140286470930SIngo Molnar };
140386470930SIngo Molnar 
1404e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1405e5b2c207SNamhyung Kim 
14061d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
140786470930SIngo Molnar {
1408ef149c25SAdrian Hunter 	int err;
14098c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
141016ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
141186470930SIngo Molnar 
141248e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
141348e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
141448e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
141548e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
141648e1cab1SWang Nan # undef set_nobuild
141748e1cab1SWang Nan #endif
141848e1cab1SWang Nan 
14197efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
14207efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
14217efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
14227efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
14237efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
14247efe0e03SHe Kuang # else
14257efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
14267efe0e03SHe Kuang # endif
14277efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
14287efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
14297efe0e03SHe Kuang # undef set_nobuild
14307efe0e03SHe Kuang # undef REASON
14317efe0e03SHe Kuang #endif
14327efe0e03SHe Kuang 
14333e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
14343e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1435361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1436361c99a6SArnaldo Carvalho de Melo 
1437eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1438eb853e80SJiri Olsa 
1439bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1440a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1441602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1442bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
144386470930SIngo Molnar 
1444bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1445c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1446c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1447c7118369SNamhyung Kim 
1448023695d9SStephane Eranian 	}
1449b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1450b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1451c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1452c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1453c7118369SNamhyung Kim 		return -EINVAL;
1454b757bb09SAdrian Hunter 	}
1455023695d9SStephane Eranian 
1456eca857abSWang Nan 	if (rec->switch_output)
1457eca857abSWang Nan 		rec->timestamp_filename = true;
1458eca857abSWang Nan 
1459ef149c25SAdrian Hunter 	if (!rec->itr) {
1460ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1461ef149c25SAdrian Hunter 		if (err)
1462ef149c25SAdrian Hunter 			return err;
1463ef149c25SAdrian Hunter 	}
1464ef149c25SAdrian Hunter 
14652dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
14662dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
14672dd6d8a1SAdrian Hunter 	if (err)
14682dd6d8a1SAdrian Hunter 		return err;
14692dd6d8a1SAdrian Hunter 
14700aab2136SWang Nan 	if (dry_run)
14710aab2136SWang Nan 		return 0;
14720aab2136SWang Nan 
1473d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1474d7888573SWang Nan 	if (err) {
1475d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1476d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1477d7888573SWang Nan 			 errbuf);
1478d7888573SWang Nan 		return err;
1479d7888573SWang Nan 	}
1480d7888573SWang Nan 
1481ef149c25SAdrian Hunter 	err = -ENOMEM;
1482ef149c25SAdrian Hunter 
14830a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1484baa2f6ceSArnaldo Carvalho de Melo 
1485ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1486646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1487646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1488ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1489646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1490646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1491646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1492646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1493646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1494ec80fde7SArnaldo Carvalho de Melo 
14950c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
1496a1ac1d3cSStephane Eranian 		disable_buildid_cache();
14970c1d46a8SWang Nan 	} else if (rec->switch_output) {
14980c1d46a8SWang Nan 		/*
14990c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
15000c1d46a8SWang Nan 		 * generation by default to reduce data file switching
15010c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
15020c1d46a8SWang Nan 		 * explicitly using
15030c1d46a8SWang Nan 		 *
15040c1d46a8SWang Nan 		 *  perf record --signal-trigger --no-no-buildid \
15050c1d46a8SWang Nan 		 *              --no-no-buildid-cache
15060c1d46a8SWang Nan 		 *
15070c1d46a8SWang Nan 		 * Following code equals to:
15080c1d46a8SWang Nan 		 *
15090c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
15100c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
15110c1d46a8SWang Nan 		 *         disable_buildid_cache();
15120c1d46a8SWang Nan 		 */
15130c1d46a8SWang Nan 		bool disable = true;
15140c1d46a8SWang Nan 
15150c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
15160c1d46a8SWang Nan 			disable = false;
15170c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
15180c1d46a8SWang Nan 			disable = false;
15190c1d46a8SWang Nan 		if (disable) {
15200c1d46a8SWang Nan 			rec->no_buildid = true;
15210c1d46a8SWang Nan 			rec->no_buildid_cache = true;
15220c1d46a8SWang Nan 			disable_buildid_cache();
15230c1d46a8SWang Nan 		}
15240c1d46a8SWang Nan 	}
1525655000e7SArnaldo Carvalho de Melo 
15263e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
15273e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
152869aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
152969aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1530bbd36e5eSPeter Zijlstra 	}
153186470930SIngo Molnar 
153269e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
153369e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
153469e7e5b0SAdrian Hunter 
1535602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
153616ad2ffbSNamhyung Kim 	if (err) {
1537602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
153816ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
153916ad2ffbSNamhyung Kim 	}
15404bd0f2d2SNamhyung Kim 
1541602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
154216ad2ffbSNamhyung Kim 	if (err) {
154316ad2ffbSNamhyung Kim 		int saved_errno = errno;
154416ad2ffbSNamhyung Kim 
1545602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
15463780f488SNamhyung Kim 		ui__error("%s", errbuf);
154716ad2ffbSNamhyung Kim 
154816ad2ffbSNamhyung Kim 		err = -saved_errno;
15498fa60e1fSNamhyung Kim 		goto out_symbol_exit;
155016ad2ffbSNamhyung Kim 	}
15510d37aa34SArnaldo Carvalho de Melo 
155216ad2ffbSNamhyung Kim 	err = -ENOMEM;
15533e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1554dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
155569aad6f1SArnaldo Carvalho de Melo 
1556ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1557ef149c25SAdrian Hunter 	if (err)
1558ef149c25SAdrian Hunter 		goto out_symbol_exit;
1559ef149c25SAdrian Hunter 
15606156681bSNamhyung Kim 	/*
15616156681bSNamhyung Kim 	 * We take all buildids when the file contains
15626156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
15636156681bSNamhyung Kim 	 * trace because it would take too long.
15646156681bSNamhyung Kim 	 */
15656156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
15666156681bSNamhyung Kim 		rec->buildid_all = true;
15676156681bSNamhyung Kim 
1568b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
156939d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
157003ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
15717e4ff9e3SMike Galbraith 	}
15727e4ff9e3SMike Galbraith 
1573d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1574d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
157545604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1576d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1577ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
157839d17dacSArnaldo Carvalho de Melo 	return err;
157986470930SIngo Molnar }
15802dd6d8a1SAdrian Hunter 
15812dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
15822dd6d8a1SAdrian Hunter {
15835f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
15845f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
15852dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
15865f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
15875f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
15885f9cf599SWang Nan 	}
15893c1cb7e3SWang Nan 
15903c1cb7e3SWang Nan 	if (trigger_is_ready(&switch_output_trigger))
15913c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
15922dd6d8a1SAdrian Hunter }
1593