builtin-record.c 25.1 KB
Newer Older
I
Ingo Molnar 已提交
1
/*
2 3 4 5 6
 * builtin-record.c
 *
 * Builtin record command: Record the profile of a workload
 * (or a CPU, or a PID) into the perf.data output file - for
 * later analysis via perf report.
I
Ingo Molnar 已提交
7
 */
8 9
#define _FILE_OFFSET_BITS 64

10
#include "builtin.h"
11 12 13

#include "perf.h"

14
#include "util/build-id.h"
15
#include "util/util.h"
16
#include "util/parse-options.h"
17
#include "util/parse-events.h"
18

19
#include "util/header.h"
20
#include "util/event.h"
21
#include "util/evlist.h"
22
#include "util/evsel.h"
23
#include "util/debug.h"
24
#include "util/session.h"
25
#include "util/tool.h"
26
#include "util/symbol.h"
27
#include "util/cpumap.h"
28
#include "util/thread_map.h"
29

30
#include <unistd.h>
31
#include <sched.h>
32
#include <sys/mman.h>
33

34 35 36 37 38
enum write_mode_t {
	WRITE_FORCE,
	WRITE_APPEND
};

39
struct perf_record {
40
	struct perf_tool	tool;
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
	struct perf_record_opts	opts;
	u64			bytes_written;
	const char		*output_name;
	struct perf_evlist	*evlist;
	struct perf_session	*session;
	const char		*progname;
	int			output;
	unsigned int		page_size;
	int			realtime_prio;
	enum write_mode_t	write_mode;
	bool			no_buildid;
	bool			no_buildid_cache;
	bool			force;
	bool			file_new;
	bool			append_file;
	long			samples;
	off_t			post_processing_offset;
58
};
59

60
static void advance_output(struct perf_record *rec, size_t size)
61
{
62
	rec->bytes_written += size;
63 64
}

65
static void write_output(struct perf_record *rec, void *buf, size_t size)
66 67
{
	while (size) {
68
		int ret = write(rec->output, buf, size);
69 70 71 72 73 74 75

		if (ret < 0)
			die("failed to write");

		size -= ret;
		buf += ret;

76
		rec->bytes_written += ret;
77 78 79
	}
}

80
static int process_synthesized_event(struct perf_tool *tool,
81
				     union perf_event *event,
82
				     struct perf_sample *sample __used,
83
				     struct machine *machine __used)
84
{
85
	struct perf_record *rec = container_of(tool, struct perf_record, tool);
86
	write_output(rec, event, event->header.size);
87 88 89
	return 0;
}

90 91
static void perf_record__mmap_read(struct perf_record *rec,
				   struct perf_mmap *md)
92
{
93
	unsigned int head = perf_mmap__read_head(md);
94
	unsigned int old = md->prev;
95
	unsigned char *data = md->base + rec->page_size;
96 97 98
	unsigned long size;
	void *buf;

99 100 101
	if (old == head)
		return;

102
	rec->samples++;
103 104 105 106 107 108 109

	size = head - old;

	if ((old & md->mask) + size != (head & md->mask)) {
		buf = &data[old & md->mask];
		size = md->mask + 1 - (old & md->mask);
		old += size;
110

111
		write_output(rec, buf, size);
112 113 114 115 116
	}

	buf = &data[old & md->mask];
	size = head - old;
	old += size;
117

118
	write_output(rec, buf, size);
119 120

	md->prev = old;
121
	perf_mmap__write_tail(md, old);
122 123 124
}

static volatile int done = 0;
125
static volatile int signr = -1;
126
static volatile int child_finished = 0;
127

128
static void sig_handler(int sig)
129
{
130 131 132
	if (sig == SIGCHLD)
		child_finished = 1;

133
	done = 1;
134 135 136
	signr = sig;
}

