1 /*
2 * builtin-record.c
3 *
4 * Builtin record command: Record the profile of a workload
5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report.
7 */
8 #define _FILE_OFFSET_BITS 64
9
10 #include "builtin.h"
11
12 #include "perf.h"
13
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 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34
35 enum write_mode_t {
36 WRITE_FORCE,
37 WRITE_APPEND
38 };
39
40 static u64 user_interval = ULLONG_MAX;
41 static u64 default_interval = 0;
42
43 static unsigned int page_size;
44 static unsigned int mmap_pages = UINT_MAX;
45 static unsigned int user_freq = UINT_MAX;
46 static int freq = 1000;
47 static int output;
48 static int pipe_output = 0;
49 static const char *output_name = NULL;
50 static int group = 0;
51 static int realtime_prio = 0;
52 static bool nodelay = false;
53 static bool raw_samples = false;
54 static bool sample_id_all_avail = true;
55 static bool system_wide = false;
56 static pid_t target_pid = -1;
57 static pid_t target_tid = -1;
58 static pid_t child_pid = -1;
59 static bool no_inherit = false;
60 static enum write_mode_t write_mode = WRITE_FORCE;
61 static bool call_graph = false;
62 static bool inherit_stat = false;
63 static bool no_samples = false;
64 static bool sample_address = false;
65 static bool sample_time = false;
66 static bool no_buildid = false;
67 static bool no_buildid_cache = false;
68 static struct perf_evlist *evsel_list;
69
70 static long samples = 0;
71 static u64 bytes_written = 0;
72
73 static int file_new = 1;
74 static off_t post_processing_offset;
75
76 static struct perf_session *session;
77 static const char *cpu_list;
78
advance_output(size_t size)79 static void advance_output(size_t size)
80 {
81 bytes_written += size;
82 }
83
write_output(void * buf,size_t size)84 static void write_output(void *buf, size_t size)
85 {
86 while (size) {
87 int ret = write(output, buf, size);
88
89 if (ret < 0)
90 die("failed to write");
91
92 size -= ret;
93 buf += ret;
94
95 bytes_written += ret;
96 }
97 }
98
process_synthesized_event(union perf_event * event,struct perf_sample * sample __used,struct perf_session * self __used)99 static int process_synthesized_event(union perf_event *event,
100 struct perf_sample *sample __used,
101 struct perf_session *self __used)
102 {
103 write_output(event, event->header.size);
104 return 0;
105 }
106
mmap_read(struct perf_mmap * md)107 static void mmap_read(struct perf_mmap *md)
108 {
109 unsigned int head = perf_mmap__read_head(md);
110 unsigned int old = md->prev;
111 unsigned char *data = md->base + page_size;
112 unsigned long size;
113 void *buf;
114
115 if (old == head)
116 return;
117
118 samples++;
119
120 size = head - old;
121
122 if ((old & md->mask) + size != (head & md->mask)) {
123 buf = &data[old & md->mask];
124 size = md->mask + 1 - (old & md->mask);
125 old += size;
126
127 write_output(buf, size);
128 }
129
130 buf = &data[old & md->mask];
131 size = head - old;
132 old += size;
133
134 write_output(buf, size);
135
136 md->prev = old;
137 perf_mmap__write_tail(md, old);
138 }
139
140 static volatile int done = 0;
141 static volatile int signr = -1;
142
sig_handler(int sig)143 static void sig_handler(int sig)
144 {
145 done = 1;
146 signr = sig;
147 }
148
sig_atexit(void)149 static void sig_atexit(void)
150 {
151 if (child_pid > 0)
152 kill(child_pid, SIGTERM);
153
154 if (signr == -1 || signr == SIGUSR1)
155 return;
156
157 signal(signr, SIG_DFL);
158 kill(getpid(), signr);
159 }
160
config_attr(struct perf_evsel * evsel,struct perf_evlist * evlist)161 static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
162 {
163 struct perf_event_attr *attr = &evsel->attr;
164 int track = !evsel->idx; /* only the first counter needs these */
165
166 attr->inherit = !no_inherit;
167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
168 PERF_FORMAT_TOTAL_TIME_RUNNING |
169 PERF_FORMAT_ID;
170
171 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
172
173 if (evlist->nr_entries > 1)
174 attr->sample_type |= PERF_SAMPLE_ID;
175
176 /*
177 * We default some events to a 1 default interval. But keep
178 * it a weak assumption overridable by the user.
179 */
180 if (!attr->sample_period || (user_freq != UINT_MAX &&
181 user_interval != ULLONG_MAX)) {
182 if (freq) {
183 attr->sample_type |= PERF_SAMPLE_PERIOD;
184 attr->freq = 1;
185 attr->sample_freq = freq;
186 } else {
187 attr->sample_period = default_interval;
188 }
189 }
190
191 if (no_samples)
192 attr->sample_freq = 0;
193
194 if (inherit_stat)
195 attr->inherit_stat = 1;
196
197 if (sample_address) {
198 attr->sample_type |= PERF_SAMPLE_ADDR;
199 attr->mmap_data = track;
200 }
201
202 if (call_graph)
203 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
204
205 if (system_wide)
206 attr->sample_type |= PERF_SAMPLE_CPU;
207
208 if (sample_id_all_avail &&
209 (sample_time || system_wide || !no_inherit || cpu_list))
210 attr->sample_type |= PERF_SAMPLE_TIME;
211
212 if (raw_samples) {
213 attr->sample_type |= PERF_SAMPLE_TIME;
214 attr->sample_type |= PERF_SAMPLE_RAW;
215 attr->sample_type |= PERF_SAMPLE_CPU;
216 }
217
218 if (nodelay) {
219 attr->watermark = 0;
220 attr->wakeup_events = 1;
221 }
222
223 attr->mmap = track;
224 attr->comm = track;
225
226 if (target_pid == -1 && target_tid == -1 && !system_wide) {
227 attr->disabled = 1;
228 attr->enable_on_exec = 1;
229 }
230 }
231
perf_evlist__equal(struct perf_evlist * evlist,struct perf_evlist * other)232 static bool perf_evlist__equal(struct perf_evlist *evlist,
233 struct perf_evlist *other)
234 {
235 struct perf_evsel *pos, *pair;
236
237 if (evlist->nr_entries != other->nr_entries)
238 return false;
239
240 pair = list_entry(other->entries.next, struct perf_evsel, node);
241
242 list_for_each_entry(pos, &evlist->entries, node) {
243 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
244 return false;
245 pair = list_entry(pair->node.next, struct perf_evsel, node);
246 }
247
248 return true;
249 }
250
open_counters(struct perf_evlist * evlist)251 static void open_counters(struct perf_evlist *evlist)
252 {
253 struct perf_evsel *pos;
254
255 if (evlist->cpus->map[0] < 0)
256 no_inherit = true;
257
258 list_for_each_entry(pos, &evlist->entries, node) {
259 struct perf_event_attr *attr = &pos->attr;
260 /*
261 * Check if parse_single_tracepoint_event has already asked for
262 * PERF_SAMPLE_TIME.
263 *
264 * XXX this is kludgy but short term fix for problems introduced by
265 * eac23d1c that broke 'perf script' by having different sample_types
266 * when using multiple tracepoint events when we use a perf binary
267 * that tries to use sample_id_all on an older kernel.
268 *
269 * We need to move counter creation to perf_session, support
270 * different sample_types, etc.
271 */
272 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
273
274 config_attr(pos, evlist);
275 retry_sample_id:
276 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
277 try_again:
278 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
279 int err = errno;
280
281 if (err == EPERM || err == EACCES) {
282 ui__warning_paranoid();
283 exit(EXIT_FAILURE);
284 } else if (err == ENODEV && cpu_list) {
285 die("No such device - did you specify"
286 " an out-of-range profile CPU?\n");
287 } else if (err == EINVAL && sample_id_all_avail) {
288 /*
289 * Old kernel, no attr->sample_id_type_all field
290 */
291 sample_id_all_avail = false;
292 if (!sample_time && !raw_samples && !time_needed)
293 attr->sample_type &= ~PERF_SAMPLE_TIME;
294
295 goto retry_sample_id;
296 }
297
298 /*
299 * If it's cycles then fall back to hrtimer
300 * based cpu-clock-tick sw counter, which
301 * is always available even if no PMU support:
302 */
303 if (attr->type == PERF_TYPE_HARDWARE
304 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
305
306 if (verbose)
307 ui__warning("The cycles event is not supported, "
308 "trying to fall back to cpu-clock-ticks\n");
309 attr->type = PERF_TYPE_SOFTWARE;
310 attr->config = PERF_COUNT_SW_CPU_CLOCK;
311 goto try_again;
312 }
313
314 if (err == ENOENT) {
315 ui__warning("The %s event is not supported.\n",
316 event_name(pos));
317 exit(EXIT_FAILURE);
318 }
319
320 printf("\n");
321 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
322 err, strerror(err));
323
324 #if defined(__i386__) || defined(__x86_64__)
325 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
326 die("No hardware sampling interrupt available."
327 " No APIC? If so then you can boot the kernel"
328 " with the \"lapic\" boot parameter to"
329 " force-enable it.\n");
330 #endif
331
332 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
333 }
334 }
335
336 if (perf_evlist__set_filters(evlist)) {
337 error("failed to set filter with %d (%s)\n", errno,
338 strerror(errno));
339 exit(-1);
340 }
341
342 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
343 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
344
345 if (file_new)
346 session->evlist = evlist;
347 else {
348 if (!perf_evlist__equal(session->evlist, evlist)) {
349 fprintf(stderr, "incompatible append\n");
350 exit(-1);
351 }
352 }
353
354 perf_session__update_sample_type(session);
355 }
356
process_buildids(void)357 static int process_buildids(void)
358 {
359 u64 size = lseek(output, 0, SEEK_CUR);
360
361 if (size == 0)
362 return 0;
363
364 session->fd = output;
365 return __perf_session__process_events(session, post_processing_offset,
366 size - post_processing_offset,
367 size, &build_id__mark_dso_hit_ops);
368 }
369
atexit_header(void)370 static void atexit_header(void)
371 {
372 if (!pipe_output) {
373 session->header.data_size += bytes_written;
374
375 if (!no_buildid)
376 process_buildids();
377 perf_session__write_header(session, evsel_list, output, true);
378 perf_session__delete(session);
379 perf_evlist__delete(evsel_list);
380 symbol__exit();
381 }
382 }
383
perf_event__synthesize_guest_os(struct machine * machine,void * data)384 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
385 {
386 int err;
387 struct perf_session *psession = data;
388
389 if (machine__is_host(machine))
390 return;
391
392 /*
393 *As for guest kernel when processing subcommand record&report,
394 *we arrange module mmap prior to guest kernel mmap and trigger
395 *a preload dso because default guest module symbols are loaded
396 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
397 *method is used to avoid symbol missing when the first addr is
398 *in module instead of in guest kernel.
399 */
400 err = perf_event__synthesize_modules(process_synthesized_event,
401 psession, machine);
402 if (err < 0)
403 pr_err("Couldn't record guest kernel [%d]'s reference"
404 " relocation symbol.\n", machine->pid);
405
406 /*
407 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
408 * have no _text sometimes.
409 */
410 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
411 psession, machine, "_text");
412 if (err < 0)
413 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
414 psession, machine,
415 "_stext");
416 if (err < 0)
417 pr_err("Couldn't record guest kernel [%d]'s reference"
418 " relocation symbol.\n", machine->pid);
419 }
420
421 static struct perf_event_header finished_round_event = {
422 .size = sizeof(struct perf_event_header),
423 .type = PERF_RECORD_FINISHED_ROUND,
424 };
425
mmap_read_all(void)426 static void mmap_read_all(void)
427 {
428 int i;
429
430 for (i = 0; i < evsel_list->nr_mmaps; i++) {
431 if (evsel_list->mmap[i].base)
432 mmap_read(&evsel_list->mmap[i]);
433 }
434
435 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
436 write_output(&finished_round_event, sizeof(finished_round_event));
437 }
438
__cmd_record(int argc,const char ** argv)439 static int __cmd_record(int argc, const char **argv)
440 {
441 /* ANDROID_CHANGE_BEGIN */
442 #ifndef __APPLE__
443 int i;
444 struct stat st;
445 int flags;
446 int err;
447 unsigned long waking = 0;
448 int child_ready_pipe[2], go_pipe[2];
449 const bool forks = argc > 0;
450 char buf;
451 struct machine *machine;
452
453 page_size = sysconf(_SC_PAGE_SIZE);
454
455 atexit(sig_atexit);
456 signal(SIGCHLD, sig_handler);
457 signal(SIGINT, sig_handler);
458 signal(SIGUSR1, sig_handler);
459
460 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
461 perror("failed to create pipes");
462 exit(-1);
463 }
464
465 if (!output_name) {
466 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
467 pipe_output = 1;
468 else
469 /* ANDROID_CHANGE_BEGIN */
470 #ifdef __BIONIC__
471 output_name = "/data/perf.data";
472 #else
473 output_name = "perf.data";
474 #endif
475 /* ANDROID_CHANGE_END */
476 }
477 if (output_name) {
478 if (!strcmp(output_name, "-"))
479 pipe_output = 1;
480 else if (!stat(output_name, &st) && st.st_size) {
481 if (write_mode == WRITE_FORCE) {
482 char oldname[PATH_MAX];
483 snprintf(oldname, sizeof(oldname), "%s.old",
484 output_name);
485 unlink(oldname);
486 rename(output_name, oldname);
487 }
488 } else if (write_mode == WRITE_APPEND) {
489 write_mode = WRITE_FORCE;
490 }
491 }
492
493 flags = O_CREAT|O_RDWR;
494 if (write_mode == WRITE_APPEND)
495 file_new = 0;
496 else
497 flags |= O_TRUNC;
498
499 if (pipe_output)
500 output = STDOUT_FILENO;
501 else
502 output = open(output_name, flags, S_IRUSR | S_IWUSR);
503 if (output < 0) {
504 perror("failed to create output file");
505 exit(-1);
506 }
507
508 session = perf_session__new(output_name, O_WRONLY,
509 write_mode == WRITE_FORCE, false, NULL);
510 if (session == NULL) {
511 pr_err("Not enough memory for reading perf file header\n");
512 return -1;
513 }
514
515 if (!no_buildid)
516 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
517
518 if (!file_new) {
519 err = perf_session__read_header(session, output);
520 if (err < 0)
521 goto out_delete_session;
522 }
523
524 if (have_tracepoints(&evsel_list->entries))
525 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
526
527 /* 512 kiB: default amount of unprivileged mlocked memory */
528 if (mmap_pages == UINT_MAX)
529 mmap_pages = (512 * 1024) / page_size;
530
531 if (forks) {
532 child_pid = fork();
533 if (child_pid < 0) {
534 perror("failed to fork");
535 exit(-1);
536 }
537
538 if (!child_pid) {
539 if (pipe_output)
540 dup2(2, 1);
541 close(child_ready_pipe[0]);
542 close(go_pipe[1]);
543 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
544
545 /*
546 * Do a dummy execvp to get the PLT entry resolved,
547 * so we avoid the resolver overhead on the real
548 * execvp call.
549 */
550 execvp("", (char **)argv);
551
552 /*
553 * Tell the parent we're ready to go
554 */
555 close(child_ready_pipe[1]);
556
557 /*
558 * Wait until the parent tells us to go.
559 */
560 if (read(go_pipe[0], &buf, 1) == -1)
561 perror("unable to read pipe");
562
563 execvp(argv[0], (char **)argv);
564
565 perror(argv[0]);
566 kill(getppid(), SIGUSR1);
567 exit(-1);
568 }
569
570 if (!system_wide && target_tid == -1 && target_pid == -1)
571 evsel_list->threads->map[0] = child_pid;
572
573 close(child_ready_pipe[1]);
574 close(go_pipe[0]);
575 /*
576 * wait for child to settle
577 */
578 if (read(child_ready_pipe[0], &buf, 1) == -1) {
579 perror("unable to read pipe");
580 exit(-1);
581 }
582 close(child_ready_pipe[0]);
583 }
584
585 open_counters(evsel_list);
586
587 /*
588 * perf_session__delete(session) will be called at atexit_header()
589 */
590 atexit(atexit_header);
591
592 if (pipe_output) {
593 err = perf_header__write_pipe(output);
594 if (err < 0)
595 return err;
596 } else if (file_new) {
597 err = perf_session__write_header(session, evsel_list,
598 output, false);
599 if (err < 0)
600 return err;
601 }
602
603 post_processing_offset = lseek(output, 0, SEEK_CUR);
604
605 if (pipe_output) {
606 err = perf_session__synthesize_attrs(session,
607 process_synthesized_event);
608 if (err < 0) {
609 pr_err("Couldn't synthesize attrs.\n");
610 return err;
611 }
612
613 err = perf_event__synthesize_event_types(process_synthesized_event,
614 session);
615 if (err < 0) {
616 pr_err("Couldn't synthesize event_types.\n");
617 return err;
618 }
619
620 if (have_tracepoints(&evsel_list->entries)) {
621 /*
622 * FIXME err <= 0 here actually means that
623 * there were no tracepoints so its not really
624 * an error, just that we don't need to
625 * synthesize anything. We really have to
626 * return this more properly and also
627 * propagate errors that now are calling die()
628 */
629 err = perf_event__synthesize_tracing_data(output, evsel_list,
630 process_synthesized_event,
631 session);
632 if (err <= 0) {
633 pr_err("Couldn't record tracing data.\n");
634 return err;
635 }
636 advance_output(err);
637 }
638 }
639
640 machine = perf_session__find_host_machine(session);
641 if (!machine) {
642 pr_err("Couldn't find native kernel information.\n");
643 return -1;
644 }
645
646 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
647 session, machine, "_text");
648 if (err < 0)
649 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
650 session, machine, "_stext");
651 if (err < 0)
652 pr_err("Couldn't record kernel reference relocation symbol\n"
653 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
654 "Check /proc/kallsyms permission or run as root.\n");
655
656 err = perf_event__synthesize_modules(process_synthesized_event,
657 session, machine);
658 if (err < 0)
659 pr_err("Couldn't record kernel module information.\n"
660 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
661 "Check /proc/modules permission or run as root.\n");
662
663 if (perf_guest)
664 perf_session__process_machines(session,
665 perf_event__synthesize_guest_os);
666
667 if (!system_wide)
668 perf_event__synthesize_thread_map(evsel_list->threads,
669 process_synthesized_event,
670 session);
671 else
672 perf_event__synthesize_threads(process_synthesized_event,
673 session);
674
675 if (realtime_prio) {
676 struct sched_param param;
677
678 param.sched_priority = realtime_prio;
679 if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
680 pr_err("Could not set realtime priority.\n");
681 exit(-1);
682 }
683 }
684
685 /*
686 * Let the child rip
687 */
688 if (forks)
689 close(go_pipe[1]);
690
691 for (;;) {
692 int hits = samples;
693 int thread;
694
695 mmap_read_all();
696
697 if (hits == samples) {
698 if (done)
699 break;
700 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
701 waking++;
702 }
703
704 if (done) {
705 for (i = 0; i < evsel_list->cpus->nr; i++) {
706 struct perf_evsel *pos;
707
708 list_for_each_entry(pos, &evsel_list->entries, node) {
709 for (thread = 0;
710 thread < evsel_list->threads->nr;
711 thread++)
712 ioctl(FD(pos, i, thread),
713 PERF_EVENT_IOC_DISABLE);
714 }
715 }
716 }
717 }
718
719 if (quiet || signr == SIGUSR1)
720 return 0;
721
722 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
723
724 /*
725 * Approximate RIP event size: 24 bytes.
726 */
727 fprintf(stderr,
728 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
729 (double)bytes_written / 1024.0 / 1024.0,
730 output_name,
731 bytes_written / 24);
732
733 return 0;
734
735 out_delete_session:
736 perf_session__delete(session);
737 return err;
738 #else
739 return -1;
740 #endif
741 /* ANDROID_CHANGE_END */
742 }
743
744 static const char * const record_usage[] = {
745 "perf record [<options>] [<command>]",
746 "perf record [<options>] -- <command> [<options>]",
747 NULL
748 };
749
750 static bool force, append_file;
751
752 const struct option record_options[] = {
753 OPT_CALLBACK('e', "event", &evsel_list, "event",
754 "event selector. use 'perf list' to list available events",
755 parse_events),
756 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
757 "event filter", parse_filter),
758 OPT_INTEGER('p', "pid", &target_pid,
759 "record events on existing process id"),
760 OPT_INTEGER('t', "tid", &target_tid,
761 "record events on existing thread id"),
762 OPT_INTEGER('r', "realtime", &realtime_prio,
763 "collect data with this RT SCHED_FIFO priority"),
764 OPT_BOOLEAN('D', "no-delay", &nodelay,
765 "collect data without buffering"),
766 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
767 "collect raw sample records from all opened counters"),
768 OPT_BOOLEAN('a', "all-cpus", &system_wide,
769 "system-wide collection from all CPUs"),
770 OPT_BOOLEAN('A', "append", &append_file,
771 "append to the output file to do incremental profiling"),
772 OPT_STRING('C', "cpu", &cpu_list, "cpu",
773 "list of cpus to monitor"),
774 OPT_BOOLEAN('f', "force", &force,
775 "overwrite existing data file (deprecated)"),
776 OPT_U64('c', "count", &user_interval, "event period to sample"),
777 OPT_STRING('o', "output", &output_name, "file",
778 "output file name"),
779 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
780 "child tasks do not inherit counters"),
781 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
782 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
783 OPT_BOOLEAN('g', "call-graph", &call_graph,
784 "do call-graph (stack chain/backtrace) recording"),
785 OPT_INCR('v', "verbose", &verbose,
786 "be more verbose (show counter open errors, etc)"),
787 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
788 OPT_BOOLEAN('s', "stat", &inherit_stat,
789 "per thread counts"),
790 OPT_BOOLEAN('d', "data", &sample_address,
791 "Sample addresses"),
792 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
793 OPT_BOOLEAN('n', "no-samples", &no_samples,
794 "don't sample"),
795 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
796 "do not update the buildid cache"),
797 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
798 "do not collect buildids in perf.data"),
799 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
800 "monitor event in cgroup name only",
801 parse_cgroups),
802 OPT_END()
803 };
804
cmd_record(int argc,const char ** argv,const char * prefix __used)805 int cmd_record(int argc, const char **argv, const char *prefix __used)
806 {
807 int err = -ENOMEM;
808 struct perf_evsel *pos;
809
810 evsel_list = perf_evlist__new(NULL, NULL);
811 if (evsel_list == NULL)
812 return -ENOMEM;
813
814 argc = parse_options(argc, argv, record_options, record_usage,
815 PARSE_OPT_STOP_AT_NON_OPTION);
816 if (!argc && target_pid == -1 && target_tid == -1 &&
817 !system_wide && !cpu_list)
818 usage_with_options(record_usage, record_options);
819
820 if (force && append_file) {
821 fprintf(stderr, "Can't overwrite and append at the same time."
822 " You need to choose between -f and -A");
823 usage_with_options(record_usage, record_options);
824 } else if (append_file) {
825 write_mode = WRITE_APPEND;
826 } else {
827 write_mode = WRITE_FORCE;
828 }
829
830 if (nr_cgroups && !system_wide) {
831 fprintf(stderr, "cgroup monitoring only available in"
832 " system-wide mode\n");
833 usage_with_options(record_usage, record_options);
834 }
835
836 symbol__init();
837
838 if (symbol_conf.kptr_restrict)
839 pr_warning(
840 "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
841 "check /proc/sys/kernel/kptr_restrict.\n\n"
842 "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
843 "file is not found in the buildid cache or in the vmlinux path.\n\n"
844 "Samples in kernel modules won't be resolved at all.\n\n"
845 "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
846 "even with a suitable vmlinux or kallsyms file.\n\n");
847
848 if (no_buildid_cache || no_buildid)
849 disable_buildid_cache();
850
851 if (evsel_list->nr_entries == 0 &&
852 perf_evlist__add_default(evsel_list) < 0) {
853 pr_err("Not enough memory for event selector list\n");
854 goto out_symbol_exit;
855 }
856
857 if (target_pid != -1)
858 target_tid = target_pid;
859
860 if (perf_evlist__create_maps(evsel_list, target_pid,
861 target_tid, cpu_list) < 0)
862 usage_with_options(record_usage, record_options);
863
864 list_for_each_entry(pos, &evsel_list->entries, node) {
865 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
866 evsel_list->threads->nr) < 0)
867 goto out_free_fd;
868 if (perf_header__push_event(pos->attr.config, event_name(pos)))
869 goto out_free_fd;
870 }
871
872 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
873 goto out_free_fd;
874
875 if (user_interval != ULLONG_MAX)
876 default_interval = user_interval;
877 if (user_freq != UINT_MAX)
878 freq = user_freq;
879
880 /*
881 * User specified count overrides default frequency.
882 */
883 if (default_interval)
884 freq = 0;
885 else if (freq) {
886 default_interval = freq;
887 } else {
888 fprintf(stderr, "frequency and count are zero, aborting\n");
889 err = -EINVAL;
890 goto out_free_fd;
891 }
892
893 err = __cmd_record(argc, argv);
894 out_free_fd:
895 perf_evlist__delete_maps(evsel_list);
896 out_symbol_exit:
897 symbol__exit();
898 return err;
899 }
900