xref: /openbmc/linux/tools/perf/builtin-record.c (revision 9d2ed64587c045304efe8872b0258c30803d370c)
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"
2694c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2745694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
288d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
29a12b51c4SPaul Mackerras #include "util/cpumap.h"
30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
31f5fc1412SJiri Olsa #include "util/data.h"
32bcc84ec6SStephane Eranian #include "util/perf_regs.h"
33ef149c25SAdrian Hunter #include "util/auxtrace.h"
3446bc29b9SAdrian Hunter #include "util/tsc.h"
35f00898f4SAndi Kleen #include "util/parse-branch-options.h"
36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3771dc2326SWang Nan #include "util/llvm-utils.h"
388690a2a7SWang Nan #include "util/bpf-loader.h"
395f9cf599SWang Nan #include "util/trigger.h"
40a074865eSWang Nan #include "util/perf-hooks.h"
41c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4258db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
437b612e29SSong Liu #include "util/bpf-event.h"
44d8871ea7SWang Nan #include "asm/bug.h"
457c6a1c65SPeter Zijlstra 
46a43783aeSArnaldo Carvalho de Melo #include <errno.h>
47fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
4867230479SArnaldo Carvalho de Melo #include <locale.h>
494208735dSArnaldo Carvalho de Melo #include <poll.h>
5086470930SIngo Molnar #include <unistd.h>
5186470930SIngo Molnar #include <sched.h>
529607ad3aSArnaldo Carvalho de Melo #include <signal.h>
53a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
544208735dSArnaldo Carvalho de Melo #include <sys/wait.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 	int			realtime_prio;
75d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
76d2db9a98SWang Nan 	bool			no_buildid_set;
77d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
78d2db9a98SWang Nan 	bool			no_buildid_cache_set;
796156681bSNamhyung Kim 	bool			buildid_all;
80ecfd7a9cSWang Nan 	bool			timestamp_filename;
8168588bafSJin Yao 	bool			timestamp_boundary;
821b43b704SJiri Olsa 	struct switch_output	switch_output;
839f065194SYang Shi 	unsigned long long	samples;
84*9d2ed645SAlexey Budankov 	cpu_set_t		affinity_mask;
850f82ebc4SArnaldo Carvalho de Melo };
8686470930SIngo Molnar 
87dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
88dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
89dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
90dc0c6127SJiri Olsa 
91*9d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
92*9d2ed645SAlexey Budankov 	"SYS", "NODE", "CPU"
93*9d2ed645SAlexey Budankov };
94*9d2ed645SAlexey Budankov 
95dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
96dc0c6127SJiri Olsa {
97dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
98dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
99dc0c6127SJiri Olsa }
100dc0c6127SJiri Olsa 
101dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
102dc0c6127SJiri Olsa {
103dc0c6127SJiri Olsa 	return rec->switch_output.size &&
104dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
105dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
106dc0c6127SJiri Olsa }
107dc0c6127SJiri Olsa 
108bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
109bfacbe3bSJiri Olsa {
110bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
111bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
112bfacbe3bSJiri Olsa }
113bfacbe3bSJiri Olsa 
114ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
115ded2b8feSJiri Olsa 			 void *bf, size_t size)
116f5970550SPeter Zijlstra {
117ded2b8feSJiri Olsa 	struct perf_data_file *file = &rec->session->data->file;
118ded2b8feSJiri Olsa 
119ded2b8feSJiri Olsa 	if (perf_data_file__write(file, bf, size) < 0) {
1204f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1218d3eca20SDavid Ahern 		return -1;
1228d3eca20SDavid Ahern 	}
123f5970550SPeter Zijlstra 
124cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
125dc0c6127SJiri Olsa 
126dc0c6127SJiri Olsa 	if (switch_output_size(rec))
127dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
128dc0c6127SJiri Olsa 
1298d3eca20SDavid Ahern 	return 0;
130f5970550SPeter Zijlstra }
131f5970550SPeter Zijlstra 
132d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
133d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
134d3d1af6fSAlexey Budankov 		void *buf, size_t size, off_t off)
135d3d1af6fSAlexey Budankov {
136d3d1af6fSAlexey Budankov 	int rc;
137d3d1af6fSAlexey Budankov 
138d3d1af6fSAlexey Budankov 	cblock->aio_fildes = trace_fd;
139d3d1af6fSAlexey Budankov 	cblock->aio_buf    = buf;
140d3d1af6fSAlexey Budankov 	cblock->aio_nbytes = size;
141d3d1af6fSAlexey Budankov 	cblock->aio_offset = off;
142d3d1af6fSAlexey Budankov 	cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
143d3d1af6fSAlexey Budankov 
144d3d1af6fSAlexey Budankov 	do {
145d3d1af6fSAlexey Budankov 		rc = aio_write(cblock);
146d3d1af6fSAlexey Budankov 		if (rc == 0) {
147d3d1af6fSAlexey Budankov 			break;
148d3d1af6fSAlexey Budankov 		} else if (errno != EAGAIN) {
149d3d1af6fSAlexey Budankov 			cblock->aio_fildes = -1;
150d3d1af6fSAlexey Budankov 			pr_err("failed to queue perf data, error: %m\n");
151d3d1af6fSAlexey Budankov 			break;
152d3d1af6fSAlexey Budankov 		}
153d3d1af6fSAlexey Budankov 	} while (1);
154d3d1af6fSAlexey Budankov 
155d3d1af6fSAlexey Budankov 	return rc;
156d3d1af6fSAlexey Budankov }
157d3d1af6fSAlexey Budankov 
158d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock)
159d3d1af6fSAlexey Budankov {
160d3d1af6fSAlexey Budankov 	void *rem_buf;
161d3d1af6fSAlexey Budankov 	off_t rem_off;
162d3d1af6fSAlexey Budankov 	size_t rem_size;
163d3d1af6fSAlexey Budankov 	int rc, aio_errno;
164d3d1af6fSAlexey Budankov 	ssize_t aio_ret, written;
165d3d1af6fSAlexey Budankov 
166d3d1af6fSAlexey Budankov 	aio_errno = aio_error(cblock);
167d3d1af6fSAlexey Budankov 	if (aio_errno == EINPROGRESS)
168d3d1af6fSAlexey Budankov 		return 0;
169d3d1af6fSAlexey Budankov 
170d3d1af6fSAlexey Budankov 	written = aio_ret = aio_return(cblock);
171d3d1af6fSAlexey Budankov 	if (aio_ret < 0) {
172d3d1af6fSAlexey Budankov 		if (aio_errno != EINTR)
173d3d1af6fSAlexey Budankov 			pr_err("failed to write perf data, error: %m\n");
174d3d1af6fSAlexey Budankov 		written = 0;
175d3d1af6fSAlexey Budankov 	}
176d3d1af6fSAlexey Budankov 
177d3d1af6fSAlexey Budankov 	rem_size = cblock->aio_nbytes - written;
178d3d1af6fSAlexey Budankov 
179d3d1af6fSAlexey Budankov 	if (rem_size == 0) {
180d3d1af6fSAlexey Budankov 		cblock->aio_fildes = -1;
181d3d1af6fSAlexey Budankov 		/*
182d3d1af6fSAlexey Budankov 		 * md->refcount is incremented in perf_mmap__push() for
183d3d1af6fSAlexey Budankov 		 * every enqueued aio write request so decrement it because
184d3d1af6fSAlexey Budankov 		 * the request is now complete.
185d3d1af6fSAlexey Budankov 		 */
186d3d1af6fSAlexey Budankov 		perf_mmap__put(md);
187d3d1af6fSAlexey Budankov 		rc = 1;
188d3d1af6fSAlexey Budankov 	} else {
189d3d1af6fSAlexey Budankov 		/*
190d3d1af6fSAlexey Budankov 		 * aio write request may require restart with the
191d3d1af6fSAlexey Budankov 		 * reminder if the kernel didn't write whole
192d3d1af6fSAlexey Budankov 		 * chunk at once.
193d3d1af6fSAlexey Budankov 		 */
194d3d1af6fSAlexey Budankov 		rem_off = cblock->aio_offset + written;
195d3d1af6fSAlexey Budankov 		rem_buf = (void *)(cblock->aio_buf + written);
196d3d1af6fSAlexey Budankov 		record__aio_write(cblock, cblock->aio_fildes,
197d3d1af6fSAlexey Budankov 				rem_buf, rem_size, rem_off);
198d3d1af6fSAlexey Budankov 		rc = 0;
199d3d1af6fSAlexey Budankov 	}
200d3d1af6fSAlexey Budankov 
201d3d1af6fSAlexey Budankov 	return rc;
202d3d1af6fSAlexey Budankov }
203d3d1af6fSAlexey Budankov 
20493f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all)
205d3d1af6fSAlexey Budankov {
20693f20c0fSAlexey Budankov 	struct aiocb **aiocb = md->aio.aiocb;
20793f20c0fSAlexey Budankov 	struct aiocb *cblocks = md->aio.cblocks;
208d3d1af6fSAlexey Budankov 	struct timespec timeout = { 0, 1000 * 1000  * 1 }; /* 1ms */
20993f20c0fSAlexey Budankov 	int i, do_suspend;
210d3d1af6fSAlexey Budankov 
211d3d1af6fSAlexey Budankov 	do {
21293f20c0fSAlexey Budankov 		do_suspend = 0;
21393f20c0fSAlexey Budankov 		for (i = 0; i < md->aio.nr_cblocks; ++i) {
21493f20c0fSAlexey Budankov 			if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
21593f20c0fSAlexey Budankov 				if (sync_all)
21693f20c0fSAlexey Budankov 					aiocb[i] = NULL;
21793f20c0fSAlexey Budankov 				else
21893f20c0fSAlexey Budankov 					return i;
21993f20c0fSAlexey Budankov 			} else {
22093f20c0fSAlexey Budankov 				/*
22193f20c0fSAlexey Budankov 				 * Started aio write is not complete yet
22293f20c0fSAlexey Budankov 				 * so it has to be waited before the
22393f20c0fSAlexey Budankov 				 * next allocation.
22493f20c0fSAlexey Budankov 				 */
22593f20c0fSAlexey Budankov 				aiocb[i] = &cblocks[i];
22693f20c0fSAlexey Budankov 				do_suspend = 1;
22793f20c0fSAlexey Budankov 			}
22893f20c0fSAlexey Budankov 		}
22993f20c0fSAlexey Budankov 		if (!do_suspend)
23093f20c0fSAlexey Budankov 			return -1;
231d3d1af6fSAlexey Budankov 
23293f20c0fSAlexey Budankov 		while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
233d3d1af6fSAlexey Budankov 			if (!(errno == EAGAIN || errno == EINTR))
234d3d1af6fSAlexey Budankov 				pr_err("failed to sync perf data, error: %m\n");
235d3d1af6fSAlexey Budankov 		}
236d3d1af6fSAlexey Budankov 	} while (1);
237d3d1af6fSAlexey Budankov }
238d3d1af6fSAlexey Budankov 
239d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off)
240d3d1af6fSAlexey Budankov {
241d3d1af6fSAlexey Budankov 	struct record *rec = to;
242d3d1af6fSAlexey Budankov 	int ret, trace_fd = rec->session->data->file.fd;
243d3d1af6fSAlexey Budankov 
244d3d1af6fSAlexey Budankov 	rec->samples++;
245d3d1af6fSAlexey Budankov 
246d3d1af6fSAlexey Budankov 	ret = record__aio_write(cblock, trace_fd, bf, size, off);
247d3d1af6fSAlexey Budankov 	if (!ret) {
248d3d1af6fSAlexey Budankov 		rec->bytes_written += size;
249d3d1af6fSAlexey Budankov 		if (switch_output_size(rec))
250d3d1af6fSAlexey Budankov 			trigger_hit(&switch_output_trigger);
251d3d1af6fSAlexey Budankov 	}
252d3d1af6fSAlexey Budankov 
253d3d1af6fSAlexey Budankov 	return ret;
254d3d1af6fSAlexey Budankov }
255d3d1af6fSAlexey Budankov 
256d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
257d3d1af6fSAlexey Budankov {
258d3d1af6fSAlexey Budankov 	return lseek(trace_fd, 0, SEEK_CUR);
259d3d1af6fSAlexey Budankov }
260d3d1af6fSAlexey Budankov 
261d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
262d3d1af6fSAlexey Budankov {
263d3d1af6fSAlexey Budankov 	lseek(trace_fd, pos, SEEK_SET);
264d3d1af6fSAlexey Budankov }
265d3d1af6fSAlexey Budankov 
266d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
267d3d1af6fSAlexey Budankov {
268d3d1af6fSAlexey Budankov 	int i;
269d3d1af6fSAlexey Budankov 	struct perf_evlist *evlist = rec->evlist;
270d3d1af6fSAlexey Budankov 	struct perf_mmap *maps = evlist->mmap;
271d3d1af6fSAlexey Budankov 
272d3d1af6fSAlexey Budankov 	if (!rec->opts.nr_cblocks)
273d3d1af6fSAlexey Budankov 		return;
274d3d1af6fSAlexey Budankov 
275d3d1af6fSAlexey Budankov 	for (i = 0; i < evlist->nr_mmaps; i++) {
276d3d1af6fSAlexey Budankov 		struct perf_mmap *map = &maps[i];
277d3d1af6fSAlexey Budankov 
278d3d1af6fSAlexey Budankov 		if (map->base)
27993f20c0fSAlexey Budankov 			record__aio_sync(map, true);
280d3d1af6fSAlexey Budankov 	}
281d3d1af6fSAlexey Budankov }
282d3d1af6fSAlexey Budankov 
283d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
28493f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
285d3d1af6fSAlexey Budankov 
286d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
28793f20c0fSAlexey Budankov 			     const char *str,
288d3d1af6fSAlexey Budankov 			     int unset)
289d3d1af6fSAlexey Budankov {
290d3d1af6fSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
291d3d1af6fSAlexey Budankov 
29293f20c0fSAlexey Budankov 	if (unset) {
293d3d1af6fSAlexey Budankov 		opts->nr_cblocks = 0;
29493f20c0fSAlexey Budankov 	} else {
29593f20c0fSAlexey Budankov 		if (str)
29693f20c0fSAlexey Budankov 			opts->nr_cblocks = strtol(str, NULL, 0);
29793f20c0fSAlexey Budankov 		if (!opts->nr_cblocks)
298d3d1af6fSAlexey Budankov 			opts->nr_cblocks = nr_cblocks_default;
29993f20c0fSAlexey Budankov 	}
300d3d1af6fSAlexey Budankov 
301d3d1af6fSAlexey Budankov 	return 0;
302d3d1af6fSAlexey Budankov }
303d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
30493f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
30593f20c0fSAlexey Budankov 
30693f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused)
307d3d1af6fSAlexey Budankov {
30893f20c0fSAlexey Budankov 	return -1;
309d3d1af6fSAlexey Budankov }
310d3d1af6fSAlexey Budankov 
311d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused,
312d3d1af6fSAlexey Budankov 		void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused)
313d3d1af6fSAlexey Budankov {
314d3d1af6fSAlexey Budankov 	return -1;
315d3d1af6fSAlexey Budankov }
316d3d1af6fSAlexey Budankov 
317d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
318d3d1af6fSAlexey Budankov {
319d3d1af6fSAlexey Budankov 	return -1;
320d3d1af6fSAlexey Budankov }
321d3d1af6fSAlexey Budankov 
322d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
323d3d1af6fSAlexey Budankov {
324d3d1af6fSAlexey Budankov }
325d3d1af6fSAlexey Budankov 
326d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
327d3d1af6fSAlexey Budankov {
328d3d1af6fSAlexey Budankov }
329d3d1af6fSAlexey Budankov #endif
330d3d1af6fSAlexey Budankov 
331d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
332d3d1af6fSAlexey Budankov {
333d3d1af6fSAlexey Budankov 	return rec->opts.nr_cblocks > 0;
334d3d1af6fSAlexey Budankov }
335d3d1af6fSAlexey Budankov 
33645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
337d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
3381d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
3391d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
340234fbbf5SArnaldo Carvalho de Melo {
3418c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
342ded2b8feSJiri Olsa 	return record__write(rec, NULL, event, event->header.size);
343234fbbf5SArnaldo Carvalho de Melo }
344234fbbf5SArnaldo Carvalho de Melo 
345ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
346d37f1586SArnaldo Carvalho de Melo {
347d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
348d37f1586SArnaldo Carvalho de Melo 
349d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
350ded2b8feSJiri Olsa 	return record__write(rec, map, bf, size);
351d37f1586SArnaldo Carvalho de Melo }
352d37f1586SArnaldo Carvalho de Melo 
3532dd6d8a1SAdrian Hunter static volatile int done;
3542dd6d8a1SAdrian Hunter static volatile int signr = -1;
3552dd6d8a1SAdrian Hunter static volatile int child_finished;
356c0bdc1c4SWang Nan 
3572dd6d8a1SAdrian Hunter static void sig_handler(int sig)
3582dd6d8a1SAdrian Hunter {
3592dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
3602dd6d8a1SAdrian Hunter 		child_finished = 1;
3612dd6d8a1SAdrian Hunter 	else
3622dd6d8a1SAdrian Hunter 		signr = sig;
3632dd6d8a1SAdrian Hunter 
3642dd6d8a1SAdrian Hunter 	done = 1;
3652dd6d8a1SAdrian Hunter }
3662dd6d8a1SAdrian Hunter 
367a074865eSWang Nan static void sigsegv_handler(int sig)
368a074865eSWang Nan {
369a074865eSWang Nan 	perf_hooks__recover();
370a074865eSWang Nan 	sighandler_dump_stack(sig);
371a074865eSWang Nan }
372a074865eSWang Nan 
3732dd6d8a1SAdrian Hunter static void record__sig_exit(void)
3742dd6d8a1SAdrian Hunter {
3752dd6d8a1SAdrian Hunter 	if (signr == -1)
3762dd6d8a1SAdrian Hunter 		return;
3772dd6d8a1SAdrian Hunter 
3782dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
3792dd6d8a1SAdrian Hunter 	raise(signr);
3802dd6d8a1SAdrian Hunter }
3812dd6d8a1SAdrian Hunter 
382e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
383e31f0d01SAdrian Hunter 
384ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
385ded2b8feSJiri Olsa 				    struct perf_mmap *map,
386ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
387ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
388ef149c25SAdrian Hunter {
389ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
3908ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
391ef149c25SAdrian Hunter 	size_t padding;
392ef149c25SAdrian Hunter 	u8 pad[8] = {0};
393ef149c25SAdrian Hunter 
3948ceb41d7SJiri Olsa 	if (!perf_data__is_pipe(data)) {
39599fa2984SAdrian Hunter 		off_t file_offset;
3968ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
39799fa2984SAdrian Hunter 		int err;
39899fa2984SAdrian Hunter 
39999fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
40099fa2984SAdrian Hunter 		if (file_offset == -1)
40199fa2984SAdrian Hunter 			return -1;
40299fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
40399fa2984SAdrian Hunter 						     event, file_offset);
40499fa2984SAdrian Hunter 		if (err)
40599fa2984SAdrian Hunter 			return err;
40699fa2984SAdrian Hunter 	}
40799fa2984SAdrian Hunter 
408ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
409ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
410ef149c25SAdrian Hunter 	if (padding)
411ef149c25SAdrian Hunter 		padding = 8 - padding;
412ef149c25SAdrian Hunter 
413ded2b8feSJiri Olsa 	record__write(rec, map, event, event->header.size);
414ded2b8feSJiri Olsa 	record__write(rec, map, data1, len1);
415ef149c25SAdrian Hunter 	if (len2)
416ded2b8feSJiri Olsa 		record__write(rec, map, data2, len2);
417ded2b8feSJiri Olsa 	record__write(rec, map, &pad, padding);
418ef149c25SAdrian Hunter 
419ef149c25SAdrian Hunter 	return 0;
420ef149c25SAdrian Hunter }
421ef149c25SAdrian Hunter 
422ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
423e035f4caSJiri Olsa 				      struct perf_mmap *map)
424ef149c25SAdrian Hunter {
425ef149c25SAdrian Hunter 	int ret;
426ef149c25SAdrian Hunter 
427e035f4caSJiri Olsa 	ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
428ef149c25SAdrian Hunter 				  record__process_auxtrace);
429ef149c25SAdrian Hunter 	if (ret < 0)
430ef149c25SAdrian Hunter 		return ret;
431ef149c25SAdrian Hunter 
432ef149c25SAdrian Hunter 	if (ret)
433ef149c25SAdrian Hunter 		rec->samples++;
434ef149c25SAdrian Hunter 
435ef149c25SAdrian Hunter 	return 0;
436ef149c25SAdrian Hunter }
437ef149c25SAdrian Hunter 
4382dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
439e035f4caSJiri Olsa 					       struct perf_mmap *map)
4402dd6d8a1SAdrian Hunter {
4412dd6d8a1SAdrian Hunter 	int ret;
4422dd6d8a1SAdrian Hunter 
443e035f4caSJiri Olsa 	ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
4442dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
4452dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
4462dd6d8a1SAdrian Hunter 	if (ret < 0)
4472dd6d8a1SAdrian Hunter 		return ret;
4482dd6d8a1SAdrian Hunter 
4492dd6d8a1SAdrian Hunter 	if (ret)
4502dd6d8a1SAdrian Hunter 		rec->samples++;
4512dd6d8a1SAdrian Hunter 
4522dd6d8a1SAdrian Hunter 	return 0;
4532dd6d8a1SAdrian Hunter }
4542dd6d8a1SAdrian Hunter 
4552dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
4562dd6d8a1SAdrian Hunter {
4572dd6d8a1SAdrian Hunter 	int i;
4582dd6d8a1SAdrian Hunter 	int rc = 0;
4592dd6d8a1SAdrian Hunter 
4602dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
461e035f4caSJiri Olsa 		struct perf_mmap *map = &rec->evlist->mmap[i];
4622dd6d8a1SAdrian Hunter 
463e035f4caSJiri Olsa 		if (!map->auxtrace_mmap.base)
4642dd6d8a1SAdrian Hunter 			continue;
4652dd6d8a1SAdrian Hunter 
466e035f4caSJiri Olsa 		if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
4672dd6d8a1SAdrian Hunter 			rc = -1;
4682dd6d8a1SAdrian Hunter 			goto out;
4692dd6d8a1SAdrian Hunter 		}
4702dd6d8a1SAdrian Hunter 	}
4712dd6d8a1SAdrian Hunter out:
4722dd6d8a1SAdrian Hunter 	return rc;
4732dd6d8a1SAdrian Hunter }
4742dd6d8a1SAdrian Hunter 
4752dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
4762dd6d8a1SAdrian Hunter {
4772dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
4782dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
4795f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
4802dd6d8a1SAdrian Hunter 	} else {
4815f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
4825f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
4835f9cf599SWang Nan 		else
4845f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
4852dd6d8a1SAdrian Hunter 	}
4862dd6d8a1SAdrian Hunter }
4872dd6d8a1SAdrian Hunter 
4884b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
4894b5ea3bdSAdrian Hunter {
4904b5ea3bdSAdrian Hunter 	int err;
4914b5ea3bdSAdrian Hunter 
4924b5ea3bdSAdrian Hunter 	if (!rec->itr) {
4934b5ea3bdSAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
4944b5ea3bdSAdrian Hunter 		if (err)
4954b5ea3bdSAdrian Hunter 			return err;
4964b5ea3bdSAdrian Hunter 	}
4974b5ea3bdSAdrian Hunter 
4984b5ea3bdSAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
4994b5ea3bdSAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
5004b5ea3bdSAdrian Hunter 	if (err)
5014b5ea3bdSAdrian Hunter 		return err;
5024b5ea3bdSAdrian Hunter 
5034b5ea3bdSAdrian Hunter 	return auxtrace_parse_filters(rec->evlist);
5044b5ea3bdSAdrian Hunter }
5054b5ea3bdSAdrian Hunter 
506e31f0d01SAdrian Hunter #else
507e31f0d01SAdrian Hunter 
508e31f0d01SAdrian Hunter static inline
509e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
510e035f4caSJiri Olsa 			       struct perf_mmap *map __maybe_unused)
511e31f0d01SAdrian Hunter {
512e31f0d01SAdrian Hunter 	return 0;
513e31f0d01SAdrian Hunter }
514e31f0d01SAdrian Hunter 
5152dd6d8a1SAdrian Hunter static inline
5162dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
5172dd6d8a1SAdrian Hunter {
5182dd6d8a1SAdrian Hunter }
5192dd6d8a1SAdrian Hunter 
5202dd6d8a1SAdrian Hunter static inline
5212dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
5222dd6d8a1SAdrian Hunter {
5232dd6d8a1SAdrian Hunter 	return 0;
5242dd6d8a1SAdrian Hunter }
5252dd6d8a1SAdrian Hunter 
5264b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
5274b5ea3bdSAdrian Hunter {
5284b5ea3bdSAdrian Hunter 	return 0;
5294b5ea3bdSAdrian Hunter }
5304b5ea3bdSAdrian Hunter 
531e31f0d01SAdrian Hunter #endif
532e31f0d01SAdrian Hunter 
533cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
534cda57a8cSWang Nan 			       struct perf_evlist *evlist)
535cda57a8cSWang Nan {
536cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
537cda57a8cSWang Nan 	char msg[512];
538cda57a8cSWang Nan 
5397a276ff6SWang Nan 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
540cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
541*9d2ed645SAlexey Budankov 				 opts->auxtrace_snapshot_mode,
542*9d2ed645SAlexey Budankov 				 opts->nr_cblocks, opts->affinity) < 0) {
543cda57a8cSWang Nan 		if (errno == EPERM) {
544cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
545cda57a8cSWang Nan 			       "Consider increasing "
546cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
547cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
548cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
549cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
550cda57a8cSWang Nan 			return -errno;
551cda57a8cSWang Nan 		} else {
552cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
553c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
554cda57a8cSWang Nan 			if (errno)
555cda57a8cSWang Nan 				return -errno;
556cda57a8cSWang Nan 			else
557cda57a8cSWang Nan 				return -EINVAL;
558cda57a8cSWang Nan 		}
559cda57a8cSWang Nan 	}
560cda57a8cSWang Nan 	return 0;
561cda57a8cSWang Nan }
562cda57a8cSWang Nan 
563cda57a8cSWang Nan static int record__mmap(struct record *rec)
564cda57a8cSWang Nan {
565cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
566cda57a8cSWang Nan }
567cda57a8cSWang Nan 
5688c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
569dd7927f4SArnaldo Carvalho de Melo {
570d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
5716a4bb04cSJiri Olsa 	struct perf_evsel *pos;
572d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
573d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
574b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
5758d3eca20SDavid Ahern 	int rc = 0;
576dd7927f4SArnaldo Carvalho de Melo 
577d3dbf43cSArnaldo Carvalho de Melo 	/*
578d3dbf43cSArnaldo Carvalho de Melo 	 * For initial_delay we need to add a dummy event so that we can track
579d3dbf43cSArnaldo Carvalho de Melo 	 * PERF_RECORD_MMAP while we wait for the initial delay to enable the
580d3dbf43cSArnaldo Carvalho de Melo 	 * real events, the ones asked by the user.
581d3dbf43cSArnaldo Carvalho de Melo 	 */
582d3dbf43cSArnaldo Carvalho de Melo 	if (opts->initial_delay) {
583d3dbf43cSArnaldo Carvalho de Melo 		if (perf_evlist__add_dummy(evlist))
584d3dbf43cSArnaldo Carvalho de Melo 			return -ENOMEM;
585d3dbf43cSArnaldo Carvalho de Melo 
586d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__first(evlist);
587d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 0;
588d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__last(evlist);
589d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 1;
590d3dbf43cSArnaldo Carvalho de Melo 		pos->attr.enable_on_exec = 1;
591d3dbf43cSArnaldo Carvalho de Melo 	}
592d3dbf43cSArnaldo Carvalho de Melo 
593e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
594cac21425SJiri Olsa 
595e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
5963da297a6SIngo Molnar try_again:
597d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
59856e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
599bb963e16SNamhyung Kim 				if (verbose > 0)
600c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
6013da297a6SIngo Molnar 				goto try_again;
6023da297a6SIngo Molnar 			}
603cf99ad14SAndi Kleen 			if ((errno == EINVAL || errno == EBADF) &&
604cf99ad14SAndi Kleen 			    pos->leader != pos &&
605cf99ad14SAndi Kleen 			    pos->weak_group) {
606cf99ad14SAndi Kleen 			        pos = perf_evlist__reset_weak_group(evlist, pos);
607cf99ad14SAndi Kleen 				goto try_again;
608cf99ad14SAndi Kleen 			}
60956e52e85SArnaldo Carvalho de Melo 			rc = -errno;
61056e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
61156e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
61256e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
6138d3eca20SDavid Ahern 			goto out;
6147c6a1c65SPeter Zijlstra 		}
615bfd8f72cSAndi Kleen 
616bfd8f72cSAndi Kleen 		pos->supported = true;
6177c6a1c65SPeter Zijlstra 	}
6187c6a1c65SPeter Zijlstra 
61923d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
62062d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
62123d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
622c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
6238d3eca20SDavid Ahern 		rc = -1;
6248d3eca20SDavid Ahern 		goto out;
6250a102479SFrederic Weisbecker 	}
6260a102479SFrederic Weisbecker 
627cda57a8cSWang Nan 	rc = record__mmap(rec);
628cda57a8cSWang Nan 	if (rc)
6298d3eca20SDavid Ahern 		goto out;
6300a27d7f9SArnaldo Carvalho de Melo 
631a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
6327b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
6338d3eca20SDavid Ahern out:
6348d3eca20SDavid Ahern 	return rc;
635a91e5431SArnaldo Carvalho de Melo }
636a91e5431SArnaldo Carvalho de Melo 
637e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
638e3d59112SNamhyung Kim 				union perf_event *event,
639e3d59112SNamhyung Kim 				struct perf_sample *sample,
640e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
641e3d59112SNamhyung Kim 				struct machine *machine)
642e3d59112SNamhyung Kim {
643e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
644e3d59112SNamhyung Kim 
64568588bafSJin Yao 	if (rec->evlist->first_sample_time == 0)
64668588bafSJin Yao 		rec->evlist->first_sample_time = sample->time;
647e3d59112SNamhyung Kim 
64868588bafSJin Yao 	rec->evlist->last_sample_time = sample->time;
64968588bafSJin Yao 
65068588bafSJin Yao 	if (rec->buildid_all)
65168588bafSJin Yao 		return 0;
65268588bafSJin Yao 
65368588bafSJin Yao 	rec->samples++;
654e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
655e3d59112SNamhyung Kim }
656e3d59112SNamhyung Kim 
6578c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
6586122e4e4SArnaldo Carvalho de Melo {
6598ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
660f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
6616122e4e4SArnaldo Carvalho de Melo 
6628ceb41d7SJiri Olsa 	if (data->size == 0)
6639f591fd7SArnaldo Carvalho de Melo 		return 0;
6649f591fd7SArnaldo Carvalho de Melo 
66500dc8657SNamhyung Kim 	/*
66600dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
66700dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
66800dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
66900dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
67000dc8657SNamhyung Kim 	 *
67100dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
67200dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
67300dc8657SNamhyung Kim 	 */
67400dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
67500dc8657SNamhyung Kim 
6766156681bSNamhyung Kim 	/*
6776156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
67868588bafSJin Yao 	 * so no need to process samples. But if timestamp_boundary is enabled,
67968588bafSJin Yao 	 * it still needs to walk on all samples to get the timestamps of
68068588bafSJin Yao 	 * first/last samples.
6816156681bSNamhyung Kim 	 */
68268588bafSJin Yao 	if (rec->buildid_all && !rec->timestamp_boundary)
6836156681bSNamhyung Kim 		rec->tool.sample = NULL;
6846156681bSNamhyung Kim 
685b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
6866122e4e4SArnaldo Carvalho de Melo }
6876122e4e4SArnaldo Carvalho de Melo 
6888115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
689a1645ce1SZhang, Yanmin {
690a1645ce1SZhang, Yanmin 	int err;
69145694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
692a1645ce1SZhang, Yanmin 	/*
693a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
694a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
695a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
696a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
697a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
698a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
699a1645ce1SZhang, Yanmin 	 */
70045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
701743eb868SArnaldo Carvalho de Melo 					     machine);
702a1645ce1SZhang, Yanmin 	if (err < 0)
703a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
70423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
705a1645ce1SZhang, Yanmin 
706a1645ce1SZhang, Yanmin 	/*
707a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
708a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
709a1645ce1SZhang, Yanmin 	 */
71045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
7110ae617beSAdrian Hunter 						 machine);
712a1645ce1SZhang, Yanmin 	if (err < 0)
713a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
71423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
715a1645ce1SZhang, Yanmin }
716a1645ce1SZhang, Yanmin 
71798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
71898402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
71998402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
72098402807SFrederic Weisbecker };
72198402807SFrederic Weisbecker 
722a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
7230b72d69aSWang Nan 				    bool overwrite)
72498402807SFrederic Weisbecker {
725dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
7260e2e63ddSPeter Zijlstra 	int i;
7278d3eca20SDavid Ahern 	int rc = 0;
728a4ea0ec4SWang Nan 	struct perf_mmap *maps;
729d3d1af6fSAlexey Budankov 	int trace_fd = rec->data.file.fd;
730d3d1af6fSAlexey Budankov 	off_t off;
73198402807SFrederic Weisbecker 
732cb21686bSWang Nan 	if (!evlist)
733cb21686bSWang Nan 		return 0;
734ef149c25SAdrian Hunter 
7350b72d69aSWang Nan 	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
736a4ea0ec4SWang Nan 	if (!maps)
737a4ea0ec4SWang Nan 		return 0;
738cb21686bSWang Nan 
7390b72d69aSWang Nan 	if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
74054cc54deSWang Nan 		return 0;
74154cc54deSWang Nan 
742d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
743d3d1af6fSAlexey Budankov 		off = record__aio_get_pos(trace_fd);
744d3d1af6fSAlexey Budankov 
745a4ea0ec4SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
746e035f4caSJiri Olsa 		struct perf_mmap *map = &maps[i];
747a4ea0ec4SWang Nan 
748e035f4caSJiri Olsa 		if (map->base) {
749d3d1af6fSAlexey Budankov 			if (!record__aio_enabled(rec)) {
750e035f4caSJiri Olsa 				if (perf_mmap__push(map, rec, record__pushfn) != 0) {
7518d3eca20SDavid Ahern 					rc = -1;
7528d3eca20SDavid Ahern 					goto out;
7538d3eca20SDavid Ahern 				}
754d3d1af6fSAlexey Budankov 			} else {
75593f20c0fSAlexey Budankov 				int idx;
756d3d1af6fSAlexey Budankov 				/*
757d3d1af6fSAlexey Budankov 				 * Call record__aio_sync() to wait till map->data buffer
758d3d1af6fSAlexey Budankov 				 * becomes available after previous aio write request.
759d3d1af6fSAlexey Budankov 				 */
76093f20c0fSAlexey Budankov 				idx = record__aio_sync(map, false);
76193f20c0fSAlexey Budankov 				if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) {
762d3d1af6fSAlexey Budankov 					record__aio_set_pos(trace_fd, off);
763d3d1af6fSAlexey Budankov 					rc = -1;
764d3d1af6fSAlexey Budankov 					goto out;
765d3d1af6fSAlexey Budankov 				}
766d3d1af6fSAlexey Budankov 			}
7678d3eca20SDavid Ahern 		}
768ef149c25SAdrian Hunter 
769e035f4caSJiri Olsa 		if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
770e035f4caSJiri Olsa 		    record__auxtrace_mmap_read(rec, map) != 0) {
771ef149c25SAdrian Hunter 			rc = -1;
772ef149c25SAdrian Hunter 			goto out;
773ef149c25SAdrian Hunter 		}
77498402807SFrederic Weisbecker 	}
77598402807SFrederic Weisbecker 
776d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
777d3d1af6fSAlexey Budankov 		record__aio_set_pos(trace_fd, off);
778d3d1af6fSAlexey Budankov 
779dcabb507SJiri Olsa 	/*
780dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
781dcabb507SJiri Olsa 	 * at least one event.
782dcabb507SJiri Olsa 	 */
783dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
784ded2b8feSJiri Olsa 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
7858d3eca20SDavid Ahern 
7860b72d69aSWang Nan 	if (overwrite)
78754cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
7888d3eca20SDavid Ahern out:
7898d3eca20SDavid Ahern 	return rc;
79098402807SFrederic Weisbecker }
79198402807SFrederic Weisbecker 
792cb21686bSWang Nan static int record__mmap_read_all(struct record *rec)
793cb21686bSWang Nan {
794cb21686bSWang Nan 	int err;
795cb21686bSWang Nan 
796a4ea0ec4SWang Nan 	err = record__mmap_read_evlist(rec, rec->evlist, false);
797cb21686bSWang Nan 	if (err)
798cb21686bSWang Nan 		return err;
799cb21686bSWang Nan 
80005737464SWang Nan 	return record__mmap_read_evlist(rec, rec->evlist, true);
801cb21686bSWang Nan }
802cb21686bSWang Nan 
8038c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
80457706abcSDavid Ahern {
80557706abcSDavid Ahern 	struct perf_session *session = rec->session;
80657706abcSDavid Ahern 	int feat;
80757706abcSDavid Ahern 
80857706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
80957706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
81057706abcSDavid Ahern 
81157706abcSDavid Ahern 	if (rec->no_buildid)
81257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
81357706abcSDavid Ahern 
8143e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
81557706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
81657706abcSDavid Ahern 
81757706abcSDavid Ahern 	if (!rec->opts.branch_stack)
81857706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
819ef149c25SAdrian Hunter 
820ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
821ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
822ffa517adSJiri Olsa 
823cf790516SAlexey Budankov 	if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
824cf790516SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_CLOCKID);
825cf790516SAlexey Budankov 
826ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
82757706abcSDavid Ahern }
82857706abcSDavid Ahern 
829e1ab48baSWang Nan static void
830e1ab48baSWang Nan record__finish_output(struct record *rec)
831e1ab48baSWang Nan {
8328ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
8338ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
834e1ab48baSWang Nan 
8358ceb41d7SJiri Olsa 	if (data->is_pipe)
836e1ab48baSWang Nan 		return;
837e1ab48baSWang Nan 
838e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
8398ceb41d7SJiri Olsa 	data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
840e1ab48baSWang Nan 
841e1ab48baSWang Nan 	if (!rec->no_buildid) {
842e1ab48baSWang Nan 		process_buildids(rec);
843e1ab48baSWang Nan 
844e1ab48baSWang Nan 		if (rec->buildid_all)
845e1ab48baSWang Nan 			dsos__hit_all(rec->session);
846e1ab48baSWang Nan 	}
847e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
848e1ab48baSWang Nan 
849e1ab48baSWang Nan 	return;
850e1ab48baSWang Nan }
851e1ab48baSWang Nan 
8524ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
853be7b0c9eSWang Nan {
8549d6aae72SArnaldo Carvalho de Melo 	int err;
8559d6aae72SArnaldo Carvalho de Melo 	struct thread_map *thread_map;
856be7b0c9eSWang Nan 
8574ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
8584ea648aeSWang Nan 		return 0;
8594ea648aeSWang Nan 
8609d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
8619d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
8629d6aae72SArnaldo Carvalho de Melo 		return -1;
8639d6aae72SArnaldo Carvalho de Melo 
8649d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
865be7b0c9eSWang Nan 						 process_synthesized_event,
866be7b0c9eSWang Nan 						 &rec->session->machines.host,
8673fcb10e4SMark Drayton 						 rec->opts.sample_address);
8689d6aae72SArnaldo Carvalho de Melo 	thread_map__put(thread_map);
8699d6aae72SArnaldo Carvalho de Melo 	return err;
870be7b0c9eSWang Nan }
871be7b0c9eSWang Nan 
8724ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
8733c1cb7e3SWang Nan 
874ecfd7a9cSWang Nan static int
875ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
876ecfd7a9cSWang Nan {
8778ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
878ecfd7a9cSWang Nan 	int fd, err;
879ecfd7a9cSWang Nan 
880ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
881ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
882ecfd7a9cSWang Nan 
883d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
884d3d1af6fSAlexey Budankov 
8854ea648aeSWang Nan 	record__synthesize(rec, true);
8864ea648aeSWang Nan 	if (target__none(&rec->opts.target))
8874ea648aeSWang Nan 		record__synthesize_workload(rec, true);
8884ea648aeSWang Nan 
889ecfd7a9cSWang Nan 	rec->samples = 0;
890ecfd7a9cSWang Nan 	record__finish_output(rec);
891ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
892ecfd7a9cSWang Nan 	if (err) {
893ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
894ecfd7a9cSWang Nan 		return -EINVAL;
895ecfd7a9cSWang Nan 	}
896ecfd7a9cSWang Nan 
8978ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
898ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
899ecfd7a9cSWang Nan 				    at_exit);
900ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
901ecfd7a9cSWang Nan 		rec->bytes_written = 0;
902ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
903ecfd7a9cSWang Nan 	}
904ecfd7a9cSWang Nan 
905ecfd7a9cSWang Nan 	if (!quiet)
906ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
907eae8ad80SJiri Olsa 			data->file.path, timestamp);
9083c1cb7e3SWang Nan 
9093c1cb7e3SWang Nan 	/* Output tracking events */
910be7b0c9eSWang Nan 	if (!at_exit) {
9114ea648aeSWang Nan 		record__synthesize(rec, false);
9123c1cb7e3SWang Nan 
913be7b0c9eSWang Nan 		/*
914be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
915be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
916be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
917be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
918be7b0c9eSWang Nan 		 * contain map and comm information.
919be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
920be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
921be7b0c9eSWang Nan 		 */
922be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
9234ea648aeSWang Nan 			record__synthesize_workload(rec, false);
924be7b0c9eSWang Nan 	}
925ecfd7a9cSWang Nan 	return fd;
926ecfd7a9cSWang Nan }
927ecfd7a9cSWang Nan 
928f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
929f33cbe72SArnaldo Carvalho de Melo 
930f33cbe72SArnaldo Carvalho de Melo /*
931f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
932f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
933f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
934f33cbe72SArnaldo Carvalho de Melo  */
93545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
93645604710SNamhyung Kim 					siginfo_t *info,
937f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
938f33cbe72SArnaldo Carvalho de Melo {
939f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
940f33cbe72SArnaldo Carvalho de Melo 	done = 1;
941f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
942f33cbe72SArnaldo Carvalho de Melo }
943f33cbe72SArnaldo Carvalho de Melo 
9442dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
945bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
9462dd6d8a1SAdrian Hunter 
94746bc29b9SAdrian Hunter int __weak
94846bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
94946bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
95046bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
95146bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
95246bc29b9SAdrian Hunter {
95346bc29b9SAdrian Hunter 	return 0;
95446bc29b9SAdrian Hunter }
95546bc29b9SAdrian Hunter 
956ee667f94SWang Nan static const struct perf_event_mmap_page *
957ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist)
958ee667f94SWang Nan {
959b2cb615dSWang Nan 	if (evlist) {
960b2cb615dSWang Nan 		if (evlist->mmap && evlist->mmap[0].base)
961ee667f94SWang Nan 			return evlist->mmap[0].base;
9620b72d69aSWang Nan 		if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
9630b72d69aSWang Nan 			return evlist->overwrite_mmap[0].base;
964b2cb615dSWang Nan 	}
965ee667f94SWang Nan 	return NULL;
966ee667f94SWang Nan }
967ee667f94SWang Nan 
968c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
969c45628b0SWang Nan {
970ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
971ee667f94SWang Nan 
972ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
973ee667f94SWang Nan 	if (pc)
974ee667f94SWang Nan 		return pc;
975c45628b0SWang Nan 	return NULL;
976c45628b0SWang Nan }
977c45628b0SWang Nan 
9784ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
979c45c86ebSWang Nan {
980c45c86ebSWang Nan 	struct perf_session *session = rec->session;
981c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
9828ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
983c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
984c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
9858ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
986c45c86ebSWang Nan 	int err = 0;
987c45c86ebSWang Nan 
9884ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
9894ea648aeSWang Nan 		return 0;
9904ea648aeSWang Nan 
9918ceb41d7SJiri Olsa 	if (data->is_pipe) {
992a2015516SJiri Olsa 		/*
993a2015516SJiri Olsa 		 * We need to synthesize events first, because some
994a2015516SJiri Olsa 		 * features works on top of them (on report side).
995a2015516SJiri Olsa 		 */
996318ec184SJiri Olsa 		err = perf_event__synthesize_attrs(tool, rec->evlist,
997c45c86ebSWang Nan 						   process_synthesized_event);
998c45c86ebSWang Nan 		if (err < 0) {
999c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
1000c45c86ebSWang Nan 			goto out;
1001c45c86ebSWang Nan 		}
1002c45c86ebSWang Nan 
1003a2015516SJiri Olsa 		err = perf_event__synthesize_features(tool, session, rec->evlist,
1004a2015516SJiri Olsa 						      process_synthesized_event);
1005a2015516SJiri Olsa 		if (err < 0) {
1006a2015516SJiri Olsa 			pr_err("Couldn't synthesize features.\n");
1007a2015516SJiri Olsa 			return err;
1008a2015516SJiri Olsa 		}
1009a2015516SJiri Olsa 
1010c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
1011c45c86ebSWang Nan 			/*
1012c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
1013c45c86ebSWang Nan 			 * there were no tracepoints so its not really
1014c45c86ebSWang Nan 			 * an error, just that we don't need to
1015c45c86ebSWang Nan 			 * synthesize anything.  We really have to
1016c45c86ebSWang Nan 			 * return this more properly and also
1017c45c86ebSWang Nan 			 * propagate errors that now are calling die()
1018c45c86ebSWang Nan 			 */
1019c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
1020c45c86ebSWang Nan 								  process_synthesized_event);
1021c45c86ebSWang Nan 			if (err <= 0) {
1022c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
1023c45c86ebSWang Nan 				goto out;
1024c45c86ebSWang Nan 			}
1025c45c86ebSWang Nan 			rec->bytes_written += err;
1026c45c86ebSWang Nan 		}
1027c45c86ebSWang Nan 	}
1028c45c86ebSWang Nan 
1029c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
103046bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
103146bc29b9SAdrian Hunter 	if (err)
103246bc29b9SAdrian Hunter 		goto out;
103346bc29b9SAdrian Hunter 
1034c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
1035c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
1036c45c86ebSWang Nan 					session, process_synthesized_event);
1037c45c86ebSWang Nan 		if (err)
1038c45c86ebSWang Nan 			goto out;
1039c45c86ebSWang Nan 	}
1040c45c86ebSWang Nan 
10416c443954SArnaldo Carvalho de Melo 	if (!perf_evlist__exclude_kernel(rec->evlist)) {
1042c45c86ebSWang Nan 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
1043c45c86ebSWang Nan 							 machine);
1044c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
1045c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1046c45c86ebSWang Nan 				   "Check /proc/kallsyms permission or run as root.\n");
1047c45c86ebSWang Nan 
1048c45c86ebSWang Nan 		err = perf_event__synthesize_modules(tool, process_synthesized_event,
1049c45c86ebSWang Nan 						     machine);
1050c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
1051c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1052c45c86ebSWang Nan 				   "Check /proc/modules permission or run as root.\n");
10536c443954SArnaldo Carvalho de Melo 	}
1054c45c86ebSWang Nan 
1055c45c86ebSWang Nan 	if (perf_guest) {
1056c45c86ebSWang Nan 		machines__process_guests(&session->machines,
1057c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
1058c45c86ebSWang Nan 	}
1059c45c86ebSWang Nan 
1060bfd8f72cSAndi Kleen 	err = perf_event__synthesize_extra_attr(&rec->tool,
1061bfd8f72cSAndi Kleen 						rec->evlist,
1062bfd8f72cSAndi Kleen 						process_synthesized_event,
1063bfd8f72cSAndi Kleen 						data->is_pipe);
1064bfd8f72cSAndi Kleen 	if (err)
1065bfd8f72cSAndi Kleen 		goto out;
1066bfd8f72cSAndi Kleen 
1067373565d2SAndi Kleen 	err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads,
1068373565d2SAndi Kleen 						 process_synthesized_event,
1069373565d2SAndi Kleen 						NULL);
1070373565d2SAndi Kleen 	if (err < 0) {
1071373565d2SAndi Kleen 		pr_err("Couldn't synthesize thread map.\n");
1072373565d2SAndi Kleen 		return err;
1073373565d2SAndi Kleen 	}
1074373565d2SAndi Kleen 
1075373565d2SAndi Kleen 	err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus,
1076373565d2SAndi Kleen 					     process_synthesized_event, NULL);
1077373565d2SAndi Kleen 	if (err < 0) {
1078373565d2SAndi Kleen 		pr_err("Couldn't synthesize cpu map.\n");
1079373565d2SAndi Kleen 		return err;
1080373565d2SAndi Kleen 	}
1081373565d2SAndi Kleen 
10827b612e29SSong Liu 	err = perf_event__synthesize_bpf_events(tool, process_synthesized_event,
10837b612e29SSong Liu 						machine, opts);
10847b612e29SSong Liu 	if (err < 0)
10857b612e29SSong Liu 		pr_warning("Couldn't synthesize bpf events.\n");
10867b612e29SSong Liu 
1087c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
1088c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
10893fcb10e4SMark Drayton 					    1);
1090c45c86ebSWang Nan out:
1091c45c86ebSWang Nan 	return err;
1092c45c86ebSWang Nan }
1093c45c86ebSWang Nan 
10948c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
109586470930SIngo Molnar {
109657706abcSDavid Ahern 	int err;
109745604710SNamhyung Kim 	int status = 0;
10988b412664SPeter Zijlstra 	unsigned long waking = 0;
109946be604bSZhang, Yanmin 	const bool forks = argc > 0;
110045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
1101b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
11028ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1103d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
11046dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
110542aa276fSNamhyung Kim 	int fd;
110686470930SIngo Molnar 
110745604710SNamhyung Kim 	atexit(record__sig_exit);
1108f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
1109f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
1110804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
1111a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
1112c0bdc1c4SWang Nan 
1113f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
1114f3b3614aSHari Bathini 		tool->namespace_events = true;
1115f3b3614aSHari Bathini 
1116dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
11172dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
11183c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
11195f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
1120dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
11213c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
1122c0bdc1c4SWang Nan 	} else {
11232dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
1124c0bdc1c4SWang Nan 	}
1125f5970550SPeter Zijlstra 
11268ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
112794c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
1128ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
1129a9a70bbcSArnaldo Carvalho de Melo 		return -1;
1130a9a70bbcSArnaldo Carvalho de Melo 	}
1131a9a70bbcSArnaldo Carvalho de Melo 
11328ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
1133d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
1134d20deb64SArnaldo Carvalho de Melo 
11358c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
1136330aa675SStephane Eranian 
1137cf790516SAlexey Budankov 	if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
1138cf790516SAlexey Budankov 		session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
1139cf790516SAlexey Budankov 
1140d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
11413e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
11428ceb41d7SJiri Olsa 						    argv, data->is_pipe,
1143735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
114435b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
114535b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
114645604710SNamhyung Kim 			status = err;
114735b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
1148856e9660SPeter Zijlstra 		}
1149856e9660SPeter Zijlstra 	}
1150856e9660SPeter Zijlstra 
1151ad46e48cSJiri Olsa 	/*
1152ad46e48cSJiri Olsa 	 * If we have just single event and are sending data
1153ad46e48cSJiri Olsa 	 * through pipe, we need to force the ids allocation,
1154ad46e48cSJiri Olsa 	 * because we synthesize event name through the pipe
1155ad46e48cSJiri Olsa 	 * and need the id for that.
1156ad46e48cSJiri Olsa 	 */
1157ad46e48cSJiri Olsa 	if (data->is_pipe && rec->evlist->nr_entries == 1)
1158ad46e48cSJiri Olsa 		rec->opts.sample_id = true;
1159ad46e48cSJiri Olsa 
11608c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
11618d3eca20SDavid Ahern 		err = -1;
116245604710SNamhyung Kim 		goto out_child;
11638d3eca20SDavid Ahern 	}
116486470930SIngo Molnar 
11658690a2a7SWang Nan 	err = bpf__apply_obj_config();
11668690a2a7SWang Nan 	if (err) {
11678690a2a7SWang Nan 		char errbuf[BUFSIZ];
11688690a2a7SWang Nan 
11698690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
11708690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
11718690a2a7SWang Nan 			 errbuf);
11728690a2a7SWang Nan 		goto out_child;
11738690a2a7SWang Nan 	}
11748690a2a7SWang Nan 
1175cca8482cSAdrian Hunter 	/*
1176cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
1177cca8482cSAdrian Hunter 	 * evlist.
1178cca8482cSAdrian Hunter 	 */
1179cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
1180cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
1181cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
1182cca8482cSAdrian Hunter 	}
1183cca8482cSAdrian Hunter 
11843e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
1185a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
1186a8bb559bSNamhyung Kim 
11878ceb41d7SJiri Olsa 	if (data->is_pipe) {
118842aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
1189529870e3STom Zanussi 		if (err < 0)
119045604710SNamhyung Kim 			goto out_child;
1191563aecb2SJiri Olsa 	} else {
119242aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
1193d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
119445604710SNamhyung Kim 			goto out_child;
1195d5eed904SArnaldo Carvalho de Melo 	}
11967c6a1c65SPeter Zijlstra 
1197d3665498SDavid Ahern 	if (!rec->no_buildid
1198e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
1199d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
1200e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
12018d3eca20SDavid Ahern 		err = -1;
120245604710SNamhyung Kim 		goto out_child;
1203e20960c0SRobert Richter 	}
1204e20960c0SRobert Richter 
12054ea648aeSWang Nan 	err = record__synthesize(rec, false);
1206c45c86ebSWang Nan 	if (err < 0)
120745604710SNamhyung Kim 		goto out_child;
12088d3eca20SDavid Ahern 
1209d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
121086470930SIngo Molnar 		struct sched_param param;
121186470930SIngo Molnar 
1212d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
121386470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
12146beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
12158d3eca20SDavid Ahern 			err = -1;
121645604710SNamhyung Kim 			goto out_child;
121786470930SIngo Molnar 		}
121886470930SIngo Molnar 	}
121986470930SIngo Molnar 
1220774cb499SJiri Olsa 	/*
1221774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
1222774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
1223774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
1224774cb499SJiri Olsa 	 */
12256619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
12263e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
1227764e16a3SDavid Ahern 
1228856e9660SPeter Zijlstra 	/*
1229856e9660SPeter Zijlstra 	 * Let the child rip
1230856e9660SPeter Zijlstra 	 */
1231e803cf97SNamhyung Kim 	if (forks) {
123220a8a3cfSJiri Olsa 		struct machine *machine = &session->machines.host;
1233e5bed564SNamhyung Kim 		union perf_event *event;
1234e907caf3SHari Bathini 		pid_t tgid;
1235e5bed564SNamhyung Kim 
1236e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
1237e5bed564SNamhyung Kim 		if (event == NULL) {
1238e5bed564SNamhyung Kim 			err = -ENOMEM;
1239e5bed564SNamhyung Kim 			goto out_child;
1240e5bed564SNamhyung Kim 		}
1241e5bed564SNamhyung Kim 
1242e803cf97SNamhyung Kim 		/*
1243e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
1244e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
1245e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
1246e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
1247e803cf97SNamhyung Kim 		 */
1248e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
1249e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
1250e803cf97SNamhyung Kim 						   process_synthesized_event,
1251e803cf97SNamhyung Kim 						   machine);
1252e5bed564SNamhyung Kim 		free(event);
1253e803cf97SNamhyung Kim 
1254e907caf3SHari Bathini 		if (tgid == -1)
1255e907caf3SHari Bathini 			goto out_child;
1256e907caf3SHari Bathini 
1257e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
1258e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1259e907caf3SHari Bathini 			       machine->id_hdr_size);
1260e907caf3SHari Bathini 		if (event == NULL) {
1261e907caf3SHari Bathini 			err = -ENOMEM;
1262e907caf3SHari Bathini 			goto out_child;
1263e907caf3SHari Bathini 		}
1264e907caf3SHari Bathini 
1265e907caf3SHari Bathini 		/*
1266e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
1267e907caf3SHari Bathini 		 */
1268e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
1269e907caf3SHari Bathini 						  rec->evlist->workload.pid,
1270e907caf3SHari Bathini 						  tgid, process_synthesized_event,
1271e907caf3SHari Bathini 						  machine);
1272e907caf3SHari Bathini 		free(event);
1273e907caf3SHari Bathini 
12743e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
1275e803cf97SNamhyung Kim 	}
1276856e9660SPeter Zijlstra 
12776619a53eSAndi Kleen 	if (opts->initial_delay) {
12780693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
12796619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
12806619a53eSAndi Kleen 	}
12816619a53eSAndi Kleen 
12825f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
12833c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
1284a074865eSWang Nan 	perf_hooks__invoke_record_start();
1285649c48a9SPeter Zijlstra 	for (;;) {
12869f065194SYang Shi 		unsigned long long hits = rec->samples;
128786470930SIngo Molnar 
128805737464SWang Nan 		/*
128905737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
129005737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
129105737464SWang Nan 		 * hits != rec->samples in previous round.
129205737464SWang Nan 		 *
129305737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
129405737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
129505737464SWang Nan 		 */
129605737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
129705737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
129805737464SWang Nan 
12998c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
13005f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
13013c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
13028d3eca20SDavid Ahern 			err = -1;
130345604710SNamhyung Kim 			goto out_child;
13048d3eca20SDavid Ahern 		}
130586470930SIngo Molnar 
13062dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
13072dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
13085f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
13092dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
13105f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
13112dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
13122dd6d8a1SAdrian Hunter 				err = -1;
13132dd6d8a1SAdrian Hunter 				goto out_child;
13142dd6d8a1SAdrian Hunter 			}
13152dd6d8a1SAdrian Hunter 		}
13162dd6d8a1SAdrian Hunter 
13173c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
131805737464SWang Nan 			/*
131905737464SWang Nan 			 * If switch_output_trigger is hit, the data in
132005737464SWang Nan 			 * overwritable ring buffer should have been collected,
132105737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
132205737464SWang Nan 			 *
132305737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
132405737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
132505737464SWang Nan 			 * overwritable ring buffer. Read again.
132605737464SWang Nan 			 */
132705737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
132805737464SWang Nan 				continue;
13293c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
13303c1cb7e3SWang Nan 
133105737464SWang Nan 			/*
133205737464SWang Nan 			 * Reenable events in overwrite ring buffer after
133305737464SWang Nan 			 * record__mmap_read_all(): we should have collected
133405737464SWang Nan 			 * data from it.
133505737464SWang Nan 			 */
133605737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
133705737464SWang Nan 
13383c1cb7e3SWang Nan 			if (!quiet)
13393c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
13403c1cb7e3SWang Nan 					waking);
13413c1cb7e3SWang Nan 			waking = 0;
13423c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
13433c1cb7e3SWang Nan 			if (fd < 0) {
13443c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
13453c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
13463c1cb7e3SWang Nan 				err = fd;
13473c1cb7e3SWang Nan 				goto out_child;
13483c1cb7e3SWang Nan 			}
1349bfacbe3bSJiri Olsa 
1350bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1351bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1352bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
13533c1cb7e3SWang Nan 		}
13543c1cb7e3SWang Nan 
1355d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
13566dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1357649c48a9SPeter Zijlstra 				break;
1358f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
1359a515114fSJiri Olsa 			/*
1360a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1361a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1362a515114fSJiri Olsa 			 */
1363a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
136445604710SNamhyung Kim 				err = 0;
13658b412664SPeter Zijlstra 			waking++;
13666dcf45efSArnaldo Carvalho de Melo 
13676dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
13686dcf45efSArnaldo Carvalho de Melo 				draining = true;
13698b412664SPeter Zijlstra 		}
13708b412664SPeter Zijlstra 
1371774cb499SJiri Olsa 		/*
1372774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1373774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1374774cb499SJiri Olsa 		 * disable events in this case.
1375774cb499SJiri Olsa 		 */
1376602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
13775f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
13783e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
13792711926aSJiri Olsa 			disabled = true;
13802711926aSJiri Olsa 		}
13818b412664SPeter Zijlstra 	}
13825f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
13833c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
13848b412664SPeter Zijlstra 
1385f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
138635550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1387c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1388f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1389f33cbe72SArnaldo Carvalho de Melo 		err = -1;
139045604710SNamhyung Kim 		goto out_child;
1391f33cbe72SArnaldo Carvalho de Melo 	}
1392f33cbe72SArnaldo Carvalho de Melo 
1393e3d59112SNamhyung Kim 	if (!quiet)
13948b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
139586470930SIngo Molnar 
13964ea648aeSWang Nan 	if (target__none(&rec->opts.target))
13974ea648aeSWang Nan 		record__synthesize_workload(rec, true);
13984ea648aeSWang Nan 
139945604710SNamhyung Kim out_child:
1400d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1401d3d1af6fSAlexey Budankov 
140245604710SNamhyung Kim 	if (forks) {
140345604710SNamhyung Kim 		int exit_status;
140445604710SNamhyung Kim 
140545604710SNamhyung Kim 		if (!child_finished)
140645604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
140745604710SNamhyung Kim 
140845604710SNamhyung Kim 		wait(&exit_status);
140945604710SNamhyung Kim 
141045604710SNamhyung Kim 		if (err < 0)
141145604710SNamhyung Kim 			status = err;
141245604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
141345604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
141445604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
141545604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
141645604710SNamhyung Kim 	} else
141745604710SNamhyung Kim 		status = err;
141845604710SNamhyung Kim 
14194ea648aeSWang Nan 	record__synthesize(rec, true);
1420e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1421e3d59112SNamhyung Kim 	rec->samples = 0;
1422e3d59112SNamhyung Kim 
1423ecfd7a9cSWang Nan 	if (!err) {
1424ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1425e1ab48baSWang Nan 			record__finish_output(rec);
1426ecfd7a9cSWang Nan 		} else {
1427ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1428ecfd7a9cSWang Nan 			if (fd < 0) {
1429ecfd7a9cSWang Nan 				status = fd;
1430ecfd7a9cSWang Nan 				goto out_delete_session;
1431ecfd7a9cSWang Nan 			}
1432ecfd7a9cSWang Nan 		}
1433ecfd7a9cSWang Nan 	}
143439d17dacSArnaldo Carvalho de Melo 
1435a074865eSWang Nan 	perf_hooks__invoke_record_end();
1436a074865eSWang Nan 
1437e3d59112SNamhyung Kim 	if (!err && !quiet) {
1438e3d59112SNamhyung Kim 		char samples[128];
1439ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1440ecfd7a9cSWang Nan 					".<timestamp>" : "";
1441e3d59112SNamhyung Kim 
1442ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1443e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1444e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1445e3d59112SNamhyung Kim 		else
1446e3d59112SNamhyung Kim 			samples[0] = '\0';
1447e3d59112SNamhyung Kim 
1448ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
14498ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
1450eae8ad80SJiri Olsa 			data->file.path, postfix, samples);
1451e3d59112SNamhyung Kim 	}
1452e3d59112SNamhyung Kim 
145339d17dacSArnaldo Carvalho de Melo out_delete_session:
145439d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
145545604710SNamhyung Kim 	return status;
145686470930SIngo Molnar }
145786470930SIngo Molnar 
14580883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
145909b0fd45SJiri Olsa {
1460aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1461a601fdffSJiri Olsa 
14620883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
146326d33022SJiri Olsa 
14640883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
146509b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
14660883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
14670883e820SArnaldo Carvalho de Melo }
14680883e820SArnaldo Carvalho de Melo 
14690883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
14700883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
14710883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
14720883e820SArnaldo Carvalho de Melo {
14730883e820SArnaldo Carvalho de Melo 	int ret;
14740883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
14750883e820SArnaldo Carvalho de Melo 
14760883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
14770883e820SArnaldo Carvalho de Melo 	if (unset) {
14780883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
14790883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
14800883e820SArnaldo Carvalho de Melo 		return 0;
14810883e820SArnaldo Carvalho de Melo 	}
14820883e820SArnaldo Carvalho de Melo 
14830883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
14840883e820SArnaldo Carvalho de Melo 	if (!ret) {
14850883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
14860883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
14870883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
14880883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
14890883e820SArnaldo Carvalho de Melo 	}
14900883e820SArnaldo Carvalho de Melo 
14910883e820SArnaldo Carvalho de Melo 	return ret;
149209b0fd45SJiri Olsa }
149309b0fd45SJiri Olsa 
1494c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
149509b0fd45SJiri Olsa 			       const char *arg,
149609b0fd45SJiri Olsa 			       int unset)
149709b0fd45SJiri Olsa {
14980883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
149926d33022SJiri Olsa }
150026d33022SJiri Olsa 
1501c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
150209b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
150309b0fd45SJiri Olsa 			 int unset __maybe_unused)
150409b0fd45SJiri Olsa {
15052ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1506c421e80bSKan Liang 
15072ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
150809b0fd45SJiri Olsa 
15092ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
15102ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1511eb853e80SJiri Olsa 
15122ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
151309b0fd45SJiri Olsa 	return 0;
151409b0fd45SJiri Olsa }
151509b0fd45SJiri Olsa 
1516eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1517eb853e80SJiri Olsa {
15187a29c087SNamhyung Kim 	struct record *rec = cb;
15197a29c087SNamhyung Kim 
15207a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
15217a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
15227a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
15237a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
15247a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
15257a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
15267a29c087SNamhyung Kim 			rec->no_buildid = true;
15277a29c087SNamhyung Kim 		else
15287a29c087SNamhyung Kim 			return -1;
15297a29c087SNamhyung Kim 		return 0;
15307a29c087SNamhyung Kim 	}
1531cff17205SYisheng Xie 	if (!strcmp(var, "record.call-graph")) {
1532cff17205SYisheng Xie 		var = "call-graph.record-mode";
1533eb853e80SJiri Olsa 		return perf_default_config(var, value, cb);
1534eb853e80SJiri Olsa 	}
153593f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
153693f20c0fSAlexey Budankov 	if (!strcmp(var, "record.aio")) {
153793f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = strtol(value, NULL, 0);
153893f20c0fSAlexey Budankov 		if (!rec->opts.nr_cblocks)
153993f20c0fSAlexey Budankov 			rec->opts.nr_cblocks = nr_cblocks_default;
154093f20c0fSAlexey Budankov 	}
154193f20c0fSAlexey Budankov #endif
1542eb853e80SJiri Olsa 
1543cff17205SYisheng Xie 	return 0;
1544cff17205SYisheng Xie }
1545cff17205SYisheng Xie 
1546814c8c38SPeter Zijlstra struct clockid_map {
1547814c8c38SPeter Zijlstra 	const char *name;
1548814c8c38SPeter Zijlstra 	int clockid;
1549814c8c38SPeter Zijlstra };
1550814c8c38SPeter Zijlstra 
1551814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1552814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1553814c8c38SPeter Zijlstra 
1554814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1555814c8c38SPeter Zijlstra 
1556814c8c38SPeter Zijlstra 
1557814c8c38SPeter Zijlstra /*
1558814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1559814c8c38SPeter Zijlstra  */
1560814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1561814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1562814c8c38SPeter Zijlstra #endif
1563814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1564814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1565814c8c38SPeter Zijlstra #endif
1566814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1567814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1568814c8c38SPeter Zijlstra #endif
1569814c8c38SPeter Zijlstra 
1570814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1571814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1572814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1573814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1574814c8c38SPeter Zijlstra 
1575814c8c38SPeter Zijlstra 	/* available for some events */
1576814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1577814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1578814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1579814c8c38SPeter Zijlstra 
1580814c8c38SPeter Zijlstra 	/* available for the lazy */
1581814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1582814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1583814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1584814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1585814c8c38SPeter Zijlstra 
1586814c8c38SPeter Zijlstra 	CLOCKID_END,
1587814c8c38SPeter Zijlstra };
1588814c8c38SPeter Zijlstra 
1589cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1590cf790516SAlexey Budankov {
1591cf790516SAlexey Budankov 	struct timespec res;
1592cf790516SAlexey Budankov 
1593cf790516SAlexey Budankov 	*res_ns = 0;
1594cf790516SAlexey Budankov 	if (!clock_getres(clk_id, &res))
1595cf790516SAlexey Budankov 		*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1596cf790516SAlexey Budankov 	else
1597cf790516SAlexey Budankov 		pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1598cf790516SAlexey Budankov 
1599cf790516SAlexey Budankov 	return 0;
1600cf790516SAlexey Budankov }
1601cf790516SAlexey Budankov 
1602814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1603814c8c38SPeter Zijlstra {
1604814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1605814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1606814c8c38SPeter Zijlstra 	const char *ostr = str;
1607814c8c38SPeter Zijlstra 
1608814c8c38SPeter Zijlstra 	if (unset) {
1609814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1610814c8c38SPeter Zijlstra 		return 0;
1611814c8c38SPeter Zijlstra 	}
1612814c8c38SPeter Zijlstra 
1613814c8c38SPeter Zijlstra 	/* no arg passed */
1614814c8c38SPeter Zijlstra 	if (!str)
1615814c8c38SPeter Zijlstra 		return 0;
1616814c8c38SPeter Zijlstra 
1617814c8c38SPeter Zijlstra 	/* no setting it twice */
1618814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1619814c8c38SPeter Zijlstra 		return -1;
1620814c8c38SPeter Zijlstra 
1621814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1622814c8c38SPeter Zijlstra 
1623814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1624814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1625cf790516SAlexey Budankov 		return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1626814c8c38SPeter Zijlstra 
1627814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1628814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1629814c8c38SPeter Zijlstra 		str += 6;
1630814c8c38SPeter Zijlstra 
1631814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1632814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1633814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1634cf790516SAlexey Budankov 			return get_clockid_res(opts->clockid,
1635cf790516SAlexey Budankov 					       &opts->clockid_res_ns);
1636814c8c38SPeter Zijlstra 		}
1637814c8c38SPeter Zijlstra 	}
1638814c8c38SPeter Zijlstra 
1639814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1640814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1641814c8c38SPeter Zijlstra 	return -1;
1642814c8c38SPeter Zijlstra }
1643814c8c38SPeter Zijlstra 
1644e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1645e9db1310SAdrian Hunter 				    const char *str,
1646e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1647e9db1310SAdrian Hunter {
1648e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1649e9db1310SAdrian Hunter 	char *s, *p;
1650e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1651e9db1310SAdrian Hunter 	int ret;
1652e9db1310SAdrian Hunter 
1653e9db1310SAdrian Hunter 	if (!str)
1654e9db1310SAdrian Hunter 		return -EINVAL;
1655e9db1310SAdrian Hunter 
1656e9db1310SAdrian Hunter 	s = strdup(str);
1657e9db1310SAdrian Hunter 	if (!s)
1658e9db1310SAdrian Hunter 		return -ENOMEM;
1659e9db1310SAdrian Hunter 
1660e9db1310SAdrian Hunter 	p = strchr(s, ',');
1661e9db1310SAdrian Hunter 	if (p)
1662e9db1310SAdrian Hunter 		*p = '\0';
1663e9db1310SAdrian Hunter 
1664e9db1310SAdrian Hunter 	if (*s) {
1665e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1666e9db1310SAdrian Hunter 		if (ret)
1667e9db1310SAdrian Hunter 			goto out_free;
1668e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1669e9db1310SAdrian Hunter 	}
1670e9db1310SAdrian Hunter 
1671e9db1310SAdrian Hunter 	if (!p) {
1672e9db1310SAdrian Hunter 		ret = 0;
1673e9db1310SAdrian Hunter 		goto out_free;
1674e9db1310SAdrian Hunter 	}
1675e9db1310SAdrian Hunter 
1676e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1677e9db1310SAdrian Hunter 	if (ret)
1678e9db1310SAdrian Hunter 		goto out_free;
1679e9db1310SAdrian Hunter 
1680e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1681e9db1310SAdrian Hunter 
1682e9db1310SAdrian Hunter out_free:
1683e9db1310SAdrian Hunter 	free(s);
1684e9db1310SAdrian Hunter 	return ret;
1685e9db1310SAdrian Hunter }
1686e9db1310SAdrian Hunter 
16870c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
16880c582449SJiri Olsa {
16890c582449SJiri Olsa 	u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
16900c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
16910c582449SJiri Olsa 
16920c582449SJiri Olsa 	wakeup_size /= 2;
16930c582449SJiri Olsa 
16940c582449SJiri Olsa 	if (s->size < wakeup_size) {
16950c582449SJiri Olsa 		char buf[100];
16960c582449SJiri Olsa 
16970c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
16980c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
16990c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
17000c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
17010c582449SJiri Olsa 	}
17020c582449SJiri Olsa }
17030c582449SJiri Olsa 
1704cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
1705cb4e1ebbSJiri Olsa {
1706cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
1707dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
1708dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
1709dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
1710dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
1711dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
1712dc0c6127SJiri Olsa 		{ .tag  = 0 },
1713dc0c6127SJiri Olsa 	};
1714bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
1715bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
1716bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
1717bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
1718bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
1719bfacbe3bSJiri Olsa 		{ .tag  = 0 },
1720bfacbe3bSJiri Olsa 	};
1721dc0c6127SJiri Olsa 	unsigned long val;
1722cb4e1ebbSJiri Olsa 
1723cb4e1ebbSJiri Olsa 	if (!s->set)
1724cb4e1ebbSJiri Olsa 		return 0;
1725cb4e1ebbSJiri Olsa 
1726cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
1727cb4e1ebbSJiri Olsa 		s->signal = true;
1728cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
1729dc0c6127SJiri Olsa 		goto enabled;
1730dc0c6127SJiri Olsa 	}
1731dc0c6127SJiri Olsa 
1732dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
1733dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
1734dc0c6127SJiri Olsa 		s->size = val;
1735dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
1736dc0c6127SJiri Olsa 		goto enabled;
1737cb4e1ebbSJiri Olsa 	}
1738cb4e1ebbSJiri Olsa 
1739bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
1740bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
1741bfacbe3bSJiri Olsa 		s->time = val;
1742bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
1743bfacbe3bSJiri Olsa 			 s->str, s->time);
1744bfacbe3bSJiri Olsa 		goto enabled;
1745bfacbe3bSJiri Olsa 	}
1746bfacbe3bSJiri Olsa 
1747cb4e1ebbSJiri Olsa 	return -1;
1748dc0c6127SJiri Olsa 
1749dc0c6127SJiri Olsa enabled:
1750dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
1751dc0c6127SJiri Olsa 	s->enabled              = true;
17520c582449SJiri Olsa 
17530c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
17540c582449SJiri Olsa 		switch_output_size_warn(rec);
17550c582449SJiri Olsa 
1756dc0c6127SJiri Olsa 	return 0;
1757cb4e1ebbSJiri Olsa }
1758cb4e1ebbSJiri Olsa 
1759e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
176086470930SIngo Molnar 	"perf record [<options>] [<command>]",
176186470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
176286470930SIngo Molnar 	NULL
176386470930SIngo Molnar };
1764e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
176586470930SIngo Molnar 
1766d20deb64SArnaldo Carvalho de Melo /*
17678c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
17688c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1769d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1770d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1771d20deb64SArnaldo Carvalho de Melo  *
1772d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1773d20deb64SArnaldo Carvalho de Melo  *
1774d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1775d20deb64SArnaldo Carvalho de Melo  */
17768c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1777d20deb64SArnaldo Carvalho de Melo 	.opts = {
17788affc2b8SAndi Kleen 		.sample_time	     = true,
1779d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1780d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1781d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1782447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1783d1cb9fceSNamhyung Kim 		.target		     = {
1784d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
17853aa5939dSAdrian Hunter 			.default_per_cpu = true,
1786d1cb9fceSNamhyung Kim 		},
1787d20deb64SArnaldo Carvalho de Melo 	},
1788e3d59112SNamhyung Kim 	.tool = {
1789e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1790e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1791cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1792e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1793f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
1794e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1795e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1796cca8482cSAdrian Hunter 		.ordered_events	= true,
1797e3d59112SNamhyung Kim 	},
1798d20deb64SArnaldo Carvalho de Melo };
17997865e817SFrederic Weisbecker 
180076a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
180176a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
180261eaa3beSArnaldo Carvalho de Melo 
18030aab2136SWang Nan static bool dry_run;
18040aab2136SWang Nan 
1805d20deb64SArnaldo Carvalho de Melo /*
1806d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1807d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1808b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1809d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1810d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1811d20deb64SArnaldo Carvalho de Melo  */
1812efd21307SJiri Olsa static struct option __record_options[] = {
1813d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
181486470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1815f120f9d5SJiri Olsa 		     parse_events_option),
1816d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1817c171b552SLi Zefan 		     "event filter", parse_filter),
18184ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
18194ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
18204ba1faa1SWang Nan 			   exclude_perf),
1821bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1822d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1823bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1824d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1825d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
182686470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1827509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1828acac03faSKirill Smelkov 		    "collect data without buffering"),
1829d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1830daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1831bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
183286470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1833bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1834c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1835d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1836eae8ad80SJiri Olsa 	OPT_STRING('o', "output", &record.data.file.path, "file",
183786470930SIngo Molnar 		    "output file name"),
183869e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
183969e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
18402e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
18414ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
18424ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
1843626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
184445178a92SSong Liu 	OPT_BOOLEAN(0, "bpf-event", &record.opts.bpf_event, "record bpf events"),
1845b09c2364SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1846b09c2364SArnaldo Carvalho de Melo 		    "Fail if the specified frequency can't be used"),
184767230479SArnaldo Carvalho de Melo 	OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
184867230479SArnaldo Carvalho de Melo 		     "profile at this frequency",
184967230479SArnaldo Carvalho de Melo 		      record__parse_freq),
1850e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1851e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1852e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1853d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
185443bece79SLin Ming 		    "put the counters into a counter group"),
18552ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
185609b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
185709b0fd45SJiri Olsa 			   &record_callchain_opt),
185809b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
185976a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
186009b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1861c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
18623da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1863b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1864d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1865649c48a9SPeter Zijlstra 		    "per thread counts"),
186656100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
18673b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
18683b0a5daaSKan Liang 		    "Record the sample physical addresses"),
1869b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
18703abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
18713abebc55SAdrian Hunter 			&record.opts.sample_time_set,
18723abebc55SAdrian Hunter 			"Record the sample timestamps"),
1873f290aa1fSJiri Olsa 	OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
1874f290aa1fSJiri Olsa 			"Record the sample period"),
1875d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1876649c48a9SPeter Zijlstra 		    "don't sample"),
1877d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1878d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1879a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1880d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1881d2db9a98SWang Nan 			&record.no_buildid_set,
1882baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1883d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1884023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1885023695d9SStephane Eranian 		     parse_cgroups),
1886a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
18876619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1888bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1889bea03405SNamhyung Kim 		   "user to profile"),
1890a5aabdacSStephane Eranian 
1891a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1892a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1893a5aabdacSStephane Eranian 		     parse_branch_stack),
1894a5aabdacSStephane Eranian 
1895a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1896a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1897bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
189805484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
189905484298SAndi Kleen 		    "sample by weight (on special events only)"),
1900475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1901475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
19023aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
19033aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1904bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1905bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1906bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
190784c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
190884c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
190984c41742SAndi Kleen 		    " use -I ? to list register names", parse_regs),
191085c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
191185c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1912814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1913814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1914814c8c38SPeter Zijlstra 	parse_clockid),
19152dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
19162dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
19173fcb10e4SMark Drayton 	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
19189d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1919f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
1920f3b3614aSHari Bathini 		    "Record namespaces events"),
1921b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1922b757bb09SAdrian Hunter 		    "Record context switch events"),
192385723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
192485723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
192585723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
192685723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
192785723885SJiri Olsa 			 "Configure all used events to run in user space.",
192885723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
192971dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
193071dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
193171dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
193271dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
19337efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
19347efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
19356156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
19366156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1937ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1938ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
193968588bafSJin Yao 	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
194068588bafSJin Yao 		    "Record timestamp boundary (time of first/last samples)"),
1941cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
1942bfacbe3bSJiri Olsa 			  &record.switch_output.set, "signal,size,time",
1943bfacbe3bSJiri Olsa 			  "Switch output when receive SIGUSR2 or cross size,time threshold",
1944dc0c6127SJiri Olsa 			  "signal"),
19450aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
19460aab2136SWang Nan 		    "Parse options then exit"),
1947d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
194893f20c0fSAlexey Budankov 	OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
194993f20c0fSAlexey Budankov 		     &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
1950d3d1af6fSAlexey Budankov 		     record__aio_parse),
1951d3d1af6fSAlexey Budankov #endif
195286470930SIngo Molnar 	OPT_END()
195386470930SIngo Molnar };
195486470930SIngo Molnar 
1955e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1956e5b2c207SNamhyung Kim 
1957b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
195886470930SIngo Molnar {
1959ef149c25SAdrian Hunter 	int err;
19608c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
196116ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
196286470930SIngo Molnar 
196367230479SArnaldo Carvalho de Melo 	setlocale(LC_ALL, "");
196467230479SArnaldo Carvalho de Melo 
196548e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
196648e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
196748e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
196848e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
196948e1cab1SWang Nan # undef set_nobuild
197048e1cab1SWang Nan #endif
197148e1cab1SWang Nan 
19727efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
19737efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
19747efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
19757efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
19767efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
19777efe0e03SHe Kuang # else
19787efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
19797efe0e03SHe Kuang # endif
19807efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
19817efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
19827efe0e03SHe Kuang # undef set_nobuild
19837efe0e03SHe Kuang # undef REASON
19847efe0e03SHe Kuang #endif
19857efe0e03SHe Kuang 
1986*9d2ed645SAlexey Budankov 	CPU_ZERO(&rec->affinity_mask);
1987*9d2ed645SAlexey Budankov 	rec->opts.affinity = PERF_AFFINITY_SYS;
1988*9d2ed645SAlexey Budankov 
19893e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
19903e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1991361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1992361c99a6SArnaldo Carvalho de Melo 
1993ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
1994ecc4c561SArnaldo Carvalho de Melo 	if (err)
1995ecc4c561SArnaldo Carvalho de Melo 		return err;
1996eb853e80SJiri Olsa 
1997bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1998a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
199968ba3235SNamhyung Kim 	if (quiet)
200068ba3235SNamhyung Kim 		perf_quiet_option();
2001483635a9SJiri Olsa 
2002483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
2003602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
2004483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
200586470930SIngo Molnar 
2006bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
2007c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
2008c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
2009c7118369SNamhyung Kim 
2010023695d9SStephane Eranian 	}
2011b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
2012b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
2013c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
2014c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
2015c7118369SNamhyung Kim 		return -EINVAL;
2016b757bb09SAdrian Hunter 	}
2017023695d9SStephane Eranian 
2018cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
2019cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
2020cb4e1ebbSJiri Olsa 		return -EINVAL;
2021cb4e1ebbSJiri Olsa 	}
2022cb4e1ebbSJiri Olsa 
2023bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
2024bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
2025bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
2026bfacbe3bSJiri Olsa 	}
2027bfacbe3bSJiri Olsa 
20281b36c03eSAdrian Hunter 	/*
20291b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
20301b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
20311b36c03eSAdrian Hunter 	 */
20321b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
20331b36c03eSAdrian Hunter 
20341b36c03eSAdrian Hunter 	symbol__init(NULL);
20351b36c03eSAdrian Hunter 
20364b5ea3bdSAdrian Hunter 	err = record__auxtrace_init(rec);
20371b36c03eSAdrian Hunter 	if (err)
20381b36c03eSAdrian Hunter 		goto out;
20391b36c03eSAdrian Hunter 
20400aab2136SWang Nan 	if (dry_run)
20415c01ad60SAdrian Hunter 		goto out;
20420aab2136SWang Nan 
2043d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
2044d7888573SWang Nan 	if (err) {
2045d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
2046d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
2047d7888573SWang Nan 			 errbuf);
20485c01ad60SAdrian Hunter 		goto out;
2049d7888573SWang Nan 	}
2050d7888573SWang Nan 
2051ef149c25SAdrian Hunter 	err = -ENOMEM;
2052ef149c25SAdrian Hunter 
20536c443954SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist))
2054646aaea6SArnaldo Carvalho de Melo 		pr_warning(
2055646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
2056ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
2057646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
2058646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
2059646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
2060646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
2061646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
2062ec80fde7SArnaldo Carvalho de Melo 
20630c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
2064a1ac1d3cSStephane Eranian 		disable_buildid_cache();
2065dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
20660c1d46a8SWang Nan 		/*
20670c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
20680c1d46a8SWang Nan 		 * generation by default to reduce data file switching
20690c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
20700c1d46a8SWang Nan 		 * explicitly using
20710c1d46a8SWang Nan 		 *
207260437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
20730c1d46a8SWang Nan 		 *              --no-no-buildid-cache
20740c1d46a8SWang Nan 		 *
20750c1d46a8SWang Nan 		 * Following code equals to:
20760c1d46a8SWang Nan 		 *
20770c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
20780c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
20790c1d46a8SWang Nan 		 *         disable_buildid_cache();
20800c1d46a8SWang Nan 		 */
20810c1d46a8SWang Nan 		bool disable = true;
20820c1d46a8SWang Nan 
20830c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
20840c1d46a8SWang Nan 			disable = false;
20850c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
20860c1d46a8SWang Nan 			disable = false;
20870c1d46a8SWang Nan 		if (disable) {
20880c1d46a8SWang Nan 			rec->no_buildid = true;
20890c1d46a8SWang Nan 			rec->no_buildid_cache = true;
20900c1d46a8SWang Nan 			disable_buildid_cache();
20910c1d46a8SWang Nan 		}
20920c1d46a8SWang Nan 	}
2093655000e7SArnaldo Carvalho de Melo 
20944ea648aeSWang Nan 	if (record.opts.overwrite)
20954ea648aeSWang Nan 		record.opts.tail_synthesize = true;
20964ea648aeSWang Nan 
20973e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
20984b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
209969aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
2100394c01edSAdrian Hunter 		goto out;
2101bbd36e5eSPeter Zijlstra 	}
210286470930SIngo Molnar 
210369e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
210469e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
210569e7e5b0SAdrian Hunter 
2106602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
210716ad2ffbSNamhyung Kim 	if (err) {
2108602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
2109c3dec27bSJiri Olsa 		ui__warning("%s\n", errbuf);
211016ad2ffbSNamhyung Kim 	}
21114bd0f2d2SNamhyung Kim 
2112602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
211316ad2ffbSNamhyung Kim 	if (err) {
211416ad2ffbSNamhyung Kim 		int saved_errno = errno;
211516ad2ffbSNamhyung Kim 
2116602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
21173780f488SNamhyung Kim 		ui__error("%s", errbuf);
211816ad2ffbSNamhyung Kim 
211916ad2ffbSNamhyung Kim 		err = -saved_errno;
2120394c01edSAdrian Hunter 		goto out;
212116ad2ffbSNamhyung Kim 	}
21220d37aa34SArnaldo Carvalho de Melo 
2123ca800068SMengting Zhang 	/* Enable ignoring missing threads when -u/-p option is defined. */
2124ca800068SMengting Zhang 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
212523dc4f15SJiri Olsa 
212616ad2ffbSNamhyung Kim 	err = -ENOMEM;
21273e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
2128dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
212969aad6f1SArnaldo Carvalho de Melo 
2130ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
2131ef149c25SAdrian Hunter 	if (err)
2132394c01edSAdrian Hunter 		goto out;
2133ef149c25SAdrian Hunter 
21346156681bSNamhyung Kim 	/*
21356156681bSNamhyung Kim 	 * We take all buildids when the file contains
21366156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
21376156681bSNamhyung Kim 	 * trace because it would take too long.
21386156681bSNamhyung Kim 	 */
21396156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
21406156681bSNamhyung Kim 		rec->buildid_all = true;
21416156681bSNamhyung Kim 
2142b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
214339d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
2144394c01edSAdrian Hunter 		goto out;
21457e4ff9e3SMike Galbraith 	}
21467e4ff9e3SMike Galbraith 
214793f20c0fSAlexey Budankov 	if (rec->opts.nr_cblocks > nr_cblocks_max)
214893f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = nr_cblocks_max;
2149d3d1af6fSAlexey Budankov 	if (verbose > 0)
2150d3d1af6fSAlexey Budankov 		pr_info("nr_cblocks: %d\n", rec->opts.nr_cblocks);
2151d3d1af6fSAlexey Budankov 
2152*9d2ed645SAlexey Budankov 	pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
2153*9d2ed645SAlexey Budankov 
2154d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
2155394c01edSAdrian Hunter out:
215645604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
2157d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
2158ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
215939d17dacSArnaldo Carvalho de Melo 	return err;
216086470930SIngo Molnar }
21612dd6d8a1SAdrian Hunter 
21622dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
21632dd6d8a1SAdrian Hunter {
2164dc0c6127SJiri Olsa 	struct record *rec = &record;
2165dc0c6127SJiri Olsa 
21665f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
21675f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
21682dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
21695f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
21705f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
21715f9cf599SWang Nan 	}
21723c1cb7e3SWang Nan 
2173dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
21743c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
21752dd6d8a1SAdrian Hunter }
2176bfacbe3bSJiri Olsa 
2177bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
2178bfacbe3bSJiri Olsa {
2179bfacbe3bSJiri Olsa 	struct record *rec = &record;
2180bfacbe3bSJiri Olsa 
2181bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
2182bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
2183bfacbe3bSJiri Olsa }
2184