xref: /openbmc/linux/tools/perf/builtin-record.c (revision d3dbf43c56f9176be325ce1cc72a44c8d3c210dc)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
286470930SIngo Molnar /*
386470930SIngo Molnar  * builtin-record.c
486470930SIngo Molnar  *
586470930SIngo Molnar  * Builtin record command: Record the profile of a workload
686470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
786470930SIngo Molnar  * later analysis via perf report.
886470930SIngo Molnar  */
986470930SIngo Molnar #include "builtin.h"
1086470930SIngo Molnar 
1186470930SIngo Molnar #include "perf.h"
1286470930SIngo Molnar 
136122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1486470930SIngo Molnar #include "util/util.h"
154b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1686470930SIngo Molnar #include "util/parse-events.h"
1741840d21STaeung Song #include "util/config.h"
1886470930SIngo Molnar 
198f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
20f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
217c6a1c65SPeter Zijlstra #include "util/header.h"
2266e274f3SFrederic Weisbecker #include "util/event.h"
23361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2469aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
258f28827aSFrederic Weisbecker #include "util/debug.h"
265d8bb1ecSMathieu Poirier #include "util/drv_configs.h"
2794c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2845694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
298d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
30a12b51c4SPaul Mackerras #include "util/cpumap.h"
31fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
32f5fc1412SJiri Olsa #include "util/data.h"
33bcc84ec6SStephane Eranian #include "util/perf_regs.h"
34ef149c25SAdrian Hunter #include "util/auxtrace.h"
3546bc29b9SAdrian Hunter #include "util/tsc.h"
36f00898f4SAndi Kleen #include "util/parse-branch-options.h"
37bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3871dc2326SWang Nan #include "util/llvm-utils.h"
398690a2a7SWang Nan #include "util/bpf-loader.h"
405f9cf599SWang Nan #include "util/trigger.h"
41a074865eSWang Nan #include "util/perf-hooks.h"
42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
44d8871ea7SWang Nan #include "asm/bug.h"
457c6a1c65SPeter Zijlstra 
46a43783aeSArnaldo Carvalho de Melo #include <errno.h>
47fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
484208735dSArnaldo Carvalho de Melo #include <poll.h>
4986470930SIngo Molnar #include <unistd.h>
5086470930SIngo Molnar #include <sched.h>
519607ad3aSArnaldo Carvalho de Melo #include <signal.h>
52a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
534208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
542d11c650SWang Nan #include <asm/bug.h>
550693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
5678da39faSBernhard Rosenkraenzer 
571b43b704SJiri Olsa struct switch_output {
58dc0c6127SJiri Olsa 	bool		 enabled;
591b43b704SJiri Olsa 	bool		 signal;
60dc0c6127SJiri Olsa 	unsigned long	 size;
61bfacbe3bSJiri Olsa 	unsigned long	 time;
62cb4e1ebbSJiri Olsa 	const char	*str;
63cb4e1ebbSJiri Olsa 	bool		 set;
641b43b704SJiri Olsa };
651b43b704SJiri Olsa 
668c6f45a7SArnaldo Carvalho de Melo struct record {
6745694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
68b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
69d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
708ceb41d7SJiri Olsa 	struct perf_data	data;
71ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
72d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
73d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
74d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
75d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
76d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
77d2db9a98SWang Nan 	bool			no_buildid_set;
78d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
79d2db9a98SWang Nan 	bool			no_buildid_cache_set;
806156681bSNamhyung Kim 	bool			buildid_all;
81ecfd7a9cSWang Nan 	bool			timestamp_filename;
821b43b704SJiri Olsa 	struct switch_output	switch_output;
839f065194SYang Shi 	unsigned long long	samples;
840f82ebc4SArnaldo Carvalho de Melo };
8586470930SIngo Molnar 
86dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
87dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
88dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
89dc0c6127SJiri Olsa 
90dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
91dc0c6127SJiri Olsa {
92dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
93dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
94dc0c6127SJiri Olsa }
95dc0c6127SJiri Olsa 
96dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
97dc0c6127SJiri Olsa {
98dc0c6127SJiri Olsa 	return rec->switch_output.size &&
99dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
100dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
101dc0c6127SJiri Olsa }
102dc0c6127SJiri Olsa 
103bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
104bfacbe3bSJiri Olsa {
105bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
106bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
107bfacbe3bSJiri Olsa }
108bfacbe3bSJiri Olsa 
1098c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
110f5970550SPeter Zijlstra {
1118ceb41d7SJiri Olsa 	if (perf_data__write(rec->session->data, bf, size) < 0) {
1124f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1138d3eca20SDavid Ahern 		return -1;
1148d3eca20SDavid Ahern 	}
115f5970550SPeter Zijlstra 
116cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
117dc0c6127SJiri Olsa 
118dc0c6127SJiri Olsa 	if (switch_output_size(rec))
119dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
120dc0c6127SJiri Olsa 
1218d3eca20SDavid Ahern 	return 0;
122f5970550SPeter Zijlstra }
123f5970550SPeter Zijlstra 
12445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
125d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
1261d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
1271d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
128234fbbf5SArnaldo Carvalho de Melo {
1298c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
1308c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
131234fbbf5SArnaldo Carvalho de Melo }
132234fbbf5SArnaldo Carvalho de Melo 
133d37f1586SArnaldo Carvalho de Melo static int record__pushfn(void *to, void *bf, size_t size)
134d37f1586SArnaldo Carvalho de Melo {
135d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
136d37f1586SArnaldo Carvalho de Melo 
137d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
138d37f1586SArnaldo Carvalho de Melo 	return record__write(rec, bf, size);
139d37f1586SArnaldo Carvalho de Melo }
140d37f1586SArnaldo Carvalho de Melo 
1412dd6d8a1SAdrian Hunter static volatile int done;
1422dd6d8a1SAdrian Hunter static volatile int signr = -1;
1432dd6d8a1SAdrian Hunter static volatile int child_finished;
144c0bdc1c4SWang Nan 
1452dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1462dd6d8a1SAdrian Hunter {
1472dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1482dd6d8a1SAdrian Hunter 		child_finished = 1;
1492dd6d8a1SAdrian Hunter 	else
1502dd6d8a1SAdrian Hunter 		signr = sig;
1512dd6d8a1SAdrian Hunter 
1522dd6d8a1SAdrian Hunter 	done = 1;
1532dd6d8a1SAdrian Hunter }
1542dd6d8a1SAdrian Hunter 
155a074865eSWang Nan static void sigsegv_handler(int sig)
156a074865eSWang Nan {
157a074865eSWang Nan 	perf_hooks__recover();
158a074865eSWang Nan 	sighandler_dump_stack(sig);
159a074865eSWang Nan }
160a074865eSWang Nan 
1612dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1622dd6d8a1SAdrian Hunter {
1632dd6d8a1SAdrian Hunter 	if (signr == -1)
1642dd6d8a1SAdrian Hunter 		return;
1652dd6d8a1SAdrian Hunter 
1662dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1672dd6d8a1SAdrian Hunter 	raise(signr);
1682dd6d8a1SAdrian Hunter }
1692dd6d8a1SAdrian Hunter 
170e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
171e31f0d01SAdrian Hunter 
172ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
173ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
174ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
175ef149c25SAdrian Hunter {
176ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
1778ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
178ef149c25SAdrian Hunter 	size_t padding;
179ef149c25SAdrian Hunter 	u8 pad[8] = {0};
180ef149c25SAdrian Hunter 
1818ceb41d7SJiri Olsa 	if (!perf_data__is_pipe(data)) {
18299fa2984SAdrian Hunter 		off_t file_offset;
1838ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
18499fa2984SAdrian Hunter 		int err;
18599fa2984SAdrian Hunter 
18699fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
18799fa2984SAdrian Hunter 		if (file_offset == -1)
18899fa2984SAdrian Hunter 			return -1;
18999fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
19099fa2984SAdrian Hunter 						     event, file_offset);
19199fa2984SAdrian Hunter 		if (err)
19299fa2984SAdrian Hunter 			return err;
19399fa2984SAdrian Hunter 	}
19499fa2984SAdrian Hunter 
195ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
196ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
197ef149c25SAdrian Hunter 	if (padding)
198ef149c25SAdrian Hunter 		padding = 8 - padding;
199ef149c25SAdrian Hunter 
200ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
201ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
202ef149c25SAdrian Hunter 	if (len2)
203ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
204ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
205ef149c25SAdrian Hunter 
206ef149c25SAdrian Hunter 	return 0;
207ef149c25SAdrian Hunter }
208ef149c25SAdrian Hunter 
209ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
210ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
211ef149c25SAdrian Hunter {
212ef149c25SAdrian Hunter 	int ret;
213ef149c25SAdrian Hunter 
214ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
215ef149c25SAdrian Hunter 				  record__process_auxtrace);
216ef149c25SAdrian Hunter 	if (ret < 0)
217ef149c25SAdrian Hunter 		return ret;
218ef149c25SAdrian Hunter 
219ef149c25SAdrian Hunter 	if (ret)
220ef149c25SAdrian Hunter 		rec->samples++;
221ef149c25SAdrian Hunter 
222ef149c25SAdrian Hunter 	return 0;
223ef149c25SAdrian Hunter }
224ef149c25SAdrian Hunter 
2252dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2262dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2272dd6d8a1SAdrian Hunter {
2282dd6d8a1SAdrian Hunter 	int ret;
2292dd6d8a1SAdrian Hunter 
2302dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2312dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2322dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2332dd6d8a1SAdrian Hunter 	if (ret < 0)
2342dd6d8a1SAdrian Hunter 		return ret;
2352dd6d8a1SAdrian Hunter 
2362dd6d8a1SAdrian Hunter 	if (ret)
2372dd6d8a1SAdrian Hunter 		rec->samples++;
2382dd6d8a1SAdrian Hunter 
2392dd6d8a1SAdrian Hunter 	return 0;
2402dd6d8a1SAdrian Hunter }
2412dd6d8a1SAdrian Hunter 
2422dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2432dd6d8a1SAdrian Hunter {
2442dd6d8a1SAdrian Hunter 	int i;
2452dd6d8a1SAdrian Hunter 	int rc = 0;
2462dd6d8a1SAdrian Hunter 
2472dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2482dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2492dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2502dd6d8a1SAdrian Hunter 
2512dd6d8a1SAdrian Hunter 		if (!mm->base)
2522dd6d8a1SAdrian Hunter 			continue;
2532dd6d8a1SAdrian Hunter 
2542dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2552dd6d8a1SAdrian Hunter 			rc = -1;
2562dd6d8a1SAdrian Hunter 			goto out;
2572dd6d8a1SAdrian Hunter 		}
2582dd6d8a1SAdrian Hunter 	}
2592dd6d8a1SAdrian Hunter out:
2602dd6d8a1SAdrian Hunter 	return rc;
2612dd6d8a1SAdrian Hunter }
2622dd6d8a1SAdrian Hunter 
2632dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2642dd6d8a1SAdrian Hunter {
2652dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2662dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2675f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
2682dd6d8a1SAdrian Hunter 	} else {
2695f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
2705f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
2715f9cf599SWang Nan 		else
2725f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
2732dd6d8a1SAdrian Hunter 	}
2742dd6d8a1SAdrian Hunter }
2752dd6d8a1SAdrian Hunter 
276e31f0d01SAdrian Hunter #else
277e31f0d01SAdrian Hunter 
278e31f0d01SAdrian Hunter static inline
279e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
280e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
281e31f0d01SAdrian Hunter {
282e31f0d01SAdrian Hunter 	return 0;
283e31f0d01SAdrian Hunter }
284e31f0d01SAdrian Hunter 
2852dd6d8a1SAdrian Hunter static inline
2862dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2872dd6d8a1SAdrian Hunter {
2882dd6d8a1SAdrian Hunter }
2892dd6d8a1SAdrian Hunter 
2902dd6d8a1SAdrian Hunter static inline
2912dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2922dd6d8a1SAdrian Hunter {
2932dd6d8a1SAdrian Hunter 	return 0;
2942dd6d8a1SAdrian Hunter }
2952dd6d8a1SAdrian Hunter 
296e31f0d01SAdrian Hunter #endif
297e31f0d01SAdrian Hunter 
298cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
299cda57a8cSWang Nan 			       struct perf_evlist *evlist)
300cda57a8cSWang Nan {
301cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
302cda57a8cSWang Nan 	char msg[512];
303cda57a8cSWang Nan 
304cda57a8cSWang Nan 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
305cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
306cda57a8cSWang Nan 				 opts->auxtrace_snapshot_mode) < 0) {
307cda57a8cSWang Nan 		if (errno == EPERM) {
308cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
309cda57a8cSWang Nan 			       "Consider increasing "
310cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
311cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
312cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
313cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
314cda57a8cSWang Nan 			return -errno;
315cda57a8cSWang Nan 		} else {
316cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
317c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
318cda57a8cSWang Nan 			if (errno)
319cda57a8cSWang Nan 				return -errno;
320cda57a8cSWang Nan 			else
321cda57a8cSWang Nan 				return -EINVAL;
322cda57a8cSWang Nan 		}
323cda57a8cSWang Nan 	}
324cda57a8cSWang Nan 	return 0;
325cda57a8cSWang Nan }
326cda57a8cSWang Nan 
327cda57a8cSWang Nan static int record__mmap(struct record *rec)
328cda57a8cSWang Nan {
329cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
330cda57a8cSWang Nan }
331cda57a8cSWang Nan 
3328c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
333dd7927f4SArnaldo Carvalho de Melo {
334d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
3356a4bb04cSJiri Olsa 	struct perf_evsel *pos;
336d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
337d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
338b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
3395d8bb1ecSMathieu Poirier 	struct perf_evsel_config_term *err_term;
3408d3eca20SDavid Ahern 	int rc = 0;
341dd7927f4SArnaldo Carvalho de Melo 
342*d3dbf43cSArnaldo Carvalho de Melo 	/*
343*d3dbf43cSArnaldo Carvalho de Melo 	 * For initial_delay we need to add a dummy event so that we can track
344*d3dbf43cSArnaldo Carvalho de Melo 	 * PERF_RECORD_MMAP while we wait for the initial delay to enable the
345*d3dbf43cSArnaldo Carvalho de Melo 	 * real events, the ones asked by the user.
346*d3dbf43cSArnaldo Carvalho de Melo 	 */
347*d3dbf43cSArnaldo Carvalho de Melo 	if (opts->initial_delay) {
348*d3dbf43cSArnaldo Carvalho de Melo 		if (perf_evlist__add_dummy(evlist))
349*d3dbf43cSArnaldo Carvalho de Melo 			return -ENOMEM;
350*d3dbf43cSArnaldo Carvalho de Melo 
351*d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__first(evlist);
352*d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 0;
353*d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__last(evlist);
354*d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 1;
355*d3dbf43cSArnaldo Carvalho de Melo 		pos->attr.enable_on_exec = 1;
356*d3dbf43cSArnaldo Carvalho de Melo 	}
357*d3dbf43cSArnaldo Carvalho de Melo 
358e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
359cac21425SJiri Olsa 
360e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
3613da297a6SIngo Molnar try_again:
362d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
36356e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
364bb963e16SNamhyung Kim 				if (verbose > 0)
365c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3663da297a6SIngo Molnar 				goto try_again;
3673da297a6SIngo Molnar 			}
368ca6a4258SDavid Ahern 
36956e52e85SArnaldo Carvalho de Melo 			rc = -errno;
37056e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
37156e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
37256e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3738d3eca20SDavid Ahern 			goto out;
3747c6a1c65SPeter Zijlstra 		}
3757c6a1c65SPeter Zijlstra 	}
3767c6a1c65SPeter Zijlstra 
37723d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
37862d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
37923d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
380c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
3818d3eca20SDavid Ahern 		rc = -1;
3828d3eca20SDavid Ahern 		goto out;
3830a102479SFrederic Weisbecker 	}
3840a102479SFrederic Weisbecker 
3855d8bb1ecSMathieu Poirier 	if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
38662d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set config \"%s\" on event %s with %d (%s)\n",
3875d8bb1ecSMathieu Poirier 		      err_term->val.drv_cfg, perf_evsel__name(pos), errno,
3885d8bb1ecSMathieu Poirier 		      str_error_r(errno, msg, sizeof(msg)));
3895d8bb1ecSMathieu Poirier 		rc = -1;
3905d8bb1ecSMathieu Poirier 		goto out;
3915d8bb1ecSMathieu Poirier 	}
3925d8bb1ecSMathieu Poirier 
393cda57a8cSWang Nan 	rc = record__mmap(rec);
394cda57a8cSWang Nan 	if (rc)
3958d3eca20SDavid Ahern 		goto out;
3960a27d7f9SArnaldo Carvalho de Melo 
397a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3987b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3998d3eca20SDavid Ahern out:
4008d3eca20SDavid Ahern 	return rc;
401a91e5431SArnaldo Carvalho de Melo }
402a91e5431SArnaldo Carvalho de Melo 
403e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
404e3d59112SNamhyung Kim 				union perf_event *event,
405e3d59112SNamhyung Kim 				struct perf_sample *sample,
406e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
407e3d59112SNamhyung Kim 				struct machine *machine)
408e3d59112SNamhyung Kim {
409e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
410e3d59112SNamhyung Kim 
411e3d59112SNamhyung Kim 	rec->samples++;
412e3d59112SNamhyung Kim 
413e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
414e3d59112SNamhyung Kim }
415e3d59112SNamhyung Kim 
4168c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
4176122e4e4SArnaldo Carvalho de Melo {
4188ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
419f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
4206122e4e4SArnaldo Carvalho de Melo 
4218ceb41d7SJiri Olsa 	if (data->size == 0)
4229f591fd7SArnaldo Carvalho de Melo 		return 0;
4239f591fd7SArnaldo Carvalho de Melo 
42400dc8657SNamhyung Kim 	/*
42500dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
42600dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
42700dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
42800dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
42900dc8657SNamhyung Kim 	 *
43000dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
43100dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
43200dc8657SNamhyung Kim 	 */
43300dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
43400dc8657SNamhyung Kim 
4356156681bSNamhyung Kim 	/*
4366156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
4376156681bSNamhyung Kim 	 * so no need to process samples.
4386156681bSNamhyung Kim 	 */
4396156681bSNamhyung Kim 	if (rec->buildid_all)
4406156681bSNamhyung Kim 		rec->tool.sample = NULL;
4416156681bSNamhyung Kim 
442b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
4436122e4e4SArnaldo Carvalho de Melo }
4446122e4e4SArnaldo Carvalho de Melo 
4458115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
446a1645ce1SZhang, Yanmin {
447a1645ce1SZhang, Yanmin 	int err;
44845694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
449a1645ce1SZhang, Yanmin 	/*
450a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
451a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
452a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
453a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
454a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
455a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
456a1645ce1SZhang, Yanmin 	 */
45745694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
458743eb868SArnaldo Carvalho de Melo 					     machine);
459a1645ce1SZhang, Yanmin 	if (err < 0)
460a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
46123346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
462a1645ce1SZhang, Yanmin 
463a1645ce1SZhang, Yanmin 	/*
464a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
465a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
466a1645ce1SZhang, Yanmin 	 */
46745694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4680ae617beSAdrian Hunter 						 machine);
469a1645ce1SZhang, Yanmin 	if (err < 0)
470a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
47123346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
472a1645ce1SZhang, Yanmin }
473a1645ce1SZhang, Yanmin 
47498402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
47598402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
47698402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
47798402807SFrederic Weisbecker };
47898402807SFrederic Weisbecker 
479a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
480a4ea0ec4SWang Nan 				    bool backward)
48198402807SFrederic Weisbecker {
482dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4830e2e63ddSPeter Zijlstra 	int i;
4848d3eca20SDavid Ahern 	int rc = 0;
485a4ea0ec4SWang Nan 	struct perf_mmap *maps;
48698402807SFrederic Weisbecker 
487cb21686bSWang Nan 	if (!evlist)
488cb21686bSWang Nan 		return 0;
489ef149c25SAdrian Hunter 
490b2cb615dSWang Nan 	maps = backward ? evlist->backward_mmap : evlist->mmap;
491a4ea0ec4SWang Nan 	if (!maps)
492a4ea0ec4SWang Nan 		return 0;
493cb21686bSWang Nan 
49454cc54deSWang Nan 	if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
49554cc54deSWang Nan 		return 0;
49654cc54deSWang Nan 
497a4ea0ec4SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
498a4ea0ec4SWang Nan 		struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
499a4ea0ec4SWang Nan 
500a4ea0ec4SWang Nan 		if (maps[i].base) {
501d37f1586SArnaldo Carvalho de Melo 			if (perf_mmap__push(&maps[i], evlist->overwrite, backward, rec, record__pushfn) != 0) {
5028d3eca20SDavid Ahern 				rc = -1;
5038d3eca20SDavid Ahern 				goto out;
5048d3eca20SDavid Ahern 			}
5058d3eca20SDavid Ahern 		}
506ef149c25SAdrian Hunter 
5072dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
508ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
509ef149c25SAdrian Hunter 			rc = -1;
510ef149c25SAdrian Hunter 			goto out;
511ef149c25SAdrian Hunter 		}
51298402807SFrederic Weisbecker 	}
51398402807SFrederic Weisbecker 
514dcabb507SJiri Olsa 	/*
515dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
516dcabb507SJiri Olsa 	 * at least one event.
517dcabb507SJiri Olsa 	 */
518dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
5198c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
5208d3eca20SDavid Ahern 
52154cc54deSWang Nan 	if (backward)
52254cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
5238d3eca20SDavid Ahern out:
5248d3eca20SDavid Ahern 	return rc;
52598402807SFrederic Weisbecker }
52698402807SFrederic Weisbecker 
527cb21686bSWang Nan static int record__mmap_read_all(struct record *rec)
528cb21686bSWang Nan {
529cb21686bSWang Nan 	int err;
530cb21686bSWang Nan 
531a4ea0ec4SWang Nan 	err = record__mmap_read_evlist(rec, rec->evlist, false);
532cb21686bSWang Nan 	if (err)
533cb21686bSWang Nan 		return err;
534cb21686bSWang Nan 
53505737464SWang Nan 	return record__mmap_read_evlist(rec, rec->evlist, true);
536cb21686bSWang Nan }
537cb21686bSWang Nan 
5388c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
53957706abcSDavid Ahern {
54057706abcSDavid Ahern 	struct perf_session *session = rec->session;
54157706abcSDavid Ahern 	int feat;
54257706abcSDavid Ahern 
54357706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
54457706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
54557706abcSDavid Ahern 
54657706abcSDavid Ahern 	if (rec->no_buildid)
54757706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
54857706abcSDavid Ahern 
5493e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
55057706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
55157706abcSDavid Ahern 
55257706abcSDavid Ahern 	if (!rec->opts.branch_stack)
55357706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
554ef149c25SAdrian Hunter 
555ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
556ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
557ffa517adSJiri Olsa 
558ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
55957706abcSDavid Ahern }
56057706abcSDavid Ahern 
561e1ab48baSWang Nan static void
562e1ab48baSWang Nan record__finish_output(struct record *rec)
563e1ab48baSWang Nan {
5648ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
5658ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
566e1ab48baSWang Nan 
5678ceb41d7SJiri Olsa 	if (data->is_pipe)
568e1ab48baSWang Nan 		return;
569e1ab48baSWang Nan 
570e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
5718ceb41d7SJiri Olsa 	data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
572e1ab48baSWang Nan 
573e1ab48baSWang Nan 	if (!rec->no_buildid) {
574e1ab48baSWang Nan 		process_buildids(rec);
575e1ab48baSWang Nan 
576e1ab48baSWang Nan 		if (rec->buildid_all)
577e1ab48baSWang Nan 			dsos__hit_all(rec->session);
578e1ab48baSWang Nan 	}
579e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
580e1ab48baSWang Nan 
581e1ab48baSWang Nan 	return;
582e1ab48baSWang Nan }
583e1ab48baSWang Nan 
5844ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
585be7b0c9eSWang Nan {
5869d6aae72SArnaldo Carvalho de Melo 	int err;
5879d6aae72SArnaldo Carvalho de Melo 	struct thread_map *thread_map;
588be7b0c9eSWang Nan 
5894ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
5904ea648aeSWang Nan 		return 0;
5914ea648aeSWang Nan 
5929d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
5939d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
5949d6aae72SArnaldo Carvalho de Melo 		return -1;
5959d6aae72SArnaldo Carvalho de Melo 
5969d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
597be7b0c9eSWang Nan 						 process_synthesized_event,
598be7b0c9eSWang Nan 						 &rec->session->machines.host,
599be7b0c9eSWang Nan 						 rec->opts.sample_address,
600be7b0c9eSWang Nan 						 rec->opts.proc_map_timeout);
6019d6aae72SArnaldo Carvalho de Melo 	thread_map__put(thread_map);
6029d6aae72SArnaldo Carvalho de Melo 	return err;
603be7b0c9eSWang Nan }
604be7b0c9eSWang Nan 
6054ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
6063c1cb7e3SWang Nan 
607ecfd7a9cSWang Nan static int
608ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
609ecfd7a9cSWang Nan {
6108ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
611ecfd7a9cSWang Nan 	int fd, err;
612ecfd7a9cSWang Nan 
613ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
614ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
615ecfd7a9cSWang Nan 
6164ea648aeSWang Nan 	record__synthesize(rec, true);
6174ea648aeSWang Nan 	if (target__none(&rec->opts.target))
6184ea648aeSWang Nan 		record__synthesize_workload(rec, true);
6194ea648aeSWang Nan 
620ecfd7a9cSWang Nan 	rec->samples = 0;
621ecfd7a9cSWang Nan 	record__finish_output(rec);
622ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
623ecfd7a9cSWang Nan 	if (err) {
624ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
625ecfd7a9cSWang Nan 		return -EINVAL;
626ecfd7a9cSWang Nan 	}
627ecfd7a9cSWang Nan 
6288ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
629ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
630ecfd7a9cSWang Nan 				    at_exit);
631ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
632ecfd7a9cSWang Nan 		rec->bytes_written = 0;
633ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
634ecfd7a9cSWang Nan 	}
635ecfd7a9cSWang Nan 
636ecfd7a9cSWang Nan 	if (!quiet)
637ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
638eae8ad80SJiri Olsa 			data->file.path, timestamp);
6393c1cb7e3SWang Nan 
6403c1cb7e3SWang Nan 	/* Output tracking events */
641be7b0c9eSWang Nan 	if (!at_exit) {
6424ea648aeSWang Nan 		record__synthesize(rec, false);
6433c1cb7e3SWang Nan 
644be7b0c9eSWang Nan 		/*
645be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
646be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
647be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
648be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
649be7b0c9eSWang Nan 		 * contain map and comm information.
650be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
651be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
652be7b0c9eSWang Nan 		 */
653be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
6544ea648aeSWang Nan 			record__synthesize_workload(rec, false);
655be7b0c9eSWang Nan 	}
656ecfd7a9cSWang Nan 	return fd;
657ecfd7a9cSWang Nan }
658ecfd7a9cSWang Nan 
659f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
660f33cbe72SArnaldo Carvalho de Melo 
661f33cbe72SArnaldo Carvalho de Melo /*
662f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
663f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
664f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
665f33cbe72SArnaldo Carvalho de Melo  */
66645604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
66745604710SNamhyung Kim 					siginfo_t *info,
668f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
669f33cbe72SArnaldo Carvalho de Melo {
670f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
671f33cbe72SArnaldo Carvalho de Melo 	done = 1;
672f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
673f33cbe72SArnaldo Carvalho de Melo }
674f33cbe72SArnaldo Carvalho de Melo 
6752dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
676bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
6772dd6d8a1SAdrian Hunter 
67846bc29b9SAdrian Hunter int __weak
67946bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
68046bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
68146bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
68246bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
68346bc29b9SAdrian Hunter {
68446bc29b9SAdrian Hunter 	return 0;
68546bc29b9SAdrian Hunter }
68646bc29b9SAdrian Hunter 
687ee667f94SWang Nan static const struct perf_event_mmap_page *
688ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist)
689ee667f94SWang Nan {
690b2cb615dSWang Nan 	if (evlist) {
691b2cb615dSWang Nan 		if (evlist->mmap && evlist->mmap[0].base)
692ee667f94SWang Nan 			return evlist->mmap[0].base;
693b2cb615dSWang Nan 		if (evlist->backward_mmap && evlist->backward_mmap[0].base)
694b2cb615dSWang Nan 			return evlist->backward_mmap[0].base;
695b2cb615dSWang Nan 	}
696ee667f94SWang Nan 	return NULL;
697ee667f94SWang Nan }
698ee667f94SWang Nan 
699c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
700c45628b0SWang Nan {
701ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
702ee667f94SWang Nan 
703ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
704ee667f94SWang Nan 	if (pc)
705ee667f94SWang Nan 		return pc;
706c45628b0SWang Nan 	return NULL;
707c45628b0SWang Nan }
708c45628b0SWang Nan 
7094ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
710c45c86ebSWang Nan {
711c45c86ebSWang Nan 	struct perf_session *session = rec->session;
712c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
7138ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
714c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
715c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
7168ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
717c45c86ebSWang Nan 	int err = 0;
718c45c86ebSWang Nan 
7194ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
7204ea648aeSWang Nan 		return 0;
7214ea648aeSWang Nan 
7228ceb41d7SJiri Olsa 	if (data->is_pipe) {
723e9def1b2SDavid Carrillo-Cisneros 		err = perf_event__synthesize_features(
724e9def1b2SDavid Carrillo-Cisneros 			tool, session, rec->evlist, process_synthesized_event);
725e9def1b2SDavid Carrillo-Cisneros 		if (err < 0) {
726e9def1b2SDavid Carrillo-Cisneros 			pr_err("Couldn't synthesize features.\n");
727e9def1b2SDavid Carrillo-Cisneros 			return err;
728e9def1b2SDavid Carrillo-Cisneros 		}
729e9def1b2SDavid Carrillo-Cisneros 
730c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
731c45c86ebSWang Nan 						   process_synthesized_event);
732c45c86ebSWang Nan 		if (err < 0) {
733c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
734c45c86ebSWang Nan 			goto out;
735c45c86ebSWang Nan 		}
736c45c86ebSWang Nan 
737c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
738c45c86ebSWang Nan 			/*
739c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
740c45c86ebSWang Nan 			 * there were no tracepoints so its not really
741c45c86ebSWang Nan 			 * an error, just that we don't need to
742c45c86ebSWang Nan 			 * synthesize anything.  We really have to
743c45c86ebSWang Nan 			 * return this more properly and also
744c45c86ebSWang Nan 			 * propagate errors that now are calling die()
745c45c86ebSWang Nan 			 */
746c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
747c45c86ebSWang Nan 								  process_synthesized_event);
748c45c86ebSWang Nan 			if (err <= 0) {
749c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
750c45c86ebSWang Nan 				goto out;
751c45c86ebSWang Nan 			}
752c45c86ebSWang Nan 			rec->bytes_written += err;
753c45c86ebSWang Nan 		}
754c45c86ebSWang Nan 	}
755c45c86ebSWang Nan 
756c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
75746bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
75846bc29b9SAdrian Hunter 	if (err)
75946bc29b9SAdrian Hunter 		goto out;
76046bc29b9SAdrian Hunter 
761c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
762c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
763c45c86ebSWang Nan 					session, process_synthesized_event);
764c45c86ebSWang Nan 		if (err)
765c45c86ebSWang Nan 			goto out;
766c45c86ebSWang Nan 	}
767c45c86ebSWang Nan 
768c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
769c45c86ebSWang Nan 						 machine);
770c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
771c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
772c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
773c45c86ebSWang Nan 
774c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
775c45c86ebSWang Nan 					     machine);
776c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
777c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
778c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
779c45c86ebSWang Nan 
780c45c86ebSWang Nan 	if (perf_guest) {
781c45c86ebSWang Nan 		machines__process_guests(&session->machines,
782c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
783c45c86ebSWang Nan 	}
784c45c86ebSWang Nan 
785c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
786c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
787340b47f5SKan Liang 					    opts->proc_map_timeout, 1);
788c45c86ebSWang Nan out:
789c45c86ebSWang Nan 	return err;
790c45c86ebSWang Nan }
791c45c86ebSWang Nan 
7928c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
79386470930SIngo Molnar {
79457706abcSDavid Ahern 	int err;
79545604710SNamhyung Kim 	int status = 0;
7968b412664SPeter Zijlstra 	unsigned long waking = 0;
79746be604bSZhang, Yanmin 	const bool forks = argc > 0;
79823346f21SArnaldo Carvalho de Melo 	struct machine *machine;
79945694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
800b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
8018ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
802d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
8036dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
80442aa276fSNamhyung Kim 	int fd;
80586470930SIngo Molnar 
806d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
80733e49ea7SAndi Kleen 
80845604710SNamhyung Kim 	atexit(record__sig_exit);
809f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
810f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
811804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
812a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
813c0bdc1c4SWang Nan 
814f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
815f3b3614aSHari Bathini 		tool->namespace_events = true;
816f3b3614aSHari Bathini 
817dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
8182dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
8193c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
8205f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
821dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
8223c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
823c0bdc1c4SWang Nan 	} else {
8242dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
825c0bdc1c4SWang Nan 	}
826f5970550SPeter Zijlstra 
8278ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
82894c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
829ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
830a9a70bbcSArnaldo Carvalho de Melo 		return -1;
831a9a70bbcSArnaldo Carvalho de Melo 	}
832a9a70bbcSArnaldo Carvalho de Melo 
8338ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
834d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
835d20deb64SArnaldo Carvalho de Melo 
8368c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
837330aa675SStephane Eranian 
838d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
8393e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
8408ceb41d7SJiri Olsa 						    argv, data->is_pipe,
841735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
84235b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
84335b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
84445604710SNamhyung Kim 			status = err;
84535b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
846856e9660SPeter Zijlstra 		}
847856e9660SPeter Zijlstra 	}
848856e9660SPeter Zijlstra 
8498c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
8508d3eca20SDavid Ahern 		err = -1;
85145604710SNamhyung Kim 		goto out_child;
8528d3eca20SDavid Ahern 	}
85386470930SIngo Molnar 
8548690a2a7SWang Nan 	err = bpf__apply_obj_config();
8558690a2a7SWang Nan 	if (err) {
8568690a2a7SWang Nan 		char errbuf[BUFSIZ];
8578690a2a7SWang Nan 
8588690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
8598690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
8608690a2a7SWang Nan 			 errbuf);
8618690a2a7SWang Nan 		goto out_child;
8628690a2a7SWang Nan 	}
8638690a2a7SWang Nan 
864cca8482cSAdrian Hunter 	/*
865cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
866cca8482cSAdrian Hunter 	 * evlist.
867cca8482cSAdrian Hunter 	 */
868cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
869cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
870cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
871cca8482cSAdrian Hunter 	}
872cca8482cSAdrian Hunter 
8733e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
874a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
875a8bb559bSNamhyung Kim 
8768ceb41d7SJiri Olsa 	if (data->is_pipe) {
87742aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
878529870e3STom Zanussi 		if (err < 0)
87945604710SNamhyung Kim 			goto out_child;
880563aecb2SJiri Olsa 	} else {
88142aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
882d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
88345604710SNamhyung Kim 			goto out_child;
884d5eed904SArnaldo Carvalho de Melo 	}
8857c6a1c65SPeter Zijlstra 
886d3665498SDavid Ahern 	if (!rec->no_buildid
887e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
888d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
889e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
8908d3eca20SDavid Ahern 		err = -1;
89145604710SNamhyung Kim 		goto out_child;
892e20960c0SRobert Richter 	}
893e20960c0SRobert Richter 
89434ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
895743eb868SArnaldo Carvalho de Melo 
8964ea648aeSWang Nan 	err = record__synthesize(rec, false);
897c45c86ebSWang Nan 	if (err < 0)
89845604710SNamhyung Kim 		goto out_child;
8998d3eca20SDavid Ahern 
900d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
90186470930SIngo Molnar 		struct sched_param param;
90286470930SIngo Molnar 
903d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
90486470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
9056beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
9068d3eca20SDavid Ahern 			err = -1;
90745604710SNamhyung Kim 			goto out_child;
90886470930SIngo Molnar 		}
90986470930SIngo Molnar 	}
91086470930SIngo Molnar 
911774cb499SJiri Olsa 	/*
912774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
913774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
914774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
915774cb499SJiri Olsa 	 */
9166619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
9173e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
918764e16a3SDavid Ahern 
919856e9660SPeter Zijlstra 	/*
920856e9660SPeter Zijlstra 	 * Let the child rip
921856e9660SPeter Zijlstra 	 */
922e803cf97SNamhyung Kim 	if (forks) {
923e5bed564SNamhyung Kim 		union perf_event *event;
924e907caf3SHari Bathini 		pid_t tgid;
925e5bed564SNamhyung Kim 
926e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
927e5bed564SNamhyung Kim 		if (event == NULL) {
928e5bed564SNamhyung Kim 			err = -ENOMEM;
929e5bed564SNamhyung Kim 			goto out_child;
930e5bed564SNamhyung Kim 		}
931e5bed564SNamhyung Kim 
932e803cf97SNamhyung Kim 		/*
933e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
934e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
935e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
936e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
937e803cf97SNamhyung Kim 		 */
938e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
939e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
940e803cf97SNamhyung Kim 						   process_synthesized_event,
941e803cf97SNamhyung Kim 						   machine);
942e5bed564SNamhyung Kim 		free(event);
943e803cf97SNamhyung Kim 
944e907caf3SHari Bathini 		if (tgid == -1)
945e907caf3SHari Bathini 			goto out_child;
946e907caf3SHari Bathini 
947e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
948e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
949e907caf3SHari Bathini 			       machine->id_hdr_size);
950e907caf3SHari Bathini 		if (event == NULL) {
951e907caf3SHari Bathini 			err = -ENOMEM;
952e907caf3SHari Bathini 			goto out_child;
953e907caf3SHari Bathini 		}
954e907caf3SHari Bathini 
955e907caf3SHari Bathini 		/*
956e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
957e907caf3SHari Bathini 		 */
958e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
959e907caf3SHari Bathini 						  rec->evlist->workload.pid,
960e907caf3SHari Bathini 						  tgid, process_synthesized_event,
961e907caf3SHari Bathini 						  machine);
962e907caf3SHari Bathini 		free(event);
963e907caf3SHari Bathini 
9643e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
965e803cf97SNamhyung Kim 	}
966856e9660SPeter Zijlstra 
9676619a53eSAndi Kleen 	if (opts->initial_delay) {
9680693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
9696619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
9706619a53eSAndi Kleen 	}
9716619a53eSAndi Kleen 
9725f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
9733c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
974a074865eSWang Nan 	perf_hooks__invoke_record_start();
975649c48a9SPeter Zijlstra 	for (;;) {
9769f065194SYang Shi 		unsigned long long hits = rec->samples;
97786470930SIngo Molnar 
97805737464SWang Nan 		/*
97905737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
98005737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
98105737464SWang Nan 		 * hits != rec->samples in previous round.
98205737464SWang Nan 		 *
98305737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
98405737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
98505737464SWang Nan 		 */
98605737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
98705737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
98805737464SWang Nan 
9898c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
9905f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
9913c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
9928d3eca20SDavid Ahern 			err = -1;
99345604710SNamhyung Kim 			goto out_child;
9948d3eca20SDavid Ahern 		}
99586470930SIngo Molnar 
9962dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
9972dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
9985f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
9992dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
10005f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
10012dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
10022dd6d8a1SAdrian Hunter 				err = -1;
10032dd6d8a1SAdrian Hunter 				goto out_child;
10042dd6d8a1SAdrian Hunter 			}
10052dd6d8a1SAdrian Hunter 		}
10062dd6d8a1SAdrian Hunter 
10073c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
100805737464SWang Nan 			/*
100905737464SWang Nan 			 * If switch_output_trigger is hit, the data in
101005737464SWang Nan 			 * overwritable ring buffer should have been collected,
101105737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
101205737464SWang Nan 			 *
101305737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
101405737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
101505737464SWang Nan 			 * overwritable ring buffer. Read again.
101605737464SWang Nan 			 */
101705737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
101805737464SWang Nan 				continue;
10193c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
10203c1cb7e3SWang Nan 
102105737464SWang Nan 			/*
102205737464SWang Nan 			 * Reenable events in overwrite ring buffer after
102305737464SWang Nan 			 * record__mmap_read_all(): we should have collected
102405737464SWang Nan 			 * data from it.
102505737464SWang Nan 			 */
102605737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
102705737464SWang Nan 
10283c1cb7e3SWang Nan 			if (!quiet)
10293c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
10303c1cb7e3SWang Nan 					waking);
10313c1cb7e3SWang Nan 			waking = 0;
10323c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
10333c1cb7e3SWang Nan 			if (fd < 0) {
10343c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
10353c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
10363c1cb7e3SWang Nan 				err = fd;
10373c1cb7e3SWang Nan 				goto out_child;
10383c1cb7e3SWang Nan 			}
1039bfacbe3bSJiri Olsa 
1040bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1041bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1042bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
10433c1cb7e3SWang Nan 		}
10443c1cb7e3SWang Nan 
1045d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
10466dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1047649c48a9SPeter Zijlstra 				break;
1048f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
1049a515114fSJiri Olsa 			/*
1050a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1051a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1052a515114fSJiri Olsa 			 */
1053a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
105445604710SNamhyung Kim 				err = 0;
10558b412664SPeter Zijlstra 			waking++;
10566dcf45efSArnaldo Carvalho de Melo 
10576dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
10586dcf45efSArnaldo Carvalho de Melo 				draining = true;
10598b412664SPeter Zijlstra 		}
10608b412664SPeter Zijlstra 
1061774cb499SJiri Olsa 		/*
1062774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1063774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1064774cb499SJiri Olsa 		 * disable events in this case.
1065774cb499SJiri Olsa 		 */
1066602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
10675f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
10683e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
10692711926aSJiri Olsa 			disabled = true;
10702711926aSJiri Olsa 		}
10718b412664SPeter Zijlstra 	}
10725f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
10733c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
10748b412664SPeter Zijlstra 
1075f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
107635550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1077c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1078f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1079f33cbe72SArnaldo Carvalho de Melo 		err = -1;
108045604710SNamhyung Kim 		goto out_child;
1081f33cbe72SArnaldo Carvalho de Melo 	}
1082f33cbe72SArnaldo Carvalho de Melo 
1083e3d59112SNamhyung Kim 	if (!quiet)
10848b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
108586470930SIngo Molnar 
10864ea648aeSWang Nan 	if (target__none(&rec->opts.target))
10874ea648aeSWang Nan 		record__synthesize_workload(rec, true);
10884ea648aeSWang Nan 
108945604710SNamhyung Kim out_child:
109045604710SNamhyung Kim 	if (forks) {
109145604710SNamhyung Kim 		int exit_status;
109245604710SNamhyung Kim 
109345604710SNamhyung Kim 		if (!child_finished)
109445604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
109545604710SNamhyung Kim 
109645604710SNamhyung Kim 		wait(&exit_status);
109745604710SNamhyung Kim 
109845604710SNamhyung Kim 		if (err < 0)
109945604710SNamhyung Kim 			status = err;
110045604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
110145604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
110245604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
110345604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
110445604710SNamhyung Kim 	} else
110545604710SNamhyung Kim 		status = err;
110645604710SNamhyung Kim 
11074ea648aeSWang Nan 	record__synthesize(rec, true);
1108e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1109e3d59112SNamhyung Kim 	rec->samples = 0;
1110e3d59112SNamhyung Kim 
1111ecfd7a9cSWang Nan 	if (!err) {
1112ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1113e1ab48baSWang Nan 			record__finish_output(rec);
1114ecfd7a9cSWang Nan 		} else {
1115ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1116ecfd7a9cSWang Nan 			if (fd < 0) {
1117ecfd7a9cSWang Nan 				status = fd;
1118ecfd7a9cSWang Nan 				goto out_delete_session;
1119ecfd7a9cSWang Nan 			}
1120ecfd7a9cSWang Nan 		}
1121ecfd7a9cSWang Nan 	}
112239d17dacSArnaldo Carvalho de Melo 
1123a074865eSWang Nan 	perf_hooks__invoke_record_end();
1124a074865eSWang Nan 
1125e3d59112SNamhyung Kim 	if (!err && !quiet) {
1126e3d59112SNamhyung Kim 		char samples[128];
1127ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1128ecfd7a9cSWang Nan 					".<timestamp>" : "";
1129e3d59112SNamhyung Kim 
1130ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1131e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1132e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1133e3d59112SNamhyung Kim 		else
1134e3d59112SNamhyung Kim 			samples[0] = '\0';
1135e3d59112SNamhyung Kim 
1136ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
11378ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
1138eae8ad80SJiri Olsa 			data->file.path, postfix, samples);
1139e3d59112SNamhyung Kim 	}
1140e3d59112SNamhyung Kim 
114139d17dacSArnaldo Carvalho de Melo out_delete_session:
114239d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
114345604710SNamhyung Kim 	return status;
114486470930SIngo Molnar }
114586470930SIngo Molnar 
11460883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
114709b0fd45SJiri Olsa {
1148aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1149a601fdffSJiri Olsa 
11500883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
115126d33022SJiri Olsa 
11520883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
115309b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
11540883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
11550883e820SArnaldo Carvalho de Melo }
11560883e820SArnaldo Carvalho de Melo 
11570883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
11580883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
11590883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
11600883e820SArnaldo Carvalho de Melo {
11610883e820SArnaldo Carvalho de Melo 	int ret;
11620883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
11630883e820SArnaldo Carvalho de Melo 
11640883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
11650883e820SArnaldo Carvalho de Melo 	if (unset) {
11660883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
11670883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
11680883e820SArnaldo Carvalho de Melo 		return 0;
11690883e820SArnaldo Carvalho de Melo 	}
11700883e820SArnaldo Carvalho de Melo 
11710883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
11720883e820SArnaldo Carvalho de Melo 	if (!ret) {
11730883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
11740883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
11750883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
11760883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
11770883e820SArnaldo Carvalho de Melo 	}
11780883e820SArnaldo Carvalho de Melo 
11790883e820SArnaldo Carvalho de Melo 	return ret;
118009b0fd45SJiri Olsa }
118109b0fd45SJiri Olsa 
1182c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
118309b0fd45SJiri Olsa 			       const char *arg,
118409b0fd45SJiri Olsa 			       int unset)
118509b0fd45SJiri Olsa {
11860883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
118726d33022SJiri Olsa }
118826d33022SJiri Olsa 
1189c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
119009b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
119109b0fd45SJiri Olsa 			 int unset __maybe_unused)
119209b0fd45SJiri Olsa {
11932ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1194c421e80bSKan Liang 
11952ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
119609b0fd45SJiri Olsa 
11972ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
11982ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1199eb853e80SJiri Olsa 
12002ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
120109b0fd45SJiri Olsa 	return 0;
120209b0fd45SJiri Olsa }
120309b0fd45SJiri Olsa 
1204eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1205eb853e80SJiri Olsa {
12067a29c087SNamhyung Kim 	struct record *rec = cb;
12077a29c087SNamhyung Kim 
12087a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
12097a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
12107a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
12117a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
12127a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
12137a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
12147a29c087SNamhyung Kim 			rec->no_buildid = true;
12157a29c087SNamhyung Kim 		else
12167a29c087SNamhyung Kim 			return -1;
12177a29c087SNamhyung Kim 		return 0;
12187a29c087SNamhyung Kim 	}
1219eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
12205a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
1221eb853e80SJiri Olsa 
1222eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
1223eb853e80SJiri Olsa }
1224eb853e80SJiri Olsa 
1225814c8c38SPeter Zijlstra struct clockid_map {
1226814c8c38SPeter Zijlstra 	const char *name;
1227814c8c38SPeter Zijlstra 	int clockid;
1228814c8c38SPeter Zijlstra };
1229814c8c38SPeter Zijlstra 
1230814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1231814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1232814c8c38SPeter Zijlstra 
1233814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1234814c8c38SPeter Zijlstra 
1235814c8c38SPeter Zijlstra 
1236814c8c38SPeter Zijlstra /*
1237814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1238814c8c38SPeter Zijlstra  */
1239814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1240814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1241814c8c38SPeter Zijlstra #endif
1242814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1243814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1244814c8c38SPeter Zijlstra #endif
1245814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1246814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1247814c8c38SPeter Zijlstra #endif
1248814c8c38SPeter Zijlstra 
1249814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1250814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1251814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1252814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1253814c8c38SPeter Zijlstra 
1254814c8c38SPeter Zijlstra 	/* available for some events */
1255814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1256814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1257814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1258814c8c38SPeter Zijlstra 
1259814c8c38SPeter Zijlstra 	/* available for the lazy */
1260814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1261814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1262814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1263814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1264814c8c38SPeter Zijlstra 
1265814c8c38SPeter Zijlstra 	CLOCKID_END,
1266814c8c38SPeter Zijlstra };
1267814c8c38SPeter Zijlstra 
1268814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1269814c8c38SPeter Zijlstra {
1270814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1271814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1272814c8c38SPeter Zijlstra 	const char *ostr = str;
1273814c8c38SPeter Zijlstra 
1274814c8c38SPeter Zijlstra 	if (unset) {
1275814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1276814c8c38SPeter Zijlstra 		return 0;
1277814c8c38SPeter Zijlstra 	}
1278814c8c38SPeter Zijlstra 
1279814c8c38SPeter Zijlstra 	/* no arg passed */
1280814c8c38SPeter Zijlstra 	if (!str)
1281814c8c38SPeter Zijlstra 		return 0;
1282814c8c38SPeter Zijlstra 
1283814c8c38SPeter Zijlstra 	/* no setting it twice */
1284814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1285814c8c38SPeter Zijlstra 		return -1;
1286814c8c38SPeter Zijlstra 
1287814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1288814c8c38SPeter Zijlstra 
1289814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1290814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1291814c8c38SPeter Zijlstra 		return 0;
1292814c8c38SPeter Zijlstra 
1293814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1294814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1295814c8c38SPeter Zijlstra 		str += 6;
1296814c8c38SPeter Zijlstra 
1297814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1298814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1299814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1300814c8c38SPeter Zijlstra 			return 0;
1301814c8c38SPeter Zijlstra 		}
1302814c8c38SPeter Zijlstra 	}
1303814c8c38SPeter Zijlstra 
1304814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1305814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1306814c8c38SPeter Zijlstra 	return -1;
1307814c8c38SPeter Zijlstra }
1308814c8c38SPeter Zijlstra 
1309e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1310e9db1310SAdrian Hunter 				    const char *str,
1311e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1312e9db1310SAdrian Hunter {
1313e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1314e9db1310SAdrian Hunter 	char *s, *p;
1315e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1316e9db1310SAdrian Hunter 	int ret;
1317e9db1310SAdrian Hunter 
1318e9db1310SAdrian Hunter 	if (!str)
1319e9db1310SAdrian Hunter 		return -EINVAL;
1320e9db1310SAdrian Hunter 
1321e9db1310SAdrian Hunter 	s = strdup(str);
1322e9db1310SAdrian Hunter 	if (!s)
1323e9db1310SAdrian Hunter 		return -ENOMEM;
1324e9db1310SAdrian Hunter 
1325e9db1310SAdrian Hunter 	p = strchr(s, ',');
1326e9db1310SAdrian Hunter 	if (p)
1327e9db1310SAdrian Hunter 		*p = '\0';
1328e9db1310SAdrian Hunter 
1329e9db1310SAdrian Hunter 	if (*s) {
1330e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1331e9db1310SAdrian Hunter 		if (ret)
1332e9db1310SAdrian Hunter 			goto out_free;
1333e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1334e9db1310SAdrian Hunter 	}
1335e9db1310SAdrian Hunter 
1336e9db1310SAdrian Hunter 	if (!p) {
1337e9db1310SAdrian Hunter 		ret = 0;
1338e9db1310SAdrian Hunter 		goto out_free;
1339e9db1310SAdrian Hunter 	}
1340e9db1310SAdrian Hunter 
1341e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1342e9db1310SAdrian Hunter 	if (ret)
1343e9db1310SAdrian Hunter 		goto out_free;
1344e9db1310SAdrian Hunter 
1345e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1346e9db1310SAdrian Hunter 
1347e9db1310SAdrian Hunter out_free:
1348e9db1310SAdrian Hunter 	free(s);
1349e9db1310SAdrian Hunter 	return ret;
1350e9db1310SAdrian Hunter }
1351e9db1310SAdrian Hunter 
13520c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
13530c582449SJiri Olsa {
13540c582449SJiri Olsa 	u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
13550c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
13560c582449SJiri Olsa 
13570c582449SJiri Olsa 	wakeup_size /= 2;
13580c582449SJiri Olsa 
13590c582449SJiri Olsa 	if (s->size < wakeup_size) {
13600c582449SJiri Olsa 		char buf[100];
13610c582449SJiri Olsa 
13620c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
13630c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
13640c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
13650c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
13660c582449SJiri Olsa 	}
13670c582449SJiri Olsa }
13680c582449SJiri Olsa 
1369cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
1370cb4e1ebbSJiri Olsa {
1371cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
1372dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
1373dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
1374dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
1375dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
1376dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
1377dc0c6127SJiri Olsa 		{ .tag  = 0 },
1378dc0c6127SJiri Olsa 	};
1379bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
1380bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
1381bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
1382bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
1383bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
1384bfacbe3bSJiri Olsa 		{ .tag  = 0 },
1385bfacbe3bSJiri Olsa 	};
1386dc0c6127SJiri Olsa 	unsigned long val;
1387cb4e1ebbSJiri Olsa 
1388cb4e1ebbSJiri Olsa 	if (!s->set)
1389cb4e1ebbSJiri Olsa 		return 0;
1390cb4e1ebbSJiri Olsa 
1391cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
1392cb4e1ebbSJiri Olsa 		s->signal = true;
1393cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
1394dc0c6127SJiri Olsa 		goto enabled;
1395dc0c6127SJiri Olsa 	}
1396dc0c6127SJiri Olsa 
1397dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
1398dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
1399dc0c6127SJiri Olsa 		s->size = val;
1400dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
1401dc0c6127SJiri Olsa 		goto enabled;
1402cb4e1ebbSJiri Olsa 	}
1403cb4e1ebbSJiri Olsa 
1404bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
1405bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
1406bfacbe3bSJiri Olsa 		s->time = val;
1407bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
1408bfacbe3bSJiri Olsa 			 s->str, s->time);
1409bfacbe3bSJiri Olsa 		goto enabled;
1410bfacbe3bSJiri Olsa 	}
1411bfacbe3bSJiri Olsa 
1412cb4e1ebbSJiri Olsa 	return -1;
1413dc0c6127SJiri Olsa 
1414dc0c6127SJiri Olsa enabled:
1415dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
1416dc0c6127SJiri Olsa 	s->enabled              = true;
14170c582449SJiri Olsa 
14180c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
14190c582449SJiri Olsa 		switch_output_size_warn(rec);
14200c582449SJiri Olsa 
1421dc0c6127SJiri Olsa 	return 0;
1422cb4e1ebbSJiri Olsa }
1423cb4e1ebbSJiri Olsa 
1424e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
142586470930SIngo Molnar 	"perf record [<options>] [<command>]",
142686470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
142786470930SIngo Molnar 	NULL
142886470930SIngo Molnar };
1429e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
143086470930SIngo Molnar 
1431d20deb64SArnaldo Carvalho de Melo /*
14328c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
14338c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1434d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1435d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1436d20deb64SArnaldo Carvalho de Melo  *
1437d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1438d20deb64SArnaldo Carvalho de Melo  *
1439d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1440d20deb64SArnaldo Carvalho de Melo  */
14418c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1442d20deb64SArnaldo Carvalho de Melo 	.opts = {
14438affc2b8SAndi Kleen 		.sample_time	     = true,
1444d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1445d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1446d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1447447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1448d1cb9fceSNamhyung Kim 		.target		     = {
1449d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
14503aa5939dSAdrian Hunter 			.default_per_cpu = true,
1451d1cb9fceSNamhyung Kim 		},
14529d9cad76SKan Liang 		.proc_map_timeout     = 500,
1453d20deb64SArnaldo Carvalho de Melo 	},
1454e3d59112SNamhyung Kim 	.tool = {
1455e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1456e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1457cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1458e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1459f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
1460e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1461e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1462cca8482cSAdrian Hunter 		.ordered_events	= true,
1463e3d59112SNamhyung Kim 	},
1464d20deb64SArnaldo Carvalho de Melo };
14657865e817SFrederic Weisbecker 
146676a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
146776a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
146861eaa3beSArnaldo Carvalho de Melo 
14690aab2136SWang Nan static bool dry_run;
14700aab2136SWang Nan 
1471d20deb64SArnaldo Carvalho de Melo /*
1472d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1473d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1474b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1475d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1476d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1477d20deb64SArnaldo Carvalho de Melo  */
1478efd21307SJiri Olsa static struct option __record_options[] = {
1479d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
148086470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1481f120f9d5SJiri Olsa 		     parse_events_option),
1482d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1483c171b552SLi Zefan 		     "event filter", parse_filter),
14844ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
14854ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
14864ba1faa1SWang Nan 			   exclude_perf),
1487bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1488d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1489bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1490d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1491d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
149286470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1493509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1494acac03faSKirill Smelkov 		    "collect data without buffering"),
1495d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1496daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1497bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
149886470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1499bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1500c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1501d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1502eae8ad80SJiri Olsa 	OPT_STRING('o', "output", &record.data.file.path, "file",
150386470930SIngo Molnar 		    "output file name"),
150469e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
150569e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
15062e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
15074ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
15084ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
1509626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1510d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1511e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1512e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1513e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1514d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
151543bece79SLin Ming 		    "put the counters into a counter group"),
15162ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
151709b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
151809b0fd45SJiri Olsa 			   &record_callchain_opt),
151909b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
152076a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
152109b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1522c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
15233da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1524b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1525d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1526649c48a9SPeter Zijlstra 		    "per thread counts"),
152756100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
15283b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
15293b0a5daaSKan Liang 		    "Record the sample physical addresses"),
1530b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
15313abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
15323abebc55SAdrian Hunter 			&record.opts.sample_time_set,
15333abebc55SAdrian Hunter 			"Record the sample timestamps"),
153456100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1535d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1536649c48a9SPeter Zijlstra 		    "don't sample"),
1537d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1538d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1539a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1540d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1541d2db9a98SWang Nan 			&record.no_buildid_set,
1542baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1543d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1544023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1545023695d9SStephane Eranian 		     parse_cgroups),
1546a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
15476619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1548bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1549bea03405SNamhyung Kim 		   "user to profile"),
1550a5aabdacSStephane Eranian 
1551a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1552a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1553a5aabdacSStephane Eranian 		     parse_branch_stack),
1554a5aabdacSStephane Eranian 
1555a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1556a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1557bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
155805484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
155905484298SAndi Kleen 		    "sample by weight (on special events only)"),
1560475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1561475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
15623aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
15633aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1564bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1565bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1566bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
156784c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
156884c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
156984c41742SAndi Kleen 		    " use -I ? to list register names", parse_regs),
157085c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
157185c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1572814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1573814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1574814c8c38SPeter Zijlstra 	parse_clockid),
15752dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
15762dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
15779d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
15789d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1579f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
1580f3b3614aSHari Bathini 		    "Record namespaces events"),
1581b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1582b757bb09SAdrian Hunter 		    "Record context switch events"),
158385723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
158485723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
158585723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
158685723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
158785723885SJiri Olsa 			 "Configure all used events to run in user space.",
158885723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
158971dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
159071dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
159171dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
159271dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
15937efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
15947efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
15956156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
15966156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1597ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1598ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
1599cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
1600bfacbe3bSJiri Olsa 			  &record.switch_output.set, "signal,size,time",
1601bfacbe3bSJiri Olsa 			  "Switch output when receive SIGUSR2 or cross size,time threshold",
1602dc0c6127SJiri Olsa 			  "signal"),
16030aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
16040aab2136SWang Nan 		    "Parse options then exit"),
160586470930SIngo Molnar 	OPT_END()
160686470930SIngo Molnar };
160786470930SIngo Molnar 
1608e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1609e5b2c207SNamhyung Kim 
1610b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
161186470930SIngo Molnar {
1612ef149c25SAdrian Hunter 	int err;
16138c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
161416ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
161586470930SIngo Molnar 
161648e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
161748e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
161848e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
161948e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
162048e1cab1SWang Nan # undef set_nobuild
162148e1cab1SWang Nan #endif
162248e1cab1SWang Nan 
16237efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
16247efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
16257efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
16267efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
16277efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
16287efe0e03SHe Kuang # else
16297efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
16307efe0e03SHe Kuang # endif
16317efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
16327efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
16337efe0e03SHe Kuang # undef set_nobuild
16347efe0e03SHe Kuang # undef REASON
16357efe0e03SHe Kuang #endif
16367efe0e03SHe Kuang 
16373e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
16383e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1639361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1640361c99a6SArnaldo Carvalho de Melo 
1641ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
1642ecc4c561SArnaldo Carvalho de Melo 	if (err)
1643ecc4c561SArnaldo Carvalho de Melo 		return err;
1644eb853e80SJiri Olsa 
1645bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1646a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
164768ba3235SNamhyung Kim 	if (quiet)
164868ba3235SNamhyung Kim 		perf_quiet_option();
1649483635a9SJiri Olsa 
1650483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
1651602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1652483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
165386470930SIngo Molnar 
1654bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1655c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1656c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1657c7118369SNamhyung Kim 
1658023695d9SStephane Eranian 	}
1659b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1660b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1661c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1662c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1663c7118369SNamhyung Kim 		return -EINVAL;
1664b757bb09SAdrian Hunter 	}
1665023695d9SStephane Eranian 
1666cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
1667cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
1668cb4e1ebbSJiri Olsa 		return -EINVAL;
1669cb4e1ebbSJiri Olsa 	}
1670cb4e1ebbSJiri Olsa 
1671bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
1672bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
1673bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
1674bfacbe3bSJiri Olsa 	}
1675bfacbe3bSJiri Olsa 
1676ef149c25SAdrian Hunter 	if (!rec->itr) {
1677ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1678ef149c25SAdrian Hunter 		if (err)
16795c01ad60SAdrian Hunter 			goto out;
1680ef149c25SAdrian Hunter 	}
1681ef149c25SAdrian Hunter 
16822dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
16832dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
16842dd6d8a1SAdrian Hunter 	if (err)
16855c01ad60SAdrian Hunter 		goto out;
16862dd6d8a1SAdrian Hunter 
16871b36c03eSAdrian Hunter 	/*
16881b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
16891b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
16901b36c03eSAdrian Hunter 	 */
16911b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
16921b36c03eSAdrian Hunter 
16931b36c03eSAdrian Hunter 	symbol__init(NULL);
16941b36c03eSAdrian Hunter 
16951b36c03eSAdrian Hunter 	err = auxtrace_parse_filters(rec->evlist);
16961b36c03eSAdrian Hunter 	if (err)
16971b36c03eSAdrian Hunter 		goto out;
16981b36c03eSAdrian Hunter 
16990aab2136SWang Nan 	if (dry_run)
17005c01ad60SAdrian Hunter 		goto out;
17010aab2136SWang Nan 
1702d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1703d7888573SWang Nan 	if (err) {
1704d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1705d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1706d7888573SWang Nan 			 errbuf);
17075c01ad60SAdrian Hunter 		goto out;
1708d7888573SWang Nan 	}
1709d7888573SWang Nan 
1710ef149c25SAdrian Hunter 	err = -ENOMEM;
1711ef149c25SAdrian Hunter 
1712ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1713646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1714646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1715ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1716646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1717646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1718646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1719646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1720646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1721ec80fde7SArnaldo Carvalho de Melo 
17220c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
1723a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1724dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
17250c1d46a8SWang Nan 		/*
17260c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
17270c1d46a8SWang Nan 		 * generation by default to reduce data file switching
17280c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
17290c1d46a8SWang Nan 		 * explicitly using
17300c1d46a8SWang Nan 		 *
173160437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
17320c1d46a8SWang Nan 		 *              --no-no-buildid-cache
17330c1d46a8SWang Nan 		 *
17340c1d46a8SWang Nan 		 * Following code equals to:
17350c1d46a8SWang Nan 		 *
17360c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
17370c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
17380c1d46a8SWang Nan 		 *         disable_buildid_cache();
17390c1d46a8SWang Nan 		 */
17400c1d46a8SWang Nan 		bool disable = true;
17410c1d46a8SWang Nan 
17420c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
17430c1d46a8SWang Nan 			disable = false;
17440c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
17450c1d46a8SWang Nan 			disable = false;
17460c1d46a8SWang Nan 		if (disable) {
17470c1d46a8SWang Nan 			rec->no_buildid = true;
17480c1d46a8SWang Nan 			rec->no_buildid_cache = true;
17490c1d46a8SWang Nan 			disable_buildid_cache();
17500c1d46a8SWang Nan 		}
17510c1d46a8SWang Nan 	}
1752655000e7SArnaldo Carvalho de Melo 
17534ea648aeSWang Nan 	if (record.opts.overwrite)
17544ea648aeSWang Nan 		record.opts.tail_synthesize = true;
17554ea648aeSWang Nan 
17563e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
17574b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
175869aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
1759394c01edSAdrian Hunter 		goto out;
1760bbd36e5eSPeter Zijlstra 	}
176186470930SIngo Molnar 
176269e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
176369e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
176469e7e5b0SAdrian Hunter 
1765602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
176616ad2ffbSNamhyung Kim 	if (err) {
1767602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
176816ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
176916ad2ffbSNamhyung Kim 	}
17704bd0f2d2SNamhyung Kim 
1771602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
177216ad2ffbSNamhyung Kim 	if (err) {
177316ad2ffbSNamhyung Kim 		int saved_errno = errno;
177416ad2ffbSNamhyung Kim 
1775602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
17763780f488SNamhyung Kim 		ui__error("%s", errbuf);
177716ad2ffbSNamhyung Kim 
177816ad2ffbSNamhyung Kim 		err = -saved_errno;
1779394c01edSAdrian Hunter 		goto out;
178016ad2ffbSNamhyung Kim 	}
17810d37aa34SArnaldo Carvalho de Melo 
178223dc4f15SJiri Olsa 	/* Enable ignoring missing threads when -u option is defined. */
178323dc4f15SJiri Olsa 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX;
178423dc4f15SJiri Olsa 
178516ad2ffbSNamhyung Kim 	err = -ENOMEM;
17863e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1787dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
178869aad6f1SArnaldo Carvalho de Melo 
1789ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1790ef149c25SAdrian Hunter 	if (err)
1791394c01edSAdrian Hunter 		goto out;
1792ef149c25SAdrian Hunter 
17936156681bSNamhyung Kim 	/*
17946156681bSNamhyung Kim 	 * We take all buildids when the file contains
17956156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
17966156681bSNamhyung Kim 	 * trace because it would take too long.
17976156681bSNamhyung Kim 	 */
17986156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
17996156681bSNamhyung Kim 		rec->buildid_all = true;
18006156681bSNamhyung Kim 
1801b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
180239d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
1803394c01edSAdrian Hunter 		goto out;
18047e4ff9e3SMike Galbraith 	}
18057e4ff9e3SMike Galbraith 
1806d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1807394c01edSAdrian Hunter out:
180845604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1809d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1810ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
181139d17dacSArnaldo Carvalho de Melo 	return err;
181286470930SIngo Molnar }
18132dd6d8a1SAdrian Hunter 
18142dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
18152dd6d8a1SAdrian Hunter {
1816dc0c6127SJiri Olsa 	struct record *rec = &record;
1817dc0c6127SJiri Olsa 
18185f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
18195f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
18202dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
18215f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
18225f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
18235f9cf599SWang Nan 	}
18243c1cb7e3SWang Nan 
1825dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
18263c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
18272dd6d8a1SAdrian Hunter }
1828bfacbe3bSJiri Olsa 
1829bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
1830bfacbe3bSJiri Olsa {
1831bfacbe3bSJiri Olsa 	struct record *rec = &record;
1832bfacbe3bSJiri Olsa 
1833bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
1834bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
1835bfacbe3bSJiri Olsa }
1836