builtin-record.c 21.9 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/symbol.h"
26
#include "util/cpumap.h"
27
#include "util/thread_map.h"
28

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

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

38 39 40 41 42 43 44 45
static struct perf_record_opts record_opts = {
	.target_pid	     = -1,
	.target_tid	     = -1,
	.user_freq	     = UINT_MAX,
	.user_interval	     = ULLONG_MAX,
	.freq		     = 1000,
	.sample_id_all_avail = true,
};
46

47
static unsigned int		page_size;
48
static unsigned int		mmap_pages			= UINT_MAX;
49
static int			output;
50
static int			pipe_output			=      0;
51
static const char		*output_name			= NULL;
52
static bool			group				=  false;
53
static int			realtime_prio			=      0;
54
static pid_t			child_pid			=     -1;
55
static enum write_mode_t	write_mode			= WRITE_FORCE;
56
static bool			no_buildid			=  false;
57
static bool			no_buildid_cache		=  false;
58
static struct perf_evlist	*evsel_list;
59 60 61

static long			samples				=      0;
static u64			bytes_written			=      0;
62

63
static int			file_new			=      1;
64
static off_t			post_processing_offset;
65

66
static struct perf_session	*session;
67
static const char               *progname;
68

69 70 71 72 73
static void advance_output(size_t size)
{
	bytes_written += size;
}

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
static void write_output(void *buf, size_t size)
{
	while (size) {
		int ret = write(output, buf, size);

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

		size -= ret;
		buf += ret;

		bytes_written += ret;
	}
}

89
static int process_synthesized_event(union perf_event *event,
90
				     struct perf_sample *sample __used,
91
				     struct perf_session *self __used)
92
{
93
	write_output(event, event->header.size);
94 95 96
	return 0;
}

97
static void mmap_read(struct perf_mmap *md)
98
{
99
	unsigned int head = perf_mmap__read_head(md);
100 101 102 103 104
	unsigned int old = md->prev;
	unsigned char *data = md->base + page_size;
	unsigned long size;
	void *buf;

105 106 107 108
	if (old == head)
		return;

	samples++;
109 110 111 112 113 114 115

	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;
116

117
		write_output(buf, size);
118 119 120 121 122
	}

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

124
	write_output(buf, size);
125 126

	md->prev = old;
127
	perf_mmap__write_tail(md, old);
128 129 130
}

static volatile int done = 0;
131
static volatile int signr = -1;
132
static volatile int child_finished = 0;
133

134
static void sig_handler(int sig)
135
{
136 137 138
	if (sig == SIGCHLD)
		child_finished = 1;

139
	done = 1;
140 141 142 143 144
	signr = sig;
}

static void sig_atexit(void)
{
145 146 147 148 149 150 151 152 153 154
	int status;

	if (child_pid > 0) {
		if (!child_finished)
			kill(child_pid, SIGTERM);

		wait(&status);
		if (WIFSIGNALED(status))
			psignal(WTERMSIG(status), progname);
	}
155

156
	if (signr == -1 || signr == SIGUSR1)
157 158 159 160
		return;

	signal(signr, SIG_DFL);
	kill(getpid(), signr);
161 162
}

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
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;
}

182 183
static void open_counters(struct perf_evlist *evlist)
{
184
	struct perf_evsel *pos, *first;
185

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

188 189
	perf_evlist__config_attrs(evlist, &record_opts);

190 191
	list_for_each_entry(pos, &evlist->entries, node) {
		struct perf_event_attr *attr = &pos->attr;
192
		struct xyarray *group_fd = NULL;
193 194 195 196 197 198 199 200 201 202 203 204 205
		/*
		 * 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;
206

207 208
		if (group && pos != first)
			group_fd = first->fd;
209
retry_sample_id:
210
		attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
211
try_again:
212 213
		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
				     group_fd) < 0) {
214 215
			int err = errno;

216
			if (err == EPERM || err == EACCES) {
217
				ui__error_paranoid();
218
				exit(EXIT_FAILURE);
219
			} else if (err ==  ENODEV && record_opts.cpu_list) {
220 221
				die("No such device - did you specify"
					" an out-of-range profile CPU?\n");
222
			} else if (err == EINVAL && record_opts.sample_id_all_avail) {
223 224 225
				/*
				 * Old kernel, no attr->sample_id_type_all field
				 */
226 227
				record_opts.sample_id_all_avail = false;
				if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
228 229
					attr->sample_type &= ~PERF_SAMPLE_TIME;

230
				goto retry_sample_id;
231
			}
232

233 234 235 236 237 238 239 240 241
			/*
			 * If it's cycles then fall back to hrtimer
			 * based cpu-clock-tick sw counter, which
			 * is always available even if no PMU support:
			 */
			if (attr->type == PERF_TYPE_HARDWARE
					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {

				if (verbose)
242 243
					ui__warning("The cycles event is not supported, "
						    "trying to fall back to cpu-clock-ticks\n");
244 245 246 247
				attr->type = PERF_TYPE_SOFTWARE;
				attr->config = PERF_COUNT_SW_CPU_CLOCK;
				goto try_again;
			}
248 249 250 251 252 253 254

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

255
			printf("\n");
256
			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
257
			      err, strerror(err));
258 259

#if defined(__i386__) || defined(__x86_64__)
260 261 262 263 264
			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");
265 266
#endif

267
			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
L
Li Zefan 已提交
268 269
		}
	}
