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 178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 197c6a1c65SPeter Zijlstra #include "util/header.h" 2066e274f3SFrederic Weisbecker #include "util/event.h" 21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 238f28827aSFrederic Weisbecker #include "util/debug.h" 2494c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 27a12b51c4SPaul Mackerras #include "util/cpumap.h" 28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 29f5fc1412SJiri Olsa #include "util/data.h" 307c6a1c65SPeter Zijlstra 3186470930SIngo Molnar #include <unistd.h> 3286470930SIngo Molnar #include <sched.h> 33a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3486470930SIngo Molnar 3578da39faSBernhard Rosenkraenzer 368c6f45a7SArnaldo Carvalho de Melo struct record { 3745694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 38b4006796SArnaldo Carvalho de Melo struct record_opts opts; 39d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 40f5fc1412SJiri Olsa struct perf_data_file file; 41d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 42d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 43d20deb64SArnaldo Carvalho de Melo const char *progname; 44d20deb64SArnaldo Carvalho de Melo int realtime_prio; 45d20deb64SArnaldo Carvalho de Melo bool no_buildid; 46d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 47d20deb64SArnaldo Carvalho de Melo long samples; 480f82ebc4SArnaldo Carvalho de Melo }; 4986470930SIngo Molnar 508c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 51f5970550SPeter Zijlstra { 52cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 534f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 548d3eca20SDavid Ahern return -1; 558d3eca20SDavid Ahern } 56f5970550SPeter Zijlstra 57cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 588d3eca20SDavid Ahern return 0; 59f5970550SPeter Zijlstra } 60f5970550SPeter Zijlstra 6145694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 62d20deb64SArnaldo Carvalho de Melo union perf_event *event, 631d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 641d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 65234fbbf5SArnaldo Carvalho de Melo { 668c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 678c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 68234fbbf5SArnaldo Carvalho de Melo } 69234fbbf5SArnaldo Carvalho de Melo 70e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7186470930SIngo Molnar { 72e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 73744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 7486470930SIngo Molnar unsigned int old = md->prev; 75918512b4SJiri Olsa unsigned char *data = md->base + page_size; 7686470930SIngo Molnar unsigned long size; 7786470930SIngo Molnar void *buf; 788d3eca20SDavid Ahern int rc = 0; 7986470930SIngo Molnar 80dc82009aSArnaldo Carvalho de Melo if (old == head) 818d3eca20SDavid Ahern return 0; 8286470930SIngo Molnar 83d20deb64SArnaldo Carvalho de Melo rec->samples++; 8486470930SIngo Molnar 8586470930SIngo Molnar size = head - old; 8686470930SIngo Molnar 8786470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 8886470930SIngo Molnar buf = &data[old & md->mask]; 8986470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9086470930SIngo Molnar old += size; 9186470930SIngo Molnar 928c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 938d3eca20SDavid Ahern rc = -1; 948d3eca20SDavid Ahern goto out; 958d3eca20SDavid Ahern } 9686470930SIngo Molnar } 9786470930SIngo Molnar 9886470930SIngo Molnar buf = &data[old & md->mask]; 9986470930SIngo Molnar size = head - old; 10086470930SIngo Molnar old += size; 10186470930SIngo Molnar 1028c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1038d3eca20SDavid Ahern rc = -1; 1048d3eca20SDavid Ahern goto out; 1058d3eca20SDavid Ahern } 10686470930SIngo Molnar 10786470930SIngo Molnar md->prev = old; 108e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1098d3eca20SDavid Ahern out: 1108d3eca20SDavid Ahern return rc; 11186470930SIngo Molnar } 11286470930SIngo Molnar 11386470930SIngo Molnar static volatile int done = 0; 114f7b7c26eSPeter Zijlstra static volatile int signr = -1; 11533e49ea7SAndi Kleen static volatile int child_finished = 0; 11686470930SIngo Molnar 11786470930SIngo Molnar static void sig_handler(int sig) 11886470930SIngo Molnar { 11933e49ea7SAndi Kleen if (sig == SIGCHLD) 12033e49ea7SAndi Kleen child_finished = 1; 12145604710SNamhyung Kim else 12245604710SNamhyung Kim signr = sig; 12333e49ea7SAndi Kleen 12486470930SIngo Molnar done = 1; 125f7b7c26eSPeter Zijlstra } 126f7b7c26eSPeter Zijlstra 12745604710SNamhyung Kim static void record__sig_exit(void) 128f7b7c26eSPeter Zijlstra { 12945604710SNamhyung Kim if (signr == -1) 130f7b7c26eSPeter Zijlstra return; 131f7b7c26eSPeter Zijlstra 132f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 13345604710SNamhyung Kim raise(signr); 13486470930SIngo Molnar } 13586470930SIngo Molnar 1368c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 137dd7927f4SArnaldo Carvalho de Melo { 13856e52e85SArnaldo Carvalho de Melo char msg[512]; 1396a4bb04cSJiri Olsa struct perf_evsel *pos; 140d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 141d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 142b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 1438d3eca20SDavid Ahern int rc = 0; 144dd7927f4SArnaldo Carvalho de Melo 145f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 146cac21425SJiri Olsa 1470050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 1483da297a6SIngo Molnar try_again: 1496a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 15056e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 1513da297a6SIngo Molnar if (verbose) 152c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 1533da297a6SIngo Molnar goto try_again; 1543da297a6SIngo Molnar } 155ca6a4258SDavid Ahern 15656e52e85SArnaldo Carvalho de Melo rc = -errno; 15756e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 15856e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 15956e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 1608d3eca20SDavid Ahern goto out; 1617c6a1c65SPeter Zijlstra } 1627c6a1c65SPeter Zijlstra } 1637c6a1c65SPeter Zijlstra 1641491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 1650a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 16635550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 1678d3eca20SDavid Ahern rc = -1; 1688d3eca20SDavid Ahern goto out; 1690a102479SFrederic Weisbecker } 1700a102479SFrederic Weisbecker 17118e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 1728d3eca20SDavid Ahern if (errno == EPERM) { 1738d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 17418e60939SNelson Elhage "Consider increasing " 17518e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 17618e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 17753653d70SAdrian Hunter "(current value: %u)\n", opts->mmap_pages); 1788d3eca20SDavid Ahern rc = -errno; 1798d3eca20SDavid Ahern } else { 18035550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 18135550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 1828d3eca20SDavid Ahern rc = -errno; 1838d3eca20SDavid Ahern } 1848d3eca20SDavid Ahern goto out; 18518e60939SNelson Elhage } 1860a27d7f9SArnaldo Carvalho de Melo 187a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 1887b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 1898d3eca20SDavid Ahern out: 1908d3eca20SDavid Ahern return rc; 191a91e5431SArnaldo Carvalho de Melo } 192a91e5431SArnaldo Carvalho de Melo 193e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 194e3d59112SNamhyung Kim union perf_event *event, 195e3d59112SNamhyung Kim struct perf_sample *sample, 196e3d59112SNamhyung Kim struct perf_evsel *evsel, 197e3d59112SNamhyung Kim struct machine *machine) 198e3d59112SNamhyung Kim { 199e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 200e3d59112SNamhyung Kim 201e3d59112SNamhyung Kim rec->samples++; 202e3d59112SNamhyung Kim 203e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 204e3d59112SNamhyung Kim } 205e3d59112SNamhyung Kim 2068c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 2076122e4e4SArnaldo Carvalho de Melo { 208f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 209f5fc1412SJiri Olsa struct perf_session *session = rec->session; 2106122e4e4SArnaldo Carvalho de Melo 21142aa276fSNamhyung Kim u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 2129f591fd7SArnaldo Carvalho de Melo if (size == 0) 2139f591fd7SArnaldo Carvalho de Melo return 0; 2149f591fd7SArnaldo Carvalho de Melo 2154ac30cf7SNamhyung Kim file->size = size; 2164ac30cf7SNamhyung Kim 21700dc8657SNamhyung Kim /* 21800dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 21900dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 22000dc8657SNamhyung Kim * we prefer the vmlinux path like 22100dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 22200dc8657SNamhyung Kim * 22300dc8657SNamhyung Kim * rather than build-id path (in debug directory). 22400dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 22500dc8657SNamhyung Kim */ 22600dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 22700dc8657SNamhyung Kim 228*b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 2296122e4e4SArnaldo Carvalho de Melo } 2306122e4e4SArnaldo Carvalho de Melo 2318115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 232a1645ce1SZhang, Yanmin { 233a1645ce1SZhang, Yanmin int err; 23445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 235a1645ce1SZhang, Yanmin /* 236a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 237a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 238a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 239a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 240a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 241a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 242a1645ce1SZhang, Yanmin */ 24345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 244743eb868SArnaldo Carvalho de Melo machine); 245a1645ce1SZhang, Yanmin if (err < 0) 246a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 24723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 248a1645ce1SZhang, Yanmin 249a1645ce1SZhang, Yanmin /* 250a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 251a1645ce1SZhang, Yanmin * have no _text sometimes. 252a1645ce1SZhang, Yanmin */ 25345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 2540ae617beSAdrian Hunter machine); 255a1645ce1SZhang, Yanmin if (err < 0) 256a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 25723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 258a1645ce1SZhang, Yanmin } 259a1645ce1SZhang, Yanmin 26098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 26198402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 26298402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 26398402807SFrederic Weisbecker }; 26498402807SFrederic Weisbecker 2658c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 26698402807SFrederic Weisbecker { 267dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 2680e2e63ddSPeter Zijlstra int i; 2698d3eca20SDavid Ahern int rc = 0; 27098402807SFrederic Weisbecker 271d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2728d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 273e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 2748d3eca20SDavid Ahern rc = -1; 2758d3eca20SDavid Ahern goto out; 2768d3eca20SDavid Ahern } 2778d3eca20SDavid Ahern } 27898402807SFrederic Weisbecker } 27998402807SFrederic Weisbecker 280dcabb507SJiri Olsa /* 281dcabb507SJiri Olsa * Mark the round finished in case we wrote 282dcabb507SJiri Olsa * at least one event. 283dcabb507SJiri Olsa */ 284dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 2858c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 2868d3eca20SDavid Ahern 2878d3eca20SDavid Ahern out: 2888d3eca20SDavid Ahern return rc; 28998402807SFrederic Weisbecker } 29098402807SFrederic Weisbecker 2918c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 29257706abcSDavid Ahern { 29357706abcSDavid Ahern struct perf_session *session = rec->session; 29457706abcSDavid Ahern int feat; 29557706abcSDavid Ahern 29657706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 29757706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 29857706abcSDavid Ahern 29957706abcSDavid Ahern if (rec->no_buildid) 30057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 30157706abcSDavid Ahern 3023e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 30357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 30457706abcSDavid Ahern 30557706abcSDavid Ahern if (!rec->opts.branch_stack) 30657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 30757706abcSDavid Ahern } 30857706abcSDavid Ahern 309f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 310f33cbe72SArnaldo Carvalho de Melo 311f33cbe72SArnaldo Carvalho de Melo /* 312f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 313f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 314f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 315f33cbe72SArnaldo Carvalho de Melo */ 31645604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 31745604710SNamhyung Kim siginfo_t *info, 318f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 319f33cbe72SArnaldo Carvalho de Melo { 320f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 321f33cbe72SArnaldo Carvalho de Melo done = 1; 322f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 323f33cbe72SArnaldo Carvalho de Melo } 324f33cbe72SArnaldo Carvalho de Melo 3258c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 32686470930SIngo Molnar { 32757706abcSDavid Ahern int err; 32845604710SNamhyung Kim int status = 0; 3298b412664SPeter Zijlstra unsigned long waking = 0; 33046be604bSZhang, Yanmin const bool forks = argc > 0; 33123346f21SArnaldo Carvalho de Melo struct machine *machine; 33245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 333b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 334f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 335d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 3366dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 33742aa276fSNamhyung Kim int fd; 33886470930SIngo Molnar 339d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 34033e49ea7SAndi Kleen 34145604710SNamhyung Kim atexit(record__sig_exit); 342f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 343f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 344804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 345f5970550SPeter Zijlstra 346*b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 34794c744b6SArnaldo Carvalho de Melo if (session == NULL) { 348ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 349a9a70bbcSArnaldo Carvalho de Melo return -1; 350a9a70bbcSArnaldo Carvalho de Melo } 351a9a70bbcSArnaldo Carvalho de Melo 35242aa276fSNamhyung Kim fd = perf_data_file__fd(file); 353d20deb64SArnaldo Carvalho de Melo rec->session = session; 354d20deb64SArnaldo Carvalho de Melo 3558c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 356330aa675SStephane Eranian 357d4db3f16SArnaldo Carvalho de Melo if (forks) { 3583e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 359f5fc1412SJiri Olsa argv, file->is_pipe, 360735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 36135b9d88eSArnaldo Carvalho de Melo if (err < 0) { 36235b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 36345604710SNamhyung Kim status = err; 36435b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 365856e9660SPeter Zijlstra } 366856e9660SPeter Zijlstra } 367856e9660SPeter Zijlstra 3688c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 3698d3eca20SDavid Ahern err = -1; 37045604710SNamhyung Kim goto out_child; 3718d3eca20SDavid Ahern } 37286470930SIngo Molnar 3733e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 374a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 375a8bb559bSNamhyung Kim 376f5fc1412SJiri Olsa if (file->is_pipe) { 37742aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 378529870e3STom Zanussi if (err < 0) 37945604710SNamhyung Kim goto out_child; 380563aecb2SJiri Olsa } else { 38142aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 382d5eed904SArnaldo Carvalho de Melo if (err < 0) 38345604710SNamhyung Kim goto out_child; 384d5eed904SArnaldo Carvalho de Melo } 3857c6a1c65SPeter Zijlstra 386d3665498SDavid Ahern if (!rec->no_buildid 387e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 388d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 389e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 3908d3eca20SDavid Ahern err = -1; 39145604710SNamhyung Kim goto out_child; 392e20960c0SRobert Richter } 393e20960c0SRobert Richter 39434ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 395743eb868SArnaldo Carvalho de Melo 396f5fc1412SJiri Olsa if (file->is_pipe) { 39745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 398a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 3992c46dbb5STom Zanussi if (err < 0) { 4002c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 40145604710SNamhyung Kim goto out_child; 4022c46dbb5STom Zanussi } 403cd19a035STom Zanussi 4043e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 40563e0c771STom Zanussi /* 40663e0c771STom Zanussi * FIXME err <= 0 here actually means that 40763e0c771STom Zanussi * there were no tracepoints so its not really 40863e0c771STom Zanussi * an error, just that we don't need to 40963e0c771STom Zanussi * synthesize anything. We really have to 41063e0c771STom Zanussi * return this more properly and also 41163e0c771STom Zanussi * propagate errors that now are calling die() 41263e0c771STom Zanussi */ 41342aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 414743eb868SArnaldo Carvalho de Melo process_synthesized_event); 41563e0c771STom Zanussi if (err <= 0) { 41663e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 41745604710SNamhyung Kim goto out_child; 41863e0c771STom Zanussi } 419f34b9001SDavid Ahern rec->bytes_written += err; 4202c46dbb5STom Zanussi } 42163e0c771STom Zanussi } 4222c46dbb5STom Zanussi 42345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4240ae617beSAdrian Hunter machine); 425c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 426c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 427c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 428c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 42956b03f3cSArnaldo Carvalho de Melo 43045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 431743eb868SArnaldo Carvalho de Melo machine); 432c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 433c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 434c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 435c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 436c1a3a4b9SArnaldo Carvalho de Melo 4377e383de4SArnaldo Carvalho de Melo if (perf_guest) { 438876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 4397e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 4407e383de4SArnaldo Carvalho de Melo } 441b7cece76SArnaldo Carvalho de Melo 4423e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 44358d925dcSArnaldo Carvalho de Melo process_synthesized_event, opts->sample_address); 4448d3eca20SDavid Ahern if (err != 0) 44545604710SNamhyung Kim goto out_child; 4468d3eca20SDavid Ahern 447d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 44886470930SIngo Molnar struct sched_param param; 44986470930SIngo Molnar 450d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 45186470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 4526beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 4538d3eca20SDavid Ahern err = -1; 45445604710SNamhyung Kim goto out_child; 45586470930SIngo Molnar } 45686470930SIngo Molnar } 45786470930SIngo Molnar 458774cb499SJiri Olsa /* 459774cb499SJiri Olsa * When perf is starting the traced process, all the events 460774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 461774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 462774cb499SJiri Olsa */ 4636619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 4643e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 465764e16a3SDavid Ahern 466856e9660SPeter Zijlstra /* 467856e9660SPeter Zijlstra * Let the child rip 468856e9660SPeter Zijlstra */ 469735f7e0bSArnaldo Carvalho de Melo if (forks) 4703e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 471856e9660SPeter Zijlstra 4726619a53eSAndi Kleen if (opts->initial_delay) { 4736619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 4746619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 4756619a53eSAndi Kleen } 4766619a53eSAndi Kleen 477649c48a9SPeter Zijlstra for (;;) { 478d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 47986470930SIngo Molnar 4808c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 4818d3eca20SDavid Ahern err = -1; 48245604710SNamhyung Kim goto out_child; 4838d3eca20SDavid Ahern } 48486470930SIngo Molnar 485d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 4866dcf45efSArnaldo Carvalho de Melo if (done || draining) 487649c48a9SPeter Zijlstra break; 488f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 489a515114fSJiri Olsa /* 490a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 491a515114fSJiri Olsa * number of returned events and interrupt error. 492a515114fSJiri Olsa */ 493a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 49445604710SNamhyung Kim err = 0; 4958b412664SPeter Zijlstra waking++; 4966dcf45efSArnaldo Carvalho de Melo 4976dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 4986dcf45efSArnaldo Carvalho de Melo draining = true; 4998b412664SPeter Zijlstra } 5008b412664SPeter Zijlstra 501774cb499SJiri Olsa /* 502774cb499SJiri Olsa * When perf is starting the traced process, at the end events 503774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 504774cb499SJiri Olsa * disable events in this case. 505774cb499SJiri Olsa */ 506602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 5073e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 5082711926aSJiri Olsa disabled = true; 5092711926aSJiri Olsa } 5108b412664SPeter Zijlstra } 5118b412664SPeter Zijlstra 512f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 51335550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 514f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 515f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 516f33cbe72SArnaldo Carvalho de Melo err = -1; 51745604710SNamhyung Kim goto out_child; 518f33cbe72SArnaldo Carvalho de Melo } 519f33cbe72SArnaldo Carvalho de Melo 520e3d59112SNamhyung Kim if (!quiet) 5218b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 52286470930SIngo Molnar 52345604710SNamhyung Kim out_child: 52445604710SNamhyung Kim if (forks) { 52545604710SNamhyung Kim int exit_status; 52645604710SNamhyung Kim 52745604710SNamhyung Kim if (!child_finished) 52845604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 52945604710SNamhyung Kim 53045604710SNamhyung Kim wait(&exit_status); 53145604710SNamhyung Kim 53245604710SNamhyung Kim if (err < 0) 53345604710SNamhyung Kim status = err; 53445604710SNamhyung Kim else if (WIFEXITED(exit_status)) 53545604710SNamhyung Kim status = WEXITSTATUS(exit_status); 53645604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 53745604710SNamhyung Kim signr = WTERMSIG(exit_status); 53845604710SNamhyung Kim } else 53945604710SNamhyung Kim status = err; 54045604710SNamhyung Kim 541e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 542e3d59112SNamhyung Kim rec->samples = 0; 543e3d59112SNamhyung Kim 54445604710SNamhyung Kim if (!err && !file->is_pipe) { 54545604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 54645604710SNamhyung Kim 54745604710SNamhyung Kim if (!rec->no_buildid) 54845604710SNamhyung Kim process_buildids(rec); 54942aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 55045604710SNamhyung Kim } 55139d17dacSArnaldo Carvalho de Melo 552e3d59112SNamhyung Kim if (!err && !quiet) { 553e3d59112SNamhyung Kim char samples[128]; 554e3d59112SNamhyung Kim 555e3d59112SNamhyung Kim if (rec->samples) 556e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 557e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 558e3d59112SNamhyung Kim else 559e3d59112SNamhyung Kim samples[0] = '\0'; 560e3d59112SNamhyung Kim 561e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 562e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 563e3d59112SNamhyung Kim file->path, samples); 564e3d59112SNamhyung Kim } 565e3d59112SNamhyung Kim 56639d17dacSArnaldo Carvalho de Melo out_delete_session: 56739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 56845604710SNamhyung Kim return status; 56986470930SIngo Molnar } 57086470930SIngo Molnar 571bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 572bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 573bdfebd84SRoberto Agostino Vitillo 574bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 575bdfebd84SRoberto Agostino Vitillo 576bdfebd84SRoberto Agostino Vitillo struct branch_mode { 577bdfebd84SRoberto Agostino Vitillo const char *name; 578bdfebd84SRoberto Agostino Vitillo int mode; 579bdfebd84SRoberto Agostino Vitillo }; 580bdfebd84SRoberto Agostino Vitillo 581bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 582bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 583bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 584bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 585bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 586bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 587bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 588bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 5890126d493SAndi Kleen BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 5900126d493SAndi Kleen BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 5910126d493SAndi Kleen BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 5920fffa5dfSAnshuman Khandual BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 593bdfebd84SRoberto Agostino Vitillo BRANCH_END 594bdfebd84SRoberto Agostino Vitillo }; 595bdfebd84SRoberto Agostino Vitillo 596bdfebd84SRoberto Agostino Vitillo static int 597a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 598bdfebd84SRoberto Agostino Vitillo { 599bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 600bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 601bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 602bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 603bdfebd84SRoberto Agostino Vitillo 604bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 605bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 606a5aabdacSStephane Eranian char *s, *os = NULL, *p; 607bdfebd84SRoberto Agostino Vitillo int ret = -1; 608bdfebd84SRoberto Agostino Vitillo 609a5aabdacSStephane Eranian if (unset) 610a5aabdacSStephane Eranian return 0; 611bdfebd84SRoberto Agostino Vitillo 612a5aabdacSStephane Eranian /* 613a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 614a5aabdacSStephane Eranian */ 615a5aabdacSStephane Eranian if (*mode) 616a5aabdacSStephane Eranian return -1; 617a5aabdacSStephane Eranian 618a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 619a5aabdacSStephane Eranian if (str) { 620bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 621bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 622bdfebd84SRoberto Agostino Vitillo if (!s) 623bdfebd84SRoberto Agostino Vitillo return -1; 624bdfebd84SRoberto Agostino Vitillo 625bdfebd84SRoberto Agostino Vitillo for (;;) { 626bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 627bdfebd84SRoberto Agostino Vitillo if (p) 628bdfebd84SRoberto Agostino Vitillo *p = '\0'; 629bdfebd84SRoberto Agostino Vitillo 630bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 631bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 632bdfebd84SRoberto Agostino Vitillo break; 633bdfebd84SRoberto Agostino Vitillo } 634a5aabdacSStephane Eranian if (!br->name) { 635a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 636a5aabdacSStephane Eranian " check man page\n", s); 637bdfebd84SRoberto Agostino Vitillo goto error; 638a5aabdacSStephane Eranian } 639bdfebd84SRoberto Agostino Vitillo 640bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 641bdfebd84SRoberto Agostino Vitillo 642bdfebd84SRoberto Agostino Vitillo if (!p) 643bdfebd84SRoberto Agostino Vitillo break; 644bdfebd84SRoberto Agostino Vitillo 645bdfebd84SRoberto Agostino Vitillo s = p + 1; 646bdfebd84SRoberto Agostino Vitillo } 647a5aabdacSStephane Eranian } 648bdfebd84SRoberto Agostino Vitillo ret = 0; 649bdfebd84SRoberto Agostino Vitillo 650a5aabdacSStephane Eranian /* default to any branch */ 651bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 652a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 653bdfebd84SRoberto Agostino Vitillo } 654bdfebd84SRoberto Agostino Vitillo error: 655bdfebd84SRoberto Agostino Vitillo free(os); 656bdfebd84SRoberto Agostino Vitillo return ret; 657bdfebd84SRoberto Agostino Vitillo } 658bdfebd84SRoberto Agostino Vitillo 65972a128aaSNamhyung Kim static void callchain_debug(void) 66009b0fd45SJiri Olsa { 661aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 662a601fdffSJiri Olsa 66372a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 66426d33022SJiri Olsa 66572a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 66609b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 66772a128aaSNamhyung Kim callchain_param.dump_size); 66809b0fd45SJiri Olsa } 66909b0fd45SJiri Olsa 67072a128aaSNamhyung Kim int record_parse_callchain_opt(const struct option *opt __maybe_unused, 67109b0fd45SJiri Olsa const char *arg, 67209b0fd45SJiri Olsa int unset) 67309b0fd45SJiri Olsa { 67409b0fd45SJiri Olsa int ret; 67509b0fd45SJiri Olsa 67672a128aaSNamhyung Kim callchain_param.enabled = !unset; 677eb853e80SJiri Olsa 67809b0fd45SJiri Olsa /* --no-call-graph */ 67909b0fd45SJiri Olsa if (unset) { 68072a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 68109b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 68209b0fd45SJiri Olsa return 0; 68309b0fd45SJiri Olsa } 68409b0fd45SJiri Olsa 685f7f084f4SNamhyung Kim ret = parse_callchain_record_opt(arg); 68609b0fd45SJiri Olsa if (!ret) 68772a128aaSNamhyung Kim callchain_debug(); 68809b0fd45SJiri Olsa 68926d33022SJiri Olsa return ret; 69026d33022SJiri Olsa } 69126d33022SJiri Olsa 69272a128aaSNamhyung Kim int record_callchain_opt(const struct option *opt __maybe_unused, 69309b0fd45SJiri Olsa const char *arg __maybe_unused, 69409b0fd45SJiri Olsa int unset __maybe_unused) 69509b0fd45SJiri Olsa { 69672a128aaSNamhyung Kim callchain_param.enabled = true; 69709b0fd45SJiri Olsa 69872a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 69972a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 700eb853e80SJiri Olsa 70172a128aaSNamhyung Kim callchain_debug(); 70209b0fd45SJiri Olsa return 0; 70309b0fd45SJiri Olsa } 70409b0fd45SJiri Olsa 705eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 706eb853e80SJiri Olsa { 707eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 7085a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 709eb853e80SJiri Olsa 710eb853e80SJiri Olsa return perf_default_config(var, value, cb); 711eb853e80SJiri Olsa } 712eb853e80SJiri Olsa 713e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 71486470930SIngo Molnar "perf record [<options>] [<command>]", 71586470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 71686470930SIngo Molnar NULL 71786470930SIngo Molnar }; 718e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 71986470930SIngo Molnar 720d20deb64SArnaldo Carvalho de Melo /* 7218c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 7228c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 723d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 724d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 725d20deb64SArnaldo Carvalho de Melo * 726d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 727d20deb64SArnaldo Carvalho de Melo * 728d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 729d20deb64SArnaldo Carvalho de Melo */ 7308c6f45a7SArnaldo Carvalho de Melo static struct record record = { 731d20deb64SArnaldo Carvalho de Melo .opts = { 7328affc2b8SAndi Kleen .sample_time = true, 733d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 734d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 735d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 736447a6013SArnaldo Carvalho de Melo .freq = 4000, 737d1cb9fceSNamhyung Kim .target = { 738d1cb9fceSNamhyung Kim .uses_mmap = true, 7393aa5939dSAdrian Hunter .default_per_cpu = true, 740d1cb9fceSNamhyung Kim }, 741d20deb64SArnaldo Carvalho de Melo }, 742e3d59112SNamhyung Kim .tool = { 743e3d59112SNamhyung Kim .sample = process_sample_event, 744e3d59112SNamhyung Kim .fork = perf_event__process_fork, 745e3d59112SNamhyung Kim .comm = perf_event__process_comm, 746e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 747e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 748e3d59112SNamhyung Kim }, 749d20deb64SArnaldo Carvalho de Melo }; 7507865e817SFrederic Weisbecker 75109b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 75261eaa3beSArnaldo Carvalho de Melo 7539ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT 754aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr"; 75561eaa3beSArnaldo Carvalho de Melo #else 756aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr"; 75761eaa3beSArnaldo Carvalho de Melo #endif 75861eaa3beSArnaldo Carvalho de Melo 759d20deb64SArnaldo Carvalho de Melo /* 760d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 761d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 762b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 763d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 764d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 765d20deb64SArnaldo Carvalho de Melo */ 766e5b2c207SNamhyung Kim struct option __record_options[] = { 767d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 76886470930SIngo Molnar "event selector. use 'perf list' to list available events", 769f120f9d5SJiri Olsa parse_events_option), 770d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 771c171b552SLi Zefan "event filter", parse_filter), 772bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 773d6d901c2SZhang, Yanmin "record events on existing process id"), 774bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 775d6d901c2SZhang, Yanmin "record events on existing thread id"), 776d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 77786470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 778509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 779acac03faSKirill Smelkov "collect data without buffering"), 780d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 781daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 782bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 78386470930SIngo Molnar "system-wide collection from all CPUs"), 784bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 785c45c6ea2SStephane Eranian "list of cpus to monitor"), 786d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 787f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 78886470930SIngo Molnar "output file name"), 78969e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 79069e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 7912e6cdf99SStephane Eranian "child tasks do not inherit counters"), 792d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 793994a1f78SJiri Olsa OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 794994a1f78SJiri Olsa "number of mmap data pages", 795994a1f78SJiri Olsa perf_evlist__parse_mmap_pages), 796d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 79743bece79SLin Ming "put the counters into a counter group"), 79809b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 79909b0fd45SJiri Olsa NULL, "enables call-graph recording" , 80009b0fd45SJiri Olsa &record_callchain_opt), 80109b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 80275d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 80309b0fd45SJiri Olsa &record_parse_callchain_opt), 804c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 8053da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 806b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 807d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 808649c48a9SPeter Zijlstra "per thread counts"), 809d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 8104bba828dSAnton Blanchard "Sample addresses"), 811d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 8123e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 813d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 814649c48a9SPeter Zijlstra "don't sample"), 815d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 816a1ac1d3cSStephane Eranian "do not update the buildid cache"), 817d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 818baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 819d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 820023695d9SStephane Eranian "monitor event in cgroup name only", 821023695d9SStephane Eranian parse_cgroups), 822a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 8236619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 824bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 825bea03405SNamhyung Kim "user to profile"), 826a5aabdacSStephane Eranian 827a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 828a5aabdacSStephane Eranian "branch any", "sample any taken branches", 829a5aabdacSStephane Eranian parse_branch_stack), 830a5aabdacSStephane Eranian 831a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 832a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 833bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 83405484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 83505484298SAndi Kleen "sample by weight (on special events only)"), 836475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 837475eeab9SAndi Kleen "sample transaction flags (special events only)"), 8383aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 8393aa5939dSAdrian Hunter "use per-thread mmaps"), 8404b6c5177SStephane Eranian OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 8414b6c5177SStephane Eranian "Sample machine registers on interrupt"), 84285c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 84385c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 84486470930SIngo Molnar OPT_END() 84586470930SIngo Molnar }; 84686470930SIngo Molnar 847e5b2c207SNamhyung Kim struct option *record_options = __record_options; 848e5b2c207SNamhyung Kim 8491d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 85086470930SIngo Molnar { 85169aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 8528c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 85316ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 85486470930SIngo Molnar 8553e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 8563e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 857361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 858361c99a6SArnaldo Carvalho de Melo 859eb853e80SJiri Olsa perf_config(perf_record_config, rec); 860eb853e80SJiri Olsa 861bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 862a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 863602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 864bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 86586470930SIngo Molnar 866bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 8673780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 868023695d9SStephane Eranian " system-wide mode\n"); 869023695d9SStephane Eranian usage_with_options(record_usage, record_options); 870023695d9SStephane Eranian } 871023695d9SStephane Eranian 8720a7e6d1bSNamhyung Kim symbol__init(NULL); 873baa2f6ceSArnaldo Carvalho de Melo 874ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 875646aaea6SArnaldo Carvalho de Melo pr_warning( 876646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 877ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 878646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 879646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 880646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 881646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 882646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 883ec80fde7SArnaldo Carvalho de Melo 884d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 885a1ac1d3cSStephane Eranian disable_buildid_cache(); 886655000e7SArnaldo Carvalho de Melo 8873e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 8883e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 88969aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 89069aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 891bbd36e5eSPeter Zijlstra } 89286470930SIngo Molnar 89369e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 89469e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 89569e7e5b0SAdrian Hunter 896602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 89716ad2ffbSNamhyung Kim if (err) { 898602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 89916ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 90016ad2ffbSNamhyung Kim } 9014bd0f2d2SNamhyung Kim 902602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 90316ad2ffbSNamhyung Kim if (err) { 90416ad2ffbSNamhyung Kim int saved_errno = errno; 90516ad2ffbSNamhyung Kim 906602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 9073780f488SNamhyung Kim ui__error("%s", errbuf); 90816ad2ffbSNamhyung Kim 90916ad2ffbSNamhyung Kim err = -saved_errno; 9108fa60e1fSNamhyung Kim goto out_symbol_exit; 91116ad2ffbSNamhyung Kim } 9120d37aa34SArnaldo Carvalho de Melo 91316ad2ffbSNamhyung Kim err = -ENOMEM; 9143e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 915dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 91669aad6f1SArnaldo Carvalho de Melo 917b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 91839d17dacSArnaldo Carvalho de Melo err = -EINVAL; 91903ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 9207e4ff9e3SMike Galbraith } 9217e4ff9e3SMike Galbraith 922d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 923d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 92445604710SNamhyung Kim perf_evlist__delete(rec->evlist); 925d65a458bSArnaldo Carvalho de Melo symbol__exit(); 92639d17dacSArnaldo Carvalho de Melo return err; 92786470930SIngo Molnar } 928