137
static void perf_record__sig_exit(int exit_status __used, void *arg)
138
{
139
	struct perf_record *rec = arg;
140 141
	int status;

142
	if (rec->evlist->workload.pid > 0) {
143
		if (!child_finished)
144
			kill(rec->evlist->workload.pid, SIGTERM);
145 146 147

		wait(&status);
		if (WIFSIGNALED(status))
148
			psignal(WTERMSIG(status), rec->progname);
149
	}
150

151
	if (signr == -1 || signr == SIGUSR1)
152 153 154 155
		return;

	signal(signr, SIG_DFL);
	kill(getpid(), signr);
156 157
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
static bool perf_evlist__equal(struct perf_evlist *evlist,
			       struct perf_evlist *other)
{
	struct perf_evsel *pos, *pair;

	if (evlist->nr_entries != other->nr_entries)
		return false;

	pair = list_entry(other->entries.next, struct perf_evsel, node);

	list_for_each_entry(pos, &evlist->entries, node) {
		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
			return false;
		pair = list_entry(pair->node.next, struct perf_evsel, node);
	}

	return true;
}

177
static void perf_record__open(struct perf_record *rec)
178
{
179
	struct perf_evsel *pos, *first;
180 181 182
	struct perf_evlist *evlist = rec->evlist;
	struct perf_session *session = rec->session;
	struct perf_record_opts *opts = &rec->opts;
183

184 185
	first = list_entry(evlist->entries.next, struct perf_evsel, node);

186
	perf_evlist__config_attrs(evlist, opts);
187

188 189
	list_for_each_entry(pos, &evlist->entries, node) {
		struct perf_event_attr *attr = &pos->attr;
190
		struct xyarray *group_fd = NULL;
191 192 193 194 195 196 197 198 199 200 201 202 203
		/*
		 * Check if parse_single_tracepoint_event has already asked for
		 * PERF_SAMPLE_TIME.
		 *
		 * XXX this is kludgy but short term fix for problems introduced by
		 * eac23d1c that broke 'perf script' by having different sample_types
		 * when using multiple tracepoint events when we use a perf binary
		 * that tries to use sample_id_all on an older kernel.
		 *
		 * We need to move counter creation to perf_session, support
		 * different sample_types, etc.
		 */
		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
204

205
		if (opts->group && pos != first)
206
			group_fd = first->fd;
207 208 209
fallback_missing_features:
		if (opts->exclude_guest_missing)
			attr->exclude_guest = attr->exclude_host = 0;
210
retry_sample_id:
211
		attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
212
try_again:
213
		if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
214
				     opts->group, group_fd) < 0) {
215 216
			int err = errno;

217
			if (err == EPERM || err == EACCES) {
218
				ui__error_paranoid();
219
				exit(EXIT_FAILURE);
220
			} else if (err ==  ENODEV && opts->target.cpu_list) {
221 222
				die("No such device - did you specify"
					" an out-of-range profile CPU?\n");
223 224 225 226 227 228 229
			} else if (err == EINVAL) {
				if (!opts->exclude_guest_missing &&
				    (attr->exclude_guest || attr->exclude_host)) {
					pr_debug("Old kernel, cannot exclude "
						 "guest or host samples.\n");
					opts->exclude_guest_missing = true;
					goto fallback_missing_features;
230
				} else if (!opts->sample_id_all_missing) {
231 232 233
					/*
					 * Old kernel, no attr->sample_id_type_all field
					 */
234
					opts->sample_id_all_missing = true;
235 236 237 238 239
					if (!opts->sample_time && !opts->raw_samples && !time_needed)
						attr->sample_type &= ~PERF_SAMPLE_TIME;

					goto retry_sample_id;
				}
240
			}
241

242 243 244
			/*
			 * If it's cycles then fall back to hrtimer
			 * based cpu-clock-tick sw counter, which
245 246 247 248
			 * is always available even if no PMU support.
			 *
			 * PPC returns ENXIO until 2.6.37 (behavior changed
			 * with commit b0a873e).
249
			 */
250 251
			if ((err == ENOENT || err == ENXIO)
					&& attr->type == PERF_TYPE_HARDWARE
252 253 254
					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {

				if (verbose)
255 256
					ui__warning("The cycles event is not supported, "
						    "trying to fall back to cpu-clock-ticks\n");
257 258 259 260
				attr->type = PERF_TYPE_SOFTWARE;
				attr->config = PERF_COUNT_SW_CPU_CLOCK;
				goto try_again;
			}
261 262 263 264 265 266 267

			if (err == ENOENT) {
				ui__warning("The %s event is not supported.\n",
					    event_name(pos));
				exit(EXIT_FAILURE);
			}

268
			printf("\n");
269
			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
270
			      err, strerror(err));
271 272

#if defined(__i386__) || defined(__x86_64__)
273 274 275 276 277
			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
				die("No hardware sampling interrupt available."
				    " No APIC? If so then you can boot the kernel"
				    " with the \"lapic\" boot parameter to"
				    " force-enable it.\n");
278 279
#endif

280
			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
L
Li Zefan 已提交
281 282
		}
	}