270

271 272 273 274 275 276
	if (perf_evlist__set_filters(evlist)) {
		error("failed to set filter with %d (%s)\n", errno,
			strerror(errno));
		exit(-1);
	}

277
	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
278 279
		die("failed to mmap with %d (%s)\n", errno, strerror(errno));

280 281 282 283 284 285 286 287 288 289
	if (file_new)
		session->evlist = evlist;
	else {
		if (!perf_evlist__equal(session->evlist, evlist)) {
			fprintf(stderr, "incompatible append\n");
			exit(-1);
		}
 	}

	perf_session__update_sample_type(session);
290 291
}

292 293 294 295
static int process_buildids(void)
{
	u64 size = lseek(output, 0, SEEK_CUR);

296 297 298
	if (size == 0)
		return 0;

299 300 301 302 303 304
	session->fd = output;
	return __perf_session__process_events(session, post_processing_offset,
					      size - post_processing_offset,
					      size, &build_id__mark_dso_hit_ops);
}

305 306
static void atexit_header(void)
{
307 308
	if (!pipe_output) {
		session->header.data_size += bytes_written;
309

310 311
		if (!no_buildid)
			process_buildids();
312
		perf_session__write_header(session, evsel_list, output, true);
313
		perf_session__delete(session);
314
		perf_evlist__delete(evsel_list);
315
		symbol__exit();
316
	}
317 318
}

319
static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
320 321
{
	int err;
322
	struct perf_session *psession = data;
323

324
	if (machine__is_host(machine))
325 326 327 328 329 330 331 332 333 334
		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.
	 */
335 336
	err = perf_event__synthesize_modules(process_synthesized_event,
					     psession, machine);
337 338
	if (err < 0)
		pr_err("Couldn't record guest kernel [%d]'s reference"
339
		       " relocation symbol.\n", machine->pid);
340 341 342 343 344

	/*
	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
	 * have no _text sometimes.
	 */
345 346
	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
						 psession, machine, "_text");
347
	if (err < 0)
348 349 350
		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
							 psession, machine,
							 "_stext");
351 352
	if (err < 0)
		pr_err("Couldn't record guest kernel [%d]'s reference"
353
		       " relocation symbol.\n", machine->pid);
354 355
}

356 357 358 359 360 361 362
static struct perf_event_header finished_round_event = {
	.size = sizeof(struct perf_event_header),
	.type = PERF_RECORD_FINISHED_ROUND,
};

static void mmap_read_all(void)
{
363
	int i;
364

365
	for (i = 0; i < evsel_list->nr_mmaps; i++) {
366 367
		if (evsel_list->mmap[i].base)
			mmap_read(&evsel_list->mmap[i]);
368 369 370 371 372 373
	}

	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
		write_output(&finished_round_event, sizeof(finished_round_event));
}

374
static int __cmd_record(int argc, const char **argv)
375
{
I
Ingo Molnar 已提交
376 377
	struct stat st;
	int flags;
378
	int err;
379
	unsigned long waking = 0;
380
	int child_ready_pipe[2], go_pipe[2];
381
	const bool forks = argc > 0;
382
	char buf;
383
	struct machine *machine;
384

385 386
	progname = argv[0];

387 388
	page_size = sysconf(_SC_PAGE_SIZE);

389 390 391
	atexit(sig_atexit);
	signal(SIGCHLD, sig_handler);
	signal(SIGINT, sig_handler);
392
	signal(SIGUSR1, sig_handler);
393

394
	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
395 396 397 398
		perror("failed to create pipes");
		exit(-1);
	}

