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; 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 { 87f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 88f5fc1412SJiri Olsa 89f5970550SPeter Zijlstra while (size) { 90f5fc1412SJiri 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 { 253f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 254f5fc1412SJiri Olsa struct perf_session *session = rec->session; 2556122e4e4SArnaldo Carvalho de Melo 256f5fc1412SJiri 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 260f5fc1412SJiri Olsa return __perf_session__process_events(session, rec->post_processing_offset, 261d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 2626122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 2636122e4e4SArnaldo Carvalho de Melo } 2646122e4e4SArnaldo Carvalho de Melo 2658d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 266f5970550SPeter Zijlstra { 267d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 268f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 269f5970550SPeter Zijlstra 2708d3eca20SDavid Ahern if (status != 0) 2718d3eca20SDavid Ahern return; 2728d3eca20SDavid Ahern 273f5fc1412SJiri Olsa if (!file->is_pipe) { 274d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 275d20deb64SArnaldo Carvalho de Melo 276d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 277d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 278d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 279f5fc1412SJiri Olsa file->fd, true); 280d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 281d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 282d65a458bSArnaldo Carvalho de Melo symbol__exit(); 283c7929e47STom Zanussi } 284f5970550SPeter Zijlstra } 285f5970550SPeter Zijlstra 2868115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 287a1645ce1SZhang, Yanmin { 288a1645ce1SZhang, Yanmin int err; 28945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 290a1645ce1SZhang, Yanmin /* 291a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 292a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 293a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 294a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 295a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 296a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 297a1645ce1SZhang, Yanmin */ 29845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 299743eb868SArnaldo Carvalho de Melo machine); 300a1645ce1SZhang, Yanmin if (err < 0) 301a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 30223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 303a1645ce1SZhang, Yanmin 304a1645ce1SZhang, Yanmin /* 305a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 306a1645ce1SZhang, Yanmin * have no _text sometimes. 307a1645ce1SZhang, Yanmin */ 30845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 309743eb868SArnaldo Carvalho de Melo machine, "_text"); 310a1645ce1SZhang, Yanmin if (err < 0) 31145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 312743eb868SArnaldo Carvalho de Melo machine, "_stext"); 313a1645ce1SZhang, Yanmin if (err < 0) 314a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 31523346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 316a1645ce1SZhang, Yanmin } 317a1645ce1SZhang, Yanmin 31898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 31998402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 32098402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 32198402807SFrederic Weisbecker }; 32298402807SFrederic Weisbecker 3238d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 32498402807SFrederic Weisbecker { 3250e2e63ddSPeter Zijlstra int i; 3268d3eca20SDavid Ahern int rc = 0; 32798402807SFrederic Weisbecker 328d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 3298d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 3308d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 3318d3eca20SDavid Ahern rc = -1; 3328d3eca20SDavid Ahern goto out; 3338d3eca20SDavid Ahern } 3348d3eca20SDavid Ahern } 33598402807SFrederic Weisbecker } 33698402807SFrederic Weisbecker 3372eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 3388d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 3398d3eca20SDavid Ahern sizeof(finished_round_event)); 3408d3eca20SDavid Ahern 3418d3eca20SDavid Ahern out: 3428d3eca20SDavid Ahern return rc; 34398402807SFrederic Weisbecker } 34498402807SFrederic Weisbecker 345*57706abcSDavid Ahern static void perf_record__init_features(struct perf_record *rec) 346*57706abcSDavid Ahern { 347*57706abcSDavid Ahern struct perf_evlist *evsel_list = rec->evlist; 348*57706abcSDavid Ahern struct perf_session *session = rec->session; 349*57706abcSDavid Ahern int feat; 350*57706abcSDavid Ahern 351*57706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 352*57706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 353*57706abcSDavid Ahern 354*57706abcSDavid Ahern if (rec->no_buildid) 355*57706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 356*57706abcSDavid Ahern 357*57706abcSDavid Ahern if (!have_tracepoints(&evsel_list->entries)) 358*57706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 359*57706abcSDavid Ahern 360*57706abcSDavid Ahern if (!rec->opts.branch_stack) 361*57706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 362*57706abcSDavid Ahern } 363*57706abcSDavid Ahern 364d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 36586470930SIngo Molnar { 366*57706abcSDavid Ahern int err; 3678b412664SPeter Zijlstra unsigned long waking = 0; 36846be604bSZhang, Yanmin const bool forks = argc > 0; 36923346f21SArnaldo Carvalho de Melo struct machine *machine; 37045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 371d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 372d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 373f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 374d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 3752711926aSJiri Olsa bool disabled = false; 37686470930SIngo Molnar 377d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 37833e49ea7SAndi Kleen 379d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 380f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 381f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 38218483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 383804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 384f5970550SPeter Zijlstra 385f5fc1412SJiri Olsa session = perf_session__new(file, false, NULL); 38694c744b6SArnaldo Carvalho de Melo if (session == NULL) { 387a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 388a9a70bbcSArnaldo Carvalho de Melo return -1; 389a9a70bbcSArnaldo Carvalho de Melo } 390a9a70bbcSArnaldo Carvalho de Melo 391d20deb64SArnaldo Carvalho de Melo rec->session = session; 392d20deb64SArnaldo Carvalho de Melo 393*57706abcSDavid Ahern perf_record__init_features(rec); 394330aa675SStephane Eranian 395d4db3f16SArnaldo Carvalho de Melo if (forks) { 3966ef73ec4SNamhyung Kim err = perf_evlist__prepare_workload(evsel_list, &opts->target, 397f5fc1412SJiri Olsa argv, file->is_pipe, 39855e162eaSNamhyung Kim true); 39935b9d88eSArnaldo Carvalho de Melo if (err < 0) { 40035b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 40135b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 402856e9660SPeter Zijlstra } 403856e9660SPeter Zijlstra } 404856e9660SPeter Zijlstra 4058d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 4068d3eca20SDavid Ahern err = -1; 4078d3eca20SDavid Ahern goto out_delete_session; 4088d3eca20SDavid Ahern } 40986470930SIngo Molnar 410a8bb559bSNamhyung Kim if (!evsel_list->nr_groups) 411a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 412a8bb559bSNamhyung Kim 413712a4b60SArnaldo Carvalho de Melo /* 414d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 415712a4b60SArnaldo Carvalho de Melo */ 416d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 417712a4b60SArnaldo Carvalho de Melo 418f5fc1412SJiri Olsa if (file->is_pipe) { 419f5fc1412SJiri Olsa err = perf_header__write_pipe(file->fd); 420529870e3STom Zanussi if (err < 0) 4218d3eca20SDavid Ahern goto out_delete_session; 422563aecb2SJiri Olsa } else { 423a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 424f5fc1412SJiri Olsa file->fd, false); 425d5eed904SArnaldo Carvalho de Melo if (err < 0) 4268d3eca20SDavid Ahern goto out_delete_session; 427d5eed904SArnaldo Carvalho de Melo } 4287c6a1c65SPeter Zijlstra 429d3665498SDavid Ahern if (!rec->no_buildid 430e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 431d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 432e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 4338d3eca20SDavid Ahern err = -1; 4348d3eca20SDavid Ahern goto out_delete_session; 435e20960c0SRobert Richter } 436e20960c0SRobert Richter 437f5fc1412SJiri Olsa rec->post_processing_offset = lseek(file->fd, 0, SEEK_CUR); 4386122e4e4SArnaldo Carvalho de Melo 43934ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 440743eb868SArnaldo Carvalho de Melo 441f5fc1412SJiri Olsa if (file->is_pipe) { 44245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 443a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 4442c46dbb5STom Zanussi if (err < 0) { 4452c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 4468d3eca20SDavid Ahern goto out_delete_session; 4472c46dbb5STom Zanussi } 448cd19a035STom Zanussi 449361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 45063e0c771STom Zanussi /* 45163e0c771STom Zanussi * FIXME err <= 0 here actually means that 45263e0c771STom Zanussi * there were no tracepoints so its not really 45363e0c771STom Zanussi * an error, just that we don't need to 45463e0c771STom Zanussi * synthesize anything. We really have to 45563e0c771STom Zanussi * return this more properly and also 45663e0c771STom Zanussi * propagate errors that now are calling die() 45763e0c771STom Zanussi */ 458f5fc1412SJiri Olsa err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, 459743eb868SArnaldo Carvalho de Melo process_synthesized_event); 46063e0c771STom Zanussi if (err <= 0) { 46163e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 4628d3eca20SDavid Ahern goto out_delete_session; 46363e0c771STom Zanussi } 464d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 4652c46dbb5STom Zanussi } 46663e0c771STom Zanussi } 4672c46dbb5STom Zanussi 46845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 469743eb868SArnaldo Carvalho de Melo machine, "_text"); 47070162138SArnaldo Carvalho de Melo if (err < 0) 47145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 472743eb868SArnaldo Carvalho de Melo machine, "_stext"); 473c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 474c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 475c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 476c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 47756b03f3cSArnaldo Carvalho de Melo 47845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 479743eb868SArnaldo Carvalho de Melo machine); 480c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 481c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 482c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 483c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 484c1a3a4b9SArnaldo Carvalho de Melo 4857e383de4SArnaldo Carvalho de Melo if (perf_guest) { 486876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 4877e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 4887e383de4SArnaldo Carvalho de Melo } 489b7cece76SArnaldo Carvalho de Melo 490e4dd45feSJiri Olsa if (perf_target__has_task(&opts->target)) 4918d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 4928115d60cSArnaldo Carvalho de Melo process_synthesized_event, 493743eb868SArnaldo Carvalho de Melo machine); 494e4dd45feSJiri Olsa else if (perf_target__has_cpu(&opts->target)) 4958d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 496743eb868SArnaldo Carvalho de Melo machine); 497e4dd45feSJiri Olsa else /* command specified */ 498e4dd45feSJiri Olsa err = 0; 4997c6a1c65SPeter Zijlstra 5008d3eca20SDavid Ahern if (err != 0) 5018d3eca20SDavid Ahern goto out_delete_session; 5028d3eca20SDavid Ahern 503d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 50486470930SIngo Molnar struct sched_param param; 50586470930SIngo Molnar 506d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 50786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5086beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 5098d3eca20SDavid Ahern err = -1; 5108d3eca20SDavid Ahern goto out_delete_session; 51186470930SIngo Molnar } 51286470930SIngo Molnar } 51386470930SIngo Molnar 514774cb499SJiri Olsa /* 515774cb499SJiri Olsa * When perf is starting the traced process, all the events 516774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 517774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 518774cb499SJiri Olsa */ 519774cb499SJiri Olsa if (!perf_target__none(&opts->target)) 520764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 521764e16a3SDavid Ahern 522856e9660SPeter Zijlstra /* 523856e9660SPeter Zijlstra * Let the child rip 524856e9660SPeter Zijlstra */ 525d4db3f16SArnaldo Carvalho de Melo if (forks) 52635b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 527856e9660SPeter Zijlstra 528649c48a9SPeter Zijlstra for (;;) { 529d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 53086470930SIngo Molnar 5318d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 5328d3eca20SDavid Ahern err = -1; 5338d3eca20SDavid Ahern goto out_delete_session; 5348d3eca20SDavid Ahern } 53586470930SIngo Molnar 536d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 537649c48a9SPeter Zijlstra if (done) 538649c48a9SPeter Zijlstra break; 5395c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 5408b412664SPeter Zijlstra waking++; 5418b412664SPeter Zijlstra } 5428b412664SPeter Zijlstra 543774cb499SJiri Olsa /* 544774cb499SJiri Olsa * When perf is starting the traced process, at the end events 545774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 546774cb499SJiri Olsa * disable events in this case. 547774cb499SJiri Olsa */ 5482711926aSJiri Olsa if (done && !disabled && !perf_target__none(&opts->target)) { 5494152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 5502711926aSJiri Olsa disabled = true; 5512711926aSJiri Olsa } 5528b412664SPeter Zijlstra } 5538b412664SPeter Zijlstra 55418483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 555b44308f5SArnaldo Carvalho de Melo return 0; 556b44308f5SArnaldo Carvalho de Melo 5578b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 55886470930SIngo Molnar 55986470930SIngo Molnar /* 56086470930SIngo Molnar * Approximate RIP event size: 24 bytes. 56186470930SIngo Molnar */ 56286470930SIngo Molnar fprintf(stderr, 5639486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 564d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 5656a4d98d7SJiri Olsa file->path, 566d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 56786470930SIngo Molnar 56886470930SIngo Molnar return 0; 56939d17dacSArnaldo Carvalho de Melo 57039d17dacSArnaldo Carvalho de Melo out_delete_session: 57139d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 57239d17dacSArnaldo Carvalho de Melo return err; 57386470930SIngo Molnar } 57486470930SIngo Molnar 575bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 576bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 577bdfebd84SRoberto Agostino Vitillo 578bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 579bdfebd84SRoberto Agostino Vitillo 580bdfebd84SRoberto Agostino Vitillo struct branch_mode { 581bdfebd84SRoberto Agostino Vitillo const char *name; 582bdfebd84SRoberto Agostino Vitillo int mode; 583bdfebd84SRoberto Agostino Vitillo }; 584bdfebd84SRoberto Agostino Vitillo 585bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 586bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 587bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 588bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 589bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 590bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 591bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 592bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 5930126d493SAndi Kleen BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 5940126d493SAndi Kleen BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 5950126d493SAndi Kleen BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 596bdfebd84SRoberto Agostino Vitillo BRANCH_END 597bdfebd84SRoberto Agostino Vitillo }; 598bdfebd84SRoberto Agostino Vitillo 599bdfebd84SRoberto Agostino Vitillo static int 600a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 601bdfebd84SRoberto Agostino Vitillo { 602bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 603bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 604bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 605bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 606bdfebd84SRoberto Agostino Vitillo 607bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 608bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 609a5aabdacSStephane Eranian char *s, *os = NULL, *p; 610bdfebd84SRoberto Agostino Vitillo int ret = -1; 611bdfebd84SRoberto Agostino Vitillo 612a5aabdacSStephane Eranian if (unset) 613a5aabdacSStephane Eranian return 0; 614bdfebd84SRoberto Agostino Vitillo 615a5aabdacSStephane Eranian /* 616a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 617a5aabdacSStephane Eranian */ 618a5aabdacSStephane Eranian if (*mode) 619a5aabdacSStephane Eranian return -1; 620a5aabdacSStephane Eranian 621a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 622a5aabdacSStephane Eranian if (str) { 623bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 624bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 625bdfebd84SRoberto Agostino Vitillo if (!s) 626bdfebd84SRoberto Agostino Vitillo return -1; 627bdfebd84SRoberto Agostino Vitillo 628bdfebd84SRoberto Agostino Vitillo for (;;) { 629bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 630bdfebd84SRoberto Agostino Vitillo if (p) 631bdfebd84SRoberto Agostino Vitillo *p = '\0'; 632bdfebd84SRoberto Agostino Vitillo 633bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 634bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 635bdfebd84SRoberto Agostino Vitillo break; 636bdfebd84SRoberto Agostino Vitillo } 637a5aabdacSStephane Eranian if (!br->name) { 638a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 639a5aabdacSStephane Eranian " check man page\n", s); 640bdfebd84SRoberto Agostino Vitillo goto error; 641a5aabdacSStephane Eranian } 642bdfebd84SRoberto Agostino Vitillo 643bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 644bdfebd84SRoberto Agostino Vitillo 645bdfebd84SRoberto Agostino Vitillo if (!p) 646bdfebd84SRoberto Agostino Vitillo break; 647bdfebd84SRoberto Agostino Vitillo 648bdfebd84SRoberto Agostino Vitillo s = p + 1; 649bdfebd84SRoberto Agostino Vitillo } 650a5aabdacSStephane Eranian } 651bdfebd84SRoberto Agostino Vitillo ret = 0; 652bdfebd84SRoberto Agostino Vitillo 653a5aabdacSStephane Eranian /* default to any branch */ 654bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 655a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 656bdfebd84SRoberto Agostino Vitillo } 657bdfebd84SRoberto Agostino Vitillo error: 658bdfebd84SRoberto Agostino Vitillo free(os); 659bdfebd84SRoberto Agostino Vitillo return ret; 660bdfebd84SRoberto Agostino Vitillo } 661bdfebd84SRoberto Agostino Vitillo 66289fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 66326d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 66426d33022SJiri Olsa { 66526d33022SJiri Olsa char *endptr; 66626d33022SJiri Olsa unsigned long size; 66726d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 66826d33022SJiri Olsa 66926d33022SJiri Olsa size = strtoul(str, &endptr, 0); 67026d33022SJiri Olsa 67126d33022SJiri Olsa do { 67226d33022SJiri Olsa if (*endptr) 67326d33022SJiri Olsa break; 67426d33022SJiri Olsa 67526d33022SJiri Olsa size = round_up(size, sizeof(u64)); 67626d33022SJiri Olsa if (!size || size > max_size) 67726d33022SJiri Olsa break; 67826d33022SJiri Olsa 67926d33022SJiri Olsa *_size = size; 68026d33022SJiri Olsa return 0; 68126d33022SJiri Olsa 68226d33022SJiri Olsa } while (0); 68326d33022SJiri Olsa 68426d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 68526d33022SJiri Olsa max_size, str); 68626d33022SJiri Olsa return -1; 68726d33022SJiri Olsa } 68889fe808aSIngo Molnar #endif /* HAVE_LIBUNWIND_SUPPORT */ 68926d33022SJiri Olsa 69009b0fd45SJiri Olsa int record_parse_callchain(const char *arg, struct perf_record_opts *opts) 69126d33022SJiri Olsa { 69226d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 69326d33022SJiri Olsa char *buf; 69426d33022SJiri Olsa int ret = -1; 69526d33022SJiri Olsa 69626d33022SJiri Olsa /* We need buffer that we know we can write to. */ 69726d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 69826d33022SJiri Olsa if (!buf) 69926d33022SJiri Olsa return -ENOMEM; 70026d33022SJiri Olsa 70126d33022SJiri Olsa strcpy(buf, arg); 70226d33022SJiri Olsa 70326d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 70426d33022SJiri Olsa name = tok ? : (char *)buf; 70526d33022SJiri Olsa 70626d33022SJiri Olsa do { 70726d33022SJiri Olsa /* Framepointer style */ 70826d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 70926d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 710c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_FP; 71126d33022SJiri Olsa ret = 0; 71226d33022SJiri Olsa } else 71326d33022SJiri Olsa pr_err("callchain: No more arguments " 71426d33022SJiri Olsa "needed for -g fp\n"); 71526d33022SJiri Olsa break; 71626d33022SJiri Olsa 71789fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 71826d33022SJiri Olsa /* Dwarf style */ 71926d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 72061eaa3beSArnaldo Carvalho de Melo const unsigned long default_stack_dump_size = 8192; 72161eaa3beSArnaldo Carvalho de Melo 72226d33022SJiri Olsa ret = 0; 723c5ff78c3SArnaldo Carvalho de Melo opts->call_graph = CALLCHAIN_DWARF; 724c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = default_stack_dump_size; 72526d33022SJiri Olsa 72626d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 72726d33022SJiri Olsa if (tok) { 72826d33022SJiri Olsa unsigned long size = 0; 72926d33022SJiri Olsa 73026d33022SJiri Olsa ret = get_stack_size(tok, &size); 731c5ff78c3SArnaldo Carvalho de Melo opts->stack_dump_size = size; 73226d33022SJiri Olsa } 73389fe808aSIngo Molnar #endif /* HAVE_LIBUNWIND_SUPPORT */ 73426d33022SJiri Olsa } else { 73509b0fd45SJiri Olsa pr_err("callchain: Unknown --call-graph option " 73626d33022SJiri Olsa "value: %s\n", arg); 73726d33022SJiri Olsa break; 73826d33022SJiri Olsa } 73926d33022SJiri Olsa 74026d33022SJiri Olsa } while (0); 74126d33022SJiri Olsa 74226d33022SJiri Olsa free(buf); 74309b0fd45SJiri Olsa return ret; 74409b0fd45SJiri Olsa } 74526d33022SJiri Olsa 74609b0fd45SJiri Olsa static void callchain_debug(struct perf_record_opts *opts) 74709b0fd45SJiri Olsa { 748c5ff78c3SArnaldo Carvalho de Melo pr_debug("callchain: type %d\n", opts->call_graph); 74926d33022SJiri Olsa 75009b0fd45SJiri Olsa if (opts->call_graph == CALLCHAIN_DWARF) 75109b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 75209b0fd45SJiri Olsa opts->stack_dump_size); 75309b0fd45SJiri Olsa } 75409b0fd45SJiri Olsa 75509b0fd45SJiri Olsa int record_parse_callchain_opt(const struct option *opt, 75609b0fd45SJiri Olsa const char *arg, 75709b0fd45SJiri Olsa int unset) 75809b0fd45SJiri Olsa { 75909b0fd45SJiri Olsa struct perf_record_opts *opts = opt->value; 76009b0fd45SJiri Olsa int ret; 76109b0fd45SJiri Olsa 76209b0fd45SJiri Olsa /* --no-call-graph */ 76309b0fd45SJiri Olsa if (unset) { 76409b0fd45SJiri Olsa opts->call_graph = CALLCHAIN_NONE; 76509b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 76609b0fd45SJiri Olsa return 0; 76709b0fd45SJiri Olsa } 76809b0fd45SJiri Olsa 76909b0fd45SJiri Olsa ret = record_parse_callchain(arg, opts); 77009b0fd45SJiri Olsa if (!ret) 77109b0fd45SJiri Olsa callchain_debug(opts); 77209b0fd45SJiri Olsa 77326d33022SJiri Olsa return ret; 77426d33022SJiri Olsa } 77526d33022SJiri Olsa 77609b0fd45SJiri Olsa int record_callchain_opt(const struct option *opt, 77709b0fd45SJiri Olsa const char *arg __maybe_unused, 77809b0fd45SJiri Olsa int unset __maybe_unused) 77909b0fd45SJiri Olsa { 78009b0fd45SJiri Olsa struct perf_record_opts *opts = opt->value; 78109b0fd45SJiri Olsa 78209b0fd45SJiri Olsa if (opts->call_graph == CALLCHAIN_NONE) 78309b0fd45SJiri Olsa opts->call_graph = CALLCHAIN_FP; 78409b0fd45SJiri Olsa 78509b0fd45SJiri Olsa callchain_debug(opts); 78609b0fd45SJiri Olsa return 0; 78709b0fd45SJiri Olsa } 78809b0fd45SJiri Olsa 78986470930SIngo Molnar static const char * const record_usage[] = { 79086470930SIngo Molnar "perf record [<options>] [<command>]", 79186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 79286470930SIngo Molnar NULL 79386470930SIngo Molnar }; 79486470930SIngo Molnar 795d20deb64SArnaldo Carvalho de Melo /* 796d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 797d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 798d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 799d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 800d20deb64SArnaldo Carvalho de Melo * 801d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 802d20deb64SArnaldo Carvalho de Melo * 803d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 804d20deb64SArnaldo Carvalho de Melo */ 805d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 806d20deb64SArnaldo Carvalho de Melo .opts = { 807d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 808d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 809d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 810447a6013SArnaldo Carvalho de Melo .freq = 4000, 811d1cb9fceSNamhyung Kim .target = { 812d1cb9fceSNamhyung Kim .uses_mmap = true, 813d1cb9fceSNamhyung Kim }, 814d20deb64SArnaldo Carvalho de Melo }, 815d20deb64SArnaldo Carvalho de Melo }; 8167865e817SFrederic Weisbecker 81709b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 81861eaa3beSArnaldo Carvalho de Melo 81989fe808aSIngo Molnar #ifdef HAVE_LIBUNWIND_SUPPORT 82009b0fd45SJiri Olsa const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 82161eaa3beSArnaldo Carvalho de Melo #else 82209b0fd45SJiri Olsa const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 82361eaa3beSArnaldo Carvalho de Melo #endif 82461eaa3beSArnaldo Carvalho de Melo 825d20deb64SArnaldo Carvalho de Melo /* 826d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 827d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 828d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 829d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 830d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 831d20deb64SArnaldo Carvalho de Melo */ 832bca647aaSTom Zanussi const struct option record_options[] = { 833d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 83486470930SIngo Molnar "event selector. use 'perf list' to list available events", 835f120f9d5SJiri Olsa parse_events_option), 836d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 837c171b552SLi Zefan "event filter", parse_filter), 838bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 839d6d901c2SZhang, Yanmin "record events on existing process id"), 840bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 841d6d901c2SZhang, Yanmin "record events on existing thread id"), 842d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 84386470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 844d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 845acac03faSKirill Smelkov "collect data without buffering"), 846d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 847daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 848bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 84986470930SIngo Molnar "system-wide collection from all CPUs"), 850bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 851c45c6ea2SStephane Eranian "list of cpus to monitor"), 852d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 853f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 85486470930SIngo Molnar "output file name"), 855d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 8562e6cdf99SStephane Eranian "child tasks do not inherit counters"), 857d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 858994a1f78SJiri Olsa OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 859994a1f78SJiri Olsa "number of mmap data pages", 860994a1f78SJiri Olsa perf_evlist__parse_mmap_pages), 861d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 86243bece79SLin Ming "put the counters into a counter group"), 86309b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 86409b0fd45SJiri Olsa NULL, "enables call-graph recording" , 86509b0fd45SJiri Olsa &record_callchain_opt), 86609b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 86775d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 86809b0fd45SJiri Olsa &record_parse_callchain_opt), 869c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 8703da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 871b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 872d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 873649c48a9SPeter Zijlstra "per thread counts"), 874d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 8754bba828dSAnton Blanchard "Sample addresses"), 876d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 8773e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 878d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 879649c48a9SPeter Zijlstra "don't sample"), 880d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 881a1ac1d3cSStephane Eranian "do not update the buildid cache"), 882d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 883baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 884d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 885023695d9SStephane Eranian "monitor event in cgroup name only", 886023695d9SStephane Eranian parse_cgroups), 887bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 888bea03405SNamhyung Kim "user to profile"), 889a5aabdacSStephane Eranian 890a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 891a5aabdacSStephane Eranian "branch any", "sample any taken branches", 892a5aabdacSStephane Eranian parse_branch_stack), 893a5aabdacSStephane Eranian 894a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 895a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 896bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 89705484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 89805484298SAndi Kleen "sample by weight (on special events only)"), 899475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 900475eeab9SAndi Kleen "sample transaction flags (special events only)"), 90186470930SIngo Molnar OPT_END() 90286470930SIngo Molnar }; 90386470930SIngo Molnar 9041d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 90586470930SIngo Molnar { 90669aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 907d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 908d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 90916ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 91086470930SIngo Molnar 911334fe7a3SNamhyung Kim evsel_list = perf_evlist__new(); 912361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 913361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 914361c99a6SArnaldo Carvalho de Melo 915d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 916d20deb64SArnaldo Carvalho de Melo 917bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 918a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 919d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 920bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 92186470930SIngo Molnar 922bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 9233780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 924023695d9SStephane Eranian " system-wide mode\n"); 925023695d9SStephane Eranian usage_with_options(record_usage, record_options); 926023695d9SStephane Eranian } 927023695d9SStephane Eranian 928655000e7SArnaldo Carvalho de Melo symbol__init(); 929baa2f6ceSArnaldo Carvalho de Melo 930ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 931646aaea6SArnaldo Carvalho de Melo pr_warning( 932646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 933ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 934646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 935646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 936646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 937646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 938646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 939ec80fde7SArnaldo Carvalho de Melo 940d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 941a1ac1d3cSStephane Eranian disable_buildid_cache(); 942655000e7SArnaldo Carvalho de Melo 943361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 944361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 94569aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 94669aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 947bbd36e5eSPeter Zijlstra } 94886470930SIngo Molnar 94916ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 95016ad2ffbSNamhyung Kim if (err) { 95116ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 95216ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 95316ad2ffbSNamhyung Kim } 9544bd0f2d2SNamhyung Kim 95516ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 95616ad2ffbSNamhyung Kim if (err) { 95716ad2ffbSNamhyung Kim int saved_errno = errno; 95816ad2ffbSNamhyung Kim 95916ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 9603780f488SNamhyung Kim ui__error("%s", errbuf); 96116ad2ffbSNamhyung Kim 96216ad2ffbSNamhyung Kim err = -saved_errno; 9638fa60e1fSNamhyung Kim goto out_symbol_exit; 96416ad2ffbSNamhyung Kim } 9650d37aa34SArnaldo Carvalho de Melo 96616ad2ffbSNamhyung Kim err = -ENOMEM; 967b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 968dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 96969aad6f1SArnaldo Carvalho de Melo 970714647bdSJiri Olsa if (perf_record_opts__config(&rec->opts)) { 97139d17dacSArnaldo Carvalho de Melo err = -EINVAL; 9725c581041SArnaldo Carvalho de Melo goto out_free_fd; 9737e4ff9e3SMike Galbraith } 9747e4ff9e3SMike Galbraith 975d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 9768fa60e1fSNamhyung Kim 9778fa60e1fSNamhyung Kim perf_evlist__munmap(evsel_list); 9788fa60e1fSNamhyung Kim perf_evlist__close(evsel_list); 97939d17dacSArnaldo Carvalho de Melo out_free_fd: 9807e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 981d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 982d65a458bSArnaldo Carvalho de Melo symbol__exit(); 98339d17dacSArnaldo Carvalho de Melo return err; 98486470930SIngo Molnar } 985