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