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" 27*f5fc1412SJiri Olsa #include "util/data.h" 287c6a1c65SPeter Zijlstra 2986470930SIngo Molnar #include <unistd.h> 3086470930SIngo Molnar #include <sched.h> 31a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3286470930SIngo Molnar 3389fe808aSIngo Molnar #ifndef HAVE_ON_EXIT_SUPPORT 3478da39faSBernhard Rosenkraenzer #ifndef ATEXIT_MAX 3578da39faSBernhard Rosenkraenzer #define ATEXIT_MAX 32 3678da39faSBernhard Rosenkraenzer #endif 3778da39faSBernhard Rosenkraenzer static int __on_exit_count = 0; 3878da39faSBernhard Rosenkraenzer typedef void (*on_exit_func_t) (int, void *); 3978da39faSBernhard Rosenkraenzer static on_exit_func_t __on_exit_funcs[ATEXIT_MAX]; 4078da39faSBernhard Rosenkraenzer static void *__on_exit_args[ATEXIT_MAX]; 4178da39faSBernhard Rosenkraenzer static int __exitcode = 0; 4278da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void); 4378da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg); 4478da39faSBernhard Rosenkraenzer #define exit(x) (exit)(__exitcode = (x)) 4578da39faSBernhard Rosenkraenzer 4678da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg) 4778da39faSBernhard Rosenkraenzer { 4878da39faSBernhard Rosenkraenzer if (__on_exit_count == ATEXIT_MAX) 4978da39faSBernhard Rosenkraenzer return -ENOMEM; 5078da39faSBernhard Rosenkraenzer else if (__on_exit_count == 0) 5178da39faSBernhard Rosenkraenzer atexit(__handle_on_exit_funcs); 5278da39faSBernhard Rosenkraenzer __on_exit_funcs[__on_exit_count] = function; 5378da39faSBernhard Rosenkraenzer __on_exit_args[__on_exit_count++] = arg; 5478da39faSBernhard Rosenkraenzer return 0; 5578da39faSBernhard Rosenkraenzer } 5678da39faSBernhard Rosenkraenzer 5778da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void) 5878da39faSBernhard Rosenkraenzer { 5978da39faSBernhard Rosenkraenzer int i; 6078da39faSBernhard Rosenkraenzer for (i = 0; i < __on_exit_count; i++) 6178da39faSBernhard Rosenkraenzer __on_exit_funcs[i] (__exitcode, __on_exit_args[i]); 6278da39faSBernhard Rosenkraenzer } 6378da39faSBernhard Rosenkraenzer #endif 6478da39faSBernhard Rosenkraenzer 65d20deb64SArnaldo Carvalho de Melo struct perf_record { 6645694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 67d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 68d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 69*f5fc1412SJiri Olsa struct perf_data_file file; 70d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 71d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 72d20deb64SArnaldo Carvalho de Melo const char *progname; 73d20deb64SArnaldo Carvalho de Melo int realtime_prio; 74d20deb64SArnaldo Carvalho de Melo bool no_buildid; 75d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 76d20deb64SArnaldo Carvalho de Melo long samples; 77d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 780f82ebc4SArnaldo Carvalho de Melo }; 7986470930SIngo Molnar 80d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 819215545eSTom Zanussi { 82d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 839215545eSTom Zanussi } 849215545eSTom Zanussi 858d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size) 86f5970550SPeter Zijlstra { 87*f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 88*f5fc1412SJiri Olsa 89f5970550SPeter Zijlstra while (size) { 90*f5fc1412SJiri Olsa int ret = write(file->fd, buf, size); 91f5970550SPeter Zijlstra 928d3eca20SDavid Ahern if (ret < 0) { 934f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 948d3eca20SDavid Ahern return -1; 958d3eca20SDavid Ahern } 96f5970550SPeter Zijlstra 97f5970550SPeter Zijlstra size -= ret; 98f5970550SPeter Zijlstra buf += ret; 99f5970550SPeter Zijlstra 100d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 101f5970550SPeter Zijlstra } 1028d3eca20SDavid Ahern 1038d3eca20SDavid Ahern return 0; 104f5970550SPeter Zijlstra } 105f5970550SPeter Zijlstra 10645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 107d20deb64SArnaldo Carvalho de Melo union perf_event *event, 1081d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 1091d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 110234fbbf5SArnaldo Carvalho de Melo { 11145694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 1128d3eca20SDavid Ahern if (write_output(rec, event, event->header.size) < 0) 1138d3eca20SDavid Ahern return -1; 1148d3eca20SDavid Ahern 115234fbbf5SArnaldo Carvalho de Melo return 0; 116234fbbf5SArnaldo Carvalho de Melo } 117234fbbf5SArnaldo Carvalho de Melo 1188d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec, 119d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 12086470930SIngo Molnar { 121744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 12286470930SIngo Molnar unsigned int old = md->prev; 123918512b4SJiri Olsa unsigned char *data = md->base + page_size; 12486470930SIngo Molnar unsigned long size; 12586470930SIngo Molnar void *buf; 1268d3eca20SDavid Ahern int rc = 0; 12786470930SIngo Molnar 128dc82009aSArnaldo Carvalho de Melo if (old == head) 1298d3eca20SDavid Ahern return 0; 13086470930SIngo Molnar 131d20deb64SArnaldo Carvalho de Melo rec->samples++; 13286470930SIngo Molnar 13386470930SIngo Molnar size = head - old; 13486470930SIngo Molnar 13586470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 13686470930SIngo Molnar buf = &data[old & md->mask]; 13786470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 13886470930SIngo Molnar old += size; 13986470930SIngo Molnar 1408d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1418d3eca20SDavid Ahern rc = -1; 1428d3eca20SDavid Ahern goto out; 1438d3eca20SDavid Ahern } 14486470930SIngo Molnar } 14586470930SIngo Molnar 14686470930SIngo Molnar buf = &data[old & md->mask]; 14786470930SIngo Molnar size = head - old; 14886470930SIngo Molnar old += size; 14986470930SIngo Molnar 1508d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1518d3eca20SDavid Ahern rc = -1; 1528d3eca20SDavid Ahern goto out; 1538d3eca20SDavid Ahern } 15486470930SIngo Molnar 15586470930SIngo Molnar md->prev = old; 156115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 1578d3eca20SDavid Ahern 1588d3eca20SDavid Ahern out: 1598d3eca20SDavid Ahern return rc; 16086470930SIngo Molnar } 16186470930SIngo Molnar 16286470930SIngo Molnar static volatile int done = 0; 163f7b7c26eSPeter Zijlstra static volatile int signr = -1; 16433e49ea7SAndi Kleen static volatile int child_finished = 0; 16586470930SIngo Molnar 16686470930SIngo Molnar static void sig_handler(int sig) 16786470930SIngo Molnar { 16833e49ea7SAndi Kleen if (sig == SIGCHLD) 16933e49ea7SAndi Kleen child_finished = 1; 17033e49ea7SAndi Kleen 17186470930SIngo Molnar done = 1; 172f7b7c26eSPeter Zijlstra signr = sig; 173f7b7c26eSPeter Zijlstra } 174f7b7c26eSPeter Zijlstra 1751d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 176f7b7c26eSPeter Zijlstra { 177d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 17833e49ea7SAndi Kleen int status; 17933e49ea7SAndi Kleen 180d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 18133e49ea7SAndi Kleen if (!child_finished) 182d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 183933da83aSChris Wilson 18433e49ea7SAndi Kleen wait(&status); 18533e49ea7SAndi Kleen if (WIFSIGNALED(status)) 186d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 18733e49ea7SAndi Kleen } 18833e49ea7SAndi Kleen 18918483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 190f7b7c26eSPeter Zijlstra return; 191f7b7c26eSPeter Zijlstra 192f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 19386470930SIngo Molnar } 19486470930SIngo Molnar 1958d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec) 196dd7927f4SArnaldo Carvalho de Melo { 19756e52e85SArnaldo Carvalho de Melo char msg[512]; 1986a4bb04cSJiri Olsa struct perf_evsel *pos; 199d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 200d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 201d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 2028d3eca20SDavid Ahern int rc = 0; 203dd7927f4SArnaldo Carvalho de Melo 204f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 205cac21425SJiri Olsa 206dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 2073da297a6SIngo Molnar try_again: 2086a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 20956e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2103da297a6SIngo Molnar if (verbose) 211c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2123da297a6SIngo Molnar goto try_again; 2133da297a6SIngo Molnar } 214ca6a4258SDavid Ahern 21556e52e85SArnaldo Carvalho de Melo rc = -errno; 21656e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 21756e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 21856e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2198d3eca20SDavid Ahern goto out; 2207c6a1c65SPeter Zijlstra } 2217c6a1c65SPeter Zijlstra } 2227c6a1c65SPeter Zijlstra 2231491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 2240a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2250a102479SFrederic Weisbecker strerror(errno)); 2268d3eca20SDavid Ahern rc = -1; 2278d3eca20SDavid Ahern goto out; 2280a102479SFrederic Weisbecker } 2290a102479SFrederic Weisbecker 23018e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 2318d3eca20SDavid Ahern if (errno == EPERM) { 2328d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 23318e60939SNelson Elhage "Consider increasing " 23418e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 23518e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 23618e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 2378d3eca20SDavid Ahern rc = -errno; 2388d3eca20SDavid Ahern } else { 2398d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 2408d3eca20SDavid Ahern rc = -errno; 2418d3eca20SDavid Ahern } 2428d3eca20SDavid Ahern goto out; 24318e60939SNelson Elhage } 2440a27d7f9SArnaldo Carvalho de Melo 245a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 2467b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 2478d3eca20SDavid Ahern out: 2488d3eca20SDavid Ahern return rc; 249a91e5431SArnaldo Carvalho de Melo } 250a91e5431SArnaldo Carvalho de Melo 251d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 2526122e4e4SArnaldo Carvalho de Melo { 253*f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 254*f5fc1412SJiri Olsa struct perf_session *session = rec->session; 2556122e4e4SArnaldo Carvalho de Melo 256*f5fc1412SJiri Olsa u64 size = lseek(file->fd, 0, SEEK_CUR); 2579f591fd7SArnaldo Carvalho de Melo if (size == 0) 2589f591fd7SArnaldo Carvalho de Melo return 0; 2599f591fd7SArnaldo Carvalho de Melo 260*f5fc1412SJiri Olsa session->fd = file->fd; 261*f5fc1412SJiri Olsa return __perf_session__process_events(session, rec->post_processing_offset, 262d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 2636122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 2646122e4e4SArnaldo Carvalho de Melo } 2656122e4e4SArnaldo Carvalho de Melo 2668d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 267f5970550SPeter Zijlstra { 268d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 269*f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 270f5970550SPeter Zijlstra 2718d3eca20SDavid Ahern if (status != 0) 2728d3eca20SDavid Ahern return; 2738d3eca20SDavid Ahern 274*f5fc1412SJiri Olsa if (!file->is_pipe) { 275d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 276d20deb64SArnaldo Carvalho de Melo 277d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 278d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 279d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 280*f5fc1412SJiri Olsa file->fd, true); 281d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 282d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 283d65a458bSArnaldo Carvalho de Melo symbol__exit(); 284c7929e47STom Zanussi } 285f5970550SPeter Zijlstra } 286f5970550SPeter Zijlstra 2878115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 288a1645ce1SZhang, Yanmin { 289a1645ce1SZhang, Yanmin int err; 29045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 291a1645ce1SZhang, Yanmin /* 292a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 293a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 294a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 295a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 296a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 297a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 298a1645ce1SZhang, Yanmin */ 29945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 300743eb868SArnaldo Carvalho de Melo machine); 301a1645ce1SZhang, Yanmin if (err < 0) 302a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 30323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 304a1645ce1SZhang, Yanmin 305a1645ce1SZhang, Yanmin /* 306a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 307a1645ce1SZhang, Yanmin * have no _text sometimes. 308a1645ce1SZhang, Yanmin */ 30945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 310743eb868SArnaldo Carvalho de Melo machine, "_text"); 311a1645ce1SZhang, Yanmin if (err < 0) 31245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 313743eb868SArnaldo Carvalho de Melo machine, "_stext"); 314a1645ce1SZhang, Yanmin if (err < 0) 315a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 31623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 317a1645ce1SZhang, Yanmin } 318a1645ce1SZhang, Yanmin 31998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 32098402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 32198402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 32298402807SFrederic Weisbecker }; 32398402807SFrederic Weisbecker 3248d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 32598402807SFrederic Weisbecker { 3260e2e63ddSPeter Zijlstra int i; 3278d3eca20SDavid Ahern int rc = 0; 32898402807SFrederic Weisbecker 329d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 3308d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 3318d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 3328d3eca20SDavid Ahern rc = -1; 3338d3eca20SDavid Ahern goto out; 3348d3eca20SDavid Ahern } 3358d3eca20SDavid Ahern } 33698402807SFrederic Weisbecker } 33798402807SFrederic Weisbecker 3382eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 3398d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 3408d3eca20SDavid Ahern sizeof(finished_round_event)); 3418d3eca20SDavid Ahern 3428d3eca20SDavid Ahern out: 3438d3eca20SDavid Ahern return rc; 34498402807SFrederic Weisbecker } 34598402807SFrederic Weisbecker 346d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 34786470930SIngo Molnar { 34886470930SIngo Molnar struct stat st; 34986470930SIngo Molnar int flags; 350*f5fc1412SJiri Olsa int err, feat; 3518b412664SPeter Zijlstra unsigned long waking = 0; 35246be604bSZhang, Yanmin const bool forks = argc > 0; 35323346f21SArnaldo Carvalho de Melo struct machine *machine; 35445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 355d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 356d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 357*f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 358*f5fc1412SJiri Olsa const char *output_name = file->path; 359d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 3602711926aSJiri Olsa bool disabled = false; 36186470930SIngo Molnar 362d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 36333e49ea7SAndi Kleen 364d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 365f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 366f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 36718483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 368804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 369f5970550SPeter Zijlstra 370d7065adbSFranck Bui-Huu if (!output_name) { 371d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 372*f5fc1412SJiri Olsa file->is_pipe = true; 373d7065adbSFranck Bui-Huu else 374*f5fc1412SJiri Olsa file->path = output_name = "perf.data"; 375d7065adbSFranck Bui-Huu } 376d7065adbSFranck Bui-Huu if (output_name) { 377529870e3STom Zanussi if (!strcmp(output_name, "-")) 378*f5fc1412SJiri Olsa file->is_pipe = true; 379529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 380b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 381b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 382b38d3464SArnaldo Carvalho de Melo output_name); 383b38d3464SArnaldo Carvalho de Melo unlink(oldname); 384b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 385b38d3464SArnaldo Carvalho de Melo } 386d7065adbSFranck Bui-Huu } 38786470930SIngo Molnar 388563aecb2SJiri Olsa flags = O_CREAT|O_RDWR|O_TRUNC; 38986470930SIngo Molnar 390*f5fc1412SJiri Olsa if (file->is_pipe) 391*f5fc1412SJiri Olsa file->fd = STDOUT_FILENO; 392529870e3STom Zanussi else 393*f5fc1412SJiri Olsa file->fd = open(output_name, flags, S_IRUSR | S_IWUSR); 394*f5fc1412SJiri Olsa if (file->fd < 0) { 39586470930SIngo Molnar perror("failed to create output file"); 3968d3eca20SDavid Ahern return -1; 39786470930SIngo Molnar } 39886470930SIngo Molnar 399*f5fc1412SJiri Olsa session = perf_session__new(file, false, NULL); 40094c744b6SArnaldo Carvalho de Melo if (session == NULL) { 401a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 402a9a70bbcSArnaldo Carvalho de Melo return -1; 403a9a70bbcSArnaldo Carvalho de Melo } 404a9a70bbcSArnaldo Carvalho de Melo 405d20deb64SArnaldo Carvalho de Melo rec->session = session; 406d20deb64SArnaldo Carvalho de Melo 407781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 408781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 409781ba9d2SRobert Richter 410781ba9d2SRobert Richter if (rec->no_buildid) 411781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 412781ba9d2SRobert Richter 413781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 4142eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 415baa2f6ceSArnaldo Carvalho de Melo 416330aa675SStephane Eranian if (!rec->opts.branch_stack) 417330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 418330aa675SStephane Eranian 419d4db3f16SArnaldo Carvalho de Melo if (forks) { 4206ef73ec4SNamhyung Kim err = perf_evlist__prepare_workload(evsel_list, &opts->target, 421*f5fc1412SJiri Olsa argv, file->is_pipe, 42255e162eaSNamhyung Kim true); 42335b9d88eSArnaldo Carvalho de Melo if (err < 0) { 42435b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 42535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 426856e9660SPeter Zijlstra } 427856e9660SPeter Zijlstra } 428856e9660SPeter Zijlstra 4298d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 4308d3eca20SDavid Ahern err = -1; 4318d3eca20SDavid Ahern goto out_delete_session; 4328d3eca20SDavid Ahern } 43386470930SIngo Molnar 434a8bb559bSNamhyung Kim if (!evsel_list->nr_groups) 435a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 436a8bb559bSNamhyung Kim 437712a4b60SArnaldo Carvalho de Melo /* 438d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 439712a4b60SArnaldo Carvalho de Melo */ 440d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 441712a4b60SArnaldo Carvalho de Melo 442*f5fc1412SJiri Olsa if (file->is_pipe) { 443*f5fc1412SJiri Olsa err = perf_header__write_pipe(file->fd); 444529870e3STom Zanussi if (err < 0) 4458d3eca20SDavid Ahern goto out_delete_session; 446563aecb2SJiri Olsa } else { 447a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 448*f5fc1412SJiri Olsa file->fd, false); 449d5eed904SArnaldo Carvalho de Melo if (err < 0) 4508d3eca20SDavid Ahern goto out_delete_session; 451d5eed904SArnaldo Carvalho de Melo } 4527c6a1c65SPeter Zijlstra 453d3665498SDavid Ahern if (!rec->no_buildid 454e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 455d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 456e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 4578d3eca20SDavid Ahern err = -1; 4588d3eca20SDavid Ahern goto out_delete_session; 459e20960c0SRobert Richter } 460e20960c0SRobert Richter 461*f5fc1412SJiri Olsa rec->post_processing_offset = lseek(file->fd, 0, SEEK_CUR); 4626122e4e4SArnaldo Carvalho de Melo 46334ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 464743eb868SArnaldo Carvalho de Melo 465*f5fc1412SJiri Olsa if (file->is_pipe) { 46645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 467a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 4682c46dbb5STom Zanussi if (err < 0) { 4692c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 4708d3eca20SDavid Ahern goto out_delete_session; 4712c46dbb5STom Zanussi } 472cd19a035STom Zanussi 473361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 47463e0c771STom Zanussi /* 47563e0c771STom Zanussi * FIXME err <= 0 here actually means that 47663e0c771STom Zanussi * there were no tracepoints so its not really 47763e0c771STom Zanussi * an error, just that we don't need to 47863e0c771STom Zanussi * synthesize anything. We really have to 47963e0c771STom Zanussi * return this more properly and also 48063e0c771STom Zanussi * propagate errors that now are calling die() 48163e0c771STom Zanussi */ 482*f5fc1412SJiri Olsa err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, 483743eb868SArnaldo Carvalho de Melo process_synthesized_event); 48463e0c771STom Zanussi if (err <= 0) { 48563e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 4868d3eca20SDavid Ahern goto out_delete_session; 48763e0c771STom Zanussi } 488d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 4892c46dbb5STom Zanussi } 49063e0c771STom Zanussi } 4912c46dbb5STom Zanussi 49245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 493743eb868SArnaldo Carvalho de Melo machine, "_text"); 49470162138SArnaldo Carvalho de Melo if (err < 0) 49545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 496743eb868SArnaldo Carvalho de Melo machine, "_stext"); 497c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 498c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 499c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 500c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 50156b03f3cSArnaldo Carvalho de Melo 50245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 503743eb868SArnaldo Carvalho de Melo machine); 504c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 505c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 506c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 507c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 508c1a3a4b9SArnaldo Carvalho de Melo 5097e383de4SArnaldo Carvalho de Melo if (perf_guest) { 510876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 5117e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 5127e383de4SArnaldo Carvalho de Melo } 513b7cece76SArnaldo Carvalho de Melo 514e4dd45feSJiri Olsa if (perf_target__has_task(&opts->target)) 5158d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 5168115d60cSArnaldo Carvalho de Melo process_synthesized_event, 517743eb868SArnaldo Carvalho de Melo machine); 518e4dd45feSJiri Olsa else if (perf_target__has_cpu(&opts->target)) 5198d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 520743eb868SArnaldo Carvalho de Melo machine); 521e4dd45feSJiri Olsa else /* command specified */ 522e4dd45feSJiri Olsa err = 0; 5237c6a1c65SPeter Zijlstra 5248d3eca20SDavid Ahern if (err != 0) 5258d3eca20SDavid Ahern goto out_delete_session; 5268d3eca20SDavid Ahern 527d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 52886470930SIngo Molnar struct sched_param param; 52986470930SIngo Molnar 530d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 53186470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5326beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 5338d3eca20SDavid Ahern err = -1; 5348d3eca20SDavid Ahern goto out_delete_session; 53586470930SIngo Molnar } 53686470930SIngo Molnar } 53786470930SIngo Molnar 538774cb499SJiri Olsa /* 539774cb499SJiri Olsa * When perf is starting the traced process, all the events 540774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 541774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 542774cb499SJiri Olsa */ 543774cb499SJiri Olsa if (!perf_target__none(&opts->target)) 544764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 545764e16a3SDavid Ahern 546856e9660SPeter Zijlstra /* 547856e9660SPeter Zijlstra * Let the child rip 548856e9660SPeter Zijlstra */ 549d4db3f16SArnaldo Carvalho de Melo if (forks) 55035b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 551856e9660SPeter Zijlstra 552649c48a9SPeter Zijlstra for (;;) { 553d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 55486470930SIngo Molnar 5558d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 5568d3eca20SDavid Ahern err = -1; 5578d3eca20SDavid Ahern goto out_delete_session; 5588d3eca20SDavid Ahern } 55986470930SIngo Molnar 560d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 561649c48a9SPeter Zijlstra if (done) 562649c48a9SPeter Zijlstra break; 5635c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 5648b412664SPeter Zijlstra waking++; 5658b412664SPeter Zijlstra } 5668b412664SPeter Zijlstra 567774cb499SJiri Olsa /* 568774cb499SJiri Olsa * When perf is starting the traced process, at the end events 569774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 570774cb499SJiri Olsa * disable events in this case. 571774cb499SJiri Olsa */ 5722711926aSJiri Olsa if (done && !disabled && !perf_target__none(&opts->target)) { 5734152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 5742711926aSJiri Olsa disabled = true; 5752711926aSJiri Olsa } 5768b412664SPeter Zijlstra } 5778b412664SPeter Zijlstra 57818483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 579b44308f5SArnaldo Carvalho de Melo return 0; 580b44308f5SArnaldo Carvalho de Melo 5818b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 58286470930SIngo Molnar 58386470930SIngo Molnar /* 58486470930SIngo Molnar * Approximate RIP event size: 24 bytes. 58586470930SIngo Molnar */ 58686470930SIngo Molnar fprintf(stderr, 5879486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 588d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 58986470930SIngo Molnar output_name, 590d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 59186470930SIngo Molnar 59286470930SIngo Molnar return 0; 59339d17dacSArnaldo Carvalho de Melo 59439d17dacSArnaldo Carvalho de Melo out_delete_session: 59539d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 59639d17dacSArnaldo Carvalho de Melo return err; 59786470930SIngo Molnar } 59886470930SIngo Molnar 599bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 600bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 601bdfebd84SRoberto Agostino Vitillo 602bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 603bdfebd84SRoberto Agostino Vitillo 604bdfebd84SRoberto Agostino Vitillo struct branch_mode { 605bdfebd84SRoberto Agostino Vitillo const char *name; 606bdfebd84SRoberto Agostino Vitillo int mode; 607bdfebd84SRoberto Agostino Vitillo }; 608bdfebd84SRoberto Agostino Vitillo 609bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 610bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 611bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 612bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 613bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 614bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 615bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 616bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 6170126d493SAndi Kleen BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 6180126d493SAndi Kleen BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 6190126d493SAndi Kleen BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 620bdfebd84SRoberto Agostino Vitillo BRANCH_END 621bdfebd84SRoberto Agostino Vitillo }; 622bdfebd84SRoberto Agostino Vitillo 623bdfebd84SRoberto Agostino Vitillo static int 624a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 625bdfebd84SRoberto Agostino Vitillo { 626bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 627bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 628bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 629bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 630bdfebd84SRoberto Agostino Vitillo 631bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 632bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 633a5aabdacSStephane Eranian char *s, *os = NULL, *p; 634bdfebd84SRoberto Agostino Vitillo int ret = -1; 635bdfebd84SRoberto Agostino Vitillo 636a5aabdacSStephane Eranian if (unset) 637a5aabdacSStephane Eranian return 0; 638bdfebd84SRoberto Agostino Vitillo 639a5aabdacSStephane Eranian /* 640a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 641a5aabdacSStephane Eranian */ 642a5aabdacSStephane Eranian if (*mode) 643a5aabdacSStephane Eranian return -1; 644a5aabdacSStephane Eranian 645a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 646a5aabdacSStephane Eranian if (str) { 647bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 648bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 649bdfebd84SRoberto Agostino Vitillo if (!s) 650bdfebd84SRoberto Agostino Vitillo return -1; 651bdfebd84SRoberto Agostino Vitillo 652bdfebd84SRoberto Agostino Vitillo for (;;) { 653bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 654bdfebd84SRoberto Agostino Vitillo if (p) 655bdfebd84SRoberto Agostino Vitillo *p = '\0'; 656bdfebd84SRoberto Agostino Vitillo 657bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 658bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 659bdfebd84SRoberto Agostino Vitillo break; 660bdfebd84SRoberto Agostino Vitillo } 661a5aabdacSStephane Eranian if (!br->name) { 662a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 663a5aabdacSStephane Eranian " check man page\n", s); 664bdfebd84SRoberto Agostino Vitillo goto error; 665a5aabdacSStephane Eranian } 666bdfebd84SRoberto Agostino Vitillo 667bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 668bdfebd84SRoberto Agostino Vitillo 669bdfebd84SRoberto Agostino Vitillo if (!p) 670bdfebd84SRoberto Agostino Vitillo break; 671bdfebd84SRoberto Agostino Vitillo 672bdfebd84SRoberto Agostino Vitillo s = p + 1; 673bdfebd84SRoberto Agostino Vitillo } 674a5aabdacSStephane Eranian } 675bdfebd84SRoberto Agostino Vitillo ret = 0; 676bdfebd84SRoberto Agostino Vitillo 677a5aabdacSStephane Eranian /* default to any branch */ 678bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 679a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 680bdfebd84SRoberto Agostino Vitillo } 681bdfebd84SRoberto Agostino Vitillo error: 682bdfebd84SRoberto Agostino Vitillo free(os); 683bdfebd84SRoberto Agostino Vitillo return ret; 684bdfebd84SRoberto Agostino Vitillo } 685bdfebd84SRoberto Agostino Vitillo 68689fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 68726d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 68826d33022SJiri Olsa { 68926d33022SJiri Olsa char *endptr; 69026d33022SJiri Olsa unsigned long size; 69126d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 69226d33022SJiri Olsa 69326d33022SJiri Olsa size = strtoul(str, &endptr, 0); 69426d33022SJiri Olsa 69526d33022SJiri Olsa do { 69626d33022SJiri Olsa if (*endptr) 69726d33022SJiri Olsa break; 69826d33022SJiri Olsa 69926d33022SJiri Olsa size = round_up(size, sizeof(u64)); 70026d33022SJiri Olsa if (!size || size > max_size) 70126d33022SJiri Olsa break; 70226d33022SJiri Olsa 70326d33022SJiri Olsa *_size = size; 70426d33022SJiri Olsa return 0; 70526d33022SJiri Olsa 70626d33022SJiri Olsa } while (0); 70726d33022SJiri Olsa 70826d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 70926d33022SJiri Olsa max_size, str); 71026d33022SJiri Olsa return -1; 71126d33022SJiri Olsa } 71289fe808aSIngo Molnar #endif /* HAVE_LIBUNWIND_SUPPORT */ 71326d33022SJiri Olsa 71475d9a108SArnaldo Carvalho de Melo int record_parse_callchain_opt(const struct option *opt, 71575d9a108SArnaldo Carvalho de Melo const char *arg, int unset) 71626d33022SJiri Olsa { 717c5ff78c3SArnaldo Carvalho de Melo struct perf_record_opts *opts = opt->value; 71826d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 71926d33022SJiri Olsa char *buf; 72026d33022SJiri Olsa int ret = -1; 72126d33022SJiri Olsa 72226d33022SJiri Olsa /* --no-call-graph */ 72326d33022SJiri Olsa if (unset) 72426d33022SJiri Olsa return 0; 72526d33022SJiri Olsa 72626d33022SJiri Olsa /* We specified default option if none is provided. */ 72726d33022SJiri Olsa BUG_ON(!arg); 72826d33022SJiri Olsa 72926d33022SJiri Olsa /* We need buffer that we know we can write to. */ 73026d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 73126d33022SJiri Olsa if (!buf) 73226d33022SJiri Olsa return -ENOMEM; 73326d33022SJiri Olsa 73426d33022SJiri Olsa strcpy(buf, arg); 73526d33022SJiri Olsa 73626d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 73726d33022SJiri Olsa name = tok ? : (char *)buf; 73826d33022SJiri Olsa 73926d33022SJiri Olsa do { 74026d33022SJiri Olsa /* Framepointer style */ 74126d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 74226d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 743c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_FP; 74426d33022SJiri Olsa ret = 0; 74526d33022SJiri Olsa } else 74626d33022SJiri Olsa pr_err("callchain: No more arguments " 74726d33022SJiri Olsa "needed for -g fp\n"); 74826d33022SJiri Olsa break; 74926d33022SJiri Olsa 75089fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 75126d33022SJiri Olsa /* Dwarf style */ 75226d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 75361eaa3beSArnaldo Carvalho de Melo const unsigned long default_stack_dump_size = 8192; 75461eaa3beSArnaldo Carvalho de Melo 75526d33022SJiri Olsa ret = 0; 756c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_DWARF; 757c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = default_stack_dump_size; 75826d33022SJiri Olsa 75926d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 76026d33022SJiri Olsa if (tok) { 76126d33022SJiri Olsa unsigned long size = 0; 76226d33022SJiri Olsa 76326d33022SJiri Olsa ret = get_stack_size(tok, &size); 764c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = size; 76526d33022SJiri Olsa } 76626d33022SJiri Olsa 76726d33022SJiri Olsa if (!ret) 76826d33022SJiri Olsa pr_debug("callchain: stack dump size %d\n", 769c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size); 77089fe808aSIngo Molnar #endif /* HAVE_LIBUNWIND_SUPPORT */ 77126d33022SJiri Olsa } else { 77226d33022SJiri Olsa pr_err("callchain: Unknown -g option " 77326d33022SJiri Olsa "value: %s\n", arg); 77426d33022SJiri Olsa break; 77526d33022SJiri Olsa } 77626d33022SJiri Olsa 77726d33022SJiri Olsa } while (0); 77826d33022SJiri Olsa 77926d33022SJiri Olsa free(buf); 78026d33022SJiri Olsa 78126d33022SJiri Olsa if (!ret) 782c5ff78c3SArnaldo Carvalho de Melo pr_debug("callchain: type %d\n", opts->call_graph); 78326d33022SJiri Olsa 78426d33022SJiri Olsa return ret; 78526d33022SJiri Olsa } 78626d33022SJiri Olsa 78786470930SIngo Molnar static const char * const record_usage[] = { 78886470930SIngo Molnar "perf record [<options>] [<command>]", 78986470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 79086470930SIngo Molnar NULL 79186470930SIngo Molnar }; 79286470930SIngo Molnar 793d20deb64SArnaldo Carvalho de Melo /* 794d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 795d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 796d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 797d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 798d20deb64SArnaldo Carvalho de Melo * 799d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 800d20deb64SArnaldo Carvalho de Melo * 801d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 802d20deb64SArnaldo Carvalho de Melo */ 803d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 804d20deb64SArnaldo Carvalho de Melo .opts = { 805d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 806d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 807d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 808447a6013SArnaldo Carvalho de Melo .freq = 4000, 809d1cb9fceSNamhyung Kim .target = { 810d1cb9fceSNamhyung Kim .uses_mmap = true, 811d1cb9fceSNamhyung Kim }, 812d20deb64SArnaldo Carvalho de Melo }, 813d20deb64SArnaldo Carvalho de Melo }; 8147865e817SFrederic Weisbecker 81561eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 81661eaa3beSArnaldo Carvalho de Melo 81789fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 81875d9a108SArnaldo Carvalho de Melo const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 81961eaa3beSArnaldo Carvalho de Melo #else 82075d9a108SArnaldo Carvalho de Melo const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; 82161eaa3beSArnaldo Carvalho de Melo #endif 82261eaa3beSArnaldo Carvalho de Melo 823d20deb64SArnaldo Carvalho de Melo /* 824d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 825d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 826d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 827d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 828d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 829d20deb64SArnaldo Carvalho de Melo */ 830bca647aaSTom Zanussi const struct option record_options[] = { 831d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 83286470930SIngo Molnar "event selector. use 'perf list' to list available events", 833f120f9d5SJiri Olsa parse_events_option), 834d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 835c171b552SLi Zefan "event filter", parse_filter), 836bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 837d6d901c2SZhang, Yanmin "record events on existing process id"), 838bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 839d6d901c2SZhang, Yanmin "record events on existing thread id"), 840d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 84186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 842d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 843acac03faSKirill Smelkov "collect data without buffering"), 844d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 845daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 846bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 84786470930SIngo Molnar "system-wide collection from all CPUs"), 848bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 849c45c6ea2SStephane Eranian "list of cpus to monitor"), 850d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 851*f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 85286470930SIngo Molnar "output file name"), 853d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 8542e6cdf99SStephane Eranian "child tasks do not inherit counters"), 855d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 856994a1f78SJiri Olsa OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 857994a1f78SJiri Olsa "number of mmap data pages", 858994a1f78SJiri Olsa perf_evlist__parse_mmap_pages), 859d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 86043bece79SLin Ming "put the counters into a counter group"), 861c5ff78c3SArnaldo Carvalho de Melo OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, 86275d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 86375d9a108SArnaldo Carvalho de Melo &record_parse_callchain_opt, "fp"), 864c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 8653da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 866b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 867d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 868649c48a9SPeter Zijlstra "per thread counts"), 869d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 8704bba828dSAnton Blanchard "Sample addresses"), 871d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 8723e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 873d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 874649c48a9SPeter Zijlstra "don't sample"), 875d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 876a1ac1d3cSStephane Eranian "do not update the buildid cache"), 877d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 878baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 879d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 880023695d9SStephane Eranian "monitor event in cgroup name only", 881023695d9SStephane Eranian parse_cgroups), 882bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 883bea03405SNamhyung Kim "user to profile"), 884a5aabdacSStephane Eranian 885a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 886a5aabdacSStephane Eranian "branch any", "sample any taken branches", 887a5aabdacSStephane Eranian parse_branch_stack), 888a5aabdacSStephane Eranian 889a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 890a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 891bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 89205484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 89305484298SAndi Kleen "sample by weight (on special events only)"), 894475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 895475eeab9SAndi Kleen "sample transaction flags (special events only)"), 89686470930SIngo Molnar OPT_END() 89786470930SIngo Molnar }; 89886470930SIngo Molnar 8991d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 90086470930SIngo Molnar { 90169aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 902d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 903d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 90416ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 90586470930SIngo Molnar 906334fe7a3SNamhyung Kim evsel_list = perf_evlist__new(); 907361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 908361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 909361c99a6SArnaldo Carvalho de Melo 910d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 911d20deb64SArnaldo Carvalho de Melo 912bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 913a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 914d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 915bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 91686470930SIngo Molnar 917bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 9183780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 919023695d9SStephane Eranian " system-wide mode\n"); 920023695d9SStephane Eranian usage_with_options(record_usage, record_options); 921023695d9SStephane Eranian } 922023695d9SStephane Eranian 923655000e7SArnaldo Carvalho de Melo symbol__init(); 924baa2f6ceSArnaldo Carvalho de Melo 925ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 926646aaea6SArnaldo Carvalho de Melo pr_warning( 927646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 928ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 929646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 930646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 931646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 932646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 933646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 934ec80fde7SArnaldo Carvalho de Melo 935d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 936a1ac1d3cSStephane Eranian disable_buildid_cache(); 937655000e7SArnaldo Carvalho de Melo 938361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 939361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 94069aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 94169aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 942bbd36e5eSPeter Zijlstra } 94386470930SIngo Molnar 94416ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 94516ad2ffbSNamhyung Kim if (err) { 94616ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 94716ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 94816ad2ffbSNamhyung Kim } 9494bd0f2d2SNamhyung Kim 95016ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 95116ad2ffbSNamhyung Kim if (err) { 95216ad2ffbSNamhyung Kim int saved_errno = errno; 95316ad2ffbSNamhyung Kim 95416ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 9553780f488SNamhyung Kim ui__error("%s", errbuf); 95616ad2ffbSNamhyung Kim 95716ad2ffbSNamhyung Kim err = -saved_errno; 9588fa60e1fSNamhyung Kim goto out_symbol_exit; 95916ad2ffbSNamhyung Kim } 9600d37aa34SArnaldo Carvalho de Melo 96116ad2ffbSNamhyung Kim err = -ENOMEM; 962b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 963dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 96469aad6f1SArnaldo Carvalho de Melo 965d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 966d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 967d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 968d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 969f9212819SFrederic Weisbecker 9707e4ff9e3SMike Galbraith /* 9717e4ff9e3SMike Galbraith * User specified count overrides default frequency. 9727e4ff9e3SMike Galbraith */ 973d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 974d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 975d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 976d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 9777e4ff9e3SMike Galbraith } else { 9783780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 97939d17dacSArnaldo Carvalho de Melo err = -EINVAL; 9805c581041SArnaldo Carvalho de Melo goto out_free_fd; 9817e4ff9e3SMike Galbraith } 9827e4ff9e3SMike Galbraith 983d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 9848fa60e1fSNamhyung Kim 9858fa60e1fSNamhyung Kim perf_evlist__munmap(evsel_list); 9868fa60e1fSNamhyung Kim perf_evlist__close(evsel_list); 98739d17dacSArnaldo Carvalho de Melo out_free_fd: 9887e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 989d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 990d65a458bSArnaldo Carvalho de Melo symbol__exit(); 99139d17dacSArnaldo Carvalho de Melo return err; 99286470930SIngo Molnar } 993