xref: /openbmc/linux/tools/perf/builtin-record.c (revision 0c1d46a8796e8309f1ca693e5cad6f318e4b8159)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-record.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin record command: Record the profile of a workload
586470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
686470930SIngo Molnar  * later analysis via perf report.
786470930SIngo Molnar  */
886470930SIngo Molnar #include "builtin.h"
986470930SIngo Molnar 
1086470930SIngo Molnar #include "perf.h"
1186470930SIngo Molnar 
126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1386470930SIngo Molnar #include "util/util.h"
144b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1586470930SIngo Molnar #include "util/parse-events.h"
1686470930SIngo Molnar 
178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
197c6a1c65SPeter Zijlstra #include "util/header.h"
2066e274f3SFrederic Weisbecker #include "util/event.h"
21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
238f28827aSFrederic Weisbecker #include "util/debug.h"
2494c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
27a12b51c4SPaul Mackerras #include "util/cpumap.h"
28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
29f5fc1412SJiri Olsa #include "util/data.h"
30bcc84ec6SStephane Eranian #include "util/perf_regs.h"
31ef149c25SAdrian Hunter #include "util/auxtrace.h"
3246bc29b9SAdrian Hunter #include "util/tsc.h"
33f00898f4SAndi Kleen #include "util/parse-branch-options.h"
34bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3571dc2326SWang Nan #include "util/llvm-utils.h"
368690a2a7SWang Nan #include "util/bpf-loader.h"
375f9cf599SWang Nan #include "util/trigger.h"
38d8871ea7SWang Nan #include "asm/bug.h"
397c6a1c65SPeter Zijlstra 
4086470930SIngo Molnar #include <unistd.h>
4186470930SIngo Molnar #include <sched.h>
42a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
4386470930SIngo Molnar 
4478da39faSBernhard Rosenkraenzer 
458c6f45a7SArnaldo Carvalho de Melo struct record {
4645694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
47b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
48d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
49f5fc1412SJiri Olsa 	struct perf_data_file	file;
50ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
51d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
52d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
53d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
54d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
55d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
56d2db9a98SWang Nan 	bool			no_buildid_set;
57d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
58d2db9a98SWang Nan 	bool			no_buildid_cache_set;
596156681bSNamhyung Kim 	bool			buildid_all;
60ecfd7a9cSWang Nan 	bool			timestamp_filename;
613c1cb7e3SWang Nan 	bool			switch_output;
629f065194SYang Shi 	unsigned long long	samples;
630f82ebc4SArnaldo Carvalho de Melo };
6486470930SIngo Molnar 
658c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
66f5970550SPeter Zijlstra {
67cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
684f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
698d3eca20SDavid Ahern 		return -1;
708d3eca20SDavid Ahern 	}
71f5970550SPeter Zijlstra 
72cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
738d3eca20SDavid Ahern 	return 0;
74f5970550SPeter Zijlstra }
75f5970550SPeter Zijlstra 
7645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
77d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
781d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
791d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
80234fbbf5SArnaldo Carvalho de Melo {
818c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
828c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
83234fbbf5SArnaldo Carvalho de Melo }
84234fbbf5SArnaldo Carvalho de Melo 
85e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
8686470930SIngo Molnar {
87e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
887b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
897b8283b5SDavid Ahern 	u64 old = md->prev;
90918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
9186470930SIngo Molnar 	unsigned long size;
9286470930SIngo Molnar 	void *buf;
938d3eca20SDavid Ahern 	int rc = 0;
9486470930SIngo Molnar 
95dc82009aSArnaldo Carvalho de Melo 	if (old == head)
968d3eca20SDavid Ahern 		return 0;
9786470930SIngo Molnar 
98d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
9986470930SIngo Molnar 
10086470930SIngo Molnar 	size = head - old;
10186470930SIngo Molnar 
10286470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
10386470930SIngo Molnar 		buf = &data[old & md->mask];
10486470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
10586470930SIngo Molnar 		old += size;
10686470930SIngo Molnar 
1078c6f45a7SArnaldo Carvalho de Melo 		if (record__write(rec, buf, size) < 0) {
1088d3eca20SDavid Ahern 			rc = -1;
1098d3eca20SDavid Ahern 			goto out;
1108d3eca20SDavid Ahern 		}
11186470930SIngo Molnar 	}
11286470930SIngo Molnar 
11386470930SIngo Molnar 	buf = &data[old & md->mask];
11486470930SIngo Molnar 	size = head - old;
11586470930SIngo Molnar 	old += size;
11686470930SIngo Molnar 
1178c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1188d3eca20SDavid Ahern 		rc = -1;
1198d3eca20SDavid Ahern 		goto out;
1208d3eca20SDavid Ahern 	}
12186470930SIngo Molnar 
12286470930SIngo Molnar 	md->prev = old;
123e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1248d3eca20SDavid Ahern out:
1258d3eca20SDavid Ahern 	return rc;
12686470930SIngo Molnar }
12786470930SIngo Molnar 
1282dd6d8a1SAdrian Hunter static volatile int done;
1292dd6d8a1SAdrian Hunter static volatile int signr = -1;
1302dd6d8a1SAdrian Hunter static volatile int child_finished;
131c0bdc1c4SWang Nan 
1322dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1335f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
1343c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger);
1352dd6d8a1SAdrian Hunter 
1362dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1372dd6d8a1SAdrian Hunter {
1382dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1392dd6d8a1SAdrian Hunter 		child_finished = 1;
1402dd6d8a1SAdrian Hunter 	else
1412dd6d8a1SAdrian Hunter 		signr = sig;
1422dd6d8a1SAdrian Hunter 
1432dd6d8a1SAdrian Hunter 	done = 1;
1442dd6d8a1SAdrian Hunter }
1452dd6d8a1SAdrian Hunter 
1462dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1472dd6d8a1SAdrian Hunter {
1482dd6d8a1SAdrian Hunter 	if (signr == -1)
1492dd6d8a1SAdrian Hunter 		return;
1502dd6d8a1SAdrian Hunter 
1512dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1522dd6d8a1SAdrian Hunter 	raise(signr);
1532dd6d8a1SAdrian Hunter }
1542dd6d8a1SAdrian Hunter 
155e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
156e31f0d01SAdrian Hunter 
157ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
158ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
159ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
160ef149c25SAdrian Hunter {
161ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
16299fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
163ef149c25SAdrian Hunter 	size_t padding;
164ef149c25SAdrian Hunter 	u8 pad[8] = {0};
165ef149c25SAdrian Hunter 
16699fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
16799fa2984SAdrian Hunter 		off_t file_offset;
16899fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
16999fa2984SAdrian Hunter 		int err;
17099fa2984SAdrian Hunter 
17199fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
17299fa2984SAdrian Hunter 		if (file_offset == -1)
17399fa2984SAdrian Hunter 			return -1;
17499fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
17599fa2984SAdrian Hunter 						     event, file_offset);
17699fa2984SAdrian Hunter 		if (err)
17799fa2984SAdrian Hunter 			return err;
17899fa2984SAdrian Hunter 	}
17999fa2984SAdrian Hunter 
180ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
181ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
182ef149c25SAdrian Hunter 	if (padding)
183ef149c25SAdrian Hunter 		padding = 8 - padding;
184ef149c25SAdrian Hunter 
185ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
186ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
187ef149c25SAdrian Hunter 	if (len2)
188ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
189ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
190ef149c25SAdrian Hunter 
191ef149c25SAdrian Hunter 	return 0;
192ef149c25SAdrian Hunter }
193ef149c25SAdrian Hunter 
194ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
195ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
196ef149c25SAdrian Hunter {
197ef149c25SAdrian Hunter 	int ret;
198ef149c25SAdrian Hunter 
199ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
200ef149c25SAdrian Hunter 				  record__process_auxtrace);
201ef149c25SAdrian Hunter 	if (ret < 0)
202ef149c25SAdrian Hunter 		return ret;
203ef149c25SAdrian Hunter 
204ef149c25SAdrian Hunter 	if (ret)
205ef149c25SAdrian Hunter 		rec->samples++;
206ef149c25SAdrian Hunter 
207ef149c25SAdrian Hunter 	return 0;
208ef149c25SAdrian Hunter }
209ef149c25SAdrian Hunter 
2102dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2112dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2122dd6d8a1SAdrian Hunter {
2132dd6d8a1SAdrian Hunter 	int ret;
2142dd6d8a1SAdrian Hunter 
2152dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2162dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2172dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2182dd6d8a1SAdrian Hunter 	if (ret < 0)
2192dd6d8a1SAdrian Hunter 		return ret;
2202dd6d8a1SAdrian Hunter 
2212dd6d8a1SAdrian Hunter 	if (ret)
2222dd6d8a1SAdrian Hunter 		rec->samples++;
2232dd6d8a1SAdrian Hunter 
2242dd6d8a1SAdrian Hunter 	return 0;
2252dd6d8a1SAdrian Hunter }
2262dd6d8a1SAdrian Hunter 
2272dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2282dd6d8a1SAdrian Hunter {
2292dd6d8a1SAdrian Hunter 	int i;
2302dd6d8a1SAdrian Hunter 	int rc = 0;
2312dd6d8a1SAdrian Hunter 
2322dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2332dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2342dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2352dd6d8a1SAdrian Hunter 
2362dd6d8a1SAdrian Hunter 		if (!mm->base)
2372dd6d8a1SAdrian Hunter 			continue;
2382dd6d8a1SAdrian Hunter 
2392dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2402dd6d8a1SAdrian Hunter 			rc = -1;
2412dd6d8a1SAdrian Hunter 			goto out;
2422dd6d8a1SAdrian Hunter 		}
2432dd6d8a1SAdrian Hunter 	}
2442dd6d8a1SAdrian Hunter out:
2452dd6d8a1SAdrian Hunter 	return rc;
2462dd6d8a1SAdrian Hunter }
2472dd6d8a1SAdrian Hunter 
2482dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2492dd6d8a1SAdrian Hunter {
2502dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2512dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2525f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
2532dd6d8a1SAdrian Hunter 	} else {
2545f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
2555f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
2565f9cf599SWang Nan 		else
2575f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
2582dd6d8a1SAdrian Hunter 	}
2592dd6d8a1SAdrian Hunter }
2602dd6d8a1SAdrian Hunter 
261e31f0d01SAdrian Hunter #else
262e31f0d01SAdrian Hunter 
263e31f0d01SAdrian Hunter static inline
264e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
265e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
266e31f0d01SAdrian Hunter {
267e31f0d01SAdrian Hunter 	return 0;
268e31f0d01SAdrian Hunter }
269e31f0d01SAdrian Hunter 
2702dd6d8a1SAdrian Hunter static inline
2712dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2722dd6d8a1SAdrian Hunter {
2732dd6d8a1SAdrian Hunter }
2742dd6d8a1SAdrian Hunter 
2752dd6d8a1SAdrian Hunter static inline
2762dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2772dd6d8a1SAdrian Hunter {
2782dd6d8a1SAdrian Hunter 	return 0;
2792dd6d8a1SAdrian Hunter }
2802dd6d8a1SAdrian Hunter 
281e31f0d01SAdrian Hunter #endif
282e31f0d01SAdrian Hunter 
2838c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
284dd7927f4SArnaldo Carvalho de Melo {
28556e52e85SArnaldo Carvalho de Melo 	char msg[512];
2866a4bb04cSJiri Olsa 	struct perf_evsel *pos;
287d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
288d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
289b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
2908d3eca20SDavid Ahern 	int rc = 0;
291dd7927f4SArnaldo Carvalho de Melo 
292e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
293cac21425SJiri Olsa 
2940050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
2953da297a6SIngo Molnar try_again:
296d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
29756e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
2983da297a6SIngo Molnar 				if (verbose)
299c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3003da297a6SIngo Molnar 				goto try_again;
3013da297a6SIngo Molnar 			}
302ca6a4258SDavid Ahern 
30356e52e85SArnaldo Carvalho de Melo 			rc = -errno;
30456e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
30556e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
30656e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3078d3eca20SDavid Ahern 			goto out;
3087c6a1c65SPeter Zijlstra 		}
3097c6a1c65SPeter Zijlstra 	}
3107c6a1c65SPeter Zijlstra 
31123d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
31223d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
31323d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
31435550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3158d3eca20SDavid Ahern 		rc = -1;
3168d3eca20SDavid Ahern 		goto out;
3170a102479SFrederic Weisbecker 	}
3180a102479SFrederic Weisbecker 
319ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3202dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3212dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3228d3eca20SDavid Ahern 		if (errno == EPERM) {
3238d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
32418e60939SNelson Elhage 			       "Consider increasing "
32518e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
32618e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
327ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
328ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3298d3eca20SDavid Ahern 			rc = -errno;
3308d3eca20SDavid Ahern 		} else {
33135550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
33235550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
33395c36561SWang Nan 			if (errno)
3348d3eca20SDavid Ahern 				rc = -errno;
33595c36561SWang Nan 			else
33695c36561SWang Nan 				rc = -EINVAL;
3378d3eca20SDavid Ahern 		}
3388d3eca20SDavid Ahern 		goto out;
33918e60939SNelson Elhage 	}
3400a27d7f9SArnaldo Carvalho de Melo 
341a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3427b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3438d3eca20SDavid Ahern out:
3448d3eca20SDavid Ahern 	return rc;
345a91e5431SArnaldo Carvalho de Melo }
346a91e5431SArnaldo Carvalho de Melo 
347e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
348e3d59112SNamhyung Kim 				union perf_event *event,
349e3d59112SNamhyung Kim 				struct perf_sample *sample,
350e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
351e3d59112SNamhyung Kim 				struct machine *machine)
352e3d59112SNamhyung Kim {
353e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
354e3d59112SNamhyung Kim 
355e3d59112SNamhyung Kim 	rec->samples++;
356e3d59112SNamhyung Kim 
357e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
358e3d59112SNamhyung Kim }
359e3d59112SNamhyung Kim 
3608c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
3616122e4e4SArnaldo Carvalho de Melo {
362f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
363f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
3646122e4e4SArnaldo Carvalho de Melo 
365457ae94aSHe Kuang 	if (file->size == 0)
3669f591fd7SArnaldo Carvalho de Melo 		return 0;
3679f591fd7SArnaldo Carvalho de Melo 
36800dc8657SNamhyung Kim 	/*
36900dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
37000dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
37100dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
37200dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
37300dc8657SNamhyung Kim 	 *
37400dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
37500dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
37600dc8657SNamhyung Kim 	 */
37700dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
37800dc8657SNamhyung Kim 
3796156681bSNamhyung Kim 	/*
3806156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
3816156681bSNamhyung Kim 	 * so no need to process samples.
3826156681bSNamhyung Kim 	 */
3836156681bSNamhyung Kim 	if (rec->buildid_all)
3846156681bSNamhyung Kim 		rec->tool.sample = NULL;
3856156681bSNamhyung Kim 
386b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
3876122e4e4SArnaldo Carvalho de Melo }
3886122e4e4SArnaldo Carvalho de Melo 
3898115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
390a1645ce1SZhang, Yanmin {
391a1645ce1SZhang, Yanmin 	int err;
39245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
393a1645ce1SZhang, Yanmin 	/*
394a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
395a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
396a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
397a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
398a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
399a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
400a1645ce1SZhang, Yanmin 	 */
40145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
402743eb868SArnaldo Carvalho de Melo 					     machine);
403a1645ce1SZhang, Yanmin 	if (err < 0)
404a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
40523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
406a1645ce1SZhang, Yanmin 
407a1645ce1SZhang, Yanmin 	/*
408a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
409a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
410a1645ce1SZhang, Yanmin 	 */
41145694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4120ae617beSAdrian Hunter 						 machine);
413a1645ce1SZhang, Yanmin 	if (err < 0)
414a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
416a1645ce1SZhang, Yanmin }
417a1645ce1SZhang, Yanmin 
41898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
41998402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
42098402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
42198402807SFrederic Weisbecker };
42298402807SFrederic Weisbecker 
4238c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
42498402807SFrederic Weisbecker {
425dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4260e2e63ddSPeter Zijlstra 	int i;
4278d3eca20SDavid Ahern 	int rc = 0;
42898402807SFrederic Weisbecker 
429d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
430ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
431ef149c25SAdrian Hunter 
4328d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
433e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4348d3eca20SDavid Ahern 				rc = -1;
4358d3eca20SDavid Ahern 				goto out;
4368d3eca20SDavid Ahern 			}
4378d3eca20SDavid Ahern 		}
438ef149c25SAdrian Hunter 
4392dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
440ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
441ef149c25SAdrian Hunter 			rc = -1;
442ef149c25SAdrian Hunter 			goto out;
443ef149c25SAdrian Hunter 		}
44498402807SFrederic Weisbecker 	}
44598402807SFrederic Weisbecker 
446dcabb507SJiri Olsa 	/*
447dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
448dcabb507SJiri Olsa 	 * at least one event.
449dcabb507SJiri Olsa 	 */
450dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
4518c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
4528d3eca20SDavid Ahern 
4538d3eca20SDavid Ahern out:
4548d3eca20SDavid Ahern 	return rc;
45598402807SFrederic Weisbecker }
45698402807SFrederic Weisbecker 
4578c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
45857706abcSDavid Ahern {
45957706abcSDavid Ahern 	struct perf_session *session = rec->session;
46057706abcSDavid Ahern 	int feat;
46157706abcSDavid Ahern 
46257706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
46357706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
46457706abcSDavid Ahern 
46557706abcSDavid Ahern 	if (rec->no_buildid)
46657706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
46757706abcSDavid Ahern 
4683e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
46957706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
47057706abcSDavid Ahern 
47157706abcSDavid Ahern 	if (!rec->opts.branch_stack)
47257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
473ef149c25SAdrian Hunter 
474ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
475ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
476ffa517adSJiri Olsa 
477ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
47857706abcSDavid Ahern }
47957706abcSDavid Ahern 
480e1ab48baSWang Nan static void
481e1ab48baSWang Nan record__finish_output(struct record *rec)
482e1ab48baSWang Nan {
483e1ab48baSWang Nan 	struct perf_data_file *file = &rec->file;
484e1ab48baSWang Nan 	int fd = perf_data_file__fd(file);
485e1ab48baSWang Nan 
486e1ab48baSWang Nan 	if (file->is_pipe)
487e1ab48baSWang Nan 		return;
488e1ab48baSWang Nan 
489e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
490e1ab48baSWang Nan 	file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
491e1ab48baSWang Nan 
492e1ab48baSWang Nan 	if (!rec->no_buildid) {
493e1ab48baSWang Nan 		process_buildids(rec);
494e1ab48baSWang Nan 
495e1ab48baSWang Nan 		if (rec->buildid_all)
496e1ab48baSWang Nan 			dsos__hit_all(rec->session);
497e1ab48baSWang Nan 	}
498e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
499e1ab48baSWang Nan 
500e1ab48baSWang Nan 	return;
501e1ab48baSWang Nan }
502e1ab48baSWang Nan 
5033c1cb7e3SWang Nan static int record__synthesize(struct record *rec);
5043c1cb7e3SWang Nan 
505ecfd7a9cSWang Nan static int
506ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
507ecfd7a9cSWang Nan {
508ecfd7a9cSWang Nan 	struct perf_data_file *file = &rec->file;
509ecfd7a9cSWang Nan 	int fd, err;
510ecfd7a9cSWang Nan 
511ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
512ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
513ecfd7a9cSWang Nan 
514ecfd7a9cSWang Nan 	rec->samples = 0;
515ecfd7a9cSWang Nan 	record__finish_output(rec);
516ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
517ecfd7a9cSWang Nan 	if (err) {
518ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
519ecfd7a9cSWang Nan 		return -EINVAL;
520ecfd7a9cSWang Nan 	}
521ecfd7a9cSWang Nan 
522ecfd7a9cSWang Nan 	fd = perf_data_file__switch(file, timestamp,
523ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
524ecfd7a9cSWang Nan 				    at_exit);
525ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
526ecfd7a9cSWang Nan 		rec->bytes_written = 0;
527ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
528ecfd7a9cSWang Nan 	}
529ecfd7a9cSWang Nan 
530ecfd7a9cSWang Nan 	if (!quiet)
531ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
532ecfd7a9cSWang Nan 			file->path, timestamp);
5333c1cb7e3SWang Nan 
5343c1cb7e3SWang Nan 	/* Output tracking events */
5353c1cb7e3SWang Nan 	if (!at_exit)
5363c1cb7e3SWang Nan 		record__synthesize(rec);
5373c1cb7e3SWang Nan 
538ecfd7a9cSWang Nan 	return fd;
539ecfd7a9cSWang Nan }
540ecfd7a9cSWang Nan 
541f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
542f33cbe72SArnaldo Carvalho de Melo 
543f33cbe72SArnaldo Carvalho de Melo /*
544f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
545f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
546f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
547f33cbe72SArnaldo Carvalho de Melo  */
54845604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
54945604710SNamhyung Kim 					siginfo_t *info,
550f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
551f33cbe72SArnaldo Carvalho de Melo {
552f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
553f33cbe72SArnaldo Carvalho de Melo 	done = 1;
554f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
555f33cbe72SArnaldo Carvalho de Melo }
556f33cbe72SArnaldo Carvalho de Melo 
5572dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
5582dd6d8a1SAdrian Hunter 
55946bc29b9SAdrian Hunter int __weak
56046bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
56146bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
56246bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
56346bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
56446bc29b9SAdrian Hunter {
56546bc29b9SAdrian Hunter 	return 0;
56646bc29b9SAdrian Hunter }
56746bc29b9SAdrian Hunter 
568c45c86ebSWang Nan static int record__synthesize(struct record *rec)
569c45c86ebSWang Nan {
570c45c86ebSWang Nan 	struct perf_session *session = rec->session;
571c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
572c45c86ebSWang Nan 	struct perf_data_file *file = &rec->file;
573c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
574c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
575c45c86ebSWang Nan 	int fd = perf_data_file__fd(file);
576c45c86ebSWang Nan 	int err = 0;
577c45c86ebSWang Nan 
578c45c86ebSWang Nan 	if (file->is_pipe) {
579c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
580c45c86ebSWang Nan 						   process_synthesized_event);
581c45c86ebSWang Nan 		if (err < 0) {
582c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
583c45c86ebSWang Nan 			goto out;
584c45c86ebSWang Nan 		}
585c45c86ebSWang Nan 
586c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
587c45c86ebSWang Nan 			/*
588c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
589c45c86ebSWang Nan 			 * there were no tracepoints so its not really
590c45c86ebSWang Nan 			 * an error, just that we don't need to
591c45c86ebSWang Nan 			 * synthesize anything.  We really have to
592c45c86ebSWang Nan 			 * return this more properly and also
593c45c86ebSWang Nan 			 * propagate errors that now are calling die()
594c45c86ebSWang Nan 			 */
595c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
596c45c86ebSWang Nan 								  process_synthesized_event);
597c45c86ebSWang Nan 			if (err <= 0) {
598c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
599c45c86ebSWang Nan 				goto out;
600c45c86ebSWang Nan 			}
601c45c86ebSWang Nan 			rec->bytes_written += err;
602c45c86ebSWang Nan 		}
603c45c86ebSWang Nan 	}
604c45c86ebSWang Nan 
60546bc29b9SAdrian Hunter 	err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
60646bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
60746bc29b9SAdrian Hunter 	if (err)
60846bc29b9SAdrian Hunter 		goto out;
60946bc29b9SAdrian Hunter 
610c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
611c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
612c45c86ebSWang Nan 					session, process_synthesized_event);
613c45c86ebSWang Nan 		if (err)
614c45c86ebSWang Nan 			goto out;
615c45c86ebSWang Nan 	}
616c45c86ebSWang Nan 
617c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
618c45c86ebSWang Nan 						 machine);
619c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
620c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
621c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
622c45c86ebSWang Nan 
623c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
624c45c86ebSWang Nan 					     machine);
625c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
626c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
627c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
628c45c86ebSWang Nan 
629c45c86ebSWang Nan 	if (perf_guest) {
630c45c86ebSWang Nan 		machines__process_guests(&session->machines,
631c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
632c45c86ebSWang Nan 	}
633c45c86ebSWang Nan 
634c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
635c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
636c45c86ebSWang Nan 					    opts->proc_map_timeout);
637c45c86ebSWang Nan out:
638c45c86ebSWang Nan 	return err;
639c45c86ebSWang Nan }
640c45c86ebSWang Nan 
6418c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
64286470930SIngo Molnar {
64357706abcSDavid Ahern 	int err;
64445604710SNamhyung Kim 	int status = 0;
6458b412664SPeter Zijlstra 	unsigned long waking = 0;
64646be604bSZhang, Yanmin 	const bool forks = argc > 0;
64723346f21SArnaldo Carvalho de Melo 	struct machine *machine;
64845694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
649b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
650f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
651d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
6526dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
65342aa276fSNamhyung Kim 	int fd;
65486470930SIngo Molnar 
655d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
65633e49ea7SAndi Kleen 
65745604710SNamhyung Kim 	atexit(record__sig_exit);
658f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
659f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
660804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
661c0bdc1c4SWang Nan 
6623c1cb7e3SWang Nan 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
6632dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
6643c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
6655f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
6663c1cb7e3SWang Nan 		if (rec->switch_output)
6673c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
668c0bdc1c4SWang Nan 	} else {
6692dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
670c0bdc1c4SWang Nan 	}
671f5970550SPeter Zijlstra 
672b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
67394c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
674ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
675a9a70bbcSArnaldo Carvalho de Melo 		return -1;
676a9a70bbcSArnaldo Carvalho de Melo 	}
677a9a70bbcSArnaldo Carvalho de Melo 
67842aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
679d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
680d20deb64SArnaldo Carvalho de Melo 
6818c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
682330aa675SStephane Eranian 
683d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
6843e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
685f5fc1412SJiri Olsa 						    argv, file->is_pipe,
686735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
68735b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
68835b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
68945604710SNamhyung Kim 			status = err;
69035b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
691856e9660SPeter Zijlstra 		}
692856e9660SPeter Zijlstra 	}
693856e9660SPeter Zijlstra 
6948c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
6958d3eca20SDavid Ahern 		err = -1;
69645604710SNamhyung Kim 		goto out_child;
6978d3eca20SDavid Ahern 	}
69886470930SIngo Molnar 
6998690a2a7SWang Nan 	err = bpf__apply_obj_config();
7008690a2a7SWang Nan 	if (err) {
7018690a2a7SWang Nan 		char errbuf[BUFSIZ];
7028690a2a7SWang Nan 
7038690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
7048690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
7058690a2a7SWang Nan 			 errbuf);
7068690a2a7SWang Nan 		goto out_child;
7078690a2a7SWang Nan 	}
7088690a2a7SWang Nan 
709cca8482cSAdrian Hunter 	/*
710cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
711cca8482cSAdrian Hunter 	 * evlist.
712cca8482cSAdrian Hunter 	 */
713cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
714cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
715cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
716cca8482cSAdrian Hunter 	}
717cca8482cSAdrian Hunter 
7183e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
719a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
720a8bb559bSNamhyung Kim 
721f5fc1412SJiri Olsa 	if (file->is_pipe) {
72242aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
723529870e3STom Zanussi 		if (err < 0)
72445604710SNamhyung Kim 			goto out_child;
725563aecb2SJiri Olsa 	} else {
72642aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
727d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
72845604710SNamhyung Kim 			goto out_child;
729d5eed904SArnaldo Carvalho de Melo 	}
7307c6a1c65SPeter Zijlstra 
731d3665498SDavid Ahern 	if (!rec->no_buildid
732e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
733d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
734e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
7358d3eca20SDavid Ahern 		err = -1;
73645604710SNamhyung Kim 		goto out_child;
737e20960c0SRobert Richter 	}
738e20960c0SRobert Richter 
73934ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
740743eb868SArnaldo Carvalho de Melo 
741c45c86ebSWang Nan 	err = record__synthesize(rec);
742c45c86ebSWang Nan 	if (err < 0)
74345604710SNamhyung Kim 		goto out_child;
7448d3eca20SDavid Ahern 
745d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
74686470930SIngo Molnar 		struct sched_param param;
74786470930SIngo Molnar 
748d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
74986470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
7506beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
7518d3eca20SDavid Ahern 			err = -1;
75245604710SNamhyung Kim 			goto out_child;
75386470930SIngo Molnar 		}
75486470930SIngo Molnar 	}
75586470930SIngo Molnar 
756774cb499SJiri Olsa 	/*
757774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
758774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
759774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
760774cb499SJiri Olsa 	 */
7616619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
7623e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
763764e16a3SDavid Ahern 
764856e9660SPeter Zijlstra 	/*
765856e9660SPeter Zijlstra 	 * Let the child rip
766856e9660SPeter Zijlstra 	 */
767e803cf97SNamhyung Kim 	if (forks) {
768e5bed564SNamhyung Kim 		union perf_event *event;
769e5bed564SNamhyung Kim 
770e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
771e5bed564SNamhyung Kim 		if (event == NULL) {
772e5bed564SNamhyung Kim 			err = -ENOMEM;
773e5bed564SNamhyung Kim 			goto out_child;
774e5bed564SNamhyung Kim 		}
775e5bed564SNamhyung Kim 
776e803cf97SNamhyung Kim 		/*
777e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
778e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
779e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
780e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
781e803cf97SNamhyung Kim 		 */
782e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
783e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
784e803cf97SNamhyung Kim 					    process_synthesized_event,
785e803cf97SNamhyung Kim 					    machine);
786e5bed564SNamhyung Kim 		free(event);
787e803cf97SNamhyung Kim 
7883e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
789e803cf97SNamhyung Kim 	}
790856e9660SPeter Zijlstra 
7916619a53eSAndi Kleen 	if (opts->initial_delay) {
7926619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
7936619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
7946619a53eSAndi Kleen 	}
7956619a53eSAndi Kleen 
7965f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
7973c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
798649c48a9SPeter Zijlstra 	for (;;) {
7999f065194SYang Shi 		unsigned long long hits = rec->samples;
80086470930SIngo Molnar 
8018c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
8025f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
8033c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
8048d3eca20SDavid Ahern 			err = -1;
80545604710SNamhyung Kim 			goto out_child;
8068d3eca20SDavid Ahern 		}
80786470930SIngo Molnar 
8082dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
8092dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
8105f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
8112dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
8125f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
8132dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
8142dd6d8a1SAdrian Hunter 				err = -1;
8152dd6d8a1SAdrian Hunter 				goto out_child;
8162dd6d8a1SAdrian Hunter 			}
8172dd6d8a1SAdrian Hunter 		}
8182dd6d8a1SAdrian Hunter 
8193c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
8203c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
8213c1cb7e3SWang Nan 
8223c1cb7e3SWang Nan 			if (!quiet)
8233c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
8243c1cb7e3SWang Nan 					waking);
8253c1cb7e3SWang Nan 			waking = 0;
8263c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
8273c1cb7e3SWang Nan 			if (fd < 0) {
8283c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
8293c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
8303c1cb7e3SWang Nan 				err = fd;
8313c1cb7e3SWang Nan 				goto out_child;
8323c1cb7e3SWang Nan 			}
8333c1cb7e3SWang Nan 		}
8343c1cb7e3SWang Nan 
835d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
8366dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
837649c48a9SPeter Zijlstra 				break;
838f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
839a515114fSJiri Olsa 			/*
840a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
841a515114fSJiri Olsa 			 * number of returned events and interrupt error.
842a515114fSJiri Olsa 			 */
843a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
84445604710SNamhyung Kim 				err = 0;
8458b412664SPeter Zijlstra 			waking++;
8466dcf45efSArnaldo Carvalho de Melo 
8476dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
8486dcf45efSArnaldo Carvalho de Melo 				draining = true;
8498b412664SPeter Zijlstra 		}
8508b412664SPeter Zijlstra 
851774cb499SJiri Olsa 		/*
852774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
853774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
854774cb499SJiri Olsa 		 * disable events in this case.
855774cb499SJiri Olsa 		 */
856602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
8575f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
8583e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
8592711926aSJiri Olsa 			disabled = true;
8602711926aSJiri Olsa 		}
8618b412664SPeter Zijlstra 	}
8625f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
8633c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
8648b412664SPeter Zijlstra 
865f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
86635550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
867f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
868f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
869f33cbe72SArnaldo Carvalho de Melo 		err = -1;
87045604710SNamhyung Kim 		goto out_child;
871f33cbe72SArnaldo Carvalho de Melo 	}
872f33cbe72SArnaldo Carvalho de Melo 
873e3d59112SNamhyung Kim 	if (!quiet)
8748b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
87586470930SIngo Molnar 
87645604710SNamhyung Kim out_child:
87745604710SNamhyung Kim 	if (forks) {
87845604710SNamhyung Kim 		int exit_status;
87945604710SNamhyung Kim 
88045604710SNamhyung Kim 		if (!child_finished)
88145604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
88245604710SNamhyung Kim 
88345604710SNamhyung Kim 		wait(&exit_status);
88445604710SNamhyung Kim 
88545604710SNamhyung Kim 		if (err < 0)
88645604710SNamhyung Kim 			status = err;
88745604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
88845604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
88945604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
89045604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
89145604710SNamhyung Kim 	} else
89245604710SNamhyung Kim 		status = err;
89345604710SNamhyung Kim 
894e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
895e3d59112SNamhyung Kim 	rec->samples = 0;
896e3d59112SNamhyung Kim 
897ecfd7a9cSWang Nan 	if (!err) {
898ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
899e1ab48baSWang Nan 			record__finish_output(rec);
900ecfd7a9cSWang Nan 		} else {
901ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
902ecfd7a9cSWang Nan 			if (fd < 0) {
903ecfd7a9cSWang Nan 				status = fd;
904ecfd7a9cSWang Nan 				goto out_delete_session;
905ecfd7a9cSWang Nan 			}
906ecfd7a9cSWang Nan 		}
907ecfd7a9cSWang Nan 	}
90839d17dacSArnaldo Carvalho de Melo 
909e3d59112SNamhyung Kim 	if (!err && !quiet) {
910e3d59112SNamhyung Kim 		char samples[128];
911ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
912ecfd7a9cSWang Nan 					".<timestamp>" : "";
913e3d59112SNamhyung Kim 
914ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
915e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
916e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
917e3d59112SNamhyung Kim 		else
918e3d59112SNamhyung Kim 			samples[0] = '\0';
919e3d59112SNamhyung Kim 
920ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
921e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
922ecfd7a9cSWang Nan 			file->path, postfix, samples);
923e3d59112SNamhyung Kim 	}
924e3d59112SNamhyung Kim 
92539d17dacSArnaldo Carvalho de Melo out_delete_session:
92639d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
92745604710SNamhyung Kim 	return status;
92886470930SIngo Molnar }
92986470930SIngo Molnar 
9300883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
93109b0fd45SJiri Olsa {
932aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
933a601fdffSJiri Olsa 
9340883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
93526d33022SJiri Olsa 
9360883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
93709b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
9380883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
9390883e820SArnaldo Carvalho de Melo }
9400883e820SArnaldo Carvalho de Melo 
9410883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
9420883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
9430883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
9440883e820SArnaldo Carvalho de Melo {
9450883e820SArnaldo Carvalho de Melo 	int ret;
9460883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
9470883e820SArnaldo Carvalho de Melo 
9480883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
9490883e820SArnaldo Carvalho de Melo 	if (unset) {
9500883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
9510883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
9520883e820SArnaldo Carvalho de Melo 		return 0;
9530883e820SArnaldo Carvalho de Melo 	}
9540883e820SArnaldo Carvalho de Melo 
9550883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
9560883e820SArnaldo Carvalho de Melo 	if (!ret) {
9570883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
9580883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
9590883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
9600883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
9610883e820SArnaldo Carvalho de Melo 	}
9620883e820SArnaldo Carvalho de Melo 
9630883e820SArnaldo Carvalho de Melo 	return ret;
96409b0fd45SJiri Olsa }
96509b0fd45SJiri Olsa 
966c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
96709b0fd45SJiri Olsa 			       const char *arg,
96809b0fd45SJiri Olsa 			       int unset)
96909b0fd45SJiri Olsa {
9700883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
97126d33022SJiri Olsa }
97226d33022SJiri Olsa 
973c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
97409b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
97509b0fd45SJiri Olsa 			 int unset __maybe_unused)
97609b0fd45SJiri Olsa {
9772ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
978c421e80bSKan Liang 
9792ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
98009b0fd45SJiri Olsa 
9812ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
9822ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
983eb853e80SJiri Olsa 
9842ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
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"),
12222ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
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"),
1295ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1296ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
12973c1cb7e3SWang Nan 	OPT_BOOLEAN(0, "switch-output", &record.switch_output,
12983c1cb7e3SWang Nan 		    "Switch output when receive SIGUSR2"),
129986470930SIngo Molnar 	OPT_END()
130086470930SIngo Molnar };
130186470930SIngo Molnar 
1302e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1303e5b2c207SNamhyung Kim 
13041d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
130586470930SIngo Molnar {
1306ef149c25SAdrian Hunter 	int err;
13078c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
130816ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
130986470930SIngo Molnar 
131048e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
131148e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
131248e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
131348e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
131448e1cab1SWang Nan # undef set_nobuild
131548e1cab1SWang Nan #endif
131648e1cab1SWang Nan 
13177efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
13187efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
13197efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
13207efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
13217efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
13227efe0e03SHe Kuang # else
13237efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
13247efe0e03SHe Kuang # endif
13257efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
13267efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
13277efe0e03SHe Kuang # undef set_nobuild
13287efe0e03SHe Kuang # undef REASON
13297efe0e03SHe Kuang #endif
13307efe0e03SHe Kuang 
13313e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
13323e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1333361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1334361c99a6SArnaldo Carvalho de Melo 
1335eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1336eb853e80SJiri Olsa 
1337bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1338a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1339602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1340bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
134186470930SIngo Molnar 
1342bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1343c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1344c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1345c7118369SNamhyung Kim 
1346023695d9SStephane Eranian 	}
1347b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1348b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1349c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1350c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1351c7118369SNamhyung Kim 		return -EINVAL;
1352b757bb09SAdrian Hunter 	}
1353023695d9SStephane Eranian 
1354eca857abSWang Nan 	if (rec->switch_output)
1355eca857abSWang Nan 		rec->timestamp_filename = true;
1356eca857abSWang Nan 
1357ef149c25SAdrian Hunter 	if (!rec->itr) {
1358ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1359ef149c25SAdrian Hunter 		if (err)
1360ef149c25SAdrian Hunter 			return err;
1361ef149c25SAdrian Hunter 	}
1362ef149c25SAdrian Hunter 
13632dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
13642dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
13652dd6d8a1SAdrian Hunter 	if (err)
13662dd6d8a1SAdrian Hunter 		return err;
13672dd6d8a1SAdrian Hunter 
1368d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1369d7888573SWang Nan 	if (err) {
1370d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1371d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1372d7888573SWang Nan 			 errbuf);
1373d7888573SWang Nan 		return err;
1374d7888573SWang Nan 	}
1375d7888573SWang Nan 
1376ef149c25SAdrian Hunter 	err = -ENOMEM;
1377ef149c25SAdrian Hunter 
13780a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1379baa2f6ceSArnaldo Carvalho de Melo 
1380ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1381646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1382646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1383ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1384646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1385646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1386646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1387646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1388646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1389ec80fde7SArnaldo Carvalho de Melo 
1390*0c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
1391a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1392*0c1d46a8SWang Nan 	} else if (rec->switch_output) {
1393*0c1d46a8SWang Nan 		/*
1394*0c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
1395*0c1d46a8SWang Nan 		 * generation by default to reduce data file switching
1396*0c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
1397*0c1d46a8SWang Nan 		 * explicitly using
1398*0c1d46a8SWang Nan 		 *
1399*0c1d46a8SWang Nan 		 *  perf record --signal-trigger --no-no-buildid \
1400*0c1d46a8SWang Nan 		 *              --no-no-buildid-cache
1401*0c1d46a8SWang Nan 		 *
1402*0c1d46a8SWang Nan 		 * Following code equals to:
1403*0c1d46a8SWang Nan 		 *
1404*0c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
1405*0c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
1406*0c1d46a8SWang Nan 		 *         disable_buildid_cache();
1407*0c1d46a8SWang Nan 		 */
1408*0c1d46a8SWang Nan 		bool disable = true;
1409*0c1d46a8SWang Nan 
1410*0c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
1411*0c1d46a8SWang Nan 			disable = false;
1412*0c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
1413*0c1d46a8SWang Nan 			disable = false;
1414*0c1d46a8SWang Nan 		if (disable) {
1415*0c1d46a8SWang Nan 			rec->no_buildid = true;
1416*0c1d46a8SWang Nan 			rec->no_buildid_cache = true;
1417*0c1d46a8SWang Nan 			disable_buildid_cache();
1418*0c1d46a8SWang Nan 		}
1419*0c1d46a8SWang Nan 	}
1420655000e7SArnaldo Carvalho de Melo 
14213e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
14223e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
142369aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
142469aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1425bbd36e5eSPeter Zijlstra 	}
142686470930SIngo Molnar 
142769e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
142869e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
142969e7e5b0SAdrian Hunter 
1430602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
143116ad2ffbSNamhyung Kim 	if (err) {
1432602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
143316ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
143416ad2ffbSNamhyung Kim 	}
14354bd0f2d2SNamhyung Kim 
1436602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
143716ad2ffbSNamhyung Kim 	if (err) {
143816ad2ffbSNamhyung Kim 		int saved_errno = errno;
143916ad2ffbSNamhyung Kim 
1440602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
14413780f488SNamhyung Kim 		ui__error("%s", errbuf);
144216ad2ffbSNamhyung Kim 
144316ad2ffbSNamhyung Kim 		err = -saved_errno;
14448fa60e1fSNamhyung Kim 		goto out_symbol_exit;
144516ad2ffbSNamhyung Kim 	}
14460d37aa34SArnaldo Carvalho de Melo 
144716ad2ffbSNamhyung Kim 	err = -ENOMEM;
14483e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1449dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
145069aad6f1SArnaldo Carvalho de Melo 
1451ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1452ef149c25SAdrian Hunter 	if (err)
1453ef149c25SAdrian Hunter 		goto out_symbol_exit;
1454ef149c25SAdrian Hunter 
14556156681bSNamhyung Kim 	/*
14566156681bSNamhyung Kim 	 * We take all buildids when the file contains
14576156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
14586156681bSNamhyung Kim 	 * trace because it would take too long.
14596156681bSNamhyung Kim 	 */
14606156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
14616156681bSNamhyung Kim 		rec->buildid_all = true;
14626156681bSNamhyung Kim 
1463b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
146439d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
146503ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
14667e4ff9e3SMike Galbraith 	}
14677e4ff9e3SMike Galbraith 
1468d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1469d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
147045604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1471d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1472ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
147339d17dacSArnaldo Carvalho de Melo 	return err;
147486470930SIngo Molnar }
14752dd6d8a1SAdrian Hunter 
14762dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
14772dd6d8a1SAdrian Hunter {
14785f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
14795f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
14802dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
14815f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
14825f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
14835f9cf599SWang Nan 	}
14843c1cb7e3SWang Nan 
14853c1cb7e3SWang Nan 	if (trigger_is_ready(&switch_output_trigger))
14863c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
14872dd6d8a1SAdrian Hunter }
1488