builtin-record.c 25.2 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
				attr->type = PERF_TYPE_SOFTWARE;
				attr->config = PERF_COUNT_SW_CPU_CLOCK;
259 260 261 262
				if (pos->name) {
					free(pos->name);
					pos->name = NULL;
				}
263 264
				goto try_again;
			}
265 266

			if (err == ENOENT) {
267
				ui__error("The %s event is not supported.\n",
268
					  perf_evsel__name(pos));
269 270 271
				exit(EXIT_FAILURE);
			}

272
			printf("\n");
273
			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
274
			      err, strerror(err));
275 276

#if defined(__i386__) || defined(__x86_64__)
277 278 279 280 281
			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");
282 283
#endif

284
			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
L
Li Zefan 已提交
285 286
		}
	}
287

288 289 290 291 292 293
	if (perf_evlist__set_filters(evlist)) {
		error("failed to set filter with %d (%s)\n", errno,
			strerror(errno));
		exit(-1);
	}

294 295 296 297 298 299 300
	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);
301 302 303
		else if (!is_power_of_2(opts->mmap_pages))
			die("--mmap_pages/-m value must be a power of two.");

304
		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
305
	}
306

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

316
	perf_session__set_id_hdr_size(session);
317 318
}

319
static int process_buildids(struct perf_record *rec)
320
{
321
	u64 size = lseek(rec->output, 0, SEEK_CUR);
322

323 324 325
	if (size == 0)
		return 0;

326 327 328
	rec->session->fd = rec->output;
	return __perf_session__process_events(rec->session, rec->post_processing_offset,
					      size - rec->post_processing_offset,
329 330 331
					      size, &build_id__mark_dso_hit_ops);
}

332
static void perf_record__exit(int status __used, void *arg)
333
{
334 335 336 337 338 339 340 341 342 343 344
	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);
345
		symbol__exit();
346
	}
347 348
}

349
static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
350 351
{
	int err;
352
	struct perf_tool *tool = data;
353

354
	if (machine__is_host(machine))
355 356 357 358 359 360 361 362 363 364
		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.
	 */
365
	err = perf_event__synthesize_modules(tool, process_synthesized_event,
366
					     machine);
367 368
	if (err < 0)
		pr_err("Couldn't record guest kernel [%d]'s reference"
369
		       " relocation symbol.\n", machine->pid);
370 371 372 373 374

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

385 386 387 388 389
static struct perf_event_header finished_round_event = {
	.size = sizeof(struct perf_event_header),
	.type = PERF_RECORD_FINISHED_ROUND,
};

390
static void perf_record__mmap_read_all(struct perf_record *rec)
391
{
392
	int i;
393

394 395 396
	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
		if (rec->evlist->mmap[i].base)
			perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
397 398
	}

399
	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
400
		write_output(rec, &finished_round_event, sizeof(finished_round_event));
401 402
}

403
static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
404
{
I
Ingo Molnar 已提交
405 406
	struct stat st;
	int flags;
407
	int err, output, feat;
408
	unsigned long waking = 0;
409
	const bool forks = argc > 0;
410
	struct machine *machine;
411
	struct perf_tool *tool = &rec->tool;
412 413 414 415
	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;
416

417
	rec->progname = argv[0];
418

419
	rec->page_size = sysconf(_SC_PAGE_SIZE);
420

421
	on_exit(perf_record__sig_exit, rec);
422 423
	signal(SIGCHLD, sig_handler);
	signal(SIGINT, sig_handler);
424
	signal(SIGUSR1, sig_handler);
425

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

448
	flags = O_CREAT|O_RDWR;
449 450
	if (rec->write_mode == WRITE_APPEND)
		rec->file_new = 0;
I
Ingo Molnar 已提交
451 452 453
	else
		flags |= O_TRUNC;

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

463 464
	rec->output = output;

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

472 473
	rec->session = session;

474 475 476 477 478 479 480
	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))
481
		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
482

483 484 485
	if (!rec->opts.branch_stack)
		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);

486
	if (!rec->file_new) {
487
		err = perf_session__read_header(session, output);
488
		if (err < 0)
489
			goto out_delete_session;
490 491
	}

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

500
	perf_record__open(rec);
501

502
	/*
503
	 * perf_session__delete(session) will be called at perf_record__exit()
504
	 */
505
	on_exit(perf_record__exit, rec);
506

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

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

525
	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
526

527 528 529 530 531 532
	machine = perf_session__find_host_machine(session);
	if (!machine) {
		pr_err("Couldn't find native kernel information.\n");
		return -1;
	}

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

541
		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
542
							 machine);
543 544 545 546
		if (err < 0) {
			pr_err("Couldn't synthesize event_types.\n");
			return err;
		}
547

548
		if (have_tracepoints(&evsel_list->entries)) {
549 550 551 552 553 554 555 556
			/*
			 * 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()
			 */
557
			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
558
								  process_synthesized_event);
559 560 561 562
			if (err <= 0) {
				pr_err("Couldn't record tracing data.\n");
				return err;
			}
563
			advance_output(rec, err);
564
		}
565 566
	}

567
	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
568
						 machine, "_text");
569
	if (err < 0)
570
		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
571
							 machine, "_stext");
572 573 574 575
	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");
576

577
	err = perf_event__synthesize_modules(tool, process_synthesized_event,
578
					     machine);
579 580 581 582 583
	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");

584
	if (perf_guest)
585
		perf_session__process_machines(session, tool,
586
					       perf_event__synthesize_guest_os);
587