283

284 285 286 287 288 289
	if (perf_evlist__set_filters(evlist)) {
		error("failed to set filter with %d (%s)\n", errno,
			strerror(errno));
		exit(-1);
	}

290 291 292 293 294 295 296
	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
		if (errno == EPERM)
			die("Permission error mapping pages.\n"
			    "Consider increasing "
			    "/proc/sys/kernel/perf_event_mlock_kb,\n"
			    "or try again with a smaller value of -m/--mmap_pages.\n"
			    "(current value: %d)\n", opts->mmap_pages);
297 298 299
		else if (!is_power_of_2(opts->mmap_pages))
			die("--mmap_pages/-m value must be a power of two.");

300
		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
301
	}
302

303
	if (rec->file_new)
304 305 306 307 308 309 310 311 312
		session->evlist = evlist;
	else {
		if (!perf_evlist__equal(session->evlist, evlist)) {
			fprintf(stderr, "incompatible append\n");
			exit(-1);
		}
 	}

	perf_session__update_sample_type(session);
313 314
}

315
static int process_buildids(struct perf_record *rec)
316
{
317
	u64 size = lseek(rec->output, 0, SEEK_CUR);
318

319 320 321
	if (size == 0)
		return 0;

322 323 324
	rec->session->fd = rec->output;
	return __perf_session__process_events(rec->session, rec->post_processing_offset,
					      size - rec->post_processing_offset,
325 326 327
					      size, &build_id__mark_dso_hit_ops);
}

328
static void perf_record__exit(int status __used, void *arg)
329
{
330 331 332 333 334 335 336 337 338 339 340
	struct perf_record *rec = arg;

	if (!rec->opts.pipe_output) {
		rec->session->header.data_size += rec->bytes_written;

		if (!rec->no_buildid)
			process_buildids(rec);
		perf_session__write_header(rec->session, rec->evlist,
					   rec->output, true);
		perf_session__delete(rec->session);
		perf_evlist__delete(rec->evlist);
341
		symbol__exit();
342
	}
343 344
}

345
static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
346 347
{
	int err;
348
	struct perf_tool *tool = data;
349

350
	if (machine__is_host(machine))
351 352 353 354 355 356 357 358 359 360
		return;

	/*
	 *As for guest kernel when processing subcommand record&report,
	 *we arrange module mmap prior to guest kernel mmap and trigger
	 *a preload dso because default guest module symbols are loaded
	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
	 *method is used to avoid symbol missing when the first addr is
	 *in module instead of in guest kernel.
	 */
361
	err = perf_event__synthesize_modules(tool, process_synthesized_event,
362
					     machine);
363 364
	if (err < 0)
		pr_err("Couldn't record guest kernel [%d]'s reference"
365
		       " relocation symbol.\n", machine->pid);
366 367 368 369 370

	/*
	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
	 * have no _text sometimes.
	 */
371
	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
372
						 machine, "_text");
373
	if (err < 0)
374
		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
375
							 machine, "_stext");
376 377
	if (err < 0)
		pr_err("Couldn't record guest kernel [%d]'s reference"
378
		       " relocation symbol.\n", machine->pid);
379 380
}

381 382 383 384 385
static struct perf_event_header finished_round_event = {
	.size = sizeof(struct perf_event_header),
	.type = PERF_RECORD_FINISHED_ROUND,
};

386
static void perf_record__mmap_read_all(struct perf_record *rec)
387
{
388
	int i;
389

390 391 392
	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
		if (rec->evlist->mmap[i].base)
			perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
393 394
	}