399 400
	if (!output_name) {
		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
401
			pipe_output = true;
402 403 404 405 406
		else
			output_name = "perf.data";
	}
	if (output_name) {
		if (!strcmp(output_name, "-"))
407
			pipe_output = true;
408 409 410 411 412 413 414 415 416 417
		else if (!stat(output_name, &st) && st.st_size) {
			if (write_mode == WRITE_FORCE) {
				char oldname[PATH_MAX];
				snprintf(oldname, sizeof(oldname), "%s.old",
					 output_name);
				unlink(oldname);
				rename(output_name, oldname);
			}
		} else if (write_mode == WRITE_APPEND) {
			write_mode = WRITE_FORCE;
418
		}
419 420
	}

421
	flags = O_CREAT|O_RDWR;
422
	if (write_mode == WRITE_APPEND)
423
		file_new = 0;
I
Ingo Molnar 已提交
424 425 426
	else
		flags |= O_TRUNC;

427 428 429 430
	if (pipe_output)
		output = STDOUT_FILENO;
	else
		output = open(output_name, flags, S_IRUSR | S_IWUSR);
431 432 433 434 435
	if (output < 0) {
		perror("failed to create output file");
		exit(-1);
	}

436
	session = perf_session__new(output_name, O_WRONLY,
437
				    write_mode == WRITE_FORCE, false, NULL);
438
	if (session == NULL) {
439 440 441 442
		pr_err("Not enough memory for reading perf file header\n");
		return -1;
	}

443 444 445
	if (!no_buildid)
		perf_header__set_feat(&session->header, HEADER_BUILD_ID);

446
	if (!file_new) {
447
		err = perf_session__read_header(session, output);
448
		if (err < 0)
449
			goto out_delete_session;
450 451
	}

452
	if (have_tracepoints(&evsel_list->entries))
453
		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
454

455 456 457 458 459 460 461 462 463 464 465 466 467
	perf_header__set_feat(&session->header, HEADER_HOSTNAME);
	perf_header__set_feat(&session->header, HEADER_OSRELEASE);
	perf_header__set_feat(&session->header, HEADER_ARCH);
	perf_header__set_feat(&session->header, HEADER_CPUDESC);
	perf_header__set_feat(&session->header, HEADER_NRCPUS);
	perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
	perf_header__set_feat(&session->header, HEADER_CMDLINE);
	perf_header__set_feat(&session->header, HEADER_VERSION);
	perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
	perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
	perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
	perf_header__set_feat(&session->header, HEADER_CPUID);

468 469 470 471
	/* 512 kiB: default amount of unprivileged mlocked memory */
	if (mmap_pages == UINT_MAX)
		mmap_pages = (512 * 1024) / page_size;

472
	if (forks) {
473
		child_pid = fork();
474
		if (child_pid < 0) {
475 476 477
			perror("failed to fork");
			exit(-1);
		}
478

479
		if (!child_pid) {
480 481
			if (pipe_output)
				dup2(2, 1);
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
			close(child_ready_pipe[0]);
			close(go_pipe[1]);
			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);

			/*
			 * Do a dummy execvp to get the PLT entry resolved,
			 * so we avoid the resolver overhead on the real
			 * execvp call.
			 */
			execvp("", (char **)argv);

			/*
			 * Tell the parent we're ready to go
			 */
			close(child_ready_pipe[1]);

			/*
			 * Wait until the parent tells us to go.
			 */
			if (read(go_pipe[0], &buf, 1) == -1)
				perror("unable to read pipe");

			execvp(argv[0], (char **)argv);

			perror(argv[0]);
507
			kill(getppid(), SIGUSR1);
508
			exit(-1);
509
		}
510

511
		if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
512
			evsel_list->threads->map[0] = child_pid;
513

514 515 516 517 518 519 520 521 522 523 524 525
		close(child_ready_pipe[1]);
		close(go_pipe[0]);
		/*
		 * wait for child to settle
		 */
		if (read(child_ready_pipe[0], &buf, 1) == -1) {
			perror("unable to read pipe");
			exit(-1);
		}
		close(child_ready_pipe[0]);
	}

526
	open_counters(evsel_list);
527

528 529 530 531 532
	/*
	 * perf_session__delete(session) will be called at atexit_header()
	 */
	atexit(atexit_header);

533 534 535 536 537
	if (pipe_output) {
		err = perf_header__write_pipe(output);
		if (err < 0)
			return err;
	} else if (file_new) {
538 539
		err = perf_session__write_header(session, evsel_list,
						 output, false);
540 541
		if (err < 0)
			return err;
542 543
	}