588
	if (!opts->target.system_wide)
589
		perf_event__synthesize_thread_map(tool, evsel_list->threads,
590
						  process_synthesized_event,
591
						  machine);
592
	else
593
		perf_event__synthesize_threads(tool, process_synthesized_event,
594
					       machine);
595

596
	if (rec->realtime_prio) {
597 598
		struct sched_param param;

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

606 607
	perf_evlist__enable(evsel_list);

608 609 610
	/*
	 * Let the child rip
	 */
611
	if (forks)
612
		perf_evlist__start_workload(evsel_list);
613

614
	for (;;) {
615
		int hits = rec->samples;
616

617
		perf_record__mmap_read_all(rec);
618

619
		if (hits == rec->samples) {
620 621
			if (done)
				break;
622
			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
623 624 625
			waking++;
		}

626 627
		if (done)
			perf_evlist__disable(evsel_list);
628 629
	}

630
	if (quiet || signr == SIGUSR1)
631 632
		return 0;

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

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

644
	return 0;
645 646 647 648

out_delete_session:
	perf_session__delete(session);
	return err;
649
}
650

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
#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
673
parse_branch_stack(const struct option *opt, const char *str, int unset)
674 675 676 677 678 679 680 681
{
#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;
682
	char *s, *os = NULL, *p;
683 684
	int ret = -1;

685 686
	if (unset)
		return 0;
687

688 689 690 691
	/*
	 * cannot set it twice, -b + --branch-filter for instance
	 */
	if (*mode)
692 693
		return -1;

694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
	/* 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;
			}
715

716
			*mode |= br->mode;
717

718 719
			if (!p)
				break;
720

721 722
			s = p + 1;
		}
723 724 725
	}
	ret = 0;

726
	/* default to any branch */
727
	if ((*mode & ~ONLY_PLM) == 0) {
728
		*mode = PERF_SAMPLE_BRANCH_ANY;
729 730 731 732 733 734
	}
error:
	free(os);
	return ret;
}

735
static const char * const record_usage[] = {
736 737
	"perf record [<options>] [<command>]",
	"perf record [<options>] -- <command> [<options>]",
738 739 740
	NULL
};

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
/*
 * 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,
756
		.freq		     = 4000,
N
Namhyung Kim 已提交
757 758 759
		.target		     = {
			.uses_mmap   = true,
		},
760 761 762 763
	},
	.write_mode = WRITE_FORCE,
	.file_new   = true,
};
764

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

	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",
835
		     parse_branch_stack),
836 837 838
	OPT_END()
};

839
int cmd_record(int argc, const char **argv, const char *prefix __used)
840
{
841 842
	int err = -ENOMEM;
	struct perf_evsel *pos;
843 844
	struct perf_evlist *evsel_list;
	struct perf_record *rec = &record;
845
	char errbuf[BUFSIZ];
846

847
	evsel_list = perf_evlist__new(NULL, NULL);
848 849 850
	if (evsel_list == NULL)
		return -ENOMEM;

851 852
	rec->evlist = evsel_list;

853
	argc = parse_options(argc, argv, record_options, record_usage,
854
			    PARSE_OPT_STOP_AT_NON_OPTION);
855
	if (!argc && perf_target__none(&rec->opts.target))
856
		usage_with_options(record_usage, record_options);
857

858
	if (rec->force && rec->append_file) {
859 860
		ui__error("Can't overwrite and append at the same time."
			  " You need to choose between -f and -A");
861
		usage_with_options(record_usage, record_options);
862 863
	} else if (rec->append_file) {
		rec->write_mode = WRITE_APPEND;
864
	} else {
865
		rec->write_mode = WRITE_FORCE;
866 867
	}

868
	if (nr_cgroups && !rec->opts.target.system_wide) {
869 870
		ui__error("cgroup monitoring only available in"
			  " system-wide mode\n");
S
Stephane Eranian 已提交
871 872 873
		usage_with_options(record_usage, record_options);
	}

874
	symbol__init();
875

876
	if (symbol_conf.kptr_restrict)
877 878 879 880 881 882 883 884
		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");
885

886
	if (rec->no_buildid_cache || rec->no_buildid)
887
		disable_buildid_cache();
888

889 890
	if (evsel_list->nr_entries == 0 &&
	    perf_evlist__add_default(evsel_list) < 0) {
891 892
		pr_err("Not enough memory for event selector list\n");
		goto out_symbol_exit;
893
	}
894

895 896 897 898 899 900 901 902 903
	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;
904

905
		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
906
		ui__error("%s", errbuf);
907 908

		err = -saved_errno;
909
		goto out_free_fd;
910
	}
911

912
	err = -ENOMEM;
913
	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
914
		usage_with_options(record_usage, record_options);
915

916
	list_for_each_entry(pos, &evsel_list->entries, node) {
917
		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
918
			goto out_free_fd;
919
	}
920

921 922 923 924
	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;
925

926 927 928
	/*
	 * User specified count overrides default frequency.
	 */
929 930 931 932
	if (rec->opts.default_interval)
		rec->opts.freq = 0;
	else if (rec->opts.freq) {
		rec->opts.default_interval = rec->opts.freq;
933
	} else {
934
		ui__error("frequency and count are zero, aborting\n");
935
		err = -EINVAL;
936
		goto out_free_fd;
937 938
	}

939
	err = __cmd_record(&record, argc, argv);
940
out_free_fd:
941
	perf_evlist__delete_maps(evsel_list);
942 943
out_symbol_exit:
	symbol__exit();
944
	return err;
945
}