395 396
	if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
		write_output(rec, &finished_round_event, sizeof(finished_round_event));
397 398
}

399
static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
400
{
I
Ingo Molnar 已提交
401 402
	struct stat st;
	int flags;
403
	int err, output, feat;
404
	unsigned long waking = 0;
405
	const bool forks = argc > 0;
406
	struct machine *machine;
407
	struct perf_tool *tool = &rec->tool;
408 409 410 411
	struct perf_record_opts *opts = &rec->opts;
	struct perf_evlist *evsel_list = rec->evlist;
	const char *output_name = rec->output_name;
	struct perf_session *session;
412

413
	rec->progname = argv[0];
414

415
	rec->page_size = sysconf(_SC_PAGE_SIZE);
416

417
	on_exit(perf_record__sig_exit, rec);
418 419
	signal(SIGCHLD, sig_handler);
	signal(SIGINT, sig_handler);
420
	signal(SIGUSR1, sig_handler);
421

422 423
	if (!output_name) {
		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
424
			opts->pipe_output = true;
425
		else
426
			rec->output_name = output_name = "perf.data";
427 428 429
	}
	if (output_name) {
		if (!strcmp(output_name, "-"))
430
			opts->pipe_output = true;
431
		else if (!stat(output_name, &st) && st.st_size) {
432
			if (rec->write_mode == WRITE_FORCE) {
433 434 435 436 437 438
				char oldname[PATH_MAX];
				snprintf(oldname, sizeof(oldname), "%s.old",
					 output_name);
				unlink(oldname);
				rename(output_name, oldname);
			}
439 440
		} else if (rec->write_mode == WRITE_APPEND) {
			rec->write_mode = WRITE_FORCE;
441
		}
442 443
	}

444
	flags = O_CREAT|O_RDWR;
445 446
	if (rec->write_mode == WRITE_APPEND)
		rec->file_new = 0;
I
Ingo Molnar 已提交
447 448 449
	else
		flags |= O_TRUNC;

450
	if (opts->pipe_output)
451 452 453
		output = STDOUT_FILENO;
	else
		output = open(output_name, flags, S_IRUSR | S_IWUSR);
454 455 456 457 458
	if (output < 0) {
		perror("failed to create output file");
		exit(-1);
	}

459 460
	rec->output = output;

461
	session = perf_session__new(output_name, O_WRONLY,
462
				    rec->write_mode == WRITE_FORCE, false, NULL);
463
	if (session == NULL) {
464 465 466 467
		pr_err("Not enough memory for reading perf file header\n");
		return -1;
	}

468 469
	rec->session = session;

470 471 472 473 474 475 476 477
	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
		perf_header__set_feat(&session->header, feat);

	if (rec->no_buildid)
		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);

	if (!have_tracepoints(&evsel_list->entries))
		perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
478

479 480 481
	if (!rec->opts.branch_stack)
		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);

482
	if (!rec->file_new) {
483
		err = perf_session__read_header(session, output);
484
		if (err < 0)
485
			goto out_delete_session;
486 487
	}

488
	if (forks) {
489
		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
490 491 492
		if (err < 0) {
			pr_err("Couldn't run the workload!\n");
			goto out_delete_session;
493 494 495
		}
	}

496
	perf_record__open(rec);
497

498
	/*
499
	 * perf_session__delete(session) will be called at perf_record__exit()
500
	 */
501
	on_exit(perf_record__exit, rec);
502

503
	if (opts->pipe_output) {
504 505 506
		err = perf_header__write_pipe(output);
		if (err < 0)
			return err;
507
	} else if (rec->file_new) {
508 509
		err = perf_session__write_header(session, evsel_list,
						 output, false);
510 511
		if (err < 0)
			return err;
512 513
	}

514
	if (!rec->no_buildid
515
	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
516
		pr_err("Couldn't generate buildids. "
517 518 519 520
		       "Use --no-buildid to profile anyway.\n");
		return -1;
	}

521
	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
522

523 524 525 526 527 528
	machine = perf_session__find_host_machine(session);
	if (!machine) {
		pr_err("Couldn't find native kernel information.\n");
		return -1;
	}

