aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c483
1 files changed, 235 insertions, 248 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a4be453fc8a9..f1411e9cdf47 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -5,10 +5,13 @@
5 * (or a CPU, or a PID) into the perf.data output file - for 5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report. 6 * later analysis via perf report.
7 */ 7 */
8#define _FILE_OFFSET_BITS 64
9
8#include "builtin.h" 10#include "builtin.h"
9 11
10#include "perf.h" 12#include "perf.h"
11 13
14#include "util/build-id.h"
12#include "util/util.h" 15#include "util/util.h"
13#include "util/parse-options.h" 16#include "util/parse-options.h"
14#include "util/parse-events.h" 17#include "util/parse-events.h"
@@ -17,55 +20,55 @@
17#include "util/header.h" 20#include "util/header.h"
18#include "util/event.h" 21#include "util/event.h"
19#include "util/debug.h" 22#include "util/debug.h"
20#include "util/trace-event.h" 23#include "util/session.h"
24#include "util/symbol.h"
25#include "util/cpumap.h"
21 26
22#include <unistd.h> 27#include <unistd.h>
23#include <sched.h> 28#include <sched.h>
24 29
25#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
26#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27
28static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 30static int fd[MAX_NR_CPUS][MAX_COUNTERS];
29 31
30static long default_interval = 100000; 32static long default_interval = 0;
31 33
32static int nr_cpus = 0; 34static int nr_cpus = 0;
33static unsigned int page_size; 35static unsigned int page_size;
34static unsigned int mmap_pages = 128; 36static unsigned int mmap_pages = 128;
35static int freq = 0; 37static int freq = 1000;
36static int output; 38static int output;
37static const char *output_name = "perf.data"; 39static const char *output_name = "perf.data";
38static int group = 0; 40static int group = 0;
39static unsigned int realtime_prio = 0; 41static unsigned int realtime_prio = 0;
40static int raw_samples = 0; 42static int raw_samples = 0;
41static int system_wide = 0; 43static int system_wide = 0;
42static int profile_cpu = -1; 44static int profile_cpu = -1;
43static pid_t target_pid = -1; 45static pid_t target_pid = -1;
44static pid_t child_pid = -1; 46static pid_t child_pid = -1;
45static int inherit = 1; 47static int inherit = 1;
46static int force = 0; 48static int force = 0;
47static int append_file = 0; 49static int append_file = 0;
48static int call_graph = 0; 50static int call_graph = 0;
49static int inherit_stat = 0; 51static int inherit_stat = 0;
50static int no_samples = 0; 52static int no_samples = 0;
51static int sample_address = 0; 53static int sample_address = 0;
52static int multiplex = 0; 54static int multiplex = 0;
53static int multiplex_fd = -1; 55static int multiplex_fd = -1;
54 56
55static long samples; 57static long samples = 0;
56static struct timeval last_read; 58static struct timeval last_read;
57static struct timeval this_read; 59static struct timeval this_read;
58 60
59static u64 bytes_written; 61static u64 bytes_written = 0;
60 62
61static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; 63static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
62 64
63static int nr_poll; 65static int nr_poll = 0;
64static int nr_cpu; 66static int nr_cpu = 0;
65 67
66static int file_new = 1; 68static int file_new = 1;
69static off_t post_processing_offset;
67 70
68struct perf_header *header; 71static struct perf_session *session;
69 72
70struct mmap_data { 73struct mmap_data {
71 int counter; 74 int counter;
@@ -113,6 +116,13 @@ static void write_output(void *buf, size_t size)
113 } 116 }
114} 117}
115 118
119static int process_synthesized_event(event_t *event,
120 struct perf_session *self __used)
121{
122 write_output(event, event->header.size);
123 return 0;
124}
125
116static void mmap_read(struct mmap_data *md) 126static void mmap_read(struct mmap_data *md)
117{ 127{
118 unsigned int head = mmap_read_head(md); 128 unsigned int head = mmap_read_head(md);
@@ -195,179 +205,21 @@ static void sig_atexit(void)
195 kill(getpid(), signr); 205 kill(getpid(), signr);
196} 206}
197 207
198static pid_t pid_synthesize_comm_event(pid_t pid, int full)
199{
200 struct comm_event comm_ev;
201 char filename[PATH_MAX];
202 char bf[BUFSIZ];
203 FILE *fp;
204 size_t size = 0;
205 DIR *tasks;
206 struct dirent dirent, *next;
207 pid_t tgid = 0;
208
209 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
210
211 fp = fopen(filename, "r");
212 if (fp == NULL) {
213 /*
214 * We raced with a task exiting - just return:
215 */
216 if (verbose)
217 fprintf(stderr, "couldn't open %s\n", filename);
218 return 0;
219 }
220
221 memset(&comm_ev, 0, sizeof(comm_ev));
222 while (!comm_ev.comm[0] || !comm_ev.pid) {
223 if (fgets(bf, sizeof(bf), fp) == NULL)
224 goto out_failure;
225
226 if (memcmp(bf, "Name:", 5) == 0) {
227 char *name = bf + 5;
228 while (*name && isspace(*name))
229 ++name;
230 size = strlen(name) - 1;
231 memcpy(comm_ev.comm, name, size++);
232 } else if (memcmp(bf, "Tgid:", 5) == 0) {
233 char *tgids = bf + 5;
234 while (*tgids && isspace(*tgids))
235 ++tgids;
236 tgid = comm_ev.pid = atoi(tgids);
237 }
238 }
239
240 comm_ev.header.type = PERF_RECORD_COMM;
241 size = ALIGN(size, sizeof(u64));
242 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
243
244 if (!full) {
245 comm_ev.tid = pid;
246
247 write_output(&comm_ev, comm_ev.header.size);
248 goto out_fclose;
249 }
250
251 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
252
253 tasks = opendir(filename);
254 while (!readdir_r(tasks, &dirent, &next) && next) {
255 char *end;
256 pid = strtol(dirent.d_name, &end, 10);
257 if (*end)
258 continue;
259
260 comm_ev.tid = pid;
261
262 write_output(&comm_ev, comm_ev.header.size);
263 }
264 closedir(tasks);
265
266out_fclose:
267 fclose(fp);
268 return tgid;
269
270out_failure:
271 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
272 filename);
273 exit(EXIT_FAILURE);
274}
275
276static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
277{
278 char filename[PATH_MAX];
279 FILE *fp;
280
281 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
282
283 fp = fopen(filename, "r");
284 if (fp == NULL) {
285 /*
286 * We raced with a task exiting - just return:
287 */
288 if (verbose)
289 fprintf(stderr, "couldn't open %s\n", filename);
290 return;
291 }
292 while (1) {
293 char bf[BUFSIZ], *pbf = bf;
294 struct mmap_event mmap_ev = {
295 .header = { .type = PERF_RECORD_MMAP },
296 };
297 int n;
298 size_t size;
299 if (fgets(bf, sizeof(bf), fp) == NULL)
300 break;
301
302 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
303 n = hex2u64(pbf, &mmap_ev.start);
304 if (n < 0)
305 continue;
306 pbf += n + 1;
307 n = hex2u64(pbf, &mmap_ev.len);
308 if (n < 0)
309 continue;
310 pbf += n + 3;
311 if (*pbf == 'x') { /* vm_exec */
312 char *execname = strchr(bf, '/');
313
314 /* Catch VDSO */
315 if (execname == NULL)
316 execname = strstr(bf, "[vdso]");
317
318 if (execname == NULL)
319 continue;
320
321 size = strlen(execname);
322 execname[size - 1] = '\0'; /* Remove \n */
323 memcpy(mmap_ev.filename, execname, size);
324 size = ALIGN(size, sizeof(u64));
325 mmap_ev.len -= mmap_ev.start;
326 mmap_ev.header.size = (sizeof(mmap_ev) -
327 (sizeof(mmap_ev.filename) - size));
328 mmap_ev.pid = tgid;
329 mmap_ev.tid = pid;
330
331 write_output(&mmap_ev, mmap_ev.header.size);
332 }
333 }
334
335 fclose(fp);
336}
337
338static void synthesize_all(void)
339{
340 DIR *proc;
341 struct dirent dirent, *next;
342
343 proc = opendir("/proc");
344
345 while (!readdir_r(proc, &dirent, &next) && next) {
346 char *end;
347 pid_t pid, tgid;
348
349 pid = strtol(dirent.d_name, &end, 10);
350 if (*end) /* only interested in proper numerical dirents */
351 continue;
352
353 tgid = pid_synthesize_comm_event(pid, 1);
354 pid_synthesize_mmap_samples(pid, tgid);
355 }
356
357 closedir(proc);
358}
359
360static int group_fd; 208static int group_fd;
361 209
362static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr) 210static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
363{ 211{
364 struct perf_header_attr *h_attr; 212 struct perf_header_attr *h_attr;
365 213
366 if (nr < header->attrs) { 214 if (nr < session->header.attrs) {
367 h_attr = header->attr[nr]; 215 h_attr = session->header.attr[nr];
368 } else { 216 } else {
369 h_attr = perf_header_attr__new(a); 217 h_attr = perf_header_attr__new(a);
370 perf_header__add_attr(header, h_attr); 218 if (h_attr != NULL)
219 if (perf_header__add_attr(&session->header, h_attr) < 0) {
220 perf_header_attr__delete(h_attr);
221 h_attr = NULL;
222 }
371 } 223 }
372 224
373 return h_attr; 225 return h_attr;
@@ -375,9 +227,11 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
375 227
376static void create_counter(int counter, int cpu, pid_t pid) 228static void create_counter(int counter, int cpu, pid_t pid)
377{ 229{
230 char *filter = filters[counter];
378 struct perf_event_attr *attr = attrs + counter; 231 struct perf_event_attr *attr = attrs + counter;
379 struct perf_header_attr *h_attr; 232 struct perf_header_attr *h_attr;
380 int track = !counter; /* only the first counter needs these */ 233 int track = !counter; /* only the first counter needs these */
234 int ret;
381 struct { 235 struct {
382 u64 count; 236 u64 count;
383 u64 time_enabled; 237 u64 time_enabled;
@@ -391,6 +245,9 @@ static void create_counter(int counter, int cpu, pid_t pid)
391 245
392 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 246 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
393 247
248 if (nr_counters > 1)
249 attr->sample_type |= PERF_SAMPLE_ID;
250
394 if (freq) { 251 if (freq) {
395 attr->sample_type |= PERF_SAMPLE_PERIOD; 252 attr->sample_type |= PERF_SAMPLE_PERIOD;
396 attr->freq = 1; 253 attr->freq = 1;
@@ -417,7 +274,7 @@ static void create_counter(int counter, int cpu, pid_t pid)
417 274
418 attr->mmap = track; 275 attr->mmap = track;
419 attr->comm = track; 276 attr->comm = track;
420 attr->inherit = (cpu < 0) && inherit; 277 attr->inherit = inherit;
421 attr->disabled = 1; 278 attr->disabled = 1;
422 279
423try_again: 280try_again:
@@ -448,11 +305,19 @@ try_again:
448 printf("\n"); 305 printf("\n");
449 error("perfcounter syscall returned with %d (%s)\n", 306 error("perfcounter syscall returned with %d (%s)\n",
450 fd[nr_cpu][counter], strerror(err)); 307 fd[nr_cpu][counter], strerror(err));
308
309#if defined(__i386__) || defined(__x86_64__)
310 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
311 die("No hardware sampling interrupt available. No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.\n");
312#endif
313
451 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 314 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
452 exit(-1); 315 exit(-1);
453 } 316 }
454 317
455 h_attr = get_header_attr(attr, counter); 318 h_attr = get_header_attr(attr, counter);
319 if (h_attr == NULL)
320 die("nomem\n");
456 321
457 if (!file_new) { 322 if (!file_new) {
458 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { 323 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
@@ -466,7 +331,10 @@ try_again:
466 exit(-1); 331 exit(-1);
467 } 332 }
468 333
469 perf_header_attr__add_id(h_attr, read_data.id); 334 if (perf_header_attr__add_id(h_attr, read_data.id) < 0) {
335 pr_warning("Not enough memory to add id\n");
336 exit(-1);
337 }
470 338
471 assert(fd[nr_cpu][counter] >= 0); 339 assert(fd[nr_cpu][counter] >= 0);
472 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); 340 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
@@ -480,7 +348,6 @@ try_again:
480 multiplex_fd = fd[nr_cpu][counter]; 348 multiplex_fd = fd[nr_cpu][counter];
481 349
482 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { 350 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) {
483 int ret;
484 351
485 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); 352 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd);
486 assert(ret != -1); 353 assert(ret != -1);
@@ -500,6 +367,16 @@ try_again:
500 } 367 }
501 } 368 }
502 369
370 if (filter != NULL) {
371 ret = ioctl(fd[nr_cpu][counter],
372 PERF_EVENT_IOC_SET_FILTER, filter);
373 if (ret) {
374 error("failed to set filter with %d (%s)\n", errno,
375 strerror(errno));
376 exit(-1);
377 }
378 }
379
503 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); 380 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE);
504} 381}
505 382
@@ -514,11 +391,25 @@ static void open_counters(int cpu, pid_t pid)
514 nr_cpu++; 391 nr_cpu++;
515} 392}
516 393
394static int process_buildids(void)
395{
396 u64 size = lseek(output, 0, SEEK_CUR);
397
398 if (size == 0)
399 return 0;
400
401 session->fd = output;
402 return __perf_session__process_events(session, post_processing_offset,
403 size - post_processing_offset,
404 size, &build_id__mark_dso_hit_ops);
405}
406
517static void atexit_header(void) 407static void atexit_header(void)
518{ 408{
519 header->data_size += bytes_written; 409 session->header.data_size += bytes_written;
520 410
521 perf_header__write(header, output); 411 process_buildids();
412 perf_header__write(&session->header, output, true);
522} 413}
523 414
524static int __cmd_record(int argc, const char **argv) 415static int __cmd_record(int argc, const char **argv)
@@ -527,23 +418,37 @@ static int __cmd_record(int argc, const char **argv)
527 struct stat st; 418 struct stat st;
528 pid_t pid = 0; 419 pid_t pid = 0;
529 int flags; 420 int flags;
530 int ret; 421 int err;
531 unsigned long waking = 0; 422 unsigned long waking = 0;
423 int child_ready_pipe[2], go_pipe[2];
424 const bool forks = target_pid == -1 && argc > 0;
425 char buf;
532 426
533 page_size = sysconf(_SC_PAGE_SIZE); 427 page_size = sysconf(_SC_PAGE_SIZE);
534 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
535 assert(nr_cpus <= MAX_NR_CPUS);
536 assert(nr_cpus >= 0);
537 428
538 atexit(sig_atexit); 429 atexit(sig_atexit);
539 signal(SIGCHLD, sig_handler); 430 signal(SIGCHLD, sig_handler);
540 signal(SIGINT, sig_handler); 431 signal(SIGINT, sig_handler);
541 432
433 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
434 perror("failed to create pipes");
435 exit(-1);
436 }
437
542 if (!stat(output_name, &st) && st.st_size) { 438 if (!stat(output_name, &st) && st.st_size) {
543 if (!force && !append_file) { 439 if (!force) {
544 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 440 if (!append_file) {
545 output_name); 441 pr_err("Error, output file %s exists, use -A "
546 exit(-1); 442 "to append or -f to overwrite.\n",
443 output_name);
444 exit(-1);
445 }
446 } else {
447 char oldname[PATH_MAX];
448 snprintf(oldname, sizeof(oldname), "%s.old",
449 output_name);
450 unlink(oldname);
451 rename(output_name, oldname);
547 } 452 }
548 } else { 453 } else {
549 append_file = 0; 454 append_file = 0;
@@ -561,73 +466,139 @@ static int __cmd_record(int argc, const char **argv)
561 exit(-1); 466 exit(-1);
562 } 467 }
563 468
564 if (!file_new) 469 session = perf_session__new(output_name, O_WRONLY, force);
565 header = perf_header__read(output); 470 if (session == NULL) {
566 else 471 pr_err("Not enough memory for reading perf file header\n");
567 header = perf_header__new(); 472 return -1;
473 }
568 474
475 if (!file_new) {
476 err = perf_header__read(&session->header, output);
477 if (err < 0)
478 return err;
479 }
569 480
570 if (raw_samples) { 481 if (raw_samples) {
571 read_tracing_data(attrs, nr_counters); 482 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
572 } else { 483 } else {
573 for (i = 0; i < nr_counters; i++) { 484 for (i = 0; i < nr_counters; i++) {
574 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 485 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
575 read_tracing_data(attrs, nr_counters); 486 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
576 break; 487 break;
577 } 488 }
578 } 489 }
579 } 490 }
491
580 atexit(atexit_header); 492 atexit(atexit_header);
581 493
582 if (!system_wide) { 494 if (forks) {
583 pid = target_pid; 495 pid = fork();
584 if (pid == -1) 496 if (pid < 0) {
585 pid = getpid(); 497 perror("failed to fork");
498 exit(-1);
499 }
586 500
587 open_counters(profile_cpu, pid); 501 if (!pid) {
588 } else { 502 close(child_ready_pipe[0]);
589 if (profile_cpu != -1) { 503 close(go_pipe[1]);
590 open_counters(profile_cpu, target_pid); 504 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
591 } else { 505
592 for (i = 0; i < nr_cpus; i++) 506 /*
593 open_counters(i, target_pid); 507 * Do a dummy execvp to get the PLT entry resolved,
508 * so we avoid the resolver overhead on the real
509 * execvp call.
510 */
511 execvp("", (char **)argv);
512
513 /*
514 * Tell the parent we're ready to go
515 */
516 close(child_ready_pipe[1]);
517
518 /*
519 * Wait until the parent tells us to go.
520 */
521 if (read(go_pipe[0], &buf, 1) == -1)
522 perror("unable to read pipe");
523
524 execvp(argv[0], (char **)argv);
525
526 perror(argv[0]);
527 exit(-1);
528 }
529
530 child_pid = pid;
531
532 if (!system_wide)
533 target_pid = pid;
534
535 close(child_ready_pipe[1]);
536 close(go_pipe[0]);
537 /*
538 * wait for child to settle
539 */
540 if (read(child_ready_pipe[0], &buf, 1) == -1) {
541 perror("unable to read pipe");
542 exit(-1);
594 } 543 }
544 close(child_ready_pipe[0]);
595 } 545 }
596 546
597 if (file_new)
598 perf_header__write(header, output);
599 547
600 if (!system_wide) { 548 if ((!system_wide && !inherit) || profile_cpu != -1) {
601 pid_t tgid = pid_synthesize_comm_event(pid, 0); 549 open_counters(profile_cpu, target_pid);
602 pid_synthesize_mmap_samples(pid, tgid); 550 } else {
603 } else 551 nr_cpus = read_cpu_map();
604 synthesize_all(); 552 for (i = 0; i < nr_cpus; i++)
553 open_counters(cpumap[i], target_pid);
554 }
605 555
606 if (target_pid == -1 && argc) { 556 if (file_new) {
607 pid = fork(); 557 err = perf_header__write(&session->header, output, false);
608 if (pid < 0) 558 if (err < 0)
609 perror("failed to fork"); 559 return err;
560 }
610 561
611 if (!pid) { 562 post_processing_offset = lseek(output, 0, SEEK_CUR);
612 if (execvp(argv[0], (char **)argv)) {
613 perror(argv[0]);
614 exit(-1);
615 }
616 }
617 563
618 child_pid = pid; 564 err = event__synthesize_kernel_mmap(process_synthesized_event,
565 session, "_text");
566 if (err < 0)
567 err = event__synthesize_kernel_mmap(process_synthesized_event,
568 session, "_stext");
569 if (err < 0) {
570 pr_err("Couldn't record kernel reference relocation symbol.\n");
571 return err;
572 }
573
574 err = event__synthesize_modules(process_synthesized_event, session);
575 if (err < 0) {
576 pr_err("Couldn't record kernel reference relocation symbol.\n");
577 return err;
619 } 578 }
620 579
580 if (!system_wide && profile_cpu == -1)
581 event__synthesize_thread(target_pid, process_synthesized_event,
582 session);
583 else
584 event__synthesize_threads(process_synthesized_event, session);
585
621 if (realtime_prio) { 586 if (realtime_prio) {
622 struct sched_param param; 587 struct sched_param param;
623 588
624 param.sched_priority = realtime_prio; 589 param.sched_priority = realtime_prio;
625 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 590 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
626 printf("Could not set realtime priority.\n"); 591 pr_err("Could not set realtime priority.\n");
627 exit(-1); 592 exit(-1);
628 } 593 }
629 } 594 }
630 595
596 /*
597 * Let the child rip
598 */
599 if (forks)
600 close(go_pipe[1]);
601
631 for (;;) { 602 for (;;) {
632 int hits = samples; 603 int hits = samples;
633 604
@@ -641,7 +612,7 @@ static int __cmd_record(int argc, const char **argv)
641 if (hits == samples) { 612 if (hits == samples) {
642 if (done) 613 if (done)
643 break; 614 break;
644 ret = poll(event_array, nr_poll, -1); 615 err = poll(event_array, nr_poll, -1);
645 waking++; 616 waking++;
646 } 617 }
647 618
@@ -677,6 +648,8 @@ static const struct option options[] = {
677 OPT_CALLBACK('e', "event", NULL, "event", 648 OPT_CALLBACK('e', "event", NULL, "event",
678 "event selector. use 'perf list' to list available events", 649 "event selector. use 'perf list' to list available events",
679 parse_events), 650 parse_events),
651 OPT_CALLBACK(0, "filter", NULL, "filter",
652 "event filter", parse_filter),
680 OPT_INTEGER('p', "pid", &target_pid, 653 OPT_INTEGER('p', "pid", &target_pid,
681 "record events on existing pid"), 654 "record events on existing pid"),
682 OPT_INTEGER('r', "realtime", &realtime_prio, 655 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -721,16 +694,30 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
721 int counter; 694 int counter;
722 695
723 argc = parse_options(argc, argv, options, record_usage, 696 argc = parse_options(argc, argv, options, record_usage,
724 PARSE_OPT_STOP_AT_NON_OPTION); 697 PARSE_OPT_STOP_AT_NON_OPTION);
725 if (!argc && target_pid == -1 && !system_wide) 698 if (!argc && target_pid == -1 && !system_wide && profile_cpu == -1)
726 usage_with_options(record_usage, options); 699 usage_with_options(record_usage, options);
727 700
701 symbol__init();
702
728 if (!nr_counters) { 703 if (!nr_counters) {
729 nr_counters = 1; 704 nr_counters = 1;
730 attrs[0].type = PERF_TYPE_HARDWARE; 705 attrs[0].type = PERF_TYPE_HARDWARE;
731 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; 706 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
732 } 707 }
733 708
709 /*
710 * User specified count overrides default frequency.
711 */
712 if (default_interval)
713 freq = 0;
714 else if (freq) {
715 default_interval = freq;
716 } else {
717 fprintf(stderr, "frequency and count are zero, aborting\n");
718 exit(EXIT_FAILURE);
719 }
720
734 for (counter = 0; counter < nr_counters; counter++) { 721 for (counter = 0; counter < nr_counters; counter++) {
735 if (attrs[counter].sample_period) 722 if (attrs[counter].sample_period)
736 continue; 723 continue;