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