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 */ 886470930SIngo Molnar #include "builtin.h" 986470930SIngo Molnar 1086470930SIngo Molnar #include "perf.h" 1186470930SIngo Molnar 126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1386470930SIngo Molnar #include "util/util.h" 1486470930SIngo Molnar #include "util/parse-options.h" 1586470930SIngo Molnar #include "util/parse-events.h" 1686470930SIngo Molnar 177c6a1c65SPeter Zijlstra #include "util/header.h" 1866e274f3SFrederic Weisbecker #include "util/event.h" 19361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2069aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 218f28827aSFrederic Weisbecker #include "util/debug.h" 2294c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2345694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 248d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 25a12b51c4SPaul Mackerras #include "util/cpumap.h" 26fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 277c6a1c65SPeter Zijlstra 2886470930SIngo Molnar #include <unistd.h> 2986470930SIngo Molnar #include <sched.h> 30a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3186470930SIngo Molnar 3278da39faSBernhard Rosenkraenzer #ifndef HAVE_ON_EXIT 3378da39faSBernhard Rosenkraenzer #ifndef ATEXIT_MAX 3478da39faSBernhard Rosenkraenzer #define ATEXIT_MAX 32 3578da39faSBernhard Rosenkraenzer #endif 3678da39faSBernhard Rosenkraenzer static int __on_exit_count = 0; 3778da39faSBernhard Rosenkraenzer typedef void (*on_exit_func_t) (int, void *); 3878da39faSBernhard Rosenkraenzer static on_exit_func_t __on_exit_funcs[ATEXIT_MAX]; 3978da39faSBernhard Rosenkraenzer static void *__on_exit_args[ATEXIT_MAX]; 4078da39faSBernhard Rosenkraenzer static int __exitcode = 0; 4178da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void); 4278da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg); 4378da39faSBernhard Rosenkraenzer #define exit(x) (exit)(__exitcode = (x)) 4478da39faSBernhard Rosenkraenzer 4578da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg) 4678da39faSBernhard Rosenkraenzer { 4778da39faSBernhard Rosenkraenzer if (__on_exit_count == ATEXIT_MAX) 4878da39faSBernhard Rosenkraenzer return -ENOMEM; 4978da39faSBernhard Rosenkraenzer else if (__on_exit_count == 0) 5078da39faSBernhard Rosenkraenzer atexit(__handle_on_exit_funcs); 5178da39faSBernhard Rosenkraenzer __on_exit_funcs[__on_exit_count] = function; 5278da39faSBernhard Rosenkraenzer __on_exit_args[__on_exit_count++] = arg; 5378da39faSBernhard Rosenkraenzer return 0; 5478da39faSBernhard Rosenkraenzer } 5578da39faSBernhard Rosenkraenzer 5678da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void) 5778da39faSBernhard Rosenkraenzer { 5878da39faSBernhard Rosenkraenzer int i; 5978da39faSBernhard Rosenkraenzer for (i = 0; i < __on_exit_count; i++) 6078da39faSBernhard Rosenkraenzer __on_exit_funcs[i] (__exitcode, __on_exit_args[i]); 6178da39faSBernhard Rosenkraenzer } 6278da39faSBernhard Rosenkraenzer #endif 6378da39faSBernhard Rosenkraenzer 647865e817SFrederic Weisbecker enum write_mode_t { 657865e817SFrederic Weisbecker WRITE_FORCE, 667865e817SFrederic Weisbecker WRITE_APPEND 677865e817SFrederic Weisbecker }; 687865e817SFrederic Weisbecker 69d20deb64SArnaldo Carvalho de Melo struct perf_record { 7045694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 71d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 72d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 73d20deb64SArnaldo Carvalho de Melo const char *output_name; 74d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 75d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 76d20deb64SArnaldo Carvalho de Melo const char *progname; 77d20deb64SArnaldo Carvalho de Melo int output; 78d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 79d20deb64SArnaldo Carvalho de Melo int realtime_prio; 80d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 81d20deb64SArnaldo Carvalho de Melo bool no_buildid; 82d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 83d20deb64SArnaldo Carvalho de Melo bool force; 84d20deb64SArnaldo Carvalho de Melo bool file_new; 85d20deb64SArnaldo Carvalho de Melo bool append_file; 86d20deb64SArnaldo Carvalho de Melo long samples; 87d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 880f82ebc4SArnaldo Carvalho de Melo }; 8986470930SIngo Molnar 90d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 919215545eSTom Zanussi { 92d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 939215545eSTom Zanussi } 949215545eSTom Zanussi 958d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size) 96f5970550SPeter Zijlstra { 97f5970550SPeter Zijlstra while (size) { 98d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 99f5970550SPeter Zijlstra 1008d3eca20SDavid Ahern if (ret < 0) { 1018d3eca20SDavid Ahern pr_err("failed to write\n"); 1028d3eca20SDavid Ahern return -1; 1038d3eca20SDavid Ahern } 104f5970550SPeter Zijlstra 105f5970550SPeter Zijlstra size -= ret; 106f5970550SPeter Zijlstra buf += ret; 107f5970550SPeter Zijlstra 108d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 109f5970550SPeter Zijlstra } 1108d3eca20SDavid Ahern 1118d3eca20SDavid Ahern return 0; 112f5970550SPeter Zijlstra } 113f5970550SPeter Zijlstra 11445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 115d20deb64SArnaldo Carvalho de Melo union perf_event *event, 1161d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 1171d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 118234fbbf5SArnaldo Carvalho de Melo { 11945694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 1208d3eca20SDavid Ahern if (write_output(rec, event, event->header.size) < 0) 1218d3eca20SDavid Ahern return -1; 1228d3eca20SDavid Ahern 123234fbbf5SArnaldo Carvalho de Melo return 0; 124234fbbf5SArnaldo Carvalho de Melo } 125234fbbf5SArnaldo Carvalho de Melo 1268d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec, 127d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 12886470930SIngo Molnar { 129744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 13086470930SIngo Molnar unsigned int old = md->prev; 131d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 13286470930SIngo Molnar unsigned long size; 13386470930SIngo Molnar void *buf; 1348d3eca20SDavid Ahern int rc = 0; 13586470930SIngo Molnar 136dc82009aSArnaldo Carvalho de Melo if (old == head) 1378d3eca20SDavid Ahern return 0; 13886470930SIngo Molnar 139d20deb64SArnaldo Carvalho de Melo rec->samples++; 14086470930SIngo Molnar 14186470930SIngo Molnar size = head - old; 14286470930SIngo Molnar 14386470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 14486470930SIngo Molnar buf = &data[old & md->mask]; 14586470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 14686470930SIngo Molnar old += size; 14786470930SIngo Molnar 1488d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1498d3eca20SDavid Ahern rc = -1; 1508d3eca20SDavid Ahern goto out; 1518d3eca20SDavid Ahern } 15286470930SIngo Molnar } 15386470930SIngo Molnar 15486470930SIngo Molnar buf = &data[old & md->mask]; 15586470930SIngo Molnar size = head - old; 15686470930SIngo Molnar old += size; 15786470930SIngo Molnar 1588d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1598d3eca20SDavid Ahern rc = -1; 1608d3eca20SDavid Ahern goto out; 1618d3eca20SDavid Ahern } 16286470930SIngo Molnar 16386470930SIngo Molnar md->prev = old; 164115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 1658d3eca20SDavid Ahern 1668d3eca20SDavid Ahern out: 1678d3eca20SDavid Ahern return rc; 16886470930SIngo Molnar } 16986470930SIngo Molnar 17086470930SIngo Molnar static volatile int done = 0; 171f7b7c26eSPeter Zijlstra static volatile int signr = -1; 17233e49ea7SAndi Kleen static volatile int child_finished = 0; 17386470930SIngo Molnar 17486470930SIngo Molnar static void sig_handler(int sig) 17586470930SIngo Molnar { 17633e49ea7SAndi Kleen if (sig == SIGCHLD) 17733e49ea7SAndi Kleen child_finished = 1; 17833e49ea7SAndi Kleen 17986470930SIngo Molnar done = 1; 180f7b7c26eSPeter Zijlstra signr = sig; 181f7b7c26eSPeter Zijlstra } 182f7b7c26eSPeter Zijlstra 1831d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 184f7b7c26eSPeter Zijlstra { 185d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 18633e49ea7SAndi Kleen int status; 18733e49ea7SAndi Kleen 188d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 18933e49ea7SAndi Kleen if (!child_finished) 190d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 191933da83aSChris Wilson 19233e49ea7SAndi Kleen wait(&status); 19333e49ea7SAndi Kleen if (WIFSIGNALED(status)) 194d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 19533e49ea7SAndi Kleen } 19633e49ea7SAndi Kleen 19718483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 198f7b7c26eSPeter Zijlstra return; 199f7b7c26eSPeter Zijlstra 200f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 201f7b7c26eSPeter Zijlstra kill(getpid(), signr); 20286470930SIngo Molnar } 20386470930SIngo Molnar 204a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 205a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 206a91e5431SArnaldo Carvalho de Melo { 207a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 208a91e5431SArnaldo Carvalho de Melo 209a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 210a91e5431SArnaldo Carvalho de Melo return false; 211a91e5431SArnaldo Carvalho de Melo 2120c21f736SArnaldo Carvalho de Melo pair = perf_evlist__first(other); 213a91e5431SArnaldo Carvalho de Melo 214a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 215a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 216a91e5431SArnaldo Carvalho de Melo return false; 2170c21f736SArnaldo Carvalho de Melo pair = perf_evsel__next(pair); 218a91e5431SArnaldo Carvalho de Melo } 219a91e5431SArnaldo Carvalho de Melo 220a91e5431SArnaldo Carvalho de Melo return true; 221a91e5431SArnaldo Carvalho de Melo } 222a91e5431SArnaldo Carvalho de Melo 2238d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec) 224dd7927f4SArnaldo Carvalho de Melo { 22556e52e85SArnaldo Carvalho de Melo char msg[512]; 2266a4bb04cSJiri Olsa struct perf_evsel *pos; 227d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 228d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 229d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 2308d3eca20SDavid Ahern int rc = 0; 231dd7927f4SArnaldo Carvalho de Melo 232f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 233cac21425SJiri Olsa 234dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 2353da297a6SIngo Molnar try_again: 2366a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 23756e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2383da297a6SIngo Molnar if (verbose) 239c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2403da297a6SIngo Molnar goto try_again; 2413da297a6SIngo Molnar } 242ca6a4258SDavid Ahern 24356e52e85SArnaldo Carvalho de Melo rc = -errno; 24456e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 24556e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 24656e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2478d3eca20SDavid Ahern goto out; 2487c6a1c65SPeter Zijlstra } 2497c6a1c65SPeter Zijlstra } 2507c6a1c65SPeter Zijlstra 2511491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 2520a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2530a102479SFrederic Weisbecker strerror(errno)); 2548d3eca20SDavid Ahern rc = -1; 2558d3eca20SDavid Ahern goto out; 2560a102479SFrederic Weisbecker } 2570a102479SFrederic Weisbecker 25818e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 2598d3eca20SDavid Ahern if (errno == EPERM) { 2608d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 26118e60939SNelson Elhage "Consider increasing " 26218e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 26318e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 26418e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 2658d3eca20SDavid Ahern rc = -errno; 2660089fa98SJiri Olsa } else if (!is_power_of_2(opts->mmap_pages) && 2670089fa98SJiri Olsa (opts->mmap_pages != UINT_MAX)) { 2688d3eca20SDavid Ahern pr_err("--mmap_pages/-m value must be a power of two."); 2698d3eca20SDavid Ahern rc = -EINVAL; 2708d3eca20SDavid Ahern } else { 2718d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 2728d3eca20SDavid Ahern rc = -errno; 2738d3eca20SDavid Ahern } 2748d3eca20SDavid Ahern goto out; 27518e60939SNelson Elhage } 2760a27d7f9SArnaldo Carvalho de Melo 277d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 278a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 279a91e5431SArnaldo Carvalho de Melo else { 280a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 281a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 2828d3eca20SDavid Ahern rc = -1; 2838d3eca20SDavid Ahern goto out; 284dd7927f4SArnaldo Carvalho de Melo } 28586470930SIngo Molnar } 28686470930SIngo Molnar 2877b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 2888d3eca20SDavid Ahern out: 2898d3eca20SDavid Ahern return rc; 290a91e5431SArnaldo Carvalho de Melo } 291a91e5431SArnaldo Carvalho de Melo 292d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 2936122e4e4SArnaldo Carvalho de Melo { 294d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 2956122e4e4SArnaldo Carvalho de Melo 2969f591fd7SArnaldo Carvalho de Melo if (size == 0) 2979f591fd7SArnaldo Carvalho de Melo return 0; 2989f591fd7SArnaldo Carvalho de Melo 299d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 300d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 301d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3026122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3036122e4e4SArnaldo Carvalho de Melo } 3046122e4e4SArnaldo Carvalho de Melo 3058d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 306f5970550SPeter Zijlstra { 307d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 308f5970550SPeter Zijlstra 3098d3eca20SDavid Ahern if (status != 0) 3108d3eca20SDavid Ahern return; 3118d3eca20SDavid Ahern 312d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 313d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 314d20deb64SArnaldo Carvalho de Melo 315d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 316d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 317d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 318d20deb64SArnaldo Carvalho de Melo rec->output, true); 319d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 320d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 321d65a458bSArnaldo Carvalho de Melo symbol__exit(); 322c7929e47STom Zanussi } 323f5970550SPeter Zijlstra } 324f5970550SPeter Zijlstra 3258115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 326a1645ce1SZhang, Yanmin { 327a1645ce1SZhang, Yanmin int err; 32845694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 329a1645ce1SZhang, Yanmin /* 330a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 331a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 332a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 333a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 334a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 335a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 336a1645ce1SZhang, Yanmin */ 33745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 338743eb868SArnaldo Carvalho de Melo machine); 339a1645ce1SZhang, Yanmin if (err < 0) 340a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 34123346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 342a1645ce1SZhang, Yanmin 343a1645ce1SZhang, Yanmin /* 344a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 345a1645ce1SZhang, Yanmin * have no _text sometimes. 346a1645ce1SZhang, Yanmin */ 34745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 348743eb868SArnaldo Carvalho de Melo machine, "_text"); 349a1645ce1SZhang, Yanmin if (err < 0) 35045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 351743eb868SArnaldo Carvalho de Melo machine, "_stext"); 352a1645ce1SZhang, Yanmin if (err < 0) 353a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 35423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 355a1645ce1SZhang, Yanmin } 356a1645ce1SZhang, Yanmin 35798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 35898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 35998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 36098402807SFrederic Weisbecker }; 36198402807SFrederic Weisbecker 3628d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 36398402807SFrederic Weisbecker { 3640e2e63ddSPeter Zijlstra int i; 3658d3eca20SDavid Ahern int rc = 0; 36698402807SFrederic Weisbecker 367d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 3688d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 3698d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 3708d3eca20SDavid Ahern rc = -1; 3718d3eca20SDavid Ahern goto out; 3728d3eca20SDavid Ahern } 3738d3eca20SDavid Ahern } 37498402807SFrederic Weisbecker } 37598402807SFrederic Weisbecker 3762eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 3778d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 3788d3eca20SDavid Ahern sizeof(finished_round_event)); 3798d3eca20SDavid Ahern 3808d3eca20SDavid Ahern out: 3818d3eca20SDavid Ahern return rc; 38298402807SFrederic Weisbecker } 38398402807SFrederic Weisbecker 384d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 38586470930SIngo Molnar { 38686470930SIngo Molnar struct stat st; 38786470930SIngo Molnar int flags; 388781ba9d2SRobert Richter int err, output, feat; 3898b412664SPeter Zijlstra unsigned long waking = 0; 39046be604bSZhang, Yanmin const bool forks = argc > 0; 39123346f21SArnaldo Carvalho de Melo struct machine *machine; 39245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 393d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 394d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 395d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 396d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 3972711926aSJiri Olsa bool disabled = false; 39886470930SIngo Molnar 399d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 40033e49ea7SAndi Kleen 401d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 40286470930SIngo Molnar 403d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 404f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 405f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 40618483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 407f5970550SPeter Zijlstra 408d7065adbSFranck Bui-Huu if (!output_name) { 409d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 410d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 411d7065adbSFranck Bui-Huu else 412d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 413d7065adbSFranck Bui-Huu } 414d7065adbSFranck Bui-Huu if (output_name) { 415529870e3STom Zanussi if (!strcmp(output_name, "-")) 416d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 417529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 418d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 419b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 420b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 421b38d3464SArnaldo Carvalho de Melo output_name); 422b38d3464SArnaldo Carvalho de Melo unlink(oldname); 423b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 424b38d3464SArnaldo Carvalho de Melo } 425d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 426d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 427266e0e21SPierre Habouzit } 428d7065adbSFranck Bui-Huu } 42986470930SIngo Molnar 430f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 431d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 432d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 43386470930SIngo Molnar else 43486470930SIngo Molnar flags |= O_TRUNC; 43586470930SIngo Molnar 436d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 437529870e3STom Zanussi output = STDOUT_FILENO; 438529870e3STom Zanussi else 43986470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 44086470930SIngo Molnar if (output < 0) { 44186470930SIngo Molnar perror("failed to create output file"); 4428d3eca20SDavid Ahern return -1; 44386470930SIngo Molnar } 44486470930SIngo Molnar 445d20deb64SArnaldo Carvalho de Melo rec->output = output; 446d20deb64SArnaldo Carvalho de Melo 4477865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 448d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 44994c744b6SArnaldo Carvalho de Melo if (session == NULL) { 450a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 451a9a70bbcSArnaldo Carvalho de Melo return -1; 452a9a70bbcSArnaldo Carvalho de Melo } 453a9a70bbcSArnaldo Carvalho de Melo 454d20deb64SArnaldo Carvalho de Melo rec->session = session; 455d20deb64SArnaldo Carvalho de Melo 456781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 457781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 458781ba9d2SRobert Richter 459781ba9d2SRobert Richter if (rec->no_buildid) 460781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 461781ba9d2SRobert Richter 462781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 4632eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 464baa2f6ceSArnaldo Carvalho de Melo 465330aa675SStephane Eranian if (!rec->opts.branch_stack) 466330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 467330aa675SStephane Eranian 468d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 469a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4704dc0a04bSArnaldo Carvalho de Melo if (err < 0) 47139d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4724dc0a04bSArnaldo Carvalho de Melo } 4734dc0a04bSArnaldo Carvalho de Melo 474d4db3f16SArnaldo Carvalho de Melo if (forks) { 4756ef73ec4SNamhyung Kim err = perf_evlist__prepare_workload(evsel_list, &opts->target, 47655e162eaSNamhyung Kim argv, opts->pipe_output, 47755e162eaSNamhyung Kim true); 47835b9d88eSArnaldo Carvalho de Melo if (err < 0) { 47935b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 48035b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 481856e9660SPeter Zijlstra } 482856e9660SPeter Zijlstra } 483856e9660SPeter Zijlstra 4848d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 4858d3eca20SDavid Ahern err = -1; 4868d3eca20SDavid Ahern goto out_delete_session; 4878d3eca20SDavid Ahern } 48886470930SIngo Molnar 489a8bb559bSNamhyung Kim if (!evsel_list->nr_groups) 490a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 491a8bb559bSNamhyung Kim 492712a4b60SArnaldo Carvalho de Melo /* 493d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 494712a4b60SArnaldo Carvalho de Melo */ 495d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 496712a4b60SArnaldo Carvalho de Melo 497d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 498529870e3STom Zanussi err = perf_header__write_pipe(output); 499529870e3STom Zanussi if (err < 0) 5008d3eca20SDavid Ahern goto out_delete_session; 501d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 502a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 503361c99a6SArnaldo Carvalho de Melo output, false); 504d5eed904SArnaldo Carvalho de Melo if (err < 0) 5058d3eca20SDavid Ahern goto out_delete_session; 506d5eed904SArnaldo Carvalho de Melo } 5077c6a1c65SPeter Zijlstra 508d3665498SDavid Ahern if (!rec->no_buildid 509e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 510d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 511e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5128d3eca20SDavid Ahern err = -1; 5138d3eca20SDavid Ahern goto out_delete_session; 514e20960c0SRobert Richter } 515e20960c0SRobert Richter 516d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5176122e4e4SArnaldo Carvalho de Melo 51834ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 519743eb868SArnaldo Carvalho de Melo 520d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 52145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 522a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5232c46dbb5STom Zanussi if (err < 0) { 5242c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5258d3eca20SDavid Ahern goto out_delete_session; 5262c46dbb5STom Zanussi } 527cd19a035STom Zanussi 52845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 529743eb868SArnaldo Carvalho de Melo machine); 530cd19a035STom Zanussi if (err < 0) { 531cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 5328d3eca20SDavid Ahern goto out_delete_session; 533cd19a035STom Zanussi } 5349215545eSTom Zanussi 535361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 53663e0c771STom Zanussi /* 53763e0c771STom Zanussi * FIXME err <= 0 here actually means that 53863e0c771STom Zanussi * there were no tracepoints so its not really 53963e0c771STom Zanussi * an error, just that we don't need to 54063e0c771STom Zanussi * synthesize anything. We really have to 54163e0c771STom Zanussi * return this more properly and also 54263e0c771STom Zanussi * propagate errors that now are calling die() 54363e0c771STom Zanussi */ 54445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 545743eb868SArnaldo Carvalho de Melo process_synthesized_event); 54663e0c771STom Zanussi if (err <= 0) { 54763e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 5488d3eca20SDavid Ahern goto out_delete_session; 54963e0c771STom Zanussi } 550d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5512c46dbb5STom Zanussi } 55263e0c771STom Zanussi } 5532c46dbb5STom Zanussi 55445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 555743eb868SArnaldo Carvalho de Melo machine, "_text"); 55670162138SArnaldo Carvalho de Melo if (err < 0) 55745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 558743eb868SArnaldo Carvalho de Melo machine, "_stext"); 559c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 560c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 561c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 562c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 56356b03f3cSArnaldo Carvalho de Melo 56445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 565743eb868SArnaldo Carvalho de Melo machine); 566c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 567c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 568c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 569c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 570c1a3a4b9SArnaldo Carvalho de Melo 5717e383de4SArnaldo Carvalho de Melo if (perf_guest) { 572876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 5737e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 5747e383de4SArnaldo Carvalho de Melo } 575b7cece76SArnaldo Carvalho de Melo 576e4dd45feSJiri Olsa if (perf_target__has_task(&opts->target)) 5778d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 5788115d60cSArnaldo Carvalho de Melo process_synthesized_event, 579743eb868SArnaldo Carvalho de Melo machine); 580e4dd45feSJiri Olsa else if (perf_target__has_cpu(&opts->target)) 5818d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 582743eb868SArnaldo Carvalho de Melo machine); 583e4dd45feSJiri Olsa else /* command specified */ 584e4dd45feSJiri Olsa err = 0; 5857c6a1c65SPeter Zijlstra 5868d3eca20SDavid Ahern if (err != 0) 5878d3eca20SDavid Ahern goto out_delete_session; 5888d3eca20SDavid Ahern 589d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 59086470930SIngo Molnar struct sched_param param; 59186470930SIngo Molnar 592d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 59386470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5946beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 5958d3eca20SDavid Ahern err = -1; 5968d3eca20SDavid Ahern goto out_delete_session; 59786470930SIngo Molnar } 59886470930SIngo Molnar } 59986470930SIngo Molnar 600774cb499SJiri Olsa /* 601774cb499SJiri Olsa * When perf is starting the traced process, all the events 602774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 603774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 604774cb499SJiri Olsa */ 605774cb499SJiri Olsa if (!perf_target__none(&opts->target)) 606764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 607764e16a3SDavid Ahern 608856e9660SPeter Zijlstra /* 609856e9660SPeter Zijlstra * Let the child rip 610856e9660SPeter Zijlstra */ 611d4db3f16SArnaldo Carvalho de Melo if (forks) 61235b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 613856e9660SPeter Zijlstra 614649c48a9SPeter Zijlstra for (;;) { 615d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 61686470930SIngo Molnar 6178d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 6188d3eca20SDavid Ahern err = -1; 6198d3eca20SDavid Ahern goto out_delete_session; 6208d3eca20SDavid Ahern } 62186470930SIngo Molnar 622d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 623649c48a9SPeter Zijlstra if (done) 624649c48a9SPeter Zijlstra break; 6255c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6268b412664SPeter Zijlstra waking++; 6278b412664SPeter Zijlstra } 6288b412664SPeter Zijlstra 629774cb499SJiri Olsa /* 630774cb499SJiri Olsa * When perf is starting the traced process, at the end events 631774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 632774cb499SJiri Olsa * disable events in this case. 633774cb499SJiri Olsa */ 6342711926aSJiri Olsa if (done && !disabled && !perf_target__none(&opts->target)) { 6354152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6362711926aSJiri Olsa disabled = true; 6372711926aSJiri Olsa } 6388b412664SPeter Zijlstra } 6398b412664SPeter Zijlstra 64018483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 641b44308f5SArnaldo Carvalho de Melo return 0; 642b44308f5SArnaldo Carvalho de Melo 6438b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 64486470930SIngo Molnar 64586470930SIngo Molnar /* 64686470930SIngo Molnar * Approximate RIP event size: 24 bytes. 64786470930SIngo Molnar */ 64886470930SIngo Molnar fprintf(stderr, 6499486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 650d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 65186470930SIngo Molnar output_name, 652d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 65386470930SIngo Molnar 65486470930SIngo Molnar return 0; 65539d17dacSArnaldo Carvalho de Melo 65639d17dacSArnaldo Carvalho de Melo out_delete_session: 65739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 65839d17dacSArnaldo Carvalho de Melo return err; 65986470930SIngo Molnar } 66086470930SIngo Molnar 661bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 662bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 663bdfebd84SRoberto Agostino Vitillo 664bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 665bdfebd84SRoberto Agostino Vitillo 666bdfebd84SRoberto Agostino Vitillo struct branch_mode { 667bdfebd84SRoberto Agostino Vitillo const char *name; 668bdfebd84SRoberto Agostino Vitillo int mode; 669bdfebd84SRoberto Agostino Vitillo }; 670bdfebd84SRoberto Agostino Vitillo 671bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 672bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 673bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 674bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 675bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 676bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 677bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 678bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 679bdfebd84SRoberto Agostino Vitillo BRANCH_END 680bdfebd84SRoberto Agostino Vitillo }; 681bdfebd84SRoberto Agostino Vitillo 682bdfebd84SRoberto Agostino Vitillo static int 683a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 684bdfebd84SRoberto Agostino Vitillo { 685bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 686bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 687bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 688bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 689bdfebd84SRoberto Agostino Vitillo 690bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 691bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 692a5aabdacSStephane Eranian char *s, *os = NULL, *p; 693bdfebd84SRoberto Agostino Vitillo int ret = -1; 694bdfebd84SRoberto Agostino Vitillo 695a5aabdacSStephane Eranian if (unset) 696a5aabdacSStephane Eranian return 0; 697bdfebd84SRoberto Agostino Vitillo 698a5aabdacSStephane Eranian /* 699a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 700a5aabdacSStephane Eranian */ 701a5aabdacSStephane Eranian if (*mode) 702a5aabdacSStephane Eranian return -1; 703a5aabdacSStephane Eranian 704a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 705a5aabdacSStephane Eranian if (str) { 706bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 707bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 708bdfebd84SRoberto Agostino Vitillo if (!s) 709bdfebd84SRoberto Agostino Vitillo return -1; 710bdfebd84SRoberto Agostino Vitillo 711bdfebd84SRoberto Agostino Vitillo for (;;) { 712bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 713bdfebd84SRoberto Agostino Vitillo if (p) 714bdfebd84SRoberto Agostino Vitillo *p = '\0'; 715bdfebd84SRoberto Agostino Vitillo 716bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 717bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 718bdfebd84SRoberto Agostino Vitillo break; 719bdfebd84SRoberto Agostino Vitillo } 720a5aabdacSStephane Eranian if (!br->name) { 721a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 722a5aabdacSStephane Eranian " check man page\n", s); 723bdfebd84SRoberto Agostino Vitillo goto error; 724a5aabdacSStephane Eranian } 725bdfebd84SRoberto Agostino Vitillo 726bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 727bdfebd84SRoberto Agostino Vitillo 728bdfebd84SRoberto Agostino Vitillo if (!p) 729bdfebd84SRoberto Agostino Vitillo break; 730bdfebd84SRoberto Agostino Vitillo 731bdfebd84SRoberto Agostino Vitillo s = p + 1; 732bdfebd84SRoberto Agostino Vitillo } 733a5aabdacSStephane Eranian } 734bdfebd84SRoberto Agostino Vitillo ret = 0; 735bdfebd84SRoberto Agostino Vitillo 736a5aabdacSStephane Eranian /* default to any branch */ 737bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 738a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 739bdfebd84SRoberto Agostino Vitillo } 740bdfebd84SRoberto Agostino Vitillo error: 741bdfebd84SRoberto Agostino Vitillo free(os); 742bdfebd84SRoberto Agostino Vitillo return ret; 743bdfebd84SRoberto Agostino Vitillo } 744bdfebd84SRoberto Agostino Vitillo 74595485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 74626d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 74726d33022SJiri Olsa { 74826d33022SJiri Olsa char *endptr; 74926d33022SJiri Olsa unsigned long size; 75026d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 75126d33022SJiri Olsa 75226d33022SJiri Olsa size = strtoul(str, &endptr, 0); 75326d33022SJiri Olsa 75426d33022SJiri Olsa do { 75526d33022SJiri Olsa if (*endptr) 75626d33022SJiri Olsa break; 75726d33022SJiri Olsa 75826d33022SJiri Olsa size = round_up(size, sizeof(u64)); 75926d33022SJiri Olsa if (!size || size > max_size) 76026d33022SJiri Olsa break; 76126d33022SJiri Olsa 76226d33022SJiri Olsa *_size = size; 76326d33022SJiri Olsa return 0; 76426d33022SJiri Olsa 76526d33022SJiri Olsa } while (0); 76626d33022SJiri Olsa 76726d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 76826d33022SJiri Olsa max_size, str); 76926d33022SJiri Olsa return -1; 77026d33022SJiri Olsa } 77195485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 77226d33022SJiri Olsa 77375d9a108SArnaldo Carvalho de Melo int record_parse_callchain_opt(const struct option *opt, 77475d9a108SArnaldo Carvalho de Melo const char *arg, int unset) 77526d33022SJiri Olsa { 776c5ff78c3SArnaldo Carvalho de Melo struct perf_record_opts *opts = opt->value; 77726d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 77826d33022SJiri Olsa char *buf; 77926d33022SJiri Olsa int ret = -1; 78026d33022SJiri Olsa 78126d33022SJiri Olsa /* --no-call-graph */ 78226d33022SJiri Olsa if (unset) 78326d33022SJiri Olsa return 0; 78426d33022SJiri Olsa 78526d33022SJiri Olsa /* We specified default option if none is provided. */ 78626d33022SJiri Olsa BUG_ON(!arg); 78726d33022SJiri Olsa 78826d33022SJiri Olsa /* We need buffer that we know we can write to. */ 78926d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 79026d33022SJiri Olsa if (!buf) 79126d33022SJiri Olsa return -ENOMEM; 79226d33022SJiri Olsa 79326d33022SJiri Olsa strcpy(buf, arg); 79426d33022SJiri Olsa 79526d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 79626d33022SJiri Olsa name = tok ? : (char *)buf; 79726d33022SJiri Olsa 79826d33022SJiri Olsa do { 79926d33022SJiri Olsa /* Framepointer style */ 80026d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 80126d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 802c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_FP; 80326d33022SJiri Olsa ret = 0; 80426d33022SJiri Olsa } else 80526d33022SJiri Olsa pr_err("callchain: No more arguments " 80626d33022SJiri Olsa "needed for -g fp\n"); 80726d33022SJiri Olsa break; 80826d33022SJiri Olsa 80995485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 81026d33022SJiri Olsa /* Dwarf style */ 81126d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 81261eaa3beSArnaldo Carvalho de Melo const unsigned long default_stack_dump_size = 8192; 81361eaa3beSArnaldo Carvalho de Melo 81426d33022SJiri Olsa ret = 0; 815c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_DWARF; 816c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = default_stack_dump_size; 81726d33022SJiri Olsa 81826d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 81926d33022SJiri Olsa if (tok) { 82026d33022SJiri Olsa unsigned long size = 0; 82126d33022SJiri Olsa 82226d33022SJiri Olsa ret = get_stack_size(tok, &size); 823c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = size; 82426d33022SJiri Olsa } 82526d33022SJiri Olsa 82626d33022SJiri Olsa if (!ret) 82726d33022SJiri Olsa pr_debug("callchain: stack dump size %d\n", 828c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size); 82995485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 83026d33022SJiri Olsa } else { 83126d33022SJiri Olsa pr_err("callchain: Unknown -g option " 83226d33022SJiri Olsa "value: %s\n", arg); 83326d33022SJiri Olsa break; 83426d33022SJiri Olsa } 83526d33022SJiri Olsa 83626d33022SJiri Olsa } while (0); 83726d33022SJiri Olsa 83826d33022SJiri Olsa free(buf); 83926d33022SJiri Olsa 84026d33022SJiri Olsa if (!ret) 841c5ff78c3SArnaldo Carvalho de Melo pr_debug("callchain: type %d\n", opts->call_graph); 84226d33022SJiri Olsa 84326d33022SJiri Olsa return ret; 84426d33022SJiri Olsa } 84526d33022SJiri Olsa 84686470930SIngo Molnar static const char * const record_usage[] = { 84786470930SIngo Molnar "perf record [<options>] [<command>]", 84886470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 84986470930SIngo Molnar NULL 85086470930SIngo Molnar }; 85186470930SIngo Molnar 852d20deb64SArnaldo Carvalho de Melo /* 853d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 854d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 855d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 856d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 857d20deb64SArnaldo Carvalho de Melo * 858d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 859d20deb64SArnaldo Carvalho de Melo * 860d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 861d20deb64SArnaldo Carvalho de Melo */ 862d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 863d20deb64SArnaldo Carvalho de Melo .opts = { 864d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 865d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 866d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 867447a6013SArnaldo Carvalho de Melo .freq = 4000, 868d1cb9fceSNamhyung Kim .target = { 869d1cb9fceSNamhyung Kim .uses_mmap = true, 870d1cb9fceSNamhyung Kim }, 871d20deb64SArnaldo Carvalho de Melo }, 872d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 873d20deb64SArnaldo Carvalho de Melo .file_new = true, 874d20deb64SArnaldo Carvalho de Melo }; 8757865e817SFrederic Weisbecker 87661eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 87761eaa3beSArnaldo Carvalho de Melo 87861eaa3beSArnaldo Carvalho de Melo #ifdef LIBUNWIND_SUPPORT 87975d9a108SArnaldo Carvalho de Melo const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 88061eaa3beSArnaldo Carvalho de Melo #else 88175d9a108SArnaldo Carvalho de Melo const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; 88261eaa3beSArnaldo Carvalho de Melo #endif 88361eaa3beSArnaldo Carvalho de Melo 884d20deb64SArnaldo Carvalho de Melo /* 885d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 886d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 887d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 888d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 889d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 890d20deb64SArnaldo Carvalho de Melo */ 891bca647aaSTom Zanussi const struct option record_options[] = { 892d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 89386470930SIngo Molnar "event selector. use 'perf list' to list available events", 894f120f9d5SJiri Olsa parse_events_option), 895d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 896c171b552SLi Zefan "event filter", parse_filter), 897bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 898d6d901c2SZhang, Yanmin "record events on existing process id"), 899bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 900d6d901c2SZhang, Yanmin "record events on existing thread id"), 901d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 90286470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 903d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 904acac03faSKirill Smelkov "collect data without buffering"), 905d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 906daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 907bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 90886470930SIngo Molnar "system-wide collection from all CPUs"), 909d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 91086470930SIngo Molnar "append to the output file to do incremental profiling"), 911bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 912c45c6ea2SStephane Eranian "list of cpus to monitor"), 913d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 9147865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 915d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 916d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 91786470930SIngo Molnar "output file name"), 918d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 9192e6cdf99SStephane Eranian "child tasks do not inherit counters"), 920d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 921d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 92201c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 923d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 92443bece79SLin Ming "put the counters into a counter group"), 925c5ff78c3SArnaldo Carvalho de Melo OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, 92675d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 92775d9a108SArnaldo Carvalho de Melo &record_parse_callchain_opt, "fp"), 928c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 9293da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 930b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 931d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 932649c48a9SPeter Zijlstra "per thread counts"), 933d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 9344bba828dSAnton Blanchard "Sample addresses"), 935d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 9363e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 937d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 938649c48a9SPeter Zijlstra "don't sample"), 939d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 940a1ac1d3cSStephane Eranian "do not update the buildid cache"), 941d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 942baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 943d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 944023695d9SStephane Eranian "monitor event in cgroup name only", 945023695d9SStephane Eranian parse_cgroups), 946bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 947bea03405SNamhyung Kim "user to profile"), 948a5aabdacSStephane Eranian 949a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 950a5aabdacSStephane Eranian "branch any", "sample any taken branches", 951a5aabdacSStephane Eranian parse_branch_stack), 952a5aabdacSStephane Eranian 953a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 954a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 955bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 956*05484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 957*05484298SAndi Kleen "sample by weight (on special events only)"), 95886470930SIngo Molnar OPT_END() 95986470930SIngo Molnar }; 96086470930SIngo Molnar 9611d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 96286470930SIngo Molnar { 96369aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 96469aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 965d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 966d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 96716ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 96886470930SIngo Molnar 969334fe7a3SNamhyung Kim evsel_list = perf_evlist__new(); 970361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 971361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 972361c99a6SArnaldo Carvalho de Melo 973d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 974d20deb64SArnaldo Carvalho de Melo 975bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 976a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 977d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 978bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 97986470930SIngo Molnar 980d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 9813780f488SNamhyung Kim ui__error("Can't overwrite and append at the same time." 9827865e817SFrederic Weisbecker " You need to choose between -f and -A"); 983bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 984d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 985d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 9867865e817SFrederic Weisbecker } else { 987d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 9887865e817SFrederic Weisbecker } 9897865e817SFrederic Weisbecker 990bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 9913780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 992023695d9SStephane Eranian " system-wide mode\n"); 993023695d9SStephane Eranian usage_with_options(record_usage, record_options); 994023695d9SStephane Eranian } 995023695d9SStephane Eranian 996655000e7SArnaldo Carvalho de Melo symbol__init(); 997baa2f6ceSArnaldo Carvalho de Melo 998ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 999646aaea6SArnaldo Carvalho de Melo pr_warning( 1000646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1001ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1002646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1003646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1004646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1005646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1006646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1007ec80fde7SArnaldo Carvalho de Melo 1008d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1009a1ac1d3cSStephane Eranian disable_buildid_cache(); 1010655000e7SArnaldo Carvalho de Melo 1011361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 1012361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 101369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 101469aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1015bbd36e5eSPeter Zijlstra } 101686470930SIngo Molnar 101716ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 101816ad2ffbSNamhyung Kim if (err) { 101916ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 102016ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 102116ad2ffbSNamhyung Kim } 10224bd0f2d2SNamhyung Kim 102316ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 102416ad2ffbSNamhyung Kim if (err) { 102516ad2ffbSNamhyung Kim int saved_errno = errno; 102616ad2ffbSNamhyung Kim 102716ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 10283780f488SNamhyung Kim ui__error("%s", errbuf); 102916ad2ffbSNamhyung Kim 103016ad2ffbSNamhyung Kim err = -saved_errno; 10318fa60e1fSNamhyung Kim goto out_symbol_exit; 103216ad2ffbSNamhyung Kim } 10330d37aa34SArnaldo Carvalho de Melo 103416ad2ffbSNamhyung Kim err = -ENOMEM; 1035b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 1036dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 103769aad6f1SArnaldo Carvalho de Melo 1038361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 10397289f83cSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) 1040ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 1041d6d901c2SZhang, Yanmin } 10425c581041SArnaldo Carvalho de Melo 1043d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 1044d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 1045d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 1046d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 1047f9212819SFrederic Weisbecker 10487e4ff9e3SMike Galbraith /* 10497e4ff9e3SMike Galbraith * User specified count overrides default frequency. 10507e4ff9e3SMike Galbraith */ 1051d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 1052d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 1053d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 1054d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 10557e4ff9e3SMike Galbraith } else { 10563780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 105739d17dacSArnaldo Carvalho de Melo err = -EINVAL; 10585c581041SArnaldo Carvalho de Melo goto out_free_fd; 10597e4ff9e3SMike Galbraith } 10607e4ff9e3SMike Galbraith 1061d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 10628fa60e1fSNamhyung Kim 10638fa60e1fSNamhyung Kim perf_evlist__munmap(evsel_list); 10648fa60e1fSNamhyung Kim perf_evlist__close(evsel_list); 106539d17dacSArnaldo Carvalho de Melo out_free_fd: 10667e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 1067d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 1068d65a458bSArnaldo Carvalho de Melo symbol__exit(); 106939d17dacSArnaldo Carvalho de Melo return err; 107086470930SIngo Molnar } 1071