xref: /openbmc/linux/tools/perf/builtin-record.c (revision 26d330226b9cf6208daae9b0b3697980c8fb51d8)
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  */
8b8f46c5aSXiao Guangrong #define _FILE_OFFSET_BITS 64
9b8f46c5aSXiao Guangrong 
1086470930SIngo Molnar #include "builtin.h"
1186470930SIngo Molnar 
1286470930SIngo Molnar #include "perf.h"
1386470930SIngo Molnar 
146122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1586470930SIngo Molnar #include "util/util.h"
1686470930SIngo Molnar #include "util/parse-options.h"
1786470930SIngo Molnar #include "util/parse-events.h"
1886470930SIngo Molnar 
197c6a1c65SPeter Zijlstra #include "util/header.h"
2066e274f3SFrederic Weisbecker #include "util/event.h"
21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
238f28827aSFrederic Weisbecker #include "util/debug.h"
2494c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
27a12b51c4SPaul Mackerras #include "util/cpumap.h"
28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
297c6a1c65SPeter Zijlstra 
3086470930SIngo Molnar #include <unistd.h>
3186470930SIngo Molnar #include <sched.h>
32a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
3386470930SIngo Molnar 
34*26d33022SJiri Olsa #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
35*26d33022SJiri Olsa 
36*26d33022SJiri Olsa #ifdef NO_LIBUNWIND_SUPPORT
37*26d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp]";
38*26d33022SJiri Olsa #else
39*26d33022SJiri Olsa static unsigned long default_stack_dump_size = 8192;
40*26d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
41*26d33022SJiri Olsa #endif
42*26d33022SJiri Olsa 
437865e817SFrederic Weisbecker enum write_mode_t {
447865e817SFrederic Weisbecker 	WRITE_FORCE,
457865e817SFrederic Weisbecker 	WRITE_APPEND
467865e817SFrederic Weisbecker };
477865e817SFrederic Weisbecker 
48d20deb64SArnaldo Carvalho de Melo struct perf_record {
4945694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
50d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts	opts;
51d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
52d20deb64SArnaldo Carvalho de Melo 	const char		*output_name;
53d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
54d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
55d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
56d20deb64SArnaldo Carvalho de Melo 	int			output;
57d20deb64SArnaldo Carvalho de Melo 	unsigned int		page_size;
58d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
59d20deb64SArnaldo Carvalho de Melo 	enum write_mode_t	write_mode;
60d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
61d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
62d20deb64SArnaldo Carvalho de Melo 	bool			force;
63d20deb64SArnaldo Carvalho de Melo 	bool			file_new;
64d20deb64SArnaldo Carvalho de Melo 	bool			append_file;
65d20deb64SArnaldo Carvalho de Melo 	long			samples;
66d20deb64SArnaldo Carvalho de Melo 	off_t			post_processing_offset;
670f82ebc4SArnaldo Carvalho de Melo };
6886470930SIngo Molnar 
69d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size)
709215545eSTom Zanussi {
71d20deb64SArnaldo Carvalho de Melo 	rec->bytes_written += size;
729215545eSTom Zanussi }
739215545eSTom Zanussi 
74d20deb64SArnaldo Carvalho de Melo static void write_output(struct perf_record *rec, void *buf, size_t size)
75f5970550SPeter Zijlstra {
76f5970550SPeter Zijlstra 	while (size) {
77d20deb64SArnaldo Carvalho de Melo 		int ret = write(rec->output, buf, size);
78f5970550SPeter Zijlstra 
79f5970550SPeter Zijlstra 		if (ret < 0)
80f5970550SPeter Zijlstra 			die("failed to write");
81f5970550SPeter Zijlstra 
82f5970550SPeter Zijlstra 		size -= ret;
83f5970550SPeter Zijlstra 		buf += ret;
84f5970550SPeter Zijlstra 
85d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written += ret;
86f5970550SPeter Zijlstra 	}
87f5970550SPeter Zijlstra }
88f5970550SPeter Zijlstra 
8945694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
90d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
918d50e5b4SArnaldo Carvalho de Melo 				     struct perf_sample *sample __used,
92743eb868SArnaldo Carvalho de Melo 				     struct machine *machine __used)
93234fbbf5SArnaldo Carvalho de Melo {
9445694aa7SArnaldo Carvalho de Melo 	struct perf_record *rec = container_of(tool, struct perf_record, tool);
95d20deb64SArnaldo Carvalho de Melo 	write_output(rec, event, event->header.size);
96234fbbf5SArnaldo Carvalho de Melo 	return 0;
97234fbbf5SArnaldo Carvalho de Melo }
98234fbbf5SArnaldo Carvalho de Melo 
99d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read(struct perf_record *rec,
100d20deb64SArnaldo Carvalho de Melo 				   struct perf_mmap *md)
10186470930SIngo Molnar {
102744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
10386470930SIngo Molnar 	unsigned int old = md->prev;
104d20deb64SArnaldo Carvalho de Melo 	unsigned char *data = md->base + rec->page_size;
10586470930SIngo Molnar 	unsigned long size;
10686470930SIngo Molnar 	void *buf;
10786470930SIngo Molnar 
108dc82009aSArnaldo Carvalho de Melo 	if (old == head)
109dc82009aSArnaldo Carvalho de Melo 		return;
11086470930SIngo Molnar 
111d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
11286470930SIngo Molnar 
11386470930SIngo Molnar 	size = head - old;
11486470930SIngo Molnar 
11586470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
11686470930SIngo Molnar 		buf = &data[old & md->mask];
11786470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
11886470930SIngo Molnar 		old += size;
11986470930SIngo Molnar 
120d20deb64SArnaldo Carvalho de Melo 		write_output(rec, buf, size);
12186470930SIngo Molnar 	}
12286470930SIngo Molnar 
12386470930SIngo Molnar 	buf = &data[old & md->mask];
12486470930SIngo Molnar 	size = head - old;
12586470930SIngo Molnar 	old += size;
12686470930SIngo Molnar 
127d20deb64SArnaldo Carvalho de Melo 	write_output(rec, buf, size);
12886470930SIngo Molnar 
12986470930SIngo Molnar 	md->prev = old;
130115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
13186470930SIngo Molnar }
13286470930SIngo Molnar 
13386470930SIngo Molnar static volatile int done = 0;
134f7b7c26eSPeter Zijlstra static volatile int signr = -1;
13533e49ea7SAndi Kleen static volatile int child_finished = 0;
13686470930SIngo Molnar 
13786470930SIngo Molnar static void sig_handler(int sig)
13886470930SIngo Molnar {
13933e49ea7SAndi Kleen 	if (sig == SIGCHLD)
14033e49ea7SAndi Kleen 		child_finished = 1;
14133e49ea7SAndi Kleen 
14286470930SIngo Molnar 	done = 1;
143f7b7c26eSPeter Zijlstra 	signr = sig;
144f7b7c26eSPeter Zijlstra }
145f7b7c26eSPeter Zijlstra 
146d20deb64SArnaldo Carvalho de Melo static void perf_record__sig_exit(int exit_status __used, void *arg)
147f7b7c26eSPeter Zijlstra {
148d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
14933e49ea7SAndi Kleen 	int status;
15033e49ea7SAndi Kleen 
151d20deb64SArnaldo Carvalho de Melo 	if (rec->evlist->workload.pid > 0) {
15233e49ea7SAndi Kleen 		if (!child_finished)
153d20deb64SArnaldo Carvalho de Melo 			kill(rec->evlist->workload.pid, SIGTERM);
154933da83aSChris Wilson 
15533e49ea7SAndi Kleen 		wait(&status);
15633e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
157d20deb64SArnaldo Carvalho de Melo 			psignal(WTERMSIG(status), rec->progname);
15833e49ea7SAndi Kleen 	}
15933e49ea7SAndi Kleen 
16018483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
161f7b7c26eSPeter Zijlstra 		return;
162f7b7c26eSPeter Zijlstra 
163f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
164f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
16586470930SIngo Molnar }
16686470930SIngo Molnar 
167a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
168a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
169a91e5431SArnaldo Carvalho de Melo {
170a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
171a91e5431SArnaldo Carvalho de Melo 
172a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
173a91e5431SArnaldo Carvalho de Melo 		return false;
174a91e5431SArnaldo Carvalho de Melo 
175a91e5431SArnaldo Carvalho de Melo 	pair = list_entry(other->entries.next, struct perf_evsel, node);
176a91e5431SArnaldo Carvalho de Melo 
177a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
178a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
179a91e5431SArnaldo Carvalho de Melo 			return false;
180a91e5431SArnaldo Carvalho de Melo 		pair = list_entry(pair->node.next, struct perf_evsel, node);
181a91e5431SArnaldo Carvalho de Melo 	}
182a91e5431SArnaldo Carvalho de Melo 
183a91e5431SArnaldo Carvalho de Melo 	return true;
184a91e5431SArnaldo Carvalho de Melo }
185a91e5431SArnaldo Carvalho de Melo 
186d20deb64SArnaldo Carvalho de Melo static void perf_record__open(struct perf_record *rec)
187dd7927f4SArnaldo Carvalho de Melo {
188727ab04eSArnaldo Carvalho de Melo 	struct perf_evsel *pos, *first;
189d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
190d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
191d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
192dd7927f4SArnaldo Carvalho de Melo 
193727ab04eSArnaldo Carvalho de Melo 	first = list_entry(evlist->entries.next, struct perf_evsel, node);
194727ab04eSArnaldo Carvalho de Melo 
195d20deb64SArnaldo Carvalho de Melo 	perf_evlist__config_attrs(evlist, opts);
1960f82ebc4SArnaldo Carvalho de Melo 
197dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
198dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
199727ab04eSArnaldo Carvalho de Melo 		struct xyarray *group_fd = NULL;
200dd7927f4SArnaldo Carvalho de Melo 		/*
201dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
202dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
203dd7927f4SArnaldo Carvalho de Melo 		 *
204dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
205dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
206dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
207dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
208dd7927f4SArnaldo Carvalho de Melo 		 *
209dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
210dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
211dd7927f4SArnaldo Carvalho de Melo 		 */
212dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
213dd7927f4SArnaldo Carvalho de Melo 
214d20deb64SArnaldo Carvalho de Melo 		if (opts->group && pos != first)
215727ab04eSArnaldo Carvalho de Melo 			group_fd = first->fd;
2160c978128SArnaldo Carvalho de Melo fallback_missing_features:
2170c978128SArnaldo Carvalho de Melo 		if (opts->exclude_guest_missing)
2180c978128SArnaldo Carvalho de Melo 			attr->exclude_guest = attr->exclude_host = 0;
2199c90a61cSArnaldo Carvalho de Melo retry_sample_id:
220808e1226SArnaldo Carvalho de Melo 		attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
2213da297a6SIngo Molnar try_again:
222ed80f581SArnaldo Carvalho de Melo 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
223d20deb64SArnaldo Carvalho de Melo 				     opts->group, group_fd) < 0) {
22486470930SIngo Molnar 			int err = errno;
22586470930SIngo Molnar 
226c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
227b8631e6eSArnaldo Carvalho de Melo 				ui__error_paranoid();
228c286c419SArnaldo Carvalho de Melo 				exit(EXIT_FAILURE);
229bea03405SNamhyung Kim 			} else if (err ==  ENODEV && opts->target.cpu_list) {
230d6d901c2SZhang, Yanmin 				die("No such device - did you specify"
231d6d901c2SZhang, Yanmin 					" an out-of-range profile CPU?\n");
2320c978128SArnaldo Carvalho de Melo 			} else if (err == EINVAL) {
2330c978128SArnaldo Carvalho de Melo 				if (!opts->exclude_guest_missing &&
2340c978128SArnaldo Carvalho de Melo 				    (attr->exclude_guest || attr->exclude_host)) {
2350c978128SArnaldo Carvalho de Melo 					pr_debug("Old kernel, cannot exclude "
2360c978128SArnaldo Carvalho de Melo 						 "guest or host samples.\n");
2370c978128SArnaldo Carvalho de Melo 					opts->exclude_guest_missing = true;
2380c978128SArnaldo Carvalho de Melo 					goto fallback_missing_features;
239808e1226SArnaldo Carvalho de Melo 				} else if (!opts->sample_id_all_missing) {
2409c90a61cSArnaldo Carvalho de Melo 					/*
2419c90a61cSArnaldo Carvalho de Melo 					 * Old kernel, no attr->sample_id_type_all field
2429c90a61cSArnaldo Carvalho de Melo 					 */
243808e1226SArnaldo Carvalho de Melo 					opts->sample_id_all_missing = true;
244d20deb64SArnaldo Carvalho de Melo 					if (!opts->sample_time && !opts->raw_samples && !time_needed)
245eac23d1cSIan Munsie 						attr->sample_type &= ~PERF_SAMPLE_TIME;
246eac23d1cSIan Munsie 
2479c90a61cSArnaldo Carvalho de Melo 					goto retry_sample_id;
248d6d901c2SZhang, Yanmin 				}
2490c978128SArnaldo Carvalho de Melo 			}
2503da297a6SIngo Molnar 
2513da297a6SIngo Molnar 			/*
2523da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2533da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
254028d455bSDavid Ahern 			 * is always available even if no PMU support.
255028d455bSDavid Ahern 			 *
256028d455bSDavid Ahern 			 * PPC returns ENXIO until 2.6.37 (behavior changed
257028d455bSDavid Ahern 			 * with commit b0a873e).
2583da297a6SIngo Molnar 			 */
259028d455bSDavid Ahern 			if ((err == ENOENT || err == ENXIO)
260028d455bSDavid Ahern 					&& attr->type == PERF_TYPE_HARDWARE
261f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
2623da297a6SIngo Molnar 
2633da297a6SIngo Molnar 				if (verbose)
264ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
265ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
2663da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
267f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
268d1cae34dSDavid Ahern 				if (pos->name) {
269d1cae34dSDavid Ahern 					free(pos->name);
270d1cae34dSDavid Ahern 					pos->name = NULL;
271d1cae34dSDavid Ahern 				}
2723da297a6SIngo Molnar 				goto try_again;
2733da297a6SIngo Molnar 			}
274ca6a4258SDavid Ahern 
275ca6a4258SDavid Ahern 			if (err == ENOENT) {
2763780f488SNamhyung Kim 				ui__error("The %s event is not supported.\n",
2777289f83cSArnaldo Carvalho de Melo 					  perf_evsel__name(pos));
278ca6a4258SDavid Ahern 				exit(EXIT_FAILURE);
279ca6a4258SDavid Ahern 			}
280ca6a4258SDavid Ahern 
28130c806a0SIngo Molnar 			printf("\n");
282d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
283dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
284bfd45118SSimon Kaempflein 
285bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
286bfd45118SSimon Kaempflein 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
287d6d901c2SZhang, Yanmin 				die("No hardware sampling interrupt available."
288d6d901c2SZhang, Yanmin 				    " No APIC? If so then you can boot the kernel"
289d6d901c2SZhang, Yanmin 				    " with the \"lapic\" boot parameter to"
290d6d901c2SZhang, Yanmin 				    " force-enable it.\n");
291bfd45118SSimon Kaempflein #endif
292bfd45118SSimon Kaempflein 
293cdd6c482SIngo Molnar 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
2947c6a1c65SPeter Zijlstra 		}
2957c6a1c65SPeter Zijlstra 	}
2967c6a1c65SPeter Zijlstra 
2970a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
2980a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
2990a102479SFrederic Weisbecker 			strerror(errno));
3000a102479SFrederic Weisbecker 		exit(-1);
3010a102479SFrederic Weisbecker 	}
3020a102479SFrederic Weisbecker 
30318e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
30418e60939SNelson Elhage 		if (errno == EPERM)
30518e60939SNelson Elhage 			die("Permission error mapping pages.\n"
30618e60939SNelson Elhage 			    "Consider increasing "
30718e60939SNelson Elhage 			    "/proc/sys/kernel/perf_event_mlock_kb,\n"
30818e60939SNelson Elhage 			    "or try again with a smaller value of -m/--mmap_pages.\n"
30918e60939SNelson Elhage 			    "(current value: %d)\n", opts->mmap_pages);
31041d0d933SNelson Elhage 		else if (!is_power_of_2(opts->mmap_pages))
31141d0d933SNelson Elhage 			die("--mmap_pages/-m value must be a power of two.");
31241d0d933SNelson Elhage 
3130a27d7f9SArnaldo Carvalho de Melo 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
31418e60939SNelson Elhage 	}
3150a27d7f9SArnaldo Carvalho de Melo 
316d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
317a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
318a91e5431SArnaldo Carvalho de Melo 	else {
319a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
320a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
321a91e5431SArnaldo Carvalho de Melo 			exit(-1);
322dd7927f4SArnaldo Carvalho de Melo 		}
32386470930SIngo Molnar  	}
32486470930SIngo Molnar 
3257b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
326a91e5431SArnaldo Carvalho de Melo }
327a91e5431SArnaldo Carvalho de Melo 
328d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
3296122e4e4SArnaldo Carvalho de Melo {
330d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
3316122e4e4SArnaldo Carvalho de Melo 
3329f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3339f591fd7SArnaldo Carvalho de Melo 		return 0;
3349f591fd7SArnaldo Carvalho de Melo 
335d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
336d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
337d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
3386122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3396122e4e4SArnaldo Carvalho de Melo }
3406122e4e4SArnaldo Carvalho de Melo 
341d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg)
342f5970550SPeter Zijlstra {
343d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
344f5970550SPeter Zijlstra 
345d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
346d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
347d20deb64SArnaldo Carvalho de Melo 
348d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
349d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
350d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
351d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
352d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
353d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
354d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
355c7929e47STom Zanussi 	}
356f5970550SPeter Zijlstra }
357f5970550SPeter Zijlstra 
3588115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
359a1645ce1SZhang, Yanmin {
360a1645ce1SZhang, Yanmin 	int err;
36145694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
362a1645ce1SZhang, Yanmin 
36323346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
364a1645ce1SZhang, Yanmin 		return;
365a1645ce1SZhang, Yanmin 
366a1645ce1SZhang, Yanmin 	/*
367a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
368a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
369a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
370a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
371a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
372a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
373a1645ce1SZhang, Yanmin 	 */
37445694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
375743eb868SArnaldo Carvalho de Melo 					     machine);
376a1645ce1SZhang, Yanmin 	if (err < 0)
377a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
37823346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
379a1645ce1SZhang, Yanmin 
380a1645ce1SZhang, Yanmin 	/*
381a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
382a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
383a1645ce1SZhang, Yanmin 	 */
38445694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
385743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
386a1645ce1SZhang, Yanmin 	if (err < 0)
38745694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
388743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
389a1645ce1SZhang, Yanmin 	if (err < 0)
390a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
39123346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
392a1645ce1SZhang, Yanmin }
393a1645ce1SZhang, Yanmin 
39498402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
39598402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
39698402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
39798402807SFrederic Weisbecker };
39898402807SFrederic Weisbecker 
399d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec)
40098402807SFrederic Weisbecker {
4010e2e63ddSPeter Zijlstra 	int i;
40298402807SFrederic Weisbecker 
403d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
404d20deb64SArnaldo Carvalho de Melo 		if (rec->evlist->mmap[i].base)
405d20deb64SArnaldo Carvalho de Melo 			perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
40698402807SFrederic Weisbecker 	}
40798402807SFrederic Weisbecker 
4082eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
409d20deb64SArnaldo Carvalho de Melo 		write_output(rec, &finished_round_event, sizeof(finished_round_event));
41098402807SFrederic Weisbecker }
41198402807SFrederic Weisbecker 
412d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
41386470930SIngo Molnar {
41486470930SIngo Molnar 	struct stat st;
41586470930SIngo Molnar 	int flags;
416781ba9d2SRobert Richter 	int err, output, feat;
4178b412664SPeter Zijlstra 	unsigned long waking = 0;
41846be604bSZhang, Yanmin 	const bool forks = argc > 0;
41923346f21SArnaldo Carvalho de Melo 	struct machine *machine;
42045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
421d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
422d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
423d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
424d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
42586470930SIngo Molnar 
426d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
42733e49ea7SAndi Kleen 
428d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
42986470930SIngo Molnar 
430d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
431f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
432f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
43318483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
434f5970550SPeter Zijlstra 
435d7065adbSFranck Bui-Huu 	if (!output_name) {
436d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
437d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
438d7065adbSFranck Bui-Huu 		else
439d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
440d7065adbSFranck Bui-Huu 	}
441d7065adbSFranck Bui-Huu 	if (output_name) {
442529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
443d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
444529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
445d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
446b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
447b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
448b38d3464SArnaldo Carvalho de Melo 					 output_name);
449b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
450b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
451b38d3464SArnaldo Carvalho de Melo 			}
452d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
453d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
454266e0e21SPierre Habouzit 		}
455d7065adbSFranck Bui-Huu 	}
45686470930SIngo Molnar 
457f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
458d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
459d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
46086470930SIngo Molnar 	else
46186470930SIngo Molnar 		flags |= O_TRUNC;
46286470930SIngo Molnar 
463d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
464529870e3STom Zanussi 		output = STDOUT_FILENO;
465529870e3STom Zanussi 	else
46686470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
46786470930SIngo Molnar 	if (output < 0) {
46886470930SIngo Molnar 		perror("failed to create output file");
46986470930SIngo Molnar 		exit(-1);
47086470930SIngo Molnar 	}
47186470930SIngo Molnar 
472d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
473d20deb64SArnaldo Carvalho de Melo 
4747865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
475d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
47694c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
477a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
478a9a70bbcSArnaldo Carvalho de Melo 		return -1;
479a9a70bbcSArnaldo Carvalho de Melo 	}
480a9a70bbcSArnaldo Carvalho de Melo 
481d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
482d20deb64SArnaldo Carvalho de Melo 
483781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
484781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
485781ba9d2SRobert Richter 
486781ba9d2SRobert Richter 	if (rec->no_buildid)
487781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
488781ba9d2SRobert Richter 
489781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
4902eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
491baa2f6ceSArnaldo Carvalho de Melo 
492330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
493330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
494330aa675SStephane Eranian 
495d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
496a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
4974dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
49839d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
4994dc0a04bSArnaldo Carvalho de Melo 	}
5004dc0a04bSArnaldo Carvalho de Melo 
501d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
502d20deb64SArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
50335b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
50435b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
50535b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
506856e9660SPeter Zijlstra 		}
507856e9660SPeter Zijlstra 	}
508856e9660SPeter Zijlstra 
509d20deb64SArnaldo Carvalho de Melo 	perf_record__open(rec);
51086470930SIngo Molnar 
511712a4b60SArnaldo Carvalho de Melo 	/*
512d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
513712a4b60SArnaldo Carvalho de Melo 	 */
514d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
515712a4b60SArnaldo Carvalho de Melo 
516d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
517529870e3STom Zanussi 		err = perf_header__write_pipe(output);
518529870e3STom Zanussi 		if (err < 0)
519529870e3STom Zanussi 			return err;
520d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
521a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
522361c99a6SArnaldo Carvalho de Melo 						 output, false);
523d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
524d5eed904SArnaldo Carvalho de Melo 			return err;
525d5eed904SArnaldo Carvalho de Melo 	}
5267c6a1c65SPeter Zijlstra 
527d3665498SDavid Ahern 	if (!rec->no_buildid
528e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
529d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
530e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
531e20960c0SRobert Richter 		return -1;
532e20960c0SRobert Richter 	}
533e20960c0SRobert Richter 
534d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
5356122e4e4SArnaldo Carvalho de Melo 
536743eb868SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
537743eb868SArnaldo Carvalho de Melo 	if (!machine) {
538743eb868SArnaldo Carvalho de Melo 		pr_err("Couldn't find native kernel information.\n");
539743eb868SArnaldo Carvalho de Melo 		return -1;
540743eb868SArnaldo Carvalho de Melo 	}
541743eb868SArnaldo Carvalho de Melo 
542d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
54345694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
544a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
5452c46dbb5STom Zanussi 		if (err < 0) {
5462c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
5472c46dbb5STom Zanussi 			return err;
5482c46dbb5STom Zanussi 		}
549cd19a035STom Zanussi 
55045694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
551743eb868SArnaldo Carvalho de Melo 							 machine);
552cd19a035STom Zanussi 		if (err < 0) {
553cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
554cd19a035STom Zanussi 			return err;
555cd19a035STom Zanussi 		}
5569215545eSTom Zanussi 
557361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
55863e0c771STom Zanussi 			/*
55963e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
56063e0c771STom Zanussi 			 * there were no tracepoints so its not really
56163e0c771STom Zanussi 			 * an error, just that we don't need to
56263e0c771STom Zanussi 			 * synthesize anything.  We really have to
56363e0c771STom Zanussi 			 * return this more properly and also
56463e0c771STom Zanussi 			 * propagate errors that now are calling die()
56563e0c771STom Zanussi 			 */
56645694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
567743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
56863e0c771STom Zanussi 			if (err <= 0) {
56963e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
57063e0c771STom Zanussi 				return err;
57163e0c771STom Zanussi 			}
572d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
5732c46dbb5STom Zanussi 		}
57463e0c771STom Zanussi 	}
5752c46dbb5STom Zanussi 
57645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
577743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
57870162138SArnaldo Carvalho de Melo 	if (err < 0)
57945694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
580743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
581c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
582c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
583c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
584c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
58556b03f3cSArnaldo Carvalho de Melo 
58645694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
587743eb868SArnaldo Carvalho de Melo 					     machine);
588c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
589c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
590c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
591c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
592c1a3a4b9SArnaldo Carvalho de Melo 
593a1645ce1SZhang, Yanmin 	if (perf_guest)
59445694aa7SArnaldo Carvalho de Melo 		perf_session__process_machines(session, tool,
5958115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
596b7cece76SArnaldo Carvalho de Melo 
597bea03405SNamhyung Kim 	if (!opts->target.system_wide)
59845694aa7SArnaldo Carvalho de Melo 		perf_event__synthesize_thread_map(tool, evsel_list->threads,
5998115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
600743eb868SArnaldo Carvalho de Melo 						  machine);
601234fbbf5SArnaldo Carvalho de Melo 	else
60245694aa7SArnaldo Carvalho de Melo 		perf_event__synthesize_threads(tool, process_synthesized_event,
603743eb868SArnaldo Carvalho de Melo 					       machine);
6047c6a1c65SPeter Zijlstra 
605d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
60686470930SIngo Molnar 		struct sched_param param;
60786470930SIngo Molnar 
608d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
60986470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6106beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
61186470930SIngo Molnar 			exit(-1);
61286470930SIngo Molnar 		}
61386470930SIngo Molnar 	}
61486470930SIngo Molnar 
615764e16a3SDavid Ahern 	perf_evlist__enable(evsel_list);
616764e16a3SDavid Ahern 
617856e9660SPeter Zijlstra 	/*
618856e9660SPeter Zijlstra 	 * Let the child rip
619856e9660SPeter Zijlstra 	 */
620d4db3f16SArnaldo Carvalho de Melo 	if (forks)
62135b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
622856e9660SPeter Zijlstra 
623649c48a9SPeter Zijlstra 	for (;;) {
624d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
62586470930SIngo Molnar 
626d20deb64SArnaldo Carvalho de Melo 		perf_record__mmap_read_all(rec);
62786470930SIngo Molnar 
628d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
629649c48a9SPeter Zijlstra 			if (done)
630649c48a9SPeter Zijlstra 				break;
6315c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6328b412664SPeter Zijlstra 			waking++;
6338b412664SPeter Zijlstra 		}
6348b412664SPeter Zijlstra 
6354152ab37SArnaldo Carvalho de Melo 		if (done)
6364152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6378b412664SPeter Zijlstra 	}
6388b412664SPeter Zijlstra 
63918483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
640b44308f5SArnaldo Carvalho de Melo 		return 0;
641b44308f5SArnaldo Carvalho de Melo 
6428b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
64386470930SIngo Molnar 
64486470930SIngo Molnar 	/*
64586470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
64686470930SIngo Molnar 	 */
64786470930SIngo Molnar 	fprintf(stderr,
6489486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
649d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
65086470930SIngo Molnar 		output_name,
651d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
65286470930SIngo Molnar 
65386470930SIngo Molnar 	return 0;
65439d17dacSArnaldo Carvalho de Melo 
65539d17dacSArnaldo Carvalho de Melo out_delete_session:
65639d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
65739d17dacSArnaldo Carvalho de Melo 	return err;
65886470930SIngo Molnar }
65986470930SIngo Molnar 
660bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
661bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
662bdfebd84SRoberto Agostino Vitillo 
663bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
664bdfebd84SRoberto Agostino Vitillo 
665bdfebd84SRoberto Agostino Vitillo struct branch_mode {
666bdfebd84SRoberto Agostino Vitillo 	const char *name;
667bdfebd84SRoberto Agostino Vitillo 	int mode;
668bdfebd84SRoberto Agostino Vitillo };
669bdfebd84SRoberto Agostino Vitillo 
670bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
671bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
672bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
673bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
674bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
675bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
676bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
677bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
678bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
679bdfebd84SRoberto Agostino Vitillo };
680bdfebd84SRoberto Agostino Vitillo 
681bdfebd84SRoberto Agostino Vitillo static int
682a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
683bdfebd84SRoberto Agostino Vitillo {
684bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
685bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
686bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
687bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
688bdfebd84SRoberto Agostino Vitillo 
689bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
690bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
691a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
692bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
693bdfebd84SRoberto Agostino Vitillo 
694a5aabdacSStephane Eranian 	if (unset)
695a5aabdacSStephane Eranian 		return 0;
696bdfebd84SRoberto Agostino Vitillo 
697a5aabdacSStephane Eranian 	/*
698a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
699a5aabdacSStephane Eranian 	 */
700a5aabdacSStephane Eranian 	if (*mode)
701a5aabdacSStephane Eranian 		return -1;
702a5aabdacSStephane Eranian 
703a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
704a5aabdacSStephane Eranian 	if (str) {
705bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
706bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
707bdfebd84SRoberto Agostino Vitillo 		if (!s)
708bdfebd84SRoberto Agostino Vitillo 			return -1;
709bdfebd84SRoberto Agostino Vitillo 
710bdfebd84SRoberto Agostino Vitillo 		for (;;) {
711bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
712bdfebd84SRoberto Agostino Vitillo 			if (p)
713bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
714bdfebd84SRoberto Agostino Vitillo 
715bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
716bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
717bdfebd84SRoberto Agostino Vitillo 					break;
718bdfebd84SRoberto Agostino Vitillo 			}
719a5aabdacSStephane Eranian 			if (!br->name) {
720a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
721a5aabdacSStephane Eranian 					    " check man page\n", s);
722bdfebd84SRoberto Agostino Vitillo 				goto error;
723a5aabdacSStephane Eranian 			}
724bdfebd84SRoberto Agostino Vitillo 
725bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
726bdfebd84SRoberto Agostino Vitillo 
727bdfebd84SRoberto Agostino Vitillo 			if (!p)
728bdfebd84SRoberto Agostino Vitillo 				break;
729bdfebd84SRoberto Agostino Vitillo 
730bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
731bdfebd84SRoberto Agostino Vitillo 		}
732a5aabdacSStephane Eranian 	}
733bdfebd84SRoberto Agostino Vitillo 	ret = 0;
734bdfebd84SRoberto Agostino Vitillo 
735a5aabdacSStephane Eranian 	/* default to any branch */
736bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
737a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
738bdfebd84SRoberto Agostino Vitillo 	}
739bdfebd84SRoberto Agostino Vitillo error:
740bdfebd84SRoberto Agostino Vitillo 	free(os);
741bdfebd84SRoberto Agostino Vitillo 	return ret;
742bdfebd84SRoberto Agostino Vitillo }
743bdfebd84SRoberto Agostino Vitillo 
744*26d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT
745*26d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
746*26d33022SJiri Olsa {
747*26d33022SJiri Olsa 	char *endptr;
748*26d33022SJiri Olsa 	unsigned long size;
749*26d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
750*26d33022SJiri Olsa 
751*26d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
752*26d33022SJiri Olsa 
753*26d33022SJiri Olsa 	do {
754*26d33022SJiri Olsa 		if (*endptr)
755*26d33022SJiri Olsa 			break;
756*26d33022SJiri Olsa 
757*26d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
758*26d33022SJiri Olsa 		if (!size || size > max_size)
759*26d33022SJiri Olsa 			break;
760*26d33022SJiri Olsa 
761*26d33022SJiri Olsa 		*_size = size;
762*26d33022SJiri Olsa 		return 0;
763*26d33022SJiri Olsa 
764*26d33022SJiri Olsa 	} while (0);
765*26d33022SJiri Olsa 
766*26d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
767*26d33022SJiri Olsa 	       max_size, str);
768*26d33022SJiri Olsa 	return -1;
769*26d33022SJiri Olsa }
770*26d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */
771*26d33022SJiri Olsa 
772*26d33022SJiri Olsa static int
773*26d33022SJiri Olsa parse_callchain_opt(const struct option *opt __used, const char *arg,
774*26d33022SJiri Olsa 		    int unset)
775*26d33022SJiri Olsa {
776*26d33022SJiri Olsa 	struct perf_record *rec = (struct perf_record *)opt->value;
777*26d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
778*26d33022SJiri Olsa 	char *buf;
779*26d33022SJiri Olsa 	int ret = -1;
780*26d33022SJiri Olsa 
781*26d33022SJiri Olsa 	/* --no-call-graph */
782*26d33022SJiri Olsa 	if (unset)
783*26d33022SJiri Olsa 		return 0;
784*26d33022SJiri Olsa 
785*26d33022SJiri Olsa 	/* We specified default option if none is provided. */
786*26d33022SJiri Olsa 	BUG_ON(!arg);
787*26d33022SJiri Olsa 
788*26d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
789*26d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
790*26d33022SJiri Olsa 	if (!buf)
791*26d33022SJiri Olsa 		return -ENOMEM;
792*26d33022SJiri Olsa 
793*26d33022SJiri Olsa 	strcpy(buf, arg);
794*26d33022SJiri Olsa 
795*26d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
796*26d33022SJiri Olsa 	name = tok ? : (char *)buf;
797*26d33022SJiri Olsa 
798*26d33022SJiri Olsa 	do {
799*26d33022SJiri Olsa 		/* Framepointer style */
800*26d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
801*26d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
802*26d33022SJiri Olsa 				rec->opts.call_graph = CALLCHAIN_FP;
803*26d33022SJiri Olsa 				ret = 0;
804*26d33022SJiri Olsa 			} else
805*26d33022SJiri Olsa 				pr_err("callchain: No more arguments "
806*26d33022SJiri Olsa 				       "needed for -g fp\n");
807*26d33022SJiri Olsa 			break;
808*26d33022SJiri Olsa 
809*26d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT
810*26d33022SJiri Olsa 		/* Dwarf style */
811*26d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
812*26d33022SJiri Olsa 			ret = 0;
813*26d33022SJiri Olsa 			rec->opts.call_graph = CALLCHAIN_DWARF;
814*26d33022SJiri Olsa 			rec->opts.stack_dump_size = default_stack_dump_size;
815*26d33022SJiri Olsa 
816*26d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
817*26d33022SJiri Olsa 			if (tok) {
818*26d33022SJiri Olsa 				unsigned long size = 0;
819*26d33022SJiri Olsa 
820*26d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
821*26d33022SJiri Olsa 				rec->opts.stack_dump_size = size;
822*26d33022SJiri Olsa 			}
823*26d33022SJiri Olsa 
824*26d33022SJiri Olsa 			if (!ret)
825*26d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
826*26d33022SJiri Olsa 					 rec->opts.stack_dump_size);
827*26d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */
828*26d33022SJiri Olsa 		} else {
829*26d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
830*26d33022SJiri Olsa 			       "value: %s\n", arg);
831*26d33022SJiri Olsa 			break;
832*26d33022SJiri Olsa 		}
833*26d33022SJiri Olsa 
834*26d33022SJiri Olsa 	} while (0);
835*26d33022SJiri Olsa 
836*26d33022SJiri Olsa 	free(buf);
837*26d33022SJiri Olsa 
838*26d33022SJiri Olsa 	if (!ret)
839*26d33022SJiri Olsa 		pr_debug("callchain: type %d\n", rec->opts.call_graph);
840*26d33022SJiri Olsa 
841*26d33022SJiri Olsa 	return ret;
842*26d33022SJiri Olsa }
843*26d33022SJiri Olsa 
84486470930SIngo Molnar static const char * const record_usage[] = {
84586470930SIngo Molnar 	"perf record [<options>] [<command>]",
84686470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
84786470930SIngo Molnar 	NULL
84886470930SIngo Molnar };
84986470930SIngo Molnar 
850d20deb64SArnaldo Carvalho de Melo /*
851d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
852d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
853d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
854d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
855d20deb64SArnaldo Carvalho de Melo  *
856d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
857d20deb64SArnaldo Carvalho de Melo  *
858d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
859d20deb64SArnaldo Carvalho de Melo  */
860d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
861d20deb64SArnaldo Carvalho de Melo 	.opts = {
862d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
863d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
864d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
865447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
866d1cb9fceSNamhyung Kim 		.target		     = {
867d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
868d1cb9fceSNamhyung Kim 		},
869d20deb64SArnaldo Carvalho de Melo 	},
870d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
871d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
872d20deb64SArnaldo Carvalho de Melo };
8737865e817SFrederic Weisbecker 
874d20deb64SArnaldo Carvalho de Melo /*
875d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
876d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
877d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
878d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
879d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
880d20deb64SArnaldo Carvalho de Melo  */
881bca647aaSTom Zanussi const struct option record_options[] = {
882d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
88386470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
884f120f9d5SJiri Olsa 		     parse_events_option),
885d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
886c171b552SLi Zefan 		     "event filter", parse_filter),
887bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
888d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
889bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
890d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
891d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
89286470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
893d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
894acac03faSKirill Smelkov 		    "collect data without buffering"),
895d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
896daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
897bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
89886470930SIngo Molnar 			    "system-wide collection from all CPUs"),
899d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
90086470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
901bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
902c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
903d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
9047865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
905d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
906d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
90786470930SIngo Molnar 		    "output file name"),
908d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
9092e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
910d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
911d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
91201c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
913d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
91443bece79SLin Ming 		    "put the counters into a counter group"),
915*26d33022SJiri Olsa 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
916*26d33022SJiri Olsa 			     callchain_help, &parse_callchain_opt,
917*26d33022SJiri Olsa 			     "fp"),
918c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
9193da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
920b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
921d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
922649c48a9SPeter Zijlstra 		    "per thread counts"),
923d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
9244bba828dSAnton Blanchard 		    "Sample addresses"),
925d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
9263e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
927d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
928649c48a9SPeter Zijlstra 		    "don't sample"),
929d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
930a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
931d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
932baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
933d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
934023695d9SStephane Eranian 		     "monitor event in cgroup name only",
935023695d9SStephane Eranian 		     parse_cgroups),
936bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
937bea03405SNamhyung Kim 		   "user to profile"),
938a5aabdacSStephane Eranian 
939a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
940a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
941a5aabdacSStephane Eranian 		     parse_branch_stack),
942a5aabdacSStephane Eranian 
943a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
944a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
945bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
94686470930SIngo Molnar 	OPT_END()
94786470930SIngo Molnar };
94886470930SIngo Molnar 
949f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used)
95086470930SIngo Molnar {
95169aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
95269aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
953d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
954d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
95516ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
95686470930SIngo Molnar 
9577e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
958361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
959361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
960361c99a6SArnaldo Carvalho de Melo 
961d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
962d20deb64SArnaldo Carvalho de Melo 
963bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
964a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
965d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
966bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
96786470930SIngo Molnar 
968d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
9693780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
9707865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
971bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
972d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
973d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
9747865e817SFrederic Weisbecker 	} else {
975d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
9767865e817SFrederic Weisbecker 	}
9777865e817SFrederic Weisbecker 
978bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
9793780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
980023695d9SStephane Eranian 			  " system-wide mode\n");
981023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
982023695d9SStephane Eranian 	}
983023695d9SStephane Eranian 
984655000e7SArnaldo Carvalho de Melo 	symbol__init();
985baa2f6ceSArnaldo Carvalho de Melo 
986ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
987646aaea6SArnaldo Carvalho de Melo 		pr_warning(
988646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
989ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
990646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
991646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
992646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
993646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
994646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
995ec80fde7SArnaldo Carvalho de Melo 
996d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
997a1ac1d3cSStephane Eranian 		disable_buildid_cache();
998655000e7SArnaldo Carvalho de Melo 
999361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
1000361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
100169aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
100269aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1003bbd36e5eSPeter Zijlstra 	}
100486470930SIngo Molnar 
100516ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
100616ad2ffbSNamhyung Kim 	if (err) {
100716ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
100816ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
100916ad2ffbSNamhyung Kim 	}
10104bd0f2d2SNamhyung Kim 
101116ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
101216ad2ffbSNamhyung Kim 	if (err) {
101316ad2ffbSNamhyung Kim 		int saved_errno = errno;
101416ad2ffbSNamhyung Kim 
101516ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
10163780f488SNamhyung Kim 		ui__error("%s", errbuf);
101716ad2ffbSNamhyung Kim 
101816ad2ffbSNamhyung Kim 		err = -saved_errno;
10190d37aa34SArnaldo Carvalho de Melo 		goto out_free_fd;
102016ad2ffbSNamhyung Kim 	}
10210d37aa34SArnaldo Carvalho de Melo 
102216ad2ffbSNamhyung Kim 	err = -ENOMEM;
1023b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1024dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
102569aad6f1SArnaldo Carvalho de Melo 
1026361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
10277289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1028ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1029d6d901c2SZhang, Yanmin 	}
10305c581041SArnaldo Carvalho de Melo 
1031d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1032d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1033d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1034d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1035f9212819SFrederic Weisbecker 
10367e4ff9e3SMike Galbraith 	/*
10377e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
10387e4ff9e3SMike Galbraith 	 */
1039d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1040d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1041d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1042d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
10437e4ff9e3SMike Galbraith 	} else {
10443780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
104539d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
10465c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
10477e4ff9e3SMike Galbraith 	}
10487e4ff9e3SMike Galbraith 
1049d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
105039d17dacSArnaldo Carvalho de Melo out_free_fd:
10517e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1052d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1053d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
105439d17dacSArnaldo Carvalho de Melo 	return err;
105586470930SIngo Molnar }
1056