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" 1686470930SIngo Molnar 178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 197c6a1c65SPeter Zijlstra #include "util/header.h" 2066e274f3SFrederic Weisbecker #include "util/event.h" 21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 238f28827aSFrederic Weisbecker #include "util/debug.h" 2494c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 27a12b51c4SPaul Mackerras #include "util/cpumap.h" 28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 29f5fc1412SJiri Olsa #include "util/data.h" 30bcc84ec6SStephane Eranian #include "util/perf_regs.h" 31ef149c25SAdrian Hunter #include "util/auxtrace.h" 3246bc29b9SAdrian Hunter #include "util/tsc.h" 33f00898f4SAndi Kleen #include "util/parse-branch-options.h" 34bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3571dc2326SWang Nan #include "util/llvm-utils.h" 368690a2a7SWang Nan #include "util/bpf-loader.h" 37d8871ea7SWang Nan #include "asm/bug.h" 387c6a1c65SPeter Zijlstra 3986470930SIngo Molnar #include <unistd.h> 4086470930SIngo Molnar #include <sched.h> 41a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 4286470930SIngo Molnar 4378da39faSBernhard Rosenkraenzer 448c6f45a7SArnaldo Carvalho de Melo struct record { 4545694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 46b4006796SArnaldo Carvalho de Melo struct record_opts opts; 47d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 48f5fc1412SJiri Olsa struct perf_data_file file; 49ef149c25SAdrian Hunter struct auxtrace_record *itr; 50d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 51d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 52d20deb64SArnaldo Carvalho de Melo const char *progname; 53d20deb64SArnaldo Carvalho de Melo int realtime_prio; 54d20deb64SArnaldo Carvalho de Melo bool no_buildid; 55d2db9a98SWang Nan bool no_buildid_set; 56d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 57d2db9a98SWang Nan bool no_buildid_cache_set; 586156681bSNamhyung Kim bool buildid_all; 59ecfd7a9cSWang Nan bool timestamp_filename; 609f065194SYang Shi unsigned long long samples; 610f82ebc4SArnaldo Carvalho de Melo }; 6286470930SIngo Molnar 638c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 64f5970550SPeter Zijlstra { 65cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 664f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 678d3eca20SDavid Ahern return -1; 688d3eca20SDavid Ahern } 69f5970550SPeter Zijlstra 70cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 718d3eca20SDavid Ahern return 0; 72f5970550SPeter Zijlstra } 73f5970550SPeter Zijlstra 7445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 75d20deb64SArnaldo Carvalho de Melo union perf_event *event, 761d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 771d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 78234fbbf5SArnaldo Carvalho de Melo { 798c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 808c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 81234fbbf5SArnaldo Carvalho de Melo } 82234fbbf5SArnaldo Carvalho de Melo 83e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 8486470930SIngo Molnar { 85e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 867b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 877b8283b5SDavid Ahern u64 old = md->prev; 88918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8986470930SIngo Molnar unsigned long size; 9086470930SIngo Molnar void *buf; 918d3eca20SDavid Ahern int rc = 0; 9286470930SIngo Molnar 93dc82009aSArnaldo Carvalho de Melo if (old == head) 948d3eca20SDavid Ahern return 0; 9586470930SIngo Molnar 96d20deb64SArnaldo Carvalho de Melo rec->samples++; 9786470930SIngo Molnar 9886470930SIngo Molnar size = head - old; 9986470930SIngo Molnar 10086470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 10186470930SIngo Molnar buf = &data[old & md->mask]; 10286470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10386470930SIngo Molnar old += size; 10486470930SIngo Molnar 1058c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1068d3eca20SDavid Ahern rc = -1; 1078d3eca20SDavid Ahern goto out; 1088d3eca20SDavid Ahern } 10986470930SIngo Molnar } 11086470930SIngo Molnar 11186470930SIngo Molnar buf = &data[old & md->mask]; 11286470930SIngo Molnar size = head - old; 11386470930SIngo Molnar old += size; 11486470930SIngo Molnar 1158c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1168d3eca20SDavid Ahern rc = -1; 1178d3eca20SDavid Ahern goto out; 1188d3eca20SDavid Ahern } 11986470930SIngo Molnar 12086470930SIngo Molnar md->prev = old; 121e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1228d3eca20SDavid Ahern out: 1238d3eca20SDavid Ahern return rc; 12486470930SIngo Molnar } 12586470930SIngo Molnar 1262dd6d8a1SAdrian Hunter static volatile int done; 1272dd6d8a1SAdrian Hunter static volatile int signr = -1; 1282dd6d8a1SAdrian Hunter static volatile int child_finished; 129c0bdc1c4SWang Nan 130c0bdc1c4SWang Nan static volatile enum { 131c0bdc1c4SWang Nan AUXTRACE_SNAPSHOT_OFF = -1, 132c0bdc1c4SWang Nan AUXTRACE_SNAPSHOT_DISABLED = 0, 133c0bdc1c4SWang Nan AUXTRACE_SNAPSHOT_ENABLED = 1, 134c0bdc1c4SWang Nan } auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_OFF; 135c0bdc1c4SWang Nan 136c0bdc1c4SWang Nan static inline void 137c0bdc1c4SWang Nan auxtrace_snapshot_on(void) 138c0bdc1c4SWang Nan { 139c0bdc1c4SWang Nan auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED; 140c0bdc1c4SWang Nan } 141c0bdc1c4SWang Nan 142c0bdc1c4SWang Nan static inline void 143c0bdc1c4SWang Nan auxtrace_snapshot_enable(void) 144c0bdc1c4SWang Nan { 145c0bdc1c4SWang Nan if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) 146c0bdc1c4SWang Nan return; 147c0bdc1c4SWang Nan auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_ENABLED; 148c0bdc1c4SWang Nan } 149c0bdc1c4SWang Nan 150c0bdc1c4SWang Nan static inline void 151c0bdc1c4SWang Nan auxtrace_snapshot_disable(void) 152c0bdc1c4SWang Nan { 153c0bdc1c4SWang Nan if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) 154c0bdc1c4SWang Nan return; 155c0bdc1c4SWang Nan auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED; 156c0bdc1c4SWang Nan } 157c0bdc1c4SWang Nan 158c0bdc1c4SWang Nan static inline bool 159c0bdc1c4SWang Nan auxtrace_snapshot_is_enabled(void) 160c0bdc1c4SWang Nan { 161c0bdc1c4SWang Nan if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) 162c0bdc1c4SWang Nan return false; 163c0bdc1c4SWang Nan return auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_ENABLED; 164c0bdc1c4SWang Nan } 165c0bdc1c4SWang Nan 1662dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1672dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1682dd6d8a1SAdrian Hunter 1692dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1702dd6d8a1SAdrian Hunter { 1712dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1722dd6d8a1SAdrian Hunter child_finished = 1; 1732dd6d8a1SAdrian Hunter else 1742dd6d8a1SAdrian Hunter signr = sig; 1752dd6d8a1SAdrian Hunter 1762dd6d8a1SAdrian Hunter done = 1; 1772dd6d8a1SAdrian Hunter } 1782dd6d8a1SAdrian Hunter 1792dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1802dd6d8a1SAdrian Hunter { 1812dd6d8a1SAdrian Hunter if (signr == -1) 1822dd6d8a1SAdrian Hunter return; 1832dd6d8a1SAdrian Hunter 1842dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1852dd6d8a1SAdrian Hunter raise(signr); 1862dd6d8a1SAdrian Hunter } 1872dd6d8a1SAdrian Hunter 188e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 189e31f0d01SAdrian Hunter 190ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 191ef149c25SAdrian Hunter union perf_event *event, void *data1, 192ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 193ef149c25SAdrian Hunter { 194ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 19599fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 196ef149c25SAdrian Hunter size_t padding; 197ef149c25SAdrian Hunter u8 pad[8] = {0}; 198ef149c25SAdrian Hunter 19999fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 20099fa2984SAdrian Hunter off_t file_offset; 20199fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 20299fa2984SAdrian Hunter int err; 20399fa2984SAdrian Hunter 20499fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 20599fa2984SAdrian Hunter if (file_offset == -1) 20699fa2984SAdrian Hunter return -1; 20799fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 20899fa2984SAdrian Hunter event, file_offset); 20999fa2984SAdrian Hunter if (err) 21099fa2984SAdrian Hunter return err; 21199fa2984SAdrian Hunter } 21299fa2984SAdrian Hunter 213ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 214ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 215ef149c25SAdrian Hunter if (padding) 216ef149c25SAdrian Hunter padding = 8 - padding; 217ef149c25SAdrian Hunter 218ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 219ef149c25SAdrian Hunter record__write(rec, data1, len1); 220ef149c25SAdrian Hunter if (len2) 221ef149c25SAdrian Hunter record__write(rec, data2, len2); 222ef149c25SAdrian Hunter record__write(rec, &pad, padding); 223ef149c25SAdrian Hunter 224ef149c25SAdrian Hunter return 0; 225ef149c25SAdrian Hunter } 226ef149c25SAdrian Hunter 227ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 228ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 229ef149c25SAdrian Hunter { 230ef149c25SAdrian Hunter int ret; 231ef149c25SAdrian Hunter 232ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 233ef149c25SAdrian Hunter record__process_auxtrace); 234ef149c25SAdrian Hunter if (ret < 0) 235ef149c25SAdrian Hunter return ret; 236ef149c25SAdrian Hunter 237ef149c25SAdrian Hunter if (ret) 238ef149c25SAdrian Hunter rec->samples++; 239ef149c25SAdrian Hunter 240ef149c25SAdrian Hunter return 0; 241ef149c25SAdrian Hunter } 242ef149c25SAdrian Hunter 2432dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2442dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2452dd6d8a1SAdrian Hunter { 2462dd6d8a1SAdrian Hunter int ret; 2472dd6d8a1SAdrian Hunter 2482dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2492dd6d8a1SAdrian Hunter record__process_auxtrace, 2502dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2512dd6d8a1SAdrian Hunter if (ret < 0) 2522dd6d8a1SAdrian Hunter return ret; 2532dd6d8a1SAdrian Hunter 2542dd6d8a1SAdrian Hunter if (ret) 2552dd6d8a1SAdrian Hunter rec->samples++; 2562dd6d8a1SAdrian Hunter 2572dd6d8a1SAdrian Hunter return 0; 2582dd6d8a1SAdrian Hunter } 2592dd6d8a1SAdrian Hunter 2602dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2612dd6d8a1SAdrian Hunter { 2622dd6d8a1SAdrian Hunter int i; 2632dd6d8a1SAdrian Hunter int rc = 0; 2642dd6d8a1SAdrian Hunter 2652dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2662dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2672dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2682dd6d8a1SAdrian Hunter 2692dd6d8a1SAdrian Hunter if (!mm->base) 2702dd6d8a1SAdrian Hunter continue; 2712dd6d8a1SAdrian Hunter 2722dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2732dd6d8a1SAdrian Hunter rc = -1; 2742dd6d8a1SAdrian Hunter goto out; 2752dd6d8a1SAdrian Hunter } 2762dd6d8a1SAdrian Hunter } 2772dd6d8a1SAdrian Hunter out: 2782dd6d8a1SAdrian Hunter return rc; 2792dd6d8a1SAdrian Hunter } 2802dd6d8a1SAdrian Hunter 2812dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2822dd6d8a1SAdrian Hunter { 2832dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2842dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2852dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2862dd6d8a1SAdrian Hunter } else { 2872dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2882dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 289c0bdc1c4SWang Nan auxtrace_snapshot_enable(); 2902dd6d8a1SAdrian Hunter } 2912dd6d8a1SAdrian Hunter } 2922dd6d8a1SAdrian Hunter 293e31f0d01SAdrian Hunter #else 294e31f0d01SAdrian Hunter 295e31f0d01SAdrian Hunter static inline 296e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 297e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 298e31f0d01SAdrian Hunter { 299e31f0d01SAdrian Hunter return 0; 300e31f0d01SAdrian Hunter } 301e31f0d01SAdrian Hunter 3022dd6d8a1SAdrian Hunter static inline 3032dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 3042dd6d8a1SAdrian Hunter { 3052dd6d8a1SAdrian Hunter } 3062dd6d8a1SAdrian Hunter 3072dd6d8a1SAdrian Hunter static inline 3082dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 3092dd6d8a1SAdrian Hunter { 3102dd6d8a1SAdrian Hunter return 0; 3112dd6d8a1SAdrian Hunter } 3122dd6d8a1SAdrian Hunter 313e31f0d01SAdrian Hunter #endif 314e31f0d01SAdrian Hunter 3158c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 316dd7927f4SArnaldo Carvalho de Melo { 31756e52e85SArnaldo Carvalho de Melo char msg[512]; 3186a4bb04cSJiri Olsa struct perf_evsel *pos; 319d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 320d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 321b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 3228d3eca20SDavid Ahern int rc = 0; 323dd7927f4SArnaldo Carvalho de Melo 324e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 325cac21425SJiri Olsa 3260050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 3273da297a6SIngo Molnar try_again: 328d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 32956e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 3303da297a6SIngo Molnar if (verbose) 331c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 3323da297a6SIngo Molnar goto try_again; 3333da297a6SIngo Molnar } 334ca6a4258SDavid Ahern 33556e52e85SArnaldo Carvalho de Melo rc = -errno; 33656e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 33756e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 33856e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3398d3eca20SDavid Ahern goto out; 3407c6a1c65SPeter Zijlstra } 3417c6a1c65SPeter Zijlstra } 3427c6a1c65SPeter Zijlstra 34323d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 34423d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 34523d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 34635550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3478d3eca20SDavid Ahern rc = -1; 3488d3eca20SDavid Ahern goto out; 3490a102479SFrederic Weisbecker } 3500a102479SFrederic Weisbecker 351ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3522dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3532dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3548d3eca20SDavid Ahern if (errno == EPERM) { 3558d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 35618e60939SNelson Elhage "Consider increasing " 35718e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 35818e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 359ef149c25SAdrian Hunter "(current value: %u,%u)\n", 360ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3618d3eca20SDavid Ahern rc = -errno; 3628d3eca20SDavid Ahern } else { 36335550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 36435550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 36595c36561SWang Nan if (errno) 3668d3eca20SDavid Ahern rc = -errno; 36795c36561SWang Nan else 36895c36561SWang Nan rc = -EINVAL; 3698d3eca20SDavid Ahern } 3708d3eca20SDavid Ahern goto out; 37118e60939SNelson Elhage } 3720a27d7f9SArnaldo Carvalho de Melo 373a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3747b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3758d3eca20SDavid Ahern out: 3768d3eca20SDavid Ahern return rc; 377a91e5431SArnaldo Carvalho de Melo } 378a91e5431SArnaldo Carvalho de Melo 379e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 380e3d59112SNamhyung Kim union perf_event *event, 381e3d59112SNamhyung Kim struct perf_sample *sample, 382e3d59112SNamhyung Kim struct perf_evsel *evsel, 383e3d59112SNamhyung Kim struct machine *machine) 384e3d59112SNamhyung Kim { 385e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 386e3d59112SNamhyung Kim 387e3d59112SNamhyung Kim rec->samples++; 388e3d59112SNamhyung Kim 389e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 390e3d59112SNamhyung Kim } 391e3d59112SNamhyung Kim 3928c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3936122e4e4SArnaldo Carvalho de Melo { 394f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 395f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3966122e4e4SArnaldo Carvalho de Melo 397457ae94aSHe Kuang if (file->size == 0) 3989f591fd7SArnaldo Carvalho de Melo return 0; 3999f591fd7SArnaldo Carvalho de Melo 40000dc8657SNamhyung Kim /* 40100dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 40200dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 40300dc8657SNamhyung Kim * we prefer the vmlinux path like 40400dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 40500dc8657SNamhyung Kim * 40600dc8657SNamhyung Kim * rather than build-id path (in debug directory). 40700dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 40800dc8657SNamhyung Kim */ 40900dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 41000dc8657SNamhyung Kim 4116156681bSNamhyung Kim /* 4126156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 4136156681bSNamhyung Kim * so no need to process samples. 4146156681bSNamhyung Kim */ 4156156681bSNamhyung Kim if (rec->buildid_all) 4166156681bSNamhyung Kim rec->tool.sample = NULL; 4176156681bSNamhyung Kim 418b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 4196122e4e4SArnaldo Carvalho de Melo } 4206122e4e4SArnaldo Carvalho de Melo 4218115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 422a1645ce1SZhang, Yanmin { 423a1645ce1SZhang, Yanmin int err; 42445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 425a1645ce1SZhang, Yanmin /* 426a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 427a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 428a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 429a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 430a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 431a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 432a1645ce1SZhang, Yanmin */ 43345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 434743eb868SArnaldo Carvalho de Melo machine); 435a1645ce1SZhang, Yanmin if (err < 0) 436a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 43723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 438a1645ce1SZhang, Yanmin 439a1645ce1SZhang, Yanmin /* 440a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 441a1645ce1SZhang, Yanmin * have no _text sometimes. 442a1645ce1SZhang, Yanmin */ 44345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4440ae617beSAdrian Hunter machine); 445a1645ce1SZhang, Yanmin if (err < 0) 446a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 44723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 448a1645ce1SZhang, Yanmin } 449a1645ce1SZhang, Yanmin 45098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 45198402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 45298402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 45398402807SFrederic Weisbecker }; 45498402807SFrederic Weisbecker 4558c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 45698402807SFrederic Weisbecker { 457dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4580e2e63ddSPeter Zijlstra int i; 4598d3eca20SDavid Ahern int rc = 0; 46098402807SFrederic Weisbecker 461d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 462ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 463ef149c25SAdrian Hunter 4648d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 465e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4668d3eca20SDavid Ahern rc = -1; 4678d3eca20SDavid Ahern goto out; 4688d3eca20SDavid Ahern } 4698d3eca20SDavid Ahern } 470ef149c25SAdrian Hunter 4712dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 472ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 473ef149c25SAdrian Hunter rc = -1; 474ef149c25SAdrian Hunter goto out; 475ef149c25SAdrian Hunter } 47698402807SFrederic Weisbecker } 47798402807SFrederic Weisbecker 478dcabb507SJiri Olsa /* 479dcabb507SJiri Olsa * Mark the round finished in case we wrote 480dcabb507SJiri Olsa * at least one event. 481dcabb507SJiri Olsa */ 482dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4838c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4848d3eca20SDavid Ahern 4858d3eca20SDavid Ahern out: 4868d3eca20SDavid Ahern return rc; 48798402807SFrederic Weisbecker } 48898402807SFrederic Weisbecker 4898c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 49057706abcSDavid Ahern { 49157706abcSDavid Ahern struct perf_session *session = rec->session; 49257706abcSDavid Ahern int feat; 49357706abcSDavid Ahern 49457706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 49557706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 49657706abcSDavid Ahern 49757706abcSDavid Ahern if (rec->no_buildid) 49857706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 49957706abcSDavid Ahern 5003e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 50157706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 50257706abcSDavid Ahern 50357706abcSDavid Ahern if (!rec->opts.branch_stack) 50457706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 505ef149c25SAdrian Hunter 506ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 507ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 508ffa517adSJiri Olsa 509ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 51057706abcSDavid Ahern } 51157706abcSDavid Ahern 512e1ab48baSWang Nan static void 513e1ab48baSWang Nan record__finish_output(struct record *rec) 514e1ab48baSWang Nan { 515e1ab48baSWang Nan struct perf_data_file *file = &rec->file; 516e1ab48baSWang Nan int fd = perf_data_file__fd(file); 517e1ab48baSWang Nan 518e1ab48baSWang Nan if (file->is_pipe) 519e1ab48baSWang Nan return; 520e1ab48baSWang Nan 521e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 522e1ab48baSWang Nan file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 523e1ab48baSWang Nan 524e1ab48baSWang Nan if (!rec->no_buildid) { 525e1ab48baSWang Nan process_buildids(rec); 526e1ab48baSWang Nan 527e1ab48baSWang Nan if (rec->buildid_all) 528e1ab48baSWang Nan dsos__hit_all(rec->session); 529e1ab48baSWang Nan } 530e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 531e1ab48baSWang Nan 532e1ab48baSWang Nan return; 533e1ab48baSWang Nan } 534e1ab48baSWang Nan 535ecfd7a9cSWang Nan static int 536ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 537ecfd7a9cSWang Nan { 538ecfd7a9cSWang Nan struct perf_data_file *file = &rec->file; 539ecfd7a9cSWang Nan int fd, err; 540ecfd7a9cSWang Nan 541ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 542ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 543ecfd7a9cSWang Nan 544ecfd7a9cSWang Nan rec->samples = 0; 545ecfd7a9cSWang Nan record__finish_output(rec); 546ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 547ecfd7a9cSWang Nan if (err) { 548ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 549ecfd7a9cSWang Nan return -EINVAL; 550ecfd7a9cSWang Nan } 551ecfd7a9cSWang Nan 552ecfd7a9cSWang Nan fd = perf_data_file__switch(file, timestamp, 553ecfd7a9cSWang Nan rec->session->header.data_offset, 554ecfd7a9cSWang Nan at_exit); 555ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 556ecfd7a9cSWang Nan rec->bytes_written = 0; 557ecfd7a9cSWang Nan rec->session->header.data_size = 0; 558ecfd7a9cSWang Nan } 559ecfd7a9cSWang Nan 560ecfd7a9cSWang Nan if (!quiet) 561ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 562ecfd7a9cSWang Nan file->path, timestamp); 563ecfd7a9cSWang Nan return fd; 564ecfd7a9cSWang Nan } 565ecfd7a9cSWang Nan 566f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 567f33cbe72SArnaldo Carvalho de Melo 568f33cbe72SArnaldo Carvalho de Melo /* 569f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 570f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 571f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 572f33cbe72SArnaldo Carvalho de Melo */ 57345604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 57445604710SNamhyung Kim siginfo_t *info, 575f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 576f33cbe72SArnaldo Carvalho de Melo { 577f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 578f33cbe72SArnaldo Carvalho de Melo done = 1; 579f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 580f33cbe72SArnaldo Carvalho de Melo } 581f33cbe72SArnaldo Carvalho de Melo 5822dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 5832dd6d8a1SAdrian Hunter 58446bc29b9SAdrian Hunter int __weak 58546bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 58646bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 58746bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 58846bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 58946bc29b9SAdrian Hunter { 59046bc29b9SAdrian Hunter return 0; 59146bc29b9SAdrian Hunter } 59246bc29b9SAdrian Hunter 593c45c86ebSWang Nan static int record__synthesize(struct record *rec) 594c45c86ebSWang Nan { 595c45c86ebSWang Nan struct perf_session *session = rec->session; 596c45c86ebSWang Nan struct machine *machine = &session->machines.host; 597c45c86ebSWang Nan struct perf_data_file *file = &rec->file; 598c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 599c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 600c45c86ebSWang Nan int fd = perf_data_file__fd(file); 601c45c86ebSWang Nan int err = 0; 602c45c86ebSWang Nan 603c45c86ebSWang Nan if (file->is_pipe) { 604c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 605c45c86ebSWang Nan process_synthesized_event); 606c45c86ebSWang Nan if (err < 0) { 607c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 608c45c86ebSWang Nan goto out; 609c45c86ebSWang Nan } 610c45c86ebSWang Nan 611c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 612c45c86ebSWang Nan /* 613c45c86ebSWang Nan * FIXME err <= 0 here actually means that 614c45c86ebSWang Nan * there were no tracepoints so its not really 615c45c86ebSWang Nan * an error, just that we don't need to 616c45c86ebSWang Nan * synthesize anything. We really have to 617c45c86ebSWang Nan * return this more properly and also 618c45c86ebSWang Nan * propagate errors that now are calling die() 619c45c86ebSWang Nan */ 620c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 621c45c86ebSWang Nan process_synthesized_event); 622c45c86ebSWang Nan if (err <= 0) { 623c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 624c45c86ebSWang Nan goto out; 625c45c86ebSWang Nan } 626c45c86ebSWang Nan rec->bytes_written += err; 627c45c86ebSWang Nan } 628c45c86ebSWang Nan } 629c45c86ebSWang Nan 63046bc29b9SAdrian Hunter err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool, 63146bc29b9SAdrian Hunter process_synthesized_event, machine); 63246bc29b9SAdrian Hunter if (err) 63346bc29b9SAdrian Hunter goto out; 63446bc29b9SAdrian Hunter 635c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 636c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 637c45c86ebSWang Nan session, process_synthesized_event); 638c45c86ebSWang Nan if (err) 639c45c86ebSWang Nan goto out; 640c45c86ebSWang Nan } 641c45c86ebSWang Nan 642c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 643c45c86ebSWang Nan machine); 644c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 645c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 646c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 647c45c86ebSWang Nan 648c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 649c45c86ebSWang Nan machine); 650c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 651c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 652c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 653c45c86ebSWang Nan 654c45c86ebSWang Nan if (perf_guest) { 655c45c86ebSWang Nan machines__process_guests(&session->machines, 656c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 657c45c86ebSWang Nan } 658c45c86ebSWang Nan 659c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 660c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 661c45c86ebSWang Nan opts->proc_map_timeout); 662c45c86ebSWang Nan out: 663c45c86ebSWang Nan return err; 664c45c86ebSWang Nan } 665c45c86ebSWang Nan 6668c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 66786470930SIngo Molnar { 66857706abcSDavid Ahern int err; 66945604710SNamhyung Kim int status = 0; 6708b412664SPeter Zijlstra unsigned long waking = 0; 67146be604bSZhang, Yanmin const bool forks = argc > 0; 67223346f21SArnaldo Carvalho de Melo struct machine *machine; 67345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 674b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 675f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 676d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 6776dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 67842aa276fSNamhyung Kim int fd; 67986470930SIngo Molnar 680d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 68133e49ea7SAndi Kleen 68245604710SNamhyung Kim atexit(record__sig_exit); 683f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 684f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 685804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 686c0bdc1c4SWang Nan 687c0bdc1c4SWang Nan if (rec->opts.auxtrace_snapshot_mode) { 6882dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 689c0bdc1c4SWang Nan auxtrace_snapshot_on(); 690c0bdc1c4SWang Nan } else { 6912dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 692c0bdc1c4SWang Nan } 693f5970550SPeter Zijlstra 694b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 69594c744b6SArnaldo Carvalho de Melo if (session == NULL) { 696ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 697a9a70bbcSArnaldo Carvalho de Melo return -1; 698a9a70bbcSArnaldo Carvalho de Melo } 699a9a70bbcSArnaldo Carvalho de Melo 70042aa276fSNamhyung Kim fd = perf_data_file__fd(file); 701d20deb64SArnaldo Carvalho de Melo rec->session = session; 702d20deb64SArnaldo Carvalho de Melo 7038c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 704330aa675SStephane Eranian 705d4db3f16SArnaldo Carvalho de Melo if (forks) { 7063e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 707f5fc1412SJiri Olsa argv, file->is_pipe, 708735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 70935b9d88eSArnaldo Carvalho de Melo if (err < 0) { 71035b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 71145604710SNamhyung Kim status = err; 71235b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 713856e9660SPeter Zijlstra } 714856e9660SPeter Zijlstra } 715856e9660SPeter Zijlstra 7168c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 7178d3eca20SDavid Ahern err = -1; 71845604710SNamhyung Kim goto out_child; 7198d3eca20SDavid Ahern } 72086470930SIngo Molnar 7218690a2a7SWang Nan err = bpf__apply_obj_config(); 7228690a2a7SWang Nan if (err) { 7238690a2a7SWang Nan char errbuf[BUFSIZ]; 7248690a2a7SWang Nan 7258690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 7268690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 7278690a2a7SWang Nan errbuf); 7288690a2a7SWang Nan goto out_child; 7298690a2a7SWang Nan } 7308690a2a7SWang Nan 731cca8482cSAdrian Hunter /* 732cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 733cca8482cSAdrian Hunter * evlist. 734cca8482cSAdrian Hunter */ 735cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 736cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 737cca8482cSAdrian Hunter rec->tool.ordered_events = false; 738cca8482cSAdrian Hunter } 739cca8482cSAdrian Hunter 7403e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 741a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 742a8bb559bSNamhyung Kim 743f5fc1412SJiri Olsa if (file->is_pipe) { 74442aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 745529870e3STom Zanussi if (err < 0) 74645604710SNamhyung Kim goto out_child; 747563aecb2SJiri Olsa } else { 74842aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 749d5eed904SArnaldo Carvalho de Melo if (err < 0) 75045604710SNamhyung Kim goto out_child; 751d5eed904SArnaldo Carvalho de Melo } 7527c6a1c65SPeter Zijlstra 753d3665498SDavid Ahern if (!rec->no_buildid 754e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 755d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 756e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 7578d3eca20SDavid Ahern err = -1; 75845604710SNamhyung Kim goto out_child; 759e20960c0SRobert Richter } 760e20960c0SRobert Richter 76134ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 762743eb868SArnaldo Carvalho de Melo 763c45c86ebSWang Nan err = record__synthesize(rec); 764c45c86ebSWang Nan if (err < 0) 76545604710SNamhyung Kim goto out_child; 7668d3eca20SDavid Ahern 767d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 76886470930SIngo Molnar struct sched_param param; 76986470930SIngo Molnar 770d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 77186470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 7726beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 7738d3eca20SDavid Ahern err = -1; 77445604710SNamhyung Kim goto out_child; 77586470930SIngo Molnar } 77686470930SIngo Molnar } 77786470930SIngo Molnar 778774cb499SJiri Olsa /* 779774cb499SJiri Olsa * When perf is starting the traced process, all the events 780774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 781774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 782774cb499SJiri Olsa */ 7836619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 7843e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 785764e16a3SDavid Ahern 786856e9660SPeter Zijlstra /* 787856e9660SPeter Zijlstra * Let the child rip 788856e9660SPeter Zijlstra */ 789e803cf97SNamhyung Kim if (forks) { 790e5bed564SNamhyung Kim union perf_event *event; 791e5bed564SNamhyung Kim 792e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 793e5bed564SNamhyung Kim if (event == NULL) { 794e5bed564SNamhyung Kim err = -ENOMEM; 795e5bed564SNamhyung Kim goto out_child; 796e5bed564SNamhyung Kim } 797e5bed564SNamhyung Kim 798e803cf97SNamhyung Kim /* 799e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 800e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 801e803cf97SNamhyung Kim * cannot see a correct process name for those events. 802e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 803e803cf97SNamhyung Kim */ 804e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 805e803cf97SNamhyung Kim rec->evlist->workload.pid, 806e803cf97SNamhyung Kim process_synthesized_event, 807e803cf97SNamhyung Kim machine); 808e5bed564SNamhyung Kim free(event); 809e803cf97SNamhyung Kim 8103e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 811e803cf97SNamhyung Kim } 812856e9660SPeter Zijlstra 8136619a53eSAndi Kleen if (opts->initial_delay) { 8146619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 8156619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 8166619a53eSAndi Kleen } 8176619a53eSAndi Kleen 818c0bdc1c4SWang Nan auxtrace_snapshot_enable(); 819649c48a9SPeter Zijlstra for (;;) { 8209f065194SYang Shi unsigned long long hits = rec->samples; 82186470930SIngo Molnar 8228c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 823c0bdc1c4SWang Nan auxtrace_snapshot_disable(); 8248d3eca20SDavid Ahern err = -1; 82545604710SNamhyung Kim goto out_child; 8268d3eca20SDavid Ahern } 82786470930SIngo Molnar 8282dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 8292dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 8302dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 8312dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 8322dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 8332dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 8342dd6d8a1SAdrian Hunter err = -1; 8352dd6d8a1SAdrian Hunter goto out_child; 8362dd6d8a1SAdrian Hunter } 8372dd6d8a1SAdrian Hunter } 8382dd6d8a1SAdrian Hunter 839d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 8406dcf45efSArnaldo Carvalho de Melo if (done || draining) 841649c48a9SPeter Zijlstra break; 842f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 843a515114fSJiri Olsa /* 844a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 845a515114fSJiri Olsa * number of returned events and interrupt error. 846a515114fSJiri Olsa */ 847a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 84845604710SNamhyung Kim err = 0; 8498b412664SPeter Zijlstra waking++; 8506dcf45efSArnaldo Carvalho de Melo 8516dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 8526dcf45efSArnaldo Carvalho de Melo draining = true; 8538b412664SPeter Zijlstra } 8548b412664SPeter Zijlstra 855774cb499SJiri Olsa /* 856774cb499SJiri Olsa * When perf is starting the traced process, at the end events 857774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 858774cb499SJiri Olsa * disable events in this case. 859774cb499SJiri Olsa */ 860602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 861c0bdc1c4SWang Nan auxtrace_snapshot_disable(); 8623e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 8632711926aSJiri Olsa disabled = true; 8642711926aSJiri Olsa } 8658b412664SPeter Zijlstra } 866c0bdc1c4SWang Nan auxtrace_snapshot_disable(); 8678b412664SPeter Zijlstra 868f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 86935550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 870f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 871f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 872f33cbe72SArnaldo Carvalho de Melo err = -1; 87345604710SNamhyung Kim goto out_child; 874f33cbe72SArnaldo Carvalho de Melo } 875f33cbe72SArnaldo Carvalho de Melo 876e3d59112SNamhyung Kim if (!quiet) 8778b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 87886470930SIngo Molnar 87945604710SNamhyung Kim out_child: 88045604710SNamhyung Kim if (forks) { 88145604710SNamhyung Kim int exit_status; 88245604710SNamhyung Kim 88345604710SNamhyung Kim if (!child_finished) 88445604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 88545604710SNamhyung Kim 88645604710SNamhyung Kim wait(&exit_status); 88745604710SNamhyung Kim 88845604710SNamhyung Kim if (err < 0) 88945604710SNamhyung Kim status = err; 89045604710SNamhyung Kim else if (WIFEXITED(exit_status)) 89145604710SNamhyung Kim status = WEXITSTATUS(exit_status); 89245604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 89345604710SNamhyung Kim signr = WTERMSIG(exit_status); 89445604710SNamhyung Kim } else 89545604710SNamhyung Kim status = err; 89645604710SNamhyung Kim 897e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 898e3d59112SNamhyung Kim rec->samples = 0; 899e3d59112SNamhyung Kim 900ecfd7a9cSWang Nan if (!err) { 901ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 902e1ab48baSWang Nan record__finish_output(rec); 903ecfd7a9cSWang Nan } else { 904ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 905ecfd7a9cSWang Nan if (fd < 0) { 906ecfd7a9cSWang Nan status = fd; 907ecfd7a9cSWang Nan goto out_delete_session; 908ecfd7a9cSWang Nan } 909ecfd7a9cSWang Nan } 910ecfd7a9cSWang Nan } 91139d17dacSArnaldo Carvalho de Melo 912e3d59112SNamhyung Kim if (!err && !quiet) { 913e3d59112SNamhyung Kim char samples[128]; 914ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 915ecfd7a9cSWang Nan ".<timestamp>" : ""; 916e3d59112SNamhyung Kim 917ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 918e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 919e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 920e3d59112SNamhyung Kim else 921e3d59112SNamhyung Kim samples[0] = '\0'; 922e3d59112SNamhyung Kim 923ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 924e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 925ecfd7a9cSWang Nan file->path, postfix, samples); 926e3d59112SNamhyung Kim } 927e3d59112SNamhyung Kim 92839d17dacSArnaldo Carvalho de Melo out_delete_session: 92939d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 93045604710SNamhyung Kim return status; 93186470930SIngo Molnar } 93286470930SIngo Molnar 933*0883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 93409b0fd45SJiri Olsa { 935aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 936a601fdffSJiri Olsa 937*0883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 93826d33022SJiri Olsa 939*0883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 94009b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 941*0883e820SArnaldo Carvalho de Melo callchain->dump_size); 942*0883e820SArnaldo Carvalho de Melo } 943*0883e820SArnaldo Carvalho de Melo 944*0883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 945*0883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 946*0883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 947*0883e820SArnaldo Carvalho de Melo { 948*0883e820SArnaldo Carvalho de Melo int ret; 949*0883e820SArnaldo Carvalho de Melo record->callgraph_set = true; 950*0883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 951*0883e820SArnaldo Carvalho de Melo 952*0883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 953*0883e820SArnaldo Carvalho de Melo if (unset) { 954*0883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 955*0883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 956*0883e820SArnaldo Carvalho de Melo return 0; 957*0883e820SArnaldo Carvalho de Melo } 958*0883e820SArnaldo Carvalho de Melo 959*0883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 960*0883e820SArnaldo Carvalho de Melo if (!ret) { 961*0883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 962*0883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 963*0883e820SArnaldo Carvalho de Melo record->sample_address = true; 964*0883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 965*0883e820SArnaldo Carvalho de Melo } 966*0883e820SArnaldo Carvalho de Melo 967*0883e820SArnaldo Carvalho de Melo return ret; 96809b0fd45SJiri Olsa } 96909b0fd45SJiri Olsa 970c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 97109b0fd45SJiri Olsa const char *arg, 97209b0fd45SJiri Olsa int unset) 97309b0fd45SJiri Olsa { 974*0883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 97526d33022SJiri Olsa } 97626d33022SJiri Olsa 977c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 97809b0fd45SJiri Olsa const char *arg __maybe_unused, 97909b0fd45SJiri Olsa int unset __maybe_unused) 98009b0fd45SJiri Olsa { 981c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 982c421e80bSKan Liang 983c421e80bSKan Liang record->callgraph_set = true; 98472a128aaSNamhyung Kim callchain_param.enabled = true; 98509b0fd45SJiri Olsa 98672a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 98772a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 988eb853e80SJiri Olsa 989*0883e820SArnaldo Carvalho de Melo callchain_debug(&callchain_param); 99009b0fd45SJiri Olsa return 0; 99109b0fd45SJiri Olsa } 99209b0fd45SJiri Olsa 993eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 994eb853e80SJiri Olsa { 9957a29c087SNamhyung Kim struct record *rec = cb; 9967a29c087SNamhyung Kim 9977a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 9987a29c087SNamhyung Kim if (!strcmp(value, "cache")) 9997a29c087SNamhyung Kim rec->no_buildid_cache = false; 10007a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 10017a29c087SNamhyung Kim rec->no_buildid_cache = true; 10027a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 10037a29c087SNamhyung Kim rec->no_buildid = true; 10047a29c087SNamhyung Kim else 10057a29c087SNamhyung Kim return -1; 10067a29c087SNamhyung Kim return 0; 10077a29c087SNamhyung Kim } 1008eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 10095a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 1010eb853e80SJiri Olsa 1011eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1012eb853e80SJiri Olsa } 1013eb853e80SJiri Olsa 1014814c8c38SPeter Zijlstra struct clockid_map { 1015814c8c38SPeter Zijlstra const char *name; 1016814c8c38SPeter Zijlstra int clockid; 1017814c8c38SPeter Zijlstra }; 1018814c8c38SPeter Zijlstra 1019814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1020814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1021814c8c38SPeter Zijlstra 1022814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1023814c8c38SPeter Zijlstra 1024814c8c38SPeter Zijlstra 1025814c8c38SPeter Zijlstra /* 1026814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1027814c8c38SPeter Zijlstra */ 1028814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1029814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1030814c8c38SPeter Zijlstra #endif 1031814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1032814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1033814c8c38SPeter Zijlstra #endif 1034814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1035814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1036814c8c38SPeter Zijlstra #endif 1037814c8c38SPeter Zijlstra 1038814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1039814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1040814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1041814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1042814c8c38SPeter Zijlstra 1043814c8c38SPeter Zijlstra /* available for some events */ 1044814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1045814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1046814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1047814c8c38SPeter Zijlstra 1048814c8c38SPeter Zijlstra /* available for the lazy */ 1049814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1050814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1051814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1052814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1053814c8c38SPeter Zijlstra 1054814c8c38SPeter Zijlstra CLOCKID_END, 1055814c8c38SPeter Zijlstra }; 1056814c8c38SPeter Zijlstra 1057814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1058814c8c38SPeter Zijlstra { 1059814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1060814c8c38SPeter Zijlstra const struct clockid_map *cm; 1061814c8c38SPeter Zijlstra const char *ostr = str; 1062814c8c38SPeter Zijlstra 1063814c8c38SPeter Zijlstra if (unset) { 1064814c8c38SPeter Zijlstra opts->use_clockid = 0; 1065814c8c38SPeter Zijlstra return 0; 1066814c8c38SPeter Zijlstra } 1067814c8c38SPeter Zijlstra 1068814c8c38SPeter Zijlstra /* no arg passed */ 1069814c8c38SPeter Zijlstra if (!str) 1070814c8c38SPeter Zijlstra return 0; 1071814c8c38SPeter Zijlstra 1072814c8c38SPeter Zijlstra /* no setting it twice */ 1073814c8c38SPeter Zijlstra if (opts->use_clockid) 1074814c8c38SPeter Zijlstra return -1; 1075814c8c38SPeter Zijlstra 1076814c8c38SPeter Zijlstra opts->use_clockid = true; 1077814c8c38SPeter Zijlstra 1078814c8c38SPeter Zijlstra /* if its a number, we're done */ 1079814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1080814c8c38SPeter Zijlstra return 0; 1081814c8c38SPeter Zijlstra 1082814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1083814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1084814c8c38SPeter Zijlstra str += 6; 1085814c8c38SPeter Zijlstra 1086814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1087814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1088814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1089814c8c38SPeter Zijlstra return 0; 1090814c8c38SPeter Zijlstra } 1091814c8c38SPeter Zijlstra } 1092814c8c38SPeter Zijlstra 1093814c8c38SPeter Zijlstra opts->use_clockid = false; 1094814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1095814c8c38SPeter Zijlstra return -1; 1096814c8c38SPeter Zijlstra } 1097814c8c38SPeter Zijlstra 1098e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1099e9db1310SAdrian Hunter const char *str, 1100e9db1310SAdrian Hunter int unset __maybe_unused) 1101e9db1310SAdrian Hunter { 1102e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1103e9db1310SAdrian Hunter char *s, *p; 1104e9db1310SAdrian Hunter unsigned int mmap_pages; 1105e9db1310SAdrian Hunter int ret; 1106e9db1310SAdrian Hunter 1107e9db1310SAdrian Hunter if (!str) 1108e9db1310SAdrian Hunter return -EINVAL; 1109e9db1310SAdrian Hunter 1110e9db1310SAdrian Hunter s = strdup(str); 1111e9db1310SAdrian Hunter if (!s) 1112e9db1310SAdrian Hunter return -ENOMEM; 1113e9db1310SAdrian Hunter 1114e9db1310SAdrian Hunter p = strchr(s, ','); 1115e9db1310SAdrian Hunter if (p) 1116e9db1310SAdrian Hunter *p = '\0'; 1117e9db1310SAdrian Hunter 1118e9db1310SAdrian Hunter if (*s) { 1119e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1120e9db1310SAdrian Hunter if (ret) 1121e9db1310SAdrian Hunter goto out_free; 1122e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1123e9db1310SAdrian Hunter } 1124e9db1310SAdrian Hunter 1125e9db1310SAdrian Hunter if (!p) { 1126e9db1310SAdrian Hunter ret = 0; 1127e9db1310SAdrian Hunter goto out_free; 1128e9db1310SAdrian Hunter } 1129e9db1310SAdrian Hunter 1130e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1131e9db1310SAdrian Hunter if (ret) 1132e9db1310SAdrian Hunter goto out_free; 1133e9db1310SAdrian Hunter 1134e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1135e9db1310SAdrian Hunter 1136e9db1310SAdrian Hunter out_free: 1137e9db1310SAdrian Hunter free(s); 1138e9db1310SAdrian Hunter return ret; 1139e9db1310SAdrian Hunter } 1140e9db1310SAdrian Hunter 1141e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 114286470930SIngo Molnar "perf record [<options>] [<command>]", 114386470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 114486470930SIngo Molnar NULL 114586470930SIngo Molnar }; 1146e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 114786470930SIngo Molnar 1148d20deb64SArnaldo Carvalho de Melo /* 11498c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 11508c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1151d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1152d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1153d20deb64SArnaldo Carvalho de Melo * 1154d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1155d20deb64SArnaldo Carvalho de Melo * 1156d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1157d20deb64SArnaldo Carvalho de Melo */ 11588c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1159d20deb64SArnaldo Carvalho de Melo .opts = { 11608affc2b8SAndi Kleen .sample_time = true, 1161d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1162d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1163d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1164447a6013SArnaldo Carvalho de Melo .freq = 4000, 1165d1cb9fceSNamhyung Kim .target = { 1166d1cb9fceSNamhyung Kim .uses_mmap = true, 11673aa5939dSAdrian Hunter .default_per_cpu = true, 1168d1cb9fceSNamhyung Kim }, 11699d9cad76SKan Liang .proc_map_timeout = 500, 1170d20deb64SArnaldo Carvalho de Melo }, 1171e3d59112SNamhyung Kim .tool = { 1172e3d59112SNamhyung Kim .sample = process_sample_event, 1173e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1174cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1175e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1176e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1177e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1178cca8482cSAdrian Hunter .ordered_events = true, 1179e3d59112SNamhyung Kim }, 1180d20deb64SArnaldo Carvalho de Melo }; 11817865e817SFrederic Weisbecker 118276a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 118376a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 118461eaa3beSArnaldo Carvalho de Melo 1185d20deb64SArnaldo Carvalho de Melo /* 1186d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1187d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1188b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1189d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1190d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1191d20deb64SArnaldo Carvalho de Melo */ 1192e5b2c207SNamhyung Kim struct option __record_options[] = { 1193d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 119486470930SIngo Molnar "event selector. use 'perf list' to list available events", 1195f120f9d5SJiri Olsa parse_events_option), 1196d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1197c171b552SLi Zefan "event filter", parse_filter), 11984ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 11994ba1faa1SWang Nan NULL, "don't record events from perf itself", 12004ba1faa1SWang Nan exclude_perf), 1201bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1202d6d901c2SZhang, Yanmin "record events on existing process id"), 1203bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1204d6d901c2SZhang, Yanmin "record events on existing thread id"), 1205d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 120686470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1207509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1208acac03faSKirill Smelkov "collect data without buffering"), 1209d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1210daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1211bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 121286470930SIngo Molnar "system-wide collection from all CPUs"), 1213bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1214c45c6ea2SStephane Eranian "list of cpus to monitor"), 1215d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1216f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 121786470930SIngo Molnar "output file name"), 121869e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 121969e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 12202e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1221d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1222e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1223e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1224e9db1310SAdrian Hunter record__parse_mmap_pages), 1225d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 122643bece79SLin Ming "put the counters into a counter group"), 122709b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 122809b0fd45SJiri Olsa NULL, "enables call-graph recording" , 122909b0fd45SJiri Olsa &record_callchain_opt), 123009b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 123176a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 123209b0fd45SJiri Olsa &record_parse_callchain_opt), 1233c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 12343da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1235b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1236d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1237649c48a9SPeter Zijlstra "per thread counts"), 123856100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 12393abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 12403abebc55SAdrian Hunter &record.opts.sample_time_set, 12413abebc55SAdrian Hunter "Record the sample timestamps"), 124256100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1243d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1244649c48a9SPeter Zijlstra "don't sample"), 1245d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1246d2db9a98SWang Nan &record.no_buildid_cache_set, 1247a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1248d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1249d2db9a98SWang Nan &record.no_buildid_set, 1250baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1251d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1252023695d9SStephane Eranian "monitor event in cgroup name only", 1253023695d9SStephane Eranian parse_cgroups), 1254a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 12556619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1256bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1257bea03405SNamhyung Kim "user to profile"), 1258a5aabdacSStephane Eranian 1259a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1260a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1261a5aabdacSStephane Eranian parse_branch_stack), 1262a5aabdacSStephane Eranian 1263a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1264a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1265bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 126605484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 126705484298SAndi Kleen "sample by weight (on special events only)"), 1268475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1269475eeab9SAndi Kleen "sample transaction flags (special events only)"), 12703aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 12713aa5939dSAdrian Hunter "use per-thread mmaps"), 1272bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1273bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1274bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 127585c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 127685c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1277814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1278814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1279814c8c38SPeter Zijlstra parse_clockid), 12802dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 12812dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 12829d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 12839d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1284b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1285b757bb09SAdrian Hunter "Record context switch events"), 128685723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 128785723885SJiri Olsa "Configure all used events to run in kernel space.", 128885723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 128985723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 129085723885SJiri Olsa "Configure all used events to run in user space.", 129185723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 129271dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 129371dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 129471dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 129571dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 12967efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 12977efe0e03SHe Kuang "file", "vmlinux pathname"), 12986156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 12996156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1300ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1301ecfd7a9cSWang Nan "append timestamp to output filename"), 130286470930SIngo Molnar OPT_END() 130386470930SIngo Molnar }; 130486470930SIngo Molnar 1305e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1306e5b2c207SNamhyung Kim 13071d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 130886470930SIngo Molnar { 1309ef149c25SAdrian Hunter int err; 13108c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 131116ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 131286470930SIngo Molnar 131348e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 131448e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 131548e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 131648e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 131748e1cab1SWang Nan # undef set_nobuild 131848e1cab1SWang Nan #endif 131948e1cab1SWang Nan 13207efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 13217efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 13227efe0e03SHe Kuang # define REASON "NO_DWARF=1" 13237efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 13247efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 13257efe0e03SHe Kuang # else 13267efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 13277efe0e03SHe Kuang # endif 13287efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 13297efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 13307efe0e03SHe Kuang # undef set_nobuild 13317efe0e03SHe Kuang # undef REASON 13327efe0e03SHe Kuang #endif 13337efe0e03SHe Kuang 13343e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 13353e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1336361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1337361c99a6SArnaldo Carvalho de Melo 1338eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1339eb853e80SJiri Olsa 1340bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1341a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1342602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1343bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 134486470930SIngo Molnar 1345bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1346c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1347c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1348c7118369SNamhyung Kim 1349023695d9SStephane Eranian } 1350b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1351b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1352c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1353c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1354c7118369SNamhyung Kim return -EINVAL; 1355b757bb09SAdrian Hunter } 1356023695d9SStephane Eranian 1357ef149c25SAdrian Hunter if (!rec->itr) { 1358ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1359ef149c25SAdrian Hunter if (err) 1360ef149c25SAdrian Hunter return err; 1361ef149c25SAdrian Hunter } 1362ef149c25SAdrian Hunter 13632dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 13642dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 13652dd6d8a1SAdrian Hunter if (err) 13662dd6d8a1SAdrian Hunter return err; 13672dd6d8a1SAdrian Hunter 1368d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 1369d7888573SWang Nan if (err) { 1370d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1371d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 1372d7888573SWang Nan errbuf); 1373d7888573SWang Nan return err; 1374d7888573SWang Nan } 1375d7888573SWang Nan 1376ef149c25SAdrian Hunter err = -ENOMEM; 1377ef149c25SAdrian Hunter 13780a7e6d1bSNamhyung Kim symbol__init(NULL); 1379baa2f6ceSArnaldo Carvalho de Melo 1380ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1381646aaea6SArnaldo Carvalho de Melo pr_warning( 1382646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1383ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1384646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1385646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1386646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1387646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1388646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1389ec80fde7SArnaldo Carvalho de Melo 1390d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1391a1ac1d3cSStephane Eranian disable_buildid_cache(); 1392655000e7SArnaldo Carvalho de Melo 13933e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 13943e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 139569aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 139669aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1397bbd36e5eSPeter Zijlstra } 139886470930SIngo Molnar 139969e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 140069e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 140169e7e5b0SAdrian Hunter 1402602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 140316ad2ffbSNamhyung Kim if (err) { 1404602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 140516ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 140616ad2ffbSNamhyung Kim } 14074bd0f2d2SNamhyung Kim 1408602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 140916ad2ffbSNamhyung Kim if (err) { 141016ad2ffbSNamhyung Kim int saved_errno = errno; 141116ad2ffbSNamhyung Kim 1412602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 14133780f488SNamhyung Kim ui__error("%s", errbuf); 141416ad2ffbSNamhyung Kim 141516ad2ffbSNamhyung Kim err = -saved_errno; 14168fa60e1fSNamhyung Kim goto out_symbol_exit; 141716ad2ffbSNamhyung Kim } 14180d37aa34SArnaldo Carvalho de Melo 141916ad2ffbSNamhyung Kim err = -ENOMEM; 14203e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1421dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 142269aad6f1SArnaldo Carvalho de Melo 1423ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1424ef149c25SAdrian Hunter if (err) 1425ef149c25SAdrian Hunter goto out_symbol_exit; 1426ef149c25SAdrian Hunter 14276156681bSNamhyung Kim /* 14286156681bSNamhyung Kim * We take all buildids when the file contains 14296156681bSNamhyung Kim * AUX area tracing data because we do not decode the 14306156681bSNamhyung Kim * trace because it would take too long. 14316156681bSNamhyung Kim */ 14326156681bSNamhyung Kim if (rec->opts.full_auxtrace) 14336156681bSNamhyung Kim rec->buildid_all = true; 14346156681bSNamhyung Kim 1435b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 143639d17dacSArnaldo Carvalho de Melo err = -EINVAL; 143703ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 14387e4ff9e3SMike Galbraith } 14397e4ff9e3SMike Galbraith 1440d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1441d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 144245604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1443d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1444ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 144539d17dacSArnaldo Carvalho de Melo return err; 144686470930SIngo Molnar } 14472dd6d8a1SAdrian Hunter 14482dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 14492dd6d8a1SAdrian Hunter { 1450c0bdc1c4SWang Nan if (!auxtrace_snapshot_is_enabled()) 14512dd6d8a1SAdrian Hunter return; 1452c0bdc1c4SWang Nan auxtrace_snapshot_disable(); 14532dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 14542dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 14552dd6d8a1SAdrian Hunter } 1456