xref: /openbmc/linux/tools/perf/builtin-record.c (revision ecfd7a9c044e98fc3da8937e652080bc5abe7918)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-record.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin record command: Record the profile of a workload
586470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
686470930SIngo Molnar  * later analysis via perf report.
786470930SIngo Molnar  */
886470930SIngo Molnar #include "builtin.h"
986470930SIngo Molnar 
1086470930SIngo Molnar #include "perf.h"
1186470930SIngo Molnar 
126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1386470930SIngo Molnar #include "util/util.h"
144b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1586470930SIngo Molnar #include "util/parse-events.h"
1686470930SIngo Molnar 
178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
197c6a1c65SPeter Zijlstra #include "util/header.h"
2066e274f3SFrederic Weisbecker #include "util/event.h"
21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
238f28827aSFrederic Weisbecker #include "util/debug.h"
2494c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
27a12b51c4SPaul Mackerras #include "util/cpumap.h"
28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
29f5fc1412SJiri Olsa #include "util/data.h"
30bcc84ec6SStephane Eranian #include "util/perf_regs.h"
31ef149c25SAdrian Hunter #include "util/auxtrace.h"
3246bc29b9SAdrian Hunter #include "util/tsc.h"
33f00898f4SAndi Kleen #include "util/parse-branch-options.h"
34bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3571dc2326SWang Nan #include "util/llvm-utils.h"
368690a2a7SWang Nan #include "util/bpf-loader.h"
37d8871ea7SWang Nan #include "asm/bug.h"
387c6a1c65SPeter Zijlstra 
3986470930SIngo Molnar #include <unistd.h>
4086470930SIngo Molnar #include <sched.h>
41a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
4286470930SIngo Molnar 
4378da39faSBernhard Rosenkraenzer 
448c6f45a7SArnaldo Carvalho de Melo struct record {
4545694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
46b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
47d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
48f5fc1412SJiri Olsa 	struct perf_data_file	file;
49ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
50d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
51d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
52d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
53d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
54d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
55d2db9a98SWang Nan 	bool			no_buildid_set;
56d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
57d2db9a98SWang Nan 	bool			no_buildid_cache_set;
586156681bSNamhyung Kim 	bool			buildid_all;
59*ecfd7a9cSWang Nan 	bool			timestamp_filename;
609f065194SYang Shi 	unsigned long long	samples;
610f82ebc4SArnaldo Carvalho de Melo };
6286470930SIngo Molnar 
638c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
64f5970550SPeter Zijlstra {
65cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
664f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
678d3eca20SDavid Ahern 		return -1;
688d3eca20SDavid Ahern 	}
69f5970550SPeter Zijlstra 
70cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
718d3eca20SDavid Ahern 	return 0;
72f5970550SPeter Zijlstra }
73f5970550SPeter Zijlstra 
7445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
75d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
761d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
771d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
78234fbbf5SArnaldo Carvalho de Melo {
798c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
808c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
81234fbbf5SArnaldo Carvalho de Melo }
82234fbbf5SArnaldo Carvalho de Melo 
83e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
8486470930SIngo Molnar {
85e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
867b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
877b8283b5SDavid Ahern 	u64 old = md->prev;
88918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
8986470930SIngo Molnar 	unsigned long size;
9086470930SIngo Molnar 	void *buf;
918d3eca20SDavid Ahern 	int rc = 0;
9286470930SIngo Molnar 
93dc82009aSArnaldo Carvalho de Melo 	if (old == head)
948d3eca20SDavid Ahern 		return 0;
9586470930SIngo Molnar 
96d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
9786470930SIngo Molnar 
9886470930SIngo Molnar 	size = head - old;
9986470930SIngo Molnar 
10086470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
10186470930SIngo Molnar 		buf = &data[old & md->mask];
10286470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
10386470930SIngo Molnar 		old += size;
10486470930SIngo Molnar 
1058c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
1068d3eca20SDavid Ahern 			rc = -1;
1078d3eca20SDavid Ahern 			goto out;
1088d3eca20SDavid Ahern 		}
10986470930SIngo Molnar 	}
11086470930SIngo Molnar 
11186470930SIngo Molnar 	buf = &data[old & md->mask];
11286470930SIngo Molnar 	size = head - old;
11386470930SIngo Molnar 	old += size;
11486470930SIngo Molnar 
1158c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1168d3eca20SDavid Ahern 		rc = -1;
1178d3eca20SDavid Ahern 		goto out;
1188d3eca20SDavid Ahern 	}
11986470930SIngo Molnar 
12086470930SIngo Molnar 	md->prev = old;
121e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1228d3eca20SDavid Ahern out:
1238d3eca20SDavid Ahern 	return rc;
12486470930SIngo Molnar }
12586470930SIngo Molnar 
1262dd6d8a1SAdrian Hunter static volatile int done;
1272dd6d8a1SAdrian Hunter static volatile int signr = -1;
1282dd6d8a1SAdrian Hunter static volatile int child_finished;
129c0bdc1c4SWang Nan 
130c0bdc1c4SWang Nan static volatile enum {
131c0bdc1c4SWang Nan 	AUXTRACE_SNAPSHOT_OFF = -1,
132c0bdc1c4SWang Nan 	AUXTRACE_SNAPSHOT_DISABLED = 0,
133c0bdc1c4SWang Nan 	AUXTRACE_SNAPSHOT_ENABLED = 1,
134c0bdc1c4SWang Nan } auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_OFF;
135c0bdc1c4SWang Nan 
136c0bdc1c4SWang Nan static inline void
137c0bdc1c4SWang Nan auxtrace_snapshot_on(void)
138c0bdc1c4SWang Nan {
139c0bdc1c4SWang Nan 	auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED;
140c0bdc1c4SWang Nan }
141c0bdc1c4SWang Nan 
142c0bdc1c4SWang Nan static inline void
143c0bdc1c4SWang Nan auxtrace_snapshot_enable(void)
144c0bdc1c4SWang Nan {
145c0bdc1c4SWang Nan 	if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF)
146c0bdc1c4SWang Nan 		return;
147c0bdc1c4SWang Nan 	auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_ENABLED;
148c0bdc1c4SWang Nan }
149c0bdc1c4SWang Nan 
150c0bdc1c4SWang Nan static inline void
151c0bdc1c4SWang Nan auxtrace_snapshot_disable(void)
152c0bdc1c4SWang Nan {
153c0bdc1c4SWang Nan 	if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF)
154c0bdc1c4SWang Nan 		return;
155c0bdc1c4SWang Nan 	auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED;
156c0bdc1c4SWang Nan }
157c0bdc1c4SWang Nan 
158c0bdc1c4SWang Nan static inline bool
159c0bdc1c4SWang Nan auxtrace_snapshot_is_enabled(void)
160c0bdc1c4SWang Nan {
161c0bdc1c4SWang Nan 	if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF)
162c0bdc1c4SWang Nan 		return false;
163c0bdc1c4SWang Nan 	return auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_ENABLED;
164c0bdc1c4SWang Nan }
165c0bdc1c4SWang Nan 
1662dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err;
1672dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1682dd6d8a1SAdrian Hunter 
1692dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1702dd6d8a1SAdrian Hunter {
1712dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1722dd6d8a1SAdrian Hunter 		child_finished = 1;
1732dd6d8a1SAdrian Hunter 	else
1742dd6d8a1SAdrian Hunter 		signr = sig;
1752dd6d8a1SAdrian Hunter 
1762dd6d8a1SAdrian Hunter 	done = 1;
1772dd6d8a1SAdrian Hunter }
1782dd6d8a1SAdrian Hunter 
1792dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1802dd6d8a1SAdrian Hunter {
1812dd6d8a1SAdrian Hunter 	if (signr == -1)
1822dd6d8a1SAdrian Hunter 		return;
1832dd6d8a1SAdrian Hunter 
1842dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1852dd6d8a1SAdrian Hunter 	raise(signr);
1862dd6d8a1SAdrian Hunter }
1872dd6d8a1SAdrian Hunter 
188e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
189e31f0d01SAdrian Hunter 
190ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
191ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
192ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
193ef149c25SAdrian Hunter {
194ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
19599fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
196ef149c25SAdrian Hunter 	size_t padding;
197ef149c25SAdrian Hunter 	u8 pad[8] = {0};
198ef149c25SAdrian Hunter 
19999fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
20099fa2984SAdrian Hunter 		off_t file_offset;
20199fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
20299fa2984SAdrian Hunter 		int err;
20399fa2984SAdrian Hunter 
20499fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
20599fa2984SAdrian Hunter 		if (file_offset == -1)
20699fa2984SAdrian Hunter 			return -1;
20799fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
20899fa2984SAdrian Hunter 						     event, file_offset);
20999fa2984SAdrian Hunter 		if (err)
21099fa2984SAdrian Hunter 			return err;
21199fa2984SAdrian Hunter 	}
21299fa2984SAdrian Hunter 
213ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
214ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
215ef149c25SAdrian Hunter 	if (padding)
216ef149c25SAdrian Hunter 		padding = 8 - padding;
217ef149c25SAdrian Hunter 
218ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
219ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
220ef149c25SAdrian Hunter 	if (len2)
221ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
222ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
223ef149c25SAdrian Hunter 
224ef149c25SAdrian Hunter 	return 0;
225ef149c25SAdrian Hunter }
226ef149c25SAdrian Hunter 
227ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
228ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
229ef149c25SAdrian Hunter {
230ef149c25SAdrian Hunter 	int ret;
231ef149c25SAdrian Hunter 
232ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
233ef149c25SAdrian Hunter 				  record__process_auxtrace);
234ef149c25SAdrian Hunter 	if (ret < 0)
235ef149c25SAdrian Hunter 		return ret;
236ef149c25SAdrian Hunter 
237ef149c25SAdrian Hunter 	if (ret)
238ef149c25SAdrian Hunter 		rec->samples++;
239ef149c25SAdrian Hunter 
240ef149c25SAdrian Hunter 	return 0;
241ef149c25SAdrian Hunter }
242ef149c25SAdrian Hunter 
2432dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2442dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2452dd6d8a1SAdrian Hunter {
2462dd6d8a1SAdrian Hunter 	int ret;
2472dd6d8a1SAdrian Hunter 
2482dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2492dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2502dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2512dd6d8a1SAdrian Hunter 	if (ret < 0)
2522dd6d8a1SAdrian Hunter 		return ret;
2532dd6d8a1SAdrian Hunter 
2542dd6d8a1SAdrian Hunter 	if (ret)
2552dd6d8a1SAdrian Hunter 		rec->samples++;
2562dd6d8a1SAdrian Hunter 
2572dd6d8a1SAdrian Hunter 	return 0;
2582dd6d8a1SAdrian Hunter }
2592dd6d8a1SAdrian Hunter 
2602dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2612dd6d8a1SAdrian Hunter {
2622dd6d8a1SAdrian Hunter 	int i;
2632dd6d8a1SAdrian Hunter 	int rc = 0;
2642dd6d8a1SAdrian Hunter 
2652dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2662dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2672dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2682dd6d8a1SAdrian Hunter 
2692dd6d8a1SAdrian Hunter 		if (!mm->base)
2702dd6d8a1SAdrian Hunter 			continue;
2712dd6d8a1SAdrian Hunter 
2722dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2732dd6d8a1SAdrian Hunter 			rc = -1;
2742dd6d8a1SAdrian Hunter 			goto out;
2752dd6d8a1SAdrian Hunter 		}
2762dd6d8a1SAdrian Hunter 	}
2772dd6d8a1SAdrian Hunter out:
2782dd6d8a1SAdrian Hunter 	return rc;
2792dd6d8a1SAdrian Hunter }
2802dd6d8a1SAdrian Hunter 
2812dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2822dd6d8a1SAdrian Hunter {
2832dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2842dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2852dd6d8a1SAdrian Hunter 		auxtrace_snapshot_err = -1;
2862dd6d8a1SAdrian Hunter 	} else {
2872dd6d8a1SAdrian Hunter 		auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr);
2882dd6d8a1SAdrian Hunter 		if (!auxtrace_snapshot_err)
289c0bdc1c4SWang Nan 			auxtrace_snapshot_enable();
2902dd6d8a1SAdrian Hunter 	}
2912dd6d8a1SAdrian Hunter }
2922dd6d8a1SAdrian Hunter 
293e31f0d01SAdrian Hunter #else
294e31f0d01SAdrian Hunter 
295e31f0d01SAdrian Hunter static inline
296e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
297e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
298e31f0d01SAdrian Hunter {
299e31f0d01SAdrian Hunter 	return 0;
300e31f0d01SAdrian Hunter }
301e31f0d01SAdrian Hunter 
3022dd6d8a1SAdrian Hunter static inline
3032dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
3042dd6d8a1SAdrian Hunter {
3052dd6d8a1SAdrian Hunter }
3062dd6d8a1SAdrian Hunter 
3072dd6d8a1SAdrian Hunter static inline
3082dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
3092dd6d8a1SAdrian Hunter {
3102dd6d8a1SAdrian Hunter 	return 0;
3112dd6d8a1SAdrian Hunter }
3122dd6d8a1SAdrian Hunter 
313e31f0d01SAdrian Hunter #endif
314e31f0d01SAdrian Hunter 
3158c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
316dd7927f4SArnaldo Carvalho de Melo {
31756e52e85SArnaldo Carvalho de Melo 	char msg[512];
3186a4bb04cSJiri Olsa 	struct perf_evsel *pos;
319d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
320d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
321b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
3228d3eca20SDavid Ahern 	int rc = 0;
323dd7927f4SArnaldo Carvalho de Melo 
324e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
325cac21425SJiri Olsa 
3260050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
3273da297a6SIngo Molnar try_again:
328d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
32956e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
3303da297a6SIngo Molnar 				if (verbose)
331c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3323da297a6SIngo Molnar 				goto try_again;
3333da297a6SIngo Molnar 			}
334ca6a4258SDavid Ahern 
33556e52e85SArnaldo Carvalho de Melo 			rc = -errno;
33656e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
33756e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
33856e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3398d3eca20SDavid Ahern 			goto out;
3407c6a1c65SPeter Zijlstra 		}
3417c6a1c65SPeter Zijlstra 	}
3427c6a1c65SPeter Zijlstra 
34323d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
34423d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
34523d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
34635550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3478d3eca20SDavid Ahern 		rc = -1;
3488d3eca20SDavid Ahern 		goto out;
3490a102479SFrederic Weisbecker 	}
3500a102479SFrederic Weisbecker 
351ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3522dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3532dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3548d3eca20SDavid Ahern 		if (errno == EPERM) {
3558d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
35618e60939SNelson Elhage 			       "Consider increasing "
35718e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
35818e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
359ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
360ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3618d3eca20SDavid Ahern 			rc = -errno;
3628d3eca20SDavid Ahern 		} else {
36335550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
36435550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
36595c36561SWang Nan 			if (errno)
3668d3eca20SDavid Ahern 				rc = -errno;
36795c36561SWang Nan 			else
36895c36561SWang Nan 				rc = -EINVAL;
3698d3eca20SDavid Ahern 		}
3708d3eca20SDavid Ahern 		goto out;
37118e60939SNelson Elhage 	}
3720a27d7f9SArnaldo Carvalho de Melo 
373a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3747b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3758d3eca20SDavid Ahern out:
3768d3eca20SDavid Ahern 	return rc;
377a91e5431SArnaldo Carvalho de Melo }
378a91e5431SArnaldo Carvalho de Melo 
379e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
380e3d59112SNamhyung Kim 				union perf_event *event,
381e3d59112SNamhyung Kim 				struct perf_sample *sample,
382e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
383e3d59112SNamhyung Kim 				struct machine *machine)
384e3d59112SNamhyung Kim {
385e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
386e3d59112SNamhyung Kim 
387e3d59112SNamhyung Kim 	rec->samples++;
388e3d59112SNamhyung Kim 
389e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
390e3d59112SNamhyung Kim }
391e3d59112SNamhyung Kim 
3928c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
3936122e4e4SArnaldo Carvalho de Melo {
394f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
395f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
3966122e4e4SArnaldo Carvalho de Melo 
397457ae94aSHe Kuang 	if (file->size == 0)
3989f591fd7SArnaldo Carvalho de Melo 		return 0;
3999f591fd7SArnaldo Carvalho de Melo 
40000dc8657SNamhyung Kim 	/*
40100dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
40200dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
40300dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
40400dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
40500dc8657SNamhyung Kim 	 *
40600dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
40700dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
40800dc8657SNamhyung Kim 	 */
40900dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
41000dc8657SNamhyung Kim 
4116156681bSNamhyung Kim 	/*
4126156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
4136156681bSNamhyung Kim 	 * so no need to process samples.
4146156681bSNamhyung Kim 	 */
4156156681bSNamhyung Kim 	if (rec->buildid_all)
4166156681bSNamhyung Kim 		rec->tool.sample = NULL;
4176156681bSNamhyung Kim 
418b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
4196122e4e4SArnaldo Carvalho de Melo }
4206122e4e4SArnaldo Carvalho de Melo 
4218115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
422a1645ce1SZhang, Yanmin {
423a1645ce1SZhang, Yanmin 	int err;
42445694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
425a1645ce1SZhang, Yanmin 	/*
426a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
427a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
428a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
429a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
430a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
431a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
432a1645ce1SZhang, Yanmin 	 */
43345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
434743eb868SArnaldo Carvalho de Melo 					     machine);
435a1645ce1SZhang, Yanmin 	if (err < 0)
436a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
43723346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
438a1645ce1SZhang, Yanmin 
439a1645ce1SZhang, Yanmin 	/*
440a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
441a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
442a1645ce1SZhang, Yanmin 	 */
44345694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4440ae617beSAdrian Hunter 						 machine);
445a1645ce1SZhang, Yanmin 	if (err < 0)
446a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
44723346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
448a1645ce1SZhang, Yanmin }
449a1645ce1SZhang, Yanmin 
45098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
45198402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
45298402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
45398402807SFrederic Weisbecker };
45498402807SFrederic Weisbecker 
4558c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
45698402807SFrederic Weisbecker {
457dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4580e2e63ddSPeter Zijlstra 	int i;
4598d3eca20SDavid Ahern 	int rc = 0;
46098402807SFrederic Weisbecker 
461d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
462ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
463ef149c25SAdrian Hunter 
4648d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
465e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4668d3eca20SDavid Ahern 				rc = -1;
4678d3eca20SDavid Ahern 				goto out;
4688d3eca20SDavid Ahern 			}
4698d3eca20SDavid Ahern 		}
470ef149c25SAdrian Hunter 
4712dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
472ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
473ef149c25SAdrian Hunter 			rc = -1;
474ef149c25SAdrian Hunter 			goto out;
475ef149c25SAdrian Hunter 		}
47698402807SFrederic Weisbecker 	}
47798402807SFrederic Weisbecker 
478dcabb507SJiri Olsa 	/*
479dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
480dcabb507SJiri Olsa 	 * at least one event.
481dcabb507SJiri Olsa 	 */
482dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
4838c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
4848d3eca20SDavid Ahern 
4858d3eca20SDavid Ahern out:
4868d3eca20SDavid Ahern 	return rc;
48798402807SFrederic Weisbecker }
48898402807SFrederic Weisbecker 
4898c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
49057706abcSDavid Ahern {
49157706abcSDavid Ahern 	struct perf_session *session = rec->session;
49257706abcSDavid Ahern 	int feat;
49357706abcSDavid Ahern 
49457706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
49557706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
49657706abcSDavid Ahern 
49757706abcSDavid Ahern 	if (rec->no_buildid)
49857706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
49957706abcSDavid Ahern 
5003e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
50157706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
50257706abcSDavid Ahern 
50357706abcSDavid Ahern 	if (!rec->opts.branch_stack)
50457706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
505ef149c25SAdrian Hunter 
506ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
507ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
508ffa517adSJiri Olsa 
509ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
51057706abcSDavid Ahern }
51157706abcSDavid Ahern 
512e1ab48baSWang Nan static void
513e1ab48baSWang Nan record__finish_output(struct record *rec)
514e1ab48baSWang Nan {
515e1ab48baSWang Nan 	struct perf_data_file *file = &rec->file;
516e1ab48baSWang Nan 	int fd = perf_data_file__fd(file);
517e1ab48baSWang Nan 
518e1ab48baSWang Nan 	if (file->is_pipe)
519e1ab48baSWang Nan 		return;
520e1ab48baSWang Nan 
521e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
522e1ab48baSWang Nan 	file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
523e1ab48baSWang Nan 
524e1ab48baSWang Nan 	if (!rec->no_buildid) {
525e1ab48baSWang Nan 		process_buildids(rec);
526e1ab48baSWang Nan 
527e1ab48baSWang Nan 		if (rec->buildid_all)
528e1ab48baSWang Nan 			dsos__hit_all(rec->session);
529e1ab48baSWang Nan 	}
530e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
531e1ab48baSWang Nan 
532e1ab48baSWang Nan 	return;
533e1ab48baSWang Nan }
534e1ab48baSWang Nan 
535*ecfd7a9cSWang Nan static int
536*ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
537*ecfd7a9cSWang Nan {
538*ecfd7a9cSWang Nan 	struct perf_data_file *file = &rec->file;
539*ecfd7a9cSWang Nan 	int fd, err;
540*ecfd7a9cSWang Nan 
541*ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
542*ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
543*ecfd7a9cSWang Nan 
544*ecfd7a9cSWang Nan 	rec->samples = 0;
545*ecfd7a9cSWang Nan 	record__finish_output(rec);
546*ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
547*ecfd7a9cSWang Nan 	if (err) {
548*ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
549*ecfd7a9cSWang Nan 		return -EINVAL;
550*ecfd7a9cSWang Nan 	}
551*ecfd7a9cSWang Nan 
552*ecfd7a9cSWang Nan 	fd = perf_data_file__switch(file, timestamp,
553*ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
554*ecfd7a9cSWang Nan 				    at_exit);
555*ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
556*ecfd7a9cSWang Nan 		rec->bytes_written = 0;
557*ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
558*ecfd7a9cSWang Nan 	}
559*ecfd7a9cSWang Nan 
560*ecfd7a9cSWang Nan 	if (!quiet)
561*ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
562*ecfd7a9cSWang Nan 			file->path, timestamp);
563*ecfd7a9cSWang Nan 	return fd;
564*ecfd7a9cSWang Nan }
565*ecfd7a9cSWang Nan 
566f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
567f33cbe72SArnaldo Carvalho de Melo 
568f33cbe72SArnaldo Carvalho de Melo /*
569f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
570f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
571f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
572f33cbe72SArnaldo Carvalho de Melo  */
57345604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
57445604710SNamhyung Kim 					siginfo_t *info,
575f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
576f33cbe72SArnaldo Carvalho de Melo {
577f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
578f33cbe72SArnaldo Carvalho de Melo 	done = 1;
579f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
580f33cbe72SArnaldo Carvalho de Melo }
581f33cbe72SArnaldo Carvalho de Melo 
5822dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
5832dd6d8a1SAdrian Hunter 
58446bc29b9SAdrian Hunter int __weak
58546bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
58646bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
58746bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
58846bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
58946bc29b9SAdrian Hunter {
59046bc29b9SAdrian Hunter 	return 0;
59146bc29b9SAdrian Hunter }
59246bc29b9SAdrian Hunter 
593c45c86ebSWang Nan static int record__synthesize(struct record *rec)
594c45c86ebSWang Nan {
595c45c86ebSWang Nan 	struct perf_session *session = rec->session;
596c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
597c45c86ebSWang Nan 	struct perf_data_file *file = &rec->file;
598c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
599c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
600c45c86ebSWang Nan 	int fd = perf_data_file__fd(file);
601c45c86ebSWang Nan 	int err = 0;
602c45c86ebSWang Nan 
603c45c86ebSWang Nan 	if (file->is_pipe) {
604c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
605c45c86ebSWang Nan 						   process_synthesized_event);
606c45c86ebSWang Nan 		if (err < 0) {
607c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
608c45c86ebSWang Nan 			goto out;
609c45c86ebSWang Nan 		}
610c45c86ebSWang Nan 
611c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
612c45c86ebSWang Nan 			/*
613c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
614c45c86ebSWang Nan 			 * there were no tracepoints so its not really
615c45c86ebSWang Nan 			 * an error, just that we don't need to
616c45c86ebSWang Nan 			 * synthesize anything.  We really have to
617c45c86ebSWang Nan 			 * return this more properly and also
618c45c86ebSWang Nan 			 * propagate errors that now are calling die()
619c45c86ebSWang Nan 			 */
620c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
621c45c86ebSWang Nan 								  process_synthesized_event);
622c45c86ebSWang Nan 			if (err <= 0) {
623c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
624c45c86ebSWang Nan 				goto out;
625c45c86ebSWang Nan 			}
626c45c86ebSWang Nan 			rec->bytes_written += err;
627c45c86ebSWang Nan 		}
628c45c86ebSWang Nan 	}
629c45c86ebSWang Nan 
63046bc29b9SAdrian Hunter 	err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
63146bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
63246bc29b9SAdrian Hunter 	if (err)
63346bc29b9SAdrian Hunter 		goto out;
63446bc29b9SAdrian Hunter 
635c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
636c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
637c45c86ebSWang Nan 					session, process_synthesized_event);
638c45c86ebSWang Nan 		if (err)
639c45c86ebSWang Nan 			goto out;
640c45c86ebSWang Nan 	}
641c45c86ebSWang Nan 
642c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
643c45c86ebSWang Nan 						 machine);
644c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
645c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
646c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
647c45c86ebSWang Nan 
648c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
649c45c86ebSWang Nan 					     machine);
650c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
651c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
652c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
653c45c86ebSWang Nan 
654c45c86ebSWang Nan 	if (perf_guest) {
655c45c86ebSWang Nan 		machines__process_guests(&session->machines,
656c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
657c45c86ebSWang Nan 	}
658c45c86ebSWang Nan 
659c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
660c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
661c45c86ebSWang Nan 					    opts->proc_map_timeout);
662c45c86ebSWang Nan out:
663c45c86ebSWang Nan 	return err;
664c45c86ebSWang Nan }
665c45c86ebSWang Nan 
6668c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
66786470930SIngo Molnar {
66857706abcSDavid Ahern 	int err;
66945604710SNamhyung Kim 	int status = 0;
6708b412664SPeter Zijlstra 	unsigned long waking = 0;
67146be604bSZhang, Yanmin 	const bool forks = argc > 0;
67223346f21SArnaldo Carvalho de Melo 	struct machine *machine;
67345694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
674b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
675f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
676d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
6776dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
67842aa276fSNamhyung Kim 	int fd;
67986470930SIngo Molnar 
680d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
68133e49ea7SAndi Kleen 
68245604710SNamhyung Kim 	atexit(record__sig_exit);
683f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
684f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
685804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
686c0bdc1c4SWang Nan 
687c0bdc1c4SWang Nan 	if (rec->opts.auxtrace_snapshot_mode) {
6882dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
689c0bdc1c4SWang Nan 		auxtrace_snapshot_on();
690c0bdc1c4SWang Nan 	} else {
6912dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
692c0bdc1c4SWang Nan 	}
693f5970550SPeter Zijlstra 
694b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
69594c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
696ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
697a9a70bbcSArnaldo Carvalho de Melo 		return -1;
698a9a70bbcSArnaldo Carvalho de Melo 	}
699a9a70bbcSArnaldo Carvalho de Melo 
70042aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
701d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
702d20deb64SArnaldo Carvalho de Melo 
7038c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
704330aa675SStephane Eranian 
705d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
7063e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
707f5fc1412SJiri Olsa 						    argv, file->is_pipe,
708735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
70935b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
71035b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
71145604710SNamhyung Kim 			status = err;
71235b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
713856e9660SPeter Zijlstra 		}
714856e9660SPeter Zijlstra 	}
715856e9660SPeter Zijlstra 
7168c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
7178d3eca20SDavid Ahern 		err = -1;
71845604710SNamhyung Kim 		goto out_child;
7198d3eca20SDavid Ahern 	}
72086470930SIngo Molnar 
7218690a2a7SWang Nan 	err = bpf__apply_obj_config();
7228690a2a7SWang Nan 	if (err) {
7238690a2a7SWang Nan 		char errbuf[BUFSIZ];
7248690a2a7SWang Nan 
7258690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
7268690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
7278690a2a7SWang Nan 			 errbuf);
7288690a2a7SWang Nan 		goto out_child;
7298690a2a7SWang Nan 	}
7308690a2a7SWang Nan 
731cca8482cSAdrian Hunter 	/*
732cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
733cca8482cSAdrian Hunter 	 * evlist.
734cca8482cSAdrian Hunter 	 */
735cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
736cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
737cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
738cca8482cSAdrian Hunter 	}
739cca8482cSAdrian Hunter 
7403e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
741a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
742a8bb559bSNamhyung Kim 
743f5fc1412SJiri Olsa 	if (file->is_pipe) {
74442aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
745529870e3STom Zanussi 		if (err < 0)
74645604710SNamhyung Kim 			goto out_child;
747563aecb2SJiri Olsa 	} else {
74842aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
749d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
75045604710SNamhyung Kim 			goto out_child;
751d5eed904SArnaldo Carvalho de Melo 	}
7527c6a1c65SPeter Zijlstra 
753d3665498SDavid Ahern 	if (!rec->no_buildid
754e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
755d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
756e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
7578d3eca20SDavid Ahern 		err = -1;
75845604710SNamhyung Kim 		goto out_child;
759e20960c0SRobert Richter 	}
760e20960c0SRobert Richter 
76134ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
762743eb868SArnaldo Carvalho de Melo 
763c45c86ebSWang Nan 	err = record__synthesize(rec);
764c45c86ebSWang Nan 	if (err < 0)
76545604710SNamhyung Kim 		goto out_child;
7668d3eca20SDavid Ahern 
767d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
76886470930SIngo Molnar 		struct sched_param param;
76986470930SIngo Molnar 
770d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
77186470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
7726beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
7738d3eca20SDavid Ahern 			err = -1;
77445604710SNamhyung Kim 			goto out_child;
77586470930SIngo Molnar 		}
77686470930SIngo Molnar 	}
77786470930SIngo Molnar 
778774cb499SJiri Olsa 	/*
779774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
780774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
781774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
782774cb499SJiri Olsa 	 */
7836619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
7843e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
785764e16a3SDavid Ahern 
786856e9660SPeter Zijlstra 	/*
787856e9660SPeter Zijlstra 	 * Let the child rip
788856e9660SPeter Zijlstra 	 */
789e803cf97SNamhyung Kim 	if (forks) {
790e5bed564SNamhyung Kim 		union perf_event *event;
791e5bed564SNamhyung Kim 
792e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
793e5bed564SNamhyung Kim 		if (event == NULL) {
794e5bed564SNamhyung Kim 			err = -ENOMEM;
795e5bed564SNamhyung Kim 			goto out_child;
796e5bed564SNamhyung Kim 		}
797e5bed564SNamhyung Kim 
798e803cf97SNamhyung Kim 		/*
799e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
800e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
801e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
802e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
803e803cf97SNamhyung Kim 		 */
804e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
805e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
806e803cf97SNamhyung Kim 					    process_synthesized_event,
807e803cf97SNamhyung Kim 					    machine);
808e5bed564SNamhyung Kim 		free(event);
809e803cf97SNamhyung Kim 
8103e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
811e803cf97SNamhyung Kim 	}
812856e9660SPeter Zijlstra 
8136619a53eSAndi Kleen 	if (opts->initial_delay) {
8146619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
8156619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
8166619a53eSAndi Kleen 	}
8176619a53eSAndi Kleen 
818c0bdc1c4SWang Nan 	auxtrace_snapshot_enable();
819649c48a9SPeter Zijlstra 	for (;;) {
8209f065194SYang Shi 		unsigned long long hits = rec->samples;
82186470930SIngo Molnar 
8228c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
823c0bdc1c4SWang Nan 			auxtrace_snapshot_disable();
8248d3eca20SDavid Ahern 			err = -1;
82545604710SNamhyung Kim 			goto out_child;
8268d3eca20SDavid Ahern 		}
82786470930SIngo Molnar 
8282dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
8292dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
8302dd6d8a1SAdrian Hunter 			if (!auxtrace_snapshot_err)
8312dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
8322dd6d8a1SAdrian Hunter 			if (auxtrace_snapshot_err) {
8332dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
8342dd6d8a1SAdrian Hunter 				err = -1;
8352dd6d8a1SAdrian Hunter 				goto out_child;
8362dd6d8a1SAdrian Hunter 			}
8372dd6d8a1SAdrian Hunter 		}
8382dd6d8a1SAdrian Hunter 
839d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
8406dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
841649c48a9SPeter Zijlstra 				break;
842f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
843a515114fSJiri Olsa 			/*
844a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
845a515114fSJiri Olsa 			 * number of returned events and interrupt error.
846a515114fSJiri Olsa 			 */
847a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
84845604710SNamhyung Kim 				err = 0;
8498b412664SPeter Zijlstra 			waking++;
8506dcf45efSArnaldo Carvalho de Melo 
8516dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
8526dcf45efSArnaldo Carvalho de Melo 				draining = true;
8538b412664SPeter Zijlstra 		}
8548b412664SPeter Zijlstra 
855774cb499SJiri Olsa 		/*
856774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
857774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
858774cb499SJiri Olsa 		 * disable events in this case.
859774cb499SJiri Olsa 		 */
860602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
861c0bdc1c4SWang Nan 			auxtrace_snapshot_disable();
8623e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
8632711926aSJiri Olsa 			disabled = true;
8642711926aSJiri Olsa 		}
8658b412664SPeter Zijlstra 	}
866c0bdc1c4SWang Nan 	auxtrace_snapshot_disable();
8678b412664SPeter Zijlstra 
868f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
86935550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
870f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
871f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
872f33cbe72SArnaldo Carvalho de Melo 		err = -1;
87345604710SNamhyung Kim 		goto out_child;
874f33cbe72SArnaldo Carvalho de Melo 	}
875f33cbe72SArnaldo Carvalho de Melo 
876e3d59112SNamhyung Kim 	if (!quiet)
8778b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
87886470930SIngo Molnar 
87945604710SNamhyung Kim out_child:
88045604710SNamhyung Kim 	if (forks) {
88145604710SNamhyung Kim 		int exit_status;
88245604710SNamhyung Kim 
88345604710SNamhyung Kim 		if (!child_finished)
88445604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
88545604710SNamhyung Kim 
88645604710SNamhyung Kim 		wait(&exit_status);
88745604710SNamhyung Kim 
88845604710SNamhyung Kim 		if (err < 0)
88945604710SNamhyung Kim 			status = err;
89045604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
89145604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
89245604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
89345604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
89445604710SNamhyung Kim 	} else
89545604710SNamhyung Kim 		status = err;
89645604710SNamhyung Kim 
897e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
898e3d59112SNamhyung Kim 	rec->samples = 0;
899e3d59112SNamhyung Kim 
900*ecfd7a9cSWang Nan 	if (!err) {
901*ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
902e1ab48baSWang Nan 			record__finish_output(rec);
903*ecfd7a9cSWang Nan 		} else {
904*ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
905*ecfd7a9cSWang Nan 			if (fd < 0) {
906*ecfd7a9cSWang Nan 				status = fd;
907*ecfd7a9cSWang Nan 				goto out_delete_session;
908*ecfd7a9cSWang Nan 			}
909*ecfd7a9cSWang Nan 		}
910*ecfd7a9cSWang Nan 	}
91139d17dacSArnaldo Carvalho de Melo 
912e3d59112SNamhyung Kim 	if (!err && !quiet) {
913e3d59112SNamhyung Kim 		char samples[128];
914*ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
915*ecfd7a9cSWang Nan 					".<timestamp>" : "";
916e3d59112SNamhyung Kim 
917ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
918e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
919e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
920e3d59112SNamhyung Kim 		else
921e3d59112SNamhyung Kim 			samples[0] = '\0';
922e3d59112SNamhyung Kim 
923*ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
924e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
925*ecfd7a9cSWang Nan 			file->path, postfix, samples);
926e3d59112SNamhyung Kim 	}
927e3d59112SNamhyung Kim 
92839d17dacSArnaldo Carvalho de Melo out_delete_session:
92939d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
93045604710SNamhyung Kim 	return status;
93186470930SIngo Molnar }
93286470930SIngo Molnar 
93372a128aaSNamhyung Kim static void callchain_debug(void)
93409b0fd45SJiri Olsa {
935aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
936a601fdffSJiri Olsa 
93772a128aaSNamhyung Kim 	pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
93826d33022SJiri Olsa 
93972a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_DWARF)
94009b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
94172a128aaSNamhyung Kim 			 callchain_param.dump_size);
94209b0fd45SJiri Olsa }
94309b0fd45SJiri Olsa 
944c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
94509b0fd45SJiri Olsa 			       const char *arg,
94609b0fd45SJiri Olsa 			       int unset)
94709b0fd45SJiri Olsa {
94809b0fd45SJiri Olsa 	int ret;
949c421e80bSKan Liang 	struct record_opts *record = (struct record_opts *)opt->value;
95009b0fd45SJiri Olsa 
951c421e80bSKan Liang 	record->callgraph_set = true;
95272a128aaSNamhyung Kim 	callchain_param.enabled = !unset;
953eb853e80SJiri Olsa 
95409b0fd45SJiri Olsa 	/* --no-call-graph */
95509b0fd45SJiri Olsa 	if (unset) {
95672a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_NONE;
95709b0fd45SJiri Olsa 		pr_debug("callchain: disabled\n");
95809b0fd45SJiri Olsa 		return 0;
95909b0fd45SJiri Olsa 	}
96009b0fd45SJiri Olsa 
961c3a6a8c4SKan Liang 	ret = parse_callchain_record_opt(arg, &callchain_param);
9625c0cf224SJiri Olsa 	if (!ret) {
9635c0cf224SJiri Olsa 		/* Enable data address sampling for DWARF unwind. */
9645c0cf224SJiri Olsa 		if (callchain_param.record_mode == CALLCHAIN_DWARF)
9655c0cf224SJiri Olsa 			record->sample_address = true;
96672a128aaSNamhyung Kim 		callchain_debug();
9675c0cf224SJiri Olsa 	}
96809b0fd45SJiri Olsa 
96926d33022SJiri Olsa 	return ret;
97026d33022SJiri Olsa }
97126d33022SJiri Olsa 
972c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
97309b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
97409b0fd45SJiri Olsa 			 int unset __maybe_unused)
97509b0fd45SJiri Olsa {
976c421e80bSKan Liang 	struct record_opts *record = (struct record_opts *)opt->value;
977c421e80bSKan Liang 
978c421e80bSKan Liang 	record->callgraph_set = true;
97972a128aaSNamhyung Kim 	callchain_param.enabled = true;
98009b0fd45SJiri Olsa 
98172a128aaSNamhyung Kim 	if (callchain_param.record_mode == CALLCHAIN_NONE)
98272a128aaSNamhyung Kim 		callchain_param.record_mode = CALLCHAIN_FP;
983eb853e80SJiri Olsa 
98472a128aaSNamhyung Kim 	callchain_debug();
98509b0fd45SJiri Olsa 	return 0;
98609b0fd45SJiri Olsa }
98709b0fd45SJiri Olsa 
988eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
989eb853e80SJiri Olsa {
9907a29c087SNamhyung Kim 	struct record *rec = cb;
9917a29c087SNamhyung Kim 
9927a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
9937a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
9947a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
9957a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
9967a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
9977a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
9987a29c087SNamhyung Kim 			rec->no_buildid = true;
9997a29c087SNamhyung Kim 		else
10007a29c087SNamhyung Kim 			return -1;
10017a29c087SNamhyung Kim 		return 0;
10027a29c087SNamhyung Kim 	}
1003eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
10045a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
1005eb853e80SJiri Olsa 
1006eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
1007eb853e80SJiri Olsa }
1008eb853e80SJiri Olsa 
1009814c8c38SPeter Zijlstra struct clockid_map {
1010814c8c38SPeter Zijlstra 	const char *name;
1011814c8c38SPeter Zijlstra 	int clockid;
1012814c8c38SPeter Zijlstra };
1013814c8c38SPeter Zijlstra 
1014814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1015814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1016814c8c38SPeter Zijlstra 
1017814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1018814c8c38SPeter Zijlstra 
1019814c8c38SPeter Zijlstra 
1020814c8c38SPeter Zijlstra /*
1021814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1022814c8c38SPeter Zijlstra  */
1023814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1024814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1025814c8c38SPeter Zijlstra #endif
1026814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1027814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1028814c8c38SPeter Zijlstra #endif
1029814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1030814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1031814c8c38SPeter Zijlstra #endif
1032814c8c38SPeter Zijlstra 
1033814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1034814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1035814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1036814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1037814c8c38SPeter Zijlstra 
1038814c8c38SPeter Zijlstra 	/* available for some events */
1039814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1040814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1041814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1042814c8c38SPeter Zijlstra 
1043814c8c38SPeter Zijlstra 	/* available for the lazy */
1044814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1045814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1046814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1047814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1048814c8c38SPeter Zijlstra 
1049814c8c38SPeter Zijlstra 	CLOCKID_END,
1050814c8c38SPeter Zijlstra };
1051814c8c38SPeter Zijlstra 
1052814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1053814c8c38SPeter Zijlstra {
1054814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1055814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1056814c8c38SPeter Zijlstra 	const char *ostr = str;
1057814c8c38SPeter Zijlstra 
1058814c8c38SPeter Zijlstra 	if (unset) {
1059814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1060814c8c38SPeter Zijlstra 		return 0;
1061814c8c38SPeter Zijlstra 	}
1062814c8c38SPeter Zijlstra 
1063814c8c38SPeter Zijlstra 	/* no arg passed */
1064814c8c38SPeter Zijlstra 	if (!str)
1065814c8c38SPeter Zijlstra 		return 0;
1066814c8c38SPeter Zijlstra 
1067814c8c38SPeter Zijlstra 	/* no setting it twice */
1068814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1069814c8c38SPeter Zijlstra 		return -1;
1070814c8c38SPeter Zijlstra 
1071814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1072814c8c38SPeter Zijlstra 
1073814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1074814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1075814c8c38SPeter Zijlstra 		return 0;
1076814c8c38SPeter Zijlstra 
1077814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1078814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1079814c8c38SPeter Zijlstra 		str += 6;
1080814c8c38SPeter Zijlstra 
1081814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1082814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1083814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1084814c8c38SPeter Zijlstra 			return 0;
1085814c8c38SPeter Zijlstra 		}
1086814c8c38SPeter Zijlstra 	}
1087814c8c38SPeter Zijlstra 
1088814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1089814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1090814c8c38SPeter Zijlstra 	return -1;
1091814c8c38SPeter Zijlstra }
1092814c8c38SPeter Zijlstra 
1093e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1094e9db1310SAdrian Hunter 				    const char *str,
1095e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1096e9db1310SAdrian Hunter {
1097e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1098e9db1310SAdrian Hunter 	char *s, *p;
1099e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1100e9db1310SAdrian Hunter 	int ret;
1101e9db1310SAdrian Hunter 
1102e9db1310SAdrian Hunter 	if (!str)
1103e9db1310SAdrian Hunter 		return -EINVAL;
1104e9db1310SAdrian Hunter 
1105e9db1310SAdrian Hunter 	s = strdup(str);
1106e9db1310SAdrian Hunter 	if (!s)
1107e9db1310SAdrian Hunter 		return -ENOMEM;
1108e9db1310SAdrian Hunter 
1109e9db1310SAdrian Hunter 	p = strchr(s, ',');
1110e9db1310SAdrian Hunter 	if (p)
1111e9db1310SAdrian Hunter 		*p = '\0';
1112e9db1310SAdrian Hunter 
1113e9db1310SAdrian Hunter 	if (*s) {
1114e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1115e9db1310SAdrian Hunter 		if (ret)
1116e9db1310SAdrian Hunter 			goto out_free;
1117e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1118e9db1310SAdrian Hunter 	}
1119e9db1310SAdrian Hunter 
1120e9db1310SAdrian Hunter 	if (!p) {
1121e9db1310SAdrian Hunter 		ret = 0;
1122e9db1310SAdrian Hunter 		goto out_free;
1123e9db1310SAdrian Hunter 	}
1124e9db1310SAdrian Hunter 
1125e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1126e9db1310SAdrian Hunter 	if (ret)
1127e9db1310SAdrian Hunter 		goto out_free;
1128e9db1310SAdrian Hunter 
1129e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1130e9db1310SAdrian Hunter 
1131e9db1310SAdrian Hunter out_free:
1132e9db1310SAdrian Hunter 	free(s);
1133e9db1310SAdrian Hunter 	return ret;
1134e9db1310SAdrian Hunter }
1135e9db1310SAdrian Hunter 
1136e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
113786470930SIngo Molnar 	"perf record [<options>] [<command>]",
113886470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
113986470930SIngo Molnar 	NULL
114086470930SIngo Molnar };
1141e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
114286470930SIngo Molnar 
1143d20deb64SArnaldo Carvalho de Melo /*
11448c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
11458c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1146d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1147d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1148d20deb64SArnaldo Carvalho de Melo  *
1149d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1150d20deb64SArnaldo Carvalho de Melo  *
1151d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1152d20deb64SArnaldo Carvalho de Melo  */
11538c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1154d20deb64SArnaldo Carvalho de Melo 	.opts = {
11558affc2b8SAndi Kleen 		.sample_time	     = true,
1156d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1157d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1158d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1159447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1160d1cb9fceSNamhyung Kim 		.target		     = {
1161d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
11623aa5939dSAdrian Hunter 			.default_per_cpu = true,
1163d1cb9fceSNamhyung Kim 		},
11649d9cad76SKan Liang 		.proc_map_timeout     = 500,
1165d20deb64SArnaldo Carvalho de Melo 	},
1166e3d59112SNamhyung Kim 	.tool = {
1167e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1168e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1169cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1170e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1171e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1172e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1173cca8482cSAdrian Hunter 		.ordered_events	= true,
1174e3d59112SNamhyung Kim 	},
1175d20deb64SArnaldo Carvalho de Melo };
11767865e817SFrederic Weisbecker 
117776a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
117876a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
117961eaa3beSArnaldo Carvalho de Melo 
1180d20deb64SArnaldo Carvalho de Melo /*
1181d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1182d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1183b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1184d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1185d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1186d20deb64SArnaldo Carvalho de Melo  */
1187e5b2c207SNamhyung Kim struct option __record_options[] = {
1188d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
118986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1190f120f9d5SJiri Olsa 		     parse_events_option),
1191d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1192c171b552SLi Zefan 		     "event filter", parse_filter),
11934ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
11944ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
11954ba1faa1SWang Nan 			   exclude_perf),
1196bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1197d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1198bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1199d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1200d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
120186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1202509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1203acac03faSKirill Smelkov 		    "collect data without buffering"),
1204d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1205daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1206bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
120786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1208bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1209c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1210d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1211f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
121286470930SIngo Molnar 		    "output file name"),
121369e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
121469e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
12152e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1216d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1217e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1218e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1219e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1220d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
122143bece79SLin Ming 		    "put the counters into a counter group"),
122209b0fd45SJiri Olsa 	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
122309b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
122409b0fd45SJiri Olsa 			   &record_callchain_opt),
122509b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
122676a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
122709b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1228c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
12293da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1230b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1231d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1232649c48a9SPeter Zijlstra 		    "per thread counts"),
123356100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
12343abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
12353abebc55SAdrian Hunter 			&record.opts.sample_time_set,
12363abebc55SAdrian Hunter 			"Record the sample timestamps"),
123756100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1238d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1239649c48a9SPeter Zijlstra 		    "don't sample"),
1240d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1241d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1242a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1243d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1244d2db9a98SWang Nan 			&record.no_buildid_set,
1245baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1246d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1247023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1248023695d9SStephane Eranian 		     parse_cgroups),
1249a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
12506619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1251bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1252bea03405SNamhyung Kim 		   "user to profile"),
1253a5aabdacSStephane Eranian 
1254a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1255a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1256a5aabdacSStephane Eranian 		     parse_branch_stack),
1257a5aabdacSStephane Eranian 
1258a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1259a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1260bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
126105484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
126205484298SAndi Kleen 		    "sample by weight (on special events only)"),
1263475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1264475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
12653aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
12663aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1267bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1268bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1269bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
127085c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
127185c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1272814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1273814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1274814c8c38SPeter Zijlstra 	parse_clockid),
12752dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
12762dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
12779d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
12789d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1279b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1280b757bb09SAdrian Hunter 		    "Record context switch events"),
128185723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
128285723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
128385723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
128485723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
128585723885SJiri Olsa 			 "Configure all used events to run in user space.",
128685723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
128771dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
128871dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
128971dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
129071dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
12917efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
12927efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
12936156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
12946156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1295*ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1296*ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
129786470930SIngo Molnar 	OPT_END()
129886470930SIngo Molnar };
129986470930SIngo Molnar 
1300e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1301e5b2c207SNamhyung Kim 
13021d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
130386470930SIngo Molnar {
1304ef149c25SAdrian Hunter 	int err;
13058c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
130616ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
130786470930SIngo Molnar 
130848e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
130948e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
131048e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
131148e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
131248e1cab1SWang Nan # undef set_nobuild
131348e1cab1SWang Nan #endif
131448e1cab1SWang Nan 
13157efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
13167efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
13177efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
13187efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
13197efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
13207efe0e03SHe Kuang # else
13217efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
13227efe0e03SHe Kuang # endif
13237efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
13247efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
13257efe0e03SHe Kuang # undef set_nobuild
13267efe0e03SHe Kuang # undef REASON
13277efe0e03SHe Kuang #endif
13287efe0e03SHe Kuang 
13293e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
13303e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1331361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1332361c99a6SArnaldo Carvalho de Melo 
1333eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1334eb853e80SJiri Olsa 
1335bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1336a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1337602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1338bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
133986470930SIngo Molnar 
1340bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1341c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1342c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1343c7118369SNamhyung Kim 
1344023695d9SStephane Eranian 	}
1345b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1346b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1347c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1348c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1349c7118369SNamhyung Kim 		return -EINVAL;
1350b757bb09SAdrian Hunter 	}
1351023695d9SStephane Eranian 
1352ef149c25SAdrian Hunter 	if (!rec->itr) {
1353ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1354ef149c25SAdrian Hunter 		if (err)
1355ef149c25SAdrian Hunter 			return err;
1356ef149c25SAdrian Hunter 	}
1357ef149c25SAdrian Hunter 
13582dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
13592dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
13602dd6d8a1SAdrian Hunter 	if (err)
13612dd6d8a1SAdrian Hunter 		return err;
13622dd6d8a1SAdrian Hunter 
1363d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1364d7888573SWang Nan 	if (err) {
1365d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1366d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1367d7888573SWang Nan 			 errbuf);
1368d7888573SWang Nan 		return err;
1369d7888573SWang Nan 	}
1370d7888573SWang Nan 
1371ef149c25SAdrian Hunter 	err = -ENOMEM;
1372ef149c25SAdrian Hunter 
13730a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1374baa2f6ceSArnaldo Carvalho de Melo 
1375ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1376646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1377646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1378ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1379646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1380646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1381646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1382646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1383646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1384ec80fde7SArnaldo Carvalho de Melo 
1385d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1386a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1387655000e7SArnaldo Carvalho de Melo 
13883e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
13893e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
139069aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
139169aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1392bbd36e5eSPeter Zijlstra 	}
139386470930SIngo Molnar 
139469e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
139569e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
139669e7e5b0SAdrian Hunter 
1397602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
139816ad2ffbSNamhyung Kim 	if (err) {
1399602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
140016ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
140116ad2ffbSNamhyung Kim 	}
14024bd0f2d2SNamhyung Kim 
1403602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
140416ad2ffbSNamhyung Kim 	if (err) {
140516ad2ffbSNamhyung Kim 		int saved_errno = errno;
140616ad2ffbSNamhyung Kim 
1407602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
14083780f488SNamhyung Kim 		ui__error("%s", errbuf);
140916ad2ffbSNamhyung Kim 
141016ad2ffbSNamhyung Kim 		err = -saved_errno;
14118fa60e1fSNamhyung Kim 		goto out_symbol_exit;
141216ad2ffbSNamhyung Kim 	}
14130d37aa34SArnaldo Carvalho de Melo 
141416ad2ffbSNamhyung Kim 	err = -ENOMEM;
14153e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1416dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
141769aad6f1SArnaldo Carvalho de Melo 
1418ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1419ef149c25SAdrian Hunter 	if (err)
1420ef149c25SAdrian Hunter 		goto out_symbol_exit;
1421ef149c25SAdrian Hunter 
14226156681bSNamhyung Kim 	/*
14236156681bSNamhyung Kim 	 * We take all buildids when the file contains
14246156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
14256156681bSNamhyung Kim 	 * trace because it would take too long.
14266156681bSNamhyung Kim 	 */
14276156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
14286156681bSNamhyung Kim 		rec->buildid_all = true;
14296156681bSNamhyung Kim 
1430b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
143139d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
143203ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
14337e4ff9e3SMike Galbraith 	}
14347e4ff9e3SMike Galbraith 
1435d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1436d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
143745604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1438d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1439ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
144039d17dacSArnaldo Carvalho de Melo 	return err;
144186470930SIngo Molnar }
14422dd6d8a1SAdrian Hunter 
14432dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
14442dd6d8a1SAdrian Hunter {
1445c0bdc1c4SWang Nan 	if (!auxtrace_snapshot_is_enabled())
14462dd6d8a1SAdrian Hunter 		return;
1447c0bdc1c4SWang Nan 	auxtrace_snapshot_disable();
14482dd6d8a1SAdrian Hunter 	auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr);
14492dd6d8a1SAdrian Hunter 	auxtrace_record__snapshot_started = 1;
14502dd6d8a1SAdrian Hunter }
1451