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 36*95485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 3726d33022SJiri Olsa static unsigned long default_stack_dump_size = 8192; 3826d33022SJiri Olsa static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 39*95485b1cSNamhyung Kim #else 40*95485b1cSNamhyung Kim static char callchain_help[] = CALLCHAIN_HELP "[fp]"; 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, 951d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 961d037ca1SIrina 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 1621d037ca1SIrina 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"); 3001863fbbbSStephane Eranian error("sys_perf_event_open() syscall returned with %d " 3011863fbbbSStephane Eranian "(%s) for event %s. /bin/dmesg may provide " 3021863fbbbSStephane Eranian "additional information.\n", 3031863fbbbSStephane Eranian err, strerror(err), perf_evsel__name(pos)); 304bfd45118SSimon Kaempflein 305bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 3068d3eca20SDavid Ahern if (attr->type == PERF_TYPE_HARDWARE && 3078d3eca20SDavid Ahern err == EOPNOTSUPP) { 3088d3eca20SDavid Ahern pr_err("No hardware sampling interrupt available." 309d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 310d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 311d6d901c2SZhang, Yanmin " force-enable it.\n"); 3128d3eca20SDavid Ahern rc = -err; 3138d3eca20SDavid Ahern goto out; 3148d3eca20SDavid Ahern } 315bfd45118SSimon Kaempflein #endif 316bfd45118SSimon Kaempflein 3178d3eca20SDavid Ahern pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 3188d3eca20SDavid Ahern rc = -err; 3198d3eca20SDavid Ahern goto out; 3207c6a1c65SPeter Zijlstra } 3217c6a1c65SPeter Zijlstra } 3227c6a1c65SPeter Zijlstra 3231491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 3240a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 3250a102479SFrederic Weisbecker strerror(errno)); 3268d3eca20SDavid Ahern rc = -1; 3278d3eca20SDavid Ahern goto out; 3280a102479SFrederic Weisbecker } 3290a102479SFrederic Weisbecker 33018e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 3318d3eca20SDavid Ahern if (errno == EPERM) { 3328d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 33318e60939SNelson Elhage "Consider increasing " 33418e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 33518e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 33618e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 3378d3eca20SDavid Ahern rc = -errno; 3388d3eca20SDavid Ahern } else if (!is_power_of_2(opts->mmap_pages)) { 3398d3eca20SDavid Ahern pr_err("--mmap_pages/-m value must be a power of two."); 3408d3eca20SDavid Ahern rc = -EINVAL; 3418d3eca20SDavid Ahern } else { 3428d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 3438d3eca20SDavid Ahern rc = -errno; 3448d3eca20SDavid Ahern } 3458d3eca20SDavid Ahern goto out; 34618e60939SNelson Elhage } 3470a27d7f9SArnaldo Carvalho de Melo 348d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 349a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 350a91e5431SArnaldo Carvalho de Melo else { 351a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 352a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 3538d3eca20SDavid Ahern rc = -1; 3548d3eca20SDavid Ahern goto out; 355dd7927f4SArnaldo Carvalho de Melo } 35686470930SIngo Molnar } 35786470930SIngo Molnar 3587b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3598d3eca20SDavid Ahern out: 3608d3eca20SDavid Ahern return rc; 361a91e5431SArnaldo Carvalho de Melo } 362a91e5431SArnaldo Carvalho de Melo 363d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3646122e4e4SArnaldo Carvalho de Melo { 365d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3666122e4e4SArnaldo Carvalho de Melo 3679f591fd7SArnaldo Carvalho de Melo if (size == 0) 3689f591fd7SArnaldo Carvalho de Melo return 0; 3699f591fd7SArnaldo Carvalho de Melo 370d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 371d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 372d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3736122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3746122e4e4SArnaldo Carvalho de Melo } 3756122e4e4SArnaldo Carvalho de Melo 3768d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 377f5970550SPeter Zijlstra { 378d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 379f5970550SPeter Zijlstra 3808d3eca20SDavid Ahern if (status != 0) 3818d3eca20SDavid Ahern return; 3828d3eca20SDavid Ahern 383d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 384d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 385d20deb64SArnaldo Carvalho de Melo 386d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 387d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 388d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 389d20deb64SArnaldo Carvalho de Melo rec->output, true); 390d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 391d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 392d65a458bSArnaldo Carvalho de Melo symbol__exit(); 393c7929e47STom Zanussi } 394f5970550SPeter Zijlstra } 395f5970550SPeter Zijlstra 3968115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 397a1645ce1SZhang, Yanmin { 398a1645ce1SZhang, Yanmin int err; 39945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 400a1645ce1SZhang, Yanmin 40123346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 402a1645ce1SZhang, Yanmin return; 403a1645ce1SZhang, Yanmin 404a1645ce1SZhang, Yanmin /* 405a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 406a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 407a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 408a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 409a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 410a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 411a1645ce1SZhang, Yanmin */ 41245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 413743eb868SArnaldo Carvalho de Melo machine); 414a1645ce1SZhang, Yanmin if (err < 0) 415a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 41623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 417a1645ce1SZhang, Yanmin 418a1645ce1SZhang, Yanmin /* 419a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 420a1645ce1SZhang, Yanmin * have no _text sometimes. 421a1645ce1SZhang, Yanmin */ 42245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 423743eb868SArnaldo Carvalho de Melo machine, "_text"); 424a1645ce1SZhang, Yanmin if (err < 0) 42545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 426743eb868SArnaldo Carvalho de Melo machine, "_stext"); 427a1645ce1SZhang, Yanmin if (err < 0) 428a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 42923346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 430a1645ce1SZhang, Yanmin } 431a1645ce1SZhang, Yanmin 43298402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 43398402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 43498402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 43598402807SFrederic Weisbecker }; 43698402807SFrederic Weisbecker 4378d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 43898402807SFrederic Weisbecker { 4390e2e63ddSPeter Zijlstra int i; 4408d3eca20SDavid Ahern int rc = 0; 44198402807SFrederic Weisbecker 442d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 4438d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 4448d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 4458d3eca20SDavid Ahern rc = -1; 4468d3eca20SDavid Ahern goto out; 4478d3eca20SDavid Ahern } 4488d3eca20SDavid Ahern } 44998402807SFrederic Weisbecker } 45098402807SFrederic Weisbecker 4512eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 4528d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 4538d3eca20SDavid Ahern sizeof(finished_round_event)); 4548d3eca20SDavid Ahern 4558d3eca20SDavid Ahern out: 4568d3eca20SDavid Ahern return rc; 45798402807SFrederic Weisbecker } 45898402807SFrederic Weisbecker 459d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 46086470930SIngo Molnar { 46186470930SIngo Molnar struct stat st; 46286470930SIngo Molnar int flags; 463781ba9d2SRobert Richter int err, output, feat; 4648b412664SPeter Zijlstra unsigned long waking = 0; 46546be604bSZhang, Yanmin const bool forks = argc > 0; 46623346f21SArnaldo Carvalho de Melo struct machine *machine; 46745694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 468d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 469d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 470d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 471d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 47286470930SIngo Molnar 473d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 47433e49ea7SAndi Kleen 475d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 47686470930SIngo Molnar 477d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 478f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 479f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 48018483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 481f5970550SPeter Zijlstra 482d7065adbSFranck Bui-Huu if (!output_name) { 483d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 484d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 485d7065adbSFranck Bui-Huu else 486d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 487d7065adbSFranck Bui-Huu } 488d7065adbSFranck Bui-Huu if (output_name) { 489529870e3STom Zanussi if (!strcmp(output_name, "-")) 490d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 491529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 492d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 493b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 494b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 495b38d3464SArnaldo Carvalho de Melo output_name); 496b38d3464SArnaldo Carvalho de Melo unlink(oldname); 497b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 498b38d3464SArnaldo Carvalho de Melo } 499d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 500d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 501266e0e21SPierre Habouzit } 502d7065adbSFranck Bui-Huu } 50386470930SIngo Molnar 504f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 505d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 506d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 50786470930SIngo Molnar else 50886470930SIngo Molnar flags |= O_TRUNC; 50986470930SIngo Molnar 510d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 511529870e3STom Zanussi output = STDOUT_FILENO; 512529870e3STom Zanussi else 51386470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 51486470930SIngo Molnar if (output < 0) { 51586470930SIngo Molnar perror("failed to create output file"); 5168d3eca20SDavid Ahern return -1; 51786470930SIngo Molnar } 51886470930SIngo Molnar 519d20deb64SArnaldo Carvalho de Melo rec->output = output; 520d20deb64SArnaldo Carvalho de Melo 5217865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 522d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 52394c744b6SArnaldo Carvalho de Melo if (session == NULL) { 524a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 525a9a70bbcSArnaldo Carvalho de Melo return -1; 526a9a70bbcSArnaldo Carvalho de Melo } 527a9a70bbcSArnaldo Carvalho de Melo 528d20deb64SArnaldo Carvalho de Melo rec->session = session; 529d20deb64SArnaldo Carvalho de Melo 530781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 531781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 532781ba9d2SRobert Richter 533781ba9d2SRobert Richter if (rec->no_buildid) 534781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 535781ba9d2SRobert Richter 536781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 5372eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 538baa2f6ceSArnaldo Carvalho de Melo 539330aa675SStephane Eranian if (!rec->opts.branch_stack) 540330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 541330aa675SStephane Eranian 542d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 543a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 5444dc0a04bSArnaldo Carvalho de Melo if (err < 0) 54539d17dacSArnaldo Carvalho de Melo goto out_delete_session; 5464dc0a04bSArnaldo Carvalho de Melo } 5474dc0a04bSArnaldo Carvalho de Melo 548d4db3f16SArnaldo Carvalho de Melo if (forks) { 549d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 55035b9d88eSArnaldo Carvalho de Melo if (err < 0) { 55135b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 55235b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 553856e9660SPeter Zijlstra } 554856e9660SPeter Zijlstra } 555856e9660SPeter Zijlstra 5568d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 5578d3eca20SDavid Ahern err = -1; 5588d3eca20SDavid Ahern goto out_delete_session; 5598d3eca20SDavid Ahern } 56086470930SIngo Molnar 561712a4b60SArnaldo Carvalho de Melo /* 562d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 563712a4b60SArnaldo Carvalho de Melo */ 564d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 565712a4b60SArnaldo Carvalho de Melo 566d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 567529870e3STom Zanussi err = perf_header__write_pipe(output); 568529870e3STom Zanussi if (err < 0) 5698d3eca20SDavid Ahern goto out_delete_session; 570d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 571a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 572361c99a6SArnaldo Carvalho de Melo output, false); 573d5eed904SArnaldo Carvalho de Melo if (err < 0) 5748d3eca20SDavid Ahern goto out_delete_session; 575d5eed904SArnaldo Carvalho de Melo } 5767c6a1c65SPeter Zijlstra 577d3665498SDavid Ahern if (!rec->no_buildid 578e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 579d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 580e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5818d3eca20SDavid Ahern err = -1; 5828d3eca20SDavid Ahern goto out_delete_session; 583e20960c0SRobert Richter } 584e20960c0SRobert Richter 585d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5866122e4e4SArnaldo Carvalho de Melo 587743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 588743eb868SArnaldo Carvalho de Melo if (!machine) { 589743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 5908d3eca20SDavid Ahern err = -1; 5918d3eca20SDavid Ahern goto out_delete_session; 592743eb868SArnaldo Carvalho de Melo } 593743eb868SArnaldo Carvalho de Melo 594d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 59545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 596a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5972c46dbb5STom Zanussi if (err < 0) { 5982c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5998d3eca20SDavid Ahern goto out_delete_session; 6002c46dbb5STom Zanussi } 601cd19a035STom Zanussi 60245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 603743eb868SArnaldo Carvalho de Melo machine); 604cd19a035STom Zanussi if (err < 0) { 605cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 6068d3eca20SDavid Ahern goto out_delete_session; 607cd19a035STom Zanussi } 6089215545eSTom Zanussi 609361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 61063e0c771STom Zanussi /* 61163e0c771STom Zanussi * FIXME err <= 0 here actually means that 61263e0c771STom Zanussi * there were no tracepoints so its not really 61363e0c771STom Zanussi * an error, just that we don't need to 61463e0c771STom Zanussi * synthesize anything. We really have to 61563e0c771STom Zanussi * return this more properly and also 61663e0c771STom Zanussi * propagate errors that now are calling die() 61763e0c771STom Zanussi */ 61845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 619743eb868SArnaldo Carvalho de Melo process_synthesized_event); 62063e0c771STom Zanussi if (err <= 0) { 62163e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 6228d3eca20SDavid Ahern goto out_delete_session; 62363e0c771STom Zanussi } 624d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 6252c46dbb5STom Zanussi } 62663e0c771STom Zanussi } 6272c46dbb5STom Zanussi 62845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 629743eb868SArnaldo Carvalho de Melo machine, "_text"); 63070162138SArnaldo Carvalho de Melo if (err < 0) 63145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 632743eb868SArnaldo Carvalho de Melo machine, "_stext"); 633c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 634c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 635c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 636c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 63756b03f3cSArnaldo Carvalho de Melo 63845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 639743eb868SArnaldo Carvalho de Melo machine); 640c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 641c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 642c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 643c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 644c1a3a4b9SArnaldo Carvalho de Melo 645a1645ce1SZhang, Yanmin if (perf_guest) 64645694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 6478115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 648b7cece76SArnaldo Carvalho de Melo 649bea03405SNamhyung Kim if (!opts->target.system_wide) 6508d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 6518115d60cSArnaldo Carvalho de Melo process_synthesized_event, 652743eb868SArnaldo Carvalho de Melo machine); 653234fbbf5SArnaldo Carvalho de Melo else 6548d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 655743eb868SArnaldo Carvalho de Melo machine); 6567c6a1c65SPeter Zijlstra 6578d3eca20SDavid Ahern if (err != 0) 6588d3eca20SDavid Ahern goto out_delete_session; 6598d3eca20SDavid Ahern 660d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 66186470930SIngo Molnar struct sched_param param; 66286470930SIngo Molnar 663d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 66486470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6656beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6668d3eca20SDavid Ahern err = -1; 6678d3eca20SDavid Ahern goto out_delete_session; 66886470930SIngo Molnar } 66986470930SIngo Molnar } 67086470930SIngo Molnar 671764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 672764e16a3SDavid Ahern 673856e9660SPeter Zijlstra /* 674856e9660SPeter Zijlstra * Let the child rip 675856e9660SPeter Zijlstra */ 676d4db3f16SArnaldo Carvalho de Melo if (forks) 67735b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 678856e9660SPeter Zijlstra 679649c48a9SPeter Zijlstra for (;;) { 680d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 68186470930SIngo Molnar 6828d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 6838d3eca20SDavid Ahern err = -1; 6848d3eca20SDavid Ahern goto out_delete_session; 6858d3eca20SDavid Ahern } 68686470930SIngo Molnar 687d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 688649c48a9SPeter Zijlstra if (done) 689649c48a9SPeter Zijlstra break; 6905c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6918b412664SPeter Zijlstra waking++; 6928b412664SPeter Zijlstra } 6938b412664SPeter Zijlstra 6944152ab37SArnaldo Carvalho de Melo if (done) 6954152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6968b412664SPeter Zijlstra } 6978b412664SPeter Zijlstra 69818483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 699b44308f5SArnaldo Carvalho de Melo return 0; 700b44308f5SArnaldo Carvalho de Melo 7018b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 70286470930SIngo Molnar 70386470930SIngo Molnar /* 70486470930SIngo Molnar * Approximate RIP event size: 24 bytes. 70586470930SIngo Molnar */ 70686470930SIngo Molnar fprintf(stderr, 7079486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 708d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 70986470930SIngo Molnar output_name, 710d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 71186470930SIngo Molnar 71286470930SIngo Molnar return 0; 71339d17dacSArnaldo Carvalho de Melo 71439d17dacSArnaldo Carvalho de Melo out_delete_session: 71539d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 71639d17dacSArnaldo Carvalho de Melo return err; 71786470930SIngo Molnar } 71886470930SIngo Molnar 719bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 720bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 721bdfebd84SRoberto Agostino Vitillo 722bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 723bdfebd84SRoberto Agostino Vitillo 724bdfebd84SRoberto Agostino Vitillo struct branch_mode { 725bdfebd84SRoberto Agostino Vitillo const char *name; 726bdfebd84SRoberto Agostino Vitillo int mode; 727bdfebd84SRoberto Agostino Vitillo }; 728bdfebd84SRoberto Agostino Vitillo 729bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 730bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 731bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 732bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 733bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 734bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 735bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 736bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 737bdfebd84SRoberto Agostino Vitillo BRANCH_END 738bdfebd84SRoberto Agostino Vitillo }; 739bdfebd84SRoberto Agostino Vitillo 740bdfebd84SRoberto Agostino Vitillo static int 741a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 742bdfebd84SRoberto Agostino Vitillo { 743bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 744bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 745bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 746bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 747bdfebd84SRoberto Agostino Vitillo 748bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 749bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 750a5aabdacSStephane Eranian char *s, *os = NULL, *p; 751bdfebd84SRoberto Agostino Vitillo int ret = -1; 752bdfebd84SRoberto Agostino Vitillo 753a5aabdacSStephane Eranian if (unset) 754a5aabdacSStephane Eranian return 0; 755bdfebd84SRoberto Agostino Vitillo 756a5aabdacSStephane Eranian /* 757a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 758a5aabdacSStephane Eranian */ 759a5aabdacSStephane Eranian if (*mode) 760a5aabdacSStephane Eranian return -1; 761a5aabdacSStephane Eranian 762a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 763a5aabdacSStephane Eranian if (str) { 764bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 765bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 766bdfebd84SRoberto Agostino Vitillo if (!s) 767bdfebd84SRoberto Agostino Vitillo return -1; 768bdfebd84SRoberto Agostino Vitillo 769bdfebd84SRoberto Agostino Vitillo for (;;) { 770bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 771bdfebd84SRoberto Agostino Vitillo if (p) 772bdfebd84SRoberto Agostino Vitillo *p = '\0'; 773bdfebd84SRoberto Agostino Vitillo 774bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 775bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 776bdfebd84SRoberto Agostino Vitillo break; 777bdfebd84SRoberto Agostino Vitillo } 778a5aabdacSStephane Eranian if (!br->name) { 779a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 780a5aabdacSStephane Eranian " check man page\n", s); 781bdfebd84SRoberto Agostino Vitillo goto error; 782a5aabdacSStephane Eranian } 783bdfebd84SRoberto Agostino Vitillo 784bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 785bdfebd84SRoberto Agostino Vitillo 786bdfebd84SRoberto Agostino Vitillo if (!p) 787bdfebd84SRoberto Agostino Vitillo break; 788bdfebd84SRoberto Agostino Vitillo 789bdfebd84SRoberto Agostino Vitillo s = p + 1; 790bdfebd84SRoberto Agostino Vitillo } 791a5aabdacSStephane Eranian } 792bdfebd84SRoberto Agostino Vitillo ret = 0; 793bdfebd84SRoberto Agostino Vitillo 794a5aabdacSStephane Eranian /* default to any branch */ 795bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 796a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 797bdfebd84SRoberto Agostino Vitillo } 798bdfebd84SRoberto Agostino Vitillo error: 799bdfebd84SRoberto Agostino Vitillo free(os); 800bdfebd84SRoberto Agostino Vitillo return ret; 801bdfebd84SRoberto Agostino Vitillo } 802bdfebd84SRoberto Agostino Vitillo 803*95485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 80426d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 80526d33022SJiri Olsa { 80626d33022SJiri Olsa char *endptr; 80726d33022SJiri Olsa unsigned long size; 80826d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 80926d33022SJiri Olsa 81026d33022SJiri Olsa size = strtoul(str, &endptr, 0); 81126d33022SJiri Olsa 81226d33022SJiri Olsa do { 81326d33022SJiri Olsa if (*endptr) 81426d33022SJiri Olsa break; 81526d33022SJiri Olsa 81626d33022SJiri Olsa size = round_up(size, sizeof(u64)); 81726d33022SJiri Olsa if (!size || size > max_size) 81826d33022SJiri Olsa break; 81926d33022SJiri Olsa 82026d33022SJiri Olsa *_size = size; 82126d33022SJiri Olsa return 0; 82226d33022SJiri Olsa 82326d33022SJiri Olsa } while (0); 82426d33022SJiri Olsa 82526d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 82626d33022SJiri Olsa max_size, str); 82726d33022SJiri Olsa return -1; 82826d33022SJiri Olsa } 829*95485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 83026d33022SJiri Olsa 83126d33022SJiri Olsa static int 8321d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 83326d33022SJiri Olsa int unset) 83426d33022SJiri Olsa { 83526d33022SJiri Olsa struct perf_record *rec = (struct perf_record *)opt->value; 83626d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 83726d33022SJiri Olsa char *buf; 83826d33022SJiri Olsa int ret = -1; 83926d33022SJiri Olsa 84026d33022SJiri Olsa /* --no-call-graph */ 84126d33022SJiri Olsa if (unset) 84226d33022SJiri Olsa return 0; 84326d33022SJiri Olsa 84426d33022SJiri Olsa /* We specified default option if none is provided. */ 84526d33022SJiri Olsa BUG_ON(!arg); 84626d33022SJiri Olsa 84726d33022SJiri Olsa /* We need buffer that we know we can write to. */ 84826d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 84926d33022SJiri Olsa if (!buf) 85026d33022SJiri Olsa return -ENOMEM; 85126d33022SJiri Olsa 85226d33022SJiri Olsa strcpy(buf, arg); 85326d33022SJiri Olsa 85426d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 85526d33022SJiri Olsa name = tok ? : (char *)buf; 85626d33022SJiri Olsa 85726d33022SJiri Olsa do { 85826d33022SJiri Olsa /* Framepointer style */ 85926d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 86026d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 86126d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_FP; 86226d33022SJiri Olsa ret = 0; 86326d33022SJiri Olsa } else 86426d33022SJiri Olsa pr_err("callchain: No more arguments " 86526d33022SJiri Olsa "needed for -g fp\n"); 86626d33022SJiri Olsa break; 86726d33022SJiri Olsa 868*95485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 86926d33022SJiri Olsa /* Dwarf style */ 87026d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 87126d33022SJiri Olsa ret = 0; 87226d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_DWARF; 87326d33022SJiri Olsa rec->opts.stack_dump_size = default_stack_dump_size; 87426d33022SJiri Olsa 87526d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 87626d33022SJiri Olsa if (tok) { 87726d33022SJiri Olsa unsigned long size = 0; 87826d33022SJiri Olsa 87926d33022SJiri Olsa ret = get_stack_size(tok, &size); 88026d33022SJiri Olsa rec->opts.stack_dump_size = size; 88126d33022SJiri Olsa } 88226d33022SJiri Olsa 88326d33022SJiri Olsa if (!ret) 88426d33022SJiri Olsa pr_debug("callchain: stack dump size %d\n", 88526d33022SJiri Olsa rec->opts.stack_dump_size); 886*95485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 88726d33022SJiri Olsa } else { 88826d33022SJiri Olsa pr_err("callchain: Unknown -g option " 88926d33022SJiri Olsa "value: %s\n", arg); 89026d33022SJiri Olsa break; 89126d33022SJiri Olsa } 89226d33022SJiri Olsa 89326d33022SJiri Olsa } while (0); 89426d33022SJiri Olsa 89526d33022SJiri Olsa free(buf); 89626d33022SJiri Olsa 89726d33022SJiri Olsa if (!ret) 89826d33022SJiri Olsa pr_debug("callchain: type %d\n", rec->opts.call_graph); 89926d33022SJiri Olsa 90026d33022SJiri Olsa return ret; 90126d33022SJiri Olsa } 90226d33022SJiri Olsa 90386470930SIngo Molnar static const char * const record_usage[] = { 90486470930SIngo Molnar "perf record [<options>] [<command>]", 90586470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 90686470930SIngo Molnar NULL 90786470930SIngo Molnar }; 90886470930SIngo Molnar 909d20deb64SArnaldo Carvalho de Melo /* 910d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 911d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 912d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 913d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 914d20deb64SArnaldo Carvalho de Melo * 915d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 916d20deb64SArnaldo Carvalho de Melo * 917d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 918d20deb64SArnaldo Carvalho de Melo */ 919d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 920d20deb64SArnaldo Carvalho de Melo .opts = { 921d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 922d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 923d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 924447a6013SArnaldo Carvalho de Melo .freq = 4000, 925d1cb9fceSNamhyung Kim .target = { 926d1cb9fceSNamhyung Kim .uses_mmap = true, 927d1cb9fceSNamhyung Kim }, 928d20deb64SArnaldo Carvalho de Melo }, 929d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 930d20deb64SArnaldo Carvalho de Melo .file_new = true, 931d20deb64SArnaldo Carvalho de Melo }; 9327865e817SFrederic Weisbecker 933d20deb64SArnaldo Carvalho de Melo /* 934d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 935d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 936d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 937d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 938d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 939d20deb64SArnaldo Carvalho de Melo */ 940bca647aaSTom Zanussi const struct option record_options[] = { 941d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 94286470930SIngo Molnar "event selector. use 'perf list' to list available events", 943f120f9d5SJiri Olsa parse_events_option), 944d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 945c171b552SLi Zefan "event filter", parse_filter), 946bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 947d6d901c2SZhang, Yanmin "record events on existing process id"), 948bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 949d6d901c2SZhang, Yanmin "record events on existing thread id"), 950d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 95186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 952d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 953acac03faSKirill Smelkov "collect data without buffering"), 954d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 955daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 956bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 95786470930SIngo Molnar "system-wide collection from all CPUs"), 958d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 95986470930SIngo Molnar "append to the output file to do incremental profiling"), 960bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 961c45c6ea2SStephane Eranian "list of cpus to monitor"), 962d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 9637865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 964d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 965d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 96686470930SIngo Molnar "output file name"), 967d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 9682e6cdf99SStephane Eranian "child tasks do not inherit counters"), 969d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 970d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 97101c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 972d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 97343bece79SLin Ming "put the counters into a counter group"), 97426d33022SJiri Olsa OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", 97526d33022SJiri Olsa callchain_help, &parse_callchain_opt, 97626d33022SJiri Olsa "fp"), 977c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 9783da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 979b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 980d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 981649c48a9SPeter Zijlstra "per thread counts"), 982d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 9834bba828dSAnton Blanchard "Sample addresses"), 984d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 9853e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 986d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 987649c48a9SPeter Zijlstra "don't sample"), 988d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 989a1ac1d3cSStephane Eranian "do not update the buildid cache"), 990d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 991baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 992d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 993023695d9SStephane Eranian "monitor event in cgroup name only", 994023695d9SStephane Eranian parse_cgroups), 995bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 996bea03405SNamhyung Kim "user to profile"), 997a5aabdacSStephane Eranian 998a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 999a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1000a5aabdacSStephane Eranian parse_branch_stack), 1001a5aabdacSStephane Eranian 1002a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1003a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1004bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 100586470930SIngo Molnar OPT_END() 100686470930SIngo Molnar }; 100786470930SIngo Molnar 10081d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 100986470930SIngo Molnar { 101069aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 101169aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 1012d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 1013d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 101416ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 101586470930SIngo Molnar 10167e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 1017361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1018361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1019361c99a6SArnaldo Carvalho de Melo 1020d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 1021d20deb64SArnaldo Carvalho de Melo 1022bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1023a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1024d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 1025bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 102686470930SIngo Molnar 1027d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 10283780f488SNamhyung Kim ui__error("Can't overwrite and append at the same time." 10297865e817SFrederic Weisbecker " You need to choose between -f and -A"); 1030bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 1031d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 1032d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 10337865e817SFrederic Weisbecker } else { 1034d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 10357865e817SFrederic Weisbecker } 10367865e817SFrederic Weisbecker 1037bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 10383780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1039023695d9SStephane Eranian " system-wide mode\n"); 1040023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1041023695d9SStephane Eranian } 1042023695d9SStephane Eranian 1043655000e7SArnaldo Carvalho de Melo symbol__init(); 1044baa2f6ceSArnaldo Carvalho de Melo 1045ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1046646aaea6SArnaldo Carvalho de Melo pr_warning( 1047646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1048ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1049646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1050646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1051646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1052646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1053646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1054ec80fde7SArnaldo Carvalho de Melo 1055d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1056a1ac1d3cSStephane Eranian disable_buildid_cache(); 1057655000e7SArnaldo Carvalho de Melo 1058361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 1059361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 106069aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 106169aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1062bbd36e5eSPeter Zijlstra } 106386470930SIngo Molnar 106416ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 106516ad2ffbSNamhyung Kim if (err) { 106616ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 106716ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 106816ad2ffbSNamhyung Kim } 10694bd0f2d2SNamhyung Kim 107016ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 107116ad2ffbSNamhyung Kim if (err) { 107216ad2ffbSNamhyung Kim int saved_errno = errno; 107316ad2ffbSNamhyung Kim 107416ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 10753780f488SNamhyung Kim ui__error("%s", errbuf); 107616ad2ffbSNamhyung Kim 107716ad2ffbSNamhyung Kim err = -saved_errno; 10780d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 107916ad2ffbSNamhyung Kim } 10800d37aa34SArnaldo Carvalho de Melo 108116ad2ffbSNamhyung Kim err = -ENOMEM; 1082b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 1083dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 108469aad6f1SArnaldo Carvalho de Melo 1085361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 10867289f83cSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) 1087ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 1088d6d901c2SZhang, Yanmin } 10895c581041SArnaldo Carvalho de Melo 1090d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 1091d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 1092d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 1093d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 1094f9212819SFrederic Weisbecker 10957e4ff9e3SMike Galbraith /* 10967e4ff9e3SMike Galbraith * User specified count overrides default frequency. 10977e4ff9e3SMike Galbraith */ 1098d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 1099d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 1100d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 1101d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 11027e4ff9e3SMike Galbraith } else { 11033780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 110439d17dacSArnaldo Carvalho de Melo err = -EINVAL; 11055c581041SArnaldo Carvalho de Melo goto out_free_fd; 11067e4ff9e3SMike Galbraith } 11077e4ff9e3SMike Galbraith 1108d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 110939d17dacSArnaldo Carvalho de Melo out_free_fd: 11107e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 1111d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 1112d65a458bSArnaldo Carvalho de Melo symbol__exit(); 111339d17dacSArnaldo Carvalho de Melo return err; 111486470930SIngo Molnar } 1115