529
	if (opts->pipe_output) {
530
		err = perf_event__synthesize_attrs(tool, session,
531
						   process_synthesized_event);
532 533 534 535
		if (err < 0) {
			pr_err("Couldn't synthesize attrs.\n");
			return err;
		}
536

537
		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
538
							 machine);
539 540 541 542
		if (err < 0) {
			pr_err("Couldn't synthesize event_types.\n");
			return err;
		}
543

544
		if (have_tracepoints(&evsel_list->entries)) {
545 546 547 548 549 550 551 552
			/*
			 * FIXME err <= 0 here actually means that
			 * there were no tracepoints so its not really
			 * an error, just that we don't need to
			 * synthesize anything.  We really have to
			 * return this more properly and also
			 * propagate errors that now are calling die()
			 */
553
			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
554
								  process_synthesized_event);
555 556 557 558
			if (err <= 0) {
				pr_err("Couldn't record tracing data.\n");
				return err;
			}
559
			advance_output(rec, err);
560
		}
561 562
	}

563
	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
564
						 machine, "_text");
565
	if (err < 0)
566
		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
567
							 machine, "_stext");
568 569 570 571
	if (err < 0)
		pr_err("Couldn't record kernel reference relocation symbol\n"
		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
		       "Check /proc/kallsyms permission or run as root.\n");
572

573
	err = perf_event__synthesize_modules(tool, process_synthesized_event,
574
					     machine);
575 576 577 578 579
	if (err < 0)
		pr_err("Couldn't record kernel module information.\n"
		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
		       "Check /proc/modules permission or run as root.\n");

580
	if (perf_guest)
581
		perf_session__process_machines(session, tool,
582
					       perf_event__synthesize_guest_os);
583

584
	if (!opts->target.system_wide)
585
		perf_event__synthesize_thread_map(tool, evsel_list->threads,
586
						  process_synthesized_event,
587
						  machine);
588
	else
589
		perf_event__synthesize_threads(tool, process_synthesized_event,
590
					       machine);
591

592
	if (rec->realtime_prio) {
593 594
		struct sched_param param;

595
		param.sched_priority = rec->realtime_prio;
596
		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
597
			pr_err("Could not set realtime priority.\n");
598 599 600 601
			exit(-1);
		}
	}

602 603
	perf_evlist__enable(evsel_list);

604 605 606
	/*
	 * Let the child rip
	 */
607
	if (forks)
608
		perf_evlist__start_workload(evsel_list);
609

610
	for (;;) {
611
		int hits = rec->samples;
612

613
		perf_record__mmap_read_all(rec);
614

615
		if (hits == rec->samples) {
616 617
			if (done)
				break;
618
			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
619 620 621
			waking++;
		}

622 623
		if (done)
			perf_evlist__disable(evsel_list);
624 625
	}

626
	if (quiet || signr == SIGUSR1)
627 628
		return 0;

629 630
	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);

631 632 633 634
	/*
	 * Approximate RIP event size: 24 bytes.
	 */
	fprintf(stderr,
635
		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
636
		(double)rec->bytes_written / 1024.0 / 1024.0,
637
		output_name,
638
		rec->bytes_written / 24);
639

640
	return 0;
641 642 643 644

out_delete_session:
	perf_session__delete(session);
	return err;
645
}
646

647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
#define BRANCH_OPT(n, m) \
	{ .name = n, .mode = (m) }

#define BRANCH_END { .name = NULL }

struct branch_mode {
	const char *name;
	int mode;
};

static const struct branch_mode branch_modes[] = {
	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
	BRANCH_END
};

