perf annotate: Group options in a struct
[deliverable/linux.git] / tools / perf / builtin-record.c
CommitLineData
abaff32a 1/*
bf9e1876
IM
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.
abaff32a 7 */
b8f46c5a
XG
8#define _FILE_OFFSET_BITS 64
9
16f762a2 10#include "builtin.h"
bf9e1876
IM
11
12#include "perf.h"
13
6122e4e4 14#include "util/build-id.h"
6eda5838 15#include "util/util.h"
0e9b20b8 16#include "util/parse-options.h"
8ad8db37 17#include "util/parse-events.h"
6eda5838 18
7c6a1c65 19#include "util/header.h"
66e274f3 20#include "util/event.h"
361c99a6 21#include "util/evlist.h"
69aad6f1 22#include "util/evsel.h"
8f28827a 23#include "util/debug.h"
94c744b6 24#include "util/session.h"
8d06367f 25#include "util/symbol.h"
a12b51c4 26#include "util/cpumap.h"
fd78260b 27#include "util/thread_map.h"
7c6a1c65 28
97124d5e 29#include <unistd.h>
de9ac07b 30#include <sched.h>
a41794cd 31#include <sys/mman.h>
de9ac07b 32
7865e817
FW
33enum write_mode_t {
34 WRITE_FORCE,
35 WRITE_APPEND
36};
37
01c2d99b 38struct perf_record_opts record_opts = {
0f82ebc4
ACM
39 .target_pid = -1,
40 .target_tid = -1,
01c2d99b 41 .mmap_pages = UINT_MAX,
0f82ebc4
ACM
42 .user_freq = UINT_MAX,
43 .user_interval = ULLONG_MAX,
44 .freq = 1000,
45 .sample_id_all_avail = true,
46};
a21ca2ca 47
de9ac07b 48static unsigned int page_size;
de9ac07b 49static int output;
d7065adb 50static const char *output_name = NULL;
1967936d 51static int realtime_prio = 0;
7865e817 52static enum write_mode_t write_mode = WRITE_FORCE;
a1ac1d3c 53static bool no_buildid = false;
baa2f6ce 54static bool no_buildid_cache = false;
361c99a6 55static struct perf_evlist *evsel_list;
42e59d7d
IM
56
57static long samples = 0;
42e59d7d 58static u64 bytes_written = 0;
a21ca2ca 59
42e59d7d 60static int file_new = 1;
6122e4e4 61static off_t post_processing_offset;
7c6a1c65 62
94c744b6 63static struct perf_session *session;
33e49ea7 64static const char *progname;
f5970550 65
9215545e
TZ
66static void advance_output(size_t size)
67{
68 bytes_written += size;
69}
70
f5970550
PZ
71static void write_output(void *buf, size_t size)
72{
73 while (size) {
74 int ret = write(output, buf, size);
75
76 if (ret < 0)
77 die("failed to write");
78
79 size -= ret;
80 buf += ret;
81
82 bytes_written += ret;
83 }
84}
85
8115d60c 86static int process_synthesized_event(union perf_event *event,
8d50e5b4 87 struct perf_sample *sample __used,
d8f66248 88 struct perf_session *self __used)
234fbbf5 89{
6122e4e4 90 write_output(event, event->header.size);
234fbbf5
ACM
91 return 0;
92}
93
744bd8aa 94static void mmap_read(struct perf_mmap *md)
de9ac07b 95{
744bd8aa 96 unsigned int head = perf_mmap__read_head(md);
de9ac07b
PZ
97 unsigned int old = md->prev;
98 unsigned char *data = md->base + page_size;
99 unsigned long size;
100 void *buf;
de9ac07b 101
dc82009a
ACM
102 if (old == head)
103 return;
104
105 samples++;
de9ac07b
PZ
106
107 size = head - old;
108
109 if ((old & md->mask) + size != (head & md->mask)) {
110 buf = &data[old & md->mask];
111 size = md->mask + 1 - (old & md->mask);
112 old += size;
021e9f47 113
6122e4e4 114 write_output(buf, size);
de9ac07b
PZ
115 }
116
117 buf = &data[old & md->mask];
118 size = head - old;
119 old += size;
021e9f47 120
6122e4e4 121 write_output(buf, size);
de9ac07b
PZ
122
123 md->prev = old;
115d2d89 124 perf_mmap__write_tail(md, old);
de9ac07b
PZ
125}
126
127static volatile int done = 0;
f7b7c26e 128static volatile int signr = -1;
33e49ea7 129static volatile int child_finished = 0;
de9ac07b 130
16c8a109 131static void sig_handler(int sig)
de9ac07b 132{
33e49ea7
AK
133 if (sig == SIGCHLD)
134 child_finished = 1;
135
16c8a109 136 done = 1;
f7b7c26e
PZ
137 signr = sig;
138}
139
140static void sig_atexit(void)
141{
33e49ea7
AK
142 int status;
143
35b9d88e 144 if (evsel_list->workload.pid > 0) {
33e49ea7 145 if (!child_finished)
35b9d88e 146 kill(evsel_list->workload.pid, SIGTERM);
33e49ea7
AK
147
148 wait(&status);
149 if (WIFSIGNALED(status))
150 psignal(WTERMSIG(status), progname);
151 }
933da83a 152
18483b81 153 if (signr == -1 || signr == SIGUSR1)
f7b7c26e
PZ
154 return;
155
156 signal(signr, SIG_DFL);
157 kill(getpid(), signr);
de9ac07b
PZ
158}
159
a91e5431
ACM
160static bool perf_evlist__equal(struct perf_evlist *evlist,
161 struct perf_evlist *other)
162{
163 struct perf_evsel *pos, *pair;
164
165 if (evlist->nr_entries != other->nr_entries)
166 return false;
167
168 pair = list_entry(other->entries.next, struct perf_evsel, node);
169
170 list_for_each_entry(pos, &evlist->entries, node) {
171 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
172 return false;
173 pair = list_entry(pair->node.next, struct perf_evsel, node);
174 }
175
176 return true;
177}
178
dd7927f4
ACM
179static void open_counters(struct perf_evlist *evlist)
180{
727ab04e 181 struct perf_evsel *pos, *first;
dd7927f4 182
727ab04e
ACM
183 first = list_entry(evlist->entries.next, struct perf_evsel, node);
184
0f82ebc4
ACM
185 perf_evlist__config_attrs(evlist, &record_opts);
186
dd7927f4
ACM
187 list_for_each_entry(pos, &evlist->entries, node) {
188 struct perf_event_attr *attr = &pos->attr;
727ab04e 189 struct xyarray *group_fd = NULL;
dd7927f4
ACM
190 /*
191 * Check if parse_single_tracepoint_event has already asked for
192 * PERF_SAMPLE_TIME.
193 *
194 * XXX this is kludgy but short term fix for problems introduced by
195 * eac23d1c that broke 'perf script' by having different sample_types
196 * when using multiple tracepoint events when we use a perf binary
197 * that tries to use sample_id_all on an older kernel.
198 *
199 * We need to move counter creation to perf_session, support
200 * different sample_types, etc.
201 */
202 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
d6d901c2 203
ed80f581 204 if (record_opts.group && pos != first)
727ab04e 205 group_fd = first->fd;
dd7927f4 206retry_sample_id:
0f82ebc4 207 attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
dd7927f4 208try_again:
ed80f581
ACM
209 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
210 record_opts.group, group_fd) < 0) {
d6d901c2
ZY
211 int err = errno;
212
c286c419 213 if (err == EPERM || err == EACCES) {
b8631e6e 214 ui__error_paranoid();
c286c419 215 exit(EXIT_FAILURE);
0f82ebc4 216 } else if (err == ENODEV && record_opts.cpu_list) {
d6d901c2
ZY
217 die("No such device - did you specify"
218 " an out-of-range profile CPU?\n");
0f82ebc4 219 } else if (err == EINVAL && record_opts.sample_id_all_avail) {
9c90a61c
ACM
220 /*
221 * Old kernel, no attr->sample_id_type_all field
222 */
0f82ebc4
ACM
223 record_opts.sample_id_all_avail = false;
224 if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
eac23d1c
IM
225 attr->sample_type &= ~PERF_SAMPLE_TIME;
226
9c90a61c 227 goto retry_sample_id;
d6d901c2 228 }
3da297a6 229
d6d901c2
ZY
230 /*
231 * If it's cycles then fall back to hrtimer
232 * based cpu-clock-tick sw counter, which
233 * is always available even if no PMU support:
234 */
235 if (attr->type == PERF_TYPE_HARDWARE
236 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
237
238 if (verbose)
ca6a4258
DA
239 ui__warning("The cycles event is not supported, "
240 "trying to fall back to cpu-clock-ticks\n");
d6d901c2
ZY
241 attr->type = PERF_TYPE_SOFTWARE;
242 attr->config = PERF_COUNT_SW_CPU_CLOCK;
243 goto try_again;
244 }
ca6a4258
DA
245
246 if (err == ENOENT) {
247 ui__warning("The %s event is not supported.\n",
248 event_name(pos));
249 exit(EXIT_FAILURE);
250 }
251
d6d901c2 252 printf("\n");
d9cf837e 253 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
dd7927f4 254 err, strerror(err));
bfd45118
SK
255
256#if defined(__i386__) || defined(__x86_64__)
d6d901c2
ZY
257 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
258 die("No hardware sampling interrupt available."
259 " No APIC? If so then you can boot the kernel"
260 " with the \"lapic\" boot parameter to"
261 " force-enable it.\n");
bfd45118
SK
262#endif
263
d6d901c2 264 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
c171b552
LZ
265 }
266 }
a43d3f08 267
0a102479
FW
268 if (perf_evlist__set_filters(evlist)) {
269 error("failed to set filter with %d (%s)\n", errno,
270 strerror(errno));
271 exit(-1);
272 }
273
01c2d99b 274 if (perf_evlist__mmap(evlist, record_opts.mmap_pages, false) < 0)
0a27d7f9
ACM
275 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
276
a91e5431
ACM
277 if (file_new)
278 session->evlist = evlist;
279 else {
280 if (!perf_evlist__equal(session->evlist, evlist)) {
281 fprintf(stderr, "incompatible append\n");
282 exit(-1);
283 }
284 }
285
286 perf_session__update_sample_type(session);
16c8a109
PZ
287}
288
6122e4e4
ACM
289static int process_buildids(void)
290{
291 u64 size = lseek(output, 0, SEEK_CUR);
292
9f591fd7
ACM
293 if (size == 0)
294 return 0;
295
6122e4e4
ACM
296 session->fd = output;
297 return __perf_session__process_events(session, post_processing_offset,
298 size - post_processing_offset,
299 size, &build_id__mark_dso_hit_ops);
300}
301
f5970550
PZ
302static void atexit_header(void)
303{
35b9d88e 304 if (!record_opts.pipe_output) {
c7929e47 305 session->header.data_size += bytes_written;
f5970550 306
baa2f6ce
ACM
307 if (!no_buildid)
308 process_buildids();
a91e5431 309 perf_session__write_header(session, evsel_list, output, true);
39d17dac 310 perf_session__delete(session);
361c99a6 311 perf_evlist__delete(evsel_list);
d65a458b 312 symbol__exit();
c7929e47 313 }
f5970550
PZ
314}
315
8115d60c 316static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
a1645ce1
ZY
317{
318 int err;
23346f21 319 struct perf_session *psession = data;
a1645ce1 320
23346f21 321 if (machine__is_host(machine))
a1645ce1
ZY
322 return;
323
324 /*
325 *As for guest kernel when processing subcommand record&report,
326 *we arrange module mmap prior to guest kernel mmap and trigger
327 *a preload dso because default guest module symbols are loaded
328 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
329 *method is used to avoid symbol missing when the first addr is
330 *in module instead of in guest kernel.
331 */
8115d60c
ACM
332 err = perf_event__synthesize_modules(process_synthesized_event,
333 psession, machine);
a1645ce1
ZY
334 if (err < 0)
335 pr_err("Couldn't record guest kernel [%d]'s reference"
23346f21 336 " relocation symbol.\n", machine->pid);
a1645ce1 337
a1645ce1
ZY
338 /*
339 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
340 * have no _text sometimes.
341 */
8115d60c
ACM
342 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
343 psession, machine, "_text");
a1645ce1 344 if (err < 0)
8115d60c
ACM
345 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
346 psession, machine,
347 "_stext");
a1645ce1
ZY
348 if (err < 0)
349 pr_err("Couldn't record guest kernel [%d]'s reference"
23346f21 350 " relocation symbol.\n", machine->pid);
a1645ce1
ZY
351}
352
98402807
FW
353static struct perf_event_header finished_round_event = {
354 .size = sizeof(struct perf_event_header),
355 .type = PERF_RECORD_FINISHED_ROUND,
356};
357
358static void mmap_read_all(void)
359{
0e2e63dd 360 int i;
98402807 361
aece948f 362 for (i = 0; i < evsel_list->nr_mmaps; i++) {
0a27d7f9
ACM
363 if (evsel_list->mmap[i].base)
364 mmap_read(&evsel_list->mmap[i]);
98402807
FW
365 }
366
367 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
368 write_output(&finished_round_event, sizeof(finished_round_event));
369}
370
d4db3f16 371static int __cmd_record(int argc, const char **argv)
16c8a109 372{
abaff32a 373 struct stat st;
abaff32a 374 int flags;
4dc0a04b 375 int err;
8b412664 376 unsigned long waking = 0;
46be604b 377 const bool forks = argc > 0;
23346f21 378 struct machine *machine;
de9ac07b 379
33e49ea7
AK
380 progname = argv[0];
381
de9ac07b 382 page_size = sysconf(_SC_PAGE_SIZE);
de9ac07b 383
f5970550
PZ
384 atexit(sig_atexit);
385 signal(SIGCHLD, sig_handler);
386 signal(SIGINT, sig_handler);
18483b81 387 signal(SIGUSR1, sig_handler);
f5970550 388
d7065adb
FBH
389 if (!output_name) {
390 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
35b9d88e 391 record_opts.pipe_output = true;
d7065adb
FBH
392 else
393 output_name = "perf.data";
394 }
395 if (output_name) {
396 if (!strcmp(output_name, "-"))
35b9d88e 397 record_opts.pipe_output = true;
d7065adb
FBH
398 else if (!stat(output_name, &st) && st.st_size) {
399 if (write_mode == WRITE_FORCE) {
400 char oldname[PATH_MAX];
401 snprintf(oldname, sizeof(oldname), "%s.old",
402 output_name);
403 unlink(oldname);
404 rename(output_name, oldname);
405 }
406 } else if (write_mode == WRITE_APPEND) {
407 write_mode = WRITE_FORCE;
266e0e21 408 }
97124d5e
PZ
409 }
410
f887f301 411 flags = O_CREAT|O_RDWR;
7865e817 412 if (write_mode == WRITE_APPEND)
f5970550 413 file_new = 0;
abaff32a
IM
414 else
415 flags |= O_TRUNC;
416
35b9d88e 417 if (record_opts.pipe_output)
529870e3
TZ
418 output = STDOUT_FILENO;
419 else
420 output = open(output_name, flags, S_IRUSR | S_IWUSR);
de9ac07b
PZ
421 if (output < 0) {
422 perror("failed to create output file");
423 exit(-1);
424 }
425
7865e817 426 session = perf_session__new(output_name, O_WRONLY,
21ef97f0 427 write_mode == WRITE_FORCE, false, NULL);
94c744b6 428 if (session == NULL) {
a9a70bbc
ACM
429 pr_err("Not enough memory for reading perf file header\n");
430 return -1;
431 }
432
baa2f6ce
ACM
433 if (!no_buildid)
434 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
435
4dc0a04b 436 if (!file_new) {
a91e5431 437 err = perf_session__read_header(session, output);
4dc0a04b 438 if (err < 0)
39d17dac 439 goto out_delete_session;
4dc0a04b
ACM
440 }
441
361c99a6 442 if (have_tracepoints(&evsel_list->entries))
94c744b6 443 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
03456a15 444
fbe96f29
SE
445 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
446 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
447 perf_header__set_feat(&session->header, HEADER_ARCH);
448 perf_header__set_feat(&session->header, HEADER_CPUDESC);
449 perf_header__set_feat(&session->header, HEADER_NRCPUS);
450 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
451 perf_header__set_feat(&session->header, HEADER_CMDLINE);
452 perf_header__set_feat(&session->header, HEADER_VERSION);
453 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
454 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
455 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
456 perf_header__set_feat(&session->header, HEADER_CPUID);
457
d4db3f16 458 if (forks) {
35b9d88e
ACM
459 err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
460 if (err < 0) {
461 pr_err("Couldn't run the workload!\n");
462 goto out_delete_session;
856e9660 463 }
856e9660
PZ
464 }
465
dd7927f4 466 open_counters(evsel_list);
de9ac07b 467
712a4b60
ACM
468 /*
469 * perf_session__delete(session) will be called at atexit_header()
470 */
471 atexit(atexit_header);
472
35b9d88e 473 if (record_opts.pipe_output) {
529870e3
TZ
474 err = perf_header__write_pipe(output);
475 if (err < 0)
476 return err;
477 } else if (file_new) {
a91e5431
ACM
478 err = perf_session__write_header(session, evsel_list,
479 output, false);
d5eed904
ACM
480 if (err < 0)
481 return err;
56b03f3c
ACM
482 }
483
6122e4e4
ACM
484 post_processing_offset = lseek(output, 0, SEEK_CUR);
485
35b9d88e 486 if (record_opts.pipe_output) {
a91e5431
ACM
487 err = perf_session__synthesize_attrs(session,
488 process_synthesized_event);
2c46dbb5
TZ
489 if (err < 0) {
490 pr_err("Couldn't synthesize attrs.\n");
491 return err;
492 }
cd19a035 493
8115d60c
ACM
494 err = perf_event__synthesize_event_types(process_synthesized_event,
495 session);
cd19a035
TZ
496 if (err < 0) {
497 pr_err("Couldn't synthesize event_types.\n");
498 return err;
499 }
9215545e 500
361c99a6 501 if (have_tracepoints(&evsel_list->entries)) {
63e0c771
TZ
502 /*
503 * FIXME err <= 0 here actually means that
504 * there were no tracepoints so its not really
505 * an error, just that we don't need to
506 * synthesize anything. We really have to
507 * return this more properly and also
508 * propagate errors that now are calling die()
509 */
8115d60c
ACM
510 err = perf_event__synthesize_tracing_data(output, evsel_list,
511 process_synthesized_event,
512 session);
63e0c771
TZ
513 if (err <= 0) {
514 pr_err("Couldn't record tracing data.\n");
515 return err;
516 }
2c9faa06 517 advance_output(err);
63e0c771 518 }
2c46dbb5
TZ
519 }
520
23346f21
ACM
521 machine = perf_session__find_host_machine(session);
522 if (!machine) {
a1645ce1
ZY
523 pr_err("Couldn't find native kernel information.\n");
524 return -1;
525 }
526
8115d60c
ACM
527 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
528 session, machine, "_text");
70162138 529 if (err < 0)
8115d60c
ACM
530 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
531 session, machine, "_stext");
c1a3a4b9
ACM
532 if (err < 0)
533 pr_err("Couldn't record kernel reference relocation symbol\n"
534 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
535 "Check /proc/kallsyms permission or run as root.\n");
b7cece76 536
8115d60c
ACM
537 err = perf_event__synthesize_modules(process_synthesized_event,
538 session, machine);
c1a3a4b9
ACM
539 if (err < 0)
540 pr_err("Couldn't record kernel module information.\n"
541 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
542 "Check /proc/modules permission or run as root.\n");
543
a1645ce1 544 if (perf_guest)
8115d60c
ACM
545 perf_session__process_machines(session,
546 perf_event__synthesize_guest_os);
7c6a1c65 547
0f82ebc4 548 if (!record_opts.system_wide)
7c940c18
ACM
549 perf_event__synthesize_thread_map(evsel_list->threads,
550 process_synthesized_event,
551 session);
234fbbf5 552 else
8115d60c
ACM
553 perf_event__synthesize_threads(process_synthesized_event,
554 session);
7c6a1c65 555
de9ac07b
PZ
556 if (realtime_prio) {
557 struct sched_param param;
558
559 param.sched_priority = realtime_prio;
560 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6beba7ad 561 pr_err("Could not set realtime priority.\n");
de9ac07b
PZ
562 exit(-1);
563 }
564 }
565
764e16a3
DA
566 perf_evlist__enable(evsel_list);
567
856e9660
PZ
568 /*
569 * Let the child rip
570 */
d4db3f16 571 if (forks)
35b9d88e 572 perf_evlist__start_workload(evsel_list);
856e9660 573
649c48a9 574 for (;;) {
2debbc83 575 int hits = samples;
de9ac07b 576
98402807 577 mmap_read_all();
de9ac07b 578
649c48a9
PZ
579 if (hits == samples) {
580 if (done)
581 break;
5c581041 582 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
8b412664
PZ
583 waking++;
584 }
585
4152ab37
ACM
586 if (done)
587 perf_evlist__disable(evsel_list);
de9ac07b
PZ
588 }
589
18483b81 590 if (quiet || signr == SIGUSR1)
b44308f5
ACM
591 return 0;
592
8b412664
PZ
593 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
594
021e9f47
IM
595 /*
596 * Approximate RIP event size: 24 bytes.
597 */
598 fprintf(stderr,
9486aa38 599 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
021e9f47
IM
600 (double)bytes_written / 1024.0 / 1024.0,
601 output_name,
602 bytes_written / 24);
addc2785 603
de9ac07b 604 return 0;
39d17dac
ACM
605
606out_delete_session:
607 perf_session__delete(session);
608 return err;
de9ac07b 609}
0e9b20b8 610
0e9b20b8 611static const char * const record_usage[] = {
9e096753
MG
612 "perf record [<options>] [<command>]",
613 "perf record [<options>] -- <command> [<options>]",
0e9b20b8
IM
614 NULL
615};
616
7865e817
FW
617static bool force, append_file;
618
bca647aa 619const struct option record_options[] = {
361c99a6 620 OPT_CALLBACK('e', "event", &evsel_list, "event",
86847b62 621 "event selector. use 'perf list' to list available events",
f120f9d5 622 parse_events_option),
361c99a6 623 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
c171b552 624 "event filter", parse_filter),
0f82ebc4 625 OPT_INTEGER('p', "pid", &record_opts.target_pid,
d6d901c2 626 "record events on existing process id"),
0f82ebc4 627 OPT_INTEGER('t', "tid", &record_opts.target_tid,
d6d901c2 628 "record events on existing thread id"),
0e9b20b8
IM
629 OPT_INTEGER('r', "realtime", &realtime_prio,
630 "collect data with this RT SCHED_FIFO priority"),
0f82ebc4 631 OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay,
acac03fa 632 "collect data without buffering"),
0f82ebc4 633 OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples,
daac07b2 634 "collect raw sample records from all opened counters"),
0f82ebc4 635 OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide,
0e9b20b8 636 "system-wide collection from all CPUs"),
abaff32a
IM
637 OPT_BOOLEAN('A', "append", &append_file,
638 "append to the output file to do incremental profiling"),
0f82ebc4 639 OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu",
c45c6ea2 640 "list of cpus to monitor"),
97124d5e 641 OPT_BOOLEAN('f', "force", &force,
7865e817 642 "overwrite existing data file (deprecated)"),
0f82ebc4 643 OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"),
abaff32a
IM
644 OPT_STRING('o', "output", &output_name, "file",
645 "output file name"),
0f82ebc4 646 OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
2e6cdf99 647 "child tasks do not inherit counters"),
0f82ebc4 648 OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
01c2d99b
ACM
649 OPT_UINTEGER('m', "mmap-pages", &record_opts.mmap_pages,
650 "number of mmap data pages"),
ed80f581 651 OPT_BOOLEAN(0, "group", &record_opts.group,
43bece79 652 "put the counters into a counter group"),
0f82ebc4 653 OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
3efa1cc9 654 "do call-graph (stack chain/backtrace) recording"),
c0555642 655 OPT_INCR('v', "verbose", &verbose,
3da297a6 656 "be more verbose (show counter open errors, etc)"),
b44308f5 657 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
0f82ebc4 658 OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat,
649c48a9 659 "per thread counts"),
0f82ebc4 660 OPT_BOOLEAN('d', "data", &record_opts.sample_address,
4bba828d 661 "Sample addresses"),
0f82ebc4
ACM
662 OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"),
663 OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples,
649c48a9 664 "don't sample"),
baa2f6ce 665 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
a1ac1d3c 666 "do not update the buildid cache"),
baa2f6ce
ACM
667 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
668 "do not collect buildids in perf.data"),
023695d9
SE
669 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
670 "monitor event in cgroup name only",
671 parse_cgroups),
0e9b20b8
IM
672 OPT_END()
673};
674
f37a291c 675int cmd_record(int argc, const char **argv, const char *prefix __used)
0e9b20b8 676{
69aad6f1
ACM
677 int err = -ENOMEM;
678 struct perf_evsel *pos;
0e9b20b8 679
fbe96f29
SE
680 perf_header__set_cmdline(argc, argv);
681
7e2ed097 682 evsel_list = perf_evlist__new(NULL, NULL);
361c99a6
ACM
683 if (evsel_list == NULL)
684 return -ENOMEM;
685
bca647aa 686 argc = parse_options(argc, argv, record_options, record_usage,
655000e7 687 PARSE_OPT_STOP_AT_NON_OPTION);
0f82ebc4
ACM
688 if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 &&
689 !record_opts.system_wide && !record_opts.cpu_list)
bca647aa 690 usage_with_options(record_usage, record_options);
0e9b20b8 691
7865e817
FW
692 if (force && append_file) {
693 fprintf(stderr, "Can't overwrite and append at the same time."
694 " You need to choose between -f and -A");
bca647aa 695 usage_with_options(record_usage, record_options);
7865e817
FW
696 } else if (append_file) {
697 write_mode = WRITE_APPEND;
698 } else {
699 write_mode = WRITE_FORCE;
700 }
701
0f82ebc4 702 if (nr_cgroups && !record_opts.system_wide) {
023695d9
SE
703 fprintf(stderr, "cgroup monitoring only available in"
704 " system-wide mode\n");
705 usage_with_options(record_usage, record_options);
706 }
707
655000e7 708 symbol__init();
baa2f6ce 709
ec80fde7 710 if (symbol_conf.kptr_restrict)
646aaea6
ACM
711 pr_warning(
712"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
713"check /proc/sys/kernel/kptr_restrict.\n\n"
714"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
715"file is not found in the buildid cache or in the vmlinux path.\n\n"
716"Samples in kernel modules won't be resolved at all.\n\n"
717"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
718"even with a suitable vmlinux or kallsyms file.\n\n");
ec80fde7 719
baa2f6ce 720 if (no_buildid_cache || no_buildid)
a1ac1d3c 721 disable_buildid_cache();
655000e7 722
361c99a6
ACM
723 if (evsel_list->nr_entries == 0 &&
724 perf_evlist__add_default(evsel_list) < 0) {
69aad6f1
ACM
725 pr_err("Not enough memory for event selector list\n");
726 goto out_symbol_exit;
bbd36e5e 727 }
0e9b20b8 728
0f82ebc4
ACM
729 if (record_opts.target_pid != -1)
730 record_opts.target_tid = record_opts.target_pid;
d6d901c2 731
0f82ebc4
ACM
732 if (perf_evlist__create_maps(evsel_list, record_opts.target_pid,
733 record_opts.target_tid, record_opts.cpu_list) < 0)
dd7927f4 734 usage_with_options(record_usage, record_options);
69aad6f1 735
361c99a6 736 list_for_each_entry(pos, &evsel_list->entries, node) {
7e2ed097
ACM
737 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
738 evsel_list->threads->nr) < 0)
69aad6f1 739 goto out_free_fd;
ad7f4e3f
ACM
740 if (perf_header__push_event(pos->attr.config, event_name(pos)))
741 goto out_free_fd;
d6d901c2 742 }
5c581041 743
7e2ed097 744 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
39d17dac 745 goto out_free_fd;
d6d901c2 746
0f82ebc4
ACM
747 if (record_opts.user_interval != ULLONG_MAX)
748 record_opts.default_interval = record_opts.user_interval;
749 if (record_opts.user_freq != UINT_MAX)
750 record_opts.freq = record_opts.user_freq;
f9212819 751
7e4ff9e3
MG
752 /*
753 * User specified count overrides default frequency.
754 */
0f82ebc4
ACM
755 if (record_opts.default_interval)
756 record_opts.freq = 0;
757 else if (record_opts.freq) {
758 record_opts.default_interval = record_opts.freq;
7e4ff9e3
MG
759 } else {
760 fprintf(stderr, "frequency and count are zero, aborting\n");
39d17dac 761 err = -EINVAL;
5c581041 762 goto out_free_fd;
7e4ff9e3
MG
763 }
764
39d17dac 765 err = __cmd_record(argc, argv);
39d17dac 766out_free_fd:
7e2ed097 767 perf_evlist__delete_maps(evsel_list);
d65a458b
ACM
768out_symbol_exit:
769 symbol__exit();
39d17dac 770 return err;
0e9b20b8 771}
This page took 0.148864 seconds and 5 git commands to generate.