544 545
	post_processing_offset = lseek(output, 0, SEEK_CUR);

546
	if (pipe_output) {
547 548
		err = perf_session__synthesize_attrs(session,
						     process_synthesized_event);
549 550 551 552
		if (err < 0) {
			pr_err("Couldn't synthesize attrs.\n");
			return err;
		}
553

554 555
		err = perf_event__synthesize_event_types(process_synthesized_event,
							 session);
556 557 558 559
		if (err < 0) {
			pr_err("Couldn't synthesize event_types.\n");
			return err;
		}
560

561
		if (have_tracepoints(&evsel_list->entries)) {
562 563 564 565 566 567 568 569
			/*
			 * 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()
			 */
570 571 572
			err = perf_event__synthesize_tracing_data(output, evsel_list,
								  process_synthesized_event,
								  session);
573 574 575 576
			if (err <= 0) {
				pr_err("Couldn't record tracing data.\n");
				return err;
			}
577
			advance_output(err);
578
		}
579 580
	}

581 582
	machine = perf_session__find_host_machine(session);
	if (!machine) {
583 584 585 586
		pr_err("Couldn't find native kernel information.\n");
		return -1;
	}

587 588
	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
						 session, machine, "_text");
589
	if (err < 0)
590 591
		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
							 session, machine, "_stext");
592 593 594 595
	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");
596

597 598
	err = perf_event__synthesize_modules(process_synthesized_event,
					     session, machine);
599 600 601 602 603
	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");

604
	if (perf_guest)
605 606
		perf_session__process_machines(session,
					       perf_event__synthesize_guest_os);
607

608
	if (!record_opts.system_wide)
609 610 611
		perf_event__synthesize_thread_map(evsel_list->threads,
						  process_synthesized_event,
						  session);
612
	else
613 614
		perf_event__synthesize_threads(process_synthesized_event,
					       session);
615

616 617 618 619 620
	if (realtime_prio) {
		struct sched_param param;

		param.sched_priority = realtime_prio;
		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
621
			pr_err("Could not set realtime priority.\n");
622 623 624 625
			exit(-1);
		}
	}

626 627
	perf_evlist__enable(evsel_list);

628 629 630
	/*
	 * Let the child rip
	 */
631 632
	if (forks)
		close(go_pipe[1]);
633

634
	for (;;) {
635
		int hits = samples;
636

637
		mmap_read_all();
638

639 640 641
		if (hits == samples) {
			if (done)
				break;
642
			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
643 644 645
			waking++;
		}

646 647
		if (done)
			perf_evlist__disable(evsel_list);
648 649
	}

650
	if (quiet || signr == SIGUSR1)
651 652
		return 0;

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

655 656 657 658
	/*
	 * Approximate RIP event size: 24 bytes.
	 */
	fprintf(stderr,
659
		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
660 661 662
		(double)bytes_written / 1024.0 / 1024.0,
		output_name,
		bytes_written / 24);
663

664
	return 0;
665 666 667 668

out_delete_session:
	perf_session__delete(session);
	return err;
669
}
670 671

static const char * const record_usage[] = {
672 673
	"perf record [<options>] [<command>]",
	"perf record [<options>] -- <command> [<options>]",
674 675 676
	NULL
};

677 678
static bool force, append_file;

679
const struct option record_options[] = {
680
	OPT_CALLBACK('e', "event", &evsel_list, "event",
681
		     "event selector. use 'perf list' to list available events",
682
		     parse_events_option),
683
	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
L
Li Zefan 已提交
684
		     "event filter", parse_filter),
685
	OPT_INTEGER('p', "pid", &record_opts.target_pid,
686
		    "record events on existing process id"),
687
	OPT_INTEGER('t', "tid", &record_opts.target_tid,
688
		    "record events on existing thread id"),
689 690
	OPT_INTEGER('r', "realtime", &realtime_prio,
		    "collect data with this RT SCHED_FIFO priority"),
691
	OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay,
692
		    "collect data without buffering"),
693
	OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples,
694
		    "collect raw sample records from all opened counters"),
695
	OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide,
696
			    "system-wide collection from all CPUs"),
I
Ingo Molnar 已提交
697 698
	OPT_BOOLEAN('A', "append", &append_file,
			    "append to the output file to do incremental profiling"),
699
	OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu",
700
		    "list of cpus to monitor"),
