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" 144b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1586470930SIngo Molnar #include "util/parse-events.h" 1641840d21STaeung Song #include "util/config.h" 1786470930SIngo Molnar 188f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 19f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 207c6a1c65SPeter Zijlstra #include "util/header.h" 2166e274f3SFrederic Weisbecker #include "util/event.h" 22361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2369aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 248f28827aSFrederic Weisbecker #include "util/debug.h" 25*5d8bb1ecSMathieu Poirier #include "util/drv_configs.h" 2694c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2745694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 288d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 29a12b51c4SPaul Mackerras #include "util/cpumap.h" 30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 31f5fc1412SJiri Olsa #include "util/data.h" 32bcc84ec6SStephane Eranian #include "util/perf_regs.h" 33ef149c25SAdrian Hunter #include "util/auxtrace.h" 3446bc29b9SAdrian Hunter #include "util/tsc.h" 35f00898f4SAndi Kleen #include "util/parse-branch-options.h" 36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3771dc2326SWang Nan #include "util/llvm-utils.h" 388690a2a7SWang Nan #include "util/bpf-loader.h" 395f9cf599SWang Nan #include "util/trigger.h" 40d8871ea7SWang Nan #include "asm/bug.h" 417c6a1c65SPeter Zijlstra 4286470930SIngo Molnar #include <unistd.h> 4386470930SIngo Molnar #include <sched.h> 44a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 452d11c650SWang Nan #include <asm/bug.h> 460693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 4778da39faSBernhard Rosenkraenzer 488c6f45a7SArnaldo Carvalho de Melo struct record { 4945694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 50b4006796SArnaldo Carvalho de Melo struct record_opts opts; 51d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 52f5fc1412SJiri Olsa struct perf_data_file file; 53ef149c25SAdrian Hunter struct auxtrace_record *itr; 54d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 55d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 56d20deb64SArnaldo Carvalho de Melo const char *progname; 57d20deb64SArnaldo Carvalho de Melo int realtime_prio; 58d20deb64SArnaldo Carvalho de Melo bool no_buildid; 59d2db9a98SWang Nan bool no_buildid_set; 60d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 61d2db9a98SWang Nan bool no_buildid_cache_set; 626156681bSNamhyung Kim bool buildid_all; 63ecfd7a9cSWang Nan bool timestamp_filename; 643c1cb7e3SWang Nan bool switch_output; 659f065194SYang Shi unsigned long long samples; 660f82ebc4SArnaldo Carvalho de Melo }; 6786470930SIngo Molnar 688c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 69f5970550SPeter Zijlstra { 70cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 714f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 728d3eca20SDavid Ahern return -1; 738d3eca20SDavid Ahern } 74f5970550SPeter Zijlstra 75cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 768d3eca20SDavid Ahern return 0; 77f5970550SPeter Zijlstra } 78f5970550SPeter Zijlstra 7945694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 80d20deb64SArnaldo Carvalho de Melo union perf_event *event, 811d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 821d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 83234fbbf5SArnaldo Carvalho de Melo { 848c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 858c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 86234fbbf5SArnaldo Carvalho de Melo } 87234fbbf5SArnaldo Carvalho de Melo 883a62a7b8SWang Nan static int 893a62a7b8SWang Nan backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) 903a62a7b8SWang Nan { 913a62a7b8SWang Nan struct perf_event_header *pheader; 923a62a7b8SWang Nan u64 evt_head = head; 933a62a7b8SWang Nan int size = mask + 1; 943a62a7b8SWang Nan 953a62a7b8SWang Nan pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); 963a62a7b8SWang Nan pheader = (struct perf_event_header *)(buf + (head & mask)); 973a62a7b8SWang Nan *start = head; 983a62a7b8SWang Nan while (true) { 993a62a7b8SWang Nan if (evt_head - head >= (unsigned int)size) { 1005e30d55cSColin Ian King pr_debug("Finished reading backward ring buffer: rewind\n"); 1013a62a7b8SWang Nan if (evt_head - head > (unsigned int)size) 1023a62a7b8SWang Nan evt_head -= pheader->size; 1033a62a7b8SWang Nan *end = evt_head; 1043a62a7b8SWang Nan return 0; 1053a62a7b8SWang Nan } 1063a62a7b8SWang Nan 1073a62a7b8SWang Nan pheader = (struct perf_event_header *)(buf + (evt_head & mask)); 1083a62a7b8SWang Nan 1093a62a7b8SWang Nan if (pheader->size == 0) { 1105e30d55cSColin Ian King pr_debug("Finished reading backward ring buffer: get start\n"); 1113a62a7b8SWang Nan *end = evt_head; 1123a62a7b8SWang Nan return 0; 1133a62a7b8SWang Nan } 1143a62a7b8SWang Nan 1153a62a7b8SWang Nan evt_head += pheader->size; 1163a62a7b8SWang Nan pr_debug3("move evt_head: %"PRIx64"\n", evt_head); 1173a62a7b8SWang Nan } 1183a62a7b8SWang Nan WARN_ONCE(1, "Shouldn't get here\n"); 1193a62a7b8SWang Nan return -1; 1203a62a7b8SWang Nan } 1213a62a7b8SWang Nan 1223a62a7b8SWang Nan static int 123a4ea0ec4SWang Nan rb_find_range(void *data, int mask, u64 head, u64 old, 124a4ea0ec4SWang Nan u64 *start, u64 *end, bool backward) 1253a62a7b8SWang Nan { 126a4ea0ec4SWang Nan if (!backward) { 1273a62a7b8SWang Nan *start = old; 1283a62a7b8SWang Nan *end = head; 1293a62a7b8SWang Nan return 0; 1303a62a7b8SWang Nan } 1313a62a7b8SWang Nan 1323a62a7b8SWang Nan return backward_rb_find_range(data, mask, head, start, end); 1333a62a7b8SWang Nan } 1343a62a7b8SWang Nan 135a4ea0ec4SWang Nan static int 136a4ea0ec4SWang Nan record__mmap_read(struct record *rec, struct perf_mmap *md, 137a4ea0ec4SWang Nan bool overwrite, bool backward) 13886470930SIngo Molnar { 1397b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 1407b8283b5SDavid Ahern u64 old = md->prev; 14109fa4f40SWang Nan u64 end = head, start = old; 142918512b4SJiri Olsa unsigned char *data = md->base + page_size; 14386470930SIngo Molnar unsigned long size; 14486470930SIngo Molnar void *buf; 1458d3eca20SDavid Ahern int rc = 0; 14686470930SIngo Molnar 147a4ea0ec4SWang Nan if (rb_find_range(data, md->mask, head, 148a4ea0ec4SWang Nan old, &start, &end, backward)) 1493a62a7b8SWang Nan return -1; 1503a62a7b8SWang Nan 15109fa4f40SWang Nan if (start == end) 1528d3eca20SDavid Ahern return 0; 15386470930SIngo Molnar 154d20deb64SArnaldo Carvalho de Melo rec->samples++; 15586470930SIngo Molnar 15609fa4f40SWang Nan size = end - start; 1572d11c650SWang Nan if (size > (unsigned long)(md->mask) + 1) { 1582d11c650SWang Nan WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 1592d11c650SWang Nan 1602d11c650SWang Nan md->prev = head; 161a4ea0ec4SWang Nan perf_mmap__consume(md, overwrite || backward); 1622d11c650SWang Nan return 0; 1632d11c650SWang Nan } 16486470930SIngo Molnar 16509fa4f40SWang Nan if ((start & md->mask) + size != (end & md->mask)) { 16609fa4f40SWang Nan buf = &data[start & md->mask]; 16709fa4f40SWang Nan size = md->mask + 1 - (start & md->mask); 16809fa4f40SWang Nan start += size; 16986470930SIngo Molnar 1708c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1718d3eca20SDavid Ahern rc = -1; 1728d3eca20SDavid Ahern goto out; 1738d3eca20SDavid Ahern } 17486470930SIngo Molnar } 17586470930SIngo Molnar 17609fa4f40SWang Nan buf = &data[start & md->mask]; 17709fa4f40SWang Nan size = end - start; 17809fa4f40SWang Nan start += size; 17986470930SIngo Molnar 1808c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1818d3eca20SDavid Ahern rc = -1; 1828d3eca20SDavid Ahern goto out; 1838d3eca20SDavid Ahern } 18486470930SIngo Molnar 18509fa4f40SWang Nan md->prev = head; 186a4ea0ec4SWang Nan perf_mmap__consume(md, overwrite || backward); 1878d3eca20SDavid Ahern out: 1888d3eca20SDavid Ahern return rc; 18986470930SIngo Molnar } 19086470930SIngo Molnar 1912dd6d8a1SAdrian Hunter static volatile int done; 1922dd6d8a1SAdrian Hunter static volatile int signr = -1; 1932dd6d8a1SAdrian Hunter static volatile int child_finished; 194c0bdc1c4SWang Nan 1952dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1965f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 1973c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger); 1982dd6d8a1SAdrian Hunter 1992dd6d8a1SAdrian Hunter static void sig_handler(int sig) 2002dd6d8a1SAdrian Hunter { 2012dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 2022dd6d8a1SAdrian Hunter child_finished = 1; 2032dd6d8a1SAdrian Hunter else 2042dd6d8a1SAdrian Hunter signr = sig; 2052dd6d8a1SAdrian Hunter 2062dd6d8a1SAdrian Hunter done = 1; 2072dd6d8a1SAdrian Hunter } 2082dd6d8a1SAdrian Hunter 2092dd6d8a1SAdrian Hunter static void record__sig_exit(void) 2102dd6d8a1SAdrian Hunter { 2112dd6d8a1SAdrian Hunter if (signr == -1) 2122dd6d8a1SAdrian Hunter return; 2132dd6d8a1SAdrian Hunter 2142dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 2152dd6d8a1SAdrian Hunter raise(signr); 2162dd6d8a1SAdrian Hunter } 2172dd6d8a1SAdrian Hunter 218e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 219e31f0d01SAdrian Hunter 220ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 221ef149c25SAdrian Hunter union perf_event *event, void *data1, 222ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 223ef149c25SAdrian Hunter { 224ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 22599fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 226ef149c25SAdrian Hunter size_t padding; 227ef149c25SAdrian Hunter u8 pad[8] = {0}; 228ef149c25SAdrian Hunter 22999fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 23099fa2984SAdrian Hunter off_t file_offset; 23199fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 23299fa2984SAdrian Hunter int err; 23399fa2984SAdrian Hunter 23499fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 23599fa2984SAdrian Hunter if (file_offset == -1) 23699fa2984SAdrian Hunter return -1; 23799fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 23899fa2984SAdrian Hunter event, file_offset); 23999fa2984SAdrian Hunter if (err) 24099fa2984SAdrian Hunter return err; 24199fa2984SAdrian Hunter } 24299fa2984SAdrian Hunter 243ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 244ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 245ef149c25SAdrian Hunter if (padding) 246ef149c25SAdrian Hunter padding = 8 - padding; 247ef149c25SAdrian Hunter 248ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 249ef149c25SAdrian Hunter record__write(rec, data1, len1); 250ef149c25SAdrian Hunter if (len2) 251ef149c25SAdrian Hunter record__write(rec, data2, len2); 252ef149c25SAdrian Hunter record__write(rec, &pad, padding); 253ef149c25SAdrian Hunter 254ef149c25SAdrian Hunter return 0; 255ef149c25SAdrian Hunter } 256ef149c25SAdrian Hunter 257ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 258ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 259ef149c25SAdrian Hunter { 260ef149c25SAdrian Hunter int ret; 261ef149c25SAdrian Hunter 262ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 263ef149c25SAdrian Hunter record__process_auxtrace); 264ef149c25SAdrian Hunter if (ret < 0) 265ef149c25SAdrian Hunter return ret; 266ef149c25SAdrian Hunter 267ef149c25SAdrian Hunter if (ret) 268ef149c25SAdrian Hunter rec->samples++; 269ef149c25SAdrian Hunter 270ef149c25SAdrian Hunter return 0; 271ef149c25SAdrian Hunter } 272ef149c25SAdrian Hunter 2732dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2742dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2752dd6d8a1SAdrian Hunter { 2762dd6d8a1SAdrian Hunter int ret; 2772dd6d8a1SAdrian Hunter 2782dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2792dd6d8a1SAdrian Hunter record__process_auxtrace, 2802dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2812dd6d8a1SAdrian Hunter if (ret < 0) 2822dd6d8a1SAdrian Hunter return ret; 2832dd6d8a1SAdrian Hunter 2842dd6d8a1SAdrian Hunter if (ret) 2852dd6d8a1SAdrian Hunter rec->samples++; 2862dd6d8a1SAdrian Hunter 2872dd6d8a1SAdrian Hunter return 0; 2882dd6d8a1SAdrian Hunter } 2892dd6d8a1SAdrian Hunter 2902dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2912dd6d8a1SAdrian Hunter { 2922dd6d8a1SAdrian Hunter int i; 2932dd6d8a1SAdrian Hunter int rc = 0; 2942dd6d8a1SAdrian Hunter 2952dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2962dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2972dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2982dd6d8a1SAdrian Hunter 2992dd6d8a1SAdrian Hunter if (!mm->base) 3002dd6d8a1SAdrian Hunter continue; 3012dd6d8a1SAdrian Hunter 3022dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 3032dd6d8a1SAdrian Hunter rc = -1; 3042dd6d8a1SAdrian Hunter goto out; 3052dd6d8a1SAdrian Hunter } 3062dd6d8a1SAdrian Hunter } 3072dd6d8a1SAdrian Hunter out: 3082dd6d8a1SAdrian Hunter return rc; 3092dd6d8a1SAdrian Hunter } 3102dd6d8a1SAdrian Hunter 3112dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 3122dd6d8a1SAdrian Hunter { 3132dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 3142dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 3155f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 3162dd6d8a1SAdrian Hunter } else { 3175f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 3185f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 3195f9cf599SWang Nan else 3205f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 3212dd6d8a1SAdrian Hunter } 3222dd6d8a1SAdrian Hunter } 3232dd6d8a1SAdrian Hunter 324e31f0d01SAdrian Hunter #else 325e31f0d01SAdrian Hunter 326e31f0d01SAdrian Hunter static inline 327e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 328e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 329e31f0d01SAdrian Hunter { 330e31f0d01SAdrian Hunter return 0; 331e31f0d01SAdrian Hunter } 332e31f0d01SAdrian Hunter 3332dd6d8a1SAdrian Hunter static inline 3342dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 3352dd6d8a1SAdrian Hunter { 3362dd6d8a1SAdrian Hunter } 3372dd6d8a1SAdrian Hunter 3382dd6d8a1SAdrian Hunter static inline 3392dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 3402dd6d8a1SAdrian Hunter { 3412dd6d8a1SAdrian Hunter return 0; 3422dd6d8a1SAdrian Hunter } 3432dd6d8a1SAdrian Hunter 344e31f0d01SAdrian Hunter #endif 345e31f0d01SAdrian Hunter 346cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 347cda57a8cSWang Nan struct perf_evlist *evlist) 348cda57a8cSWang Nan { 349cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 350cda57a8cSWang Nan char msg[512]; 351cda57a8cSWang Nan 352cda57a8cSWang Nan if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 353cda57a8cSWang Nan opts->auxtrace_mmap_pages, 354cda57a8cSWang Nan opts->auxtrace_snapshot_mode) < 0) { 355cda57a8cSWang Nan if (errno == EPERM) { 356cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 357cda57a8cSWang Nan "Consider increasing " 358cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 359cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 360cda57a8cSWang Nan "(current value: %u,%u)\n", 361cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 362cda57a8cSWang Nan return -errno; 363cda57a8cSWang Nan } else { 364cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 365c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 366cda57a8cSWang Nan if (errno) 367cda57a8cSWang Nan return -errno; 368cda57a8cSWang Nan else 369cda57a8cSWang Nan return -EINVAL; 370cda57a8cSWang Nan } 371cda57a8cSWang Nan } 372cda57a8cSWang Nan return 0; 373cda57a8cSWang Nan } 374cda57a8cSWang Nan 375cda57a8cSWang Nan static int record__mmap(struct record *rec) 376cda57a8cSWang Nan { 377cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 378cda57a8cSWang Nan } 379cda57a8cSWang Nan 3808c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 381dd7927f4SArnaldo Carvalho de Melo { 38256e52e85SArnaldo Carvalho de Melo char msg[512]; 3836a4bb04cSJiri Olsa struct perf_evsel *pos; 384d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 385d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 386b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 387*5d8bb1ecSMathieu Poirier struct perf_evsel_config_term *err_term; 3888d3eca20SDavid Ahern int rc = 0; 389dd7927f4SArnaldo Carvalho de Melo 390e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 391cac21425SJiri Olsa 392e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 3933da297a6SIngo Molnar try_again: 394d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 39556e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 3963da297a6SIngo Molnar if (verbose) 397c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 3983da297a6SIngo Molnar goto try_again; 3993da297a6SIngo Molnar } 400ca6a4258SDavid Ahern 40156e52e85SArnaldo Carvalho de Melo rc = -errno; 40256e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 40356e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 40456e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 4058d3eca20SDavid Ahern goto out; 4067c6a1c65SPeter Zijlstra } 4077c6a1c65SPeter Zijlstra } 4087c6a1c65SPeter Zijlstra 40923d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 41023d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 41123d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 412c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 4138d3eca20SDavid Ahern rc = -1; 4148d3eca20SDavid Ahern goto out; 4150a102479SFrederic Weisbecker } 4160a102479SFrederic Weisbecker 417*5d8bb1ecSMathieu Poirier if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) { 418*5d8bb1ecSMathieu Poirier error("failed to set config \"%s\" on event %s with %d (%s)\n", 419*5d8bb1ecSMathieu Poirier err_term->val.drv_cfg, perf_evsel__name(pos), errno, 420*5d8bb1ecSMathieu Poirier str_error_r(errno, msg, sizeof(msg))); 421*5d8bb1ecSMathieu Poirier rc = -1; 422*5d8bb1ecSMathieu Poirier goto out; 423*5d8bb1ecSMathieu Poirier } 424*5d8bb1ecSMathieu Poirier 425cda57a8cSWang Nan rc = record__mmap(rec); 426cda57a8cSWang Nan if (rc) 4278d3eca20SDavid Ahern goto out; 4280a27d7f9SArnaldo Carvalho de Melo 429a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 4307b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 4318d3eca20SDavid Ahern out: 4328d3eca20SDavid Ahern return rc; 433a91e5431SArnaldo Carvalho de Melo } 434a91e5431SArnaldo Carvalho de Melo 435e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 436e3d59112SNamhyung Kim union perf_event *event, 437e3d59112SNamhyung Kim struct perf_sample *sample, 438e3d59112SNamhyung Kim struct perf_evsel *evsel, 439e3d59112SNamhyung Kim struct machine *machine) 440e3d59112SNamhyung Kim { 441e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 442e3d59112SNamhyung Kim 443e3d59112SNamhyung Kim rec->samples++; 444e3d59112SNamhyung Kim 445e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 446e3d59112SNamhyung Kim } 447e3d59112SNamhyung Kim 4488c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 4496122e4e4SArnaldo Carvalho de Melo { 450f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 451f5fc1412SJiri Olsa struct perf_session *session = rec->session; 4526122e4e4SArnaldo Carvalho de Melo 453457ae94aSHe Kuang if (file->size == 0) 4549f591fd7SArnaldo Carvalho de Melo return 0; 4559f591fd7SArnaldo Carvalho de Melo 45600dc8657SNamhyung Kim /* 45700dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 45800dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 45900dc8657SNamhyung Kim * we prefer the vmlinux path like 46000dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 46100dc8657SNamhyung Kim * 46200dc8657SNamhyung Kim * rather than build-id path (in debug directory). 46300dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 46400dc8657SNamhyung Kim */ 46500dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 46600dc8657SNamhyung Kim 4676156681bSNamhyung Kim /* 4686156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 4696156681bSNamhyung Kim * so no need to process samples. 4706156681bSNamhyung Kim */ 4716156681bSNamhyung Kim if (rec->buildid_all) 4726156681bSNamhyung Kim rec->tool.sample = NULL; 4736156681bSNamhyung Kim 474b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 4756122e4e4SArnaldo Carvalho de Melo } 4766122e4e4SArnaldo Carvalho de Melo 4778115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 478a1645ce1SZhang, Yanmin { 479a1645ce1SZhang, Yanmin int err; 48045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 481a1645ce1SZhang, Yanmin /* 482a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 483a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 484a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 485a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 486a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 487a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 488a1645ce1SZhang, Yanmin */ 48945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 490743eb868SArnaldo Carvalho de Melo machine); 491a1645ce1SZhang, Yanmin if (err < 0) 492a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 49323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 494a1645ce1SZhang, Yanmin 495a1645ce1SZhang, Yanmin /* 496a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 497a1645ce1SZhang, Yanmin * have no _text sometimes. 498a1645ce1SZhang, Yanmin */ 49945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 5000ae617beSAdrian Hunter machine); 501a1645ce1SZhang, Yanmin if (err < 0) 502a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 50323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 504a1645ce1SZhang, Yanmin } 505a1645ce1SZhang, Yanmin 50698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 50798402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 50898402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 50998402807SFrederic Weisbecker }; 51098402807SFrederic Weisbecker 511a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 512a4ea0ec4SWang Nan bool backward) 51398402807SFrederic Weisbecker { 514dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 5150e2e63ddSPeter Zijlstra int i; 5168d3eca20SDavid Ahern int rc = 0; 517a4ea0ec4SWang Nan struct perf_mmap *maps; 51898402807SFrederic Weisbecker 519cb21686bSWang Nan if (!evlist) 520cb21686bSWang Nan return 0; 521ef149c25SAdrian Hunter 522b2cb615dSWang Nan maps = backward ? evlist->backward_mmap : evlist->mmap; 523a4ea0ec4SWang Nan if (!maps) 524a4ea0ec4SWang Nan return 0; 525cb21686bSWang Nan 52654cc54deSWang Nan if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 52754cc54deSWang Nan return 0; 52854cc54deSWang Nan 529a4ea0ec4SWang Nan for (i = 0; i < evlist->nr_mmaps; i++) { 530a4ea0ec4SWang Nan struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 531a4ea0ec4SWang Nan 532a4ea0ec4SWang Nan if (maps[i].base) { 533a4ea0ec4SWang Nan if (record__mmap_read(rec, &maps[i], 534a4ea0ec4SWang Nan evlist->overwrite, backward) != 0) { 5358d3eca20SDavid Ahern rc = -1; 5368d3eca20SDavid Ahern goto out; 5378d3eca20SDavid Ahern } 5388d3eca20SDavid Ahern } 539ef149c25SAdrian Hunter 5402dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 541ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 542ef149c25SAdrian Hunter rc = -1; 543ef149c25SAdrian Hunter goto out; 544ef149c25SAdrian Hunter } 54598402807SFrederic Weisbecker } 54698402807SFrederic Weisbecker 547dcabb507SJiri Olsa /* 548dcabb507SJiri Olsa * Mark the round finished in case we wrote 549dcabb507SJiri Olsa * at least one event. 550dcabb507SJiri Olsa */ 551dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 5528c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 5538d3eca20SDavid Ahern 55454cc54deSWang Nan if (backward) 55554cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 5568d3eca20SDavid Ahern out: 5578d3eca20SDavid Ahern return rc; 55898402807SFrederic Weisbecker } 55998402807SFrederic Weisbecker 560cb21686bSWang Nan static int record__mmap_read_all(struct record *rec) 561cb21686bSWang Nan { 562cb21686bSWang Nan int err; 563cb21686bSWang Nan 564a4ea0ec4SWang Nan err = record__mmap_read_evlist(rec, rec->evlist, false); 565cb21686bSWang Nan if (err) 566cb21686bSWang Nan return err; 567cb21686bSWang Nan 56805737464SWang Nan return record__mmap_read_evlist(rec, rec->evlist, true); 569cb21686bSWang Nan } 570cb21686bSWang Nan 5718c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 57257706abcSDavid Ahern { 57357706abcSDavid Ahern struct perf_session *session = rec->session; 57457706abcSDavid Ahern int feat; 57557706abcSDavid Ahern 57657706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 57757706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 57857706abcSDavid Ahern 57957706abcSDavid Ahern if (rec->no_buildid) 58057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 58157706abcSDavid Ahern 5823e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 58357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 58457706abcSDavid Ahern 58557706abcSDavid Ahern if (!rec->opts.branch_stack) 58657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 587ef149c25SAdrian Hunter 588ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 589ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 590ffa517adSJiri Olsa 591ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 59257706abcSDavid Ahern } 59357706abcSDavid Ahern 594e1ab48baSWang Nan static void 595e1ab48baSWang Nan record__finish_output(struct record *rec) 596e1ab48baSWang Nan { 597e1ab48baSWang Nan struct perf_data_file *file = &rec->file; 598e1ab48baSWang Nan int fd = perf_data_file__fd(file); 599e1ab48baSWang Nan 600e1ab48baSWang Nan if (file->is_pipe) 601e1ab48baSWang Nan return; 602e1ab48baSWang Nan 603e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 604e1ab48baSWang Nan file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 605e1ab48baSWang Nan 606e1ab48baSWang Nan if (!rec->no_buildid) { 607e1ab48baSWang Nan process_buildids(rec); 608e1ab48baSWang Nan 609e1ab48baSWang Nan if (rec->buildid_all) 610e1ab48baSWang Nan dsos__hit_all(rec->session); 611e1ab48baSWang Nan } 612e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 613e1ab48baSWang Nan 614e1ab48baSWang Nan return; 615e1ab48baSWang Nan } 616e1ab48baSWang Nan 6174ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 618be7b0c9eSWang Nan { 619be7b0c9eSWang Nan struct { 620be7b0c9eSWang Nan struct thread_map map; 621be7b0c9eSWang Nan struct thread_map_data map_data; 622be7b0c9eSWang Nan } thread_map; 623be7b0c9eSWang Nan 6244ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 6254ea648aeSWang Nan return 0; 6264ea648aeSWang Nan 627be7b0c9eSWang Nan thread_map.map.nr = 1; 628be7b0c9eSWang Nan thread_map.map.map[0].pid = rec->evlist->workload.pid; 629be7b0c9eSWang Nan thread_map.map.map[0].comm = NULL; 630be7b0c9eSWang Nan return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map, 631be7b0c9eSWang Nan process_synthesized_event, 632be7b0c9eSWang Nan &rec->session->machines.host, 633be7b0c9eSWang Nan rec->opts.sample_address, 634be7b0c9eSWang Nan rec->opts.proc_map_timeout); 635be7b0c9eSWang Nan } 636be7b0c9eSWang Nan 6374ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 6383c1cb7e3SWang Nan 639ecfd7a9cSWang Nan static int 640ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 641ecfd7a9cSWang Nan { 642ecfd7a9cSWang Nan struct perf_data_file *file = &rec->file; 643ecfd7a9cSWang Nan int fd, err; 644ecfd7a9cSWang Nan 645ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 646ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 647ecfd7a9cSWang Nan 6484ea648aeSWang Nan record__synthesize(rec, true); 6494ea648aeSWang Nan if (target__none(&rec->opts.target)) 6504ea648aeSWang Nan record__synthesize_workload(rec, true); 6514ea648aeSWang Nan 652ecfd7a9cSWang Nan rec->samples = 0; 653ecfd7a9cSWang Nan record__finish_output(rec); 654ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 655ecfd7a9cSWang Nan if (err) { 656ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 657ecfd7a9cSWang Nan return -EINVAL; 658ecfd7a9cSWang Nan } 659ecfd7a9cSWang Nan 660ecfd7a9cSWang Nan fd = perf_data_file__switch(file, timestamp, 661ecfd7a9cSWang Nan rec->session->header.data_offset, 662ecfd7a9cSWang Nan at_exit); 663ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 664ecfd7a9cSWang Nan rec->bytes_written = 0; 665ecfd7a9cSWang Nan rec->session->header.data_size = 0; 666ecfd7a9cSWang Nan } 667ecfd7a9cSWang Nan 668ecfd7a9cSWang Nan if (!quiet) 669ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 670ecfd7a9cSWang Nan file->path, timestamp); 6713c1cb7e3SWang Nan 6723c1cb7e3SWang Nan /* Output tracking events */ 673be7b0c9eSWang Nan if (!at_exit) { 6744ea648aeSWang Nan record__synthesize(rec, false); 6753c1cb7e3SWang Nan 676be7b0c9eSWang Nan /* 677be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 678be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 679be7b0c9eSWang Nan * generate tracking events because there's no thread_map 680be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 681be7b0c9eSWang Nan * contain map and comm information. 682be7b0c9eSWang Nan * Create a fake thread_map and directly call 683be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 684be7b0c9eSWang Nan */ 685be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 6864ea648aeSWang Nan record__synthesize_workload(rec, false); 687be7b0c9eSWang Nan } 688ecfd7a9cSWang Nan return fd; 689ecfd7a9cSWang Nan } 690ecfd7a9cSWang Nan 691f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 692f33cbe72SArnaldo Carvalho de Melo 693f33cbe72SArnaldo Carvalho de Melo /* 694f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 695f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 696f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 697f33cbe72SArnaldo Carvalho de Melo */ 69845604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 69945604710SNamhyung Kim siginfo_t *info, 700f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 701f33cbe72SArnaldo Carvalho de Melo { 702f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 703f33cbe72SArnaldo Carvalho de Melo done = 1; 704f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 705f33cbe72SArnaldo Carvalho de Melo } 706f33cbe72SArnaldo Carvalho de Melo 7072dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 7082dd6d8a1SAdrian Hunter 70946bc29b9SAdrian Hunter int __weak 71046bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 71146bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 71246bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 71346bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 71446bc29b9SAdrian Hunter { 71546bc29b9SAdrian Hunter return 0; 71646bc29b9SAdrian Hunter } 71746bc29b9SAdrian Hunter 718ee667f94SWang Nan static const struct perf_event_mmap_page * 719ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist) 720ee667f94SWang Nan { 721b2cb615dSWang Nan if (evlist) { 722b2cb615dSWang Nan if (evlist->mmap && evlist->mmap[0].base) 723ee667f94SWang Nan return evlist->mmap[0].base; 724b2cb615dSWang Nan if (evlist->backward_mmap && evlist->backward_mmap[0].base) 725b2cb615dSWang Nan return evlist->backward_mmap[0].base; 726b2cb615dSWang Nan } 727ee667f94SWang Nan return NULL; 728ee667f94SWang Nan } 729ee667f94SWang Nan 730c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 731c45628b0SWang Nan { 732ee667f94SWang Nan const struct perf_event_mmap_page *pc; 733ee667f94SWang Nan 734ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 735ee667f94SWang Nan if (pc) 736ee667f94SWang Nan return pc; 737c45628b0SWang Nan return NULL; 738c45628b0SWang Nan } 739c45628b0SWang Nan 7404ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 741c45c86ebSWang Nan { 742c45c86ebSWang Nan struct perf_session *session = rec->session; 743c45c86ebSWang Nan struct machine *machine = &session->machines.host; 744c45c86ebSWang Nan struct perf_data_file *file = &rec->file; 745c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 746c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 747c45c86ebSWang Nan int fd = perf_data_file__fd(file); 748c45c86ebSWang Nan int err = 0; 749c45c86ebSWang Nan 7504ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 7514ea648aeSWang Nan return 0; 7524ea648aeSWang Nan 753c45c86ebSWang Nan if (file->is_pipe) { 754c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 755c45c86ebSWang Nan process_synthesized_event); 756c45c86ebSWang Nan if (err < 0) { 757c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 758c45c86ebSWang Nan goto out; 759c45c86ebSWang Nan } 760c45c86ebSWang Nan 761c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 762c45c86ebSWang Nan /* 763c45c86ebSWang Nan * FIXME err <= 0 here actually means that 764c45c86ebSWang Nan * there were no tracepoints so its not really 765c45c86ebSWang Nan * an error, just that we don't need to 766c45c86ebSWang Nan * synthesize anything. We really have to 767c45c86ebSWang Nan * return this more properly and also 768c45c86ebSWang Nan * propagate errors that now are calling die() 769c45c86ebSWang Nan */ 770c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 771c45c86ebSWang Nan process_synthesized_event); 772c45c86ebSWang Nan if (err <= 0) { 773c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 774c45c86ebSWang Nan goto out; 775c45c86ebSWang Nan } 776c45c86ebSWang Nan rec->bytes_written += err; 777c45c86ebSWang Nan } 778c45c86ebSWang Nan } 779c45c86ebSWang Nan 780c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 78146bc29b9SAdrian Hunter process_synthesized_event, machine); 78246bc29b9SAdrian Hunter if (err) 78346bc29b9SAdrian Hunter goto out; 78446bc29b9SAdrian Hunter 785c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 786c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 787c45c86ebSWang Nan session, process_synthesized_event); 788c45c86ebSWang Nan if (err) 789c45c86ebSWang Nan goto out; 790c45c86ebSWang Nan } 791c45c86ebSWang Nan 792c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 793c45c86ebSWang Nan machine); 794c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 795c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 796c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 797c45c86ebSWang Nan 798c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 799c45c86ebSWang Nan machine); 800c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 801c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 802c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 803c45c86ebSWang Nan 804c45c86ebSWang Nan if (perf_guest) { 805c45c86ebSWang Nan machines__process_guests(&session->machines, 806c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 807c45c86ebSWang Nan } 808c45c86ebSWang Nan 809c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 810c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 811c45c86ebSWang Nan opts->proc_map_timeout); 812c45c86ebSWang Nan out: 813c45c86ebSWang Nan return err; 814c45c86ebSWang Nan } 815c45c86ebSWang Nan 8168c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 81786470930SIngo Molnar { 81857706abcSDavid Ahern int err; 81945604710SNamhyung Kim int status = 0; 8208b412664SPeter Zijlstra unsigned long waking = 0; 82146be604bSZhang, Yanmin const bool forks = argc > 0; 82223346f21SArnaldo Carvalho de Melo struct machine *machine; 82345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 824b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 825f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 826d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 8276dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 82842aa276fSNamhyung Kim int fd; 82986470930SIngo Molnar 830d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 83133e49ea7SAndi Kleen 83245604710SNamhyung Kim atexit(record__sig_exit); 833f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 834f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 835804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 836c0bdc1c4SWang Nan 8373c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) { 8382dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 8393c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 8405f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 8413c1cb7e3SWang Nan if (rec->switch_output) 8423c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 843c0bdc1c4SWang Nan } else { 8442dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 845c0bdc1c4SWang Nan } 846f5970550SPeter Zijlstra 847b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 84894c744b6SArnaldo Carvalho de Melo if (session == NULL) { 849ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 850a9a70bbcSArnaldo Carvalho de Melo return -1; 851a9a70bbcSArnaldo Carvalho de Melo } 852a9a70bbcSArnaldo Carvalho de Melo 85342aa276fSNamhyung Kim fd = perf_data_file__fd(file); 854d20deb64SArnaldo Carvalho de Melo rec->session = session; 855d20deb64SArnaldo Carvalho de Melo 8568c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 857330aa675SStephane Eranian 858d4db3f16SArnaldo Carvalho de Melo if (forks) { 8593e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 860f5fc1412SJiri Olsa argv, file->is_pipe, 861735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 86235b9d88eSArnaldo Carvalho de Melo if (err < 0) { 86335b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 86445604710SNamhyung Kim status = err; 86535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 866856e9660SPeter Zijlstra } 867856e9660SPeter Zijlstra } 868856e9660SPeter Zijlstra 8698c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 8708d3eca20SDavid Ahern err = -1; 87145604710SNamhyung Kim goto out_child; 8728d3eca20SDavid Ahern } 87386470930SIngo Molnar 8748690a2a7SWang Nan err = bpf__apply_obj_config(); 8758690a2a7SWang Nan if (err) { 8768690a2a7SWang Nan char errbuf[BUFSIZ]; 8778690a2a7SWang Nan 8788690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 8798690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 8808690a2a7SWang Nan errbuf); 8818690a2a7SWang Nan goto out_child; 8828690a2a7SWang Nan } 8838690a2a7SWang Nan 884cca8482cSAdrian Hunter /* 885cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 886cca8482cSAdrian Hunter * evlist. 887cca8482cSAdrian Hunter */ 888cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 889cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 890cca8482cSAdrian Hunter rec->tool.ordered_events = false; 891cca8482cSAdrian Hunter } 892cca8482cSAdrian Hunter 8933e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 894a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 895a8bb559bSNamhyung Kim 896f5fc1412SJiri Olsa if (file->is_pipe) { 89742aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 898529870e3STom Zanussi if (err < 0) 89945604710SNamhyung Kim goto out_child; 900563aecb2SJiri Olsa } else { 90142aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 902d5eed904SArnaldo Carvalho de Melo if (err < 0) 90345604710SNamhyung Kim goto out_child; 904d5eed904SArnaldo Carvalho de Melo } 9057c6a1c65SPeter Zijlstra 906d3665498SDavid Ahern if (!rec->no_buildid 907e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 908d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 909e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 9108d3eca20SDavid Ahern err = -1; 91145604710SNamhyung Kim goto out_child; 912e20960c0SRobert Richter } 913e20960c0SRobert Richter 91434ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 915743eb868SArnaldo Carvalho de Melo 9164ea648aeSWang Nan err = record__synthesize(rec, false); 917c45c86ebSWang Nan if (err < 0) 91845604710SNamhyung Kim goto out_child; 9198d3eca20SDavid Ahern 920d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 92186470930SIngo Molnar struct sched_param param; 92286470930SIngo Molnar 923d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 92486470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 9256beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 9268d3eca20SDavid Ahern err = -1; 92745604710SNamhyung Kim goto out_child; 92886470930SIngo Molnar } 92986470930SIngo Molnar } 93086470930SIngo Molnar 931774cb499SJiri Olsa /* 932774cb499SJiri Olsa * When perf is starting the traced process, all the events 933774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 934774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 935774cb499SJiri Olsa */ 9366619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 9373e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 938764e16a3SDavid Ahern 939856e9660SPeter Zijlstra /* 940856e9660SPeter Zijlstra * Let the child rip 941856e9660SPeter Zijlstra */ 942e803cf97SNamhyung Kim if (forks) { 943e5bed564SNamhyung Kim union perf_event *event; 944e5bed564SNamhyung Kim 945e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 946e5bed564SNamhyung Kim if (event == NULL) { 947e5bed564SNamhyung Kim err = -ENOMEM; 948e5bed564SNamhyung Kim goto out_child; 949e5bed564SNamhyung Kim } 950e5bed564SNamhyung Kim 951e803cf97SNamhyung Kim /* 952e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 953e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 954e803cf97SNamhyung Kim * cannot see a correct process name for those events. 955e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 956e803cf97SNamhyung Kim */ 957e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 958e803cf97SNamhyung Kim rec->evlist->workload.pid, 959e803cf97SNamhyung Kim process_synthesized_event, 960e803cf97SNamhyung Kim machine); 961e5bed564SNamhyung Kim free(event); 962e803cf97SNamhyung Kim 9633e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 964e803cf97SNamhyung Kim } 965856e9660SPeter Zijlstra 9666619a53eSAndi Kleen if (opts->initial_delay) { 9670693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 9686619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 9696619a53eSAndi Kleen } 9706619a53eSAndi Kleen 9715f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 9723c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 973649c48a9SPeter Zijlstra for (;;) { 9749f065194SYang Shi unsigned long long hits = rec->samples; 97586470930SIngo Molnar 97605737464SWang Nan /* 97705737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 97805737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 97905737464SWang Nan * hits != rec->samples in previous round. 98005737464SWang Nan * 98105737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 98205737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 98305737464SWang Nan */ 98405737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 98505737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 98605737464SWang Nan 9878c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 9885f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 9893c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 9908d3eca20SDavid Ahern err = -1; 99145604710SNamhyung Kim goto out_child; 9928d3eca20SDavid Ahern } 99386470930SIngo Molnar 9942dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 9952dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 9965f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 9972dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 9985f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 9992dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 10002dd6d8a1SAdrian Hunter err = -1; 10012dd6d8a1SAdrian Hunter goto out_child; 10022dd6d8a1SAdrian Hunter } 10032dd6d8a1SAdrian Hunter } 10042dd6d8a1SAdrian Hunter 10053c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 100605737464SWang Nan /* 100705737464SWang Nan * If switch_output_trigger is hit, the data in 100805737464SWang Nan * overwritable ring buffer should have been collected, 100905737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 101005737464SWang Nan * 101105737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 101205737464SWang Nan * record__mmap_read_all() didn't collect data from 101305737464SWang Nan * overwritable ring buffer. Read again. 101405737464SWang Nan */ 101505737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 101605737464SWang Nan continue; 10173c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 10183c1cb7e3SWang Nan 101905737464SWang Nan /* 102005737464SWang Nan * Reenable events in overwrite ring buffer after 102105737464SWang Nan * record__mmap_read_all(): we should have collected 102205737464SWang Nan * data from it. 102305737464SWang Nan */ 102405737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 102505737464SWang Nan 10263c1cb7e3SWang Nan if (!quiet) 10273c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 10283c1cb7e3SWang Nan waking); 10293c1cb7e3SWang Nan waking = 0; 10303c1cb7e3SWang Nan fd = record__switch_output(rec, false); 10313c1cb7e3SWang Nan if (fd < 0) { 10323c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 10333c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 10343c1cb7e3SWang Nan err = fd; 10353c1cb7e3SWang Nan goto out_child; 10363c1cb7e3SWang Nan } 10373c1cb7e3SWang Nan } 10383c1cb7e3SWang Nan 1039d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 10406dcf45efSArnaldo Carvalho de Melo if (done || draining) 1041649c48a9SPeter Zijlstra break; 1042f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 1043a515114fSJiri Olsa /* 1044a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1045a515114fSJiri Olsa * number of returned events and interrupt error. 1046a515114fSJiri Olsa */ 1047a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 104845604710SNamhyung Kim err = 0; 10498b412664SPeter Zijlstra waking++; 10506dcf45efSArnaldo Carvalho de Melo 10516dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 10526dcf45efSArnaldo Carvalho de Melo draining = true; 10538b412664SPeter Zijlstra } 10548b412664SPeter Zijlstra 1055774cb499SJiri Olsa /* 1056774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1057774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1058774cb499SJiri Olsa * disable events in this case. 1059774cb499SJiri Olsa */ 1060602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 10615f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 10623e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 10632711926aSJiri Olsa disabled = true; 10642711926aSJiri Olsa } 10658b412664SPeter Zijlstra } 10665f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 10673c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 10688b412664SPeter Zijlstra 1069f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 107035550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1071c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1072f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1073f33cbe72SArnaldo Carvalho de Melo err = -1; 107445604710SNamhyung Kim goto out_child; 1075f33cbe72SArnaldo Carvalho de Melo } 1076f33cbe72SArnaldo Carvalho de Melo 1077e3d59112SNamhyung Kim if (!quiet) 10788b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 107986470930SIngo Molnar 10804ea648aeSWang Nan if (target__none(&rec->opts.target)) 10814ea648aeSWang Nan record__synthesize_workload(rec, true); 10824ea648aeSWang Nan 108345604710SNamhyung Kim out_child: 108445604710SNamhyung Kim if (forks) { 108545604710SNamhyung Kim int exit_status; 108645604710SNamhyung Kim 108745604710SNamhyung Kim if (!child_finished) 108845604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 108945604710SNamhyung Kim 109045604710SNamhyung Kim wait(&exit_status); 109145604710SNamhyung Kim 109245604710SNamhyung Kim if (err < 0) 109345604710SNamhyung Kim status = err; 109445604710SNamhyung Kim else if (WIFEXITED(exit_status)) 109545604710SNamhyung Kim status = WEXITSTATUS(exit_status); 109645604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 109745604710SNamhyung Kim signr = WTERMSIG(exit_status); 109845604710SNamhyung Kim } else 109945604710SNamhyung Kim status = err; 110045604710SNamhyung Kim 11014ea648aeSWang Nan record__synthesize(rec, true); 1102e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1103e3d59112SNamhyung Kim rec->samples = 0; 1104e3d59112SNamhyung Kim 1105ecfd7a9cSWang Nan if (!err) { 1106ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1107e1ab48baSWang Nan record__finish_output(rec); 1108ecfd7a9cSWang Nan } else { 1109ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1110ecfd7a9cSWang Nan if (fd < 0) { 1111ecfd7a9cSWang Nan status = fd; 1112ecfd7a9cSWang Nan goto out_delete_session; 1113ecfd7a9cSWang Nan } 1114ecfd7a9cSWang Nan } 1115ecfd7a9cSWang Nan } 111639d17dacSArnaldo Carvalho de Melo 1117e3d59112SNamhyung Kim if (!err && !quiet) { 1118e3d59112SNamhyung Kim char samples[128]; 1119ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1120ecfd7a9cSWang Nan ".<timestamp>" : ""; 1121e3d59112SNamhyung Kim 1122ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1123e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1124e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1125e3d59112SNamhyung Kim else 1126e3d59112SNamhyung Kim samples[0] = '\0'; 1127e3d59112SNamhyung Kim 1128ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1129e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 1130ecfd7a9cSWang Nan file->path, postfix, samples); 1131e3d59112SNamhyung Kim } 1132e3d59112SNamhyung Kim 113339d17dacSArnaldo Carvalho de Melo out_delete_session: 113439d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 113545604710SNamhyung Kim return status; 113686470930SIngo Molnar } 113786470930SIngo Molnar 11380883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 113909b0fd45SJiri Olsa { 1140aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1141a601fdffSJiri Olsa 11420883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 114326d33022SJiri Olsa 11440883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 114509b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 11460883e820SArnaldo Carvalho de Melo callchain->dump_size); 11470883e820SArnaldo Carvalho de Melo } 11480883e820SArnaldo Carvalho de Melo 11490883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 11500883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 11510883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 11520883e820SArnaldo Carvalho de Melo { 11530883e820SArnaldo Carvalho de Melo int ret; 11540883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 11550883e820SArnaldo Carvalho de Melo 11560883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 11570883e820SArnaldo Carvalho de Melo if (unset) { 11580883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 11590883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 11600883e820SArnaldo Carvalho de Melo return 0; 11610883e820SArnaldo Carvalho de Melo } 11620883e820SArnaldo Carvalho de Melo 11630883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 11640883e820SArnaldo Carvalho de Melo if (!ret) { 11650883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 11660883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 11670883e820SArnaldo Carvalho de Melo record->sample_address = true; 11680883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 11690883e820SArnaldo Carvalho de Melo } 11700883e820SArnaldo Carvalho de Melo 11710883e820SArnaldo Carvalho de Melo return ret; 117209b0fd45SJiri Olsa } 117309b0fd45SJiri Olsa 1174c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 117509b0fd45SJiri Olsa const char *arg, 117609b0fd45SJiri Olsa int unset) 117709b0fd45SJiri Olsa { 11780883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 117926d33022SJiri Olsa } 118026d33022SJiri Olsa 1181c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 118209b0fd45SJiri Olsa const char *arg __maybe_unused, 118309b0fd45SJiri Olsa int unset __maybe_unused) 118409b0fd45SJiri Olsa { 11852ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1186c421e80bSKan Liang 11872ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 118809b0fd45SJiri Olsa 11892ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 11902ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1191eb853e80SJiri Olsa 11922ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 119309b0fd45SJiri Olsa return 0; 119409b0fd45SJiri Olsa } 119509b0fd45SJiri Olsa 1196eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1197eb853e80SJiri Olsa { 11987a29c087SNamhyung Kim struct record *rec = cb; 11997a29c087SNamhyung Kim 12007a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 12017a29c087SNamhyung Kim if (!strcmp(value, "cache")) 12027a29c087SNamhyung Kim rec->no_buildid_cache = false; 12037a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 12047a29c087SNamhyung Kim rec->no_buildid_cache = true; 12057a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 12067a29c087SNamhyung Kim rec->no_buildid = true; 12077a29c087SNamhyung Kim else 12087a29c087SNamhyung Kim return -1; 12097a29c087SNamhyung Kim return 0; 12107a29c087SNamhyung Kim } 1211eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 12125a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 1213eb853e80SJiri Olsa 1214eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1215eb853e80SJiri Olsa } 1216eb853e80SJiri Olsa 1217814c8c38SPeter Zijlstra struct clockid_map { 1218814c8c38SPeter Zijlstra const char *name; 1219814c8c38SPeter Zijlstra int clockid; 1220814c8c38SPeter Zijlstra }; 1221814c8c38SPeter Zijlstra 1222814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1223814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1224814c8c38SPeter Zijlstra 1225814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1226814c8c38SPeter Zijlstra 1227814c8c38SPeter Zijlstra 1228814c8c38SPeter Zijlstra /* 1229814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1230814c8c38SPeter Zijlstra */ 1231814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1232814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1233814c8c38SPeter Zijlstra #endif 1234814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1235814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1236814c8c38SPeter Zijlstra #endif 1237814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1238814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1239814c8c38SPeter Zijlstra #endif 1240814c8c38SPeter Zijlstra 1241814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1242814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1243814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1244814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1245814c8c38SPeter Zijlstra 1246814c8c38SPeter Zijlstra /* available for some events */ 1247814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1248814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1249814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1250814c8c38SPeter Zijlstra 1251814c8c38SPeter Zijlstra /* available for the lazy */ 1252814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1253814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1254814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1255814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1256814c8c38SPeter Zijlstra 1257814c8c38SPeter Zijlstra CLOCKID_END, 1258814c8c38SPeter Zijlstra }; 1259814c8c38SPeter Zijlstra 1260814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1261814c8c38SPeter Zijlstra { 1262814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1263814c8c38SPeter Zijlstra const struct clockid_map *cm; 1264814c8c38SPeter Zijlstra const char *ostr = str; 1265814c8c38SPeter Zijlstra 1266814c8c38SPeter Zijlstra if (unset) { 1267814c8c38SPeter Zijlstra opts->use_clockid = 0; 1268814c8c38SPeter Zijlstra return 0; 1269814c8c38SPeter Zijlstra } 1270814c8c38SPeter Zijlstra 1271814c8c38SPeter Zijlstra /* no arg passed */ 1272814c8c38SPeter Zijlstra if (!str) 1273814c8c38SPeter Zijlstra return 0; 1274814c8c38SPeter Zijlstra 1275814c8c38SPeter Zijlstra /* no setting it twice */ 1276814c8c38SPeter Zijlstra if (opts->use_clockid) 1277814c8c38SPeter Zijlstra return -1; 1278814c8c38SPeter Zijlstra 1279814c8c38SPeter Zijlstra opts->use_clockid = true; 1280814c8c38SPeter Zijlstra 1281814c8c38SPeter Zijlstra /* if its a number, we're done */ 1282814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1283814c8c38SPeter Zijlstra return 0; 1284814c8c38SPeter Zijlstra 1285814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1286814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1287814c8c38SPeter Zijlstra str += 6; 1288814c8c38SPeter Zijlstra 1289814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1290814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1291814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1292814c8c38SPeter Zijlstra return 0; 1293814c8c38SPeter Zijlstra } 1294814c8c38SPeter Zijlstra } 1295814c8c38SPeter Zijlstra 1296814c8c38SPeter Zijlstra opts->use_clockid = false; 1297814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1298814c8c38SPeter Zijlstra return -1; 1299814c8c38SPeter Zijlstra } 1300814c8c38SPeter Zijlstra 1301e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1302e9db1310SAdrian Hunter const char *str, 1303e9db1310SAdrian Hunter int unset __maybe_unused) 1304e9db1310SAdrian Hunter { 1305e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1306e9db1310SAdrian Hunter char *s, *p; 1307e9db1310SAdrian Hunter unsigned int mmap_pages; 1308e9db1310SAdrian Hunter int ret; 1309e9db1310SAdrian Hunter 1310e9db1310SAdrian Hunter if (!str) 1311e9db1310SAdrian Hunter return -EINVAL; 1312e9db1310SAdrian Hunter 1313e9db1310SAdrian Hunter s = strdup(str); 1314e9db1310SAdrian Hunter if (!s) 1315e9db1310SAdrian Hunter return -ENOMEM; 1316e9db1310SAdrian Hunter 1317e9db1310SAdrian Hunter p = strchr(s, ','); 1318e9db1310SAdrian Hunter if (p) 1319e9db1310SAdrian Hunter *p = '\0'; 1320e9db1310SAdrian Hunter 1321e9db1310SAdrian Hunter if (*s) { 1322e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1323e9db1310SAdrian Hunter if (ret) 1324e9db1310SAdrian Hunter goto out_free; 1325e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1326e9db1310SAdrian Hunter } 1327e9db1310SAdrian Hunter 1328e9db1310SAdrian Hunter if (!p) { 1329e9db1310SAdrian Hunter ret = 0; 1330e9db1310SAdrian Hunter goto out_free; 1331e9db1310SAdrian Hunter } 1332e9db1310SAdrian Hunter 1333e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1334e9db1310SAdrian Hunter if (ret) 1335e9db1310SAdrian Hunter goto out_free; 1336e9db1310SAdrian Hunter 1337e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1338e9db1310SAdrian Hunter 1339e9db1310SAdrian Hunter out_free: 1340e9db1310SAdrian Hunter free(s); 1341e9db1310SAdrian Hunter return ret; 1342e9db1310SAdrian Hunter } 1343e9db1310SAdrian Hunter 1344e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 134586470930SIngo Molnar "perf record [<options>] [<command>]", 134686470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 134786470930SIngo Molnar NULL 134886470930SIngo Molnar }; 1349e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 135086470930SIngo Molnar 1351d20deb64SArnaldo Carvalho de Melo /* 13528c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 13538c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1354d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1355d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1356d20deb64SArnaldo Carvalho de Melo * 1357d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1358d20deb64SArnaldo Carvalho de Melo * 1359d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1360d20deb64SArnaldo Carvalho de Melo */ 13618c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1362d20deb64SArnaldo Carvalho de Melo .opts = { 13638affc2b8SAndi Kleen .sample_time = true, 1364d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1365d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1366d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1367447a6013SArnaldo Carvalho de Melo .freq = 4000, 1368d1cb9fceSNamhyung Kim .target = { 1369d1cb9fceSNamhyung Kim .uses_mmap = true, 13703aa5939dSAdrian Hunter .default_per_cpu = true, 1371d1cb9fceSNamhyung Kim }, 13729d9cad76SKan Liang .proc_map_timeout = 500, 1373d20deb64SArnaldo Carvalho de Melo }, 1374e3d59112SNamhyung Kim .tool = { 1375e3d59112SNamhyung Kim .sample = process_sample_event, 1376e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1377cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1378e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1379e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1380e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1381cca8482cSAdrian Hunter .ordered_events = true, 1382e3d59112SNamhyung Kim }, 1383d20deb64SArnaldo Carvalho de Melo }; 13847865e817SFrederic Weisbecker 138576a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 138676a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 138761eaa3beSArnaldo Carvalho de Melo 13880aab2136SWang Nan static bool dry_run; 13890aab2136SWang Nan 1390d20deb64SArnaldo Carvalho de Melo /* 1391d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1392d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1393b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1394d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1395d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1396d20deb64SArnaldo Carvalho de Melo */ 1397e5b2c207SNamhyung Kim struct option __record_options[] = { 1398d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 139986470930SIngo Molnar "event selector. use 'perf list' to list available events", 1400f120f9d5SJiri Olsa parse_events_option), 1401d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1402c171b552SLi Zefan "event filter", parse_filter), 14034ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 14044ba1faa1SWang Nan NULL, "don't record events from perf itself", 14054ba1faa1SWang Nan exclude_perf), 1406bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1407d6d901c2SZhang, Yanmin "record events on existing process id"), 1408bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1409d6d901c2SZhang, Yanmin "record events on existing thread id"), 1410d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 141186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1412509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1413acac03faSKirill Smelkov "collect data without buffering"), 1414d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1415daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1416bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 141786470930SIngo Molnar "system-wide collection from all CPUs"), 1418bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1419c45c6ea2SStephane Eranian "list of cpus to monitor"), 1420d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1421f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 142286470930SIngo Molnar "output file name"), 142369e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 142469e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 14252e6cdf99SStephane Eranian "child tasks do not inherit counters"), 14264ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 14274ea648aeSWang Nan "synthesize non-sample events at the end of output"), 1428626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1429d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1430e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1431e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1432e9db1310SAdrian Hunter record__parse_mmap_pages), 1433d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 143443bece79SLin Ming "put the counters into a counter group"), 14352ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 143609b0fd45SJiri Olsa NULL, "enables call-graph recording" , 143709b0fd45SJiri Olsa &record_callchain_opt), 143809b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 143976a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 144009b0fd45SJiri Olsa &record_parse_callchain_opt), 1441c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 14423da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1443b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1444d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1445649c48a9SPeter Zijlstra "per thread counts"), 144656100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1447b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 14483abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 14493abebc55SAdrian Hunter &record.opts.sample_time_set, 14503abebc55SAdrian Hunter "Record the sample timestamps"), 145156100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1452d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1453649c48a9SPeter Zijlstra "don't sample"), 1454d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1455d2db9a98SWang Nan &record.no_buildid_cache_set, 1456a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1457d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1458d2db9a98SWang Nan &record.no_buildid_set, 1459baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1460d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1461023695d9SStephane Eranian "monitor event in cgroup name only", 1462023695d9SStephane Eranian parse_cgroups), 1463a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 14646619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1465bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1466bea03405SNamhyung Kim "user to profile"), 1467a5aabdacSStephane Eranian 1468a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1469a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1470a5aabdacSStephane Eranian parse_branch_stack), 1471a5aabdacSStephane Eranian 1472a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1473a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1474bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 147505484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 147605484298SAndi Kleen "sample by weight (on special events only)"), 1477475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1478475eeab9SAndi Kleen "sample transaction flags (special events only)"), 14793aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 14803aa5939dSAdrian Hunter "use per-thread mmaps"), 1481bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1482bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1483bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 148485c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 148585c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1486814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1487814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1488814c8c38SPeter Zijlstra parse_clockid), 14892dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 14902dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 14919d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 14929d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1493b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1494b757bb09SAdrian Hunter "Record context switch events"), 149585723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 149685723885SJiri Olsa "Configure all used events to run in kernel space.", 149785723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 149885723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 149985723885SJiri Olsa "Configure all used events to run in user space.", 150085723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 150171dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 150271dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 150371dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 150471dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 15057efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 15067efe0e03SHe Kuang "file", "vmlinux pathname"), 15076156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 15086156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1509ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1510ecfd7a9cSWang Nan "append timestamp to output filename"), 15113c1cb7e3SWang Nan OPT_BOOLEAN(0, "switch-output", &record.switch_output, 15123c1cb7e3SWang Nan "Switch output when receive SIGUSR2"), 15130aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 15140aab2136SWang Nan "Parse options then exit"), 151586470930SIngo Molnar OPT_END() 151686470930SIngo Molnar }; 151786470930SIngo Molnar 1518e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1519e5b2c207SNamhyung Kim 15201d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 152186470930SIngo Molnar { 1522ef149c25SAdrian Hunter int err; 15238c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 152416ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 152586470930SIngo Molnar 152648e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 152748e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 152848e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 152948e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 153048e1cab1SWang Nan # undef set_nobuild 153148e1cab1SWang Nan #endif 153248e1cab1SWang Nan 15337efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 15347efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 15357efe0e03SHe Kuang # define REASON "NO_DWARF=1" 15367efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 15377efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 15387efe0e03SHe Kuang # else 15397efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 15407efe0e03SHe Kuang # endif 15417efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 15427efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 15437efe0e03SHe Kuang # undef set_nobuild 15447efe0e03SHe Kuang # undef REASON 15457efe0e03SHe Kuang #endif 15467efe0e03SHe Kuang 15473e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 15483e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1549361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1550361c99a6SArnaldo Carvalho de Melo 1551eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1552eb853e80SJiri Olsa 1553bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1554a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1555602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1556bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 155786470930SIngo Molnar 1558bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1559c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1560c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1561c7118369SNamhyung Kim 1562023695d9SStephane Eranian } 1563b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1564b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1565c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1566c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1567c7118369SNamhyung Kim return -EINVAL; 1568b757bb09SAdrian Hunter } 1569023695d9SStephane Eranian 1570eca857abSWang Nan if (rec->switch_output) 1571eca857abSWang Nan rec->timestamp_filename = true; 1572eca857abSWang Nan 1573ef149c25SAdrian Hunter if (!rec->itr) { 1574ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1575ef149c25SAdrian Hunter if (err) 1576ef149c25SAdrian Hunter return err; 1577ef149c25SAdrian Hunter } 1578ef149c25SAdrian Hunter 15792dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 15802dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 15812dd6d8a1SAdrian Hunter if (err) 15822dd6d8a1SAdrian Hunter return err; 15832dd6d8a1SAdrian Hunter 15840aab2136SWang Nan if (dry_run) 15850aab2136SWang Nan return 0; 15860aab2136SWang Nan 1587d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 1588d7888573SWang Nan if (err) { 1589d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1590d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 1591d7888573SWang Nan errbuf); 1592d7888573SWang Nan return err; 1593d7888573SWang Nan } 1594d7888573SWang Nan 1595ef149c25SAdrian Hunter err = -ENOMEM; 1596ef149c25SAdrian Hunter 15970a7e6d1bSNamhyung Kim symbol__init(NULL); 1598baa2f6ceSArnaldo Carvalho de Melo 1599ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1600646aaea6SArnaldo Carvalho de Melo pr_warning( 1601646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1602ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1603646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1604646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1605646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1606646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1607646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1608ec80fde7SArnaldo Carvalho de Melo 16090c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 1610a1ac1d3cSStephane Eranian disable_buildid_cache(); 16110c1d46a8SWang Nan } else if (rec->switch_output) { 16120c1d46a8SWang Nan /* 16130c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 16140c1d46a8SWang Nan * generation by default to reduce data file switching 16150c1d46a8SWang Nan * overhead. Still generate buildid if they are required 16160c1d46a8SWang Nan * explicitly using 16170c1d46a8SWang Nan * 16180c1d46a8SWang Nan * perf record --signal-trigger --no-no-buildid \ 16190c1d46a8SWang Nan * --no-no-buildid-cache 16200c1d46a8SWang Nan * 16210c1d46a8SWang Nan * Following code equals to: 16220c1d46a8SWang Nan * 16230c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 16240c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 16250c1d46a8SWang Nan * disable_buildid_cache(); 16260c1d46a8SWang Nan */ 16270c1d46a8SWang Nan bool disable = true; 16280c1d46a8SWang Nan 16290c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 16300c1d46a8SWang Nan disable = false; 16310c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 16320c1d46a8SWang Nan disable = false; 16330c1d46a8SWang Nan if (disable) { 16340c1d46a8SWang Nan rec->no_buildid = true; 16350c1d46a8SWang Nan rec->no_buildid_cache = true; 16360c1d46a8SWang Nan disable_buildid_cache(); 16370c1d46a8SWang Nan } 16380c1d46a8SWang Nan } 1639655000e7SArnaldo Carvalho de Melo 16404ea648aeSWang Nan if (record.opts.overwrite) 16414ea648aeSWang Nan record.opts.tail_synthesize = true; 16424ea648aeSWang Nan 16433e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 16443e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 164569aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 164669aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1647bbd36e5eSPeter Zijlstra } 164886470930SIngo Molnar 164969e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 165069e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 165169e7e5b0SAdrian Hunter 1652602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 165316ad2ffbSNamhyung Kim if (err) { 1654602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 165516ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 165616ad2ffbSNamhyung Kim } 16574bd0f2d2SNamhyung Kim 1658602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 165916ad2ffbSNamhyung Kim if (err) { 166016ad2ffbSNamhyung Kim int saved_errno = errno; 166116ad2ffbSNamhyung Kim 1662602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 16633780f488SNamhyung Kim ui__error("%s", errbuf); 166416ad2ffbSNamhyung Kim 166516ad2ffbSNamhyung Kim err = -saved_errno; 16668fa60e1fSNamhyung Kim goto out_symbol_exit; 166716ad2ffbSNamhyung Kim } 16680d37aa34SArnaldo Carvalho de Melo 166916ad2ffbSNamhyung Kim err = -ENOMEM; 16703e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1671dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 167269aad6f1SArnaldo Carvalho de Melo 1673ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1674ef149c25SAdrian Hunter if (err) 1675ef149c25SAdrian Hunter goto out_symbol_exit; 1676ef149c25SAdrian Hunter 16776156681bSNamhyung Kim /* 16786156681bSNamhyung Kim * We take all buildids when the file contains 16796156681bSNamhyung Kim * AUX area tracing data because we do not decode the 16806156681bSNamhyung Kim * trace because it would take too long. 16816156681bSNamhyung Kim */ 16826156681bSNamhyung Kim if (rec->opts.full_auxtrace) 16836156681bSNamhyung Kim rec->buildid_all = true; 16846156681bSNamhyung Kim 1685b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 168639d17dacSArnaldo Carvalho de Melo err = -EINVAL; 168703ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 16887e4ff9e3SMike Galbraith } 16897e4ff9e3SMike Galbraith 1690d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1691d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 169245604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1693d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1694ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 169539d17dacSArnaldo Carvalho de Melo return err; 169686470930SIngo Molnar } 16972dd6d8a1SAdrian Hunter 16982dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 16992dd6d8a1SAdrian Hunter { 17005f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 17015f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 17022dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 17035f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 17045f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 17055f9cf599SWang Nan } 17063c1cb7e3SWang Nan 17073c1cb7e3SWang Nan if (trigger_is_ready(&switch_output_trigger)) 17083c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 17092dd6d8a1SAdrian Hunter } 1710