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 347865e817SFrederic Weisbecker enum write_mode_t { 357865e817SFrederic Weisbecker WRITE_FORCE, 367865e817SFrederic Weisbecker WRITE_APPEND 377865e817SFrederic Weisbecker }; 387865e817SFrederic Weisbecker 39d20deb64SArnaldo Carvalho de Melo struct perf_record { 4045694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 41d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 42d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 43d20deb64SArnaldo Carvalho de Melo const char *output_name; 44d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 45d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 46d20deb64SArnaldo Carvalho de Melo const char *progname; 47d20deb64SArnaldo Carvalho de Melo int output; 48d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 49d20deb64SArnaldo Carvalho de Melo int realtime_prio; 50d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 51d20deb64SArnaldo Carvalho de Melo bool no_buildid; 52d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 53d20deb64SArnaldo Carvalho de Melo bool force; 54d20deb64SArnaldo Carvalho de Melo bool file_new; 55d20deb64SArnaldo Carvalho de Melo bool append_file; 56d20deb64SArnaldo Carvalho de Melo long samples; 57d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 580f82ebc4SArnaldo Carvalho de Melo }; 5986470930SIngo Molnar 60d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 619215545eSTom Zanussi { 62d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 639215545eSTom Zanussi } 649215545eSTom Zanussi 658d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size) 66f5970550SPeter Zijlstra { 67f5970550SPeter Zijlstra while (size) { 68d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 69f5970550SPeter Zijlstra 708d3eca20SDavid Ahern if (ret < 0) { 718d3eca20SDavid Ahern pr_err("failed to write\n"); 728d3eca20SDavid Ahern return -1; 738d3eca20SDavid Ahern } 74f5970550SPeter Zijlstra 75f5970550SPeter Zijlstra size -= ret; 76f5970550SPeter Zijlstra buf += ret; 77f5970550SPeter Zijlstra 78d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 79f5970550SPeter Zijlstra } 808d3eca20SDavid Ahern 818d3eca20SDavid Ahern return 0; 82f5970550SPeter Zijlstra } 83f5970550SPeter Zijlstra 8445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 85d20deb64SArnaldo Carvalho de Melo union perf_event *event, 861d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 871d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 88234fbbf5SArnaldo Carvalho de Melo { 8945694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 908d3eca20SDavid Ahern if (write_output(rec, event, event->header.size) < 0) 918d3eca20SDavid Ahern return -1; 928d3eca20SDavid Ahern 93234fbbf5SArnaldo Carvalho de Melo return 0; 94234fbbf5SArnaldo Carvalho de Melo } 95234fbbf5SArnaldo Carvalho de Melo 968d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec, 97d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 9886470930SIngo Molnar { 99744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 10086470930SIngo Molnar unsigned int old = md->prev; 101d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 10286470930SIngo Molnar unsigned long size; 10386470930SIngo Molnar void *buf; 1048d3eca20SDavid Ahern int rc = 0; 10586470930SIngo Molnar 106dc82009aSArnaldo Carvalho de Melo if (old == head) 1078d3eca20SDavid Ahern return 0; 10886470930SIngo Molnar 109d20deb64SArnaldo Carvalho de Melo rec->samples++; 11086470930SIngo Molnar 11186470930SIngo Molnar size = head - old; 11286470930SIngo Molnar 11386470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 11486470930SIngo Molnar buf = &data[old & md->mask]; 11586470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 11686470930SIngo Molnar old += size; 11786470930SIngo Molnar 1188d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1198d3eca20SDavid Ahern rc = -1; 1208d3eca20SDavid Ahern goto out; 1218d3eca20SDavid Ahern } 12286470930SIngo Molnar } 12386470930SIngo Molnar 12486470930SIngo Molnar buf = &data[old & md->mask]; 12586470930SIngo Molnar size = head - old; 12686470930SIngo Molnar old += size; 12786470930SIngo Molnar 1288d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1298d3eca20SDavid Ahern rc = -1; 1308d3eca20SDavid Ahern goto out; 1318d3eca20SDavid Ahern } 13286470930SIngo Molnar 13386470930SIngo Molnar md->prev = old; 134115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 1358d3eca20SDavid Ahern 1368d3eca20SDavid Ahern out: 1378d3eca20SDavid Ahern return rc; 13886470930SIngo Molnar } 13986470930SIngo Molnar 14086470930SIngo Molnar static volatile int done = 0; 141f7b7c26eSPeter Zijlstra static volatile int signr = -1; 14233e49ea7SAndi Kleen static volatile int child_finished = 0; 14386470930SIngo Molnar 14486470930SIngo Molnar static void sig_handler(int sig) 14586470930SIngo Molnar { 14633e49ea7SAndi Kleen if (sig == SIGCHLD) 14733e49ea7SAndi Kleen child_finished = 1; 14833e49ea7SAndi Kleen 14986470930SIngo Molnar done = 1; 150f7b7c26eSPeter Zijlstra signr = sig; 151f7b7c26eSPeter Zijlstra } 152f7b7c26eSPeter Zijlstra 1531d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 154f7b7c26eSPeter Zijlstra { 155d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 15633e49ea7SAndi Kleen int status; 15733e49ea7SAndi Kleen 158d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 15933e49ea7SAndi Kleen if (!child_finished) 160d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 161933da83aSChris Wilson 16233e49ea7SAndi Kleen wait(&status); 16333e49ea7SAndi Kleen if (WIFSIGNALED(status)) 164d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 16533e49ea7SAndi Kleen } 16633e49ea7SAndi Kleen 16718483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 168f7b7c26eSPeter Zijlstra return; 169f7b7c26eSPeter Zijlstra 170f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 171f7b7c26eSPeter Zijlstra kill(getpid(), signr); 17286470930SIngo Molnar } 17386470930SIngo Molnar 174a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 175a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 176a91e5431SArnaldo Carvalho de Melo { 177a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 178a91e5431SArnaldo Carvalho de Melo 179a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 180a91e5431SArnaldo Carvalho de Melo return false; 181a91e5431SArnaldo Carvalho de Melo 1820c21f736SArnaldo Carvalho de Melo pair = perf_evlist__first(other); 183a91e5431SArnaldo Carvalho de Melo 184a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 185a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 186a91e5431SArnaldo Carvalho de Melo return false; 1870c21f736SArnaldo Carvalho de Melo pair = perf_evsel__next(pair); 188a91e5431SArnaldo Carvalho de Melo } 189a91e5431SArnaldo Carvalho de Melo 190a91e5431SArnaldo Carvalho de Melo return true; 191a91e5431SArnaldo Carvalho de Melo } 192a91e5431SArnaldo Carvalho de Melo 1938d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec) 194dd7927f4SArnaldo Carvalho de Melo { 1956a4bb04cSJiri Olsa struct perf_evsel *pos; 196d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 197d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 198d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 1998d3eca20SDavid Ahern int rc = 0; 200dd7927f4SArnaldo Carvalho de Melo 201d20deb64SArnaldo Carvalho de Melo perf_evlist__config_attrs(evlist, opts); 2020f82ebc4SArnaldo Carvalho de Melo 2036a4bb04cSJiri Olsa if (opts->group) 20463dab225SArnaldo Carvalho de Melo perf_evlist__set_leader(evlist); 2056a4bb04cSJiri Olsa 206dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 207dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 208dd7927f4SArnaldo Carvalho de Melo /* 209dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 210dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 211dd7927f4SArnaldo Carvalho de Melo * 212dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 213dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 214dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 215dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 216dd7927f4SArnaldo Carvalho de Melo * 217dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 218dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 219dd7927f4SArnaldo Carvalho de Melo */ 220dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 221dd7927f4SArnaldo Carvalho de Melo 2220c978128SArnaldo Carvalho de Melo fallback_missing_features: 2230c978128SArnaldo Carvalho de Melo if (opts->exclude_guest_missing) 2240c978128SArnaldo Carvalho de Melo attr->exclude_guest = attr->exclude_host = 0; 2259c90a61cSArnaldo Carvalho de Melo retry_sample_id: 226808e1226SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 2273da297a6SIngo Molnar try_again: 2286a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 22986470930SIngo Molnar int err = errno; 23086470930SIngo Molnar 231c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 232b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 2338d3eca20SDavid Ahern rc = -err; 2348d3eca20SDavid Ahern goto out; 235bea03405SNamhyung Kim } else if (err == ENODEV && opts->target.cpu_list) { 2368d3eca20SDavid Ahern pr_err("No such device - did you specify" 237d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2388d3eca20SDavid Ahern rc = -err; 2398d3eca20SDavid Ahern goto out; 2400c978128SArnaldo Carvalho de Melo } else if (err == EINVAL) { 2410c978128SArnaldo Carvalho de Melo if (!opts->exclude_guest_missing && 2420c978128SArnaldo Carvalho de Melo (attr->exclude_guest || attr->exclude_host)) { 2430c978128SArnaldo Carvalho de Melo pr_debug("Old kernel, cannot exclude " 2440c978128SArnaldo Carvalho de Melo "guest or host samples.\n"); 2450c978128SArnaldo Carvalho de Melo opts->exclude_guest_missing = true; 2460c978128SArnaldo Carvalho de Melo goto fallback_missing_features; 247808e1226SArnaldo Carvalho de Melo } else if (!opts->sample_id_all_missing) { 2489c90a61cSArnaldo Carvalho de Melo /* 2499c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2509c90a61cSArnaldo Carvalho de Melo */ 251808e1226SArnaldo Carvalho de Melo opts->sample_id_all_missing = true; 252d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 253eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 254eac23d1cSIan Munsie 2559c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 256d6d901c2SZhang, Yanmin } 2570c978128SArnaldo Carvalho de Melo } 2583da297a6SIngo Molnar 2593da297a6SIngo Molnar /* 2603da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2613da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 262028d455bSDavid Ahern * is always available even if no PMU support. 263028d455bSDavid Ahern * 264028d455bSDavid Ahern * PPC returns ENXIO until 2.6.37 (behavior changed 265028d455bSDavid Ahern * with commit b0a873e). 2663da297a6SIngo Molnar */ 267028d455bSDavid Ahern if ((err == ENOENT || err == ENXIO) 268028d455bSDavid Ahern && attr->type == PERF_TYPE_HARDWARE 269f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2703da297a6SIngo Molnar 2713da297a6SIngo Molnar if (verbose) 272ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 273ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2743da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 275f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 276d1cae34dSDavid Ahern if (pos->name) { 277d1cae34dSDavid Ahern free(pos->name); 278d1cae34dSDavid Ahern pos->name = NULL; 279d1cae34dSDavid Ahern } 2803da297a6SIngo Molnar goto try_again; 2813da297a6SIngo Molnar } 282ca6a4258SDavid Ahern 283ca6a4258SDavid Ahern if (err == ENOENT) { 2843780f488SNamhyung Kim ui__error("The %s event is not supported.\n", 2857289f83cSArnaldo Carvalho de Melo perf_evsel__name(pos)); 2868d3eca20SDavid Ahern rc = -err; 2878d3eca20SDavid Ahern goto out; 288ca6a4258SDavid Ahern } 289ca6a4258SDavid Ahern 29030c806a0SIngo Molnar printf("\n"); 2911863fbbbSStephane Eranian error("sys_perf_event_open() syscall returned with %d " 2921863fbbbSStephane Eranian "(%s) for event %s. /bin/dmesg may provide " 2931863fbbbSStephane Eranian "additional information.\n", 2941863fbbbSStephane Eranian err, strerror(err), perf_evsel__name(pos)); 295bfd45118SSimon Kaempflein 296bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 2978d3eca20SDavid Ahern if (attr->type == PERF_TYPE_HARDWARE && 2988d3eca20SDavid Ahern err == EOPNOTSUPP) { 2998d3eca20SDavid Ahern pr_err("No hardware sampling interrupt available." 300d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 301d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 302d6d901c2SZhang, Yanmin " force-enable it.\n"); 3038d3eca20SDavid Ahern rc = -err; 3048d3eca20SDavid Ahern goto out; 3058d3eca20SDavid Ahern } 306bfd45118SSimon Kaempflein #endif 307bfd45118SSimon Kaempflein 3088d3eca20SDavid Ahern pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 3098d3eca20SDavid Ahern rc = -err; 3108d3eca20SDavid Ahern goto out; 3117c6a1c65SPeter Zijlstra } 3127c6a1c65SPeter Zijlstra } 3137c6a1c65SPeter Zijlstra 3141491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 3150a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 3160a102479SFrederic Weisbecker strerror(errno)); 3178d3eca20SDavid Ahern rc = -1; 3188d3eca20SDavid Ahern goto out; 3190a102479SFrederic Weisbecker } 3200a102479SFrederic Weisbecker 32118e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 3228d3eca20SDavid Ahern if (errno == EPERM) { 3238d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 32418e60939SNelson Elhage "Consider increasing " 32518e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 32618e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 32718e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 3288d3eca20SDavid Ahern rc = -errno; 3298d3eca20SDavid Ahern } else if (!is_power_of_2(opts->mmap_pages)) { 3308d3eca20SDavid Ahern pr_err("--mmap_pages/-m value must be a power of two."); 3318d3eca20SDavid Ahern rc = -EINVAL; 3328d3eca20SDavid Ahern } else { 3338d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 3348d3eca20SDavid Ahern rc = -errno; 3358d3eca20SDavid Ahern } 3368d3eca20SDavid Ahern goto out; 33718e60939SNelson Elhage } 3380a27d7f9SArnaldo Carvalho de Melo 339d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 340a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 341a91e5431SArnaldo Carvalho de Melo else { 342a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 343a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 3448d3eca20SDavid Ahern rc = -1; 3458d3eca20SDavid Ahern goto out; 346dd7927f4SArnaldo Carvalho de Melo } 34786470930SIngo Molnar } 34886470930SIngo Molnar 3497b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3508d3eca20SDavid Ahern out: 3518d3eca20SDavid Ahern return rc; 352a91e5431SArnaldo Carvalho de Melo } 353a91e5431SArnaldo Carvalho de Melo 354d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3556122e4e4SArnaldo Carvalho de Melo { 356d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3576122e4e4SArnaldo Carvalho de Melo 3589f591fd7SArnaldo Carvalho de Melo if (size == 0) 3599f591fd7SArnaldo Carvalho de Melo return 0; 3609f591fd7SArnaldo Carvalho de Melo 361d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 362d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 363d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3646122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3656122e4e4SArnaldo Carvalho de Melo } 3666122e4e4SArnaldo Carvalho de Melo 3678d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 368f5970550SPeter Zijlstra { 369d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 370f5970550SPeter Zijlstra 3718d3eca20SDavid Ahern if (status != 0) 3728d3eca20SDavid Ahern return; 3738d3eca20SDavid Ahern 374d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 375d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 376d20deb64SArnaldo Carvalho de Melo 377d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 378d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 379d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 380d20deb64SArnaldo Carvalho de Melo rec->output, true); 381d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 382d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 383d65a458bSArnaldo Carvalho de Melo symbol__exit(); 384c7929e47STom Zanussi } 385f5970550SPeter Zijlstra } 386f5970550SPeter Zijlstra 3878115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 388a1645ce1SZhang, Yanmin { 389a1645ce1SZhang, Yanmin int err; 39045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 391a1645ce1SZhang, Yanmin 39223346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 393a1645ce1SZhang, Yanmin return; 394a1645ce1SZhang, Yanmin 395a1645ce1SZhang, Yanmin /* 396a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 397a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 398a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 399a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 400a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 401a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 402a1645ce1SZhang, Yanmin */ 40345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 404743eb868SArnaldo Carvalho de Melo machine); 405a1645ce1SZhang, Yanmin if (err < 0) 406a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 408a1645ce1SZhang, Yanmin 409a1645ce1SZhang, Yanmin /* 410a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 411a1645ce1SZhang, Yanmin * have no _text sometimes. 412a1645ce1SZhang, Yanmin */ 41345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 414743eb868SArnaldo Carvalho de Melo machine, "_text"); 415a1645ce1SZhang, Yanmin if (err < 0) 41645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 417743eb868SArnaldo Carvalho de Melo machine, "_stext"); 418a1645ce1SZhang, Yanmin if (err < 0) 419a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 42023346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 421a1645ce1SZhang, Yanmin } 422a1645ce1SZhang, Yanmin 42398402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 42498402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 42598402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 42698402807SFrederic Weisbecker }; 42798402807SFrederic Weisbecker 4288d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 42998402807SFrederic Weisbecker { 4300e2e63ddSPeter Zijlstra int i; 4318d3eca20SDavid Ahern int rc = 0; 43298402807SFrederic Weisbecker 433d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 4348d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 4358d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 4368d3eca20SDavid Ahern rc = -1; 4378d3eca20SDavid Ahern goto out; 4388d3eca20SDavid Ahern } 4398d3eca20SDavid Ahern } 44098402807SFrederic Weisbecker } 44198402807SFrederic Weisbecker 4422eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 4438d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 4448d3eca20SDavid Ahern sizeof(finished_round_event)); 4458d3eca20SDavid Ahern 4468d3eca20SDavid Ahern out: 4478d3eca20SDavid Ahern return rc; 44898402807SFrederic Weisbecker } 44998402807SFrederic Weisbecker 450d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 45186470930SIngo Molnar { 45286470930SIngo Molnar struct stat st; 45386470930SIngo Molnar int flags; 454781ba9d2SRobert Richter int err, output, feat; 4558b412664SPeter Zijlstra unsigned long waking = 0; 45646be604bSZhang, Yanmin const bool forks = argc > 0; 45723346f21SArnaldo Carvalho de Melo struct machine *machine; 45845694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 459d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 460d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 461d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 462d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 46386470930SIngo Molnar 464d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 46533e49ea7SAndi Kleen 466d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 46786470930SIngo Molnar 468d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 469f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 470f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 47118483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 472f5970550SPeter Zijlstra 473d7065adbSFranck Bui-Huu if (!output_name) { 474d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 475d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 476d7065adbSFranck Bui-Huu else 477d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 478d7065adbSFranck Bui-Huu } 479d7065adbSFranck Bui-Huu if (output_name) { 480529870e3STom Zanussi if (!strcmp(output_name, "-")) 481d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 482529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 483d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 484b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 485b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 486b38d3464SArnaldo Carvalho de Melo output_name); 487b38d3464SArnaldo Carvalho de Melo unlink(oldname); 488b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 489b38d3464SArnaldo Carvalho de Melo } 490d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 491d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 492266e0e21SPierre Habouzit } 493d7065adbSFranck Bui-Huu } 49486470930SIngo Molnar 495f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 496d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 497d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 49886470930SIngo Molnar else 49986470930SIngo Molnar flags |= O_TRUNC; 50086470930SIngo Molnar 501d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 502529870e3STom Zanussi output = STDOUT_FILENO; 503529870e3STom Zanussi else 50486470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 50586470930SIngo Molnar if (output < 0) { 50686470930SIngo Molnar perror("failed to create output file"); 5078d3eca20SDavid Ahern return -1; 50886470930SIngo Molnar } 50986470930SIngo Molnar 510d20deb64SArnaldo Carvalho de Melo rec->output = output; 511d20deb64SArnaldo Carvalho de Melo 5127865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 513d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 51494c744b6SArnaldo Carvalho de Melo if (session == NULL) { 515a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 516a9a70bbcSArnaldo Carvalho de Melo return -1; 517a9a70bbcSArnaldo Carvalho de Melo } 518a9a70bbcSArnaldo Carvalho de Melo 519d20deb64SArnaldo Carvalho de Melo rec->session = session; 520d20deb64SArnaldo Carvalho de Melo 521781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 522781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 523781ba9d2SRobert Richter 524781ba9d2SRobert Richter if (rec->no_buildid) 525781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 526781ba9d2SRobert Richter 527781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 5282eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 529baa2f6ceSArnaldo Carvalho de Melo 530330aa675SStephane Eranian if (!rec->opts.branch_stack) 531330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 532330aa675SStephane Eranian 533d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 534a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 5354dc0a04bSArnaldo Carvalho de Melo if (err < 0) 53639d17dacSArnaldo Carvalho de Melo goto out_delete_session; 5374dc0a04bSArnaldo Carvalho de Melo } 5384dc0a04bSArnaldo Carvalho de Melo 539d4db3f16SArnaldo Carvalho de Melo if (forks) { 540d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 54135b9d88eSArnaldo Carvalho de Melo if (err < 0) { 54235b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 54335b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 544856e9660SPeter Zijlstra } 545856e9660SPeter Zijlstra } 546856e9660SPeter Zijlstra 5478d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 5488d3eca20SDavid Ahern err = -1; 5498d3eca20SDavid Ahern goto out_delete_session; 5508d3eca20SDavid Ahern } 55186470930SIngo Molnar 552712a4b60SArnaldo Carvalho de Melo /* 553d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 554712a4b60SArnaldo Carvalho de Melo */ 555d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 556712a4b60SArnaldo Carvalho de Melo 557d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 558529870e3STom Zanussi err = perf_header__write_pipe(output); 559529870e3STom Zanussi if (err < 0) 5608d3eca20SDavid Ahern goto out_delete_session; 561d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 562a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 563361c99a6SArnaldo Carvalho de Melo output, false); 564d5eed904SArnaldo Carvalho de Melo if (err < 0) 5658d3eca20SDavid Ahern goto out_delete_session; 566d5eed904SArnaldo Carvalho de Melo } 5677c6a1c65SPeter Zijlstra 568d3665498SDavid Ahern if (!rec->no_buildid 569e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 570d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 571e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5728d3eca20SDavid Ahern err = -1; 5738d3eca20SDavid Ahern goto out_delete_session; 574e20960c0SRobert Richter } 575e20960c0SRobert Richter 576d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5776122e4e4SArnaldo Carvalho de Melo 578743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 579743eb868SArnaldo Carvalho de Melo if (!machine) { 580743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 5818d3eca20SDavid Ahern err = -1; 5828d3eca20SDavid Ahern goto out_delete_session; 583743eb868SArnaldo Carvalho de Melo } 584743eb868SArnaldo Carvalho de Melo 585d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 58645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 587a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5882c46dbb5STom Zanussi if (err < 0) { 5892c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5908d3eca20SDavid Ahern goto out_delete_session; 5912c46dbb5STom Zanussi } 592cd19a035STom Zanussi 59345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 594743eb868SArnaldo Carvalho de Melo machine); 595cd19a035STom Zanussi if (err < 0) { 596cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 5978d3eca20SDavid Ahern goto out_delete_session; 598cd19a035STom Zanussi } 5999215545eSTom Zanussi 600361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 60163e0c771STom Zanussi /* 60263e0c771STom Zanussi * FIXME err <= 0 here actually means that 60363e0c771STom Zanussi * there were no tracepoints so its not really 60463e0c771STom Zanussi * an error, just that we don't need to 60563e0c771STom Zanussi * synthesize anything. We really have to 60663e0c771STom Zanussi * return this more properly and also 60763e0c771STom Zanussi * propagate errors that now are calling die() 60863e0c771STom Zanussi */ 60945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 610743eb868SArnaldo Carvalho de Melo process_synthesized_event); 61163e0c771STom Zanussi if (err <= 0) { 61263e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 6138d3eca20SDavid Ahern goto out_delete_session; 61463e0c771STom Zanussi } 615d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 6162c46dbb5STom Zanussi } 61763e0c771STom Zanussi } 6182c46dbb5STom Zanussi 61945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 620743eb868SArnaldo Carvalho de Melo machine, "_text"); 62170162138SArnaldo Carvalho de Melo if (err < 0) 62245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 623743eb868SArnaldo Carvalho de Melo machine, "_stext"); 624c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 625c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 626c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 627c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 62856b03f3cSArnaldo Carvalho de Melo 62945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 630743eb868SArnaldo Carvalho de Melo machine); 631c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 632c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 633c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 634c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 635c1a3a4b9SArnaldo Carvalho de Melo 636a1645ce1SZhang, Yanmin if (perf_guest) 63745694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 6388115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 639b7cece76SArnaldo Carvalho de Melo 640bea03405SNamhyung Kim if (!opts->target.system_wide) 6418d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 6428115d60cSArnaldo Carvalho de Melo process_synthesized_event, 643743eb868SArnaldo Carvalho de Melo machine); 644234fbbf5SArnaldo Carvalho de Melo else 6458d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 646743eb868SArnaldo Carvalho de Melo machine); 6477c6a1c65SPeter Zijlstra 6488d3eca20SDavid Ahern if (err != 0) 6498d3eca20SDavid Ahern goto out_delete_session; 6508d3eca20SDavid Ahern 651d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 65286470930SIngo Molnar struct sched_param param; 65386470930SIngo Molnar 654d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 65586470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6566beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6578d3eca20SDavid Ahern err = -1; 6588d3eca20SDavid Ahern goto out_delete_session; 65986470930SIngo Molnar } 66086470930SIngo Molnar } 66186470930SIngo Molnar 662764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 663764e16a3SDavid Ahern 664856e9660SPeter Zijlstra /* 665856e9660SPeter Zijlstra * Let the child rip 666856e9660SPeter Zijlstra */ 667d4db3f16SArnaldo Carvalho de Melo if (forks) 66835b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 669856e9660SPeter Zijlstra 670649c48a9SPeter Zijlstra for (;;) { 671d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 67286470930SIngo Molnar 6738d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 6748d3eca20SDavid Ahern err = -1; 6758d3eca20SDavid Ahern goto out_delete_session; 6768d3eca20SDavid Ahern } 67786470930SIngo Molnar 678d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 679649c48a9SPeter Zijlstra if (done) 680649c48a9SPeter Zijlstra break; 6815c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6828b412664SPeter Zijlstra waking++; 6838b412664SPeter Zijlstra } 6848b412664SPeter Zijlstra 6854152ab37SArnaldo Carvalho de Melo if (done) 6864152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6878b412664SPeter Zijlstra } 6888b412664SPeter Zijlstra 68918483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 690b44308f5SArnaldo Carvalho de Melo return 0; 691b44308f5SArnaldo Carvalho de Melo 6928b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 69386470930SIngo Molnar 69486470930SIngo Molnar /* 69586470930SIngo Molnar * Approximate RIP event size: 24 bytes. 69686470930SIngo Molnar */ 69786470930SIngo Molnar fprintf(stderr, 6989486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 699d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 70086470930SIngo Molnar output_name, 701d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 70286470930SIngo Molnar 70386470930SIngo Molnar return 0; 70439d17dacSArnaldo Carvalho de Melo 70539d17dacSArnaldo Carvalho de Melo out_delete_session: 70639d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 70739d17dacSArnaldo Carvalho de Melo return err; 70886470930SIngo Molnar } 70986470930SIngo Molnar 710bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 711bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 712bdfebd84SRoberto Agostino Vitillo 713bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 714bdfebd84SRoberto Agostino Vitillo 715bdfebd84SRoberto Agostino Vitillo struct branch_mode { 716bdfebd84SRoberto Agostino Vitillo const char *name; 717bdfebd84SRoberto Agostino Vitillo int mode; 718bdfebd84SRoberto Agostino Vitillo }; 719bdfebd84SRoberto Agostino Vitillo 720bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 721bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 722bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 723bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 724bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 725bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 726bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 727bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 728bdfebd84SRoberto Agostino Vitillo BRANCH_END 729bdfebd84SRoberto Agostino Vitillo }; 730bdfebd84SRoberto Agostino Vitillo 731bdfebd84SRoberto Agostino Vitillo static int 732a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 733bdfebd84SRoberto Agostino Vitillo { 734bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 735bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 736bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 737bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 738bdfebd84SRoberto Agostino Vitillo 739bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 740bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 741a5aabdacSStephane Eranian char *s, *os = NULL, *p; 742bdfebd84SRoberto Agostino Vitillo int ret = -1; 743bdfebd84SRoberto Agostino Vitillo 744a5aabdacSStephane Eranian if (unset) 745a5aabdacSStephane Eranian return 0; 746bdfebd84SRoberto Agostino Vitillo 747a5aabdacSStephane Eranian /* 748a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 749a5aabdacSStephane Eranian */ 750a5aabdacSStephane Eranian if (*mode) 751a5aabdacSStephane Eranian return -1; 752a5aabdacSStephane Eranian 753a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 754a5aabdacSStephane Eranian if (str) { 755bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 756bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 757bdfebd84SRoberto Agostino Vitillo if (!s) 758bdfebd84SRoberto Agostino Vitillo return -1; 759bdfebd84SRoberto Agostino Vitillo 760bdfebd84SRoberto Agostino Vitillo for (;;) { 761bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 762bdfebd84SRoberto Agostino Vitillo if (p) 763bdfebd84SRoberto Agostino Vitillo *p = '\0'; 764bdfebd84SRoberto Agostino Vitillo 765bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 766bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 767bdfebd84SRoberto Agostino Vitillo break; 768bdfebd84SRoberto Agostino Vitillo } 769a5aabdacSStephane Eranian if (!br->name) { 770a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 771a5aabdacSStephane Eranian " check man page\n", s); 772bdfebd84SRoberto Agostino Vitillo goto error; 773a5aabdacSStephane Eranian } 774bdfebd84SRoberto Agostino Vitillo 775bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 776bdfebd84SRoberto Agostino Vitillo 777bdfebd84SRoberto Agostino Vitillo if (!p) 778bdfebd84SRoberto Agostino Vitillo break; 779bdfebd84SRoberto Agostino Vitillo 780bdfebd84SRoberto Agostino Vitillo s = p + 1; 781bdfebd84SRoberto Agostino Vitillo } 782a5aabdacSStephane Eranian } 783bdfebd84SRoberto Agostino Vitillo ret = 0; 784bdfebd84SRoberto Agostino Vitillo 785a5aabdacSStephane Eranian /* default to any branch */ 786bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 787a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 788bdfebd84SRoberto Agostino Vitillo } 789bdfebd84SRoberto Agostino Vitillo error: 790bdfebd84SRoberto Agostino Vitillo free(os); 791bdfebd84SRoberto Agostino Vitillo return ret; 792bdfebd84SRoberto Agostino Vitillo } 793bdfebd84SRoberto Agostino Vitillo 79495485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 79526d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 79626d33022SJiri Olsa { 79726d33022SJiri Olsa char *endptr; 79826d33022SJiri Olsa unsigned long size; 79926d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 80026d33022SJiri Olsa 80126d33022SJiri Olsa size = strtoul(str, &endptr, 0); 80226d33022SJiri Olsa 80326d33022SJiri Olsa do { 80426d33022SJiri Olsa if (*endptr) 80526d33022SJiri Olsa break; 80626d33022SJiri Olsa 80726d33022SJiri Olsa size = round_up(size, sizeof(u64)); 80826d33022SJiri Olsa if (!size || size > max_size) 80926d33022SJiri Olsa break; 81026d33022SJiri Olsa 81126d33022SJiri Olsa *_size = size; 81226d33022SJiri Olsa return 0; 81326d33022SJiri Olsa 81426d33022SJiri Olsa } while (0); 81526d33022SJiri Olsa 81626d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 81726d33022SJiri Olsa max_size, str); 81826d33022SJiri Olsa return -1; 81926d33022SJiri Olsa } 82095485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 82126d33022SJiri Olsa 82226d33022SJiri Olsa static int 8231d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 82426d33022SJiri Olsa int unset) 82526d33022SJiri Olsa { 82626d33022SJiri Olsa struct perf_record *rec = (struct perf_record *)opt->value; 82726d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 82826d33022SJiri Olsa char *buf; 82926d33022SJiri Olsa int ret = -1; 83026d33022SJiri Olsa 83126d33022SJiri Olsa /* --no-call-graph */ 83226d33022SJiri Olsa if (unset) 83326d33022SJiri Olsa return 0; 83426d33022SJiri Olsa 83526d33022SJiri Olsa /* We specified default option if none is provided. */ 83626d33022SJiri Olsa BUG_ON(!arg); 83726d33022SJiri Olsa 83826d33022SJiri Olsa /* We need buffer that we know we can write to. */ 83926d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 84026d33022SJiri Olsa if (!buf) 84126d33022SJiri Olsa return -ENOMEM; 84226d33022SJiri Olsa 84326d33022SJiri Olsa strcpy(buf, arg); 84426d33022SJiri Olsa 84526d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 84626d33022SJiri Olsa name = tok ? : (char *)buf; 84726d33022SJiri Olsa 84826d33022SJiri Olsa do { 84926d33022SJiri Olsa /* Framepointer style */ 85026d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 85126d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 85226d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_FP; 85326d33022SJiri Olsa ret = 0; 85426d33022SJiri Olsa } else 85526d33022SJiri Olsa pr_err("callchain: No more arguments " 85626d33022SJiri Olsa "needed for -g fp\n"); 85726d33022SJiri Olsa break; 85826d33022SJiri Olsa 85995485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 86026d33022SJiri Olsa /* Dwarf style */ 86126d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 862*61eaa3beSArnaldo Carvalho de Melo const unsigned long default_stack_dump_size = 8192; 863*61eaa3beSArnaldo Carvalho de Melo 86426d33022SJiri Olsa ret = 0; 86526d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_DWARF; 86626d33022SJiri Olsa rec->opts.stack_dump_size = default_stack_dump_size; 86726d33022SJiri Olsa 86826d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 86926d33022SJiri Olsa if (tok) { 87026d33022SJiri Olsa unsigned long size = 0; 87126d33022SJiri Olsa 87226d33022SJiri Olsa ret = get_stack_size(tok, &size); 87326d33022SJiri Olsa rec->opts.stack_dump_size = size; 87426d33022SJiri Olsa } 87526d33022SJiri Olsa 87626d33022SJiri Olsa if (!ret) 87726d33022SJiri Olsa pr_debug("callchain: stack dump size %d\n", 87826d33022SJiri Olsa rec->opts.stack_dump_size); 87995485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 88026d33022SJiri Olsa } else { 88126d33022SJiri Olsa pr_err("callchain: Unknown -g option " 88226d33022SJiri Olsa "value: %s\n", arg); 88326d33022SJiri Olsa break; 88426d33022SJiri Olsa } 88526d33022SJiri Olsa 88626d33022SJiri Olsa } while (0); 88726d33022SJiri Olsa 88826d33022SJiri Olsa free(buf); 88926d33022SJiri Olsa 89026d33022SJiri Olsa if (!ret) 89126d33022SJiri Olsa pr_debug("callchain: type %d\n", rec->opts.call_graph); 89226d33022SJiri Olsa 89326d33022SJiri Olsa return ret; 89426d33022SJiri Olsa } 89526d33022SJiri Olsa 89686470930SIngo Molnar static const char * const record_usage[] = { 89786470930SIngo Molnar "perf record [<options>] [<command>]", 89886470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 89986470930SIngo Molnar NULL 90086470930SIngo Molnar }; 90186470930SIngo Molnar 902d20deb64SArnaldo Carvalho de Melo /* 903d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 904d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 905d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 906d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 907d20deb64SArnaldo Carvalho de Melo * 908d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 909d20deb64SArnaldo Carvalho de Melo * 910d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 911d20deb64SArnaldo Carvalho de Melo */ 912d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 913d20deb64SArnaldo Carvalho de Melo .opts = { 914d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 915d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 916d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 917447a6013SArnaldo Carvalho de Melo .freq = 4000, 918d1cb9fceSNamhyung Kim .target = { 919d1cb9fceSNamhyung Kim .uses_mmap = true, 920d1cb9fceSNamhyung Kim }, 921d20deb64SArnaldo Carvalho de Melo }, 922d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 923d20deb64SArnaldo Carvalho de Melo .file_new = true, 924d20deb64SArnaldo Carvalho de Melo }; 9257865e817SFrederic Weisbecker 926*61eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 927*61eaa3beSArnaldo Carvalho de Melo 928*61eaa3beSArnaldo Carvalho de Melo #ifdef LIBUNWIND_SUPPORT 929*61eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 930*61eaa3beSArnaldo Carvalho de Melo #else 931*61eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp]"; 932*61eaa3beSArnaldo Carvalho de Melo #endif 933*61eaa3beSArnaldo Carvalho de Melo 934d20deb64SArnaldo Carvalho de Melo /* 935d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 936d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 937d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 938d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 939d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 940d20deb64SArnaldo Carvalho de Melo */ 941bca647aaSTom Zanussi const struct option record_options[] = { 942d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 94386470930SIngo Molnar "event selector. use 'perf list' to list available events", 944f120f9d5SJiri Olsa parse_events_option), 945d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 946c171b552SLi Zefan "event filter", parse_filter), 947bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 948d6d901c2SZhang, Yanmin "record events on existing process id"), 949bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 950d6d901c2SZhang, Yanmin "record events on existing thread id"), 951d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 95286470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 953d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 954acac03faSKirill Smelkov "collect data without buffering"), 955d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 956daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 957bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 95886470930SIngo Molnar "system-wide collection from all CPUs"), 959d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 96086470930SIngo Molnar "append to the output file to do incremental profiling"), 961bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 962c45c6ea2SStephane Eranian "list of cpus to monitor"), 963d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 9647865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 965d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 966d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 96786470930SIngo Molnar "output file name"), 968d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 9692e6cdf99SStephane Eranian "child tasks do not inherit counters"), 970d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 971d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 97201c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 973d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 97443bece79SLin Ming "put the counters into a counter group"), 97526d33022SJiri Olsa OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", 97626d33022SJiri Olsa callchain_help, &parse_callchain_opt, 97726d33022SJiri Olsa "fp"), 978c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 9793da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 980b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 981d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 982649c48a9SPeter Zijlstra "per thread counts"), 983d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 9844bba828dSAnton Blanchard "Sample addresses"), 985d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 9863e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 987d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 988649c48a9SPeter Zijlstra "don't sample"), 989d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 990a1ac1d3cSStephane Eranian "do not update the buildid cache"), 991d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 992baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 993d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 994023695d9SStephane Eranian "monitor event in cgroup name only", 995023695d9SStephane Eranian parse_cgroups), 996bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 997bea03405SNamhyung Kim "user to profile"), 998a5aabdacSStephane Eranian 999a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1000a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1001a5aabdacSStephane Eranian parse_branch_stack), 1002a5aabdacSStephane Eranian 1003a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1004a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1005bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 100686470930SIngo Molnar OPT_END() 100786470930SIngo Molnar }; 100886470930SIngo Molnar 10091d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 101086470930SIngo Molnar { 101169aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 101269aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 1013d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 1014d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 101516ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 101686470930SIngo Molnar 10177e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 1018361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1019361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1020361c99a6SArnaldo Carvalho de Melo 1021d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 1022d20deb64SArnaldo Carvalho de Melo 1023bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1024a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1025d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 1026bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 102786470930SIngo Molnar 1028d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 10293780f488SNamhyung Kim ui__error("Can't overwrite and append at the same time." 10307865e817SFrederic Weisbecker " You need to choose between -f and -A"); 1031bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 1032d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 1033d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 10347865e817SFrederic Weisbecker } else { 1035d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 10367865e817SFrederic Weisbecker } 10377865e817SFrederic Weisbecker 1038bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 10393780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1040023695d9SStephane Eranian " system-wide mode\n"); 1041023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1042023695d9SStephane Eranian } 1043023695d9SStephane Eranian 1044655000e7SArnaldo Carvalho de Melo symbol__init(); 1045baa2f6ceSArnaldo Carvalho de Melo 1046ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1047646aaea6SArnaldo Carvalho de Melo pr_warning( 1048646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1049ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1050646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1051646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1052646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1053646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1054646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1055ec80fde7SArnaldo Carvalho de Melo 1056d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1057a1ac1d3cSStephane Eranian disable_buildid_cache(); 1058655000e7SArnaldo Carvalho de Melo 1059361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 1060361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 106169aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 106269aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1063bbd36e5eSPeter Zijlstra } 106486470930SIngo Molnar 106516ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 106616ad2ffbSNamhyung Kim if (err) { 106716ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 106816ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 106916ad2ffbSNamhyung Kim } 10704bd0f2d2SNamhyung Kim 107116ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 107216ad2ffbSNamhyung Kim if (err) { 107316ad2ffbSNamhyung Kim int saved_errno = errno; 107416ad2ffbSNamhyung Kim 107516ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 10763780f488SNamhyung Kim ui__error("%s", errbuf); 107716ad2ffbSNamhyung Kim 107816ad2ffbSNamhyung Kim err = -saved_errno; 10790d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 108016ad2ffbSNamhyung Kim } 10810d37aa34SArnaldo Carvalho de Melo 108216ad2ffbSNamhyung Kim err = -ENOMEM; 1083b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 1084dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 108569aad6f1SArnaldo Carvalho de Melo 1086361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 10877289f83cSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) 1088ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 1089d6d901c2SZhang, Yanmin } 10905c581041SArnaldo Carvalho de Melo 1091d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 1092d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 1093d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 1094d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 1095f9212819SFrederic Weisbecker 10967e4ff9e3SMike Galbraith /* 10977e4ff9e3SMike Galbraith * User specified count overrides default frequency. 10987e4ff9e3SMike Galbraith */ 1099d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 1100d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 1101d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 1102d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 11037e4ff9e3SMike Galbraith } else { 11043780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 110539d17dacSArnaldo Carvalho de Melo err = -EINVAL; 11065c581041SArnaldo Carvalho de Melo goto out_free_fd; 11077e4ff9e3SMike Galbraith } 11087e4ff9e3SMike Galbraith 1109d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 111039d17dacSArnaldo Carvalho de Melo out_free_fd: 11117e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 1112d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 1113d65a458bSArnaldo Carvalho de Melo symbol__exit(); 111439d17dacSArnaldo Carvalho de Melo return err; 111586470930SIngo Molnar } 1116