xref: /openbmc/linux/tools/perf/builtin-record.c (revision 2d11c65071d489e20b3a811167507939dd8c2eac)
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>
43*2d11c650SWang Nan #include <asm/bug.h>
4486470930SIngo Molnar 
4578da39faSBernhard Rosenkraenzer 
468c6f45a7SArnaldo Carvalho de Melo struct record {
4745694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
48b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
49d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
50f5fc1412SJiri Olsa 	struct perf_data_file	file;
51ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
52d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
53d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
54d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
55d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
56d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
57d2db9a98SWang Nan 	bool			no_buildid_set;
58d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
59d2db9a98SWang Nan 	bool			no_buildid_cache_set;
606156681bSNamhyung Kim 	bool			buildid_all;
61ecfd7a9cSWang Nan 	bool			timestamp_filename;
623c1cb7e3SWang Nan 	bool			switch_output;
639f065194SYang Shi 	unsigned long long	samples;
640f82ebc4SArnaldo Carvalho de Melo };
6586470930SIngo Molnar 
668c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
67f5970550SPeter Zijlstra {
68cf8b2e69SArnaldo Carvalho de Melo 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
694f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
708d3eca20SDavid Ahern 		return -1;
718d3eca20SDavid Ahern 	}
72f5970550SPeter Zijlstra 
73cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
748d3eca20SDavid Ahern 	return 0;
75f5970550SPeter Zijlstra }
76f5970550SPeter Zijlstra 
7745694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
78d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
791d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
801d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
81234fbbf5SArnaldo Carvalho de Melo {
828c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
838c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
84234fbbf5SArnaldo Carvalho de Melo }
85234fbbf5SArnaldo Carvalho de Melo 
86e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx)
8786470930SIngo Molnar {
88e5685730SArnaldo Carvalho de Melo 	struct perf_mmap *md = &rec->evlist->mmap[idx];
897b8283b5SDavid Ahern 	u64 head = perf_mmap__read_head(md);
907b8283b5SDavid Ahern 	u64 old = md->prev;
91918512b4SJiri Olsa 	unsigned char *data = md->base + page_size;
9286470930SIngo Molnar 	unsigned long size;
9386470930SIngo Molnar 	void *buf;
948d3eca20SDavid Ahern 	int rc = 0;
9586470930SIngo Molnar 
96dc82009aSArnaldo Carvalho de Melo 	if (old == head)
978d3eca20SDavid Ahern 		return 0;
9886470930SIngo Molnar 
99d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
10086470930SIngo Molnar 
10186470930SIngo Molnar 	size = head - old;
102*2d11c650SWang Nan 	if (size > (unsigned long)(md->mask) + 1) {
103*2d11c650SWang Nan 		WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
104*2d11c650SWang Nan 
105*2d11c650SWang Nan 		md->prev = head;
106*2d11c650SWang Nan 		perf_evlist__mmap_consume(rec->evlist, idx);
107*2d11c650SWang Nan 		return 0;
108*2d11c650SWang Nan 	}
10986470930SIngo Molnar 
11086470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
11186470930SIngo Molnar 		buf = &data[old & md->mask];
11286470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
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 
12186470930SIngo Molnar 	buf = &data[old & md->mask];
12286470930SIngo Molnar 	size = head - old;
12386470930SIngo Molnar 	old += size;
12486470930SIngo Molnar 
1258c6f45a7SArnaldo Carvalho de Melo 	if (record__write(rec, buf, size) < 0) {
1268d3eca20SDavid Ahern 		rc = -1;
1278d3eca20SDavid Ahern 		goto out;
1288d3eca20SDavid Ahern 	}
12986470930SIngo Molnar 
13086470930SIngo Molnar 	md->prev = old;
131e5685730SArnaldo Carvalho de Melo 	perf_evlist__mmap_consume(rec->evlist, idx);
1328d3eca20SDavid Ahern out:
1338d3eca20SDavid Ahern 	return rc;
13486470930SIngo Molnar }
13586470930SIngo Molnar 
1362dd6d8a1SAdrian Hunter static volatile int done;
1372dd6d8a1SAdrian Hunter static volatile int signr = -1;
1382dd6d8a1SAdrian Hunter static volatile int child_finished;
139c0bdc1c4SWang Nan 
1402dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started;
1415f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
1423c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger);
1432dd6d8a1SAdrian Hunter 
1442dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1452dd6d8a1SAdrian Hunter {
1462dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1472dd6d8a1SAdrian Hunter 		child_finished = 1;
1482dd6d8a1SAdrian Hunter 	else
1492dd6d8a1SAdrian Hunter 		signr = sig;
1502dd6d8a1SAdrian Hunter 
1512dd6d8a1SAdrian Hunter 	done = 1;
1522dd6d8a1SAdrian Hunter }
1532dd6d8a1SAdrian Hunter 
1542dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1552dd6d8a1SAdrian Hunter {
1562dd6d8a1SAdrian Hunter 	if (signr == -1)
1572dd6d8a1SAdrian Hunter 		return;
1582dd6d8a1SAdrian Hunter 
1592dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1602dd6d8a1SAdrian Hunter 	raise(signr);
1612dd6d8a1SAdrian Hunter }
1622dd6d8a1SAdrian Hunter 
163e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
164e31f0d01SAdrian Hunter 
165ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
166ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
167ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
168ef149c25SAdrian Hunter {
169ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
17099fa2984SAdrian Hunter 	struct perf_data_file *file = &rec->file;
171ef149c25SAdrian Hunter 	size_t padding;
172ef149c25SAdrian Hunter 	u8 pad[8] = {0};
173ef149c25SAdrian Hunter 
17499fa2984SAdrian Hunter 	if (!perf_data_file__is_pipe(file)) {
17599fa2984SAdrian Hunter 		off_t file_offset;
17699fa2984SAdrian Hunter 		int fd = perf_data_file__fd(file);
17799fa2984SAdrian Hunter 		int err;
17899fa2984SAdrian Hunter 
17999fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
18099fa2984SAdrian Hunter 		if (file_offset == -1)
18199fa2984SAdrian Hunter 			return -1;
18299fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
18399fa2984SAdrian Hunter 						     event, file_offset);
18499fa2984SAdrian Hunter 		if (err)
18599fa2984SAdrian Hunter 			return err;
18699fa2984SAdrian Hunter 	}
18799fa2984SAdrian Hunter 
188ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
189ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
190ef149c25SAdrian Hunter 	if (padding)
191ef149c25SAdrian Hunter 		padding = 8 - padding;
192ef149c25SAdrian Hunter 
193ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
194ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
195ef149c25SAdrian Hunter 	if (len2)
196ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
197ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
198ef149c25SAdrian Hunter 
199ef149c25SAdrian Hunter 	return 0;
200ef149c25SAdrian Hunter }
201ef149c25SAdrian Hunter 
202ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
203ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
204ef149c25SAdrian Hunter {
205ef149c25SAdrian Hunter 	int ret;
206ef149c25SAdrian Hunter 
207ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
208ef149c25SAdrian Hunter 				  record__process_auxtrace);
209ef149c25SAdrian Hunter 	if (ret < 0)
210ef149c25SAdrian Hunter 		return ret;
211ef149c25SAdrian Hunter 
212ef149c25SAdrian Hunter 	if (ret)
213ef149c25SAdrian Hunter 		rec->samples++;
214ef149c25SAdrian Hunter 
215ef149c25SAdrian Hunter 	return 0;
216ef149c25SAdrian Hunter }
217ef149c25SAdrian Hunter 
2182dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2192dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2202dd6d8a1SAdrian Hunter {
2212dd6d8a1SAdrian Hunter 	int ret;
2222dd6d8a1SAdrian Hunter 
2232dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2242dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2252dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2262dd6d8a1SAdrian Hunter 	if (ret < 0)
2272dd6d8a1SAdrian Hunter 		return ret;
2282dd6d8a1SAdrian Hunter 
2292dd6d8a1SAdrian Hunter 	if (ret)
2302dd6d8a1SAdrian Hunter 		rec->samples++;
2312dd6d8a1SAdrian Hunter 
2322dd6d8a1SAdrian Hunter 	return 0;
2332dd6d8a1SAdrian Hunter }
2342dd6d8a1SAdrian Hunter 
2352dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2362dd6d8a1SAdrian Hunter {
2372dd6d8a1SAdrian Hunter 	int i;
2382dd6d8a1SAdrian Hunter 	int rc = 0;
2392dd6d8a1SAdrian Hunter 
2402dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2412dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2422dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2432dd6d8a1SAdrian Hunter 
2442dd6d8a1SAdrian Hunter 		if (!mm->base)
2452dd6d8a1SAdrian Hunter 			continue;
2462dd6d8a1SAdrian Hunter 
2472dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2482dd6d8a1SAdrian Hunter 			rc = -1;
2492dd6d8a1SAdrian Hunter 			goto out;
2502dd6d8a1SAdrian Hunter 		}
2512dd6d8a1SAdrian Hunter 	}
2522dd6d8a1SAdrian Hunter out:
2532dd6d8a1SAdrian Hunter 	return rc;
2542dd6d8a1SAdrian Hunter }
2552dd6d8a1SAdrian Hunter 
2562dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2572dd6d8a1SAdrian Hunter {
2582dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2592dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2605f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
2612dd6d8a1SAdrian Hunter 	} else {
2625f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
2635f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
2645f9cf599SWang Nan 		else
2655f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
2662dd6d8a1SAdrian Hunter 	}
2672dd6d8a1SAdrian Hunter }
2682dd6d8a1SAdrian Hunter 
269e31f0d01SAdrian Hunter #else
270e31f0d01SAdrian Hunter 
271e31f0d01SAdrian Hunter static inline
272e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
273e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
274e31f0d01SAdrian Hunter {
275e31f0d01SAdrian Hunter 	return 0;
276e31f0d01SAdrian Hunter }
277e31f0d01SAdrian Hunter 
2782dd6d8a1SAdrian Hunter static inline
2792dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2802dd6d8a1SAdrian Hunter {
2812dd6d8a1SAdrian Hunter }
2822dd6d8a1SAdrian Hunter 
2832dd6d8a1SAdrian Hunter static inline
2842dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2852dd6d8a1SAdrian Hunter {
2862dd6d8a1SAdrian Hunter 	return 0;
2872dd6d8a1SAdrian Hunter }
2882dd6d8a1SAdrian Hunter 
289e31f0d01SAdrian Hunter #endif
290e31f0d01SAdrian Hunter 
2918c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
292dd7927f4SArnaldo Carvalho de Melo {
29356e52e85SArnaldo Carvalho de Melo 	char msg[512];
2946a4bb04cSJiri Olsa 	struct perf_evsel *pos;
295d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
296d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
297b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
2988d3eca20SDavid Ahern 	int rc = 0;
299dd7927f4SArnaldo Carvalho de Melo 
300e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
301cac21425SJiri Olsa 
3020050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
3033da297a6SIngo Molnar try_again:
304d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
30556e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
3063da297a6SIngo Molnar 				if (verbose)
307c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3083da297a6SIngo Molnar 				goto try_again;
3093da297a6SIngo Molnar 			}
310ca6a4258SDavid Ahern 
31156e52e85SArnaldo Carvalho de Melo 			rc = -errno;
31256e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
31356e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
31456e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3158d3eca20SDavid Ahern 			goto out;
3167c6a1c65SPeter Zijlstra 		}
3177c6a1c65SPeter Zijlstra 	}
3187c6a1c65SPeter Zijlstra 
31923d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
32023d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
32123d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
32235550da3SMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
3238d3eca20SDavid Ahern 		rc = -1;
3248d3eca20SDavid Ahern 		goto out;
3250a102479SFrederic Weisbecker 	}
3260a102479SFrederic Weisbecker 
327ef149c25SAdrian Hunter 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
3282dd6d8a1SAdrian Hunter 				 opts->auxtrace_mmap_pages,
3292dd6d8a1SAdrian Hunter 				 opts->auxtrace_snapshot_mode) < 0) {
3308d3eca20SDavid Ahern 		if (errno == EPERM) {
3318d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
33218e60939SNelson Elhage 			       "Consider increasing "
33318e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
33418e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
335ef149c25SAdrian Hunter 			       "(current value: %u,%u)\n",
336ef149c25SAdrian Hunter 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
3378d3eca20SDavid Ahern 			rc = -errno;
3388d3eca20SDavid Ahern 		} else {
33935550da3SMasami Hiramatsu 			pr_err("failed to mmap with %d (%s)\n", errno,
34035550da3SMasami Hiramatsu 				strerror_r(errno, msg, sizeof(msg)));
34195c36561SWang Nan 			if (errno)
3428d3eca20SDavid Ahern 				rc = -errno;
34395c36561SWang Nan 			else
34495c36561SWang Nan 				rc = -EINVAL;
3458d3eca20SDavid Ahern 		}
3468d3eca20SDavid Ahern 		goto out;
34718e60939SNelson Elhage 	}
3480a27d7f9SArnaldo Carvalho de Melo 
349a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3507b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3518d3eca20SDavid Ahern out:
3528d3eca20SDavid Ahern 	return rc;
353a91e5431SArnaldo Carvalho de Melo }
354a91e5431SArnaldo Carvalho de Melo 
355e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
356e3d59112SNamhyung Kim 				union perf_event *event,
357e3d59112SNamhyung Kim 				struct perf_sample *sample,
358e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
359e3d59112SNamhyung Kim 				struct machine *machine)
360e3d59112SNamhyung Kim {
361e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
362e3d59112SNamhyung Kim 
363e3d59112SNamhyung Kim 	rec->samples++;
364e3d59112SNamhyung Kim 
365e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
366e3d59112SNamhyung Kim }
367e3d59112SNamhyung Kim 
3688c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
3696122e4e4SArnaldo Carvalho de Melo {
370f5fc1412SJiri Olsa 	struct perf_data_file *file  = &rec->file;
371f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
3726122e4e4SArnaldo Carvalho de Melo 
373457ae94aSHe Kuang 	if (file->size == 0)
3749f591fd7SArnaldo Carvalho de Melo 		return 0;
3759f591fd7SArnaldo Carvalho de Melo 
37600dc8657SNamhyung Kim 	/*
37700dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
37800dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
37900dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
38000dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
38100dc8657SNamhyung Kim 	 *
38200dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
38300dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
38400dc8657SNamhyung Kim 	 */
38500dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
38600dc8657SNamhyung Kim 
3876156681bSNamhyung Kim 	/*
3886156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
3896156681bSNamhyung Kim 	 * so no need to process samples.
3906156681bSNamhyung Kim 	 */
3916156681bSNamhyung Kim 	if (rec->buildid_all)
3926156681bSNamhyung Kim 		rec->tool.sample = NULL;
3936156681bSNamhyung Kim 
394b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
3956122e4e4SArnaldo Carvalho de Melo }
3966122e4e4SArnaldo Carvalho de Melo 
3978115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
398a1645ce1SZhang, Yanmin {
399a1645ce1SZhang, Yanmin 	int err;
40045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
401a1645ce1SZhang, Yanmin 	/*
402a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
403a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
404a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
405a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
406a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
407a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
408a1645ce1SZhang, Yanmin 	 */
40945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
410743eb868SArnaldo Carvalho de Melo 					     machine);
411a1645ce1SZhang, Yanmin 	if (err < 0)
412a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
414a1645ce1SZhang, Yanmin 
415a1645ce1SZhang, Yanmin 	/*
416a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
417a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
418a1645ce1SZhang, Yanmin 	 */
41945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4200ae617beSAdrian Hunter 						 machine);
421a1645ce1SZhang, Yanmin 	if (err < 0)
422a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
42323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
424a1645ce1SZhang, Yanmin }
425a1645ce1SZhang, Yanmin 
42698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
42798402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
42898402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
42998402807SFrederic Weisbecker };
43098402807SFrederic Weisbecker 
4318c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec)
43298402807SFrederic Weisbecker {
433dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4340e2e63ddSPeter Zijlstra 	int i;
4358d3eca20SDavid Ahern 	int rc = 0;
43698402807SFrederic Weisbecker 
437d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
438ef149c25SAdrian Hunter 		struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
439ef149c25SAdrian Hunter 
4408d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
441e5685730SArnaldo Carvalho de Melo 			if (record__mmap_read(rec, i) != 0) {
4428d3eca20SDavid Ahern 				rc = -1;
4438d3eca20SDavid Ahern 				goto out;
4448d3eca20SDavid Ahern 			}
4458d3eca20SDavid Ahern 		}
446ef149c25SAdrian Hunter 
4472dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
448ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
449ef149c25SAdrian Hunter 			rc = -1;
450ef149c25SAdrian Hunter 			goto out;
451ef149c25SAdrian Hunter 		}
45298402807SFrederic Weisbecker 	}
45398402807SFrederic Weisbecker 
454dcabb507SJiri Olsa 	/*
455dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
456dcabb507SJiri Olsa 	 * at least one event.
457dcabb507SJiri Olsa 	 */
458dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
4598c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
4608d3eca20SDavid Ahern 
4618d3eca20SDavid Ahern out:
4628d3eca20SDavid Ahern 	return rc;
46398402807SFrederic Weisbecker }
46498402807SFrederic Weisbecker 
4658c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
46657706abcSDavid Ahern {
46757706abcSDavid Ahern 	struct perf_session *session = rec->session;
46857706abcSDavid Ahern 	int feat;
46957706abcSDavid Ahern 
47057706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
47157706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
47257706abcSDavid Ahern 
47357706abcSDavid Ahern 	if (rec->no_buildid)
47457706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
47557706abcSDavid Ahern 
4763e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
47757706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
47857706abcSDavid Ahern 
47957706abcSDavid Ahern 	if (!rec->opts.branch_stack)
48057706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
481ef149c25SAdrian Hunter 
482ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
483ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
484ffa517adSJiri Olsa 
485ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
48657706abcSDavid Ahern }
48757706abcSDavid Ahern 
488e1ab48baSWang Nan static void
489e1ab48baSWang Nan record__finish_output(struct record *rec)
490e1ab48baSWang Nan {
491e1ab48baSWang Nan 	struct perf_data_file *file = &rec->file;
492e1ab48baSWang Nan 	int fd = perf_data_file__fd(file);
493e1ab48baSWang Nan 
494e1ab48baSWang Nan 	if (file->is_pipe)
495e1ab48baSWang Nan 		return;
496e1ab48baSWang Nan 
497e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
498e1ab48baSWang Nan 	file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
499e1ab48baSWang Nan 
500e1ab48baSWang Nan 	if (!rec->no_buildid) {
501e1ab48baSWang Nan 		process_buildids(rec);
502e1ab48baSWang Nan 
503e1ab48baSWang Nan 		if (rec->buildid_all)
504e1ab48baSWang Nan 			dsos__hit_all(rec->session);
505e1ab48baSWang Nan 	}
506e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
507e1ab48baSWang Nan 
508e1ab48baSWang Nan 	return;
509e1ab48baSWang Nan }
510e1ab48baSWang Nan 
511be7b0c9eSWang Nan static int record__synthesize_workload(struct record *rec)
512be7b0c9eSWang Nan {
513be7b0c9eSWang Nan 	struct {
514be7b0c9eSWang Nan 		struct thread_map map;
515be7b0c9eSWang Nan 		struct thread_map_data map_data;
516be7b0c9eSWang Nan 	} thread_map;
517be7b0c9eSWang Nan 
518be7b0c9eSWang Nan 	thread_map.map.nr = 1;
519be7b0c9eSWang Nan 	thread_map.map.map[0].pid = rec->evlist->workload.pid;
520be7b0c9eSWang Nan 	thread_map.map.map[0].comm = NULL;
521be7b0c9eSWang Nan 	return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
522be7b0c9eSWang Nan 						 process_synthesized_event,
523be7b0c9eSWang Nan 						 &rec->session->machines.host,
524be7b0c9eSWang Nan 						 rec->opts.sample_address,
525be7b0c9eSWang Nan 						 rec->opts.proc_map_timeout);
526be7b0c9eSWang Nan }
527be7b0c9eSWang Nan 
5283c1cb7e3SWang Nan static int record__synthesize(struct record *rec);
5293c1cb7e3SWang Nan 
530ecfd7a9cSWang Nan static int
531ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
532ecfd7a9cSWang Nan {
533ecfd7a9cSWang Nan 	struct perf_data_file *file = &rec->file;
534ecfd7a9cSWang Nan 	int fd, err;
535ecfd7a9cSWang Nan 
536ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
537ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
538ecfd7a9cSWang Nan 
539ecfd7a9cSWang Nan 	rec->samples = 0;
540ecfd7a9cSWang Nan 	record__finish_output(rec);
541ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
542ecfd7a9cSWang Nan 	if (err) {
543ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
544ecfd7a9cSWang Nan 		return -EINVAL;
545ecfd7a9cSWang Nan 	}
546ecfd7a9cSWang Nan 
547ecfd7a9cSWang Nan 	fd = perf_data_file__switch(file, timestamp,
548ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
549ecfd7a9cSWang Nan 				    at_exit);
550ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
551ecfd7a9cSWang Nan 		rec->bytes_written = 0;
552ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
553ecfd7a9cSWang Nan 	}
554ecfd7a9cSWang Nan 
555ecfd7a9cSWang Nan 	if (!quiet)
556ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
557ecfd7a9cSWang Nan 			file->path, timestamp);
5583c1cb7e3SWang Nan 
5593c1cb7e3SWang Nan 	/* Output tracking events */
560be7b0c9eSWang Nan 	if (!at_exit) {
5613c1cb7e3SWang Nan 		record__synthesize(rec);
5623c1cb7e3SWang Nan 
563be7b0c9eSWang Nan 		/*
564be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
565be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
566be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
567be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
568be7b0c9eSWang Nan 		 * contain map and comm information.
569be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
570be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
571be7b0c9eSWang Nan 		 */
572be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
573be7b0c9eSWang Nan 			record__synthesize_workload(rec);
574be7b0c9eSWang Nan 	}
575ecfd7a9cSWang Nan 	return fd;
576ecfd7a9cSWang Nan }
577ecfd7a9cSWang Nan 
578f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
579f33cbe72SArnaldo Carvalho de Melo 
580f33cbe72SArnaldo Carvalho de Melo /*
581f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
582f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
583f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
584f33cbe72SArnaldo Carvalho de Melo  */
58545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
58645604710SNamhyung Kim 					siginfo_t *info,
587f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
588f33cbe72SArnaldo Carvalho de Melo {
589f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
590f33cbe72SArnaldo Carvalho de Melo 	done = 1;
591f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
592f33cbe72SArnaldo Carvalho de Melo }
593f33cbe72SArnaldo Carvalho de Melo 
5942dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
5952dd6d8a1SAdrian Hunter 
59646bc29b9SAdrian Hunter int __weak
59746bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
59846bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
59946bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
60046bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
60146bc29b9SAdrian Hunter {
60246bc29b9SAdrian Hunter 	return 0;
60346bc29b9SAdrian Hunter }
60446bc29b9SAdrian Hunter 
605c45c86ebSWang Nan static int record__synthesize(struct record *rec)
606c45c86ebSWang Nan {
607c45c86ebSWang Nan 	struct perf_session *session = rec->session;
608c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
609c45c86ebSWang Nan 	struct perf_data_file *file = &rec->file;
610c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
611c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
612c45c86ebSWang Nan 	int fd = perf_data_file__fd(file);
613c45c86ebSWang Nan 	int err = 0;
614c45c86ebSWang Nan 
615c45c86ebSWang Nan 	if (file->is_pipe) {
616c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
617c45c86ebSWang Nan 						   process_synthesized_event);
618c45c86ebSWang Nan 		if (err < 0) {
619c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
620c45c86ebSWang Nan 			goto out;
621c45c86ebSWang Nan 		}
622c45c86ebSWang Nan 
623c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
624c45c86ebSWang Nan 			/*
625c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
626c45c86ebSWang Nan 			 * there were no tracepoints so its not really
627c45c86ebSWang Nan 			 * an error, just that we don't need to
628c45c86ebSWang Nan 			 * synthesize anything.  We really have to
629c45c86ebSWang Nan 			 * return this more properly and also
630c45c86ebSWang Nan 			 * propagate errors that now are calling die()
631c45c86ebSWang Nan 			 */
632c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
633c45c86ebSWang Nan 								  process_synthesized_event);
634c45c86ebSWang Nan 			if (err <= 0) {
635c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
636c45c86ebSWang Nan 				goto out;
637c45c86ebSWang Nan 			}
638c45c86ebSWang Nan 			rec->bytes_written += err;
639c45c86ebSWang Nan 		}
640c45c86ebSWang Nan 	}
641c45c86ebSWang Nan 
64246bc29b9SAdrian Hunter 	err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
64346bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
64446bc29b9SAdrian Hunter 	if (err)
64546bc29b9SAdrian Hunter 		goto out;
64646bc29b9SAdrian Hunter 
647c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
648c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
649c45c86ebSWang Nan 					session, process_synthesized_event);
650c45c86ebSWang Nan 		if (err)
651c45c86ebSWang Nan 			goto out;
652c45c86ebSWang Nan 	}
653c45c86ebSWang Nan 
654c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
655c45c86ebSWang Nan 						 machine);
656c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
657c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
658c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
659c45c86ebSWang Nan 
660c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
661c45c86ebSWang Nan 					     machine);
662c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
663c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
664c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
665c45c86ebSWang Nan 
666c45c86ebSWang Nan 	if (perf_guest) {
667c45c86ebSWang Nan 		machines__process_guests(&session->machines,
668c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
669c45c86ebSWang Nan 	}
670c45c86ebSWang Nan 
671c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
672c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
673c45c86ebSWang Nan 					    opts->proc_map_timeout);
674c45c86ebSWang Nan out:
675c45c86ebSWang Nan 	return err;
676c45c86ebSWang Nan }
677c45c86ebSWang Nan 
6788c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
67986470930SIngo Molnar {
68057706abcSDavid Ahern 	int err;
68145604710SNamhyung Kim 	int status = 0;
6828b412664SPeter Zijlstra 	unsigned long waking = 0;
68346be604bSZhang, Yanmin 	const bool forks = argc > 0;
68423346f21SArnaldo Carvalho de Melo 	struct machine *machine;
68545694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
686b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
687f5fc1412SJiri Olsa 	struct perf_data_file *file = &rec->file;
688d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
6896dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
69042aa276fSNamhyung Kim 	int fd;
69186470930SIngo Molnar 
692d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
69333e49ea7SAndi Kleen 
69445604710SNamhyung Kim 	atexit(record__sig_exit);
695f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
696f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
697804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
698c0bdc1c4SWang Nan 
6993c1cb7e3SWang Nan 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
7002dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
7013c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
7025f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
7033c1cb7e3SWang Nan 		if (rec->switch_output)
7043c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
705c0bdc1c4SWang Nan 	} else {
7062dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
707c0bdc1c4SWang Nan 	}
708f5970550SPeter Zijlstra 
709b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(file, false, tool);
71094c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
711ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
712a9a70bbcSArnaldo Carvalho de Melo 		return -1;
713a9a70bbcSArnaldo Carvalho de Melo 	}
714a9a70bbcSArnaldo Carvalho de Melo 
71542aa276fSNamhyung Kim 	fd = perf_data_file__fd(file);
716d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
717d20deb64SArnaldo Carvalho de Melo 
7188c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
719330aa675SStephane Eranian 
720d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
7213e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
722f5fc1412SJiri Olsa 						    argv, file->is_pipe,
723735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
72435b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
72535b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
72645604710SNamhyung Kim 			status = err;
72735b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
728856e9660SPeter Zijlstra 		}
729856e9660SPeter Zijlstra 	}
730856e9660SPeter Zijlstra 
7318c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
7328d3eca20SDavid Ahern 		err = -1;
73345604710SNamhyung Kim 		goto out_child;
7348d3eca20SDavid Ahern 	}
73586470930SIngo Molnar 
7368690a2a7SWang Nan 	err = bpf__apply_obj_config();
7378690a2a7SWang Nan 	if (err) {
7388690a2a7SWang Nan 		char errbuf[BUFSIZ];
7398690a2a7SWang Nan 
7408690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
7418690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
7428690a2a7SWang Nan 			 errbuf);
7438690a2a7SWang Nan 		goto out_child;
7448690a2a7SWang Nan 	}
7458690a2a7SWang Nan 
746cca8482cSAdrian Hunter 	/*
747cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
748cca8482cSAdrian Hunter 	 * evlist.
749cca8482cSAdrian Hunter 	 */
750cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
751cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
752cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
753cca8482cSAdrian Hunter 	}
754cca8482cSAdrian Hunter 
7553e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
756a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
757a8bb559bSNamhyung Kim 
758f5fc1412SJiri Olsa 	if (file->is_pipe) {
75942aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
760529870e3STom Zanussi 		if (err < 0)
76145604710SNamhyung Kim 			goto out_child;
762563aecb2SJiri Olsa 	} else {
76342aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
764d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
76545604710SNamhyung Kim 			goto out_child;
766d5eed904SArnaldo Carvalho de Melo 	}
7677c6a1c65SPeter Zijlstra 
768d3665498SDavid Ahern 	if (!rec->no_buildid
769e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
770d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
771e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
7728d3eca20SDavid Ahern 		err = -1;
77345604710SNamhyung Kim 		goto out_child;
774e20960c0SRobert Richter 	}
775e20960c0SRobert Richter 
77634ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
777743eb868SArnaldo Carvalho de Melo 
778c45c86ebSWang Nan 	err = record__synthesize(rec);
779c45c86ebSWang Nan 	if (err < 0)
78045604710SNamhyung Kim 		goto out_child;
7818d3eca20SDavid Ahern 
782d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
78386470930SIngo Molnar 		struct sched_param param;
78486470930SIngo Molnar 
785d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
78686470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
7876beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
7888d3eca20SDavid Ahern 			err = -1;
78945604710SNamhyung Kim 			goto out_child;
79086470930SIngo Molnar 		}
79186470930SIngo Molnar 	}
79286470930SIngo Molnar 
793774cb499SJiri Olsa 	/*
794774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
795774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
796774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
797774cb499SJiri Olsa 	 */
7986619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
7993e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
800764e16a3SDavid Ahern 
801856e9660SPeter Zijlstra 	/*
802856e9660SPeter Zijlstra 	 * Let the child rip
803856e9660SPeter Zijlstra 	 */
804e803cf97SNamhyung Kim 	if (forks) {
805e5bed564SNamhyung Kim 		union perf_event *event;
806e5bed564SNamhyung Kim 
807e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
808e5bed564SNamhyung Kim 		if (event == NULL) {
809e5bed564SNamhyung Kim 			err = -ENOMEM;
810e5bed564SNamhyung Kim 			goto out_child;
811e5bed564SNamhyung Kim 		}
812e5bed564SNamhyung Kim 
813e803cf97SNamhyung Kim 		/*
814e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
815e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
816e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
817e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
818e803cf97SNamhyung Kim 		 */
819e5bed564SNamhyung Kim 		perf_event__synthesize_comm(tool, event,
820e803cf97SNamhyung Kim 					    rec->evlist->workload.pid,
821e803cf97SNamhyung Kim 					    process_synthesized_event,
822e803cf97SNamhyung Kim 					    machine);
823e5bed564SNamhyung Kim 		free(event);
824e803cf97SNamhyung Kim 
8253e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
826e803cf97SNamhyung Kim 	}
827856e9660SPeter Zijlstra 
8286619a53eSAndi Kleen 	if (opts->initial_delay) {
8296619a53eSAndi Kleen 		usleep(opts->initial_delay * 1000);
8306619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
8316619a53eSAndi Kleen 	}
8326619a53eSAndi Kleen 
8335f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
8343c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
835649c48a9SPeter Zijlstra 	for (;;) {
8369f065194SYang Shi 		unsigned long long hits = rec->samples;
83786470930SIngo Molnar 
8388c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
8395f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
8403c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
8418d3eca20SDavid Ahern 			err = -1;
84245604710SNamhyung Kim 			goto out_child;
8438d3eca20SDavid Ahern 		}
84486470930SIngo Molnar 
8452dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
8462dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
8475f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
8482dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
8495f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
8502dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
8512dd6d8a1SAdrian Hunter 				err = -1;
8522dd6d8a1SAdrian Hunter 				goto out_child;
8532dd6d8a1SAdrian Hunter 			}
8542dd6d8a1SAdrian Hunter 		}
8552dd6d8a1SAdrian Hunter 
8563c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
8573c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
8583c1cb7e3SWang Nan 
8593c1cb7e3SWang Nan 			if (!quiet)
8603c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
8613c1cb7e3SWang Nan 					waking);
8623c1cb7e3SWang Nan 			waking = 0;
8633c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
8643c1cb7e3SWang Nan 			if (fd < 0) {
8653c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
8663c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
8673c1cb7e3SWang Nan 				err = fd;
8683c1cb7e3SWang Nan 				goto out_child;
8693c1cb7e3SWang Nan 			}
8703c1cb7e3SWang Nan 		}
8713c1cb7e3SWang Nan 
872d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
8736dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
874649c48a9SPeter Zijlstra 				break;
875f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
876a515114fSJiri Olsa 			/*
877a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
878a515114fSJiri Olsa 			 * number of returned events and interrupt error.
879a515114fSJiri Olsa 			 */
880a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
88145604710SNamhyung Kim 				err = 0;
8828b412664SPeter Zijlstra 			waking++;
8836dcf45efSArnaldo Carvalho de Melo 
8846dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
8856dcf45efSArnaldo Carvalho de Melo 				draining = true;
8868b412664SPeter Zijlstra 		}
8878b412664SPeter Zijlstra 
888774cb499SJiri Olsa 		/*
889774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
890774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
891774cb499SJiri Olsa 		 * disable events in this case.
892774cb499SJiri Olsa 		 */
893602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
8945f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
8953e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
8962711926aSJiri Olsa 			disabled = true;
8972711926aSJiri Olsa 		}
8988b412664SPeter Zijlstra 	}
8995f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
9003c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
9018b412664SPeter Zijlstra 
902f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
90335550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
904f33cbe72SArnaldo Carvalho de Melo 		const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
905f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
906f33cbe72SArnaldo Carvalho de Melo 		err = -1;
90745604710SNamhyung Kim 		goto out_child;
908f33cbe72SArnaldo Carvalho de Melo 	}
909f33cbe72SArnaldo Carvalho de Melo 
910e3d59112SNamhyung Kim 	if (!quiet)
9118b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
91286470930SIngo Molnar 
91345604710SNamhyung Kim out_child:
91445604710SNamhyung Kim 	if (forks) {
91545604710SNamhyung Kim 		int exit_status;
91645604710SNamhyung Kim 
91745604710SNamhyung Kim 		if (!child_finished)
91845604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
91945604710SNamhyung Kim 
92045604710SNamhyung Kim 		wait(&exit_status);
92145604710SNamhyung Kim 
92245604710SNamhyung Kim 		if (err < 0)
92345604710SNamhyung Kim 			status = err;
92445604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
92545604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
92645604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
92745604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
92845604710SNamhyung Kim 	} else
92945604710SNamhyung Kim 		status = err;
93045604710SNamhyung Kim 
931e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
932e3d59112SNamhyung Kim 	rec->samples = 0;
933e3d59112SNamhyung Kim 
934ecfd7a9cSWang Nan 	if (!err) {
935ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
936e1ab48baSWang Nan 			record__finish_output(rec);
937ecfd7a9cSWang Nan 		} else {
938ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
939ecfd7a9cSWang Nan 			if (fd < 0) {
940ecfd7a9cSWang Nan 				status = fd;
941ecfd7a9cSWang Nan 				goto out_delete_session;
942ecfd7a9cSWang Nan 			}
943ecfd7a9cSWang Nan 		}
944ecfd7a9cSWang Nan 	}
94539d17dacSArnaldo Carvalho de Melo 
946e3d59112SNamhyung Kim 	if (!err && !quiet) {
947e3d59112SNamhyung Kim 		char samples[128];
948ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
949ecfd7a9cSWang Nan 					".<timestamp>" : "";
950e3d59112SNamhyung Kim 
951ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
952e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
953e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
954e3d59112SNamhyung Kim 		else
955e3d59112SNamhyung Kim 			samples[0] = '\0';
956e3d59112SNamhyung Kim 
957ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
958e3d59112SNamhyung Kim 			perf_data_file__size(file) / 1024.0 / 1024.0,
959ecfd7a9cSWang Nan 			file->path, postfix, samples);
960e3d59112SNamhyung Kim 	}
961e3d59112SNamhyung Kim 
96239d17dacSArnaldo Carvalho de Melo out_delete_session:
96339d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
96445604710SNamhyung Kim 	return status;
96586470930SIngo Molnar }
96686470930SIngo Molnar 
9670883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
96809b0fd45SJiri Olsa {
969aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
970a601fdffSJiri Olsa 
9710883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
97226d33022SJiri Olsa 
9730883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
97409b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
9750883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
9760883e820SArnaldo Carvalho de Melo }
9770883e820SArnaldo Carvalho de Melo 
9780883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
9790883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
9800883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
9810883e820SArnaldo Carvalho de Melo {
9820883e820SArnaldo Carvalho de Melo 	int ret;
9830883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
9840883e820SArnaldo Carvalho de Melo 
9850883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
9860883e820SArnaldo Carvalho de Melo 	if (unset) {
9870883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
9880883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
9890883e820SArnaldo Carvalho de Melo 		return 0;
9900883e820SArnaldo Carvalho de Melo 	}
9910883e820SArnaldo Carvalho de Melo 
9920883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
9930883e820SArnaldo Carvalho de Melo 	if (!ret) {
9940883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
9950883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
9960883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
9970883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
9980883e820SArnaldo Carvalho de Melo 	}
9990883e820SArnaldo Carvalho de Melo 
10000883e820SArnaldo Carvalho de Melo 	return ret;
100109b0fd45SJiri Olsa }
100209b0fd45SJiri Olsa 
1003c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
100409b0fd45SJiri Olsa 			       const char *arg,
100509b0fd45SJiri Olsa 			       int unset)
100609b0fd45SJiri Olsa {
10070883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
100826d33022SJiri Olsa }
100926d33022SJiri Olsa 
1010c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
101109b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
101209b0fd45SJiri Olsa 			 int unset __maybe_unused)
101309b0fd45SJiri Olsa {
10142ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1015c421e80bSKan Liang 
10162ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
101709b0fd45SJiri Olsa 
10182ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
10192ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1020eb853e80SJiri Olsa 
10212ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
102209b0fd45SJiri Olsa 	return 0;
102309b0fd45SJiri Olsa }
102409b0fd45SJiri Olsa 
1025eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1026eb853e80SJiri Olsa {
10277a29c087SNamhyung Kim 	struct record *rec = cb;
10287a29c087SNamhyung Kim 
10297a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
10307a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
10317a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
10327a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
10337a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
10347a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
10357a29c087SNamhyung Kim 			rec->no_buildid = true;
10367a29c087SNamhyung Kim 		else
10377a29c087SNamhyung Kim 			return -1;
10387a29c087SNamhyung Kim 		return 0;
10397a29c087SNamhyung Kim 	}
1040eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
10415a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
1042eb853e80SJiri Olsa 
1043eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
1044eb853e80SJiri Olsa }
1045eb853e80SJiri Olsa 
1046814c8c38SPeter Zijlstra struct clockid_map {
1047814c8c38SPeter Zijlstra 	const char *name;
1048814c8c38SPeter Zijlstra 	int clockid;
1049814c8c38SPeter Zijlstra };
1050814c8c38SPeter Zijlstra 
1051814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1052814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1053814c8c38SPeter Zijlstra 
1054814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1055814c8c38SPeter Zijlstra 
1056814c8c38SPeter Zijlstra 
1057814c8c38SPeter Zijlstra /*
1058814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1059814c8c38SPeter Zijlstra  */
1060814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1061814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1062814c8c38SPeter Zijlstra #endif
1063814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1064814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1065814c8c38SPeter Zijlstra #endif
1066814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1067814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1068814c8c38SPeter Zijlstra #endif
1069814c8c38SPeter Zijlstra 
1070814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1071814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1072814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1073814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1074814c8c38SPeter Zijlstra 
1075814c8c38SPeter Zijlstra 	/* available for some events */
1076814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1077814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1078814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1079814c8c38SPeter Zijlstra 
1080814c8c38SPeter Zijlstra 	/* available for the lazy */
1081814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1082814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1083814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1084814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1085814c8c38SPeter Zijlstra 
1086814c8c38SPeter Zijlstra 	CLOCKID_END,
1087814c8c38SPeter Zijlstra };
1088814c8c38SPeter Zijlstra 
1089814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1090814c8c38SPeter Zijlstra {
1091814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1092814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1093814c8c38SPeter Zijlstra 	const char *ostr = str;
1094814c8c38SPeter Zijlstra 
1095814c8c38SPeter Zijlstra 	if (unset) {
1096814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1097814c8c38SPeter Zijlstra 		return 0;
1098814c8c38SPeter Zijlstra 	}
1099814c8c38SPeter Zijlstra 
1100814c8c38SPeter Zijlstra 	/* no arg passed */
1101814c8c38SPeter Zijlstra 	if (!str)
1102814c8c38SPeter Zijlstra 		return 0;
1103814c8c38SPeter Zijlstra 
1104814c8c38SPeter Zijlstra 	/* no setting it twice */
1105814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1106814c8c38SPeter Zijlstra 		return -1;
1107814c8c38SPeter Zijlstra 
1108814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1109814c8c38SPeter Zijlstra 
1110814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1111814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1112814c8c38SPeter Zijlstra 		return 0;
1113814c8c38SPeter Zijlstra 
1114814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1115814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1116814c8c38SPeter Zijlstra 		str += 6;
1117814c8c38SPeter Zijlstra 
1118814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1119814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1120814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1121814c8c38SPeter Zijlstra 			return 0;
1122814c8c38SPeter Zijlstra 		}
1123814c8c38SPeter Zijlstra 	}
1124814c8c38SPeter Zijlstra 
1125814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1126814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1127814c8c38SPeter Zijlstra 	return -1;
1128814c8c38SPeter Zijlstra }
1129814c8c38SPeter Zijlstra 
1130e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1131e9db1310SAdrian Hunter 				    const char *str,
1132e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1133e9db1310SAdrian Hunter {
1134e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1135e9db1310SAdrian Hunter 	char *s, *p;
1136e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1137e9db1310SAdrian Hunter 	int ret;
1138e9db1310SAdrian Hunter 
1139e9db1310SAdrian Hunter 	if (!str)
1140e9db1310SAdrian Hunter 		return -EINVAL;
1141e9db1310SAdrian Hunter 
1142e9db1310SAdrian Hunter 	s = strdup(str);
1143e9db1310SAdrian Hunter 	if (!s)
1144e9db1310SAdrian Hunter 		return -ENOMEM;
1145e9db1310SAdrian Hunter 
1146e9db1310SAdrian Hunter 	p = strchr(s, ',');
1147e9db1310SAdrian Hunter 	if (p)
1148e9db1310SAdrian Hunter 		*p = '\0';
1149e9db1310SAdrian Hunter 
1150e9db1310SAdrian Hunter 	if (*s) {
1151e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1152e9db1310SAdrian Hunter 		if (ret)
1153e9db1310SAdrian Hunter 			goto out_free;
1154e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1155e9db1310SAdrian Hunter 	}
1156e9db1310SAdrian Hunter 
1157e9db1310SAdrian Hunter 	if (!p) {
1158e9db1310SAdrian Hunter 		ret = 0;
1159e9db1310SAdrian Hunter 		goto out_free;
1160e9db1310SAdrian Hunter 	}
1161e9db1310SAdrian Hunter 
1162e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1163e9db1310SAdrian Hunter 	if (ret)
1164e9db1310SAdrian Hunter 		goto out_free;
1165e9db1310SAdrian Hunter 
1166e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1167e9db1310SAdrian Hunter 
1168e9db1310SAdrian Hunter out_free:
1169e9db1310SAdrian Hunter 	free(s);
1170e9db1310SAdrian Hunter 	return ret;
1171e9db1310SAdrian Hunter }
1172e9db1310SAdrian Hunter 
1173e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
117486470930SIngo Molnar 	"perf record [<options>] [<command>]",
117586470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
117686470930SIngo Molnar 	NULL
117786470930SIngo Molnar };
1178e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
117986470930SIngo Molnar 
1180d20deb64SArnaldo Carvalho de Melo /*
11818c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
11828c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1183d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1184d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1185d20deb64SArnaldo Carvalho de Melo  *
1186d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1187d20deb64SArnaldo Carvalho de Melo  *
1188d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1189d20deb64SArnaldo Carvalho de Melo  */
11908c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1191d20deb64SArnaldo Carvalho de Melo 	.opts = {
11928affc2b8SAndi Kleen 		.sample_time	     = true,
1193d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1194d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1195d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1196447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1197d1cb9fceSNamhyung Kim 		.target		     = {
1198d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
11993aa5939dSAdrian Hunter 			.default_per_cpu = true,
1200d1cb9fceSNamhyung Kim 		},
12019d9cad76SKan Liang 		.proc_map_timeout     = 500,
1202d20deb64SArnaldo Carvalho de Melo 	},
1203e3d59112SNamhyung Kim 	.tool = {
1204e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1205e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1206cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1207e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1208e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1209e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1210cca8482cSAdrian Hunter 		.ordered_events	= true,
1211e3d59112SNamhyung Kim 	},
1212d20deb64SArnaldo Carvalho de Melo };
12137865e817SFrederic Weisbecker 
121476a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
121576a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
121661eaa3beSArnaldo Carvalho de Melo 
1217d20deb64SArnaldo Carvalho de Melo /*
1218d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1219d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1220b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1221d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1222d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1223d20deb64SArnaldo Carvalho de Melo  */
1224e5b2c207SNamhyung Kim struct option __record_options[] = {
1225d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
122686470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1227f120f9d5SJiri Olsa 		     parse_events_option),
1228d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1229c171b552SLi Zefan 		     "event filter", parse_filter),
12304ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
12314ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
12324ba1faa1SWang Nan 			   exclude_perf),
1233bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1234d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1235bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1236d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1237d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
123886470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1239509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1240acac03faSKirill Smelkov 		    "collect data without buffering"),
1241d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1242daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1243bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
124486470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1245bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1246c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1247d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1248f5fc1412SJiri Olsa 	OPT_STRING('o', "output", &record.file.path, "file",
124986470930SIngo Molnar 		    "output file name"),
125069e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
125169e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
12522e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
1253d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1254e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1255e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1256e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1257d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
125843bece79SLin Ming 		    "put the counters into a counter group"),
12592ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
126009b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
126109b0fd45SJiri Olsa 			   &record_callchain_opt),
126209b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
126376a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
126409b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1265c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
12663da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1267b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1268d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1269649c48a9SPeter Zijlstra 		    "per thread counts"),
127056100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
12713abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
12723abebc55SAdrian Hunter 			&record.opts.sample_time_set,
12733abebc55SAdrian Hunter 			"Record the sample timestamps"),
127456100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1275d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1276649c48a9SPeter Zijlstra 		    "don't sample"),
1277d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1278d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1279a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1280d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1281d2db9a98SWang Nan 			&record.no_buildid_set,
1282baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1283d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1284023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1285023695d9SStephane Eranian 		     parse_cgroups),
1286a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
12876619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1288bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1289bea03405SNamhyung Kim 		   "user to profile"),
1290a5aabdacSStephane Eranian 
1291a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1292a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1293a5aabdacSStephane Eranian 		     parse_branch_stack),
1294a5aabdacSStephane Eranian 
1295a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1296a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1297bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
129805484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
129905484298SAndi Kleen 		    "sample by weight (on special events only)"),
1300475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1301475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
13023aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
13033aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1304bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1305bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1306bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
130785c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
130885c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1309814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1310814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1311814c8c38SPeter Zijlstra 	parse_clockid),
13122dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
13132dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
13149d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
13159d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1316b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1317b757bb09SAdrian Hunter 		    "Record context switch events"),
131885723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
131985723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
132085723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
132185723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
132285723885SJiri Olsa 			 "Configure all used events to run in user space.",
132385723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
132471dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
132571dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
132671dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
132771dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
13287efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
13297efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
13306156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
13316156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1332ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1333ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
13343c1cb7e3SWang Nan 	OPT_BOOLEAN(0, "switch-output", &record.switch_output,
13353c1cb7e3SWang Nan 		    "Switch output when receive SIGUSR2"),
133686470930SIngo Molnar 	OPT_END()
133786470930SIngo Molnar };
133886470930SIngo Molnar 
1339e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1340e5b2c207SNamhyung Kim 
13411d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
134286470930SIngo Molnar {
1343ef149c25SAdrian Hunter 	int err;
13448c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
134516ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
134686470930SIngo Molnar 
134748e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
134848e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
134948e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
135048e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
135148e1cab1SWang Nan # undef set_nobuild
135248e1cab1SWang Nan #endif
135348e1cab1SWang Nan 
13547efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
13557efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
13567efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
13577efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
13587efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
13597efe0e03SHe Kuang # else
13607efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
13617efe0e03SHe Kuang # endif
13627efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
13637efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
13647efe0e03SHe Kuang # undef set_nobuild
13657efe0e03SHe Kuang # undef REASON
13667efe0e03SHe Kuang #endif
13677efe0e03SHe Kuang 
13683e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
13693e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1370361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1371361c99a6SArnaldo Carvalho de Melo 
1372eb853e80SJiri Olsa 	perf_config(perf_record_config, rec);
1373eb853e80SJiri Olsa 
1374bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1375a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1376602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1377bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
137886470930SIngo Molnar 
1379bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1380c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1381c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1382c7118369SNamhyung Kim 
1383023695d9SStephane Eranian 	}
1384b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1385b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1386c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1387c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1388c7118369SNamhyung Kim 		return -EINVAL;
1389b757bb09SAdrian Hunter 	}
1390023695d9SStephane Eranian 
1391eca857abSWang Nan 	if (rec->switch_output)
1392eca857abSWang Nan 		rec->timestamp_filename = true;
1393eca857abSWang Nan 
1394ef149c25SAdrian Hunter 	if (!rec->itr) {
1395ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1396ef149c25SAdrian Hunter 		if (err)
1397ef149c25SAdrian Hunter 			return err;
1398ef149c25SAdrian Hunter 	}
1399ef149c25SAdrian Hunter 
14002dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
14012dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
14022dd6d8a1SAdrian Hunter 	if (err)
14032dd6d8a1SAdrian Hunter 		return err;
14042dd6d8a1SAdrian Hunter 
1405d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1406d7888573SWang Nan 	if (err) {
1407d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1408d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1409d7888573SWang Nan 			 errbuf);
1410d7888573SWang Nan 		return err;
1411d7888573SWang Nan 	}
1412d7888573SWang Nan 
1413ef149c25SAdrian Hunter 	err = -ENOMEM;
1414ef149c25SAdrian Hunter 
14150a7e6d1bSNamhyung Kim 	symbol__init(NULL);
1416baa2f6ceSArnaldo Carvalho de Melo 
1417ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1418646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1419646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1420ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1421646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1422646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1423646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1424646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1425646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1426ec80fde7SArnaldo Carvalho de Melo 
14270c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
1428a1ac1d3cSStephane Eranian 		disable_buildid_cache();
14290c1d46a8SWang Nan 	} else if (rec->switch_output) {
14300c1d46a8SWang Nan 		/*
14310c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
14320c1d46a8SWang Nan 		 * generation by default to reduce data file switching
14330c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
14340c1d46a8SWang Nan 		 * explicitly using
14350c1d46a8SWang Nan 		 *
14360c1d46a8SWang Nan 		 *  perf record --signal-trigger --no-no-buildid \
14370c1d46a8SWang Nan 		 *              --no-no-buildid-cache
14380c1d46a8SWang Nan 		 *
14390c1d46a8SWang Nan 		 * Following code equals to:
14400c1d46a8SWang Nan 		 *
14410c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
14420c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
14430c1d46a8SWang Nan 		 *         disable_buildid_cache();
14440c1d46a8SWang Nan 		 */
14450c1d46a8SWang Nan 		bool disable = true;
14460c1d46a8SWang Nan 
14470c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
14480c1d46a8SWang Nan 			disable = false;
14490c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
14500c1d46a8SWang Nan 			disable = false;
14510c1d46a8SWang Nan 		if (disable) {
14520c1d46a8SWang Nan 			rec->no_buildid = true;
14530c1d46a8SWang Nan 			rec->no_buildid_cache = true;
14540c1d46a8SWang Nan 			disable_buildid_cache();
14550c1d46a8SWang Nan 		}
14560c1d46a8SWang Nan 	}
1457655000e7SArnaldo Carvalho de Melo 
14583e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
14593e2be2daSArnaldo Carvalho de Melo 	    perf_evlist__add_default(rec->evlist) < 0) {
146069aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
146169aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1462bbd36e5eSPeter Zijlstra 	}
146386470930SIngo Molnar 
146469e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
146569e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
146669e7e5b0SAdrian Hunter 
1467602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
146816ad2ffbSNamhyung Kim 	if (err) {
1469602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
147016ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
147116ad2ffbSNamhyung Kim 	}
14724bd0f2d2SNamhyung Kim 
1473602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
147416ad2ffbSNamhyung Kim 	if (err) {
147516ad2ffbSNamhyung Kim 		int saved_errno = errno;
147616ad2ffbSNamhyung Kim 
1477602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
14783780f488SNamhyung Kim 		ui__error("%s", errbuf);
147916ad2ffbSNamhyung Kim 
148016ad2ffbSNamhyung Kim 		err = -saved_errno;
14818fa60e1fSNamhyung Kim 		goto out_symbol_exit;
148216ad2ffbSNamhyung Kim 	}
14830d37aa34SArnaldo Carvalho de Melo 
148416ad2ffbSNamhyung Kim 	err = -ENOMEM;
14853e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1486dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
148769aad6f1SArnaldo Carvalho de Melo 
1488ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1489ef149c25SAdrian Hunter 	if (err)
1490ef149c25SAdrian Hunter 		goto out_symbol_exit;
1491ef149c25SAdrian Hunter 
14926156681bSNamhyung Kim 	/*
14936156681bSNamhyung Kim 	 * We take all buildids when the file contains
14946156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
14956156681bSNamhyung Kim 	 * trace because it would take too long.
14966156681bSNamhyung Kim 	 */
14976156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
14986156681bSNamhyung Kim 		rec->buildid_all = true;
14996156681bSNamhyung Kim 
1500b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
150139d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
150203ad9747SArnaldo Carvalho de Melo 		goto out_symbol_exit;
15037e4ff9e3SMike Galbraith 	}
15047e4ff9e3SMike Galbraith 
1505d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1506d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
150745604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1508d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1509ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
151039d17dacSArnaldo Carvalho de Melo 	return err;
151186470930SIngo Molnar }
15122dd6d8a1SAdrian Hunter 
15132dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
15142dd6d8a1SAdrian Hunter {
15155f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
15165f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
15172dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
15185f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
15195f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
15205f9cf599SWang Nan 	}
15213c1cb7e3SWang Nan 
15223c1cb7e3SWang Nan 	if (trigger_is_ready(&switch_output_trigger))
15233c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
15242dd6d8a1SAdrian Hunter }
1525