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" 30ef149c25SAdrian Hunter #include "util/auxtrace.h" 317c6a1c65SPeter Zijlstra 3286470930SIngo Molnar #include <unistd.h> 3386470930SIngo Molnar #include <sched.h> 34a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3586470930SIngo Molnar 3678da39faSBernhard Rosenkraenzer 378c6f45a7SArnaldo Carvalho de Melo struct record { 3845694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 39b4006796SArnaldo Carvalho de Melo struct record_opts opts; 40d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 41f5fc1412SJiri Olsa struct perf_data_file file; 42ef149c25SAdrian Hunter struct auxtrace_record *itr; 43d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 44d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 45d20deb64SArnaldo Carvalho de Melo const char *progname; 46d20deb64SArnaldo Carvalho de Melo int realtime_prio; 47d20deb64SArnaldo Carvalho de Melo bool no_buildid; 48d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 49d20deb64SArnaldo Carvalho de Melo long samples; 500f82ebc4SArnaldo Carvalho de Melo }; 5186470930SIngo Molnar 528c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 53f5970550SPeter Zijlstra { 54cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 554f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 568d3eca20SDavid Ahern return -1; 578d3eca20SDavid Ahern } 58f5970550SPeter Zijlstra 59cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 608d3eca20SDavid Ahern return 0; 61f5970550SPeter Zijlstra } 62f5970550SPeter Zijlstra 6345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 64d20deb64SArnaldo Carvalho de Melo union perf_event *event, 651d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 661d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 67234fbbf5SArnaldo Carvalho de Melo { 688c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 698c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 70234fbbf5SArnaldo Carvalho de Melo } 71234fbbf5SArnaldo Carvalho de Melo 72e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7386470930SIngo Molnar { 74e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 757b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 767b8283b5SDavid Ahern u64 old = md->prev; 77918512b4SJiri Olsa unsigned char *data = md->base + page_size; 7886470930SIngo Molnar unsigned long size; 7986470930SIngo Molnar void *buf; 808d3eca20SDavid Ahern int rc = 0; 8186470930SIngo Molnar 82dc82009aSArnaldo Carvalho de Melo if (old == head) 838d3eca20SDavid Ahern return 0; 8486470930SIngo Molnar 85d20deb64SArnaldo Carvalho de Melo rec->samples++; 8686470930SIngo Molnar 8786470930SIngo Molnar size = head - old; 8886470930SIngo Molnar 8986470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9086470930SIngo Molnar buf = &data[old & md->mask]; 9186470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9286470930SIngo Molnar old += size; 9386470930SIngo Molnar 948c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 958d3eca20SDavid Ahern rc = -1; 968d3eca20SDavid Ahern goto out; 978d3eca20SDavid Ahern } 9886470930SIngo Molnar } 9986470930SIngo Molnar 10086470930SIngo Molnar buf = &data[old & md->mask]; 10186470930SIngo Molnar size = head - old; 10286470930SIngo Molnar old += size; 10386470930SIngo Molnar 1048c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1058d3eca20SDavid Ahern rc = -1; 1068d3eca20SDavid Ahern goto out; 1078d3eca20SDavid Ahern } 10886470930SIngo Molnar 10986470930SIngo Molnar md->prev = old; 110e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1118d3eca20SDavid Ahern out: 1128d3eca20SDavid Ahern return rc; 11386470930SIngo Molnar } 11486470930SIngo Molnar 115ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 116ef149c25SAdrian Hunter union perf_event *event, void *data1, 117ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 118ef149c25SAdrian Hunter { 119ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 120*99fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 121ef149c25SAdrian Hunter size_t padding; 122ef149c25SAdrian Hunter u8 pad[8] = {0}; 123ef149c25SAdrian Hunter 124*99fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 125*99fa2984SAdrian Hunter off_t file_offset; 126*99fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 127*99fa2984SAdrian Hunter int err; 128*99fa2984SAdrian Hunter 129*99fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 130*99fa2984SAdrian Hunter if (file_offset == -1) 131*99fa2984SAdrian Hunter return -1; 132*99fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 133*99fa2984SAdrian Hunter event, file_offset); 134*99fa2984SAdrian Hunter if (err) 135*99fa2984SAdrian Hunter return err; 136*99fa2984SAdrian Hunter } 137*99fa2984SAdrian Hunter 138ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 139ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 140ef149c25SAdrian Hunter if (padding) 141ef149c25SAdrian Hunter padding = 8 - padding; 142ef149c25SAdrian Hunter 143ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 144ef149c25SAdrian Hunter record__write(rec, data1, len1); 145ef149c25SAdrian Hunter if (len2) 146ef149c25SAdrian Hunter record__write(rec, data2, len2); 147ef149c25SAdrian Hunter record__write(rec, &pad, padding); 148ef149c25SAdrian Hunter 149ef149c25SAdrian Hunter return 0; 150ef149c25SAdrian Hunter } 151ef149c25SAdrian Hunter 152ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 153ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 154ef149c25SAdrian Hunter { 155ef149c25SAdrian Hunter int ret; 156ef149c25SAdrian Hunter 157ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 158ef149c25SAdrian Hunter record__process_auxtrace); 159ef149c25SAdrian Hunter if (ret < 0) 160ef149c25SAdrian Hunter return ret; 161ef149c25SAdrian Hunter 162ef149c25SAdrian Hunter if (ret) 163ef149c25SAdrian Hunter rec->samples++; 164ef149c25SAdrian Hunter 165ef149c25SAdrian Hunter return 0; 166ef149c25SAdrian Hunter } 167ef149c25SAdrian Hunter 16886470930SIngo Molnar static volatile int done = 0; 169f7b7c26eSPeter Zijlstra static volatile int signr = -1; 17033e49ea7SAndi Kleen static volatile int child_finished = 0; 17186470930SIngo Molnar 17286470930SIngo Molnar static void sig_handler(int sig) 17386470930SIngo Molnar { 17433e49ea7SAndi Kleen if (sig == SIGCHLD) 17533e49ea7SAndi Kleen child_finished = 1; 17645604710SNamhyung Kim else 17745604710SNamhyung Kim signr = sig; 17833e49ea7SAndi Kleen 17986470930SIngo Molnar done = 1; 180f7b7c26eSPeter Zijlstra } 181f7b7c26eSPeter Zijlstra 18245604710SNamhyung Kim static void record__sig_exit(void) 183f7b7c26eSPeter Zijlstra { 18445604710SNamhyung Kim if (signr == -1) 185f7b7c26eSPeter Zijlstra return; 186f7b7c26eSPeter Zijlstra 187f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 18845604710SNamhyung Kim raise(signr); 18986470930SIngo Molnar } 19086470930SIngo Molnar 1918c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 192dd7927f4SArnaldo Carvalho de Melo { 19356e52e85SArnaldo Carvalho de Melo char msg[512]; 1946a4bb04cSJiri Olsa struct perf_evsel *pos; 195d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 196d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 197b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 1988d3eca20SDavid Ahern int rc = 0; 199dd7927f4SArnaldo Carvalho de Melo 200f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 201cac21425SJiri Olsa 2020050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2033da297a6SIngo Molnar try_again: 2046a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 20556e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2063da297a6SIngo Molnar if (verbose) 207c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2083da297a6SIngo Molnar goto try_again; 2093da297a6SIngo Molnar } 210ca6a4258SDavid Ahern 21156e52e85SArnaldo Carvalho de Melo rc = -errno; 21256e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 21356e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 21456e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2158d3eca20SDavid Ahern goto out; 2167c6a1c65SPeter Zijlstra } 2177c6a1c65SPeter Zijlstra } 2187c6a1c65SPeter Zijlstra 21923d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 22023d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 22123d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 22235550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 2238d3eca20SDavid Ahern rc = -1; 2248d3eca20SDavid Ahern goto out; 2250a102479SFrederic Weisbecker } 2260a102479SFrederic Weisbecker 227ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 228ef149c25SAdrian Hunter opts->auxtrace_mmap_pages, false) < 0) { 2298d3eca20SDavid Ahern if (errno == EPERM) { 2308d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 23118e60939SNelson Elhage "Consider increasing " 23218e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 23318e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 234ef149c25SAdrian Hunter "(current value: %u,%u)\n", 235ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 2368d3eca20SDavid Ahern rc = -errno; 2378d3eca20SDavid Ahern } else { 23835550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 23935550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 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 251e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 252e3d59112SNamhyung Kim union perf_event *event, 253e3d59112SNamhyung Kim struct perf_sample *sample, 254e3d59112SNamhyung Kim struct perf_evsel *evsel, 255e3d59112SNamhyung Kim struct machine *machine) 256e3d59112SNamhyung Kim { 257e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 258e3d59112SNamhyung Kim 259e3d59112SNamhyung Kim rec->samples++; 260e3d59112SNamhyung Kim 261e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 262e3d59112SNamhyung Kim } 263e3d59112SNamhyung Kim 2648c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 2656122e4e4SArnaldo Carvalho de Melo { 266f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 267f5fc1412SJiri Olsa struct perf_session *session = rec->session; 2686122e4e4SArnaldo Carvalho de Melo 26942aa276fSNamhyung Kim u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 2709f591fd7SArnaldo Carvalho de Melo if (size == 0) 2719f591fd7SArnaldo Carvalho de Melo return 0; 2729f591fd7SArnaldo Carvalho de Melo 2734ac30cf7SNamhyung Kim file->size = size; 2744ac30cf7SNamhyung Kim 27500dc8657SNamhyung Kim /* 27600dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 27700dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 27800dc8657SNamhyung Kim * we prefer the vmlinux path like 27900dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 28000dc8657SNamhyung Kim * 28100dc8657SNamhyung Kim * rather than build-id path (in debug directory). 28200dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 28300dc8657SNamhyung Kim */ 28400dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 28500dc8657SNamhyung Kim 286b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 2876122e4e4SArnaldo Carvalho de Melo } 2886122e4e4SArnaldo Carvalho de Melo 2898115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 290a1645ce1SZhang, Yanmin { 291a1645ce1SZhang, Yanmin int err; 29245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 293a1645ce1SZhang, Yanmin /* 294a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 295a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 296a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 297a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 298a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 299a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 300a1645ce1SZhang, Yanmin */ 30145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 302743eb868SArnaldo Carvalho de Melo machine); 303a1645ce1SZhang, Yanmin if (err < 0) 304a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 30523346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 306a1645ce1SZhang, Yanmin 307a1645ce1SZhang, Yanmin /* 308a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 309a1645ce1SZhang, Yanmin * have no _text sometimes. 310a1645ce1SZhang, Yanmin */ 31145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 3120ae617beSAdrian Hunter machine); 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 3238c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 32498402807SFrederic Weisbecker { 325dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 3260e2e63ddSPeter Zijlstra int i; 3278d3eca20SDavid Ahern int rc = 0; 32898402807SFrederic Weisbecker 329d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 330ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 331ef149c25SAdrian Hunter 3328d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 333e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 3348d3eca20SDavid Ahern rc = -1; 3358d3eca20SDavid Ahern goto out; 3368d3eca20SDavid Ahern } 3378d3eca20SDavid Ahern } 338ef149c25SAdrian Hunter 339ef149c25SAdrian Hunter if (mm->base && 340ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 341ef149c25SAdrian Hunter rc = -1; 342ef149c25SAdrian Hunter goto out; 343ef149c25SAdrian Hunter } 34498402807SFrederic Weisbecker } 34598402807SFrederic Weisbecker 346dcabb507SJiri Olsa /* 347dcabb507SJiri Olsa * Mark the round finished in case we wrote 348dcabb507SJiri Olsa * at least one event. 349dcabb507SJiri Olsa */ 350dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 3518c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 3528d3eca20SDavid Ahern 3538d3eca20SDavid Ahern out: 3548d3eca20SDavid Ahern return rc; 35598402807SFrederic Weisbecker } 35698402807SFrederic Weisbecker 3578c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 35857706abcSDavid Ahern { 35957706abcSDavid Ahern struct perf_session *session = rec->session; 36057706abcSDavid Ahern int feat; 36157706abcSDavid Ahern 36257706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 36357706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 36457706abcSDavid Ahern 36557706abcSDavid Ahern if (rec->no_buildid) 36657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 36757706abcSDavid Ahern 3683e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 36957706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 37057706abcSDavid Ahern 37157706abcSDavid Ahern if (!rec->opts.branch_stack) 37257706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 373ef149c25SAdrian Hunter 374ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 375ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 37657706abcSDavid Ahern } 37757706abcSDavid Ahern 378f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 379f33cbe72SArnaldo Carvalho de Melo 380f33cbe72SArnaldo Carvalho de Melo /* 381f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 382f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 383f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 384f33cbe72SArnaldo Carvalho de Melo */ 38545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 38645604710SNamhyung Kim siginfo_t *info, 387f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 388f33cbe72SArnaldo Carvalho de Melo { 389f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 390f33cbe72SArnaldo Carvalho de Melo done = 1; 391f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 392f33cbe72SArnaldo Carvalho de Melo } 393f33cbe72SArnaldo Carvalho de Melo 3948c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 39586470930SIngo Molnar { 39657706abcSDavid Ahern int err; 39745604710SNamhyung Kim int status = 0; 3988b412664SPeter Zijlstra unsigned long waking = 0; 39946be604bSZhang, Yanmin const bool forks = argc > 0; 40023346f21SArnaldo Carvalho de Melo struct machine *machine; 40145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 402b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 403f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 404d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 4056dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 40642aa276fSNamhyung Kim int fd; 40786470930SIngo Molnar 408d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 40933e49ea7SAndi Kleen 41045604710SNamhyung Kim atexit(record__sig_exit); 411f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 412f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 413804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 414f5970550SPeter Zijlstra 415b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 41694c744b6SArnaldo Carvalho de Melo if (session == NULL) { 417ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 418a9a70bbcSArnaldo Carvalho de Melo return -1; 419a9a70bbcSArnaldo Carvalho de Melo } 420a9a70bbcSArnaldo Carvalho de Melo 42142aa276fSNamhyung Kim fd = perf_data_file__fd(file); 422d20deb64SArnaldo Carvalho de Melo rec->session = session; 423d20deb64SArnaldo Carvalho de Melo 4248c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 425330aa675SStephane Eranian 426d4db3f16SArnaldo Carvalho de Melo if (forks) { 4273e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 428f5fc1412SJiri Olsa argv, file->is_pipe, 429735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 43035b9d88eSArnaldo Carvalho de Melo if (err < 0) { 43135b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 43245604710SNamhyung Kim status = err; 43335b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 434856e9660SPeter Zijlstra } 435856e9660SPeter Zijlstra } 436856e9660SPeter Zijlstra 4378c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 4388d3eca20SDavid Ahern err = -1; 43945604710SNamhyung Kim goto out_child; 4408d3eca20SDavid Ahern } 44186470930SIngo Molnar 4423e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 443a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 444a8bb559bSNamhyung Kim 445f5fc1412SJiri Olsa if (file->is_pipe) { 44642aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 447529870e3STom Zanussi if (err < 0) 44845604710SNamhyung Kim goto out_child; 449563aecb2SJiri Olsa } else { 45042aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 451d5eed904SArnaldo Carvalho de Melo if (err < 0) 45245604710SNamhyung Kim goto out_child; 453d5eed904SArnaldo Carvalho de Melo } 4547c6a1c65SPeter Zijlstra 455d3665498SDavid Ahern if (!rec->no_buildid 456e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 457d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 458e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 4598d3eca20SDavid Ahern err = -1; 46045604710SNamhyung Kim goto out_child; 461e20960c0SRobert Richter } 462e20960c0SRobert Richter 46334ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 464743eb868SArnaldo Carvalho de Melo 465f5fc1412SJiri Olsa if (file->is_pipe) { 46645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 467a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 4682c46dbb5STom Zanussi if (err < 0) { 4692c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 47045604710SNamhyung Kim goto out_child; 4712c46dbb5STom Zanussi } 472cd19a035STom Zanussi 4733e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 47463e0c771STom Zanussi /* 47563e0c771STom Zanussi * FIXME err <= 0 here actually means that 47663e0c771STom Zanussi * there were no tracepoints so its not really 47763e0c771STom Zanussi * an error, just that we don't need to 47863e0c771STom Zanussi * synthesize anything. We really have to 47963e0c771STom Zanussi * return this more properly and also 48063e0c771STom Zanussi * propagate errors that now are calling die() 48163e0c771STom Zanussi */ 48242aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 483743eb868SArnaldo Carvalho de Melo process_synthesized_event); 48463e0c771STom Zanussi if (err <= 0) { 48563e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 48645604710SNamhyung Kim goto out_child; 48763e0c771STom Zanussi } 488f34b9001SDavid Ahern rec->bytes_written += err; 4892c46dbb5STom Zanussi } 49063e0c771STom Zanussi } 4912c46dbb5STom Zanussi 492ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 493ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 494ef149c25SAdrian Hunter session, process_synthesized_event); 495ef149c25SAdrian Hunter if (err) 496ef149c25SAdrian Hunter goto out_delete_session; 497ef149c25SAdrian Hunter } 498ef149c25SAdrian Hunter 49945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 5000ae617beSAdrian Hunter machine); 501c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 502c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 503c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 504c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 50556b03f3cSArnaldo Carvalho de Melo 50645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 507743eb868SArnaldo Carvalho de Melo machine); 508c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 509c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 510c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 511c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 512c1a3a4b9SArnaldo Carvalho de Melo 5137e383de4SArnaldo Carvalho de Melo if (perf_guest) { 514876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 5157e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 5167e383de4SArnaldo Carvalho de Melo } 517b7cece76SArnaldo Carvalho de Melo 5183e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 51958d925dcSArnaldo Carvalho de Melo process_synthesized_event, opts->sample_address); 5208d3eca20SDavid Ahern if (err != 0) 52145604710SNamhyung Kim goto out_child; 5228d3eca20SDavid Ahern 523d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 52486470930SIngo Molnar struct sched_param param; 52586470930SIngo Molnar 526d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 52786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5286beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 5298d3eca20SDavid Ahern err = -1; 53045604710SNamhyung Kim goto out_child; 53186470930SIngo Molnar } 53286470930SIngo Molnar } 53386470930SIngo Molnar 534774cb499SJiri Olsa /* 535774cb499SJiri Olsa * When perf is starting the traced process, all the events 536774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 537774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 538774cb499SJiri Olsa */ 5396619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 5403e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 541764e16a3SDavid Ahern 542856e9660SPeter Zijlstra /* 543856e9660SPeter Zijlstra * Let the child rip 544856e9660SPeter Zijlstra */ 545735f7e0bSArnaldo Carvalho de Melo if (forks) 5463e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 547856e9660SPeter Zijlstra 5486619a53eSAndi Kleen if (opts->initial_delay) { 5496619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 5506619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 5516619a53eSAndi Kleen } 5526619a53eSAndi Kleen 553649c48a9SPeter Zijlstra for (;;) { 554d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 55586470930SIngo Molnar 5568c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 5578d3eca20SDavid Ahern err = -1; 55845604710SNamhyung Kim goto out_child; 5598d3eca20SDavid Ahern } 56086470930SIngo Molnar 561d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 5626dcf45efSArnaldo Carvalho de Melo if (done || draining) 563649c48a9SPeter Zijlstra break; 564f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 565a515114fSJiri Olsa /* 566a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 567a515114fSJiri Olsa * number of returned events and interrupt error. 568a515114fSJiri Olsa */ 569a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 57045604710SNamhyung Kim err = 0; 5718b412664SPeter Zijlstra waking++; 5726dcf45efSArnaldo Carvalho de Melo 5736dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 5746dcf45efSArnaldo Carvalho de Melo draining = true; 5758b412664SPeter Zijlstra } 5768b412664SPeter Zijlstra 577774cb499SJiri Olsa /* 578774cb499SJiri Olsa * When perf is starting the traced process, at the end events 579774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 580774cb499SJiri Olsa * disable events in this case. 581774cb499SJiri Olsa */ 582602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 5833e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 5842711926aSJiri Olsa disabled = true; 5852711926aSJiri Olsa } 5868b412664SPeter Zijlstra } 5878b412664SPeter Zijlstra 588f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 58935550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 590f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 591f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 592f33cbe72SArnaldo Carvalho de Melo err = -1; 59345604710SNamhyung Kim goto out_child; 594f33cbe72SArnaldo Carvalho de Melo } 595f33cbe72SArnaldo Carvalho de Melo 596e3d59112SNamhyung Kim if (!quiet) 5978b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 59886470930SIngo Molnar 59945604710SNamhyung Kim out_child: 60045604710SNamhyung Kim if (forks) { 60145604710SNamhyung Kim int exit_status; 60245604710SNamhyung Kim 60345604710SNamhyung Kim if (!child_finished) 60445604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 60545604710SNamhyung Kim 60645604710SNamhyung Kim wait(&exit_status); 60745604710SNamhyung Kim 60845604710SNamhyung Kim if (err < 0) 60945604710SNamhyung Kim status = err; 61045604710SNamhyung Kim else if (WIFEXITED(exit_status)) 61145604710SNamhyung Kim status = WEXITSTATUS(exit_status); 61245604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 61345604710SNamhyung Kim signr = WTERMSIG(exit_status); 61445604710SNamhyung Kim } else 61545604710SNamhyung Kim status = err; 61645604710SNamhyung Kim 617e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 618e3d59112SNamhyung Kim rec->samples = 0; 619e3d59112SNamhyung Kim 62045604710SNamhyung Kim if (!err && !file->is_pipe) { 62145604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 62245604710SNamhyung Kim 62345604710SNamhyung Kim if (!rec->no_buildid) 62445604710SNamhyung Kim process_buildids(rec); 62542aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 62645604710SNamhyung Kim } 62739d17dacSArnaldo Carvalho de Melo 628e3d59112SNamhyung Kim if (!err && !quiet) { 629e3d59112SNamhyung Kim char samples[128]; 630e3d59112SNamhyung Kim 631ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 632e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 633e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 634e3d59112SNamhyung Kim else 635e3d59112SNamhyung Kim samples[0] = '\0'; 636e3d59112SNamhyung Kim 637e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 638e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 639e3d59112SNamhyung Kim file->path, samples); 640e3d59112SNamhyung Kim } 641e3d59112SNamhyung Kim 64239d17dacSArnaldo Carvalho de Melo out_delete_session: 64339d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 64445604710SNamhyung Kim return status; 64586470930SIngo Molnar } 64686470930SIngo Molnar 647bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 648bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 649bdfebd84SRoberto Agostino Vitillo 650bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 651bdfebd84SRoberto Agostino Vitillo 652bdfebd84SRoberto Agostino Vitillo struct branch_mode { 653bdfebd84SRoberto Agostino Vitillo const char *name; 654bdfebd84SRoberto Agostino Vitillo int mode; 655bdfebd84SRoberto Agostino Vitillo }; 656bdfebd84SRoberto Agostino Vitillo 657bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 658bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 659bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 660bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 661bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 662bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 663bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 664bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 6650126d493SAndi Kleen BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 6660126d493SAndi Kleen BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 6670126d493SAndi Kleen BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 6680fffa5dfSAnshuman Khandual BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 669bdfebd84SRoberto Agostino Vitillo BRANCH_END 670bdfebd84SRoberto Agostino Vitillo }; 671bdfebd84SRoberto Agostino Vitillo 672bdfebd84SRoberto Agostino Vitillo static int 673a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 674bdfebd84SRoberto Agostino Vitillo { 675bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 676bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 677bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 678bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 679bdfebd84SRoberto Agostino Vitillo 680bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 681bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 682a5aabdacSStephane Eranian char *s, *os = NULL, *p; 683bdfebd84SRoberto Agostino Vitillo int ret = -1; 684bdfebd84SRoberto Agostino Vitillo 685a5aabdacSStephane Eranian if (unset) 686a5aabdacSStephane Eranian return 0; 687bdfebd84SRoberto Agostino Vitillo 688a5aabdacSStephane Eranian /* 689a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 690a5aabdacSStephane Eranian */ 691a5aabdacSStephane Eranian if (*mode) 692a5aabdacSStephane Eranian return -1; 693a5aabdacSStephane Eranian 694a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 695a5aabdacSStephane Eranian if (str) { 696bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 697bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 698bdfebd84SRoberto Agostino Vitillo if (!s) 699bdfebd84SRoberto Agostino Vitillo return -1; 700bdfebd84SRoberto Agostino Vitillo 701bdfebd84SRoberto Agostino Vitillo for (;;) { 702bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 703bdfebd84SRoberto Agostino Vitillo if (p) 704bdfebd84SRoberto Agostino Vitillo *p = '\0'; 705bdfebd84SRoberto Agostino Vitillo 706bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 707bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 708bdfebd84SRoberto Agostino Vitillo break; 709bdfebd84SRoberto Agostino Vitillo } 710a5aabdacSStephane Eranian if (!br->name) { 711a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 712a5aabdacSStephane Eranian " check man page\n", s); 713bdfebd84SRoberto Agostino Vitillo goto error; 714a5aabdacSStephane Eranian } 715bdfebd84SRoberto Agostino Vitillo 716bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 717bdfebd84SRoberto Agostino Vitillo 718bdfebd84SRoberto Agostino Vitillo if (!p) 719bdfebd84SRoberto Agostino Vitillo break; 720bdfebd84SRoberto Agostino Vitillo 721bdfebd84SRoberto Agostino Vitillo s = p + 1; 722bdfebd84SRoberto Agostino Vitillo } 723a5aabdacSStephane Eranian } 724bdfebd84SRoberto Agostino Vitillo ret = 0; 725bdfebd84SRoberto Agostino Vitillo 726a5aabdacSStephane Eranian /* default to any branch */ 727bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 728a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 729bdfebd84SRoberto Agostino Vitillo } 730bdfebd84SRoberto Agostino Vitillo error: 731bdfebd84SRoberto Agostino Vitillo free(os); 732bdfebd84SRoberto Agostino Vitillo return ret; 733bdfebd84SRoberto Agostino Vitillo } 734bdfebd84SRoberto Agostino Vitillo 73572a128aaSNamhyung Kim static void callchain_debug(void) 73609b0fd45SJiri Olsa { 737aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 738a601fdffSJiri Olsa 73972a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 74026d33022SJiri Olsa 74172a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 74209b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 74372a128aaSNamhyung Kim callchain_param.dump_size); 74409b0fd45SJiri Olsa } 74509b0fd45SJiri Olsa 74672a128aaSNamhyung Kim int record_parse_callchain_opt(const struct option *opt __maybe_unused, 74709b0fd45SJiri Olsa const char *arg, 74809b0fd45SJiri Olsa int unset) 74909b0fd45SJiri Olsa { 75009b0fd45SJiri Olsa int ret; 75109b0fd45SJiri Olsa 75272a128aaSNamhyung Kim callchain_param.enabled = !unset; 753eb853e80SJiri Olsa 75409b0fd45SJiri Olsa /* --no-call-graph */ 75509b0fd45SJiri Olsa if (unset) { 75672a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 75709b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 75809b0fd45SJiri Olsa return 0; 75909b0fd45SJiri Olsa } 76009b0fd45SJiri Olsa 761f7f084f4SNamhyung Kim ret = parse_callchain_record_opt(arg); 76209b0fd45SJiri Olsa if (!ret) 76372a128aaSNamhyung Kim callchain_debug(); 76409b0fd45SJiri Olsa 76526d33022SJiri Olsa return ret; 76626d33022SJiri Olsa } 76726d33022SJiri Olsa 76872a128aaSNamhyung Kim int record_callchain_opt(const struct option *opt __maybe_unused, 76909b0fd45SJiri Olsa const char *arg __maybe_unused, 77009b0fd45SJiri Olsa int unset __maybe_unused) 77109b0fd45SJiri Olsa { 77272a128aaSNamhyung Kim callchain_param.enabled = true; 77309b0fd45SJiri Olsa 77472a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 77572a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 776eb853e80SJiri Olsa 77772a128aaSNamhyung Kim callchain_debug(); 77809b0fd45SJiri Olsa return 0; 77909b0fd45SJiri Olsa } 78009b0fd45SJiri Olsa 781eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 782eb853e80SJiri Olsa { 783eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 7845a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 785eb853e80SJiri Olsa 786eb853e80SJiri Olsa return perf_default_config(var, value, cb); 787eb853e80SJiri Olsa } 788eb853e80SJiri Olsa 789814c8c38SPeter Zijlstra struct clockid_map { 790814c8c38SPeter Zijlstra const char *name; 791814c8c38SPeter Zijlstra int clockid; 792814c8c38SPeter Zijlstra }; 793814c8c38SPeter Zijlstra 794814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 795814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 796814c8c38SPeter Zijlstra 797814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 798814c8c38SPeter Zijlstra 799814c8c38SPeter Zijlstra 800814c8c38SPeter Zijlstra /* 801814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 802814c8c38SPeter Zijlstra */ 803814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 804814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 805814c8c38SPeter Zijlstra #endif 806814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 807814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 808814c8c38SPeter Zijlstra #endif 809814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 810814c8c38SPeter Zijlstra #define CLOCK_TAI 11 811814c8c38SPeter Zijlstra #endif 812814c8c38SPeter Zijlstra 813814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 814814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 815814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 816814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 817814c8c38SPeter Zijlstra 818814c8c38SPeter Zijlstra /* available for some events */ 819814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 820814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 821814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 822814c8c38SPeter Zijlstra 823814c8c38SPeter Zijlstra /* available for the lazy */ 824814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 825814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 826814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 827814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 828814c8c38SPeter Zijlstra 829814c8c38SPeter Zijlstra CLOCKID_END, 830814c8c38SPeter Zijlstra }; 831814c8c38SPeter Zijlstra 832814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 833814c8c38SPeter Zijlstra { 834814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 835814c8c38SPeter Zijlstra const struct clockid_map *cm; 836814c8c38SPeter Zijlstra const char *ostr = str; 837814c8c38SPeter Zijlstra 838814c8c38SPeter Zijlstra if (unset) { 839814c8c38SPeter Zijlstra opts->use_clockid = 0; 840814c8c38SPeter Zijlstra return 0; 841814c8c38SPeter Zijlstra } 842814c8c38SPeter Zijlstra 843814c8c38SPeter Zijlstra /* no arg passed */ 844814c8c38SPeter Zijlstra if (!str) 845814c8c38SPeter Zijlstra return 0; 846814c8c38SPeter Zijlstra 847814c8c38SPeter Zijlstra /* no setting it twice */ 848814c8c38SPeter Zijlstra if (opts->use_clockid) 849814c8c38SPeter Zijlstra return -1; 850814c8c38SPeter Zijlstra 851814c8c38SPeter Zijlstra opts->use_clockid = true; 852814c8c38SPeter Zijlstra 853814c8c38SPeter Zijlstra /* if its a number, we're done */ 854814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 855814c8c38SPeter Zijlstra return 0; 856814c8c38SPeter Zijlstra 857814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 858814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 859814c8c38SPeter Zijlstra str += 6; 860814c8c38SPeter Zijlstra 861814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 862814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 863814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 864814c8c38SPeter Zijlstra return 0; 865814c8c38SPeter Zijlstra } 866814c8c38SPeter Zijlstra } 867814c8c38SPeter Zijlstra 868814c8c38SPeter Zijlstra opts->use_clockid = false; 869814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 870814c8c38SPeter Zijlstra return -1; 871814c8c38SPeter Zijlstra } 872814c8c38SPeter Zijlstra 873e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 874e9db1310SAdrian Hunter const char *str, 875e9db1310SAdrian Hunter int unset __maybe_unused) 876e9db1310SAdrian Hunter { 877e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 878e9db1310SAdrian Hunter char *s, *p; 879e9db1310SAdrian Hunter unsigned int mmap_pages; 880e9db1310SAdrian Hunter int ret; 881e9db1310SAdrian Hunter 882e9db1310SAdrian Hunter if (!str) 883e9db1310SAdrian Hunter return -EINVAL; 884e9db1310SAdrian Hunter 885e9db1310SAdrian Hunter s = strdup(str); 886e9db1310SAdrian Hunter if (!s) 887e9db1310SAdrian Hunter return -ENOMEM; 888e9db1310SAdrian Hunter 889e9db1310SAdrian Hunter p = strchr(s, ','); 890e9db1310SAdrian Hunter if (p) 891e9db1310SAdrian Hunter *p = '\0'; 892e9db1310SAdrian Hunter 893e9db1310SAdrian Hunter if (*s) { 894e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 895e9db1310SAdrian Hunter if (ret) 896e9db1310SAdrian Hunter goto out_free; 897e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 898e9db1310SAdrian Hunter } 899e9db1310SAdrian Hunter 900e9db1310SAdrian Hunter if (!p) { 901e9db1310SAdrian Hunter ret = 0; 902e9db1310SAdrian Hunter goto out_free; 903e9db1310SAdrian Hunter } 904e9db1310SAdrian Hunter 905e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 906e9db1310SAdrian Hunter if (ret) 907e9db1310SAdrian Hunter goto out_free; 908e9db1310SAdrian Hunter 909e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 910e9db1310SAdrian Hunter 911e9db1310SAdrian Hunter out_free: 912e9db1310SAdrian Hunter free(s); 913e9db1310SAdrian Hunter return ret; 914e9db1310SAdrian Hunter } 915e9db1310SAdrian Hunter 916e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 91786470930SIngo Molnar "perf record [<options>] [<command>]", 91886470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 91986470930SIngo Molnar NULL 92086470930SIngo Molnar }; 921e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 92286470930SIngo Molnar 923d20deb64SArnaldo Carvalho de Melo /* 9248c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 9258c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 926d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 927d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 928d20deb64SArnaldo Carvalho de Melo * 929d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 930d20deb64SArnaldo Carvalho de Melo * 931d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 932d20deb64SArnaldo Carvalho de Melo */ 9338c6f45a7SArnaldo Carvalho de Melo static struct record record = { 934d20deb64SArnaldo Carvalho de Melo .opts = { 9358affc2b8SAndi Kleen .sample_time = true, 936d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 937d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 938d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 939447a6013SArnaldo Carvalho de Melo .freq = 4000, 940d1cb9fceSNamhyung Kim .target = { 941d1cb9fceSNamhyung Kim .uses_mmap = true, 9423aa5939dSAdrian Hunter .default_per_cpu = true, 943d1cb9fceSNamhyung Kim }, 944d20deb64SArnaldo Carvalho de Melo }, 945e3d59112SNamhyung Kim .tool = { 946e3d59112SNamhyung Kim .sample = process_sample_event, 947e3d59112SNamhyung Kim .fork = perf_event__process_fork, 948e3d59112SNamhyung Kim .comm = perf_event__process_comm, 949e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 950e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 951e3d59112SNamhyung Kim }, 952d20deb64SArnaldo Carvalho de Melo }; 9537865e817SFrederic Weisbecker 95409b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 95561eaa3beSArnaldo Carvalho de Melo 9569ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT 957aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr"; 95861eaa3beSArnaldo Carvalho de Melo #else 959aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr"; 96061eaa3beSArnaldo Carvalho de Melo #endif 96161eaa3beSArnaldo Carvalho de Melo 962d20deb64SArnaldo Carvalho de Melo /* 963d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 964d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 965b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 966d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 967d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 968d20deb64SArnaldo Carvalho de Melo */ 969e5b2c207SNamhyung Kim struct option __record_options[] = { 970d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 97186470930SIngo Molnar "event selector. use 'perf list' to list available events", 972f120f9d5SJiri Olsa parse_events_option), 973d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 974c171b552SLi Zefan "event filter", parse_filter), 975bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 976d6d901c2SZhang, Yanmin "record events on existing process id"), 977bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 978d6d901c2SZhang, Yanmin "record events on existing thread id"), 979d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 98086470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 981509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 982acac03faSKirill Smelkov "collect data without buffering"), 983d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 984daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 985bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 98686470930SIngo Molnar "system-wide collection from all CPUs"), 987bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 988c45c6ea2SStephane Eranian "list of cpus to monitor"), 989d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 990f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 99186470930SIngo Molnar "output file name"), 99269e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 99369e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 9942e6cdf99SStephane Eranian "child tasks do not inherit counters"), 995d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 996e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 997e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 998e9db1310SAdrian Hunter record__parse_mmap_pages), 999d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 100043bece79SLin Ming "put the counters into a counter group"), 100109b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 100209b0fd45SJiri Olsa NULL, "enables call-graph recording" , 100309b0fd45SJiri Olsa &record_callchain_opt), 100409b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 100575d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 100609b0fd45SJiri Olsa &record_parse_callchain_opt), 1007c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10083da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1009b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1010d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1011649c48a9SPeter Zijlstra "per thread counts"), 1012d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 10134bba828dSAnton Blanchard "Sample addresses"), 1014d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 10153e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 1016d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1017649c48a9SPeter Zijlstra "don't sample"), 1018d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1019a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1020d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1021baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1022d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1023023695d9SStephane Eranian "monitor event in cgroup name only", 1024023695d9SStephane Eranian parse_cgroups), 1025a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 10266619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1027bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1028bea03405SNamhyung Kim "user to profile"), 1029a5aabdacSStephane Eranian 1030a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1031a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1032a5aabdacSStephane Eranian parse_branch_stack), 1033a5aabdacSStephane Eranian 1034a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1035a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1036bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 103705484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 103805484298SAndi Kleen "sample by weight (on special events only)"), 1039475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1040475eeab9SAndi Kleen "sample transaction flags (special events only)"), 10413aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 10423aa5939dSAdrian Hunter "use per-thread mmaps"), 10434b6c5177SStephane Eranian OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 10444b6c5177SStephane Eranian "Sample machine registers on interrupt"), 104585c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 104685c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1047814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1048814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1049814c8c38SPeter Zijlstra parse_clockid), 105086470930SIngo Molnar OPT_END() 105186470930SIngo Molnar }; 105286470930SIngo Molnar 1053e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1054e5b2c207SNamhyung Kim 10551d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 105686470930SIngo Molnar { 1057ef149c25SAdrian Hunter int err; 10588c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 105916ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 106086470930SIngo Molnar 10613e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 10623e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1063361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1064361c99a6SArnaldo Carvalho de Melo 1065eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1066eb853e80SJiri Olsa 1067bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1068a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1069602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1070bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 107186470930SIngo Molnar 1072bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 10733780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1074023695d9SStephane Eranian " system-wide mode\n"); 1075023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1076023695d9SStephane Eranian } 1077023695d9SStephane Eranian 1078ef149c25SAdrian Hunter if (!rec->itr) { 1079ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1080ef149c25SAdrian Hunter if (err) 1081ef149c25SAdrian Hunter return err; 1082ef149c25SAdrian Hunter } 1083ef149c25SAdrian Hunter 1084ef149c25SAdrian Hunter err = -ENOMEM; 1085ef149c25SAdrian Hunter 10860a7e6d1bSNamhyung Kim symbol__init(NULL); 1087baa2f6ceSArnaldo Carvalho de Melo 1088ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1089646aaea6SArnaldo Carvalho de Melo pr_warning( 1090646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1091ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1092646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1093646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1094646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1095646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1096646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1097ec80fde7SArnaldo Carvalho de Melo 1098d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1099a1ac1d3cSStephane Eranian disable_buildid_cache(); 1100655000e7SArnaldo Carvalho de Melo 11013e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 11023e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 110369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 110469aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1105bbd36e5eSPeter Zijlstra } 110686470930SIngo Molnar 110769e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 110869e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 110969e7e5b0SAdrian Hunter 1110602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 111116ad2ffbSNamhyung Kim if (err) { 1112602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 111316ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 111416ad2ffbSNamhyung Kim } 11154bd0f2d2SNamhyung Kim 1116602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 111716ad2ffbSNamhyung Kim if (err) { 111816ad2ffbSNamhyung Kim int saved_errno = errno; 111916ad2ffbSNamhyung Kim 1120602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 11213780f488SNamhyung Kim ui__error("%s", errbuf); 112216ad2ffbSNamhyung Kim 112316ad2ffbSNamhyung Kim err = -saved_errno; 11248fa60e1fSNamhyung Kim goto out_symbol_exit; 112516ad2ffbSNamhyung Kim } 11260d37aa34SArnaldo Carvalho de Melo 112716ad2ffbSNamhyung Kim err = -ENOMEM; 11283e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1129dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 113069aad6f1SArnaldo Carvalho de Melo 1131ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1132ef149c25SAdrian Hunter if (err) 1133ef149c25SAdrian Hunter goto out_symbol_exit; 1134ef149c25SAdrian Hunter 1135b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 113639d17dacSArnaldo Carvalho de Melo err = -EINVAL; 113703ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 11387e4ff9e3SMike Galbraith } 11397e4ff9e3SMike Galbraith 1140d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1141d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 114245604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1143d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1144ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 114539d17dacSArnaldo Carvalho de Melo return err; 114686470930SIngo Molnar } 1147