xref: /openbmc/linux/tools/perf/builtin-record.c (revision 8ceb41d7e305f186543c58178d2e1fe34f708948)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-record.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin record command: Record the profile of a workload
586470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
686470930SIngo Molnar  * later analysis via perf report.
786470930SIngo Molnar  */
886470930SIngo Molnar #include "builtin.h"
986470930SIngo Molnar 
1086470930SIngo Molnar #include "perf.h"
1186470930SIngo Molnar 
126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1386470930SIngo Molnar #include "util/util.h"
144b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1586470930SIngo Molnar #include "util/parse-events.h"
1641840d21STaeung Song #include "util/config.h"
1786470930SIngo Molnar 
188f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
19f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
207c6a1c65SPeter Zijlstra #include "util/header.h"
2166e274f3SFrederic Weisbecker #include "util/event.h"
22361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2369aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
248f28827aSFrederic Weisbecker #include "util/debug.h"
255d8bb1ecSMathieu Poirier #include "util/drv_configs.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"
43d8871ea7SWang Nan #include "asm/bug.h"
447c6a1c65SPeter Zijlstra 
45a43783aeSArnaldo Carvalho de Melo #include <errno.h>
46fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
474208735dSArnaldo Carvalho de Melo #include <poll.h>
4886470930SIngo Molnar #include <unistd.h>
4986470930SIngo Molnar #include <sched.h>
509607ad3aSArnaldo Carvalho de Melo #include <signal.h>
51a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
524208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
532d11c650SWang Nan #include <asm/bug.h>
540693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
5578da39faSBernhard Rosenkraenzer 
561b43b704SJiri Olsa struct switch_output {
57dc0c6127SJiri Olsa 	bool		 enabled;
581b43b704SJiri Olsa 	bool		 signal;
59dc0c6127SJiri Olsa 	unsigned long	 size;
60bfacbe3bSJiri Olsa 	unsigned long	 time;
61cb4e1ebbSJiri Olsa 	const char	*str;
62cb4e1ebbSJiri Olsa 	bool		 set;
631b43b704SJiri Olsa };
641b43b704SJiri Olsa 
658c6f45a7SArnaldo Carvalho de Melo struct record {
6645694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
67b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
68d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
69*8ceb41d7SJiri Olsa 	struct perf_data	data;
70ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
71d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
72d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
73d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
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;
811b43b704SJiri Olsa 	struct switch_output	switch_output;
829f065194SYang Shi 	unsigned long long	samples;
830f82ebc4SArnaldo Carvalho de Melo };
8486470930SIngo Molnar 
85dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
86dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
87dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
88dc0c6127SJiri Olsa 
89dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
90dc0c6127SJiri Olsa {
91dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
92dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
93dc0c6127SJiri Olsa }
94dc0c6127SJiri Olsa 
95dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
96dc0c6127SJiri Olsa {
97dc0c6127SJiri Olsa 	return rec->switch_output.size &&
98dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
99dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
100dc0c6127SJiri Olsa }
101dc0c6127SJiri Olsa 
102bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
103bfacbe3bSJiri Olsa {
104bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
105bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
106bfacbe3bSJiri Olsa }
107bfacbe3bSJiri Olsa 
1088c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size)
109f5970550SPeter Zijlstra {
110*8ceb41d7SJiri Olsa 	if (perf_data__write(rec->session->data, bf, size) < 0) {
1114f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1128d3eca20SDavid Ahern 		return -1;
1138d3eca20SDavid Ahern 	}
114f5970550SPeter Zijlstra 
115cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
116dc0c6127SJiri Olsa 
117dc0c6127SJiri Olsa 	if (switch_output_size(rec))
118dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
119dc0c6127SJiri Olsa 
1208d3eca20SDavid Ahern 	return 0;
121f5970550SPeter Zijlstra }
122f5970550SPeter Zijlstra 
12345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
124d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
1251d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
1261d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
127234fbbf5SArnaldo Carvalho de Melo {
1288c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
1298c6f45a7SArnaldo Carvalho de Melo 	return record__write(rec, event, event->header.size);
130234fbbf5SArnaldo Carvalho de Melo }
131234fbbf5SArnaldo Carvalho de Melo 
132d37f1586SArnaldo Carvalho de Melo static int record__pushfn(void *to, void *bf, size_t size)
133d37f1586SArnaldo Carvalho de Melo {
134d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
135d37f1586SArnaldo Carvalho de Melo 
136d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
137d37f1586SArnaldo Carvalho de Melo 	return record__write(rec, bf, size);
138d37f1586SArnaldo Carvalho de Melo }
139d37f1586SArnaldo Carvalho de Melo 
1402dd6d8a1SAdrian Hunter static volatile int done;
1412dd6d8a1SAdrian Hunter static volatile int signr = -1;
1422dd6d8a1SAdrian Hunter static volatile int child_finished;
143c0bdc1c4SWang Nan 
1442dd6d8a1SAdrian Hunter static void sig_handler(int sig)
1452dd6d8a1SAdrian Hunter {
1462dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
1472dd6d8a1SAdrian Hunter 		child_finished = 1;
1482dd6d8a1SAdrian Hunter 	else
1492dd6d8a1SAdrian Hunter 		signr = sig;
1502dd6d8a1SAdrian Hunter 
1512dd6d8a1SAdrian Hunter 	done = 1;
1522dd6d8a1SAdrian Hunter }
1532dd6d8a1SAdrian Hunter 
154a074865eSWang Nan static void sigsegv_handler(int sig)
155a074865eSWang Nan {
156a074865eSWang Nan 	perf_hooks__recover();
157a074865eSWang Nan 	sighandler_dump_stack(sig);
158a074865eSWang Nan }
159a074865eSWang Nan 
1602dd6d8a1SAdrian Hunter static void record__sig_exit(void)
1612dd6d8a1SAdrian Hunter {
1622dd6d8a1SAdrian Hunter 	if (signr == -1)
1632dd6d8a1SAdrian Hunter 		return;
1642dd6d8a1SAdrian Hunter 
1652dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
1662dd6d8a1SAdrian Hunter 	raise(signr);
1672dd6d8a1SAdrian Hunter }
1682dd6d8a1SAdrian Hunter 
169e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
170e31f0d01SAdrian Hunter 
171ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
172ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
173ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
174ef149c25SAdrian Hunter {
175ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
176*8ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
177ef149c25SAdrian Hunter 	size_t padding;
178ef149c25SAdrian Hunter 	u8 pad[8] = {0};
179ef149c25SAdrian Hunter 
180*8ceb41d7SJiri Olsa 	if (!perf_data__is_pipe(data)) {
18199fa2984SAdrian Hunter 		off_t file_offset;
182*8ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
18399fa2984SAdrian Hunter 		int err;
18499fa2984SAdrian Hunter 
18599fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
18699fa2984SAdrian Hunter 		if (file_offset == -1)
18799fa2984SAdrian Hunter 			return -1;
18899fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
18999fa2984SAdrian Hunter 						     event, file_offset);
19099fa2984SAdrian Hunter 		if (err)
19199fa2984SAdrian Hunter 			return err;
19299fa2984SAdrian Hunter 	}
19399fa2984SAdrian Hunter 
194ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
195ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
196ef149c25SAdrian Hunter 	if (padding)
197ef149c25SAdrian Hunter 		padding = 8 - padding;
198ef149c25SAdrian Hunter 
199ef149c25SAdrian Hunter 	record__write(rec, event, event->header.size);
200ef149c25SAdrian Hunter 	record__write(rec, data1, len1);
201ef149c25SAdrian Hunter 	if (len2)
202ef149c25SAdrian Hunter 		record__write(rec, data2, len2);
203ef149c25SAdrian Hunter 	record__write(rec, &pad, padding);
204ef149c25SAdrian Hunter 
205ef149c25SAdrian Hunter 	return 0;
206ef149c25SAdrian Hunter }
207ef149c25SAdrian Hunter 
208ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
209ef149c25SAdrian Hunter 				      struct auxtrace_mmap *mm)
210ef149c25SAdrian Hunter {
211ef149c25SAdrian Hunter 	int ret;
212ef149c25SAdrian Hunter 
213ef149c25SAdrian Hunter 	ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
214ef149c25SAdrian Hunter 				  record__process_auxtrace);
215ef149c25SAdrian Hunter 	if (ret < 0)
216ef149c25SAdrian Hunter 		return ret;
217ef149c25SAdrian Hunter 
218ef149c25SAdrian Hunter 	if (ret)
219ef149c25SAdrian Hunter 		rec->samples++;
220ef149c25SAdrian Hunter 
221ef149c25SAdrian Hunter 	return 0;
222ef149c25SAdrian Hunter }
223ef149c25SAdrian Hunter 
2242dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
2252dd6d8a1SAdrian Hunter 					       struct auxtrace_mmap *mm)
2262dd6d8a1SAdrian Hunter {
2272dd6d8a1SAdrian Hunter 	int ret;
2282dd6d8a1SAdrian Hunter 
2292dd6d8a1SAdrian Hunter 	ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
2302dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
2312dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
2322dd6d8a1SAdrian Hunter 	if (ret < 0)
2332dd6d8a1SAdrian Hunter 		return ret;
2342dd6d8a1SAdrian Hunter 
2352dd6d8a1SAdrian Hunter 	if (ret)
2362dd6d8a1SAdrian Hunter 		rec->samples++;
2372dd6d8a1SAdrian Hunter 
2382dd6d8a1SAdrian Hunter 	return 0;
2392dd6d8a1SAdrian Hunter }
2402dd6d8a1SAdrian Hunter 
2412dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
2422dd6d8a1SAdrian Hunter {
2432dd6d8a1SAdrian Hunter 	int i;
2442dd6d8a1SAdrian Hunter 	int rc = 0;
2452dd6d8a1SAdrian Hunter 
2462dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
2472dd6d8a1SAdrian Hunter 		struct auxtrace_mmap *mm =
2482dd6d8a1SAdrian Hunter 				&rec->evlist->mmap[i].auxtrace_mmap;
2492dd6d8a1SAdrian Hunter 
2502dd6d8a1SAdrian Hunter 		if (!mm->base)
2512dd6d8a1SAdrian Hunter 			continue;
2522dd6d8a1SAdrian Hunter 
2532dd6d8a1SAdrian Hunter 		if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
2542dd6d8a1SAdrian Hunter 			rc = -1;
2552dd6d8a1SAdrian Hunter 			goto out;
2562dd6d8a1SAdrian Hunter 		}
2572dd6d8a1SAdrian Hunter 	}
2582dd6d8a1SAdrian Hunter out:
2592dd6d8a1SAdrian Hunter 	return rc;
2602dd6d8a1SAdrian Hunter }
2612dd6d8a1SAdrian Hunter 
2622dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
2632dd6d8a1SAdrian Hunter {
2642dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
2652dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
2665f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
2672dd6d8a1SAdrian Hunter 	} else {
2685f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
2695f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
2705f9cf599SWang Nan 		else
2715f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
2722dd6d8a1SAdrian Hunter 	}
2732dd6d8a1SAdrian Hunter }
2742dd6d8a1SAdrian Hunter 
275e31f0d01SAdrian Hunter #else
276e31f0d01SAdrian Hunter 
277e31f0d01SAdrian Hunter static inline
278e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
279e31f0d01SAdrian Hunter 			       struct auxtrace_mmap *mm __maybe_unused)
280e31f0d01SAdrian Hunter {
281e31f0d01SAdrian Hunter 	return 0;
282e31f0d01SAdrian Hunter }
283e31f0d01SAdrian Hunter 
2842dd6d8a1SAdrian Hunter static inline
2852dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
2862dd6d8a1SAdrian Hunter {
2872dd6d8a1SAdrian Hunter }
2882dd6d8a1SAdrian Hunter 
2892dd6d8a1SAdrian Hunter static inline
2902dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
2912dd6d8a1SAdrian Hunter {
2922dd6d8a1SAdrian Hunter 	return 0;
2932dd6d8a1SAdrian Hunter }
2942dd6d8a1SAdrian Hunter 
295e31f0d01SAdrian Hunter #endif
296e31f0d01SAdrian Hunter 
297cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
298cda57a8cSWang Nan 			       struct perf_evlist *evlist)
299cda57a8cSWang Nan {
300cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
301cda57a8cSWang Nan 	char msg[512];
302cda57a8cSWang Nan 
303cda57a8cSWang Nan 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
304cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
305cda57a8cSWang Nan 				 opts->auxtrace_snapshot_mode) < 0) {
306cda57a8cSWang Nan 		if (errno == EPERM) {
307cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
308cda57a8cSWang Nan 			       "Consider increasing "
309cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
310cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
311cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
312cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
313cda57a8cSWang Nan 			return -errno;
314cda57a8cSWang Nan 		} else {
315cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
316c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
317cda57a8cSWang Nan 			if (errno)
318cda57a8cSWang Nan 				return -errno;
319cda57a8cSWang Nan 			else
320cda57a8cSWang Nan 				return -EINVAL;
321cda57a8cSWang Nan 		}
322cda57a8cSWang Nan 	}
323cda57a8cSWang Nan 	return 0;
324cda57a8cSWang Nan }
325cda57a8cSWang Nan 
326cda57a8cSWang Nan static int record__mmap(struct record *rec)
327cda57a8cSWang Nan {
328cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
329cda57a8cSWang Nan }
330cda57a8cSWang Nan 
3318c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
332dd7927f4SArnaldo Carvalho de Melo {
333d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
3346a4bb04cSJiri Olsa 	struct perf_evsel *pos;
335d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
336d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
337b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
3385d8bb1ecSMathieu Poirier 	struct perf_evsel_config_term *err_term;
3398d3eca20SDavid Ahern 	int rc = 0;
340dd7927f4SArnaldo Carvalho de Melo 
341e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
342cac21425SJiri Olsa 
343e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
3443da297a6SIngo Molnar try_again:
345d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
34656e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
347bb963e16SNamhyung Kim 				if (verbose > 0)
348c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
3493da297a6SIngo Molnar 				goto try_again;
3503da297a6SIngo Molnar 			}
351ca6a4258SDavid Ahern 
35256e52e85SArnaldo Carvalho de Melo 			rc = -errno;
35356e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
35456e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
35556e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
3568d3eca20SDavid Ahern 			goto out;
3577c6a1c65SPeter Zijlstra 		}
3587c6a1c65SPeter Zijlstra 	}
3597c6a1c65SPeter Zijlstra 
36023d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
36162d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
36223d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
363c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
3648d3eca20SDavid Ahern 		rc = -1;
3658d3eca20SDavid Ahern 		goto out;
3660a102479SFrederic Weisbecker 	}
3670a102479SFrederic Weisbecker 
3685d8bb1ecSMathieu Poirier 	if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
36962d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set config \"%s\" on event %s with %d (%s)\n",
3705d8bb1ecSMathieu Poirier 		      err_term->val.drv_cfg, perf_evsel__name(pos), errno,
3715d8bb1ecSMathieu Poirier 		      str_error_r(errno, msg, sizeof(msg)));
3725d8bb1ecSMathieu Poirier 		rc = -1;
3735d8bb1ecSMathieu Poirier 		goto out;
3745d8bb1ecSMathieu Poirier 	}
3755d8bb1ecSMathieu Poirier 
376cda57a8cSWang Nan 	rc = record__mmap(rec);
377cda57a8cSWang Nan 	if (rc)
3788d3eca20SDavid Ahern 		goto out;
3790a27d7f9SArnaldo Carvalho de Melo 
380a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
3817b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3828d3eca20SDavid Ahern out:
3838d3eca20SDavid Ahern 	return rc;
384a91e5431SArnaldo Carvalho de Melo }
385a91e5431SArnaldo Carvalho de Melo 
386e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
387e3d59112SNamhyung Kim 				union perf_event *event,
388e3d59112SNamhyung Kim 				struct perf_sample *sample,
389e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
390e3d59112SNamhyung Kim 				struct machine *machine)
391e3d59112SNamhyung Kim {
392e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
393e3d59112SNamhyung Kim 
394e3d59112SNamhyung Kim 	rec->samples++;
395e3d59112SNamhyung Kim 
396e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
397e3d59112SNamhyung Kim }
398e3d59112SNamhyung Kim 
3998c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
4006122e4e4SArnaldo Carvalho de Melo {
401*8ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
402f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
4036122e4e4SArnaldo Carvalho de Melo 
404*8ceb41d7SJiri Olsa 	if (data->size == 0)
4059f591fd7SArnaldo Carvalho de Melo 		return 0;
4069f591fd7SArnaldo Carvalho de Melo 
40700dc8657SNamhyung Kim 	/*
40800dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
40900dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
41000dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
41100dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
41200dc8657SNamhyung Kim 	 *
41300dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
41400dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
41500dc8657SNamhyung Kim 	 */
41600dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
41700dc8657SNamhyung Kim 
4186156681bSNamhyung Kim 	/*
4196156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
4206156681bSNamhyung Kim 	 * so no need to process samples.
4216156681bSNamhyung Kim 	 */
4226156681bSNamhyung Kim 	if (rec->buildid_all)
4236156681bSNamhyung Kim 		rec->tool.sample = NULL;
4246156681bSNamhyung Kim 
425b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
4266122e4e4SArnaldo Carvalho de Melo }
4276122e4e4SArnaldo Carvalho de Melo 
4288115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
429a1645ce1SZhang, Yanmin {
430a1645ce1SZhang, Yanmin 	int err;
43145694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
432a1645ce1SZhang, Yanmin 	/*
433a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
434a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
435a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
436a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
437a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
438a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
439a1645ce1SZhang, Yanmin 	 */
44045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
441743eb868SArnaldo Carvalho de Melo 					     machine);
442a1645ce1SZhang, Yanmin 	if (err < 0)
443a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
44423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
445a1645ce1SZhang, Yanmin 
446a1645ce1SZhang, Yanmin 	/*
447a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
448a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
449a1645ce1SZhang, Yanmin 	 */
45045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
4510ae617beSAdrian Hunter 						 machine);
452a1645ce1SZhang, Yanmin 	if (err < 0)
453a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
45423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
455a1645ce1SZhang, Yanmin }
456a1645ce1SZhang, Yanmin 
45798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
45898402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
45998402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
46098402807SFrederic Weisbecker };
46198402807SFrederic Weisbecker 
462a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
463a4ea0ec4SWang Nan 				    bool backward)
46498402807SFrederic Weisbecker {
465dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
4660e2e63ddSPeter Zijlstra 	int i;
4678d3eca20SDavid Ahern 	int rc = 0;
468a4ea0ec4SWang Nan 	struct perf_mmap *maps;
46998402807SFrederic Weisbecker 
470cb21686bSWang Nan 	if (!evlist)
471cb21686bSWang Nan 		return 0;
472ef149c25SAdrian Hunter 
473b2cb615dSWang Nan 	maps = backward ? evlist->backward_mmap : evlist->mmap;
474a4ea0ec4SWang Nan 	if (!maps)
475a4ea0ec4SWang Nan 		return 0;
476cb21686bSWang Nan 
47754cc54deSWang Nan 	if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
47854cc54deSWang Nan 		return 0;
47954cc54deSWang Nan 
480a4ea0ec4SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
481a4ea0ec4SWang Nan 		struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
482a4ea0ec4SWang Nan 
483a4ea0ec4SWang Nan 		if (maps[i].base) {
484d37f1586SArnaldo Carvalho de Melo 			if (perf_mmap__push(&maps[i], evlist->overwrite, backward, rec, record__pushfn) != 0) {
4858d3eca20SDavid Ahern 				rc = -1;
4868d3eca20SDavid Ahern 				goto out;
4878d3eca20SDavid Ahern 			}
4888d3eca20SDavid Ahern 		}
489ef149c25SAdrian Hunter 
4902dd6d8a1SAdrian Hunter 		if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
491ef149c25SAdrian Hunter 		    record__auxtrace_mmap_read(rec, mm) != 0) {
492ef149c25SAdrian Hunter 			rc = -1;
493ef149c25SAdrian Hunter 			goto out;
494ef149c25SAdrian Hunter 		}
49598402807SFrederic Weisbecker 	}
49698402807SFrederic Weisbecker 
497dcabb507SJiri Olsa 	/*
498dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
499dcabb507SJiri Olsa 	 * at least one event.
500dcabb507SJiri Olsa 	 */
501dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
5028c6f45a7SArnaldo Carvalho de Melo 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
5038d3eca20SDavid Ahern 
50454cc54deSWang Nan 	if (backward)
50554cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
5068d3eca20SDavid Ahern out:
5078d3eca20SDavid Ahern 	return rc;
50898402807SFrederic Weisbecker }
50998402807SFrederic Weisbecker 
510cb21686bSWang Nan static int record__mmap_read_all(struct record *rec)
511cb21686bSWang Nan {
512cb21686bSWang Nan 	int err;
513cb21686bSWang Nan 
514a4ea0ec4SWang Nan 	err = record__mmap_read_evlist(rec, rec->evlist, false);
515cb21686bSWang Nan 	if (err)
516cb21686bSWang Nan 		return err;
517cb21686bSWang Nan 
51805737464SWang Nan 	return record__mmap_read_evlist(rec, rec->evlist, true);
519cb21686bSWang Nan }
520cb21686bSWang Nan 
5218c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
52257706abcSDavid Ahern {
52357706abcSDavid Ahern 	struct perf_session *session = rec->session;
52457706abcSDavid Ahern 	int feat;
52557706abcSDavid Ahern 
52657706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
52757706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
52857706abcSDavid Ahern 
52957706abcSDavid Ahern 	if (rec->no_buildid)
53057706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
53157706abcSDavid Ahern 
5323e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
53357706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
53457706abcSDavid Ahern 
53557706abcSDavid Ahern 	if (!rec->opts.branch_stack)
53657706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
537ef149c25SAdrian Hunter 
538ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
539ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
540ffa517adSJiri Olsa 
541ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
54257706abcSDavid Ahern }
54357706abcSDavid Ahern 
544e1ab48baSWang Nan static void
545e1ab48baSWang Nan record__finish_output(struct record *rec)
546e1ab48baSWang Nan {
547*8ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
548*8ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
549e1ab48baSWang Nan 
550*8ceb41d7SJiri Olsa 	if (data->is_pipe)
551e1ab48baSWang Nan 		return;
552e1ab48baSWang Nan 
553e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
554*8ceb41d7SJiri Olsa 	data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
555e1ab48baSWang Nan 
556e1ab48baSWang Nan 	if (!rec->no_buildid) {
557e1ab48baSWang Nan 		process_buildids(rec);
558e1ab48baSWang Nan 
559e1ab48baSWang Nan 		if (rec->buildid_all)
560e1ab48baSWang Nan 			dsos__hit_all(rec->session);
561e1ab48baSWang Nan 	}
562e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
563e1ab48baSWang Nan 
564e1ab48baSWang Nan 	return;
565e1ab48baSWang Nan }
566e1ab48baSWang Nan 
5674ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
568be7b0c9eSWang Nan {
5699d6aae72SArnaldo Carvalho de Melo 	int err;
5709d6aae72SArnaldo Carvalho de Melo 	struct thread_map *thread_map;
571be7b0c9eSWang Nan 
5724ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
5734ea648aeSWang Nan 		return 0;
5744ea648aeSWang Nan 
5759d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
5769d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
5779d6aae72SArnaldo Carvalho de Melo 		return -1;
5789d6aae72SArnaldo Carvalho de Melo 
5799d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
580be7b0c9eSWang Nan 						 process_synthesized_event,
581be7b0c9eSWang Nan 						 &rec->session->machines.host,
582be7b0c9eSWang Nan 						 rec->opts.sample_address,
583be7b0c9eSWang Nan 						 rec->opts.proc_map_timeout);
5849d6aae72SArnaldo Carvalho de Melo 	thread_map__put(thread_map);
5859d6aae72SArnaldo Carvalho de Melo 	return err;
586be7b0c9eSWang Nan }
587be7b0c9eSWang Nan 
5884ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
5893c1cb7e3SWang Nan 
590ecfd7a9cSWang Nan static int
591ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
592ecfd7a9cSWang Nan {
593*8ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
594ecfd7a9cSWang Nan 	int fd, err;
595ecfd7a9cSWang Nan 
596ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
597ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
598ecfd7a9cSWang Nan 
5994ea648aeSWang Nan 	record__synthesize(rec, true);
6004ea648aeSWang Nan 	if (target__none(&rec->opts.target))
6014ea648aeSWang Nan 		record__synthesize_workload(rec, true);
6024ea648aeSWang Nan 
603ecfd7a9cSWang Nan 	rec->samples = 0;
604ecfd7a9cSWang Nan 	record__finish_output(rec);
605ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
606ecfd7a9cSWang Nan 	if (err) {
607ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
608ecfd7a9cSWang Nan 		return -EINVAL;
609ecfd7a9cSWang Nan 	}
610ecfd7a9cSWang Nan 
611*8ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
612ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
613ecfd7a9cSWang Nan 				    at_exit);
614ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
615ecfd7a9cSWang Nan 		rec->bytes_written = 0;
616ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
617ecfd7a9cSWang Nan 	}
618ecfd7a9cSWang Nan 
619ecfd7a9cSWang Nan 	if (!quiet)
620ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
621*8ceb41d7SJiri Olsa 			data->path, timestamp);
6223c1cb7e3SWang Nan 
6233c1cb7e3SWang Nan 	/* Output tracking events */
624be7b0c9eSWang Nan 	if (!at_exit) {
6254ea648aeSWang Nan 		record__synthesize(rec, false);
6263c1cb7e3SWang Nan 
627be7b0c9eSWang Nan 		/*
628be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
629be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
630be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
631be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
632be7b0c9eSWang Nan 		 * contain map and comm information.
633be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
634be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
635be7b0c9eSWang Nan 		 */
636be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
6374ea648aeSWang Nan 			record__synthesize_workload(rec, false);
638be7b0c9eSWang Nan 	}
639ecfd7a9cSWang Nan 	return fd;
640ecfd7a9cSWang Nan }
641ecfd7a9cSWang Nan 
642f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
643f33cbe72SArnaldo Carvalho de Melo 
644f33cbe72SArnaldo Carvalho de Melo /*
645f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
646f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
647f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
648f33cbe72SArnaldo Carvalho de Melo  */
64945604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
65045604710SNamhyung Kim 					siginfo_t *info,
651f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
652f33cbe72SArnaldo Carvalho de Melo {
653f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
654f33cbe72SArnaldo Carvalho de Melo 	done = 1;
655f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
656f33cbe72SArnaldo Carvalho de Melo }
657f33cbe72SArnaldo Carvalho de Melo 
6582dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
659bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
6602dd6d8a1SAdrian Hunter 
66146bc29b9SAdrian Hunter int __weak
66246bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
66346bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
66446bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
66546bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
66646bc29b9SAdrian Hunter {
66746bc29b9SAdrian Hunter 	return 0;
66846bc29b9SAdrian Hunter }
66946bc29b9SAdrian Hunter 
670ee667f94SWang Nan static const struct perf_event_mmap_page *
671ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist)
672ee667f94SWang Nan {
673b2cb615dSWang Nan 	if (evlist) {
674b2cb615dSWang Nan 		if (evlist->mmap && evlist->mmap[0].base)
675ee667f94SWang Nan 			return evlist->mmap[0].base;
676b2cb615dSWang Nan 		if (evlist->backward_mmap && evlist->backward_mmap[0].base)
677b2cb615dSWang Nan 			return evlist->backward_mmap[0].base;
678b2cb615dSWang Nan 	}
679ee667f94SWang Nan 	return NULL;
680ee667f94SWang Nan }
681ee667f94SWang Nan 
682c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
683c45628b0SWang Nan {
684ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
685ee667f94SWang Nan 
686ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
687ee667f94SWang Nan 	if (pc)
688ee667f94SWang Nan 		return pc;
689c45628b0SWang Nan 	return NULL;
690c45628b0SWang Nan }
691c45628b0SWang Nan 
6924ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
693c45c86ebSWang Nan {
694c45c86ebSWang Nan 	struct perf_session *session = rec->session;
695c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
696*8ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
697c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
698c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
699*8ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
700c45c86ebSWang Nan 	int err = 0;
701c45c86ebSWang Nan 
7024ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
7034ea648aeSWang Nan 		return 0;
7044ea648aeSWang Nan 
705*8ceb41d7SJiri Olsa 	if (data->is_pipe) {
706e9def1b2SDavid Carrillo-Cisneros 		err = perf_event__synthesize_features(
707e9def1b2SDavid Carrillo-Cisneros 			tool, session, rec->evlist, process_synthesized_event);
708e9def1b2SDavid Carrillo-Cisneros 		if (err < 0) {
709e9def1b2SDavid Carrillo-Cisneros 			pr_err("Couldn't synthesize features.\n");
710e9def1b2SDavid Carrillo-Cisneros 			return err;
711e9def1b2SDavid Carrillo-Cisneros 		}
712e9def1b2SDavid Carrillo-Cisneros 
713c45c86ebSWang Nan 		err = perf_event__synthesize_attrs(tool, session,
714c45c86ebSWang Nan 						   process_synthesized_event);
715c45c86ebSWang Nan 		if (err < 0) {
716c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
717c45c86ebSWang Nan 			goto out;
718c45c86ebSWang Nan 		}
719c45c86ebSWang Nan 
720c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
721c45c86ebSWang Nan 			/*
722c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
723c45c86ebSWang Nan 			 * there were no tracepoints so its not really
724c45c86ebSWang Nan 			 * an error, just that we don't need to
725c45c86ebSWang Nan 			 * synthesize anything.  We really have to
726c45c86ebSWang Nan 			 * return this more properly and also
727c45c86ebSWang Nan 			 * propagate errors that now are calling die()
728c45c86ebSWang Nan 			 */
729c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
730c45c86ebSWang Nan 								  process_synthesized_event);
731c45c86ebSWang Nan 			if (err <= 0) {
732c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
733c45c86ebSWang Nan 				goto out;
734c45c86ebSWang Nan 			}
735c45c86ebSWang Nan 			rec->bytes_written += err;
736c45c86ebSWang Nan 		}
737c45c86ebSWang Nan 	}
738c45c86ebSWang Nan 
739c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
74046bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
74146bc29b9SAdrian Hunter 	if (err)
74246bc29b9SAdrian Hunter 		goto out;
74346bc29b9SAdrian Hunter 
744c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
745c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
746c45c86ebSWang Nan 					session, process_synthesized_event);
747c45c86ebSWang Nan 		if (err)
748c45c86ebSWang Nan 			goto out;
749c45c86ebSWang Nan 	}
750c45c86ebSWang Nan 
751c45c86ebSWang Nan 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
752c45c86ebSWang Nan 						 machine);
753c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
754c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
755c45c86ebSWang Nan 			   "Check /proc/kallsyms permission or run as root.\n");
756c45c86ebSWang Nan 
757c45c86ebSWang Nan 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
758c45c86ebSWang Nan 					     machine);
759c45c86ebSWang Nan 	WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
760c45c86ebSWang Nan 			   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
761c45c86ebSWang Nan 			   "Check /proc/modules permission or run as root.\n");
762c45c86ebSWang Nan 
763c45c86ebSWang Nan 	if (perf_guest) {
764c45c86ebSWang Nan 		machines__process_guests(&session->machines,
765c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
766c45c86ebSWang Nan 	}
767c45c86ebSWang Nan 
768c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
769c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
770340b47f5SKan Liang 					    opts->proc_map_timeout, 1);
771c45c86ebSWang Nan out:
772c45c86ebSWang Nan 	return err;
773c45c86ebSWang Nan }
774c45c86ebSWang Nan 
7758c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
77686470930SIngo Molnar {
77757706abcSDavid Ahern 	int err;
77845604710SNamhyung Kim 	int status = 0;
7798b412664SPeter Zijlstra 	unsigned long waking = 0;
78046be604bSZhang, Yanmin 	const bool forks = argc > 0;
78123346f21SArnaldo Carvalho de Melo 	struct machine *machine;
78245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
783b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
784*8ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
785d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
7866dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
78742aa276fSNamhyung Kim 	int fd;
78886470930SIngo Molnar 
789d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
79033e49ea7SAndi Kleen 
79145604710SNamhyung Kim 	atexit(record__sig_exit);
792f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
793f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
794804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
795a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
796c0bdc1c4SWang Nan 
797f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
798f3b3614aSHari Bathini 		tool->namespace_events = true;
799f3b3614aSHari Bathini 
800dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
8012dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
8023c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
8035f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
804dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
8053c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
806c0bdc1c4SWang Nan 	} else {
8072dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
808c0bdc1c4SWang Nan 	}
809f5970550SPeter Zijlstra 
810*8ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
81194c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
812ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
813a9a70bbcSArnaldo Carvalho de Melo 		return -1;
814a9a70bbcSArnaldo Carvalho de Melo 	}
815a9a70bbcSArnaldo Carvalho de Melo 
816*8ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
817d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
818d20deb64SArnaldo Carvalho de Melo 
8198c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
820330aa675SStephane Eranian 
821d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
8223e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
823*8ceb41d7SJiri Olsa 						    argv, data->is_pipe,
824735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
82535b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
82635b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
82745604710SNamhyung Kim 			status = err;
82835b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
829856e9660SPeter Zijlstra 		}
830856e9660SPeter Zijlstra 	}
831856e9660SPeter Zijlstra 
8328c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
8338d3eca20SDavid Ahern 		err = -1;
83445604710SNamhyung Kim 		goto out_child;
8358d3eca20SDavid Ahern 	}
83686470930SIngo Molnar 
8378690a2a7SWang Nan 	err = bpf__apply_obj_config();
8388690a2a7SWang Nan 	if (err) {
8398690a2a7SWang Nan 		char errbuf[BUFSIZ];
8408690a2a7SWang Nan 
8418690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
8428690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
8438690a2a7SWang Nan 			 errbuf);
8448690a2a7SWang Nan 		goto out_child;
8458690a2a7SWang Nan 	}
8468690a2a7SWang Nan 
847cca8482cSAdrian Hunter 	/*
848cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
849cca8482cSAdrian Hunter 	 * evlist.
850cca8482cSAdrian Hunter 	 */
851cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
852cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
853cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
854cca8482cSAdrian Hunter 	}
855cca8482cSAdrian Hunter 
8563e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
857a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
858a8bb559bSNamhyung Kim 
859*8ceb41d7SJiri Olsa 	if (data->is_pipe) {
86042aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
861529870e3STom Zanussi 		if (err < 0)
86245604710SNamhyung Kim 			goto out_child;
863563aecb2SJiri Olsa 	} else {
86442aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
865d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
86645604710SNamhyung Kim 			goto out_child;
867d5eed904SArnaldo Carvalho de Melo 	}
8687c6a1c65SPeter Zijlstra 
869d3665498SDavid Ahern 	if (!rec->no_buildid
870e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
871d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
872e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
8738d3eca20SDavid Ahern 		err = -1;
87445604710SNamhyung Kim 		goto out_child;
875e20960c0SRobert Richter 	}
876e20960c0SRobert Richter 
87734ba5122SArnaldo Carvalho de Melo 	machine = &session->machines.host;
878743eb868SArnaldo Carvalho de Melo 
8794ea648aeSWang Nan 	err = record__synthesize(rec, false);
880c45c86ebSWang Nan 	if (err < 0)
88145604710SNamhyung Kim 		goto out_child;
8828d3eca20SDavid Ahern 
883d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
88486470930SIngo Molnar 		struct sched_param param;
88586470930SIngo Molnar 
886d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
88786470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
8886beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
8898d3eca20SDavid Ahern 			err = -1;
89045604710SNamhyung Kim 			goto out_child;
89186470930SIngo Molnar 		}
89286470930SIngo Molnar 	}
89386470930SIngo Molnar 
894774cb499SJiri Olsa 	/*
895774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
896774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
897774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
898774cb499SJiri Olsa 	 */
8996619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
9003e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
901764e16a3SDavid Ahern 
902856e9660SPeter Zijlstra 	/*
903856e9660SPeter Zijlstra 	 * Let the child rip
904856e9660SPeter Zijlstra 	 */
905e803cf97SNamhyung Kim 	if (forks) {
906e5bed564SNamhyung Kim 		union perf_event *event;
907e907caf3SHari Bathini 		pid_t tgid;
908e5bed564SNamhyung Kim 
909e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
910e5bed564SNamhyung Kim 		if (event == NULL) {
911e5bed564SNamhyung Kim 			err = -ENOMEM;
912e5bed564SNamhyung Kim 			goto out_child;
913e5bed564SNamhyung Kim 		}
914e5bed564SNamhyung Kim 
915e803cf97SNamhyung Kim 		/*
916e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
917e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
918e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
919e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
920e803cf97SNamhyung Kim 		 */
921e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
922e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
923e803cf97SNamhyung Kim 						   process_synthesized_event,
924e803cf97SNamhyung Kim 						   machine);
925e5bed564SNamhyung Kim 		free(event);
926e803cf97SNamhyung Kim 
927e907caf3SHari Bathini 		if (tgid == -1)
928e907caf3SHari Bathini 			goto out_child;
929e907caf3SHari Bathini 
930e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
931e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
932e907caf3SHari Bathini 			       machine->id_hdr_size);
933e907caf3SHari Bathini 		if (event == NULL) {
934e907caf3SHari Bathini 			err = -ENOMEM;
935e907caf3SHari Bathini 			goto out_child;
936e907caf3SHari Bathini 		}
937e907caf3SHari Bathini 
938e907caf3SHari Bathini 		/*
939e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
940e907caf3SHari Bathini 		 */
941e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
942e907caf3SHari Bathini 						  rec->evlist->workload.pid,
943e907caf3SHari Bathini 						  tgid, process_synthesized_event,
944e907caf3SHari Bathini 						  machine);
945e907caf3SHari Bathini 		free(event);
946e907caf3SHari Bathini 
9473e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
948e803cf97SNamhyung Kim 	}
949856e9660SPeter Zijlstra 
9506619a53eSAndi Kleen 	if (opts->initial_delay) {
9510693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
9526619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
9536619a53eSAndi Kleen 	}
9546619a53eSAndi Kleen 
9555f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
9563c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
957a074865eSWang Nan 	perf_hooks__invoke_record_start();
958649c48a9SPeter Zijlstra 	for (;;) {
9599f065194SYang Shi 		unsigned long long hits = rec->samples;
96086470930SIngo Molnar 
96105737464SWang Nan 		/*
96205737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
96305737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
96405737464SWang Nan 		 * hits != rec->samples in previous round.
96505737464SWang Nan 		 *
96605737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
96705737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
96805737464SWang Nan 		 */
96905737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
97005737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
97105737464SWang Nan 
9728c6f45a7SArnaldo Carvalho de Melo 		if (record__mmap_read_all(rec) < 0) {
9735f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
9743c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
9758d3eca20SDavid Ahern 			err = -1;
97645604710SNamhyung Kim 			goto out_child;
9778d3eca20SDavid Ahern 		}
97886470930SIngo Molnar 
9792dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
9802dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
9815f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
9822dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
9835f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
9842dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
9852dd6d8a1SAdrian Hunter 				err = -1;
9862dd6d8a1SAdrian Hunter 				goto out_child;
9872dd6d8a1SAdrian Hunter 			}
9882dd6d8a1SAdrian Hunter 		}
9892dd6d8a1SAdrian Hunter 
9903c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
99105737464SWang Nan 			/*
99205737464SWang Nan 			 * If switch_output_trigger is hit, the data in
99305737464SWang Nan 			 * overwritable ring buffer should have been collected,
99405737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
99505737464SWang Nan 			 *
99605737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
99705737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
99805737464SWang Nan 			 * overwritable ring buffer. Read again.
99905737464SWang Nan 			 */
100005737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
100105737464SWang Nan 				continue;
10023c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
10033c1cb7e3SWang Nan 
100405737464SWang Nan 			/*
100505737464SWang Nan 			 * Reenable events in overwrite ring buffer after
100605737464SWang Nan 			 * record__mmap_read_all(): we should have collected
100705737464SWang Nan 			 * data from it.
100805737464SWang Nan 			 */
100905737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
101005737464SWang Nan 
10113c1cb7e3SWang Nan 			if (!quiet)
10123c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
10133c1cb7e3SWang Nan 					waking);
10143c1cb7e3SWang Nan 			waking = 0;
10153c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
10163c1cb7e3SWang Nan 			if (fd < 0) {
10173c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
10183c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
10193c1cb7e3SWang Nan 				err = fd;
10203c1cb7e3SWang Nan 				goto out_child;
10213c1cb7e3SWang Nan 			}
1022bfacbe3bSJiri Olsa 
1023bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1024bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1025bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
10263c1cb7e3SWang Nan 		}
10273c1cb7e3SWang Nan 
1028d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
10296dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1030649c48a9SPeter Zijlstra 				break;
1031f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
1032a515114fSJiri Olsa 			/*
1033a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1034a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1035a515114fSJiri Olsa 			 */
1036a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
103745604710SNamhyung Kim 				err = 0;
10388b412664SPeter Zijlstra 			waking++;
10396dcf45efSArnaldo Carvalho de Melo 
10406dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
10416dcf45efSArnaldo Carvalho de Melo 				draining = true;
10428b412664SPeter Zijlstra 		}
10438b412664SPeter Zijlstra 
1044774cb499SJiri Olsa 		/*
1045774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1046774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1047774cb499SJiri Olsa 		 * disable events in this case.
1048774cb499SJiri Olsa 		 */
1049602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
10505f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
10513e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
10522711926aSJiri Olsa 			disabled = true;
10532711926aSJiri Olsa 		}
10548b412664SPeter Zijlstra 	}
10555f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
10563c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
10578b412664SPeter Zijlstra 
1058f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
105935550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1060c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1061f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1062f33cbe72SArnaldo Carvalho de Melo 		err = -1;
106345604710SNamhyung Kim 		goto out_child;
1064f33cbe72SArnaldo Carvalho de Melo 	}
1065f33cbe72SArnaldo Carvalho de Melo 
1066e3d59112SNamhyung Kim 	if (!quiet)
10678b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
106886470930SIngo Molnar 
10694ea648aeSWang Nan 	if (target__none(&rec->opts.target))
10704ea648aeSWang Nan 		record__synthesize_workload(rec, true);
10714ea648aeSWang Nan 
107245604710SNamhyung Kim out_child:
107345604710SNamhyung Kim 	if (forks) {
107445604710SNamhyung Kim 		int exit_status;
107545604710SNamhyung Kim 
107645604710SNamhyung Kim 		if (!child_finished)
107745604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
107845604710SNamhyung Kim 
107945604710SNamhyung Kim 		wait(&exit_status);
108045604710SNamhyung Kim 
108145604710SNamhyung Kim 		if (err < 0)
108245604710SNamhyung Kim 			status = err;
108345604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
108445604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
108545604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
108645604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
108745604710SNamhyung Kim 	} else
108845604710SNamhyung Kim 		status = err;
108945604710SNamhyung Kim 
10904ea648aeSWang Nan 	record__synthesize(rec, true);
1091e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1092e3d59112SNamhyung Kim 	rec->samples = 0;
1093e3d59112SNamhyung Kim 
1094ecfd7a9cSWang Nan 	if (!err) {
1095ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1096e1ab48baSWang Nan 			record__finish_output(rec);
1097ecfd7a9cSWang Nan 		} else {
1098ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1099ecfd7a9cSWang Nan 			if (fd < 0) {
1100ecfd7a9cSWang Nan 				status = fd;
1101ecfd7a9cSWang Nan 				goto out_delete_session;
1102ecfd7a9cSWang Nan 			}
1103ecfd7a9cSWang Nan 		}
1104ecfd7a9cSWang Nan 	}
110539d17dacSArnaldo Carvalho de Melo 
1106a074865eSWang Nan 	perf_hooks__invoke_record_end();
1107a074865eSWang Nan 
1108e3d59112SNamhyung Kim 	if (!err && !quiet) {
1109e3d59112SNamhyung Kim 		char samples[128];
1110ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1111ecfd7a9cSWang Nan 					".<timestamp>" : "";
1112e3d59112SNamhyung Kim 
1113ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1114e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1115e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1116e3d59112SNamhyung Kim 		else
1117e3d59112SNamhyung Kim 			samples[0] = '\0';
1118e3d59112SNamhyung Kim 
1119ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
1120*8ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
1121*8ceb41d7SJiri Olsa 			data->path, postfix, samples);
1122e3d59112SNamhyung Kim 	}
1123e3d59112SNamhyung Kim 
112439d17dacSArnaldo Carvalho de Melo out_delete_session:
112539d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
112645604710SNamhyung Kim 	return status;
112786470930SIngo Molnar }
112886470930SIngo Molnar 
11290883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
113009b0fd45SJiri Olsa {
1131aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1132a601fdffSJiri Olsa 
11330883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
113426d33022SJiri Olsa 
11350883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
113609b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
11370883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
11380883e820SArnaldo Carvalho de Melo }
11390883e820SArnaldo Carvalho de Melo 
11400883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
11410883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
11420883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
11430883e820SArnaldo Carvalho de Melo {
11440883e820SArnaldo Carvalho de Melo 	int ret;
11450883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
11460883e820SArnaldo Carvalho de Melo 
11470883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
11480883e820SArnaldo Carvalho de Melo 	if (unset) {
11490883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
11500883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
11510883e820SArnaldo Carvalho de Melo 		return 0;
11520883e820SArnaldo Carvalho de Melo 	}
11530883e820SArnaldo Carvalho de Melo 
11540883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
11550883e820SArnaldo Carvalho de Melo 	if (!ret) {
11560883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
11570883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
11580883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
11590883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
11600883e820SArnaldo Carvalho de Melo 	}
11610883e820SArnaldo Carvalho de Melo 
11620883e820SArnaldo Carvalho de Melo 	return ret;
116309b0fd45SJiri Olsa }
116409b0fd45SJiri Olsa 
1165c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
116609b0fd45SJiri Olsa 			       const char *arg,
116709b0fd45SJiri Olsa 			       int unset)
116809b0fd45SJiri Olsa {
11690883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
117026d33022SJiri Olsa }
117126d33022SJiri Olsa 
1172c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
117309b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
117409b0fd45SJiri Olsa 			 int unset __maybe_unused)
117509b0fd45SJiri Olsa {
11762ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1177c421e80bSKan Liang 
11782ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
117909b0fd45SJiri Olsa 
11802ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
11812ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1182eb853e80SJiri Olsa 
11832ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
118409b0fd45SJiri Olsa 	return 0;
118509b0fd45SJiri Olsa }
118609b0fd45SJiri Olsa 
1187eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1188eb853e80SJiri Olsa {
11897a29c087SNamhyung Kim 	struct record *rec = cb;
11907a29c087SNamhyung Kim 
11917a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
11927a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
11937a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
11947a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
11957a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
11967a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
11977a29c087SNamhyung Kim 			rec->no_buildid = true;
11987a29c087SNamhyung Kim 		else
11997a29c087SNamhyung Kim 			return -1;
12007a29c087SNamhyung Kim 		return 0;
12017a29c087SNamhyung Kim 	}
1202eb853e80SJiri Olsa 	if (!strcmp(var, "record.call-graph"))
12035a2e5e85SNamhyung Kim 		var = "call-graph.record-mode"; /* fall-through */
1204eb853e80SJiri Olsa 
1205eb853e80SJiri Olsa 	return perf_default_config(var, value, cb);
1206eb853e80SJiri Olsa }
1207eb853e80SJiri Olsa 
1208814c8c38SPeter Zijlstra struct clockid_map {
1209814c8c38SPeter Zijlstra 	const char *name;
1210814c8c38SPeter Zijlstra 	int clockid;
1211814c8c38SPeter Zijlstra };
1212814c8c38SPeter Zijlstra 
1213814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1214814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1215814c8c38SPeter Zijlstra 
1216814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1217814c8c38SPeter Zijlstra 
1218814c8c38SPeter Zijlstra 
1219814c8c38SPeter Zijlstra /*
1220814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1221814c8c38SPeter Zijlstra  */
1222814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1223814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1224814c8c38SPeter Zijlstra #endif
1225814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1226814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1227814c8c38SPeter Zijlstra #endif
1228814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1229814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1230814c8c38SPeter Zijlstra #endif
1231814c8c38SPeter Zijlstra 
1232814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1233814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1234814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1235814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1236814c8c38SPeter Zijlstra 
1237814c8c38SPeter Zijlstra 	/* available for some events */
1238814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1239814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1240814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1241814c8c38SPeter Zijlstra 
1242814c8c38SPeter Zijlstra 	/* available for the lazy */
1243814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1244814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1245814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1246814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1247814c8c38SPeter Zijlstra 
1248814c8c38SPeter Zijlstra 	CLOCKID_END,
1249814c8c38SPeter Zijlstra };
1250814c8c38SPeter Zijlstra 
1251814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1252814c8c38SPeter Zijlstra {
1253814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1254814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1255814c8c38SPeter Zijlstra 	const char *ostr = str;
1256814c8c38SPeter Zijlstra 
1257814c8c38SPeter Zijlstra 	if (unset) {
1258814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1259814c8c38SPeter Zijlstra 		return 0;
1260814c8c38SPeter Zijlstra 	}
1261814c8c38SPeter Zijlstra 
1262814c8c38SPeter Zijlstra 	/* no arg passed */
1263814c8c38SPeter Zijlstra 	if (!str)
1264814c8c38SPeter Zijlstra 		return 0;
1265814c8c38SPeter Zijlstra 
1266814c8c38SPeter Zijlstra 	/* no setting it twice */
1267814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1268814c8c38SPeter Zijlstra 		return -1;
1269814c8c38SPeter Zijlstra 
1270814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1271814c8c38SPeter Zijlstra 
1272814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1273814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1274814c8c38SPeter Zijlstra 		return 0;
1275814c8c38SPeter Zijlstra 
1276814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1277814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1278814c8c38SPeter Zijlstra 		str += 6;
1279814c8c38SPeter Zijlstra 
1280814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1281814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1282814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1283814c8c38SPeter Zijlstra 			return 0;
1284814c8c38SPeter Zijlstra 		}
1285814c8c38SPeter Zijlstra 	}
1286814c8c38SPeter Zijlstra 
1287814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1288814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1289814c8c38SPeter Zijlstra 	return -1;
1290814c8c38SPeter Zijlstra }
1291814c8c38SPeter Zijlstra 
1292e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1293e9db1310SAdrian Hunter 				    const char *str,
1294e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1295e9db1310SAdrian Hunter {
1296e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1297e9db1310SAdrian Hunter 	char *s, *p;
1298e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1299e9db1310SAdrian Hunter 	int ret;
1300e9db1310SAdrian Hunter 
1301e9db1310SAdrian Hunter 	if (!str)
1302e9db1310SAdrian Hunter 		return -EINVAL;
1303e9db1310SAdrian Hunter 
1304e9db1310SAdrian Hunter 	s = strdup(str);
1305e9db1310SAdrian Hunter 	if (!s)
1306e9db1310SAdrian Hunter 		return -ENOMEM;
1307e9db1310SAdrian Hunter 
1308e9db1310SAdrian Hunter 	p = strchr(s, ',');
1309e9db1310SAdrian Hunter 	if (p)
1310e9db1310SAdrian Hunter 		*p = '\0';
1311e9db1310SAdrian Hunter 
1312e9db1310SAdrian Hunter 	if (*s) {
1313e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1314e9db1310SAdrian Hunter 		if (ret)
1315e9db1310SAdrian Hunter 			goto out_free;
1316e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1317e9db1310SAdrian Hunter 	}
1318e9db1310SAdrian Hunter 
1319e9db1310SAdrian Hunter 	if (!p) {
1320e9db1310SAdrian Hunter 		ret = 0;
1321e9db1310SAdrian Hunter 		goto out_free;
1322e9db1310SAdrian Hunter 	}
1323e9db1310SAdrian Hunter 
1324e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1325e9db1310SAdrian Hunter 	if (ret)
1326e9db1310SAdrian Hunter 		goto out_free;
1327e9db1310SAdrian Hunter 
1328e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1329e9db1310SAdrian Hunter 
1330e9db1310SAdrian Hunter out_free:
1331e9db1310SAdrian Hunter 	free(s);
1332e9db1310SAdrian Hunter 	return ret;
1333e9db1310SAdrian Hunter }
1334e9db1310SAdrian Hunter 
13350c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
13360c582449SJiri Olsa {
13370c582449SJiri Olsa 	u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
13380c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
13390c582449SJiri Olsa 
13400c582449SJiri Olsa 	wakeup_size /= 2;
13410c582449SJiri Olsa 
13420c582449SJiri Olsa 	if (s->size < wakeup_size) {
13430c582449SJiri Olsa 		char buf[100];
13440c582449SJiri Olsa 
13450c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
13460c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
13470c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
13480c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
13490c582449SJiri Olsa 	}
13500c582449SJiri Olsa }
13510c582449SJiri Olsa 
1352cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
1353cb4e1ebbSJiri Olsa {
1354cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
1355dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
1356dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
1357dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
1358dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
1359dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
1360dc0c6127SJiri Olsa 		{ .tag  = 0 },
1361dc0c6127SJiri Olsa 	};
1362bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
1363bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
1364bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
1365bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
1366bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
1367bfacbe3bSJiri Olsa 		{ .tag  = 0 },
1368bfacbe3bSJiri Olsa 	};
1369dc0c6127SJiri Olsa 	unsigned long val;
1370cb4e1ebbSJiri Olsa 
1371cb4e1ebbSJiri Olsa 	if (!s->set)
1372cb4e1ebbSJiri Olsa 		return 0;
1373cb4e1ebbSJiri Olsa 
1374cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
1375cb4e1ebbSJiri Olsa 		s->signal = true;
1376cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
1377dc0c6127SJiri Olsa 		goto enabled;
1378dc0c6127SJiri Olsa 	}
1379dc0c6127SJiri Olsa 
1380dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
1381dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
1382dc0c6127SJiri Olsa 		s->size = val;
1383dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
1384dc0c6127SJiri Olsa 		goto enabled;
1385cb4e1ebbSJiri Olsa 	}
1386cb4e1ebbSJiri Olsa 
1387bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
1388bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
1389bfacbe3bSJiri Olsa 		s->time = val;
1390bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
1391bfacbe3bSJiri Olsa 			 s->str, s->time);
1392bfacbe3bSJiri Olsa 		goto enabled;
1393bfacbe3bSJiri Olsa 	}
1394bfacbe3bSJiri Olsa 
1395cb4e1ebbSJiri Olsa 	return -1;
1396dc0c6127SJiri Olsa 
1397dc0c6127SJiri Olsa enabled:
1398dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
1399dc0c6127SJiri Olsa 	s->enabled              = true;
14000c582449SJiri Olsa 
14010c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
14020c582449SJiri Olsa 		switch_output_size_warn(rec);
14030c582449SJiri Olsa 
1404dc0c6127SJiri Olsa 	return 0;
1405cb4e1ebbSJiri Olsa }
1406cb4e1ebbSJiri Olsa 
1407e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
140886470930SIngo Molnar 	"perf record [<options>] [<command>]",
140986470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
141086470930SIngo Molnar 	NULL
141186470930SIngo Molnar };
1412e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
141386470930SIngo Molnar 
1414d20deb64SArnaldo Carvalho de Melo /*
14158c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
14168c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1417d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1418d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1419d20deb64SArnaldo Carvalho de Melo  *
1420d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1421d20deb64SArnaldo Carvalho de Melo  *
1422d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1423d20deb64SArnaldo Carvalho de Melo  */
14248c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1425d20deb64SArnaldo Carvalho de Melo 	.opts = {
14268affc2b8SAndi Kleen 		.sample_time	     = true,
1427d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1428d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1429d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1430447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1431d1cb9fceSNamhyung Kim 		.target		     = {
1432d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
14333aa5939dSAdrian Hunter 			.default_per_cpu = true,
1434d1cb9fceSNamhyung Kim 		},
14359d9cad76SKan Liang 		.proc_map_timeout     = 500,
1436d20deb64SArnaldo Carvalho de Melo 	},
1437e3d59112SNamhyung Kim 	.tool = {
1438e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1439e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1440cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1441e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1442f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
1443e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1444e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1445cca8482cSAdrian Hunter 		.ordered_events	= true,
1446e3d59112SNamhyung Kim 	},
1447d20deb64SArnaldo Carvalho de Melo };
14487865e817SFrederic Weisbecker 
144976a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
145076a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
145161eaa3beSArnaldo Carvalho de Melo 
14520aab2136SWang Nan static bool dry_run;
14530aab2136SWang Nan 
1454d20deb64SArnaldo Carvalho de Melo /*
1455d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1456d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1457b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1458d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1459d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1460d20deb64SArnaldo Carvalho de Melo  */
1461efd21307SJiri Olsa static struct option __record_options[] = {
1462d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
146386470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1464f120f9d5SJiri Olsa 		     parse_events_option),
1465d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1466c171b552SLi Zefan 		     "event filter", parse_filter),
14674ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
14684ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
14694ba1faa1SWang Nan 			   exclude_perf),
1470bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1471d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1472bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1473d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1474d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
147586470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1476509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1477acac03faSKirill Smelkov 		    "collect data without buffering"),
1478d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1479daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1480bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
148186470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1482bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1483c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1484d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1485*8ceb41d7SJiri Olsa 	OPT_STRING('o', "output", &record.data.path, "file",
148686470930SIngo Molnar 		    "output file name"),
148769e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
148869e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
14892e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
14904ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
14914ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
1492626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1493d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1494e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1495e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1496e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1497d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
149843bece79SLin Ming 		    "put the counters into a counter group"),
14992ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
150009b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
150109b0fd45SJiri Olsa 			   &record_callchain_opt),
150209b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
150376a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
150409b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1505c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
15063da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1507b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1508d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1509649c48a9SPeter Zijlstra 		    "per thread counts"),
151056100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
15113b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
15123b0a5daaSKan Liang 		    "Record the sample physical addresses"),
1513b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
15143abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
15153abebc55SAdrian Hunter 			&record.opts.sample_time_set,
15163abebc55SAdrian Hunter 			"Record the sample timestamps"),
151756100321SPeter Zijlstra 	OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1518d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1519649c48a9SPeter Zijlstra 		    "don't sample"),
1520d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1521d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1522a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1523d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1524d2db9a98SWang Nan 			&record.no_buildid_set,
1525baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1526d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1527023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1528023695d9SStephane Eranian 		     parse_cgroups),
1529a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
15306619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
1531bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1532bea03405SNamhyung Kim 		   "user to profile"),
1533a5aabdacSStephane Eranian 
1534a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1535a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1536a5aabdacSStephane Eranian 		     parse_branch_stack),
1537a5aabdacSStephane Eranian 
1538a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1539a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1540bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
154105484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
154205484298SAndi Kleen 		    "sample by weight (on special events only)"),
1543475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
1544475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
15453aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
15463aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
1547bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1548bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
1549bcc84ec6SStephane Eranian 		    " use -I ? to list register names", parse_regs),
155084c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
155184c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
155284c41742SAndi Kleen 		    " use -I ? to list register names", parse_regs),
155385c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
155485c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
1555814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
1556814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
1557814c8c38SPeter Zijlstra 	parse_clockid),
15582dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
15592dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
15609d9cad76SKan Liang 	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
15619d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
1562f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
1563f3b3614aSHari Bathini 		    "Record namespaces events"),
1564b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1565b757bb09SAdrian Hunter 		    "Record context switch events"),
156685723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
156785723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
156885723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
156985723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
157085723885SJiri Olsa 			 "Configure all used events to run in user space.",
157185723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
157271dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
157371dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
157471dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
157571dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
15767efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
15777efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
15786156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
15796156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
1580ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1581ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
1582cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
1583bfacbe3bSJiri Olsa 			  &record.switch_output.set, "signal,size,time",
1584bfacbe3bSJiri Olsa 			  "Switch output when receive SIGUSR2 or cross size,time threshold",
1585dc0c6127SJiri Olsa 			  "signal"),
15860aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
15870aab2136SWang Nan 		    "Parse options then exit"),
158886470930SIngo Molnar 	OPT_END()
158986470930SIngo Molnar };
159086470930SIngo Molnar 
1591e5b2c207SNamhyung Kim struct option *record_options = __record_options;
1592e5b2c207SNamhyung Kim 
1593b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
159486470930SIngo Molnar {
1595ef149c25SAdrian Hunter 	int err;
15968c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
159716ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
159886470930SIngo Molnar 
159948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
160048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
160148e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
160248e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
160348e1cab1SWang Nan # undef set_nobuild
160448e1cab1SWang Nan #endif
160548e1cab1SWang Nan 
16067efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
16077efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
16087efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
16097efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
16107efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
16117efe0e03SHe Kuang # else
16127efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
16137efe0e03SHe Kuang # endif
16147efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
16157efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
16167efe0e03SHe Kuang # undef set_nobuild
16177efe0e03SHe Kuang # undef REASON
16187efe0e03SHe Kuang #endif
16197efe0e03SHe Kuang 
16203e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
16213e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
1622361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1623361c99a6SArnaldo Carvalho de Melo 
1624ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
1625ecc4c561SArnaldo Carvalho de Melo 	if (err)
1626ecc4c561SArnaldo Carvalho de Melo 		return err;
1627eb853e80SJiri Olsa 
1628bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1629a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
163068ba3235SNamhyung Kim 	if (quiet)
163168ba3235SNamhyung Kim 		perf_quiet_option();
1632483635a9SJiri Olsa 
1633483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
1634602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
1635483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
163686470930SIngo Molnar 
1637bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
1638c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
1639c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
1640c7118369SNamhyung Kim 
1641023695d9SStephane Eranian 	}
1642b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
1643b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
1644c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
1645c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
1646c7118369SNamhyung Kim 		return -EINVAL;
1647b757bb09SAdrian Hunter 	}
1648023695d9SStephane Eranian 
1649cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
1650cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
1651cb4e1ebbSJiri Olsa 		return -EINVAL;
1652cb4e1ebbSJiri Olsa 	}
1653cb4e1ebbSJiri Olsa 
1654bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
1655bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
1656bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
1657bfacbe3bSJiri Olsa 	}
1658bfacbe3bSJiri Olsa 
1659ef149c25SAdrian Hunter 	if (!rec->itr) {
1660ef149c25SAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
1661ef149c25SAdrian Hunter 		if (err)
16625c01ad60SAdrian Hunter 			goto out;
1663ef149c25SAdrian Hunter 	}
1664ef149c25SAdrian Hunter 
16652dd6d8a1SAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
16662dd6d8a1SAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
16672dd6d8a1SAdrian Hunter 	if (err)
16685c01ad60SAdrian Hunter 		goto out;
16692dd6d8a1SAdrian Hunter 
16701b36c03eSAdrian Hunter 	/*
16711b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
16721b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
16731b36c03eSAdrian Hunter 	 */
16741b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
16751b36c03eSAdrian Hunter 
16761b36c03eSAdrian Hunter 	symbol__init(NULL);
16771b36c03eSAdrian Hunter 
16781b36c03eSAdrian Hunter 	err = auxtrace_parse_filters(rec->evlist);
16791b36c03eSAdrian Hunter 	if (err)
16801b36c03eSAdrian Hunter 		goto out;
16811b36c03eSAdrian Hunter 
16820aab2136SWang Nan 	if (dry_run)
16835c01ad60SAdrian Hunter 		goto out;
16840aab2136SWang Nan 
1685d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
1686d7888573SWang Nan 	if (err) {
1687d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1688d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
1689d7888573SWang Nan 			 errbuf);
16905c01ad60SAdrian Hunter 		goto out;
1691d7888573SWang Nan 	}
1692d7888573SWang Nan 
1693ef149c25SAdrian Hunter 	err = -ENOMEM;
1694ef149c25SAdrian Hunter 
1695ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1696646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1697646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1698ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1699646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1700646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1701646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1702646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1703646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1704ec80fde7SArnaldo Carvalho de Melo 
17050c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
1706a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1707dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
17080c1d46a8SWang Nan 		/*
17090c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
17100c1d46a8SWang Nan 		 * generation by default to reduce data file switching
17110c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
17120c1d46a8SWang Nan 		 * explicitly using
17130c1d46a8SWang Nan 		 *
171460437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
17150c1d46a8SWang Nan 		 *              --no-no-buildid-cache
17160c1d46a8SWang Nan 		 *
17170c1d46a8SWang Nan 		 * Following code equals to:
17180c1d46a8SWang Nan 		 *
17190c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
17200c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
17210c1d46a8SWang Nan 		 *         disable_buildid_cache();
17220c1d46a8SWang Nan 		 */
17230c1d46a8SWang Nan 		bool disable = true;
17240c1d46a8SWang Nan 
17250c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
17260c1d46a8SWang Nan 			disable = false;
17270c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
17280c1d46a8SWang Nan 			disable = false;
17290c1d46a8SWang Nan 		if (disable) {
17300c1d46a8SWang Nan 			rec->no_buildid = true;
17310c1d46a8SWang Nan 			rec->no_buildid_cache = true;
17320c1d46a8SWang Nan 			disable_buildid_cache();
17330c1d46a8SWang Nan 		}
17340c1d46a8SWang Nan 	}
1735655000e7SArnaldo Carvalho de Melo 
17364ea648aeSWang Nan 	if (record.opts.overwrite)
17374ea648aeSWang Nan 		record.opts.tail_synthesize = true;
17384ea648aeSWang Nan 
17393e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
17404b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
174169aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
1742394c01edSAdrian Hunter 		goto out;
1743bbd36e5eSPeter Zijlstra 	}
174486470930SIngo Molnar 
174569e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
174669e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
174769e7e5b0SAdrian Hunter 
1748602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
174916ad2ffbSNamhyung Kim 	if (err) {
1750602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
175116ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
175216ad2ffbSNamhyung Kim 	}
17534bd0f2d2SNamhyung Kim 
1754602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
175516ad2ffbSNamhyung Kim 	if (err) {
175616ad2ffbSNamhyung Kim 		int saved_errno = errno;
175716ad2ffbSNamhyung Kim 
1758602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
17593780f488SNamhyung Kim 		ui__error("%s", errbuf);
176016ad2ffbSNamhyung Kim 
176116ad2ffbSNamhyung Kim 		err = -saved_errno;
1762394c01edSAdrian Hunter 		goto out;
176316ad2ffbSNamhyung Kim 	}
17640d37aa34SArnaldo Carvalho de Melo 
176523dc4f15SJiri Olsa 	/* Enable ignoring missing threads when -u option is defined. */
176623dc4f15SJiri Olsa 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX;
176723dc4f15SJiri Olsa 
176816ad2ffbSNamhyung Kim 	err = -ENOMEM;
17693e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1770dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
177169aad6f1SArnaldo Carvalho de Melo 
1772ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1773ef149c25SAdrian Hunter 	if (err)
1774394c01edSAdrian Hunter 		goto out;
1775ef149c25SAdrian Hunter 
17766156681bSNamhyung Kim 	/*
17776156681bSNamhyung Kim 	 * We take all buildids when the file contains
17786156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
17796156681bSNamhyung Kim 	 * trace because it would take too long.
17806156681bSNamhyung Kim 	 */
17816156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
17826156681bSNamhyung Kim 		rec->buildid_all = true;
17836156681bSNamhyung Kim 
1784b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
178539d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
1786394c01edSAdrian Hunter 		goto out;
17877e4ff9e3SMike Galbraith 	}
17887e4ff9e3SMike Galbraith 
1789d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
1790394c01edSAdrian Hunter out:
179145604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
1792d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
1793ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
179439d17dacSArnaldo Carvalho de Melo 	return err;
179586470930SIngo Molnar }
17962dd6d8a1SAdrian Hunter 
17972dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
17982dd6d8a1SAdrian Hunter {
1799dc0c6127SJiri Olsa 	struct record *rec = &record;
1800dc0c6127SJiri Olsa 
18015f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
18025f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
18032dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
18045f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
18055f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
18065f9cf599SWang Nan 	}
18073c1cb7e3SWang Nan 
1808dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
18093c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
18102dd6d8a1SAdrian Hunter }
1811bfacbe3bSJiri Olsa 
1812bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
1813bfacbe3bSJiri Olsa {
1814bfacbe3bSJiri Olsa 	struct record *rec = &record;
1815bfacbe3bSJiri Olsa 
1816bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
1817bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
1818bfacbe3bSJiri Olsa }
1819