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" 32f00898f4SAndi Kleen #include "util/parse-branch-options.h" 33bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3471dc2326SWang Nan #include "util/llvm-utils.h" 358690a2a7SWang Nan #include "util/bpf-loader.h" 36*d8871ea7SWang Nan #include "asm/bug.h" 377c6a1c65SPeter Zijlstra 3886470930SIngo Molnar #include <unistd.h> 3986470930SIngo Molnar #include <sched.h> 40a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 4186470930SIngo Molnar 4278da39faSBernhard Rosenkraenzer 438c6f45a7SArnaldo Carvalho de Melo struct record { 4445694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 45b4006796SArnaldo Carvalho de Melo struct record_opts opts; 46d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 47f5fc1412SJiri Olsa struct perf_data_file file; 48ef149c25SAdrian Hunter struct auxtrace_record *itr; 49d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 50d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 51d20deb64SArnaldo Carvalho de Melo const char *progname; 52d20deb64SArnaldo Carvalho de Melo int realtime_prio; 53d20deb64SArnaldo Carvalho de Melo bool no_buildid; 54d2db9a98SWang Nan bool no_buildid_set; 55d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 56d2db9a98SWang Nan bool no_buildid_cache_set; 576156681bSNamhyung Kim bool buildid_all; 589f065194SYang Shi unsigned long long samples; 590f82ebc4SArnaldo Carvalho de Melo }; 6086470930SIngo Molnar 618c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 62f5970550SPeter Zijlstra { 63cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 644f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 658d3eca20SDavid Ahern return -1; 668d3eca20SDavid Ahern } 67f5970550SPeter Zijlstra 68cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 698d3eca20SDavid Ahern return 0; 70f5970550SPeter Zijlstra } 71f5970550SPeter Zijlstra 7245694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 73d20deb64SArnaldo Carvalho de Melo union perf_event *event, 741d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 751d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 76234fbbf5SArnaldo Carvalho de Melo { 778c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 788c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 79234fbbf5SArnaldo Carvalho de Melo } 80234fbbf5SArnaldo Carvalho de Melo 81e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 8286470930SIngo Molnar { 83e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 847b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 857b8283b5SDavid Ahern u64 old = md->prev; 86918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8786470930SIngo Molnar unsigned long size; 8886470930SIngo Molnar void *buf; 898d3eca20SDavid Ahern int rc = 0; 9086470930SIngo Molnar 91dc82009aSArnaldo Carvalho de Melo if (old == head) 928d3eca20SDavid Ahern return 0; 9386470930SIngo Molnar 94d20deb64SArnaldo Carvalho de Melo rec->samples++; 9586470930SIngo Molnar 9686470930SIngo Molnar size = head - old; 9786470930SIngo Molnar 9886470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9986470930SIngo Molnar buf = &data[old & md->mask]; 10086470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10186470930SIngo Molnar old += size; 10286470930SIngo Molnar 1038c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1048d3eca20SDavid Ahern rc = -1; 1058d3eca20SDavid Ahern goto out; 1068d3eca20SDavid Ahern } 10786470930SIngo Molnar } 10886470930SIngo Molnar 10986470930SIngo Molnar buf = &data[old & md->mask]; 11086470930SIngo Molnar size = head - old; 11186470930SIngo Molnar old += size; 11286470930SIngo Molnar 1138c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1148d3eca20SDavid Ahern rc = -1; 1158d3eca20SDavid Ahern goto out; 1168d3eca20SDavid Ahern } 11786470930SIngo Molnar 11886470930SIngo Molnar md->prev = old; 119e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1208d3eca20SDavid Ahern out: 1218d3eca20SDavid Ahern return rc; 12286470930SIngo Molnar } 12386470930SIngo Molnar 1242dd6d8a1SAdrian Hunter static volatile int done; 1252dd6d8a1SAdrian Hunter static volatile int signr = -1; 1262dd6d8a1SAdrian Hunter static volatile int child_finished; 1272dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1282dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1292dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1302dd6d8a1SAdrian Hunter 1312dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1322dd6d8a1SAdrian Hunter { 1332dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1342dd6d8a1SAdrian Hunter child_finished = 1; 1352dd6d8a1SAdrian Hunter else 1362dd6d8a1SAdrian Hunter signr = sig; 1372dd6d8a1SAdrian Hunter 1382dd6d8a1SAdrian Hunter done = 1; 1392dd6d8a1SAdrian Hunter } 1402dd6d8a1SAdrian Hunter 1412dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1422dd6d8a1SAdrian Hunter { 1432dd6d8a1SAdrian Hunter if (signr == -1) 1442dd6d8a1SAdrian Hunter return; 1452dd6d8a1SAdrian Hunter 1462dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1472dd6d8a1SAdrian Hunter raise(signr); 1482dd6d8a1SAdrian Hunter } 1492dd6d8a1SAdrian Hunter 150e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 151e31f0d01SAdrian Hunter 152ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 153ef149c25SAdrian Hunter union perf_event *event, void *data1, 154ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 155ef149c25SAdrian Hunter { 156ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15799fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 158ef149c25SAdrian Hunter size_t padding; 159ef149c25SAdrian Hunter u8 pad[8] = {0}; 160ef149c25SAdrian Hunter 16199fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 16299fa2984SAdrian Hunter off_t file_offset; 16399fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 16499fa2984SAdrian Hunter int err; 16599fa2984SAdrian Hunter 16699fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16799fa2984SAdrian Hunter if (file_offset == -1) 16899fa2984SAdrian Hunter return -1; 16999fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 17099fa2984SAdrian Hunter event, file_offset); 17199fa2984SAdrian Hunter if (err) 17299fa2984SAdrian Hunter return err; 17399fa2984SAdrian Hunter } 17499fa2984SAdrian Hunter 175ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 176ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 177ef149c25SAdrian Hunter if (padding) 178ef149c25SAdrian Hunter padding = 8 - padding; 179ef149c25SAdrian Hunter 180ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 181ef149c25SAdrian Hunter record__write(rec, data1, len1); 182ef149c25SAdrian Hunter if (len2) 183ef149c25SAdrian Hunter record__write(rec, data2, len2); 184ef149c25SAdrian Hunter record__write(rec, &pad, padding); 185ef149c25SAdrian Hunter 186ef149c25SAdrian Hunter return 0; 187ef149c25SAdrian Hunter } 188ef149c25SAdrian Hunter 189ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 190ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 191ef149c25SAdrian Hunter { 192ef149c25SAdrian Hunter int ret; 193ef149c25SAdrian Hunter 194ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 195ef149c25SAdrian Hunter record__process_auxtrace); 196ef149c25SAdrian Hunter if (ret < 0) 197ef149c25SAdrian Hunter return ret; 198ef149c25SAdrian Hunter 199ef149c25SAdrian Hunter if (ret) 200ef149c25SAdrian Hunter rec->samples++; 201ef149c25SAdrian Hunter 202ef149c25SAdrian Hunter return 0; 203ef149c25SAdrian Hunter } 204ef149c25SAdrian Hunter 2052dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2062dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2072dd6d8a1SAdrian Hunter { 2082dd6d8a1SAdrian Hunter int ret; 2092dd6d8a1SAdrian Hunter 2102dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2112dd6d8a1SAdrian Hunter record__process_auxtrace, 2122dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2132dd6d8a1SAdrian Hunter if (ret < 0) 2142dd6d8a1SAdrian Hunter return ret; 2152dd6d8a1SAdrian Hunter 2162dd6d8a1SAdrian Hunter if (ret) 2172dd6d8a1SAdrian Hunter rec->samples++; 2182dd6d8a1SAdrian Hunter 2192dd6d8a1SAdrian Hunter return 0; 2202dd6d8a1SAdrian Hunter } 2212dd6d8a1SAdrian Hunter 2222dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2232dd6d8a1SAdrian Hunter { 2242dd6d8a1SAdrian Hunter int i; 2252dd6d8a1SAdrian Hunter int rc = 0; 2262dd6d8a1SAdrian Hunter 2272dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2282dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2292dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2302dd6d8a1SAdrian Hunter 2312dd6d8a1SAdrian Hunter if (!mm->base) 2322dd6d8a1SAdrian Hunter continue; 2332dd6d8a1SAdrian Hunter 2342dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2352dd6d8a1SAdrian Hunter rc = -1; 2362dd6d8a1SAdrian Hunter goto out; 2372dd6d8a1SAdrian Hunter } 2382dd6d8a1SAdrian Hunter } 2392dd6d8a1SAdrian Hunter out: 2402dd6d8a1SAdrian Hunter return rc; 2412dd6d8a1SAdrian Hunter } 2422dd6d8a1SAdrian Hunter 2432dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2442dd6d8a1SAdrian Hunter { 2452dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2462dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2472dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2482dd6d8a1SAdrian Hunter } else { 2492dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2502dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2512dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2522dd6d8a1SAdrian Hunter } 2532dd6d8a1SAdrian Hunter } 2542dd6d8a1SAdrian Hunter 255e31f0d01SAdrian Hunter #else 256e31f0d01SAdrian Hunter 257e31f0d01SAdrian Hunter static inline 258e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 259e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 260e31f0d01SAdrian Hunter { 261e31f0d01SAdrian Hunter return 0; 262e31f0d01SAdrian Hunter } 263e31f0d01SAdrian Hunter 2642dd6d8a1SAdrian Hunter static inline 2652dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2662dd6d8a1SAdrian Hunter { 2672dd6d8a1SAdrian Hunter } 2682dd6d8a1SAdrian Hunter 2692dd6d8a1SAdrian Hunter static inline 2702dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2712dd6d8a1SAdrian Hunter { 2722dd6d8a1SAdrian Hunter return 0; 2732dd6d8a1SAdrian Hunter } 2742dd6d8a1SAdrian Hunter 275e31f0d01SAdrian Hunter #endif 276e31f0d01SAdrian Hunter 2778c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 278dd7927f4SArnaldo Carvalho de Melo { 27956e52e85SArnaldo Carvalho de Melo char msg[512]; 2806a4bb04cSJiri Olsa struct perf_evsel *pos; 281d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 282d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 283b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2848d3eca20SDavid Ahern int rc = 0; 285dd7927f4SArnaldo Carvalho de Melo 286f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 287cac21425SJiri Olsa 2880050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2893da297a6SIngo Molnar try_again: 290d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 29156e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2923da297a6SIngo Molnar if (verbose) 293c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2943da297a6SIngo Molnar goto try_again; 2953da297a6SIngo Molnar } 296ca6a4258SDavid Ahern 29756e52e85SArnaldo Carvalho de Melo rc = -errno; 29856e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29956e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 30056e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3018d3eca20SDavid Ahern goto out; 3027c6a1c65SPeter Zijlstra } 3037c6a1c65SPeter Zijlstra } 3047c6a1c65SPeter Zijlstra 30523d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30623d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30723d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30835550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3098d3eca20SDavid Ahern rc = -1; 3108d3eca20SDavid Ahern goto out; 3110a102479SFrederic Weisbecker } 3120a102479SFrederic Weisbecker 313ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3142dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3152dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3168d3eca20SDavid Ahern if (errno == EPERM) { 3178d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31818e60939SNelson Elhage "Consider increasing " 31918e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 32018e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 321ef149c25SAdrian Hunter "(current value: %u,%u)\n", 322ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3238d3eca20SDavid Ahern rc = -errno; 3248d3eca20SDavid Ahern } else { 32535550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32635550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3278d3eca20SDavid Ahern rc = -errno; 3288d3eca20SDavid Ahern } 3298d3eca20SDavid Ahern goto out; 33018e60939SNelson Elhage } 3310a27d7f9SArnaldo Carvalho de Melo 332a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3337b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3348d3eca20SDavid Ahern out: 3358d3eca20SDavid Ahern return rc; 336a91e5431SArnaldo Carvalho de Melo } 337a91e5431SArnaldo Carvalho de Melo 338e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 339e3d59112SNamhyung Kim union perf_event *event, 340e3d59112SNamhyung Kim struct perf_sample *sample, 341e3d59112SNamhyung Kim struct perf_evsel *evsel, 342e3d59112SNamhyung Kim struct machine *machine) 343e3d59112SNamhyung Kim { 344e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 345e3d59112SNamhyung Kim 346e3d59112SNamhyung Kim rec->samples++; 347e3d59112SNamhyung Kim 348e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 349e3d59112SNamhyung Kim } 350e3d59112SNamhyung Kim 3518c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3526122e4e4SArnaldo Carvalho de Melo { 353f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 354f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3556122e4e4SArnaldo Carvalho de Melo 356457ae94aSHe Kuang if (file->size == 0) 3579f591fd7SArnaldo Carvalho de Melo return 0; 3589f591fd7SArnaldo Carvalho de Melo 35900dc8657SNamhyung Kim /* 36000dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 36100dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 36200dc8657SNamhyung Kim * we prefer the vmlinux path like 36300dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 36400dc8657SNamhyung Kim * 36500dc8657SNamhyung Kim * rather than build-id path (in debug directory). 36600dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 36700dc8657SNamhyung Kim */ 36800dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 36900dc8657SNamhyung Kim 3706156681bSNamhyung Kim /* 3716156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 3726156681bSNamhyung Kim * so no need to process samples. 3736156681bSNamhyung Kim */ 3746156681bSNamhyung Kim if (rec->buildid_all) 3756156681bSNamhyung Kim rec->tool.sample = NULL; 3766156681bSNamhyung Kim 377b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3786122e4e4SArnaldo Carvalho de Melo } 3796122e4e4SArnaldo Carvalho de Melo 3808115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 381a1645ce1SZhang, Yanmin { 382a1645ce1SZhang, Yanmin int err; 38345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 384a1645ce1SZhang, Yanmin /* 385a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 386a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 387a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 388a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 389a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 390a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 391a1645ce1SZhang, Yanmin */ 39245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 393743eb868SArnaldo Carvalho de Melo machine); 394a1645ce1SZhang, Yanmin if (err < 0) 395a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 397a1645ce1SZhang, Yanmin 398a1645ce1SZhang, Yanmin /* 399a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 400a1645ce1SZhang, Yanmin * have no _text sometimes. 401a1645ce1SZhang, Yanmin */ 40245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4030ae617beSAdrian Hunter machine); 404a1645ce1SZhang, Yanmin if (err < 0) 405a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 407a1645ce1SZhang, Yanmin } 408a1645ce1SZhang, Yanmin 40998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 41098402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 41198402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 41298402807SFrederic Weisbecker }; 41398402807SFrederic Weisbecker 4148c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 41598402807SFrederic Weisbecker { 416dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4170e2e63ddSPeter Zijlstra int i; 4188d3eca20SDavid Ahern int rc = 0; 41998402807SFrederic Weisbecker 420d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 421ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 422ef149c25SAdrian Hunter 4238d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 424e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4258d3eca20SDavid Ahern rc = -1; 4268d3eca20SDavid Ahern goto out; 4278d3eca20SDavid Ahern } 4288d3eca20SDavid Ahern } 429ef149c25SAdrian Hunter 4302dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 431ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 432ef149c25SAdrian Hunter rc = -1; 433ef149c25SAdrian Hunter goto out; 434ef149c25SAdrian Hunter } 43598402807SFrederic Weisbecker } 43698402807SFrederic Weisbecker 437dcabb507SJiri Olsa /* 438dcabb507SJiri Olsa * Mark the round finished in case we wrote 439dcabb507SJiri Olsa * at least one event. 440dcabb507SJiri Olsa */ 441dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4428c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4438d3eca20SDavid Ahern 4448d3eca20SDavid Ahern out: 4458d3eca20SDavid Ahern return rc; 44698402807SFrederic Weisbecker } 44798402807SFrederic Weisbecker 4488c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 44957706abcSDavid Ahern { 45057706abcSDavid Ahern struct perf_session *session = rec->session; 45157706abcSDavid Ahern int feat; 45257706abcSDavid Ahern 45357706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 45457706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 45557706abcSDavid Ahern 45657706abcSDavid Ahern if (rec->no_buildid) 45757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 45857706abcSDavid Ahern 4593e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 46057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 46157706abcSDavid Ahern 46257706abcSDavid Ahern if (!rec->opts.branch_stack) 46357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 464ef149c25SAdrian Hunter 465ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 466ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 467ffa517adSJiri Olsa 468ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 46957706abcSDavid Ahern } 47057706abcSDavid Ahern 471f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 472f33cbe72SArnaldo Carvalho de Melo 473f33cbe72SArnaldo Carvalho de Melo /* 474f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 475f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 476f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 477f33cbe72SArnaldo Carvalho de Melo */ 47845604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 47945604710SNamhyung Kim siginfo_t *info, 480f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 481f33cbe72SArnaldo Carvalho de Melo { 482f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 483f33cbe72SArnaldo Carvalho de Melo done = 1; 484f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 485f33cbe72SArnaldo Carvalho de Melo } 486f33cbe72SArnaldo Carvalho de Melo 4872dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 4882dd6d8a1SAdrian Hunter 4898c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 49086470930SIngo Molnar { 49157706abcSDavid Ahern int err; 49245604710SNamhyung Kim int status = 0; 4938b412664SPeter Zijlstra unsigned long waking = 0; 49446be604bSZhang, Yanmin const bool forks = argc > 0; 49523346f21SArnaldo Carvalho de Melo struct machine *machine; 49645694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 497b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 498f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 499d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 5006dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 50142aa276fSNamhyung Kim int fd; 50286470930SIngo Molnar 503d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 50433e49ea7SAndi Kleen 50545604710SNamhyung Kim atexit(record__sig_exit); 506f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 507f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 508804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 5092dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 5102dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 5112dd6d8a1SAdrian Hunter else 5122dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 513f5970550SPeter Zijlstra 514b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 51594c744b6SArnaldo Carvalho de Melo if (session == NULL) { 516ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 517a9a70bbcSArnaldo Carvalho de Melo return -1; 518a9a70bbcSArnaldo Carvalho de Melo } 519a9a70bbcSArnaldo Carvalho de Melo 52042aa276fSNamhyung Kim fd = perf_data_file__fd(file); 521d20deb64SArnaldo Carvalho de Melo rec->session = session; 522d20deb64SArnaldo Carvalho de Melo 5238c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 524330aa675SStephane Eranian 525d4db3f16SArnaldo Carvalho de Melo if (forks) { 5263e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 527f5fc1412SJiri Olsa argv, file->is_pipe, 528735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 52935b9d88eSArnaldo Carvalho de Melo if (err < 0) { 53035b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 53145604710SNamhyung Kim status = err; 53235b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 533856e9660SPeter Zijlstra } 534856e9660SPeter Zijlstra } 535856e9660SPeter Zijlstra 5368c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 5378d3eca20SDavid Ahern err = -1; 53845604710SNamhyung Kim goto out_child; 5398d3eca20SDavid Ahern } 54086470930SIngo Molnar 5418690a2a7SWang Nan err = bpf__apply_obj_config(); 5428690a2a7SWang Nan if (err) { 5438690a2a7SWang Nan char errbuf[BUFSIZ]; 5448690a2a7SWang Nan 5458690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 5468690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 5478690a2a7SWang Nan errbuf); 5488690a2a7SWang Nan goto out_child; 5498690a2a7SWang Nan } 5508690a2a7SWang Nan 551cca8482cSAdrian Hunter /* 552cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 553cca8482cSAdrian Hunter * evlist. 554cca8482cSAdrian Hunter */ 555cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 556cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 557cca8482cSAdrian Hunter rec->tool.ordered_events = false; 558cca8482cSAdrian Hunter } 559cca8482cSAdrian Hunter 5603e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 561a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 562a8bb559bSNamhyung Kim 563f5fc1412SJiri Olsa if (file->is_pipe) { 56442aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 565529870e3STom Zanussi if (err < 0) 56645604710SNamhyung Kim goto out_child; 567563aecb2SJiri Olsa } else { 56842aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 569d5eed904SArnaldo Carvalho de Melo if (err < 0) 57045604710SNamhyung Kim goto out_child; 571d5eed904SArnaldo Carvalho de Melo } 5727c6a1c65SPeter Zijlstra 573d3665498SDavid Ahern if (!rec->no_buildid 574e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 575d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 576e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5778d3eca20SDavid Ahern err = -1; 57845604710SNamhyung Kim goto out_child; 579e20960c0SRobert Richter } 580e20960c0SRobert Richter 58134ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 582743eb868SArnaldo Carvalho de Melo 583f5fc1412SJiri Olsa if (file->is_pipe) { 58445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 585a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5862c46dbb5STom Zanussi if (err < 0) { 5872c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 58845604710SNamhyung Kim goto out_child; 5892c46dbb5STom Zanussi } 590cd19a035STom Zanussi 5913e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 59263e0c771STom Zanussi /* 59363e0c771STom Zanussi * FIXME err <= 0 here actually means that 59463e0c771STom Zanussi * there were no tracepoints so its not really 59563e0c771STom Zanussi * an error, just that we don't need to 59663e0c771STom Zanussi * synthesize anything. We really have to 59763e0c771STom Zanussi * return this more properly and also 59863e0c771STom Zanussi * propagate errors that now are calling die() 59963e0c771STom Zanussi */ 60042aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 601743eb868SArnaldo Carvalho de Melo process_synthesized_event); 60263e0c771STom Zanussi if (err <= 0) { 60363e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 60445604710SNamhyung Kim goto out_child; 60563e0c771STom Zanussi } 606f34b9001SDavid Ahern rec->bytes_written += err; 6072c46dbb5STom Zanussi } 60863e0c771STom Zanussi } 6092c46dbb5STom Zanussi 610ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 611ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 612ef149c25SAdrian Hunter session, process_synthesized_event); 613ef149c25SAdrian Hunter if (err) 614ef149c25SAdrian Hunter goto out_delete_session; 615ef149c25SAdrian Hunter } 616ef149c25SAdrian Hunter 61745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 6180ae617beSAdrian Hunter machine); 619*d8871ea7SWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 620c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 621c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 62256b03f3cSArnaldo Carvalho de Melo 62345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 624743eb868SArnaldo Carvalho de Melo machine); 625*d8871ea7SWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 626c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 627c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 628c1a3a4b9SArnaldo Carvalho de Melo 6297e383de4SArnaldo Carvalho de Melo if (perf_guest) { 630876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 6317e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 6327e383de4SArnaldo Carvalho de Melo } 633b7cece76SArnaldo Carvalho de Melo 6343e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 6359d9cad76SKan Liang process_synthesized_event, opts->sample_address, 6369d9cad76SKan Liang opts->proc_map_timeout); 6378d3eca20SDavid Ahern if (err != 0) 63845604710SNamhyung Kim goto out_child; 6398d3eca20SDavid Ahern 640d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 64186470930SIngo Molnar struct sched_param param; 64286470930SIngo Molnar 643d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 64486470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6456beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6468d3eca20SDavid Ahern err = -1; 64745604710SNamhyung Kim goto out_child; 64886470930SIngo Molnar } 64986470930SIngo Molnar } 65086470930SIngo Molnar 651774cb499SJiri Olsa /* 652774cb499SJiri Olsa * When perf is starting the traced process, all the events 653774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 654774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 655774cb499SJiri Olsa */ 6566619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6573e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 658764e16a3SDavid Ahern 659856e9660SPeter Zijlstra /* 660856e9660SPeter Zijlstra * Let the child rip 661856e9660SPeter Zijlstra */ 662e803cf97SNamhyung Kim if (forks) { 663e5bed564SNamhyung Kim union perf_event *event; 664e5bed564SNamhyung Kim 665e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 666e5bed564SNamhyung Kim if (event == NULL) { 667e5bed564SNamhyung Kim err = -ENOMEM; 668e5bed564SNamhyung Kim goto out_child; 669e5bed564SNamhyung Kim } 670e5bed564SNamhyung Kim 671e803cf97SNamhyung Kim /* 672e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 673e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 674e803cf97SNamhyung Kim * cannot see a correct process name for those events. 675e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 676e803cf97SNamhyung Kim */ 677e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 678e803cf97SNamhyung Kim rec->evlist->workload.pid, 679e803cf97SNamhyung Kim process_synthesized_event, 680e803cf97SNamhyung Kim machine); 681e5bed564SNamhyung Kim free(event); 682e803cf97SNamhyung Kim 6833e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 684e803cf97SNamhyung Kim } 685856e9660SPeter Zijlstra 6866619a53eSAndi Kleen if (opts->initial_delay) { 6876619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 6886619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 6896619a53eSAndi Kleen } 6906619a53eSAndi Kleen 6912dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 692649c48a9SPeter Zijlstra for (;;) { 6939f065194SYang Shi unsigned long long hits = rec->samples; 69486470930SIngo Molnar 6958c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 6962dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6978d3eca20SDavid Ahern err = -1; 69845604710SNamhyung Kim goto out_child; 6998d3eca20SDavid Ahern } 70086470930SIngo Molnar 7012dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 7022dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 7032dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 7042dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 7052dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 7062dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 7072dd6d8a1SAdrian Hunter err = -1; 7082dd6d8a1SAdrian Hunter goto out_child; 7092dd6d8a1SAdrian Hunter } 7102dd6d8a1SAdrian Hunter } 7112dd6d8a1SAdrian Hunter 712d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 7136dcf45efSArnaldo Carvalho de Melo if (done || draining) 714649c48a9SPeter Zijlstra break; 715f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 716a515114fSJiri Olsa /* 717a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 718a515114fSJiri Olsa * number of returned events and interrupt error. 719a515114fSJiri Olsa */ 720a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 72145604710SNamhyung Kim err = 0; 7228b412664SPeter Zijlstra waking++; 7236dcf45efSArnaldo Carvalho de Melo 7246dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7256dcf45efSArnaldo Carvalho de Melo draining = true; 7268b412664SPeter Zijlstra } 7278b412664SPeter Zijlstra 728774cb499SJiri Olsa /* 729774cb499SJiri Olsa * When perf is starting the traced process, at the end events 730774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 731774cb499SJiri Olsa * disable events in this case. 732774cb499SJiri Olsa */ 733602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7342dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7353e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7362711926aSJiri Olsa disabled = true; 7372711926aSJiri Olsa } 7388b412664SPeter Zijlstra } 7392dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7408b412664SPeter Zijlstra 741f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 74235550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 743f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 744f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 745f33cbe72SArnaldo Carvalho de Melo err = -1; 74645604710SNamhyung Kim goto out_child; 747f33cbe72SArnaldo Carvalho de Melo } 748f33cbe72SArnaldo Carvalho de Melo 749e3d59112SNamhyung Kim if (!quiet) 7508b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 75186470930SIngo Molnar 75245604710SNamhyung Kim out_child: 75345604710SNamhyung Kim if (forks) { 75445604710SNamhyung Kim int exit_status; 75545604710SNamhyung Kim 75645604710SNamhyung Kim if (!child_finished) 75745604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 75845604710SNamhyung Kim 75945604710SNamhyung Kim wait(&exit_status); 76045604710SNamhyung Kim 76145604710SNamhyung Kim if (err < 0) 76245604710SNamhyung Kim status = err; 76345604710SNamhyung Kim else if (WIFEXITED(exit_status)) 76445604710SNamhyung Kim status = WEXITSTATUS(exit_status); 76545604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 76645604710SNamhyung Kim signr = WTERMSIG(exit_status); 76745604710SNamhyung Kim } else 76845604710SNamhyung Kim status = err; 76945604710SNamhyung Kim 770e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 771e3d59112SNamhyung Kim rec->samples = 0; 772e3d59112SNamhyung Kim 77345604710SNamhyung Kim if (!err && !file->is_pipe) { 77445604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 775457ae94aSHe Kuang file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 77645604710SNamhyung Kim 777cd10b289SAdrian Hunter if (!rec->no_buildid) { 77845604710SNamhyung Kim process_buildids(rec); 7796156681bSNamhyung Kim 7806156681bSNamhyung Kim if (rec->buildid_all) 781cd10b289SAdrian Hunter dsos__hit_all(rec->session); 782cd10b289SAdrian Hunter } 78342aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 78445604710SNamhyung Kim } 78539d17dacSArnaldo Carvalho de Melo 786e3d59112SNamhyung Kim if (!err && !quiet) { 787e3d59112SNamhyung Kim char samples[128]; 788e3d59112SNamhyung Kim 789ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 790e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 791e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 792e3d59112SNamhyung Kim else 793e3d59112SNamhyung Kim samples[0] = '\0'; 794e3d59112SNamhyung Kim 795e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 796e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 797e3d59112SNamhyung Kim file->path, samples); 798e3d59112SNamhyung Kim } 799e3d59112SNamhyung Kim 80039d17dacSArnaldo Carvalho de Melo out_delete_session: 80139d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 80245604710SNamhyung Kim return status; 80386470930SIngo Molnar } 80486470930SIngo Molnar 80572a128aaSNamhyung Kim static void callchain_debug(void) 80609b0fd45SJiri Olsa { 807aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 808a601fdffSJiri Olsa 80972a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 81026d33022SJiri Olsa 81172a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 81209b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 81372a128aaSNamhyung Kim callchain_param.dump_size); 81409b0fd45SJiri Olsa } 81509b0fd45SJiri Olsa 816c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 81709b0fd45SJiri Olsa const char *arg, 81809b0fd45SJiri Olsa int unset) 81909b0fd45SJiri Olsa { 82009b0fd45SJiri Olsa int ret; 821c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 82209b0fd45SJiri Olsa 823c421e80bSKan Liang record->callgraph_set = true; 82472a128aaSNamhyung Kim callchain_param.enabled = !unset; 825eb853e80SJiri Olsa 82609b0fd45SJiri Olsa /* --no-call-graph */ 82709b0fd45SJiri Olsa if (unset) { 82872a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 82909b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 83009b0fd45SJiri Olsa return 0; 83109b0fd45SJiri Olsa } 83209b0fd45SJiri Olsa 833c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 8345c0cf224SJiri Olsa if (!ret) { 8355c0cf224SJiri Olsa /* Enable data address sampling for DWARF unwind. */ 8365c0cf224SJiri Olsa if (callchain_param.record_mode == CALLCHAIN_DWARF) 8375c0cf224SJiri Olsa record->sample_address = true; 83872a128aaSNamhyung Kim callchain_debug(); 8395c0cf224SJiri Olsa } 84009b0fd45SJiri Olsa 84126d33022SJiri Olsa return ret; 84226d33022SJiri Olsa } 84326d33022SJiri Olsa 844c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 84509b0fd45SJiri Olsa const char *arg __maybe_unused, 84609b0fd45SJiri Olsa int unset __maybe_unused) 84709b0fd45SJiri Olsa { 848c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 849c421e80bSKan Liang 850c421e80bSKan Liang record->callgraph_set = true; 85172a128aaSNamhyung Kim callchain_param.enabled = true; 85209b0fd45SJiri Olsa 85372a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 85472a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 855eb853e80SJiri Olsa 85672a128aaSNamhyung Kim callchain_debug(); 85709b0fd45SJiri Olsa return 0; 85809b0fd45SJiri Olsa } 85909b0fd45SJiri Olsa 860eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 861eb853e80SJiri Olsa { 8627a29c087SNamhyung Kim struct record *rec = cb; 8637a29c087SNamhyung Kim 8647a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 8657a29c087SNamhyung Kim if (!strcmp(value, "cache")) 8667a29c087SNamhyung Kim rec->no_buildid_cache = false; 8677a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 8687a29c087SNamhyung Kim rec->no_buildid_cache = true; 8697a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 8707a29c087SNamhyung Kim rec->no_buildid = true; 8717a29c087SNamhyung Kim else 8727a29c087SNamhyung Kim return -1; 8737a29c087SNamhyung Kim return 0; 8747a29c087SNamhyung Kim } 875eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 8765a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 877eb853e80SJiri Olsa 878eb853e80SJiri Olsa return perf_default_config(var, value, cb); 879eb853e80SJiri Olsa } 880eb853e80SJiri Olsa 881814c8c38SPeter Zijlstra struct clockid_map { 882814c8c38SPeter Zijlstra const char *name; 883814c8c38SPeter Zijlstra int clockid; 884814c8c38SPeter Zijlstra }; 885814c8c38SPeter Zijlstra 886814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 887814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 888814c8c38SPeter Zijlstra 889814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 890814c8c38SPeter Zijlstra 891814c8c38SPeter Zijlstra 892814c8c38SPeter Zijlstra /* 893814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 894814c8c38SPeter Zijlstra */ 895814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 896814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 897814c8c38SPeter Zijlstra #endif 898814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 899814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 900814c8c38SPeter Zijlstra #endif 901814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 902814c8c38SPeter Zijlstra #define CLOCK_TAI 11 903814c8c38SPeter Zijlstra #endif 904814c8c38SPeter Zijlstra 905814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 906814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 907814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 908814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 909814c8c38SPeter Zijlstra 910814c8c38SPeter Zijlstra /* available for some events */ 911814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 912814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 913814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 914814c8c38SPeter Zijlstra 915814c8c38SPeter Zijlstra /* available for the lazy */ 916814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 917814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 918814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 919814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 920814c8c38SPeter Zijlstra 921814c8c38SPeter Zijlstra CLOCKID_END, 922814c8c38SPeter Zijlstra }; 923814c8c38SPeter Zijlstra 924814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 925814c8c38SPeter Zijlstra { 926814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 927814c8c38SPeter Zijlstra const struct clockid_map *cm; 928814c8c38SPeter Zijlstra const char *ostr = str; 929814c8c38SPeter Zijlstra 930814c8c38SPeter Zijlstra if (unset) { 931814c8c38SPeter Zijlstra opts->use_clockid = 0; 932814c8c38SPeter Zijlstra return 0; 933814c8c38SPeter Zijlstra } 934814c8c38SPeter Zijlstra 935814c8c38SPeter Zijlstra /* no arg passed */ 936814c8c38SPeter Zijlstra if (!str) 937814c8c38SPeter Zijlstra return 0; 938814c8c38SPeter Zijlstra 939814c8c38SPeter Zijlstra /* no setting it twice */ 940814c8c38SPeter Zijlstra if (opts->use_clockid) 941814c8c38SPeter Zijlstra return -1; 942814c8c38SPeter Zijlstra 943814c8c38SPeter Zijlstra opts->use_clockid = true; 944814c8c38SPeter Zijlstra 945814c8c38SPeter Zijlstra /* if its a number, we're done */ 946814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 947814c8c38SPeter Zijlstra return 0; 948814c8c38SPeter Zijlstra 949814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 950814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 951814c8c38SPeter Zijlstra str += 6; 952814c8c38SPeter Zijlstra 953814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 954814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 955814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 956814c8c38SPeter Zijlstra return 0; 957814c8c38SPeter Zijlstra } 958814c8c38SPeter Zijlstra } 959814c8c38SPeter Zijlstra 960814c8c38SPeter Zijlstra opts->use_clockid = false; 961814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 962814c8c38SPeter Zijlstra return -1; 963814c8c38SPeter Zijlstra } 964814c8c38SPeter Zijlstra 965e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 966e9db1310SAdrian Hunter const char *str, 967e9db1310SAdrian Hunter int unset __maybe_unused) 968e9db1310SAdrian Hunter { 969e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 970e9db1310SAdrian Hunter char *s, *p; 971e9db1310SAdrian Hunter unsigned int mmap_pages; 972e9db1310SAdrian Hunter int ret; 973e9db1310SAdrian Hunter 974e9db1310SAdrian Hunter if (!str) 975e9db1310SAdrian Hunter return -EINVAL; 976e9db1310SAdrian Hunter 977e9db1310SAdrian Hunter s = strdup(str); 978e9db1310SAdrian Hunter if (!s) 979e9db1310SAdrian Hunter return -ENOMEM; 980e9db1310SAdrian Hunter 981e9db1310SAdrian Hunter p = strchr(s, ','); 982e9db1310SAdrian Hunter if (p) 983e9db1310SAdrian Hunter *p = '\0'; 984e9db1310SAdrian Hunter 985e9db1310SAdrian Hunter if (*s) { 986e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 987e9db1310SAdrian Hunter if (ret) 988e9db1310SAdrian Hunter goto out_free; 989e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 990e9db1310SAdrian Hunter } 991e9db1310SAdrian Hunter 992e9db1310SAdrian Hunter if (!p) { 993e9db1310SAdrian Hunter ret = 0; 994e9db1310SAdrian Hunter goto out_free; 995e9db1310SAdrian Hunter } 996e9db1310SAdrian Hunter 997e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 998e9db1310SAdrian Hunter if (ret) 999e9db1310SAdrian Hunter goto out_free; 1000e9db1310SAdrian Hunter 1001e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1002e9db1310SAdrian Hunter 1003e9db1310SAdrian Hunter out_free: 1004e9db1310SAdrian Hunter free(s); 1005e9db1310SAdrian Hunter return ret; 1006e9db1310SAdrian Hunter } 1007e9db1310SAdrian Hunter 1008e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 100986470930SIngo Molnar "perf record [<options>] [<command>]", 101086470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 101186470930SIngo Molnar NULL 101286470930SIngo Molnar }; 1013e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 101486470930SIngo Molnar 1015d20deb64SArnaldo Carvalho de Melo /* 10168c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 10178c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1018d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1019d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1020d20deb64SArnaldo Carvalho de Melo * 1021d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1022d20deb64SArnaldo Carvalho de Melo * 1023d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1024d20deb64SArnaldo Carvalho de Melo */ 10258c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1026d20deb64SArnaldo Carvalho de Melo .opts = { 10278affc2b8SAndi Kleen .sample_time = true, 1028d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1029d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1030d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1031447a6013SArnaldo Carvalho de Melo .freq = 4000, 1032d1cb9fceSNamhyung Kim .target = { 1033d1cb9fceSNamhyung Kim .uses_mmap = true, 10343aa5939dSAdrian Hunter .default_per_cpu = true, 1035d1cb9fceSNamhyung Kim }, 10369d9cad76SKan Liang .proc_map_timeout = 500, 1037d20deb64SArnaldo Carvalho de Melo }, 1038e3d59112SNamhyung Kim .tool = { 1039e3d59112SNamhyung Kim .sample = process_sample_event, 1040e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1041cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1042e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1043e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1044e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1045cca8482cSAdrian Hunter .ordered_events = true, 1046e3d59112SNamhyung Kim }, 1047d20deb64SArnaldo Carvalho de Melo }; 10487865e817SFrederic Weisbecker 104976a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 105076a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 105161eaa3beSArnaldo Carvalho de Melo 1052d20deb64SArnaldo Carvalho de Melo /* 1053d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1054d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1055b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1056d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1057d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1058d20deb64SArnaldo Carvalho de Melo */ 1059e5b2c207SNamhyung Kim struct option __record_options[] = { 1060d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 106186470930SIngo Molnar "event selector. use 'perf list' to list available events", 1062f120f9d5SJiri Olsa parse_events_option), 1063d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1064c171b552SLi Zefan "event filter", parse_filter), 10654ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10664ba1faa1SWang Nan NULL, "don't record events from perf itself", 10674ba1faa1SWang Nan exclude_perf), 1068bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1069d6d901c2SZhang, Yanmin "record events on existing process id"), 1070bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1071d6d901c2SZhang, Yanmin "record events on existing thread id"), 1072d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 107386470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1074509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1075acac03faSKirill Smelkov "collect data without buffering"), 1076d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1077daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1078bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 107986470930SIngo Molnar "system-wide collection from all CPUs"), 1080bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1081c45c6ea2SStephane Eranian "list of cpus to monitor"), 1082d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1083f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 108486470930SIngo Molnar "output file name"), 108569e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 108669e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 10872e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1088d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1089e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1090e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1091e9db1310SAdrian Hunter record__parse_mmap_pages), 1092d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 109343bece79SLin Ming "put the counters into a counter group"), 109409b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 109509b0fd45SJiri Olsa NULL, "enables call-graph recording" , 109609b0fd45SJiri Olsa &record_callchain_opt), 109709b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 109876a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 109909b0fd45SJiri Olsa &record_parse_callchain_opt), 1100c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 11013da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1102b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1103d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1104649c48a9SPeter Zijlstra "per thread counts"), 110556100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 11063abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 11073abebc55SAdrian Hunter &record.opts.sample_time_set, 11083abebc55SAdrian Hunter "Record the sample timestamps"), 110956100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1110d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1111649c48a9SPeter Zijlstra "don't sample"), 1112d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1113d2db9a98SWang Nan &record.no_buildid_cache_set, 1114a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1115d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1116d2db9a98SWang Nan &record.no_buildid_set, 1117baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1118d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1119023695d9SStephane Eranian "monitor event in cgroup name only", 1120023695d9SStephane Eranian parse_cgroups), 1121a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 11226619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1123bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1124bea03405SNamhyung Kim "user to profile"), 1125a5aabdacSStephane Eranian 1126a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1127a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1128a5aabdacSStephane Eranian parse_branch_stack), 1129a5aabdacSStephane Eranian 1130a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1131a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1132bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 113305484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 113405484298SAndi Kleen "sample by weight (on special events only)"), 1135475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1136475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11373aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11383aa5939dSAdrian Hunter "use per-thread mmaps"), 1139bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1140bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1141bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 114285c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 114385c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1144814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1145814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1146814c8c38SPeter Zijlstra parse_clockid), 11472dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11482dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11499d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11509d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1151b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1152b757bb09SAdrian Hunter "Record context switch events"), 115385723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 115485723885SJiri Olsa "Configure all used events to run in kernel space.", 115585723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 115685723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 115785723885SJiri Olsa "Configure all used events to run in user space.", 115885723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 115971dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 116071dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 116171dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 116271dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 11637efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 11647efe0e03SHe Kuang "file", "vmlinux pathname"), 11656156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 11666156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 116786470930SIngo Molnar OPT_END() 116886470930SIngo Molnar }; 116986470930SIngo Molnar 1170e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1171e5b2c207SNamhyung Kim 11721d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 117386470930SIngo Molnar { 1174ef149c25SAdrian Hunter int err; 11758c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 117616ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 117786470930SIngo Molnar 117848e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 117948e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 118048e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 118148e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 118248e1cab1SWang Nan # undef set_nobuild 118348e1cab1SWang Nan #endif 118448e1cab1SWang Nan 11857efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 11867efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 11877efe0e03SHe Kuang # define REASON "NO_DWARF=1" 11887efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 11897efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 11907efe0e03SHe Kuang # else 11917efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 11927efe0e03SHe Kuang # endif 11937efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 11947efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 11957efe0e03SHe Kuang # undef set_nobuild 11967efe0e03SHe Kuang # undef REASON 11977efe0e03SHe Kuang #endif 11987efe0e03SHe Kuang 11993e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 12003e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1201361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1202361c99a6SArnaldo Carvalho de Melo 1203eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1204eb853e80SJiri Olsa 1205bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1206a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1207602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1208bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 120986470930SIngo Molnar 1210bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1211c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1212c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1213c7118369SNamhyung Kim 1214023695d9SStephane Eranian } 1215b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1216b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1217c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1218c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1219c7118369SNamhyung Kim return -EINVAL; 1220b757bb09SAdrian Hunter } 1221023695d9SStephane Eranian 1222ef149c25SAdrian Hunter if (!rec->itr) { 1223ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1224ef149c25SAdrian Hunter if (err) 1225ef149c25SAdrian Hunter return err; 1226ef149c25SAdrian Hunter } 1227ef149c25SAdrian Hunter 12282dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 12292dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 12302dd6d8a1SAdrian Hunter if (err) 12312dd6d8a1SAdrian Hunter return err; 12322dd6d8a1SAdrian Hunter 1233ef149c25SAdrian Hunter err = -ENOMEM; 1234ef149c25SAdrian Hunter 12350a7e6d1bSNamhyung Kim symbol__init(NULL); 1236baa2f6ceSArnaldo Carvalho de Melo 1237ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1238646aaea6SArnaldo Carvalho de Melo pr_warning( 1239646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1240ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1241646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1242646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1243646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1244646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1245646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1246ec80fde7SArnaldo Carvalho de Melo 1247d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1248a1ac1d3cSStephane Eranian disable_buildid_cache(); 1249655000e7SArnaldo Carvalho de Melo 12503e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 12513e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 125269aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 125369aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1254bbd36e5eSPeter Zijlstra } 125586470930SIngo Molnar 125669e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 125769e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 125869e7e5b0SAdrian Hunter 1259602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 126016ad2ffbSNamhyung Kim if (err) { 1261602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 126216ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 126316ad2ffbSNamhyung Kim } 12644bd0f2d2SNamhyung Kim 1265602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 126616ad2ffbSNamhyung Kim if (err) { 126716ad2ffbSNamhyung Kim int saved_errno = errno; 126816ad2ffbSNamhyung Kim 1269602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 12703780f488SNamhyung Kim ui__error("%s", errbuf); 127116ad2ffbSNamhyung Kim 127216ad2ffbSNamhyung Kim err = -saved_errno; 12738fa60e1fSNamhyung Kim goto out_symbol_exit; 127416ad2ffbSNamhyung Kim } 12750d37aa34SArnaldo Carvalho de Melo 127616ad2ffbSNamhyung Kim err = -ENOMEM; 12773e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1278dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 127969aad6f1SArnaldo Carvalho de Melo 1280ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1281ef149c25SAdrian Hunter if (err) 1282ef149c25SAdrian Hunter goto out_symbol_exit; 1283ef149c25SAdrian Hunter 12846156681bSNamhyung Kim /* 12856156681bSNamhyung Kim * We take all buildids when the file contains 12866156681bSNamhyung Kim * AUX area tracing data because we do not decode the 12876156681bSNamhyung Kim * trace because it would take too long. 12886156681bSNamhyung Kim */ 12896156681bSNamhyung Kim if (rec->opts.full_auxtrace) 12906156681bSNamhyung Kim rec->buildid_all = true; 12916156681bSNamhyung Kim 1292b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 129339d17dacSArnaldo Carvalho de Melo err = -EINVAL; 129403ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 12957e4ff9e3SMike Galbraith } 12967e4ff9e3SMike Galbraith 1297d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1298d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 129945604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1300d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1301ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 130239d17dacSArnaldo Carvalho de Melo return err; 130386470930SIngo Molnar } 13042dd6d8a1SAdrian Hunter 13052dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 13062dd6d8a1SAdrian Hunter { 13072dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 13082dd6d8a1SAdrian Hunter return; 13092dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 13102dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 13112dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 13122dd6d8a1SAdrian Hunter } 1313