static int
669
parse_branch_stack(const struct option *opt, const char *str, int unset)
670 671 672 673 674 675 676 677
{
#define ONLY_PLM \
	(PERF_SAMPLE_BRANCH_USER	|\
	 PERF_SAMPLE_BRANCH_KERNEL	|\
	 PERF_SAMPLE_BRANCH_HV)

	uint64_t *mode = (uint64_t *)opt->value;
	const struct branch_mode *br;
678
	char *s, *os = NULL, *p;
679 680
	int ret = -1;

681 682
	if (unset)
		return 0;
683

684 685 686 687
	/*
	 * cannot set it twice, -b + --branch-filter for instance
	 */
	if (*mode)
688 689
		return -1;

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
	/* str may be NULL in case no arg is passed to -b */
	if (str) {
		/* because str is read-only */
		s = os = strdup(str);
		if (!s)
			return -1;

		for (;;) {
			p = strchr(s, ',');
			if (p)
				*p = '\0';

			for (br = branch_modes; br->name; br++) {
				if (!strcasecmp(s, br->name))
					break;
			}
			if (!br->name) {
				ui__warning("unknown branch filter %s,"
					    " check man page\n", s);
				goto error;
			}
711

712
			*mode |= br->mode;
713

714 715
			if (!p)
				break;
716

717 718
			s = p + 1;
		}
719 720 721
	}
	ret = 0;

722
	/* default to any branch */
723
	if ((*mode & ~ONLY_PLM) == 0) {
724
		*mode = PERF_SAMPLE_BRANCH_ANY;
725 726 727 728 729 730
	}
error:
	free(os);
	return ret;
}

731
static const char * const record_usage[] = {
732 733
	"perf record [<options>] [<command>]",
	"perf record [<options>] -- <command> [<options>]",
734 735 736
	NULL
};

737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
/*
 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
 * because we need to have access to it in perf_record__exit, that is called
 * after cmd_record() exits, but since record_options need to be accessible to
 * builtin-script, leave it here.
 *
 * At least we don't ouch it in all the other functions here directly.
 *
 * Just say no to tons of global variables, sigh.
 */
static struct perf_record record = {
	.opts = {
		.mmap_pages	     = UINT_MAX,
		.user_freq	     = UINT_MAX,
		.user_interval	     = ULLONG_MAX,
		.freq		     = 1000,
	},
	.write_mode = WRITE_FORCE,
	.file_new   = true,
};
757

758 759 760 761 762 763 764
/*
 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
 * with it and switch to use the library functions in perf_evlist that came
 * from builtin-record.c, i.e. use perf_record_opts,
 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
 * using pipes, etc.
 */
765
const struct option record_options[] = {
766
	OPT_CALLBACK('e', "event", &record.evlist, "event",
767
		     "event selector. use 'perf list' to list available events",
768
		     parse_events_option),
769
	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
L
Li Zefan 已提交
770
		     "event filter", parse_filter),
771
	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
772
		    "record events on existing process id"),
773
	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
774
		    "record events on existing thread id"),
775
	OPT_INTEGER('r', "realtime", &record.realtime_prio,
776
		    "collect data with this RT SCHED_FIFO priority"),
777
	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
778
		    "collect data without buffering"),
779
	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
780
		    "collect raw sample records from all opened counters"),
781
	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
782
			    "system-wide collection from all CPUs"),
783
	OPT_BOOLEAN('A', "append", &record.append_file,
I
Ingo Molnar 已提交
784
			    "append to the output file to do incremental profiling"),
785
	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
786
		    "list of cpus to monitor"),
787
	OPT_BOOLEAN('f', "force", &record.force,
788
			"overwrite existing data file (deprecated)"),
789 790
	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
	OPT_STRING('o', "output", &record.output_name, "file",
I
Ingo Molnar 已提交
791
		    "output file name"),
792
	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
793
		    "child tasks do not inherit counters"),
794 795
	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
796
		     "number of mmap data pages"),
797
	OPT_BOOLEAN(0, "group", &record.opts.group,
798
		    "put the counters into a counter group"),
799
	OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
800
		    "do call-graph (stack chain/backtrace) recording"),
801
	OPT_INCR('v', "verbose", &verbose,
802
		    "be more verbose (show counter open errors, etc)"),
803
	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
804
	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
805
		    "per thread counts"),
806
	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
807
		    "Sample addresses"),
808
	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
809
	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
810
	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
811
		    "don't sample"),
812
	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
813
		    "do not update the buildid cache"),
814
	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
815
		    "do not collect buildids in perf.data"),
816
	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
S
Stephane Eranian 已提交
817 818
		     "monitor event in cgroup name only",
		     parse_cgroups),
819 820
	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
		   "user to profile"),
