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" 16*41840d21STaeung 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" 2594c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2645694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 278d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 28a12b51c4SPaul Mackerras #include "util/cpumap.h" 29fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 30f5fc1412SJiri Olsa #include "util/data.h" 31bcc84ec6SStephane Eranian #include "util/perf_regs.h" 32ef149c25SAdrian Hunter #include "util/auxtrace.h" 3346bc29b9SAdrian Hunter #include "util/tsc.h" 34f00898f4SAndi Kleen #include "util/parse-branch-options.h" 35bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3671dc2326SWang Nan #include "util/llvm-utils.h" 378690a2a7SWang Nan #include "util/bpf-loader.h" 385f9cf599SWang Nan #include "util/trigger.h" 39d8871ea7SWang Nan #include "asm/bug.h" 407c6a1c65SPeter Zijlstra 4186470930SIngo Molnar #include <unistd.h> 4286470930SIngo Molnar #include <sched.h> 43a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 442d11c650SWang Nan #include <asm/bug.h> 4586470930SIngo Molnar 4678da39faSBernhard Rosenkraenzer 478c6f45a7SArnaldo Carvalho de Melo struct record { 4845694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 49b4006796SArnaldo Carvalho de Melo struct record_opts opts; 50d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 51f5fc1412SJiri Olsa struct perf_data_file file; 52ef149c25SAdrian Hunter struct auxtrace_record *itr; 53d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 54d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 55d20deb64SArnaldo Carvalho de Melo const char *progname; 56d20deb64SArnaldo Carvalho de Melo int realtime_prio; 57d20deb64SArnaldo Carvalho de Melo bool no_buildid; 58d2db9a98SWang Nan bool no_buildid_set; 59d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 60d2db9a98SWang Nan bool no_buildid_cache_set; 616156681bSNamhyung Kim bool buildid_all; 62ecfd7a9cSWang Nan bool timestamp_filename; 633c1cb7e3SWang Nan bool switch_output; 649f065194SYang Shi unsigned long long samples; 650f82ebc4SArnaldo Carvalho de Melo }; 6686470930SIngo Molnar 678c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 68f5970550SPeter Zijlstra { 69cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 704f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 718d3eca20SDavid Ahern return -1; 728d3eca20SDavid Ahern } 73f5970550SPeter Zijlstra 74cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 758d3eca20SDavid Ahern return 0; 76f5970550SPeter Zijlstra } 77f5970550SPeter Zijlstra 7845694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 79d20deb64SArnaldo Carvalho de Melo union perf_event *event, 801d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 811d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 82234fbbf5SArnaldo Carvalho de Melo { 838c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 848c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 85234fbbf5SArnaldo Carvalho de Melo } 86234fbbf5SArnaldo Carvalho de Melo 873a62a7b8SWang Nan static int 883a62a7b8SWang Nan backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) 893a62a7b8SWang Nan { 903a62a7b8SWang Nan struct perf_event_header *pheader; 913a62a7b8SWang Nan u64 evt_head = head; 923a62a7b8SWang Nan int size = mask + 1; 933a62a7b8SWang Nan 943a62a7b8SWang Nan pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); 953a62a7b8SWang Nan pheader = (struct perf_event_header *)(buf + (head & mask)); 963a62a7b8SWang Nan *start = head; 973a62a7b8SWang Nan while (true) { 983a62a7b8SWang Nan if (evt_head - head >= (unsigned int)size) { 993a62a7b8SWang Nan pr_debug("Finshed reading backward ring buffer: rewind\n"); 1003a62a7b8SWang Nan if (evt_head - head > (unsigned int)size) 1013a62a7b8SWang Nan evt_head -= pheader->size; 1023a62a7b8SWang Nan *end = evt_head; 1033a62a7b8SWang Nan return 0; 1043a62a7b8SWang Nan } 1053a62a7b8SWang Nan 1063a62a7b8SWang Nan pheader = (struct perf_event_header *)(buf + (evt_head & mask)); 1073a62a7b8SWang Nan 1083a62a7b8SWang Nan if (pheader->size == 0) { 1093a62a7b8SWang Nan pr_debug("Finshed reading backward ring buffer: get start\n"); 1103a62a7b8SWang Nan *end = evt_head; 1113a62a7b8SWang Nan return 0; 1123a62a7b8SWang Nan } 1133a62a7b8SWang Nan 1143a62a7b8SWang Nan evt_head += pheader->size; 1153a62a7b8SWang Nan pr_debug3("move evt_head: %"PRIx64"\n", evt_head); 1163a62a7b8SWang Nan } 1173a62a7b8SWang Nan WARN_ONCE(1, "Shouldn't get here\n"); 1183a62a7b8SWang Nan return -1; 1193a62a7b8SWang Nan } 1203a62a7b8SWang Nan 1213a62a7b8SWang Nan static int 1223a62a7b8SWang Nan rb_find_range(struct perf_evlist *evlist, 1233a62a7b8SWang Nan void *data, int mask, u64 head, u64 old, 1243a62a7b8SWang Nan u64 *start, u64 *end) 1253a62a7b8SWang Nan { 1263a62a7b8SWang Nan if (!evlist->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 135e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 13686470930SIngo Molnar { 137e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 1387b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 1397b8283b5SDavid Ahern u64 old = md->prev; 14009fa4f40SWang Nan u64 end = head, start = old; 141918512b4SJiri Olsa unsigned char *data = md->base + page_size; 14286470930SIngo Molnar unsigned long size; 14386470930SIngo Molnar void *buf; 1448d3eca20SDavid Ahern int rc = 0; 14586470930SIngo Molnar 1463a62a7b8SWang Nan if (rb_find_range(rec->evlist, data, md->mask, head, 1473a62a7b8SWang Nan old, &start, &end)) 1483a62a7b8SWang Nan return -1; 1493a62a7b8SWang Nan 15009fa4f40SWang Nan if (start == end) 1518d3eca20SDavid Ahern return 0; 15286470930SIngo Molnar 153d20deb64SArnaldo Carvalho de Melo rec->samples++; 15486470930SIngo Molnar 15509fa4f40SWang Nan size = end - start; 1562d11c650SWang Nan if (size > (unsigned long)(md->mask) + 1) { 1572d11c650SWang Nan WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 1582d11c650SWang Nan 1592d11c650SWang Nan md->prev = head; 1602d11c650SWang Nan perf_evlist__mmap_consume(rec->evlist, idx); 1612d11c650SWang Nan return 0; 1622d11c650SWang Nan } 16386470930SIngo Molnar 16409fa4f40SWang Nan if ((start & md->mask) + size != (end & md->mask)) { 16509fa4f40SWang Nan buf = &data[start & md->mask]; 16609fa4f40SWang Nan size = md->mask + 1 - (start & md->mask); 16709fa4f40SWang Nan start += size; 16886470930SIngo Molnar 1698c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1708d3eca20SDavid Ahern rc = -1; 1718d3eca20SDavid Ahern goto out; 1728d3eca20SDavid Ahern } 17386470930SIngo Molnar } 17486470930SIngo Molnar 17509fa4f40SWang Nan buf = &data[start & md->mask]; 17609fa4f40SWang Nan size = end - start; 17709fa4f40SWang Nan start += size; 17886470930SIngo Molnar 1798c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1808d3eca20SDavid Ahern rc = -1; 1818d3eca20SDavid Ahern goto out; 1828d3eca20SDavid Ahern } 18386470930SIngo Molnar 18409fa4f40SWang Nan md->prev = head; 185e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1868d3eca20SDavid Ahern out: 1878d3eca20SDavid Ahern return rc; 18886470930SIngo Molnar } 18986470930SIngo Molnar 1902dd6d8a1SAdrian Hunter static volatile int done; 1912dd6d8a1SAdrian Hunter static volatile int signr = -1; 1922dd6d8a1SAdrian Hunter static volatile int child_finished; 193c0bdc1c4SWang Nan 1942dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1955f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 1963c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger); 1972dd6d8a1SAdrian Hunter 1982dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1992dd6d8a1SAdrian Hunter { 2002dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 2012dd6d8a1SAdrian Hunter child_finished = 1; 2022dd6d8a1SAdrian Hunter else 2032dd6d8a1SAdrian Hunter signr = sig; 2042dd6d8a1SAdrian Hunter 2052dd6d8a1SAdrian Hunter done = 1; 2062dd6d8a1SAdrian Hunter } 2072dd6d8a1SAdrian Hunter 2082dd6d8a1SAdrian Hunter static void record__sig_exit(void) 2092dd6d8a1SAdrian Hunter { 2102dd6d8a1SAdrian Hunter if (signr == -1) 2112dd6d8a1SAdrian Hunter return; 2122dd6d8a1SAdrian Hunter 2132dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 2142dd6d8a1SAdrian Hunter raise(signr); 2152dd6d8a1SAdrian Hunter } 2162dd6d8a1SAdrian Hunter 217e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 218e31f0d01SAdrian Hunter 219ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 220ef149c25SAdrian Hunter union perf_event *event, void *data1, 221ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 222ef149c25SAdrian Hunter { 223ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 22499fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 225ef149c25SAdrian Hunter size_t padding; 226ef149c25SAdrian Hunter u8 pad[8] = {0}; 227ef149c25SAdrian Hunter 22899fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 22999fa2984SAdrian Hunter off_t file_offset; 23099fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 23199fa2984SAdrian Hunter int err; 23299fa2984SAdrian Hunter 23399fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 23499fa2984SAdrian Hunter if (file_offset == -1) 23599fa2984SAdrian Hunter return -1; 23699fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 23799fa2984SAdrian Hunter event, file_offset); 23899fa2984SAdrian Hunter if (err) 23999fa2984SAdrian Hunter return err; 24099fa2984SAdrian Hunter } 24199fa2984SAdrian Hunter 242ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 243ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 244ef149c25SAdrian Hunter if (padding) 245ef149c25SAdrian Hunter padding = 8 - padding; 246ef149c25SAdrian Hunter 247ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 248ef149c25SAdrian Hunter record__write(rec, data1, len1); 249ef149c25SAdrian Hunter if (len2) 250ef149c25SAdrian Hunter record__write(rec, data2, len2); 251ef149c25SAdrian Hunter record__write(rec, &pad, padding); 252ef149c25SAdrian Hunter 253ef149c25SAdrian Hunter return 0; 254ef149c25SAdrian Hunter } 255ef149c25SAdrian Hunter 256ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 257ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 258ef149c25SAdrian Hunter { 259ef149c25SAdrian Hunter int ret; 260ef149c25SAdrian Hunter 261ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 262ef149c25SAdrian Hunter record__process_auxtrace); 263ef149c25SAdrian Hunter if (ret < 0) 264ef149c25SAdrian Hunter return ret; 265ef149c25SAdrian Hunter 266ef149c25SAdrian Hunter if (ret) 267ef149c25SAdrian Hunter rec->samples++; 268ef149c25SAdrian Hunter 269ef149c25SAdrian Hunter return 0; 270ef149c25SAdrian Hunter } 271ef149c25SAdrian Hunter 2722dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2732dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2742dd6d8a1SAdrian Hunter { 2752dd6d8a1SAdrian Hunter int ret; 2762dd6d8a1SAdrian Hunter 2772dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2782dd6d8a1SAdrian Hunter record__process_auxtrace, 2792dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2802dd6d8a1SAdrian Hunter if (ret < 0) 2812dd6d8a1SAdrian Hunter return ret; 2822dd6d8a1SAdrian Hunter 2832dd6d8a1SAdrian Hunter if (ret) 2842dd6d8a1SAdrian Hunter rec->samples++; 2852dd6d8a1SAdrian Hunter 2862dd6d8a1SAdrian Hunter return 0; 2872dd6d8a1SAdrian Hunter } 2882dd6d8a1SAdrian Hunter 2892dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2902dd6d8a1SAdrian Hunter { 2912dd6d8a1SAdrian Hunter int i; 2922dd6d8a1SAdrian Hunter int rc = 0; 2932dd6d8a1SAdrian Hunter 2942dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2952dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2962dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2972dd6d8a1SAdrian Hunter 2982dd6d8a1SAdrian Hunter if (!mm->base) 2992dd6d8a1SAdrian Hunter continue; 3002dd6d8a1SAdrian Hunter 3012dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 3022dd6d8a1SAdrian Hunter rc = -1; 3032dd6d8a1SAdrian Hunter goto out; 3042dd6d8a1SAdrian Hunter } 3052dd6d8a1SAdrian Hunter } 3062dd6d8a1SAdrian Hunter out: 3072dd6d8a1SAdrian Hunter return rc; 3082dd6d8a1SAdrian Hunter } 3092dd6d8a1SAdrian Hunter 3102dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 3112dd6d8a1SAdrian Hunter { 3122dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 3132dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 3145f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 3152dd6d8a1SAdrian Hunter } else { 3165f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 3175f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 3185f9cf599SWang Nan else 3195f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 3202dd6d8a1SAdrian Hunter } 3212dd6d8a1SAdrian Hunter } 3222dd6d8a1SAdrian Hunter 323e31f0d01SAdrian Hunter #else 324e31f0d01SAdrian Hunter 325e31f0d01SAdrian Hunter static inline 326e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 327e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 328e31f0d01SAdrian Hunter { 329e31f0d01SAdrian Hunter return 0; 330e31f0d01SAdrian Hunter } 331e31f0d01SAdrian Hunter 3322dd6d8a1SAdrian Hunter static inline 3332dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 3342dd6d8a1SAdrian Hunter { 3352dd6d8a1SAdrian Hunter } 3362dd6d8a1SAdrian Hunter 3372dd6d8a1SAdrian Hunter static inline 3382dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 3392dd6d8a1SAdrian Hunter { 3402dd6d8a1SAdrian Hunter return 0; 3412dd6d8a1SAdrian Hunter } 3422dd6d8a1SAdrian Hunter 343e31f0d01SAdrian Hunter #endif 344e31f0d01SAdrian Hunter 3458c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 346dd7927f4SArnaldo Carvalho de Melo { 34756e52e85SArnaldo Carvalho de Melo char msg[512]; 3486a4bb04cSJiri Olsa struct perf_evsel *pos; 349d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 350d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 351b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 3528d3eca20SDavid Ahern int rc = 0; 353dd7927f4SArnaldo Carvalho de Melo 354e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 355cac21425SJiri Olsa 3560050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 3573da297a6SIngo Molnar try_again: 358d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 35956e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 3603da297a6SIngo Molnar if (verbose) 361c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 3623da297a6SIngo Molnar goto try_again; 3633da297a6SIngo Molnar } 364ca6a4258SDavid Ahern 36556e52e85SArnaldo Carvalho de Melo rc = -errno; 36656e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 36756e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 36856e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3698d3eca20SDavid Ahern goto out; 3707c6a1c65SPeter Zijlstra } 3717c6a1c65SPeter Zijlstra } 3727c6a1c65SPeter Zijlstra 37323d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 37423d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 37523d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 37635550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3778d3eca20SDavid Ahern rc = -1; 3788d3eca20SDavid Ahern goto out; 3790a102479SFrederic Weisbecker } 3800a102479SFrederic Weisbecker 381ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3822dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3832dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3848d3eca20SDavid Ahern if (errno == EPERM) { 3858d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 38618e60939SNelson Elhage "Consider increasing " 38718e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 38818e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 389ef149c25SAdrian Hunter "(current value: %u,%u)\n", 390ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3918d3eca20SDavid Ahern rc = -errno; 3928d3eca20SDavid Ahern } else { 39335550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 39435550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 39595c36561SWang Nan if (errno) 3968d3eca20SDavid Ahern rc = -errno; 39795c36561SWang Nan else 39895c36561SWang Nan rc = -EINVAL; 3998d3eca20SDavid Ahern } 4008d3eca20SDavid Ahern goto out; 40118e60939SNelson Elhage } 4020a27d7f9SArnaldo Carvalho de Melo 403a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 4047b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 4058d3eca20SDavid Ahern out: 4068d3eca20SDavid Ahern return rc; 407a91e5431SArnaldo Carvalho de Melo } 408a91e5431SArnaldo Carvalho de Melo 409e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 410e3d59112SNamhyung Kim union perf_event *event, 411e3d59112SNamhyung Kim struct perf_sample *sample, 412e3d59112SNamhyung Kim struct perf_evsel *evsel, 413e3d59112SNamhyung Kim struct machine *machine) 414e3d59112SNamhyung Kim { 415e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 416e3d59112SNamhyung Kim 417e3d59112SNamhyung Kim rec->samples++; 418e3d59112SNamhyung Kim 419e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 420e3d59112SNamhyung Kim } 421e3d59112SNamhyung Kim 4228c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 4236122e4e4SArnaldo Carvalho de Melo { 424f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 425f5fc1412SJiri Olsa struct perf_session *session = rec->session; 4266122e4e4SArnaldo Carvalho de Melo 427457ae94aSHe Kuang if (file->size == 0) 4289f591fd7SArnaldo Carvalho de Melo return 0; 4299f591fd7SArnaldo Carvalho de Melo 43000dc8657SNamhyung Kim /* 43100dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 43200dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 43300dc8657SNamhyung Kim * we prefer the vmlinux path like 43400dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 43500dc8657SNamhyung Kim * 43600dc8657SNamhyung Kim * rather than build-id path (in debug directory). 43700dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 43800dc8657SNamhyung Kim */ 43900dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 44000dc8657SNamhyung Kim 4416156681bSNamhyung Kim /* 4426156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 4436156681bSNamhyung Kim * so no need to process samples. 4446156681bSNamhyung Kim */ 4456156681bSNamhyung Kim if (rec->buildid_all) 4466156681bSNamhyung Kim rec->tool.sample = NULL; 4476156681bSNamhyung Kim 448b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 4496122e4e4SArnaldo Carvalho de Melo } 4506122e4e4SArnaldo Carvalho de Melo 4518115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 452a1645ce1SZhang, Yanmin { 453a1645ce1SZhang, Yanmin int err; 45445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 455a1645ce1SZhang, Yanmin /* 456a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 457a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 458a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 459a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 460a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 461a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 462a1645ce1SZhang, Yanmin */ 46345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 464743eb868SArnaldo Carvalho de Melo machine); 465a1645ce1SZhang, Yanmin if (err < 0) 466a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 46723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 468a1645ce1SZhang, Yanmin 469a1645ce1SZhang, Yanmin /* 470a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 471a1645ce1SZhang, Yanmin * have no _text sometimes. 472a1645ce1SZhang, Yanmin */ 47345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4740ae617beSAdrian Hunter machine); 475a1645ce1SZhang, Yanmin if (err < 0) 476a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 47723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 478a1645ce1SZhang, Yanmin } 479a1645ce1SZhang, Yanmin 48098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 48198402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 48298402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 48398402807SFrederic Weisbecker }; 48498402807SFrederic Weisbecker 4858c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 48698402807SFrederic Weisbecker { 487dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4880e2e63ddSPeter Zijlstra int i; 4898d3eca20SDavid Ahern int rc = 0; 49098402807SFrederic Weisbecker 491d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 492ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 493ef149c25SAdrian Hunter 4948d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 495e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4968d3eca20SDavid Ahern rc = -1; 4978d3eca20SDavid Ahern goto out; 4988d3eca20SDavid Ahern } 4998d3eca20SDavid Ahern } 500ef149c25SAdrian Hunter 5012dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 502ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 503ef149c25SAdrian Hunter rc = -1; 504ef149c25SAdrian Hunter goto out; 505ef149c25SAdrian Hunter } 50698402807SFrederic Weisbecker } 50798402807SFrederic Weisbecker 508dcabb507SJiri Olsa /* 509dcabb507SJiri Olsa * Mark the round finished in case we wrote 510dcabb507SJiri Olsa * at least one event. 511dcabb507SJiri Olsa */ 512dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 5138c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 5148d3eca20SDavid Ahern 5158d3eca20SDavid Ahern out: 5168d3eca20SDavid Ahern return rc; 51798402807SFrederic Weisbecker } 51898402807SFrederic Weisbecker 5198c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 52057706abcSDavid Ahern { 52157706abcSDavid Ahern struct perf_session *session = rec->session; 52257706abcSDavid Ahern int feat; 52357706abcSDavid Ahern 52457706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 52557706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 52657706abcSDavid Ahern 52757706abcSDavid Ahern if (rec->no_buildid) 52857706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 52957706abcSDavid Ahern 5303e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 53157706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 53257706abcSDavid Ahern 53357706abcSDavid Ahern if (!rec->opts.branch_stack) 53457706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 535ef149c25SAdrian Hunter 536ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 537ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 538ffa517adSJiri Olsa 539ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 54057706abcSDavid Ahern } 54157706abcSDavid Ahern 542e1ab48baSWang Nan static void 543e1ab48baSWang Nan record__finish_output(struct record *rec) 544e1ab48baSWang Nan { 545e1ab48baSWang Nan struct perf_data_file *file = &rec->file; 546e1ab48baSWang Nan int fd = perf_data_file__fd(file); 547e1ab48baSWang Nan 548e1ab48baSWang Nan if (file->is_pipe) 549e1ab48baSWang Nan return; 550e1ab48baSWang Nan 551e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 552e1ab48baSWang Nan file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 553e1ab48baSWang Nan 554e1ab48baSWang Nan if (!rec->no_buildid) { 555e1ab48baSWang Nan process_buildids(rec); 556e1ab48baSWang Nan 557e1ab48baSWang Nan if (rec->buildid_all) 558e1ab48baSWang Nan dsos__hit_all(rec->session); 559e1ab48baSWang Nan } 560e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 561e1ab48baSWang Nan 562e1ab48baSWang Nan return; 563e1ab48baSWang Nan } 564e1ab48baSWang Nan 565be7b0c9eSWang Nan static int record__synthesize_workload(struct record *rec) 566be7b0c9eSWang Nan { 567be7b0c9eSWang Nan struct { 568be7b0c9eSWang Nan struct thread_map map; 569be7b0c9eSWang Nan struct thread_map_data map_data; 570be7b0c9eSWang Nan } thread_map; 571be7b0c9eSWang Nan 572be7b0c9eSWang Nan thread_map.map.nr = 1; 573be7b0c9eSWang Nan thread_map.map.map[0].pid = rec->evlist->workload.pid; 574be7b0c9eSWang Nan thread_map.map.map[0].comm = NULL; 575be7b0c9eSWang Nan return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map, 576be7b0c9eSWang Nan process_synthesized_event, 577be7b0c9eSWang Nan &rec->session->machines.host, 578be7b0c9eSWang Nan rec->opts.sample_address, 579be7b0c9eSWang Nan rec->opts.proc_map_timeout); 580be7b0c9eSWang Nan } 581be7b0c9eSWang Nan 5823c1cb7e3SWang Nan static int record__synthesize(struct record *rec); 5833c1cb7e3SWang Nan 584ecfd7a9cSWang Nan static int 585ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 586ecfd7a9cSWang Nan { 587ecfd7a9cSWang Nan struct perf_data_file *file = &rec->file; 588ecfd7a9cSWang Nan int fd, err; 589ecfd7a9cSWang Nan 590ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 591ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 592ecfd7a9cSWang Nan 593ecfd7a9cSWang Nan rec->samples = 0; 594ecfd7a9cSWang Nan record__finish_output(rec); 595ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 596ecfd7a9cSWang Nan if (err) { 597ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 598ecfd7a9cSWang Nan return -EINVAL; 599ecfd7a9cSWang Nan } 600ecfd7a9cSWang Nan 601ecfd7a9cSWang Nan fd = perf_data_file__switch(file, timestamp, 602ecfd7a9cSWang Nan rec->session->header.data_offset, 603ecfd7a9cSWang Nan at_exit); 604ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 605ecfd7a9cSWang Nan rec->bytes_written = 0; 606ecfd7a9cSWang Nan rec->session->header.data_size = 0; 607ecfd7a9cSWang Nan } 608ecfd7a9cSWang Nan 609ecfd7a9cSWang Nan if (!quiet) 610ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 611ecfd7a9cSWang Nan file->path, timestamp); 6123c1cb7e3SWang Nan 6133c1cb7e3SWang Nan /* Output tracking events */ 614be7b0c9eSWang Nan if (!at_exit) { 6153c1cb7e3SWang Nan record__synthesize(rec); 6163c1cb7e3SWang Nan 617be7b0c9eSWang Nan /* 618be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 619be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 620be7b0c9eSWang Nan * generate tracking events because there's no thread_map 621be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 622be7b0c9eSWang Nan * contain map and comm information. 623be7b0c9eSWang Nan * Create a fake thread_map and directly call 624be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 625be7b0c9eSWang Nan */ 626be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 627be7b0c9eSWang Nan record__synthesize_workload(rec); 628be7b0c9eSWang Nan } 629ecfd7a9cSWang Nan return fd; 630ecfd7a9cSWang Nan } 631ecfd7a9cSWang Nan 632f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 633f33cbe72SArnaldo Carvalho de Melo 634f33cbe72SArnaldo Carvalho de Melo /* 635f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 636f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 637f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 638f33cbe72SArnaldo Carvalho de Melo */ 63945604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 64045604710SNamhyung Kim siginfo_t *info, 641f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 642f33cbe72SArnaldo Carvalho de Melo { 643f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 644f33cbe72SArnaldo Carvalho de Melo done = 1; 645f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 646f33cbe72SArnaldo Carvalho de Melo } 647f33cbe72SArnaldo Carvalho de Melo 6482dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 6492dd6d8a1SAdrian Hunter 65046bc29b9SAdrian Hunter int __weak 65146bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 65246bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 65346bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 65446bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 65546bc29b9SAdrian Hunter { 65646bc29b9SAdrian Hunter return 0; 65746bc29b9SAdrian Hunter } 65846bc29b9SAdrian Hunter 659c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 660c45628b0SWang Nan { 661c45628b0SWang Nan if (rec->evlist && rec->evlist->mmap && rec->evlist->mmap[0].base) 662c45628b0SWang Nan return rec->evlist->mmap[0].base; 663c45628b0SWang Nan return NULL; 664c45628b0SWang Nan } 665c45628b0SWang Nan 666c45c86ebSWang Nan static int record__synthesize(struct record *rec) 667c45c86ebSWang Nan { 668c45c86ebSWang Nan struct perf_session *session = rec->session; 669c45c86ebSWang Nan struct machine *machine = &session->machines.host; 670c45c86ebSWang Nan struct perf_data_file *file = &rec->file; 671c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 672c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 673c45c86ebSWang Nan int fd = perf_data_file__fd(file); 674c45c86ebSWang Nan int err = 0; 675c45c86ebSWang Nan 676c45c86ebSWang Nan if (file->is_pipe) { 677c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 678c45c86ebSWang Nan process_synthesized_event); 679c45c86ebSWang Nan if (err < 0) { 680c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 681c45c86ebSWang Nan goto out; 682c45c86ebSWang Nan } 683c45c86ebSWang Nan 684c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 685c45c86ebSWang Nan /* 686c45c86ebSWang Nan * FIXME err <= 0 here actually means that 687c45c86ebSWang Nan * there were no tracepoints so its not really 688c45c86ebSWang Nan * an error, just that we don't need to 689c45c86ebSWang Nan * synthesize anything. We really have to 690c45c86ebSWang Nan * return this more properly and also 691c45c86ebSWang Nan * propagate errors that now are calling die() 692c45c86ebSWang Nan */ 693c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 694c45c86ebSWang Nan process_synthesized_event); 695c45c86ebSWang Nan if (err <= 0) { 696c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 697c45c86ebSWang Nan goto out; 698c45c86ebSWang Nan } 699c45c86ebSWang Nan rec->bytes_written += err; 700c45c86ebSWang Nan } 701c45c86ebSWang Nan } 702c45c86ebSWang Nan 703c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 70446bc29b9SAdrian Hunter process_synthesized_event, machine); 70546bc29b9SAdrian Hunter if (err) 70646bc29b9SAdrian Hunter goto out; 70746bc29b9SAdrian Hunter 708c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 709c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 710c45c86ebSWang Nan session, process_synthesized_event); 711c45c86ebSWang Nan if (err) 712c45c86ebSWang Nan goto out; 713c45c86ebSWang Nan } 714c45c86ebSWang Nan 715c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 716c45c86ebSWang Nan machine); 717c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 718c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 719c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 720c45c86ebSWang Nan 721c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 722c45c86ebSWang Nan machine); 723c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 724c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 725c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 726c45c86ebSWang Nan 727c45c86ebSWang Nan if (perf_guest) { 728c45c86ebSWang Nan machines__process_guests(&session->machines, 729c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 730c45c86ebSWang Nan } 731c45c86ebSWang Nan 732c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 733c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 734c45c86ebSWang Nan opts->proc_map_timeout); 735c45c86ebSWang Nan out: 736c45c86ebSWang Nan return err; 737c45c86ebSWang Nan } 738c45c86ebSWang Nan 7398c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 74086470930SIngo Molnar { 74157706abcSDavid Ahern int err; 74245604710SNamhyung Kim int status = 0; 7438b412664SPeter Zijlstra unsigned long waking = 0; 74446be604bSZhang, Yanmin const bool forks = argc > 0; 74523346f21SArnaldo Carvalho de Melo struct machine *machine; 74645694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 747b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 748f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 749d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 7506dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 75142aa276fSNamhyung Kim int fd; 75286470930SIngo Molnar 753d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 75433e49ea7SAndi Kleen 75545604710SNamhyung Kim atexit(record__sig_exit); 756f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 757f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 758804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 759c0bdc1c4SWang Nan 7603c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) { 7612dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 7623c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 7635f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 7643c1cb7e3SWang Nan if (rec->switch_output) 7653c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 766c0bdc1c4SWang Nan } else { 7672dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 768c0bdc1c4SWang Nan } 769f5970550SPeter Zijlstra 770b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 77194c744b6SArnaldo Carvalho de Melo if (session == NULL) { 772ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 773a9a70bbcSArnaldo Carvalho de Melo return -1; 774a9a70bbcSArnaldo Carvalho de Melo } 775a9a70bbcSArnaldo Carvalho de Melo 77642aa276fSNamhyung Kim fd = perf_data_file__fd(file); 777d20deb64SArnaldo Carvalho de Melo rec->session = session; 778d20deb64SArnaldo Carvalho de Melo 7798c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 780330aa675SStephane Eranian 781d4db3f16SArnaldo Carvalho de Melo if (forks) { 7823e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 783f5fc1412SJiri Olsa argv, file->is_pipe, 784735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 78535b9d88eSArnaldo Carvalho de Melo if (err < 0) { 78635b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 78745604710SNamhyung Kim status = err; 78835b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 789856e9660SPeter Zijlstra } 790856e9660SPeter Zijlstra } 791856e9660SPeter Zijlstra 7928c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 7938d3eca20SDavid Ahern err = -1; 79445604710SNamhyung Kim goto out_child; 7958d3eca20SDavid Ahern } 79686470930SIngo Molnar 7978690a2a7SWang Nan err = bpf__apply_obj_config(); 7988690a2a7SWang Nan if (err) { 7998690a2a7SWang Nan char errbuf[BUFSIZ]; 8008690a2a7SWang Nan 8018690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 8028690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 8038690a2a7SWang Nan errbuf); 8048690a2a7SWang Nan goto out_child; 8058690a2a7SWang Nan } 8068690a2a7SWang Nan 807cca8482cSAdrian Hunter /* 808cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 809cca8482cSAdrian Hunter * evlist. 810cca8482cSAdrian Hunter */ 811cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 812cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 813cca8482cSAdrian Hunter rec->tool.ordered_events = false; 814cca8482cSAdrian Hunter } 815cca8482cSAdrian Hunter 8163e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 817a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 818a8bb559bSNamhyung Kim 819f5fc1412SJiri Olsa if (file->is_pipe) { 82042aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 821529870e3STom Zanussi if (err < 0) 82245604710SNamhyung Kim goto out_child; 823563aecb2SJiri Olsa } else { 82442aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 825d5eed904SArnaldo Carvalho de Melo if (err < 0) 82645604710SNamhyung Kim goto out_child; 827d5eed904SArnaldo Carvalho de Melo } 8287c6a1c65SPeter Zijlstra 829d3665498SDavid Ahern if (!rec->no_buildid 830e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 831d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 832e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 8338d3eca20SDavid Ahern err = -1; 83445604710SNamhyung Kim goto out_child; 835e20960c0SRobert Richter } 836e20960c0SRobert Richter 83734ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 838743eb868SArnaldo Carvalho de Melo 839c45c86ebSWang Nan err = record__synthesize(rec); 840c45c86ebSWang Nan if (err < 0) 84145604710SNamhyung Kim goto out_child; 8428d3eca20SDavid Ahern 843d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 84486470930SIngo Molnar struct sched_param param; 84586470930SIngo Molnar 846d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 84786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 8486beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 8498d3eca20SDavid Ahern err = -1; 85045604710SNamhyung Kim goto out_child; 85186470930SIngo Molnar } 85286470930SIngo Molnar } 85386470930SIngo Molnar 854774cb499SJiri Olsa /* 855774cb499SJiri Olsa * When perf is starting the traced process, all the events 856774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 857774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 858774cb499SJiri Olsa */ 8596619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 8603e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 861764e16a3SDavid Ahern 862856e9660SPeter Zijlstra /* 863856e9660SPeter Zijlstra * Let the child rip 864856e9660SPeter Zijlstra */ 865e803cf97SNamhyung Kim if (forks) { 866e5bed564SNamhyung Kim union perf_event *event; 867e5bed564SNamhyung Kim 868e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 869e5bed564SNamhyung Kim if (event == NULL) { 870e5bed564SNamhyung Kim err = -ENOMEM; 871e5bed564SNamhyung Kim goto out_child; 872e5bed564SNamhyung Kim } 873e5bed564SNamhyung Kim 874e803cf97SNamhyung Kim /* 875e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 876e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 877e803cf97SNamhyung Kim * cannot see a correct process name for those events. 878e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 879e803cf97SNamhyung Kim */ 880e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 881e803cf97SNamhyung Kim rec->evlist->workload.pid, 882e803cf97SNamhyung Kim process_synthesized_event, 883e803cf97SNamhyung Kim machine); 884e5bed564SNamhyung Kim free(event); 885e803cf97SNamhyung Kim 8863e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 887e803cf97SNamhyung Kim } 888856e9660SPeter Zijlstra 8896619a53eSAndi Kleen if (opts->initial_delay) { 8906619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 8916619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 8926619a53eSAndi Kleen } 8936619a53eSAndi Kleen 8945f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 8953c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 896649c48a9SPeter Zijlstra for (;;) { 8979f065194SYang Shi unsigned long long hits = rec->samples; 89886470930SIngo Molnar 8998c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 9005f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 9013c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 9028d3eca20SDavid Ahern err = -1; 90345604710SNamhyung Kim goto out_child; 9048d3eca20SDavid Ahern } 90586470930SIngo Molnar 9062dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 9072dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 9085f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 9092dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 9105f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 9112dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 9122dd6d8a1SAdrian Hunter err = -1; 9132dd6d8a1SAdrian Hunter goto out_child; 9142dd6d8a1SAdrian Hunter } 9152dd6d8a1SAdrian Hunter } 9162dd6d8a1SAdrian Hunter 9173c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 9183c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 9193c1cb7e3SWang Nan 9203c1cb7e3SWang Nan if (!quiet) 9213c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 9223c1cb7e3SWang Nan waking); 9233c1cb7e3SWang Nan waking = 0; 9243c1cb7e3SWang Nan fd = record__switch_output(rec, false); 9253c1cb7e3SWang Nan if (fd < 0) { 9263c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 9273c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 9283c1cb7e3SWang Nan err = fd; 9293c1cb7e3SWang Nan goto out_child; 9303c1cb7e3SWang Nan } 9313c1cb7e3SWang Nan } 9323c1cb7e3SWang Nan 933d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 9346dcf45efSArnaldo Carvalho de Melo if (done || draining) 935649c48a9SPeter Zijlstra break; 936f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 937a515114fSJiri Olsa /* 938a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 939a515114fSJiri Olsa * number of returned events and interrupt error. 940a515114fSJiri Olsa */ 941a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 94245604710SNamhyung Kim err = 0; 9438b412664SPeter Zijlstra waking++; 9446dcf45efSArnaldo Carvalho de Melo 9456dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 9466dcf45efSArnaldo Carvalho de Melo draining = true; 9478b412664SPeter Zijlstra } 9488b412664SPeter Zijlstra 949774cb499SJiri Olsa /* 950774cb499SJiri Olsa * When perf is starting the traced process, at the end events 951774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 952774cb499SJiri Olsa * disable events in this case. 953774cb499SJiri Olsa */ 954602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 9555f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 9563e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 9572711926aSJiri Olsa disabled = true; 9582711926aSJiri Olsa } 9598b412664SPeter Zijlstra } 9605f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 9613c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 9628b412664SPeter Zijlstra 963f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 96435550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 965f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 966f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 967f33cbe72SArnaldo Carvalho de Melo err = -1; 96845604710SNamhyung Kim goto out_child; 969f33cbe72SArnaldo Carvalho de Melo } 970f33cbe72SArnaldo Carvalho de Melo 971e3d59112SNamhyung Kim if (!quiet) 9728b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 97386470930SIngo Molnar 97445604710SNamhyung Kim out_child: 97545604710SNamhyung Kim if (forks) { 97645604710SNamhyung Kim int exit_status; 97745604710SNamhyung Kim 97845604710SNamhyung Kim if (!child_finished) 97945604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 98045604710SNamhyung Kim 98145604710SNamhyung Kim wait(&exit_status); 98245604710SNamhyung Kim 98345604710SNamhyung Kim if (err < 0) 98445604710SNamhyung Kim status = err; 98545604710SNamhyung Kim else if (WIFEXITED(exit_status)) 98645604710SNamhyung Kim status = WEXITSTATUS(exit_status); 98745604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 98845604710SNamhyung Kim signr = WTERMSIG(exit_status); 98945604710SNamhyung Kim } else 99045604710SNamhyung Kim status = err; 99145604710SNamhyung Kim 992e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 993e3d59112SNamhyung Kim rec->samples = 0; 994e3d59112SNamhyung Kim 995ecfd7a9cSWang Nan if (!err) { 996ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 997e1ab48baSWang Nan record__finish_output(rec); 998ecfd7a9cSWang Nan } else { 999ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1000ecfd7a9cSWang Nan if (fd < 0) { 1001ecfd7a9cSWang Nan status = fd; 1002ecfd7a9cSWang Nan goto out_delete_session; 1003ecfd7a9cSWang Nan } 1004ecfd7a9cSWang Nan } 1005ecfd7a9cSWang Nan } 100639d17dacSArnaldo Carvalho de Melo 1007e3d59112SNamhyung Kim if (!err && !quiet) { 1008e3d59112SNamhyung Kim char samples[128]; 1009ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1010ecfd7a9cSWang Nan ".<timestamp>" : ""; 1011e3d59112SNamhyung Kim 1012ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1013e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1014e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1015e3d59112SNamhyung Kim else 1016e3d59112SNamhyung Kim samples[0] = '\0'; 1017e3d59112SNamhyung Kim 1018ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1019e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 1020ecfd7a9cSWang Nan file->path, postfix, samples); 1021e3d59112SNamhyung Kim } 1022e3d59112SNamhyung Kim 102339d17dacSArnaldo Carvalho de Melo out_delete_session: 102439d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 102545604710SNamhyung Kim return status; 102686470930SIngo Molnar } 102786470930SIngo Molnar 10280883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 102909b0fd45SJiri Olsa { 1030aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1031a601fdffSJiri Olsa 10320883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 103326d33022SJiri Olsa 10340883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 103509b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 10360883e820SArnaldo Carvalho de Melo callchain->dump_size); 10370883e820SArnaldo Carvalho de Melo } 10380883e820SArnaldo Carvalho de Melo 10390883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 10400883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 10410883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 10420883e820SArnaldo Carvalho de Melo { 10430883e820SArnaldo Carvalho de Melo int ret; 10440883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 10450883e820SArnaldo Carvalho de Melo 10460883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 10470883e820SArnaldo Carvalho de Melo if (unset) { 10480883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 10490883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 10500883e820SArnaldo Carvalho de Melo return 0; 10510883e820SArnaldo Carvalho de Melo } 10520883e820SArnaldo Carvalho de Melo 10530883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 10540883e820SArnaldo Carvalho de Melo if (!ret) { 10550883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 10560883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 10570883e820SArnaldo Carvalho de Melo record->sample_address = true; 10580883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 10590883e820SArnaldo Carvalho de Melo } 10600883e820SArnaldo Carvalho de Melo 10610883e820SArnaldo Carvalho de Melo return ret; 106209b0fd45SJiri Olsa } 106309b0fd45SJiri Olsa 1064c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 106509b0fd45SJiri Olsa const char *arg, 106609b0fd45SJiri Olsa int unset) 106709b0fd45SJiri Olsa { 10680883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 106926d33022SJiri Olsa } 107026d33022SJiri Olsa 1071c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 107209b0fd45SJiri Olsa const char *arg __maybe_unused, 107309b0fd45SJiri Olsa int unset __maybe_unused) 107409b0fd45SJiri Olsa { 10752ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1076c421e80bSKan Liang 10772ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 107809b0fd45SJiri Olsa 10792ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 10802ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1081eb853e80SJiri Olsa 10822ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 108309b0fd45SJiri Olsa return 0; 108409b0fd45SJiri Olsa } 108509b0fd45SJiri Olsa 1086eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1087eb853e80SJiri Olsa { 10887a29c087SNamhyung Kim struct record *rec = cb; 10897a29c087SNamhyung Kim 10907a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 10917a29c087SNamhyung Kim if (!strcmp(value, "cache")) 10927a29c087SNamhyung Kim rec->no_buildid_cache = false; 10937a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 10947a29c087SNamhyung Kim rec->no_buildid_cache = true; 10957a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 10967a29c087SNamhyung Kim rec->no_buildid = true; 10977a29c087SNamhyung Kim else 10987a29c087SNamhyung Kim return -1; 10997a29c087SNamhyung Kim return 0; 11007a29c087SNamhyung Kim } 1101eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 11025a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 1103eb853e80SJiri Olsa 1104eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1105eb853e80SJiri Olsa } 1106eb853e80SJiri Olsa 1107814c8c38SPeter Zijlstra struct clockid_map { 1108814c8c38SPeter Zijlstra const char *name; 1109814c8c38SPeter Zijlstra int clockid; 1110814c8c38SPeter Zijlstra }; 1111814c8c38SPeter Zijlstra 1112814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1113814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1114814c8c38SPeter Zijlstra 1115814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1116814c8c38SPeter Zijlstra 1117814c8c38SPeter Zijlstra 1118814c8c38SPeter Zijlstra /* 1119814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1120814c8c38SPeter Zijlstra */ 1121814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1122814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1123814c8c38SPeter Zijlstra #endif 1124814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1125814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1126814c8c38SPeter Zijlstra #endif 1127814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1128814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1129814c8c38SPeter Zijlstra #endif 1130814c8c38SPeter Zijlstra 1131814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1132814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1133814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1134814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1135814c8c38SPeter Zijlstra 1136814c8c38SPeter Zijlstra /* available for some events */ 1137814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1138814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1139814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1140814c8c38SPeter Zijlstra 1141814c8c38SPeter Zijlstra /* available for the lazy */ 1142814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1143814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1144814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1145814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1146814c8c38SPeter Zijlstra 1147814c8c38SPeter Zijlstra CLOCKID_END, 1148814c8c38SPeter Zijlstra }; 1149814c8c38SPeter Zijlstra 1150814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1151814c8c38SPeter Zijlstra { 1152814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1153814c8c38SPeter Zijlstra const struct clockid_map *cm; 1154814c8c38SPeter Zijlstra const char *ostr = str; 1155814c8c38SPeter Zijlstra 1156814c8c38SPeter Zijlstra if (unset) { 1157814c8c38SPeter Zijlstra opts->use_clockid = 0; 1158814c8c38SPeter Zijlstra return 0; 1159814c8c38SPeter Zijlstra } 1160814c8c38SPeter Zijlstra 1161814c8c38SPeter Zijlstra /* no arg passed */ 1162814c8c38SPeter Zijlstra if (!str) 1163814c8c38SPeter Zijlstra return 0; 1164814c8c38SPeter Zijlstra 1165814c8c38SPeter Zijlstra /* no setting it twice */ 1166814c8c38SPeter Zijlstra if (opts->use_clockid) 1167814c8c38SPeter Zijlstra return -1; 1168814c8c38SPeter Zijlstra 1169814c8c38SPeter Zijlstra opts->use_clockid = true; 1170814c8c38SPeter Zijlstra 1171814c8c38SPeter Zijlstra /* if its a number, we're done */ 1172814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1173814c8c38SPeter Zijlstra return 0; 1174814c8c38SPeter Zijlstra 1175814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1176814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1177814c8c38SPeter Zijlstra str += 6; 1178814c8c38SPeter Zijlstra 1179814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1180814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1181814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1182814c8c38SPeter Zijlstra return 0; 1183814c8c38SPeter Zijlstra } 1184814c8c38SPeter Zijlstra } 1185814c8c38SPeter Zijlstra 1186814c8c38SPeter Zijlstra opts->use_clockid = false; 1187814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1188814c8c38SPeter Zijlstra return -1; 1189814c8c38SPeter Zijlstra } 1190814c8c38SPeter Zijlstra 1191e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1192e9db1310SAdrian Hunter const char *str, 1193e9db1310SAdrian Hunter int unset __maybe_unused) 1194e9db1310SAdrian Hunter { 1195e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1196e9db1310SAdrian Hunter char *s, *p; 1197e9db1310SAdrian Hunter unsigned int mmap_pages; 1198e9db1310SAdrian Hunter int ret; 1199e9db1310SAdrian Hunter 1200e9db1310SAdrian Hunter if (!str) 1201e9db1310SAdrian Hunter return -EINVAL; 1202e9db1310SAdrian Hunter 1203e9db1310SAdrian Hunter s = strdup(str); 1204e9db1310SAdrian Hunter if (!s) 1205e9db1310SAdrian Hunter return -ENOMEM; 1206e9db1310SAdrian Hunter 1207e9db1310SAdrian Hunter p = strchr(s, ','); 1208e9db1310SAdrian Hunter if (p) 1209e9db1310SAdrian Hunter *p = '\0'; 1210e9db1310SAdrian Hunter 1211e9db1310SAdrian Hunter if (*s) { 1212e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1213e9db1310SAdrian Hunter if (ret) 1214e9db1310SAdrian Hunter goto out_free; 1215e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1216e9db1310SAdrian Hunter } 1217e9db1310SAdrian Hunter 1218e9db1310SAdrian Hunter if (!p) { 1219e9db1310SAdrian Hunter ret = 0; 1220e9db1310SAdrian Hunter goto out_free; 1221e9db1310SAdrian Hunter } 1222e9db1310SAdrian Hunter 1223e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1224e9db1310SAdrian Hunter if (ret) 1225e9db1310SAdrian Hunter goto out_free; 1226e9db1310SAdrian Hunter 1227e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1228e9db1310SAdrian Hunter 1229e9db1310SAdrian Hunter out_free: 1230e9db1310SAdrian Hunter free(s); 1231e9db1310SAdrian Hunter return ret; 1232e9db1310SAdrian Hunter } 1233e9db1310SAdrian Hunter 1234e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 123586470930SIngo Molnar "perf record [<options>] [<command>]", 123686470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 123786470930SIngo Molnar NULL 123886470930SIngo Molnar }; 1239e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 124086470930SIngo Molnar 1241d20deb64SArnaldo Carvalho de Melo /* 12428c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 12438c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1244d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1245d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1246d20deb64SArnaldo Carvalho de Melo * 1247d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1248d20deb64SArnaldo Carvalho de Melo * 1249d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1250d20deb64SArnaldo Carvalho de Melo */ 12518c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1252d20deb64SArnaldo Carvalho de Melo .opts = { 12538affc2b8SAndi Kleen .sample_time = true, 1254d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1255d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1256d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1257447a6013SArnaldo Carvalho de Melo .freq = 4000, 1258d1cb9fceSNamhyung Kim .target = { 1259d1cb9fceSNamhyung Kim .uses_mmap = true, 12603aa5939dSAdrian Hunter .default_per_cpu = true, 1261d1cb9fceSNamhyung Kim }, 12629d9cad76SKan Liang .proc_map_timeout = 500, 1263d20deb64SArnaldo Carvalho de Melo }, 1264e3d59112SNamhyung Kim .tool = { 1265e3d59112SNamhyung Kim .sample = process_sample_event, 1266e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1267cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1268e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1269e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1270e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1271cca8482cSAdrian Hunter .ordered_events = true, 1272e3d59112SNamhyung Kim }, 1273d20deb64SArnaldo Carvalho de Melo }; 12747865e817SFrederic Weisbecker 127576a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 127676a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 127761eaa3beSArnaldo Carvalho de Melo 12780aab2136SWang Nan static bool dry_run; 12790aab2136SWang Nan 1280d20deb64SArnaldo Carvalho de Melo /* 1281d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1282d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1283b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1284d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1285d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1286d20deb64SArnaldo Carvalho de Melo */ 1287e5b2c207SNamhyung Kim struct option __record_options[] = { 1288d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 128986470930SIngo Molnar "event selector. use 'perf list' to list available events", 1290f120f9d5SJiri Olsa parse_events_option), 1291d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1292c171b552SLi Zefan "event filter", parse_filter), 12934ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 12944ba1faa1SWang Nan NULL, "don't record events from perf itself", 12954ba1faa1SWang Nan exclude_perf), 1296bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1297d6d901c2SZhang, Yanmin "record events on existing process id"), 1298bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1299d6d901c2SZhang, Yanmin "record events on existing thread id"), 1300d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 130186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1302509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1303acac03faSKirill Smelkov "collect data without buffering"), 1304d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1305daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1306bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 130786470930SIngo Molnar "system-wide collection from all CPUs"), 1308bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1309c45c6ea2SStephane Eranian "list of cpus to monitor"), 1310d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1311f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 131286470930SIngo Molnar "output file name"), 131369e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 131469e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 13152e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1316d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1317e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1318e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1319e9db1310SAdrian Hunter record__parse_mmap_pages), 1320d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 132143bece79SLin Ming "put the counters into a counter group"), 13222ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 132309b0fd45SJiri Olsa NULL, "enables call-graph recording" , 132409b0fd45SJiri Olsa &record_callchain_opt), 132509b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 132676a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 132709b0fd45SJiri Olsa &record_parse_callchain_opt), 1328c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 13293da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1330b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1331d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1332649c48a9SPeter Zijlstra "per thread counts"), 133356100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 13343abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 13353abebc55SAdrian Hunter &record.opts.sample_time_set, 13363abebc55SAdrian Hunter "Record the sample timestamps"), 133756100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1338d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1339649c48a9SPeter Zijlstra "don't sample"), 1340d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1341d2db9a98SWang Nan &record.no_buildid_cache_set, 1342a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1343d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1344d2db9a98SWang Nan &record.no_buildid_set, 1345baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1346d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1347023695d9SStephane Eranian "monitor event in cgroup name only", 1348023695d9SStephane Eranian parse_cgroups), 1349a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 13506619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1351bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1352bea03405SNamhyung Kim "user to profile"), 1353a5aabdacSStephane Eranian 1354a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1355a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1356a5aabdacSStephane Eranian parse_branch_stack), 1357a5aabdacSStephane Eranian 1358a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1359a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1360bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 136105484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 136205484298SAndi Kleen "sample by weight (on special events only)"), 1363475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1364475eeab9SAndi Kleen "sample transaction flags (special events only)"), 13653aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 13663aa5939dSAdrian Hunter "use per-thread mmaps"), 1367bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1368bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1369bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 137085c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 137185c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1372814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1373814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1374814c8c38SPeter Zijlstra parse_clockid), 13752dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 13762dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 13779d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 13789d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1379b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1380b757bb09SAdrian Hunter "Record context switch events"), 138185723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 138285723885SJiri Olsa "Configure all used events to run in kernel space.", 138385723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 138485723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 138585723885SJiri Olsa "Configure all used events to run in user space.", 138685723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 138771dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 138871dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 138971dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 139071dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 13917efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 13927efe0e03SHe Kuang "file", "vmlinux pathname"), 13936156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 13946156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1395ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1396ecfd7a9cSWang Nan "append timestamp to output filename"), 13973c1cb7e3SWang Nan OPT_BOOLEAN(0, "switch-output", &record.switch_output, 13983c1cb7e3SWang Nan "Switch output when receive SIGUSR2"), 13990aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 14000aab2136SWang Nan "Parse options then exit"), 140186470930SIngo Molnar OPT_END() 140286470930SIngo Molnar }; 140386470930SIngo Molnar 1404e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1405e5b2c207SNamhyung Kim 14061d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 140786470930SIngo Molnar { 1408ef149c25SAdrian Hunter int err; 14098c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 141016ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 141186470930SIngo Molnar 141248e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 141348e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 141448e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 141548e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 141648e1cab1SWang Nan # undef set_nobuild 141748e1cab1SWang Nan #endif 141848e1cab1SWang Nan 14197efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 14207efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 14217efe0e03SHe Kuang # define REASON "NO_DWARF=1" 14227efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 14237efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 14247efe0e03SHe Kuang # else 14257efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 14267efe0e03SHe Kuang # endif 14277efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 14287efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 14297efe0e03SHe Kuang # undef set_nobuild 14307efe0e03SHe Kuang # undef REASON 14317efe0e03SHe Kuang #endif 14327efe0e03SHe Kuang 14333e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 14343e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1435361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1436361c99a6SArnaldo Carvalho de Melo 1437eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1438eb853e80SJiri Olsa 1439bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1440a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1441602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1442bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 144386470930SIngo Molnar 1444bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1445c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1446c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1447c7118369SNamhyung Kim 1448023695d9SStephane Eranian } 1449b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1450b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1451c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1452c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1453c7118369SNamhyung Kim return -EINVAL; 1454b757bb09SAdrian Hunter } 1455023695d9SStephane Eranian 1456eca857abSWang Nan if (rec->switch_output) 1457eca857abSWang Nan rec->timestamp_filename = true; 1458eca857abSWang Nan 1459ef149c25SAdrian Hunter if (!rec->itr) { 1460ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1461ef149c25SAdrian Hunter if (err) 1462ef149c25SAdrian Hunter return err; 1463ef149c25SAdrian Hunter } 1464ef149c25SAdrian Hunter 14652dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 14662dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 14672dd6d8a1SAdrian Hunter if (err) 14682dd6d8a1SAdrian Hunter return err; 14692dd6d8a1SAdrian Hunter 14700aab2136SWang Nan if (dry_run) 14710aab2136SWang Nan return 0; 14720aab2136SWang Nan 1473d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 1474d7888573SWang Nan if (err) { 1475d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1476d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 1477d7888573SWang Nan errbuf); 1478d7888573SWang Nan return err; 1479d7888573SWang Nan } 1480d7888573SWang Nan 1481ef149c25SAdrian Hunter err = -ENOMEM; 1482ef149c25SAdrian Hunter 14830a7e6d1bSNamhyung Kim symbol__init(NULL); 1484baa2f6ceSArnaldo Carvalho de Melo 1485ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1486646aaea6SArnaldo Carvalho de Melo pr_warning( 1487646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1488ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1489646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1490646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1491646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1492646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1493646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1494ec80fde7SArnaldo Carvalho de Melo 14950c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 1496a1ac1d3cSStephane Eranian disable_buildid_cache(); 14970c1d46a8SWang Nan } else if (rec->switch_output) { 14980c1d46a8SWang Nan /* 14990c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 15000c1d46a8SWang Nan * generation by default to reduce data file switching 15010c1d46a8SWang Nan * overhead. Still generate buildid if they are required 15020c1d46a8SWang Nan * explicitly using 15030c1d46a8SWang Nan * 15040c1d46a8SWang Nan * perf record --signal-trigger --no-no-buildid \ 15050c1d46a8SWang Nan * --no-no-buildid-cache 15060c1d46a8SWang Nan * 15070c1d46a8SWang Nan * Following code equals to: 15080c1d46a8SWang Nan * 15090c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 15100c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 15110c1d46a8SWang Nan * disable_buildid_cache(); 15120c1d46a8SWang Nan */ 15130c1d46a8SWang Nan bool disable = true; 15140c1d46a8SWang Nan 15150c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 15160c1d46a8SWang Nan disable = false; 15170c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 15180c1d46a8SWang Nan disable = false; 15190c1d46a8SWang Nan if (disable) { 15200c1d46a8SWang Nan rec->no_buildid = true; 15210c1d46a8SWang Nan rec->no_buildid_cache = true; 15220c1d46a8SWang Nan disable_buildid_cache(); 15230c1d46a8SWang Nan } 15240c1d46a8SWang Nan } 1525655000e7SArnaldo Carvalho de Melo 15263e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 15273e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 152869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 152969aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1530bbd36e5eSPeter Zijlstra } 153186470930SIngo Molnar 153269e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 153369e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 153469e7e5b0SAdrian Hunter 1535602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 153616ad2ffbSNamhyung Kim if (err) { 1537602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 153816ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 153916ad2ffbSNamhyung Kim } 15404bd0f2d2SNamhyung Kim 1541602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 154216ad2ffbSNamhyung Kim if (err) { 154316ad2ffbSNamhyung Kim int saved_errno = errno; 154416ad2ffbSNamhyung Kim 1545602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 15463780f488SNamhyung Kim ui__error("%s", errbuf); 154716ad2ffbSNamhyung Kim 154816ad2ffbSNamhyung Kim err = -saved_errno; 15498fa60e1fSNamhyung Kim goto out_symbol_exit; 155016ad2ffbSNamhyung Kim } 15510d37aa34SArnaldo Carvalho de Melo 155216ad2ffbSNamhyung Kim err = -ENOMEM; 15533e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1554dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 155569aad6f1SArnaldo Carvalho de Melo 1556ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1557ef149c25SAdrian Hunter if (err) 1558ef149c25SAdrian Hunter goto out_symbol_exit; 1559ef149c25SAdrian Hunter 15606156681bSNamhyung Kim /* 15616156681bSNamhyung Kim * We take all buildids when the file contains 15626156681bSNamhyung Kim * AUX area tracing data because we do not decode the 15636156681bSNamhyung Kim * trace because it would take too long. 15646156681bSNamhyung Kim */ 15656156681bSNamhyung Kim if (rec->opts.full_auxtrace) 15666156681bSNamhyung Kim rec->buildid_all = true; 15676156681bSNamhyung Kim 1568b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 156939d17dacSArnaldo Carvalho de Melo err = -EINVAL; 157003ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 15717e4ff9e3SMike Galbraith } 15727e4ff9e3SMike Galbraith 1573d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1574d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 157545604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1576d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1577ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 157839d17dacSArnaldo Carvalho de Melo return err; 157986470930SIngo Molnar } 15802dd6d8a1SAdrian Hunter 15812dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 15822dd6d8a1SAdrian Hunter { 15835f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 15845f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 15852dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 15865f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 15875f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 15885f9cf599SWang Nan } 15893c1cb7e3SWang Nan 15903c1cb7e3SWang Nan if (trigger_is_ready(&switch_output_trigger)) 15913c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 15922dd6d8a1SAdrian Hunter } 1593