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