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" 27f5fc1412SJiri 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; 69f5fc1412SJiri 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; 770f82ebc4SArnaldo Carvalho de Melo }; 7886470930SIngo Molnar 798d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size) 80f5970550SPeter Zijlstra { 81f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 82f5fc1412SJiri Olsa 83f5970550SPeter Zijlstra while (size) { 84f5fc1412SJiri Olsa int ret = write(file->fd, buf, size); 85f5970550SPeter Zijlstra 868d3eca20SDavid Ahern if (ret < 0) { 874f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 888d3eca20SDavid Ahern return -1; 898d3eca20SDavid Ahern } 90f5970550SPeter Zijlstra 91f5970550SPeter Zijlstra size -= ret; 92f5970550SPeter Zijlstra buf += ret; 93f5970550SPeter Zijlstra 94d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 95f5970550SPeter Zijlstra } 968d3eca20SDavid Ahern 978d3eca20SDavid Ahern return 0; 98f5970550SPeter Zijlstra } 99f5970550SPeter Zijlstra 10045694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 101d20deb64SArnaldo Carvalho de Melo union perf_event *event, 1021d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 1031d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 104234fbbf5SArnaldo Carvalho de Melo { 10545694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 1068d3eca20SDavid Ahern if (write_output(rec, event, event->header.size) < 0) 1078d3eca20SDavid Ahern return -1; 1088d3eca20SDavid Ahern 109234fbbf5SArnaldo Carvalho de Melo return 0; 110234fbbf5SArnaldo Carvalho de Melo } 111234fbbf5SArnaldo Carvalho de Melo 1128d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec, 113d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 11486470930SIngo Molnar { 115744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 11686470930SIngo Molnar unsigned int old = md->prev; 117918512b4SJiri Olsa unsigned char *data = md->base + page_size; 11886470930SIngo Molnar unsigned long size; 11986470930SIngo Molnar void *buf; 1208d3eca20SDavid Ahern int rc = 0; 12186470930SIngo Molnar 122dc82009aSArnaldo Carvalho de Melo if (old == head) 1238d3eca20SDavid Ahern return 0; 12486470930SIngo Molnar 125d20deb64SArnaldo Carvalho de Melo rec->samples++; 12686470930SIngo Molnar 12786470930SIngo Molnar size = head - old; 12886470930SIngo Molnar 12986470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 13086470930SIngo Molnar buf = &data[old & md->mask]; 13186470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 13286470930SIngo Molnar old += size; 13386470930SIngo Molnar 1348d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1358d3eca20SDavid Ahern rc = -1; 1368d3eca20SDavid Ahern goto out; 1378d3eca20SDavid Ahern } 13886470930SIngo Molnar } 13986470930SIngo Molnar 14086470930SIngo Molnar buf = &data[old & md->mask]; 14186470930SIngo Molnar size = head - old; 14286470930SIngo Molnar old += size; 14386470930SIngo Molnar 1448d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1458d3eca20SDavid Ahern rc = -1; 1468d3eca20SDavid Ahern goto out; 1478d3eca20SDavid Ahern } 14886470930SIngo Molnar 14986470930SIngo Molnar md->prev = old; 150115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 1518d3eca20SDavid Ahern 1528d3eca20SDavid Ahern out: 1538d3eca20SDavid Ahern return rc; 15486470930SIngo Molnar } 15586470930SIngo Molnar 15686470930SIngo Molnar static volatile int done = 0; 157f7b7c26eSPeter Zijlstra static volatile int signr = -1; 15833e49ea7SAndi Kleen static volatile int child_finished = 0; 15986470930SIngo Molnar 16086470930SIngo Molnar static void sig_handler(int sig) 16186470930SIngo Molnar { 16233e49ea7SAndi Kleen if (sig == SIGCHLD) 16333e49ea7SAndi Kleen child_finished = 1; 16433e49ea7SAndi Kleen 16586470930SIngo Molnar done = 1; 166f7b7c26eSPeter Zijlstra signr = sig; 167f7b7c26eSPeter Zijlstra } 168f7b7c26eSPeter Zijlstra 1691d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 170f7b7c26eSPeter Zijlstra { 171d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 17233e49ea7SAndi Kleen int status; 17333e49ea7SAndi Kleen 174d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 17533e49ea7SAndi Kleen if (!child_finished) 176d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 177933da83aSChris Wilson 17833e49ea7SAndi Kleen wait(&status); 17933e49ea7SAndi Kleen if (WIFSIGNALED(status)) 180d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 18133e49ea7SAndi Kleen } 18233e49ea7SAndi Kleen 18318483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 184f7b7c26eSPeter Zijlstra return; 185f7b7c26eSPeter Zijlstra 186f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 18786470930SIngo Molnar } 18886470930SIngo Molnar 1898d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec) 190dd7927f4SArnaldo Carvalho de Melo { 19156e52e85SArnaldo Carvalho de Melo char msg[512]; 1926a4bb04cSJiri Olsa struct perf_evsel *pos; 193d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 194d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 195d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 1968d3eca20SDavid Ahern int rc = 0; 197dd7927f4SArnaldo Carvalho de Melo 198f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 199cac21425SJiri Olsa 200dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 2013da297a6SIngo Molnar try_again: 2026a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 20356e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2043da297a6SIngo Molnar if (verbose) 205c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2063da297a6SIngo Molnar goto try_again; 2073da297a6SIngo Molnar } 208ca6a4258SDavid Ahern 20956e52e85SArnaldo Carvalho de Melo rc = -errno; 21056e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 21156e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 21256e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2138d3eca20SDavid Ahern goto out; 2147c6a1c65SPeter Zijlstra } 2157c6a1c65SPeter Zijlstra } 2167c6a1c65SPeter Zijlstra 2171491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 2180a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2190a102479SFrederic Weisbecker strerror(errno)); 2208d3eca20SDavid Ahern rc = -1; 2218d3eca20SDavid Ahern goto out; 2220a102479SFrederic Weisbecker } 2230a102479SFrederic Weisbecker 22418e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 2258d3eca20SDavid Ahern if (errno == EPERM) { 2268d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 22718e60939SNelson Elhage "Consider increasing " 22818e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 22918e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 23018e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 2318d3eca20SDavid Ahern rc = -errno; 2328d3eca20SDavid Ahern } else { 2338d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 2348d3eca20SDavid Ahern rc = -errno; 2358d3eca20SDavid Ahern } 2368d3eca20SDavid Ahern goto out; 23718e60939SNelson Elhage } 2380a27d7f9SArnaldo Carvalho de Melo 239a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 2407b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 2418d3eca20SDavid Ahern out: 2428d3eca20SDavid Ahern return rc; 243a91e5431SArnaldo Carvalho de Melo } 244a91e5431SArnaldo Carvalho de Melo 245d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 2466122e4e4SArnaldo Carvalho de Melo { 247f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 248f5fc1412SJiri Olsa struct perf_session *session = rec->session; 2497ab75cffSDavid Ahern u64 start = session->header.data_offset; 2506122e4e4SArnaldo Carvalho de Melo 251f5fc1412SJiri Olsa u64 size = lseek(file->fd, 0, SEEK_CUR); 2529f591fd7SArnaldo Carvalho de Melo if (size == 0) 2539f591fd7SArnaldo Carvalho de Melo return 0; 2549f591fd7SArnaldo Carvalho de Melo 2557ab75cffSDavid Ahern return __perf_session__process_events(session, start, 2567ab75cffSDavid Ahern size - start, 2576122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 2586122e4e4SArnaldo Carvalho de Melo } 2596122e4e4SArnaldo Carvalho de Melo 2608d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 261f5970550SPeter Zijlstra { 262d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 263f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 264f5970550SPeter Zijlstra 2658d3eca20SDavid Ahern if (status != 0) 2668d3eca20SDavid Ahern return; 2678d3eca20SDavid Ahern 268f5fc1412SJiri Olsa if (!file->is_pipe) { 269d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 270d20deb64SArnaldo Carvalho de Melo 271d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 272d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 273d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 274f5fc1412SJiri Olsa file->fd, true); 275d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 276d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 277d65a458bSArnaldo Carvalho de Melo symbol__exit(); 278c7929e47STom Zanussi } 279f5970550SPeter Zijlstra } 280f5970550SPeter Zijlstra 2818115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 282a1645ce1SZhang, Yanmin { 283a1645ce1SZhang, Yanmin int err; 28445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 285a1645ce1SZhang, Yanmin /* 286a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 287a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 288a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 289a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 290a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 291a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 292a1645ce1SZhang, Yanmin */ 29345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 294743eb868SArnaldo Carvalho de Melo machine); 295a1645ce1SZhang, Yanmin if (err < 0) 296a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 29723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 298a1645ce1SZhang, Yanmin 299a1645ce1SZhang, Yanmin /* 300a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 301a1645ce1SZhang, Yanmin * have no _text sometimes. 302a1645ce1SZhang, Yanmin */ 30345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 304743eb868SArnaldo Carvalho de Melo machine, "_text"); 305a1645ce1SZhang, Yanmin if (err < 0) 30645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 307743eb868SArnaldo Carvalho de Melo machine, "_stext"); 308a1645ce1SZhang, Yanmin if (err < 0) 309a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 31023346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 311a1645ce1SZhang, Yanmin } 312a1645ce1SZhang, Yanmin 31398402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 31498402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 31598402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 31698402807SFrederic Weisbecker }; 31798402807SFrederic Weisbecker 3188d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 31998402807SFrederic Weisbecker { 3200e2e63ddSPeter Zijlstra int i; 3218d3eca20SDavid Ahern int rc = 0; 32298402807SFrederic Weisbecker 323d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 3248d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 3258d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 3268d3eca20SDavid Ahern rc = -1; 3278d3eca20SDavid Ahern goto out; 3288d3eca20SDavid Ahern } 3298d3eca20SDavid Ahern } 33098402807SFrederic Weisbecker } 33198402807SFrederic Weisbecker 3322eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 3338d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 3348d3eca20SDavid Ahern sizeof(finished_round_event)); 3358d3eca20SDavid Ahern 3368d3eca20SDavid Ahern out: 3378d3eca20SDavid Ahern return rc; 33898402807SFrederic Weisbecker } 33998402807SFrederic Weisbecker 34057706abcSDavid Ahern static void perf_record__init_features(struct perf_record *rec) 34157706abcSDavid Ahern { 34257706abcSDavid Ahern struct perf_evlist *evsel_list = rec->evlist; 34357706abcSDavid Ahern struct perf_session *session = rec->session; 34457706abcSDavid Ahern int feat; 34557706abcSDavid Ahern 34657706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 34757706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 34857706abcSDavid Ahern 34957706abcSDavid Ahern if (rec->no_buildid) 35057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 35157706abcSDavid Ahern 35257706abcSDavid Ahern if (!have_tracepoints(&evsel_list->entries)) 35357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 35457706abcSDavid Ahern 35557706abcSDavid Ahern if (!rec->opts.branch_stack) 35657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 35757706abcSDavid Ahern } 35857706abcSDavid Ahern 359d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 36086470930SIngo Molnar { 36157706abcSDavid Ahern int err; 3628b412664SPeter Zijlstra unsigned long waking = 0; 36346be604bSZhang, Yanmin const bool forks = argc > 0; 36423346f21SArnaldo Carvalho de Melo struct machine *machine; 36545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 366d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 367d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 368f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 369d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 3702711926aSJiri Olsa bool disabled = false; 37186470930SIngo Molnar 372d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 37333e49ea7SAndi Kleen 374d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 375f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 376f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 37718483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 378804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 379f5970550SPeter Zijlstra 380f5fc1412SJiri Olsa session = perf_session__new(file, false, NULL); 38194c744b6SArnaldo Carvalho de Melo if (session == NULL) { 382a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 383a9a70bbcSArnaldo Carvalho de Melo return -1; 384a9a70bbcSArnaldo Carvalho de Melo } 385a9a70bbcSArnaldo Carvalho de Melo 386d20deb64SArnaldo Carvalho de Melo rec->session = session; 387d20deb64SArnaldo Carvalho de Melo 38857706abcSDavid Ahern perf_record__init_features(rec); 389330aa675SStephane Eranian 390d4db3f16SArnaldo Carvalho de Melo if (forks) { 3916ef73ec4SNamhyung Kim err = perf_evlist__prepare_workload(evsel_list, &opts->target, 392f5fc1412SJiri Olsa argv, file->is_pipe, 39355e162eaSNamhyung Kim true); 39435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 39535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 39635b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 397856e9660SPeter Zijlstra } 398856e9660SPeter Zijlstra } 399856e9660SPeter Zijlstra 4008d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 4018d3eca20SDavid Ahern err = -1; 4028d3eca20SDavid Ahern goto out_delete_session; 4038d3eca20SDavid Ahern } 40486470930SIngo Molnar 405a8bb559bSNamhyung Kim if (!evsel_list->nr_groups) 406a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 407a8bb559bSNamhyung Kim 408712a4b60SArnaldo Carvalho de Melo /* 409d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 410712a4b60SArnaldo Carvalho de Melo */ 411d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 412712a4b60SArnaldo Carvalho de Melo 413f5fc1412SJiri Olsa if (file->is_pipe) { 414f5fc1412SJiri Olsa err = perf_header__write_pipe(file->fd); 415529870e3STom Zanussi if (err < 0) 4168d3eca20SDavid Ahern goto out_delete_session; 417563aecb2SJiri Olsa } else { 418a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 419f5fc1412SJiri Olsa file->fd, false); 420d5eed904SArnaldo Carvalho de Melo if (err < 0) 4218d3eca20SDavid Ahern goto out_delete_session; 422d5eed904SArnaldo Carvalho de Melo } 4237c6a1c65SPeter Zijlstra 424d3665498SDavid Ahern if (!rec->no_buildid 425e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 426d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 427e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 4288d3eca20SDavid Ahern err = -1; 4298d3eca20SDavid Ahern goto out_delete_session; 430e20960c0SRobert Richter } 431e20960c0SRobert Richter 43234ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 433743eb868SArnaldo Carvalho de Melo 434f5fc1412SJiri Olsa if (file->is_pipe) { 43545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 436a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 4372c46dbb5STom Zanussi if (err < 0) { 4382c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 4398d3eca20SDavid Ahern goto out_delete_session; 4402c46dbb5STom Zanussi } 441cd19a035STom Zanussi 442361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 44363e0c771STom Zanussi /* 44463e0c771STom Zanussi * FIXME err <= 0 here actually means that 44563e0c771STom Zanussi * there were no tracepoints so its not really 44663e0c771STom Zanussi * an error, just that we don't need to 44763e0c771STom Zanussi * synthesize anything. We really have to 44863e0c771STom Zanussi * return this more properly and also 44963e0c771STom Zanussi * propagate errors that now are calling die() 45063e0c771STom Zanussi */ 451f5fc1412SJiri Olsa err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, 452743eb868SArnaldo Carvalho de Melo process_synthesized_event); 45363e0c771STom Zanussi if (err <= 0) { 45463e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 4558d3eca20SDavid Ahern goto out_delete_session; 45663e0c771STom Zanussi } 457f34b9001SDavid Ahern rec->bytes_written += err; 4582c46dbb5STom Zanussi } 45963e0c771STom Zanussi } 4602c46dbb5STom Zanussi 46145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 462743eb868SArnaldo Carvalho de Melo machine, "_text"); 46370162138SArnaldo Carvalho de Melo if (err < 0) 46445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 465743eb868SArnaldo Carvalho de Melo machine, "_stext"); 466c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 467c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 468c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 469c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 47056b03f3cSArnaldo Carvalho de Melo 47145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 472743eb868SArnaldo Carvalho de Melo machine); 473c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 474c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 475c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 476c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 477c1a3a4b9SArnaldo Carvalho de Melo 4787e383de4SArnaldo Carvalho de Melo if (perf_guest) { 479876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 4807e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 4817e383de4SArnaldo Carvalho de Melo } 482b7cece76SArnaldo Carvalho de Melo 483*a33fbd56SArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, 48458d925dcSArnaldo Carvalho de Melo process_synthesized_event, opts->sample_address); 4858d3eca20SDavid Ahern if (err != 0) 4868d3eca20SDavid Ahern goto out_delete_session; 4878d3eca20SDavid Ahern 488d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 48986470930SIngo Molnar struct sched_param param; 49086470930SIngo Molnar 491d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 49286470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 4936beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 4948d3eca20SDavid Ahern err = -1; 4958d3eca20SDavid Ahern goto out_delete_session; 49686470930SIngo Molnar } 49786470930SIngo Molnar } 49886470930SIngo Molnar 499774cb499SJiri Olsa /* 500774cb499SJiri Olsa * When perf is starting the traced process, all the events 501774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 502774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 503774cb499SJiri Olsa */ 504774cb499SJiri Olsa if (!perf_target__none(&opts->target)) 505764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 506764e16a3SDavid Ahern 507856e9660SPeter Zijlstra /* 508856e9660SPeter Zijlstra * Let the child rip 509856e9660SPeter Zijlstra */ 510d4db3f16SArnaldo Carvalho de Melo if (forks) 51135b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 512856e9660SPeter Zijlstra 513649c48a9SPeter Zijlstra for (;;) { 514d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 51586470930SIngo Molnar 5168d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 5178d3eca20SDavid Ahern err = -1; 5188d3eca20SDavid Ahern goto out_delete_session; 5198d3eca20SDavid Ahern } 52086470930SIngo Molnar 521d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 522649c48a9SPeter Zijlstra if (done) 523649c48a9SPeter Zijlstra break; 5245c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 5258b412664SPeter Zijlstra waking++; 5268b412664SPeter Zijlstra } 5278b412664SPeter Zijlstra 528774cb499SJiri Olsa /* 529774cb499SJiri Olsa * When perf is starting the traced process, at the end events 530774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 531774cb499SJiri Olsa * disable events in this case. 532774cb499SJiri Olsa */ 5332711926aSJiri Olsa if (done && !disabled && !perf_target__none(&opts->target)) { 5344152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 5352711926aSJiri Olsa disabled = true; 5362711926aSJiri Olsa } 5378b412664SPeter Zijlstra } 5388b412664SPeter Zijlstra 53918483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 540b44308f5SArnaldo Carvalho de Melo return 0; 541b44308f5SArnaldo Carvalho de Melo 5428b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 54386470930SIngo Molnar 54486470930SIngo Molnar /* 54586470930SIngo Molnar * Approximate RIP event size: 24 bytes. 54686470930SIngo Molnar */ 54786470930SIngo Molnar fprintf(stderr, 5489486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 549d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 5506a4d98d7SJiri Olsa file->path, 551d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 55286470930SIngo Molnar 55386470930SIngo Molnar return 0; 55439d17dacSArnaldo Carvalho de Melo 55539d17dacSArnaldo Carvalho de Melo out_delete_session: 55639d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 55739d17dacSArnaldo Carvalho de Melo return err; 55886470930SIngo Molnar } 55986470930SIngo Molnar 560bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 561bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 562bdfebd84SRoberto Agostino Vitillo 563bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 564bdfebd84SRoberto Agostino Vitillo 565bdfebd84SRoberto Agostino Vitillo struct branch_mode { 566bdfebd84SRoberto Agostino Vitillo const char *name; 567bdfebd84SRoberto Agostino Vitillo int mode; 568bdfebd84SRoberto Agostino Vitillo }; 569bdfebd84SRoberto Agostino Vitillo 570bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 571bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 572bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 573bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 574bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 575bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 576bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 577bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 5780126d493SAndi Kleen BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 5790126d493SAndi Kleen BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 5800126d493SAndi Kleen BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 581bdfebd84SRoberto Agostino Vitillo BRANCH_END 582bdfebd84SRoberto Agostino Vitillo }; 583bdfebd84SRoberto Agostino Vitillo 584bdfebd84SRoberto Agostino Vitillo static int 585a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 586bdfebd84SRoberto Agostino Vitillo { 587bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 588bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 589bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 590bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 591bdfebd84SRoberto Agostino Vitillo 592bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 593bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 594a5aabdacSStephane Eranian char *s, *os = NULL, *p; 595bdfebd84SRoberto Agostino Vitillo int ret = -1; 596bdfebd84SRoberto Agostino Vitillo 597a5aabdacSStephane Eranian if (unset) 598a5aabdacSStephane Eranian return 0; 599bdfebd84SRoberto Agostino Vitillo 600a5aabdacSStephane Eranian /* 601a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 602a5aabdacSStephane Eranian */ 603a5aabdacSStephane Eranian if (*mode) 604a5aabdacSStephane Eranian return -1; 605a5aabdacSStephane Eranian 606a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 607a5aabdacSStephane Eranian if (str) { 608bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 609bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 610bdfebd84SRoberto Agostino Vitillo if (!s) 611bdfebd84SRoberto Agostino Vitillo return -1; 612bdfebd84SRoberto Agostino Vitillo 613bdfebd84SRoberto Agostino Vitillo for (;;) { 614bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 615bdfebd84SRoberto Agostino Vitillo if (p) 616bdfebd84SRoberto Agostino Vitillo *p = '\0'; 617bdfebd84SRoberto Agostino Vitillo 618bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 619bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 620bdfebd84SRoberto Agostino Vitillo break; 621bdfebd84SRoberto Agostino Vitillo } 622a5aabdacSStephane Eranian if (!br->name) { 623a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 624a5aabdacSStephane Eranian " check man page\n", s); 625bdfebd84SRoberto Agostino Vitillo goto error; 626a5aabdacSStephane Eranian } 627bdfebd84SRoberto Agostino Vitillo 628bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 629bdfebd84SRoberto Agostino Vitillo 630bdfebd84SRoberto Agostino Vitillo if (!p) 631bdfebd84SRoberto Agostino Vitillo break; 632bdfebd84SRoberto Agostino Vitillo 633bdfebd84SRoberto Agostino Vitillo s = p + 1; 634bdfebd84SRoberto Agostino Vitillo } 635a5aabdacSStephane Eranian } 636bdfebd84SRoberto Agostino Vitillo ret = 0; 637bdfebd84SRoberto Agostino Vitillo 638a5aabdacSStephane Eranian /* default to any branch */ 639bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 640a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 641bdfebd84SRoberto Agostino Vitillo } 642bdfebd84SRoberto Agostino Vitillo error: 643bdfebd84SRoberto Agostino Vitillo free(os); 644bdfebd84SRoberto Agostino Vitillo return ret; 645bdfebd84SRoberto Agostino Vitillo } 646bdfebd84SRoberto Agostino Vitillo 64789fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 64826d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 64926d33022SJiri Olsa { 65026d33022SJiri Olsa char *endptr; 65126d33022SJiri Olsa unsigned long size; 65226d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 65326d33022SJiri Olsa 65426d33022SJiri Olsa size = strtoul(str, &endptr, 0); 65526d33022SJiri Olsa 65626d33022SJiri Olsa do { 65726d33022SJiri Olsa if (*endptr) 65826d33022SJiri Olsa break; 65926d33022SJiri Olsa 66026d33022SJiri Olsa size = round_up(size, sizeof(u64)); 66126d33022SJiri Olsa if (!size || size > max_size) 66226d33022SJiri Olsa break; 66326d33022SJiri Olsa 66426d33022SJiri Olsa *_size = size; 66526d33022SJiri Olsa return 0; 66626d33022SJiri Olsa 66726d33022SJiri Olsa } while (0); 66826d33022SJiri Olsa 66926d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 67026d33022SJiri Olsa max_size, str); 67126d33022SJiri Olsa return -1; 67226d33022SJiri Olsa } 67389fe808aSIngo Molnar #endif /* HAVE_LIBUNWIND_SUPPORT */ 67426d33022SJiri Olsa 67509b0fd45SJiri Olsa int record_parse_callchain(const char *arg, struct perf_record_opts *opts) 67626d33022SJiri Olsa { 67726d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 67826d33022SJiri Olsa char *buf; 67926d33022SJiri Olsa int ret = -1; 68026d33022SJiri Olsa 68126d33022SJiri Olsa /* We need buffer that we know we can write to. */ 68226d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 68326d33022SJiri Olsa if (!buf) 68426d33022SJiri Olsa return -ENOMEM; 68526d33022SJiri Olsa 68626d33022SJiri Olsa strcpy(buf, arg); 68726d33022SJiri Olsa 68826d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 68926d33022SJiri Olsa name = tok ? : (char *)buf; 69026d33022SJiri Olsa 69126d33022SJiri Olsa do { 69226d33022SJiri Olsa /* Framepointer style */ 69326d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 69426d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 695c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_FP; 69626d33022SJiri Olsa ret = 0; 69726d33022SJiri Olsa } else 69826d33022SJiri Olsa pr_err("callchain: No more arguments " 69926d33022SJiri Olsa "needed for -g fp\n"); 70026d33022SJiri Olsa break; 70126d33022SJiri Olsa 70289fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 70326d33022SJiri Olsa /* Dwarf style */ 70426d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 70561eaa3beSArnaldo Carvalho de Melo const unsigned long default_stack_dump_size = 8192; 70661eaa3beSArnaldo Carvalho de Melo 70726d33022SJiri Olsa ret = 0; 708c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_DWARF; 709c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = default_stack_dump_size; 71026d33022SJiri Olsa 71126d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 71226d33022SJiri Olsa if (tok) { 71326d33022SJiri Olsa unsigned long size = 0; 71426d33022SJiri Olsa 71526d33022SJiri Olsa ret = get_stack_size(tok, &size); 716c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = size; 71726d33022SJiri Olsa } 71889fe808aSIngo Molnar #endif /* HAVE_LIBUNWIND_SUPPORT */ 71926d33022SJiri Olsa } else { 72009b0fd45SJiri Olsa pr_err("callchain: Unknown --call-graph option " 72126d33022SJiri Olsa "value: %s\n", arg); 72226d33022SJiri Olsa break; 72326d33022SJiri Olsa } 72426d33022SJiri Olsa 72526d33022SJiri Olsa } while (0); 72626d33022SJiri Olsa 72726d33022SJiri Olsa free(buf); 72809b0fd45SJiri Olsa return ret; 72909b0fd45SJiri Olsa } 73026d33022SJiri Olsa 73109b0fd45SJiri Olsa static void callchain_debug(struct perf_record_opts *opts) 73209b0fd45SJiri Olsa { 733c5ff78c3SArnaldo Carvalho de Melo pr_debug("callchain: type %d\n", opts->call_graph); 73426d33022SJiri Olsa 73509b0fd45SJiri Olsa if (opts->call_graph == CALLCHAIN_DWARF) 73609b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 73709b0fd45SJiri Olsa opts->stack_dump_size); 73809b0fd45SJiri Olsa } 73909b0fd45SJiri Olsa 74009b0fd45SJiri Olsa int record_parse_callchain_opt(const struct option *opt, 74109b0fd45SJiri Olsa const char *arg, 74209b0fd45SJiri Olsa int unset) 74309b0fd45SJiri Olsa { 74409b0fd45SJiri Olsa struct perf_record_opts *opts = opt->value; 74509b0fd45SJiri Olsa int ret; 74609b0fd45SJiri Olsa 74709b0fd45SJiri Olsa /* --no-call-graph */ 74809b0fd45SJiri Olsa if (unset) { 74909b0fd45SJiri Olsa opts->call_graph = CALLCHAIN_NONE; 75009b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 75109b0fd45SJiri Olsa return 0; 75209b0fd45SJiri Olsa } 75309b0fd45SJiri Olsa 75409b0fd45SJiri Olsa ret = record_parse_callchain(arg, opts); 75509b0fd45SJiri Olsa if (!ret) 75609b0fd45SJiri Olsa callchain_debug(opts); 75709b0fd45SJiri Olsa 75826d33022SJiri Olsa return ret; 75926d33022SJiri Olsa } 76026d33022SJiri Olsa 76109b0fd45SJiri Olsa int record_callchain_opt(const struct option *opt, 76209b0fd45SJiri Olsa const char *arg __maybe_unused, 76309b0fd45SJiri Olsa int unset __maybe_unused) 76409b0fd45SJiri Olsa { 76509b0fd45SJiri Olsa struct perf_record_opts *opts = opt->value; 76609b0fd45SJiri Olsa 76709b0fd45SJiri Olsa if (opts->call_graph == CALLCHAIN_NONE) 76809b0fd45SJiri Olsa opts->call_graph = CALLCHAIN_FP; 76909b0fd45SJiri Olsa 77009b0fd45SJiri Olsa callchain_debug(opts); 77109b0fd45SJiri Olsa return 0; 77209b0fd45SJiri Olsa } 77309b0fd45SJiri Olsa 77486470930SIngo Molnar static const char * const record_usage[] = { 77586470930SIngo Molnar "perf record [<options>] [<command>]", 77686470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 77786470930SIngo Molnar NULL 77886470930SIngo Molnar }; 77986470930SIngo Molnar 780d20deb64SArnaldo Carvalho de Melo /* 781d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 782d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 783d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 784d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 785d20deb64SArnaldo Carvalho de Melo * 786d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 787d20deb64SArnaldo Carvalho de Melo * 788d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 789d20deb64SArnaldo Carvalho de Melo */ 790d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 791d20deb64SArnaldo Carvalho de Melo .opts = { 792d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 793d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 794d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 795447a6013SArnaldo Carvalho de Melo .freq = 4000, 796d1cb9fceSNamhyung Kim .target = { 797d1cb9fceSNamhyung Kim .uses_mmap = true, 798d1cb9fceSNamhyung Kim }, 799d20deb64SArnaldo Carvalho de Melo }, 800d20deb64SArnaldo Carvalho de Melo }; 8017865e817SFrederic Weisbecker 80209b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 80361eaa3beSArnaldo Carvalho de Melo 80489fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 80509b0fd45SJiri Olsa const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 80661eaa3beSArnaldo Carvalho de Melo #else 80709b0fd45SJiri Olsa const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 80861eaa3beSArnaldo Carvalho de Melo #endif 80961eaa3beSArnaldo Carvalho de Melo 810d20deb64SArnaldo Carvalho de Melo /* 811d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 812d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 813d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 814d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 815d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 816d20deb64SArnaldo Carvalho de Melo */ 817bca647aaSTom Zanussi const struct option record_options[] = { 818d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 81986470930SIngo Molnar "event selector. use 'perf list' to list available events", 820f120f9d5SJiri Olsa parse_events_option), 821d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 822c171b552SLi Zefan "event filter", parse_filter), 823bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 824d6d901c2SZhang, Yanmin "record events on existing process id"), 825bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 826d6d901c2SZhang, Yanmin "record events on existing thread id"), 827d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 82886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 829d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 830acac03faSKirill Smelkov "collect data without buffering"), 831d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 832daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 833bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 83486470930SIngo Molnar "system-wide collection from all CPUs"), 835bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 836c45c6ea2SStephane Eranian "list of cpus to monitor"), 837d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 838f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 83986470930SIngo Molnar "output file name"), 840d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 8412e6cdf99SStephane Eranian "child tasks do not inherit counters"), 842d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 843994a1f78SJiri Olsa OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 844994a1f78SJiri Olsa "number of mmap data pages", 845994a1f78SJiri Olsa perf_evlist__parse_mmap_pages), 846d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 84743bece79SLin Ming "put the counters into a counter group"), 84809b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 84909b0fd45SJiri Olsa NULL, "enables call-graph recording" , 85009b0fd45SJiri Olsa &record_callchain_opt), 85109b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 85275d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 85309b0fd45SJiri Olsa &record_parse_callchain_opt), 854c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 8553da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 856b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 857d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 858649c48a9SPeter Zijlstra "per thread counts"), 859d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 8604bba828dSAnton Blanchard "Sample addresses"), 861d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 8623e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 863d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 864649c48a9SPeter Zijlstra "don't sample"), 865d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 866a1ac1d3cSStephane Eranian "do not update the buildid cache"), 867d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 868baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 869d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 870023695d9SStephane Eranian "monitor event in cgroup name only", 871023695d9SStephane Eranian parse_cgroups), 872bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 873bea03405SNamhyung Kim "user to profile"), 874a5aabdacSStephane Eranian 875a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 876a5aabdacSStephane Eranian "branch any", "sample any taken branches", 877a5aabdacSStephane Eranian parse_branch_stack), 878a5aabdacSStephane Eranian 879a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 880a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 881bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 88205484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 88305484298SAndi Kleen "sample by weight (on special events only)"), 884475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 885475eeab9SAndi Kleen "sample transaction flags (special events only)"), 88686470930SIngo Molnar OPT_END() 88786470930SIngo Molnar }; 88886470930SIngo Molnar 8891d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 89086470930SIngo Molnar { 89169aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 892d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 893d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 89416ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 89586470930SIngo Molnar 896334fe7a3SNamhyung Kim evsel_list = perf_evlist__new(); 897361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 898361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 899361c99a6SArnaldo Carvalho de Melo 900d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 901d20deb64SArnaldo Carvalho de Melo 902bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 903a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 904d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 905bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 90686470930SIngo Molnar 907bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 9083780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 909023695d9SStephane Eranian " system-wide mode\n"); 910023695d9SStephane Eranian usage_with_options(record_usage, record_options); 911023695d9SStephane Eranian } 912023695d9SStephane Eranian 913655000e7SArnaldo Carvalho de Melo symbol__init(); 914baa2f6ceSArnaldo Carvalho de Melo 915ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 916646aaea6SArnaldo Carvalho de Melo pr_warning( 917646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 918ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 919646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 920646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 921646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 922646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 923646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 924ec80fde7SArnaldo Carvalho de Melo 925d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 926a1ac1d3cSStephane Eranian disable_buildid_cache(); 927655000e7SArnaldo Carvalho de Melo 928361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 929361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 93069aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 93169aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 932bbd36e5eSPeter Zijlstra } 93386470930SIngo Molnar 93416ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 93516ad2ffbSNamhyung Kim if (err) { 93616ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 93716ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 93816ad2ffbSNamhyung Kim } 9394bd0f2d2SNamhyung Kim 94016ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 94116ad2ffbSNamhyung Kim if (err) { 94216ad2ffbSNamhyung Kim int saved_errno = errno; 94316ad2ffbSNamhyung Kim 94416ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 9453780f488SNamhyung Kim ui__error("%s", errbuf); 94616ad2ffbSNamhyung Kim 94716ad2ffbSNamhyung Kim err = -saved_errno; 9488fa60e1fSNamhyung Kim goto out_symbol_exit; 94916ad2ffbSNamhyung Kim } 9500d37aa34SArnaldo Carvalho de Melo 95116ad2ffbSNamhyung Kim err = -ENOMEM; 952b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 953dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 95469aad6f1SArnaldo Carvalho de Melo 955714647bdSJiri Olsa if (perf_record_opts__config(&rec->opts)) { 95639d17dacSArnaldo Carvalho de Melo err = -EINVAL; 9575c581041SArnaldo Carvalho de Melo goto out_free_fd; 9587e4ff9e3SMike Galbraith } 9597e4ff9e3SMike Galbraith 960d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 9618fa60e1fSNamhyung Kim 9628fa60e1fSNamhyung Kim perf_evlist__munmap(evsel_list); 9638fa60e1fSNamhyung Kim perf_evlist__close(evsel_list); 96439d17dacSArnaldo Carvalho de Melo out_free_fd: 9657e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 966d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 967d65a458bSArnaldo Carvalho de Melo symbol__exit(); 96839d17dacSArnaldo Carvalho de Melo return err; 96986470930SIngo Molnar } 970