701
	OPT_BOOLEAN('f', "force", &force,
702
			"overwrite existing data file (deprecated)"),
703
	OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"),
I
Ingo Molnar 已提交
704 705
	OPT_STRING('o', "output", &output_name, "file",
		    "output file name"),
706
	OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
707
		    "child tasks do not inherit counters"),
708
	OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
709
	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
710 711
	OPT_BOOLEAN(0, "group", &group,
		    "put the counters into a counter group"),
712
	OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
713
		    "do call-graph (stack chain/backtrace) recording"),
714
	OPT_INCR('v', "verbose", &verbose,
715
		    "be more verbose (show counter open errors, etc)"),
716
	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
717
	OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat,
718
		    "per thread counts"),
719
	OPT_BOOLEAN('d', "data", &record_opts.sample_address,
720
		    "Sample addresses"),
721 722
	OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"),
	OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples,
723
		    "don't sample"),
724
	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
725
		    "do not update the buildid cache"),
726 727
	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
		    "do not collect buildids in perf.data"),
S
Stephane Eranian 已提交
728 729 730
	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
		     "monitor event in cgroup name only",
		     parse_cgroups),
731 732 733
	OPT_END()
};

734
int cmd_record(int argc, const char **argv, const char *prefix __used)
735
{
736 737
	int err = -ENOMEM;
	struct perf_evsel *pos;
738

739 740
	perf_header__set_cmdline(argc, argv);

741
	evsel_list = perf_evlist__new(NULL, NULL);
742 743 744
	if (evsel_list == NULL)
		return -ENOMEM;

745
	argc = parse_options(argc, argv, record_options, record_usage,
746
			    PARSE_OPT_STOP_AT_NON_OPTION);
747 748
	if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 &&
		!record_opts.system_wide && !record_opts.cpu_list)
749
		usage_with_options(record_usage, record_options);
750

751 752 753
	if (force && append_file) {
		fprintf(stderr, "Can't overwrite and append at the same time."
				" You need to choose between -f and -A");
754
		usage_with_options(record_usage, record_options);
755 756 757 758 759 760
	} else if (append_file) {
		write_mode = WRITE_APPEND;
	} else {
		write_mode = WRITE_FORCE;
	}

761
	if (nr_cgroups && !record_opts.system_wide) {
S
Stephane Eranian 已提交
762 763 764 765 766
		fprintf(stderr, "cgroup monitoring only available in"
			" system-wide mode\n");
		usage_with_options(record_usage, record_options);
	}

767
	symbol__init();
768

769
	if (symbol_conf.kptr_restrict)
770 771 772 773 774 775 776 777
		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");
778

779
	if (no_buildid_cache || no_buildid)
780
		disable_buildid_cache();
781

782 783
	if (evsel_list->nr_entries == 0 &&
	    perf_evlist__add_default(evsel_list) < 0) {
784 785
		pr_err("Not enough memory for event selector list\n");
		goto out_symbol_exit;
786
	}
787

788 789
	if (record_opts.target_pid != -1)
		record_opts.target_tid = record_opts.target_pid;
790

791 792
	if (perf_evlist__create_maps(evsel_list, record_opts.target_pid,
				     record_opts.target_tid, record_opts.cpu_list) < 0)
793
		usage_with_options(record_usage, record_options);
794

795
	list_for_each_entry(pos, &evsel_list->entries, node) {
796 797
		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
					 evsel_list->threads->nr) < 0)
798
			goto out_free_fd;
799 800
		if (perf_header__push_event(pos->attr.config, event_name(pos)))
			goto out_free_fd;
801
	}
802

803
	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
804
		goto out_free_fd;
805

806 807 808 809
	if (record_opts.user_interval != ULLONG_MAX)
		record_opts.default_interval = record_opts.user_interval;
	if (record_opts.user_freq != UINT_MAX)
		record_opts.freq = record_opts.user_freq;
810

811 812 813
	/*
	 * User specified count overrides default frequency.
	 */
814 815 816 817
	if (record_opts.default_interval)
		record_opts.freq = 0;
	else if (record_opts.freq) {
		record_opts.default_interval = record_opts.freq;
818 819
	} else {
		fprintf(stderr, "frequency and count are zero, aborting\n");
820
		err = -EINVAL;
821
		goto out_free_fd;
822 823
	}

824 825
	err = __cmd_record(argc, argv);
out_free_fd:
826
	perf_evlist__delete_maps(evsel_list);
827 828
out_symbol_exit:
	symbol__exit();
829
	return err;
830
}