821 822 823 824 825 826 827

	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
		     "branch any", "sample any taken branches",
		     parse_branch_stack),

	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
		     "branch filter mask", "branch stack filter modes",
828
		     parse_branch_stack),
829 830 831
	OPT_END()
};

832
int cmd_record(int argc, const char **argv, const char *prefix __used)
833
{
834 835
	int err = -ENOMEM;
	struct perf_evsel *pos;
836 837
	struct perf_evlist *evsel_list;
	struct perf_record *rec = &record;
838
	char errbuf[BUFSIZ];
839

840 841
	perf_header__set_cmdline(argc, argv);

842
	evsel_list = perf_evlist__new(NULL, NULL);
843 844 845
	if (evsel_list == NULL)
		return -ENOMEM;

846 847
	rec->evlist = evsel_list;

848
	argc = parse_options(argc, argv, record_options, record_usage,
849
			    PARSE_OPT_STOP_AT_NON_OPTION);
850
	if (!argc && perf_target__none(&rec->opts.target))
851
		usage_with_options(record_usage, record_options);
852

853
	if (rec->force && rec->append_file) {
854 855
		fprintf(stderr, "Can't overwrite and append at the same time."
				" You need to choose between -f and -A");
856
		usage_with_options(record_usage, record_options);
857 858
	} else if (rec->append_file) {
		rec->write_mode = WRITE_APPEND;
859
	} else {
860
		rec->write_mode = WRITE_FORCE;
861 862
	}

863
	if (nr_cgroups && !rec->opts.target.system_wide) {
S
Stephane Eranian 已提交
864 865 866 867 868
		fprintf(stderr, "cgroup monitoring only available in"
			" system-wide mode\n");
		usage_with_options(record_usage, record_options);
	}

869
	symbol__init();
870

871
	if (symbol_conf.kptr_restrict)
872 873 874 875 876 877 878 879
		pr_warning(
"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
"check /proc/sys/kernel/kptr_restrict.\n\n"
"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
"file is not found in the buildid cache or in the vmlinux path.\n\n"
"Samples in kernel modules won't be resolved at all.\n\n"
"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
"even with a suitable vmlinux or kallsyms file.\n\n");
880

881
	if (rec->no_buildid_cache || rec->no_buildid)
882
		disable_buildid_cache();
883

884 885
	if (evsel_list->nr_entries == 0 &&
	    perf_evlist__add_default(evsel_list) < 0) {
886 887
		pr_err("Not enough memory for event selector list\n");
		goto out_symbol_exit;
888
	}
889

890 891 892 893 894 895 896 897 898
	err = perf_target__validate(&rec->opts.target);
	if (err) {
		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
		ui__warning("%s", errbuf);
	}

	err = perf_target__parse_uid(&rec->opts.target);
	if (err) {
		int saved_errno = errno;
899

900 901 902 903
		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
		ui__warning("%s", errbuf);

		err = -saved_errno;
904
		goto out_free_fd;
905
	}
906

907
	err = -ENOMEM;
908
	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
909
		usage_with_options(record_usage, record_options);
910

911
	list_for_each_entry(pos, &evsel_list->entries, node) {
912 913
		if (perf_header__push_event(pos->attr.config, event_name(pos)))
			goto out_free_fd;
914
	}
915

916 917 918 919
	if (rec->opts.user_interval != ULLONG_MAX)
		rec->opts.default_interval = rec->opts.user_interval;
	if (rec->opts.user_freq != UINT_MAX)
		rec->opts.freq = rec->opts.user_freq;
920

921 922 923
	/*
	 * User specified count overrides default frequency.
	 */
924 925 926 927
	if (rec->opts.default_interval)
		rec->opts.freq = 0;
	else if (rec->opts.freq) {
		rec->opts.default_interval = rec->opts.freq;
928 929
	} else {
		fprintf(stderr, "frequency and count are zero, aborting\n");
930
		err = -EINVAL;
931
		goto out_free_fd;
932 933
	}

934
	err = __cmd_record(&record, argc, argv);
935
out_free_fd:
936
	perf_evlist__delete_maps(evsel_list);
937 938
out_symbol_exit:
	symbol__exit();
939
	return err;
940
}