186470930SIngo Molnar /* 286470930SIngo Molnar * builtin-record.c 386470930SIngo Molnar * 486470930SIngo Molnar * Builtin record command: Record the profile of a workload 586470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for 686470930SIngo Molnar * later analysis via perf report. 786470930SIngo Molnar */ 8b8f46c5aSXiao Guangrong #define _FILE_OFFSET_BITS 64 9b8f46c5aSXiao Guangrong 1086470930SIngo Molnar #include "builtin.h" 1186470930SIngo Molnar 1286470930SIngo Molnar #include "perf.h" 1386470930SIngo Molnar 146122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1586470930SIngo Molnar #include "util/util.h" 1686470930SIngo Molnar #include "util/parse-options.h" 1786470930SIngo Molnar #include "util/parse-events.h" 1886470930SIngo Molnar 197c6a1c65SPeter Zijlstra #include "util/header.h" 2066e274f3SFrederic Weisbecker #include "util/event.h" 21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 238f28827aSFrederic Weisbecker #include "util/debug.h" 2494c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 27a12b51c4SPaul Mackerras #include "util/cpumap.h" 28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 297c6a1c65SPeter Zijlstra 3086470930SIngo Molnar #include <unistd.h> 3186470930SIngo Molnar #include <sched.h> 32a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3386470930SIngo Molnar 3426d33022SJiri Olsa #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 3526d33022SJiri Olsa 3626d33022SJiri Olsa #ifdef NO_LIBUNWIND_SUPPORT 3726d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp]"; 3826d33022SJiri Olsa #else 3926d33022SJiri Olsa static unsigned long default_stack_dump_size = 8192; 4026d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 4126d33022SJiri Olsa #endif 4226d33022SJiri Olsa 437865e817SFrederic Weisbecker enum write_mode_t { 447865e817SFrederic Weisbecker WRITE_FORCE, 457865e817SFrederic Weisbecker WRITE_APPEND 467865e817SFrederic Weisbecker }; 477865e817SFrederic Weisbecker 48d20deb64SArnaldo Carvalho de Melo struct perf_record { 4945694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 50d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 51d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 52d20deb64SArnaldo Carvalho de Melo const char *output_name; 53d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 54d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 55d20deb64SArnaldo Carvalho de Melo const char *progname; 56d20deb64SArnaldo Carvalho de Melo int output; 57d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 58d20deb64SArnaldo Carvalho de Melo int realtime_prio; 59d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 60d20deb64SArnaldo Carvalho de Melo bool no_buildid; 61d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 62d20deb64SArnaldo Carvalho de Melo bool force; 63d20deb64SArnaldo Carvalho de Melo bool file_new; 64d20deb64SArnaldo Carvalho de Melo bool append_file; 65d20deb64SArnaldo Carvalho de Melo long samples; 66d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 670f82ebc4SArnaldo Carvalho de Melo }; 6886470930SIngo Molnar 69d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 709215545eSTom Zanussi { 71d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 729215545eSTom Zanussi } 739215545eSTom Zanussi 748d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size) 75f5970550SPeter Zijlstra { 76f5970550SPeter Zijlstra while (size) { 77d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 78f5970550SPeter Zijlstra 798d3eca20SDavid Ahern if (ret < 0) { 808d3eca20SDavid Ahern pr_err("failed to write\n"); 818d3eca20SDavid Ahern return -1; 828d3eca20SDavid Ahern } 83f5970550SPeter Zijlstra 84f5970550SPeter Zijlstra size -= ret; 85f5970550SPeter Zijlstra buf += ret; 86f5970550SPeter Zijlstra 87d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 88f5970550SPeter Zijlstra } 898d3eca20SDavid Ahern 908d3eca20SDavid Ahern return 0; 91f5970550SPeter Zijlstra } 92f5970550SPeter Zijlstra 9345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 94d20deb64SArnaldo Carvalho de Melo union perf_event *event, 95*1d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 96*1d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 97234fbbf5SArnaldo Carvalho de Melo { 9845694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 998d3eca20SDavid Ahern if (write_output(rec, event, event->header.size) < 0) 1008d3eca20SDavid Ahern return -1; 1018d3eca20SDavid Ahern 102234fbbf5SArnaldo Carvalho de Melo return 0; 103234fbbf5SArnaldo Carvalho de Melo } 104234fbbf5SArnaldo Carvalho de Melo 1058d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec, 106d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 10786470930SIngo Molnar { 108744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 10986470930SIngo Molnar unsigned int old = md->prev; 110d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 11186470930SIngo Molnar unsigned long size; 11286470930SIngo Molnar void *buf; 1138d3eca20SDavid Ahern int rc = 0; 11486470930SIngo Molnar 115dc82009aSArnaldo Carvalho de Melo if (old == head) 1168d3eca20SDavid Ahern return 0; 11786470930SIngo Molnar 118d20deb64SArnaldo Carvalho de Melo rec->samples++; 11986470930SIngo Molnar 12086470930SIngo Molnar size = head - old; 12186470930SIngo Molnar 12286470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 12386470930SIngo Molnar buf = &data[old & md->mask]; 12486470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 12586470930SIngo Molnar old += size; 12686470930SIngo Molnar 1278d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1288d3eca20SDavid Ahern rc = -1; 1298d3eca20SDavid Ahern goto out; 1308d3eca20SDavid Ahern } 13186470930SIngo Molnar } 13286470930SIngo Molnar 13386470930SIngo Molnar buf = &data[old & md->mask]; 13486470930SIngo Molnar size = head - old; 13586470930SIngo Molnar old += size; 13686470930SIngo Molnar 1378d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1388d3eca20SDavid Ahern rc = -1; 1398d3eca20SDavid Ahern goto out; 1408d3eca20SDavid Ahern } 14186470930SIngo Molnar 14286470930SIngo Molnar md->prev = old; 143115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 1448d3eca20SDavid Ahern 1458d3eca20SDavid Ahern out: 1468d3eca20SDavid Ahern return rc; 14786470930SIngo Molnar } 14886470930SIngo Molnar 14986470930SIngo Molnar static volatile int done = 0; 150f7b7c26eSPeter Zijlstra static volatile int signr = -1; 15133e49ea7SAndi Kleen static volatile int child_finished = 0; 15286470930SIngo Molnar 15386470930SIngo Molnar static void sig_handler(int sig) 15486470930SIngo Molnar { 15533e49ea7SAndi Kleen if (sig == SIGCHLD) 15633e49ea7SAndi Kleen child_finished = 1; 15733e49ea7SAndi Kleen 15886470930SIngo Molnar done = 1; 159f7b7c26eSPeter Zijlstra signr = sig; 160f7b7c26eSPeter Zijlstra } 161f7b7c26eSPeter Zijlstra 162*1d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 163f7b7c26eSPeter Zijlstra { 164d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 16533e49ea7SAndi Kleen int status; 16633e49ea7SAndi Kleen 167d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 16833e49ea7SAndi Kleen if (!child_finished) 169d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 170933da83aSChris Wilson 17133e49ea7SAndi Kleen wait(&status); 17233e49ea7SAndi Kleen if (WIFSIGNALED(status)) 173d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 17433e49ea7SAndi Kleen } 17533e49ea7SAndi Kleen 17618483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 177f7b7c26eSPeter Zijlstra return; 178f7b7c26eSPeter Zijlstra 179f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 180f7b7c26eSPeter Zijlstra kill(getpid(), signr); 18186470930SIngo Molnar } 18286470930SIngo Molnar 183a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 184a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 185a91e5431SArnaldo Carvalho de Melo { 186a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 187a91e5431SArnaldo Carvalho de Melo 188a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 189a91e5431SArnaldo Carvalho de Melo return false; 190a91e5431SArnaldo Carvalho de Melo 1910c21f736SArnaldo Carvalho de Melo pair = perf_evlist__first(other); 192a91e5431SArnaldo Carvalho de Melo 193a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 194a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 195a91e5431SArnaldo Carvalho de Melo return false; 1960c21f736SArnaldo Carvalho de Melo pair = perf_evsel__next(pair); 197a91e5431SArnaldo Carvalho de Melo } 198a91e5431SArnaldo Carvalho de Melo 199a91e5431SArnaldo Carvalho de Melo return true; 200a91e5431SArnaldo Carvalho de Melo } 201a91e5431SArnaldo Carvalho de Melo 2028d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec) 203dd7927f4SArnaldo Carvalho de Melo { 2046a4bb04cSJiri Olsa struct perf_evsel *pos; 205d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 206d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 207d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 2088d3eca20SDavid Ahern int rc = 0; 209dd7927f4SArnaldo Carvalho de Melo 210d20deb64SArnaldo Carvalho de Melo perf_evlist__config_attrs(evlist, opts); 2110f82ebc4SArnaldo Carvalho de Melo 2126a4bb04cSJiri Olsa if (opts->group) 21363dab225SArnaldo Carvalho de Melo perf_evlist__set_leader(evlist); 2146a4bb04cSJiri Olsa 215dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 216dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 217dd7927f4SArnaldo Carvalho de Melo /* 218dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 219dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 220dd7927f4SArnaldo Carvalho de Melo * 221dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 222dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 223dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 224dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 225dd7927f4SArnaldo Carvalho de Melo * 226dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 227dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 228dd7927f4SArnaldo Carvalho de Melo */ 229dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 230dd7927f4SArnaldo Carvalho de Melo 2310c978128SArnaldo Carvalho de Melo fallback_missing_features: 2320c978128SArnaldo Carvalho de Melo if (opts->exclude_guest_missing) 2330c978128SArnaldo Carvalho de Melo attr->exclude_guest = attr->exclude_host = 0; 2349c90a61cSArnaldo Carvalho de Melo retry_sample_id: 235808e1226SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 2363da297a6SIngo Molnar try_again: 2376a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 23886470930SIngo Molnar int err = errno; 23986470930SIngo Molnar 240c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 241b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 2428d3eca20SDavid Ahern rc = -err; 2438d3eca20SDavid Ahern goto out; 244bea03405SNamhyung Kim } else if (err == ENODEV && opts->target.cpu_list) { 2458d3eca20SDavid Ahern pr_err("No such device - did you specify" 246d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2478d3eca20SDavid Ahern rc = -err; 2488d3eca20SDavid Ahern goto out; 2490c978128SArnaldo Carvalho de Melo } else if (err == EINVAL) { 2500c978128SArnaldo Carvalho de Melo if (!opts->exclude_guest_missing && 2510c978128SArnaldo Carvalho de Melo (attr->exclude_guest || attr->exclude_host)) { 2520c978128SArnaldo Carvalho de Melo pr_debug("Old kernel, cannot exclude " 2530c978128SArnaldo Carvalho de Melo "guest or host samples.\n"); 2540c978128SArnaldo Carvalho de Melo opts->exclude_guest_missing = true; 2550c978128SArnaldo Carvalho de Melo goto fallback_missing_features; 256808e1226SArnaldo Carvalho de Melo } else if (!opts->sample_id_all_missing) { 2579c90a61cSArnaldo Carvalho de Melo /* 2589c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2599c90a61cSArnaldo Carvalho de Melo */ 260808e1226SArnaldo Carvalho de Melo opts->sample_id_all_missing = true; 261d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 262eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 263eac23d1cSIan Munsie 2649c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 265d6d901c2SZhang, Yanmin } 2660c978128SArnaldo Carvalho de Melo } 2673da297a6SIngo Molnar 2683da297a6SIngo Molnar /* 2693da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2703da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 271028d455bSDavid Ahern * is always available even if no PMU support. 272028d455bSDavid Ahern * 273028d455bSDavid Ahern * PPC returns ENXIO until 2.6.37 (behavior changed 274028d455bSDavid Ahern * with commit b0a873e). 2753da297a6SIngo Molnar */ 276028d455bSDavid Ahern if ((err == ENOENT || err == ENXIO) 277028d455bSDavid Ahern && attr->type == PERF_TYPE_HARDWARE 278f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2793da297a6SIngo Molnar 2803da297a6SIngo Molnar if (verbose) 281ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 282ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2833da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 284f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 285d1cae34dSDavid Ahern if (pos->name) { 286d1cae34dSDavid Ahern free(pos->name); 287d1cae34dSDavid Ahern pos->name = NULL; 288d1cae34dSDavid Ahern } 2893da297a6SIngo Molnar goto try_again; 2903da297a6SIngo Molnar } 291ca6a4258SDavid Ahern 292ca6a4258SDavid Ahern if (err == ENOENT) { 2933780f488SNamhyung Kim ui__error("The %s event is not supported.\n", 2947289f83cSArnaldo Carvalho de Melo perf_evsel__name(pos)); 2958d3eca20SDavid Ahern rc = -err; 2968d3eca20SDavid Ahern goto out; 297ca6a4258SDavid Ahern } 298ca6a4258SDavid Ahern 29930c806a0SIngo Molnar printf("\n"); 300d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 301dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 302bfd45118SSimon Kaempflein 303bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 3048d3eca20SDavid Ahern if (attr->type == PERF_TYPE_HARDWARE && 3058d3eca20SDavid Ahern err == EOPNOTSUPP) { 3068d3eca20SDavid Ahern pr_err("No hardware sampling interrupt available." 307d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 308d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 309d6d901c2SZhang, Yanmin " force-enable it.\n"); 3108d3eca20SDavid Ahern rc = -err; 3118d3eca20SDavid Ahern goto out; 3128d3eca20SDavid Ahern } 313bfd45118SSimon Kaempflein #endif 314bfd45118SSimon Kaempflein 3158d3eca20SDavid Ahern pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 3168d3eca20SDavid Ahern rc = -err; 3178d3eca20SDavid Ahern goto out; 3187c6a1c65SPeter Zijlstra } 3197c6a1c65SPeter Zijlstra } 3207c6a1c65SPeter Zijlstra 3210a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 3220a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 3230a102479SFrederic Weisbecker strerror(errno)); 3248d3eca20SDavid Ahern rc = -1; 3258d3eca20SDavid Ahern goto out; 3260a102479SFrederic Weisbecker } 3270a102479SFrederic Weisbecker 32818e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 3298d3eca20SDavid Ahern if (errno == EPERM) { 3308d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 33118e60939SNelson Elhage "Consider increasing " 33218e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 33318e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 33418e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 3358d3eca20SDavid Ahern rc = -errno; 3368d3eca20SDavid Ahern } else if (!is_power_of_2(opts->mmap_pages)) { 3378d3eca20SDavid Ahern pr_err("--mmap_pages/-m value must be a power of two."); 3388d3eca20SDavid Ahern rc = -EINVAL; 3398d3eca20SDavid Ahern } else { 3408d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 3418d3eca20SDavid Ahern rc = -errno; 3428d3eca20SDavid Ahern } 3438d3eca20SDavid Ahern goto out; 34418e60939SNelson Elhage } 3450a27d7f9SArnaldo Carvalho de Melo 346d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 347a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 348a91e5431SArnaldo Carvalho de Melo else { 349a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 350a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 3518d3eca20SDavid Ahern rc = -1; 3528d3eca20SDavid Ahern goto out; 353dd7927f4SArnaldo Carvalho de Melo } 35486470930SIngo Molnar } 35586470930SIngo Molnar 3567b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3578d3eca20SDavid Ahern out: 3588d3eca20SDavid Ahern return rc; 359a91e5431SArnaldo Carvalho de Melo } 360a91e5431SArnaldo Carvalho de Melo 361d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3626122e4e4SArnaldo Carvalho de Melo { 363d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3646122e4e4SArnaldo Carvalho de Melo 3659f591fd7SArnaldo Carvalho de Melo if (size == 0) 3669f591fd7SArnaldo Carvalho de Melo return 0; 3679f591fd7SArnaldo Carvalho de Melo 368d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 369d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 370d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3716122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3726122e4e4SArnaldo Carvalho de Melo } 3736122e4e4SArnaldo Carvalho de Melo 3748d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 375f5970550SPeter Zijlstra { 376d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 377f5970550SPeter Zijlstra 3788d3eca20SDavid Ahern if (status != 0) 3798d3eca20SDavid Ahern return; 3808d3eca20SDavid Ahern 381d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 382d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 383d20deb64SArnaldo Carvalho de Melo 384d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 385d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 386d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 387d20deb64SArnaldo Carvalho de Melo rec->output, true); 388d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 389d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 390d65a458bSArnaldo Carvalho de Melo symbol__exit(); 391c7929e47STom Zanussi } 392f5970550SPeter Zijlstra } 393f5970550SPeter Zijlstra 3948115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 395a1645ce1SZhang, Yanmin { 396a1645ce1SZhang, Yanmin int err; 39745694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 398a1645ce1SZhang, Yanmin 39923346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 400a1645ce1SZhang, Yanmin return; 401a1645ce1SZhang, Yanmin 402a1645ce1SZhang, Yanmin /* 403a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 404a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 405a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 406a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 407a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 408a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 409a1645ce1SZhang, Yanmin */ 41045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 411743eb868SArnaldo Carvalho de Melo machine); 412a1645ce1SZhang, Yanmin if (err < 0) 413a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 41423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 415a1645ce1SZhang, Yanmin 416a1645ce1SZhang, Yanmin /* 417a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 418a1645ce1SZhang, Yanmin * have no _text sometimes. 419a1645ce1SZhang, Yanmin */ 42045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 421743eb868SArnaldo Carvalho de Melo machine, "_text"); 422a1645ce1SZhang, Yanmin if (err < 0) 42345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 424743eb868SArnaldo Carvalho de Melo machine, "_stext"); 425a1645ce1SZhang, Yanmin if (err < 0) 426a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 42723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 428a1645ce1SZhang, Yanmin } 429a1645ce1SZhang, Yanmin 43098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 43198402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 43298402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 43398402807SFrederic Weisbecker }; 43498402807SFrederic Weisbecker 4358d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 43698402807SFrederic Weisbecker { 4370e2e63ddSPeter Zijlstra int i; 4388d3eca20SDavid Ahern int rc = 0; 43998402807SFrederic Weisbecker 440d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 4418d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 4428d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 4438d3eca20SDavid Ahern rc = -1; 4448d3eca20SDavid Ahern goto out; 4458d3eca20SDavid Ahern } 4468d3eca20SDavid Ahern } 44798402807SFrederic Weisbecker } 44898402807SFrederic Weisbecker 4492eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 4508d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 4518d3eca20SDavid Ahern sizeof(finished_round_event)); 4528d3eca20SDavid Ahern 4538d3eca20SDavid Ahern out: 4548d3eca20SDavid Ahern return rc; 45598402807SFrederic Weisbecker } 45698402807SFrederic Weisbecker 457d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 45886470930SIngo Molnar { 45986470930SIngo Molnar struct stat st; 46086470930SIngo Molnar int flags; 461781ba9d2SRobert Richter int err, output, feat; 4628b412664SPeter Zijlstra unsigned long waking = 0; 46346be604bSZhang, Yanmin const bool forks = argc > 0; 46423346f21SArnaldo Carvalho de Melo struct machine *machine; 46545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 466d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 467d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 468d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 469d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 47086470930SIngo Molnar 471d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 47233e49ea7SAndi Kleen 473d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 47486470930SIngo Molnar 475d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 476f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 477f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 47818483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 479f5970550SPeter Zijlstra 480d7065adbSFranck Bui-Huu if (!output_name) { 481d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 482d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 483d7065adbSFranck Bui-Huu else 484d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 485d7065adbSFranck Bui-Huu } 486d7065adbSFranck Bui-Huu if (output_name) { 487529870e3STom Zanussi if (!strcmp(output_name, "-")) 488d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 489529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 490d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 491b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 492b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 493b38d3464SArnaldo Carvalho de Melo output_name); 494b38d3464SArnaldo Carvalho de Melo unlink(oldname); 495b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 496b38d3464SArnaldo Carvalho de Melo } 497d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 498d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 499266e0e21SPierre Habouzit } 500d7065adbSFranck Bui-Huu } 50186470930SIngo Molnar 502f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 503d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 504d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 50586470930SIngo Molnar else 50686470930SIngo Molnar flags |= O_TRUNC; 50786470930SIngo Molnar 508d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 509529870e3STom Zanussi output = STDOUT_FILENO; 510529870e3STom Zanussi else 51186470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 51286470930SIngo Molnar if (output < 0) { 51386470930SIngo Molnar perror("failed to create output file"); 5148d3eca20SDavid Ahern return -1; 51586470930SIngo Molnar } 51686470930SIngo Molnar 517d20deb64SArnaldo Carvalho de Melo rec->output = output; 518d20deb64SArnaldo Carvalho de Melo 5197865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 520d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 52194c744b6SArnaldo Carvalho de Melo if (session == NULL) { 522a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 523a9a70bbcSArnaldo Carvalho de Melo return -1; 524a9a70bbcSArnaldo Carvalho de Melo } 525a9a70bbcSArnaldo Carvalho de Melo 526d20deb64SArnaldo Carvalho de Melo rec->session = session; 527d20deb64SArnaldo Carvalho de Melo 528781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 529781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 530781ba9d2SRobert Richter 531781ba9d2SRobert Richter if (rec->no_buildid) 532781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 533781ba9d2SRobert Richter 534781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 5352eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 536baa2f6ceSArnaldo Carvalho de Melo 537330aa675SStephane Eranian if (!rec->opts.branch_stack) 538330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 539330aa675SStephane Eranian 540d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 541a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 5424dc0a04bSArnaldo Carvalho de Melo if (err < 0) 54339d17dacSArnaldo Carvalho de Melo goto out_delete_session; 5444dc0a04bSArnaldo Carvalho de Melo } 5454dc0a04bSArnaldo Carvalho de Melo 546d4db3f16SArnaldo Carvalho de Melo if (forks) { 547d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 54835b9d88eSArnaldo Carvalho de Melo if (err < 0) { 54935b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 55035b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 551856e9660SPeter Zijlstra } 552856e9660SPeter Zijlstra } 553856e9660SPeter Zijlstra 5548d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 5558d3eca20SDavid Ahern err = -1; 5568d3eca20SDavid Ahern goto out_delete_session; 5578d3eca20SDavid Ahern } 55886470930SIngo Molnar 559712a4b60SArnaldo Carvalho de Melo /* 560d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 561712a4b60SArnaldo Carvalho de Melo */ 562d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 563712a4b60SArnaldo Carvalho de Melo 564d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 565529870e3STom Zanussi err = perf_header__write_pipe(output); 566529870e3STom Zanussi if (err < 0) 5678d3eca20SDavid Ahern goto out_delete_session; 568d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 569a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 570361c99a6SArnaldo Carvalho de Melo output, false); 571d5eed904SArnaldo Carvalho de Melo if (err < 0) 5728d3eca20SDavid Ahern goto out_delete_session; 573d5eed904SArnaldo Carvalho de Melo } 5747c6a1c65SPeter Zijlstra 575d3665498SDavid Ahern if (!rec->no_buildid 576e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 577d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 578e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5798d3eca20SDavid Ahern err = -1; 5808d3eca20SDavid Ahern goto out_delete_session; 581e20960c0SRobert Richter } 582e20960c0SRobert Richter 583d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5846122e4e4SArnaldo Carvalho de Melo 585743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 586743eb868SArnaldo Carvalho de Melo if (!machine) { 587743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 5888d3eca20SDavid Ahern err = -1; 5898d3eca20SDavid Ahern goto out_delete_session; 590743eb868SArnaldo Carvalho de Melo } 591743eb868SArnaldo Carvalho de Melo 592d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 59345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 594a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5952c46dbb5STom Zanussi if (err < 0) { 5962c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5978d3eca20SDavid Ahern goto out_delete_session; 5982c46dbb5STom Zanussi } 599cd19a035STom Zanussi 60045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 601743eb868SArnaldo Carvalho de Melo machine); 602cd19a035STom Zanussi if (err < 0) { 603cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 6048d3eca20SDavid Ahern goto out_delete_session; 605cd19a035STom Zanussi } 6069215545eSTom Zanussi 607361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 60863e0c771STom Zanussi /* 60963e0c771STom Zanussi * FIXME err <= 0 here actually means that 61063e0c771STom Zanussi * there were no tracepoints so its not really 61163e0c771STom Zanussi * an error, just that we don't need to 61263e0c771STom Zanussi * synthesize anything. We really have to 61363e0c771STom Zanussi * return this more properly and also 61463e0c771STom Zanussi * propagate errors that now are calling die() 61563e0c771STom Zanussi */ 61645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 617743eb868SArnaldo Carvalho de Melo process_synthesized_event); 61863e0c771STom Zanussi if (err <= 0) { 61963e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 6208d3eca20SDavid Ahern goto out_delete_session; 62163e0c771STom Zanussi } 622d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 6232c46dbb5STom Zanussi } 62463e0c771STom Zanussi } 6252c46dbb5STom Zanussi 62645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 627743eb868SArnaldo Carvalho de Melo machine, "_text"); 62870162138SArnaldo Carvalho de Melo if (err < 0) 62945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 630743eb868SArnaldo Carvalho de Melo machine, "_stext"); 631c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 632c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 633c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 634c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 63556b03f3cSArnaldo Carvalho de Melo 63645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 637743eb868SArnaldo Carvalho de Melo machine); 638c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 639c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 640c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 641c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 642c1a3a4b9SArnaldo Carvalho de Melo 643a1645ce1SZhang, Yanmin if (perf_guest) 64445694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 6458115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 646b7cece76SArnaldo Carvalho de Melo 647bea03405SNamhyung Kim if (!opts->target.system_wide) 6488d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 6498115d60cSArnaldo Carvalho de Melo process_synthesized_event, 650743eb868SArnaldo Carvalho de Melo machine); 651234fbbf5SArnaldo Carvalho de Melo else 6528d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 653743eb868SArnaldo Carvalho de Melo machine); 6547c6a1c65SPeter Zijlstra 6558d3eca20SDavid Ahern if (err != 0) 6568d3eca20SDavid Ahern goto out_delete_session; 6578d3eca20SDavid Ahern 658d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 65986470930SIngo Molnar struct sched_param param; 66086470930SIngo Molnar 661d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 66286470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6636beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6648d3eca20SDavid Ahern err = -1; 6658d3eca20SDavid Ahern goto out_delete_session; 66686470930SIngo Molnar } 66786470930SIngo Molnar } 66886470930SIngo Molnar 669764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 670764e16a3SDavid Ahern 671856e9660SPeter Zijlstra /* 672856e9660SPeter Zijlstra * Let the child rip 673856e9660SPeter Zijlstra */ 674d4db3f16SArnaldo Carvalho de Melo if (forks) 67535b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 676856e9660SPeter Zijlstra 677649c48a9SPeter Zijlstra for (;;) { 678d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 67986470930SIngo Molnar 6808d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 6818d3eca20SDavid Ahern err = -1; 6828d3eca20SDavid Ahern goto out_delete_session; 6838d3eca20SDavid Ahern } 68486470930SIngo Molnar 685d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 686649c48a9SPeter Zijlstra if (done) 687649c48a9SPeter Zijlstra break; 6885c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6898b412664SPeter Zijlstra waking++; 6908b412664SPeter Zijlstra } 6918b412664SPeter Zijlstra 6924152ab37SArnaldo Carvalho de Melo if (done) 6934152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6948b412664SPeter Zijlstra } 6958b412664SPeter Zijlstra 69618483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 697b44308f5SArnaldo Carvalho de Melo return 0; 698b44308f5SArnaldo Carvalho de Melo 6998b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 70086470930SIngo Molnar 70186470930SIngo Molnar /* 70286470930SIngo Molnar * Approximate RIP event size: 24 bytes. 70386470930SIngo Molnar */ 70486470930SIngo Molnar fprintf(stderr, 7059486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 706d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 70786470930SIngo Molnar output_name, 708d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 70986470930SIngo Molnar 71086470930SIngo Molnar return 0; 71139d17dacSArnaldo Carvalho de Melo 71239d17dacSArnaldo Carvalho de Melo out_delete_session: 71339d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 71439d17dacSArnaldo Carvalho de Melo return err; 71586470930SIngo Molnar } 71686470930SIngo Molnar 717bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 718bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 719bdfebd84SRoberto Agostino Vitillo 720bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 721bdfebd84SRoberto Agostino Vitillo 722bdfebd84SRoberto Agostino Vitillo struct branch_mode { 723bdfebd84SRoberto Agostino Vitillo const char *name; 724bdfebd84SRoberto Agostino Vitillo int mode; 725bdfebd84SRoberto Agostino Vitillo }; 726bdfebd84SRoberto Agostino Vitillo 727bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 728bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 729bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 730bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 731bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 732bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 733bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 734bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 735bdfebd84SRoberto Agostino Vitillo BRANCH_END 736bdfebd84SRoberto Agostino Vitillo }; 737bdfebd84SRoberto Agostino Vitillo 738bdfebd84SRoberto Agostino Vitillo static int 739a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 740bdfebd84SRoberto Agostino Vitillo { 741bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 742bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 743bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 744bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 745bdfebd84SRoberto Agostino Vitillo 746bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 747bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 748a5aabdacSStephane Eranian char *s, *os = NULL, *p; 749bdfebd84SRoberto Agostino Vitillo int ret = -1; 750bdfebd84SRoberto Agostino Vitillo 751a5aabdacSStephane Eranian if (unset) 752a5aabdacSStephane Eranian return 0; 753bdfebd84SRoberto Agostino Vitillo 754a5aabdacSStephane Eranian /* 755a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 756a5aabdacSStephane Eranian */ 757a5aabdacSStephane Eranian if (*mode) 758a5aabdacSStephane Eranian return -1; 759a5aabdacSStephane Eranian 760a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 761a5aabdacSStephane Eranian if (str) { 762bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 763bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 764bdfebd84SRoberto Agostino Vitillo if (!s) 765bdfebd84SRoberto Agostino Vitillo return -1; 766bdfebd84SRoberto Agostino Vitillo 767bdfebd84SRoberto Agostino Vitillo for (;;) { 768bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 769bdfebd84SRoberto Agostino Vitillo if (p) 770bdfebd84SRoberto Agostino Vitillo *p = '\0'; 771bdfebd84SRoberto Agostino Vitillo 772bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 773bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 774bdfebd84SRoberto Agostino Vitillo break; 775bdfebd84SRoberto Agostino Vitillo } 776a5aabdacSStephane Eranian if (!br->name) { 777a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 778a5aabdacSStephane Eranian " check man page\n", s); 779bdfebd84SRoberto Agostino Vitillo goto error; 780a5aabdacSStephane Eranian } 781bdfebd84SRoberto Agostino Vitillo 782bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 783bdfebd84SRoberto Agostino Vitillo 784bdfebd84SRoberto Agostino Vitillo if (!p) 785bdfebd84SRoberto Agostino Vitillo break; 786bdfebd84SRoberto Agostino Vitillo 787bdfebd84SRoberto Agostino Vitillo s = p + 1; 788bdfebd84SRoberto Agostino Vitillo } 789a5aabdacSStephane Eranian } 790bdfebd84SRoberto Agostino Vitillo ret = 0; 791bdfebd84SRoberto Agostino Vitillo 792a5aabdacSStephane Eranian /* default to any branch */ 793bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 794a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 795bdfebd84SRoberto Agostino Vitillo } 796bdfebd84SRoberto Agostino Vitillo error: 797bdfebd84SRoberto Agostino Vitillo free(os); 798bdfebd84SRoberto Agostino Vitillo return ret; 799bdfebd84SRoberto Agostino Vitillo } 800bdfebd84SRoberto Agostino Vitillo 80126d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT 80226d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 80326d33022SJiri Olsa { 80426d33022SJiri Olsa char *endptr; 80526d33022SJiri Olsa unsigned long size; 80626d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 80726d33022SJiri Olsa 80826d33022SJiri Olsa size = strtoul(str, &endptr, 0); 80926d33022SJiri Olsa 81026d33022SJiri Olsa do { 81126d33022SJiri Olsa if (*endptr) 81226d33022SJiri Olsa break; 81326d33022SJiri Olsa 81426d33022SJiri Olsa size = round_up(size, sizeof(u64)); 81526d33022SJiri Olsa if (!size || size > max_size) 81626d33022SJiri Olsa break; 81726d33022SJiri Olsa 81826d33022SJiri Olsa *_size = size; 81926d33022SJiri Olsa return 0; 82026d33022SJiri Olsa 82126d33022SJiri Olsa } while (0); 82226d33022SJiri Olsa 82326d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 82426d33022SJiri Olsa max_size, str); 82526d33022SJiri Olsa return -1; 82626d33022SJiri Olsa } 82726d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */ 82826d33022SJiri Olsa 82926d33022SJiri Olsa static int 830*1d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 83126d33022SJiri Olsa int unset) 83226d33022SJiri Olsa { 83326d33022SJiri Olsa struct perf_record *rec = (struct perf_record *)opt->value; 83426d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 83526d33022SJiri Olsa char *buf; 83626d33022SJiri Olsa int ret = -1; 83726d33022SJiri Olsa 83826d33022SJiri Olsa /* --no-call-graph */ 83926d33022SJiri Olsa if (unset) 84026d33022SJiri Olsa return 0; 84126d33022SJiri Olsa 84226d33022SJiri Olsa /* We specified default option if none is provided. */ 84326d33022SJiri Olsa BUG_ON(!arg); 84426d33022SJiri Olsa 84526d33022SJiri Olsa /* We need buffer that we know we can write to. */ 84626d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 84726d33022SJiri Olsa if (!buf) 84826d33022SJiri Olsa return -ENOMEM; 84926d33022SJiri Olsa 85026d33022SJiri Olsa strcpy(buf, arg); 85126d33022SJiri Olsa 85226d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 85326d33022SJiri Olsa name = tok ? : (char *)buf; 85426d33022SJiri Olsa 85526d33022SJiri Olsa do { 85626d33022SJiri Olsa /* Framepointer style */ 85726d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 85826d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 85926d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_FP; 86026d33022SJiri Olsa ret = 0; 86126d33022SJiri Olsa } else 86226d33022SJiri Olsa pr_err("callchain: No more arguments " 86326d33022SJiri Olsa "needed for -g fp\n"); 86426d33022SJiri Olsa break; 86526d33022SJiri Olsa 86626d33022SJiri Olsa #ifndef NO_LIBUNWIND_SUPPORT 86726d33022SJiri Olsa /* Dwarf style */ 86826d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 86926d33022SJiri Olsa ret = 0; 87026d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_DWARF; 87126d33022SJiri Olsa rec->opts.stack_dump_size = default_stack_dump_size; 87226d33022SJiri Olsa 87326d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 87426d33022SJiri Olsa if (tok) { 87526d33022SJiri Olsa unsigned long size = 0; 87626d33022SJiri Olsa 87726d33022SJiri Olsa ret = get_stack_size(tok, &size); 87826d33022SJiri Olsa rec->opts.stack_dump_size = size; 87926d33022SJiri Olsa } 88026d33022SJiri Olsa 88126d33022SJiri Olsa if (!ret) 88226d33022SJiri Olsa pr_debug("callchain: stack dump size %d\n", 88326d33022SJiri Olsa rec->opts.stack_dump_size); 88426d33022SJiri Olsa #endif /* !NO_LIBUNWIND_SUPPORT */ 88526d33022SJiri Olsa } else { 88626d33022SJiri Olsa pr_err("callchain: Unknown -g option " 88726d33022SJiri Olsa "value: %s\n", arg); 88826d33022SJiri Olsa break; 88926d33022SJiri Olsa } 89026d33022SJiri Olsa 89126d33022SJiri Olsa } while (0); 89226d33022SJiri Olsa 89326d33022SJiri Olsa free(buf); 89426d33022SJiri Olsa 89526d33022SJiri Olsa if (!ret) 89626d33022SJiri Olsa pr_debug("callchain: type %d\n", rec->opts.call_graph); 89726d33022SJiri Olsa 89826d33022SJiri Olsa return ret; 89926d33022SJiri Olsa } 90026d33022SJiri Olsa 90186470930SIngo Molnar static const char * const record_usage[] = { 90286470930SIngo Molnar "perf record [<options>] [<command>]", 90386470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 90486470930SIngo Molnar NULL 90586470930SIngo Molnar }; 90686470930SIngo Molnar 907d20deb64SArnaldo Carvalho de Melo /* 908d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 909d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 910d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 911d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 912d20deb64SArnaldo Carvalho de Melo * 913d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 914d20deb64SArnaldo Carvalho de Melo * 915d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 916d20deb64SArnaldo Carvalho de Melo */ 917d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 918d20deb64SArnaldo Carvalho de Melo .opts = { 919d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 920d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 921d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 922447a6013SArnaldo Carvalho de Melo .freq = 4000, 923d1cb9fceSNamhyung Kim .target = { 924d1cb9fceSNamhyung Kim .uses_mmap = true, 925d1cb9fceSNamhyung Kim }, 926d20deb64SArnaldo Carvalho de Melo }, 927d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 928d20deb64SArnaldo Carvalho de Melo .file_new = true, 929d20deb64SArnaldo Carvalho de Melo }; 9307865e817SFrederic Weisbecker 931d20deb64SArnaldo Carvalho de Melo /* 932d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 933d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 934d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 935d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 936d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 937d20deb64SArnaldo Carvalho de Melo */ 938bca647aaSTom Zanussi const struct option record_options[] = { 939d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 94086470930SIngo Molnar "event selector. use 'perf list' to list available events", 941f120f9d5SJiri Olsa parse_events_option), 942d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 943c171b552SLi Zefan "event filter", parse_filter), 944bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 945d6d901c2SZhang, Yanmin "record events on existing process id"), 946bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 947d6d901c2SZhang, Yanmin "record events on existing thread id"), 948d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 94986470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 950d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 951acac03faSKirill Smelkov "collect data without buffering"), 952d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 953daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 954bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 95586470930SIngo Molnar "system-wide collection from all CPUs"), 956d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 95786470930SIngo Molnar "append to the output file to do incremental profiling"), 958bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 959c45c6ea2SStephane Eranian "list of cpus to monitor"), 960d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 9617865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 962d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 963d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 96486470930SIngo Molnar "output file name"), 965d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 9662e6cdf99SStephane Eranian "child tasks do not inherit counters"), 967d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 968d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 96901c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 970d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 97143bece79SLin Ming "put the counters into a counter group"), 97226d33022SJiri Olsa OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", 97326d33022SJiri Olsa callchain_help, &parse_callchain_opt, 97426d33022SJiri Olsa "fp"), 975c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 9763da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 977b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 978d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 979649c48a9SPeter Zijlstra "per thread counts"), 980d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 9814bba828dSAnton Blanchard "Sample addresses"), 982d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 9833e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 984d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 985649c48a9SPeter Zijlstra "don't sample"), 986d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 987a1ac1d3cSStephane Eranian "do not update the buildid cache"), 988d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 989baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 990d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 991023695d9SStephane Eranian "monitor event in cgroup name only", 992023695d9SStephane Eranian parse_cgroups), 993bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 994bea03405SNamhyung Kim "user to profile"), 995a5aabdacSStephane Eranian 996a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 997a5aabdacSStephane Eranian "branch any", "sample any taken branches", 998a5aabdacSStephane Eranian parse_branch_stack), 999a5aabdacSStephane Eranian 1000a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1001a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1002bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 100386470930SIngo Molnar OPT_END() 100486470930SIngo Molnar }; 100586470930SIngo Molnar 1006*1d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 100786470930SIngo Molnar { 100869aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 100969aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 1010d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 1011d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 101216ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 101386470930SIngo Molnar 10147e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 1015361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1016361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1017361c99a6SArnaldo Carvalho de Melo 1018d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 1019d20deb64SArnaldo Carvalho de Melo 1020bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1021a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1022d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 1023bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 102486470930SIngo Molnar 1025d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 10263780f488SNamhyung Kim ui__error("Can't overwrite and append at the same time." 10277865e817SFrederic Weisbecker " You need to choose between -f and -A"); 1028bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 1029d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 1030d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 10317865e817SFrederic Weisbecker } else { 1032d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 10337865e817SFrederic Weisbecker } 10347865e817SFrederic Weisbecker 1035bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 10363780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1037023695d9SStephane Eranian " system-wide mode\n"); 1038023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1039023695d9SStephane Eranian } 1040023695d9SStephane Eranian 1041655000e7SArnaldo Carvalho de Melo symbol__init(); 1042baa2f6ceSArnaldo Carvalho de Melo 1043ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1044646aaea6SArnaldo Carvalho de Melo pr_warning( 1045646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1046ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1047646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1048646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1049646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1050646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1051646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1052ec80fde7SArnaldo Carvalho de Melo 1053d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1054a1ac1d3cSStephane Eranian disable_buildid_cache(); 1055655000e7SArnaldo Carvalho de Melo 1056361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 1057361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 105869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 105969aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1060bbd36e5eSPeter Zijlstra } 106186470930SIngo Molnar 106216ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 106316ad2ffbSNamhyung Kim if (err) { 106416ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 106516ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 106616ad2ffbSNamhyung Kim } 10674bd0f2d2SNamhyung Kim 106816ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 106916ad2ffbSNamhyung Kim if (err) { 107016ad2ffbSNamhyung Kim int saved_errno = errno; 107116ad2ffbSNamhyung Kim 107216ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 10733780f488SNamhyung Kim ui__error("%s", errbuf); 107416ad2ffbSNamhyung Kim 107516ad2ffbSNamhyung Kim err = -saved_errno; 10760d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 107716ad2ffbSNamhyung Kim } 10780d37aa34SArnaldo Carvalho de Melo 107916ad2ffbSNamhyung Kim err = -ENOMEM; 1080b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 1081dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 108269aad6f1SArnaldo Carvalho de Melo 1083361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 10847289f83cSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) 1085ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 1086d6d901c2SZhang, Yanmin } 10875c581041SArnaldo Carvalho de Melo 1088d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 1089d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 1090d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 1091d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 1092f9212819SFrederic Weisbecker 10937e4ff9e3SMike Galbraith /* 10947e4ff9e3SMike Galbraith * User specified count overrides default frequency. 10957e4ff9e3SMike Galbraith */ 1096d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 1097d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 1098d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 1099d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 11007e4ff9e3SMike Galbraith } else { 11013780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 110239d17dacSArnaldo Carvalho de Melo err = -EINVAL; 11035c581041SArnaldo Carvalho de Melo goto out_free_fd; 11047e4ff9e3SMike Galbraith } 11057e4ff9e3SMike Galbraith 1106d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 110739d17dacSArnaldo Carvalho de Melo out_free_fd: 11087e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 1109d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 1110d65a458bSArnaldo Carvalho de Melo symbol__exit(); 111139d17dacSArnaldo Carvalho de Melo return err; 111286470930SIngo Molnar } 1113