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" 35*8690a2a7SWang Nan #include "util/bpf-loader.h" 367c6a1c65SPeter Zijlstra 3786470930SIngo Molnar #include <unistd.h> 3886470930SIngo Molnar #include <sched.h> 39a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 4086470930SIngo Molnar 4178da39faSBernhard Rosenkraenzer 428c6f45a7SArnaldo Carvalho de Melo struct record { 4345694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 44b4006796SArnaldo Carvalho de Melo struct record_opts opts; 45d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 46f5fc1412SJiri Olsa struct perf_data_file file; 47ef149c25SAdrian Hunter struct auxtrace_record *itr; 48d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 49d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 50d20deb64SArnaldo Carvalho de Melo const char *progname; 51d20deb64SArnaldo Carvalho de Melo int realtime_prio; 52d20deb64SArnaldo Carvalho de Melo bool no_buildid; 53d2db9a98SWang Nan bool no_buildid_set; 54d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 55d2db9a98SWang Nan bool no_buildid_cache_set; 566156681bSNamhyung Kim bool buildid_all; 579f065194SYang Shi unsigned long long samples; 580f82ebc4SArnaldo Carvalho de Melo }; 5986470930SIngo Molnar 608c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 61f5970550SPeter Zijlstra { 62cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 634f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 648d3eca20SDavid Ahern return -1; 658d3eca20SDavid Ahern } 66f5970550SPeter Zijlstra 67cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 688d3eca20SDavid Ahern return 0; 69f5970550SPeter Zijlstra } 70f5970550SPeter Zijlstra 7145694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 72d20deb64SArnaldo Carvalho de Melo union perf_event *event, 731d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 741d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 75234fbbf5SArnaldo Carvalho de Melo { 768c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 778c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 78234fbbf5SArnaldo Carvalho de Melo } 79234fbbf5SArnaldo Carvalho de Melo 80e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 8186470930SIngo Molnar { 82e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 837b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 847b8283b5SDavid Ahern u64 old = md->prev; 85918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8686470930SIngo Molnar unsigned long size; 8786470930SIngo Molnar void *buf; 888d3eca20SDavid Ahern int rc = 0; 8986470930SIngo Molnar 90dc82009aSArnaldo Carvalho de Melo if (old == head) 918d3eca20SDavid Ahern return 0; 9286470930SIngo Molnar 93d20deb64SArnaldo Carvalho de Melo rec->samples++; 9486470930SIngo Molnar 9586470930SIngo Molnar size = head - old; 9686470930SIngo Molnar 9786470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9886470930SIngo Molnar buf = &data[old & md->mask]; 9986470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10086470930SIngo Molnar old += size; 10186470930SIngo Molnar 1028c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1038d3eca20SDavid Ahern rc = -1; 1048d3eca20SDavid Ahern goto out; 1058d3eca20SDavid Ahern } 10686470930SIngo Molnar } 10786470930SIngo Molnar 10886470930SIngo Molnar buf = &data[old & md->mask]; 10986470930SIngo Molnar size = head - old; 11086470930SIngo Molnar old += size; 11186470930SIngo Molnar 1128c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1138d3eca20SDavid Ahern rc = -1; 1148d3eca20SDavid Ahern goto out; 1158d3eca20SDavid Ahern } 11686470930SIngo Molnar 11786470930SIngo Molnar md->prev = old; 118e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1198d3eca20SDavid Ahern out: 1208d3eca20SDavid Ahern return rc; 12186470930SIngo Molnar } 12286470930SIngo Molnar 1232dd6d8a1SAdrian Hunter static volatile int done; 1242dd6d8a1SAdrian Hunter static volatile int signr = -1; 1252dd6d8a1SAdrian Hunter static volatile int child_finished; 1262dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1272dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1282dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1292dd6d8a1SAdrian Hunter 1302dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1312dd6d8a1SAdrian Hunter { 1322dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1332dd6d8a1SAdrian Hunter child_finished = 1; 1342dd6d8a1SAdrian Hunter else 1352dd6d8a1SAdrian Hunter signr = sig; 1362dd6d8a1SAdrian Hunter 1372dd6d8a1SAdrian Hunter done = 1; 1382dd6d8a1SAdrian Hunter } 1392dd6d8a1SAdrian Hunter 1402dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1412dd6d8a1SAdrian Hunter { 1422dd6d8a1SAdrian Hunter if (signr == -1) 1432dd6d8a1SAdrian Hunter return; 1442dd6d8a1SAdrian Hunter 1452dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1462dd6d8a1SAdrian Hunter raise(signr); 1472dd6d8a1SAdrian Hunter } 1482dd6d8a1SAdrian Hunter 149e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 150e31f0d01SAdrian Hunter 151ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 152ef149c25SAdrian Hunter union perf_event *event, void *data1, 153ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 154ef149c25SAdrian Hunter { 155ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15699fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 157ef149c25SAdrian Hunter size_t padding; 158ef149c25SAdrian Hunter u8 pad[8] = {0}; 159ef149c25SAdrian Hunter 16099fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 16199fa2984SAdrian Hunter off_t file_offset; 16299fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 16399fa2984SAdrian Hunter int err; 16499fa2984SAdrian Hunter 16599fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16699fa2984SAdrian Hunter if (file_offset == -1) 16799fa2984SAdrian Hunter return -1; 16899fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 16999fa2984SAdrian Hunter event, file_offset); 17099fa2984SAdrian Hunter if (err) 17199fa2984SAdrian Hunter return err; 17299fa2984SAdrian Hunter } 17399fa2984SAdrian Hunter 174ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 175ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 176ef149c25SAdrian Hunter if (padding) 177ef149c25SAdrian Hunter padding = 8 - padding; 178ef149c25SAdrian Hunter 179ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 180ef149c25SAdrian Hunter record__write(rec, data1, len1); 181ef149c25SAdrian Hunter if (len2) 182ef149c25SAdrian Hunter record__write(rec, data2, len2); 183ef149c25SAdrian Hunter record__write(rec, &pad, padding); 184ef149c25SAdrian Hunter 185ef149c25SAdrian Hunter return 0; 186ef149c25SAdrian Hunter } 187ef149c25SAdrian Hunter 188ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 189ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 190ef149c25SAdrian Hunter { 191ef149c25SAdrian Hunter int ret; 192ef149c25SAdrian Hunter 193ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 194ef149c25SAdrian Hunter record__process_auxtrace); 195ef149c25SAdrian Hunter if (ret < 0) 196ef149c25SAdrian Hunter return ret; 197ef149c25SAdrian Hunter 198ef149c25SAdrian Hunter if (ret) 199ef149c25SAdrian Hunter rec->samples++; 200ef149c25SAdrian Hunter 201ef149c25SAdrian Hunter return 0; 202ef149c25SAdrian Hunter } 203ef149c25SAdrian Hunter 2042dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2052dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2062dd6d8a1SAdrian Hunter { 2072dd6d8a1SAdrian Hunter int ret; 2082dd6d8a1SAdrian Hunter 2092dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2102dd6d8a1SAdrian Hunter record__process_auxtrace, 2112dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2122dd6d8a1SAdrian Hunter if (ret < 0) 2132dd6d8a1SAdrian Hunter return ret; 2142dd6d8a1SAdrian Hunter 2152dd6d8a1SAdrian Hunter if (ret) 2162dd6d8a1SAdrian Hunter rec->samples++; 2172dd6d8a1SAdrian Hunter 2182dd6d8a1SAdrian Hunter return 0; 2192dd6d8a1SAdrian Hunter } 2202dd6d8a1SAdrian Hunter 2212dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2222dd6d8a1SAdrian Hunter { 2232dd6d8a1SAdrian Hunter int i; 2242dd6d8a1SAdrian Hunter int rc = 0; 2252dd6d8a1SAdrian Hunter 2262dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2272dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2282dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2292dd6d8a1SAdrian Hunter 2302dd6d8a1SAdrian Hunter if (!mm->base) 2312dd6d8a1SAdrian Hunter continue; 2322dd6d8a1SAdrian Hunter 2332dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2342dd6d8a1SAdrian Hunter rc = -1; 2352dd6d8a1SAdrian Hunter goto out; 2362dd6d8a1SAdrian Hunter } 2372dd6d8a1SAdrian Hunter } 2382dd6d8a1SAdrian Hunter out: 2392dd6d8a1SAdrian Hunter return rc; 2402dd6d8a1SAdrian Hunter } 2412dd6d8a1SAdrian Hunter 2422dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2432dd6d8a1SAdrian Hunter { 2442dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2452dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2462dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2472dd6d8a1SAdrian Hunter } else { 2482dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2492dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2502dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2512dd6d8a1SAdrian Hunter } 2522dd6d8a1SAdrian Hunter } 2532dd6d8a1SAdrian Hunter 254e31f0d01SAdrian Hunter #else 255e31f0d01SAdrian Hunter 256e31f0d01SAdrian Hunter static inline 257e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 258e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 259e31f0d01SAdrian Hunter { 260e31f0d01SAdrian Hunter return 0; 261e31f0d01SAdrian Hunter } 262e31f0d01SAdrian Hunter 2632dd6d8a1SAdrian Hunter static inline 2642dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2652dd6d8a1SAdrian Hunter { 2662dd6d8a1SAdrian Hunter } 2672dd6d8a1SAdrian Hunter 2682dd6d8a1SAdrian Hunter static inline 2692dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2702dd6d8a1SAdrian Hunter { 2712dd6d8a1SAdrian Hunter return 0; 2722dd6d8a1SAdrian Hunter } 2732dd6d8a1SAdrian Hunter 274e31f0d01SAdrian Hunter #endif 275e31f0d01SAdrian Hunter 2768c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 277dd7927f4SArnaldo Carvalho de Melo { 27856e52e85SArnaldo Carvalho de Melo char msg[512]; 2796a4bb04cSJiri Olsa struct perf_evsel *pos; 280d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 281d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 282b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2838d3eca20SDavid Ahern int rc = 0; 284dd7927f4SArnaldo Carvalho de Melo 285f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 286cac21425SJiri Olsa 2870050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2883da297a6SIngo Molnar try_again: 289d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 29056e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2913da297a6SIngo Molnar if (verbose) 292c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2933da297a6SIngo Molnar goto try_again; 2943da297a6SIngo Molnar } 295ca6a4258SDavid Ahern 29656e52e85SArnaldo Carvalho de Melo rc = -errno; 29756e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29856e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 29956e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3008d3eca20SDavid Ahern goto out; 3017c6a1c65SPeter Zijlstra } 3027c6a1c65SPeter Zijlstra } 3037c6a1c65SPeter Zijlstra 30423d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30523d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30623d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30735550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3088d3eca20SDavid Ahern rc = -1; 3098d3eca20SDavid Ahern goto out; 3100a102479SFrederic Weisbecker } 3110a102479SFrederic Weisbecker 312ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3132dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3142dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3158d3eca20SDavid Ahern if (errno == EPERM) { 3168d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31718e60939SNelson Elhage "Consider increasing " 31818e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 31918e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 320ef149c25SAdrian Hunter "(current value: %u,%u)\n", 321ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3228d3eca20SDavid Ahern rc = -errno; 3238d3eca20SDavid Ahern } else { 32435550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32535550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3268d3eca20SDavid Ahern rc = -errno; 3278d3eca20SDavid Ahern } 3288d3eca20SDavid Ahern goto out; 32918e60939SNelson Elhage } 3300a27d7f9SArnaldo Carvalho de Melo 331a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3327b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3338d3eca20SDavid Ahern out: 3348d3eca20SDavid Ahern return rc; 335a91e5431SArnaldo Carvalho de Melo } 336a91e5431SArnaldo Carvalho de Melo 337e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 338e3d59112SNamhyung Kim union perf_event *event, 339e3d59112SNamhyung Kim struct perf_sample *sample, 340e3d59112SNamhyung Kim struct perf_evsel *evsel, 341e3d59112SNamhyung Kim struct machine *machine) 342e3d59112SNamhyung Kim { 343e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 344e3d59112SNamhyung Kim 345e3d59112SNamhyung Kim rec->samples++; 346e3d59112SNamhyung Kim 347e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 348e3d59112SNamhyung Kim } 349e3d59112SNamhyung Kim 3508c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3516122e4e4SArnaldo Carvalho de Melo { 352f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 353f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3546122e4e4SArnaldo Carvalho de Melo 355457ae94aSHe Kuang if (file->size == 0) 3569f591fd7SArnaldo Carvalho de Melo return 0; 3579f591fd7SArnaldo Carvalho de Melo 35800dc8657SNamhyung Kim /* 35900dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 36000dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 36100dc8657SNamhyung Kim * we prefer the vmlinux path like 36200dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 36300dc8657SNamhyung Kim * 36400dc8657SNamhyung Kim * rather than build-id path (in debug directory). 36500dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 36600dc8657SNamhyung Kim */ 36700dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 36800dc8657SNamhyung Kim 3696156681bSNamhyung Kim /* 3706156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 3716156681bSNamhyung Kim * so no need to process samples. 3726156681bSNamhyung Kim */ 3736156681bSNamhyung Kim if (rec->buildid_all) 3746156681bSNamhyung Kim rec->tool.sample = NULL; 3756156681bSNamhyung Kim 376b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3776122e4e4SArnaldo Carvalho de Melo } 3786122e4e4SArnaldo Carvalho de Melo 3798115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 380a1645ce1SZhang, Yanmin { 381a1645ce1SZhang, Yanmin int err; 38245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 383a1645ce1SZhang, Yanmin /* 384a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 385a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 386a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 387a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 388a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 389a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 390a1645ce1SZhang, Yanmin */ 39145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 392743eb868SArnaldo Carvalho de Melo machine); 393a1645ce1SZhang, Yanmin if (err < 0) 394a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39523346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 396a1645ce1SZhang, Yanmin 397a1645ce1SZhang, Yanmin /* 398a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 399a1645ce1SZhang, Yanmin * have no _text sometimes. 400a1645ce1SZhang, Yanmin */ 40145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4020ae617beSAdrian Hunter machine); 403a1645ce1SZhang, Yanmin if (err < 0) 404a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40523346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 406a1645ce1SZhang, Yanmin } 407a1645ce1SZhang, Yanmin 40898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 40998402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 41098402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 41198402807SFrederic Weisbecker }; 41298402807SFrederic Weisbecker 4138c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 41498402807SFrederic Weisbecker { 415dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4160e2e63ddSPeter Zijlstra int i; 4178d3eca20SDavid Ahern int rc = 0; 41898402807SFrederic Weisbecker 419d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 420ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 421ef149c25SAdrian Hunter 4228d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 423e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4248d3eca20SDavid Ahern rc = -1; 4258d3eca20SDavid Ahern goto out; 4268d3eca20SDavid Ahern } 4278d3eca20SDavid Ahern } 428ef149c25SAdrian Hunter 4292dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 430ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 431ef149c25SAdrian Hunter rc = -1; 432ef149c25SAdrian Hunter goto out; 433ef149c25SAdrian Hunter } 43498402807SFrederic Weisbecker } 43598402807SFrederic Weisbecker 436dcabb507SJiri Olsa /* 437dcabb507SJiri Olsa * Mark the round finished in case we wrote 438dcabb507SJiri Olsa * at least one event. 439dcabb507SJiri Olsa */ 440dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4418c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4428d3eca20SDavid Ahern 4438d3eca20SDavid Ahern out: 4448d3eca20SDavid Ahern return rc; 44598402807SFrederic Weisbecker } 44698402807SFrederic Weisbecker 4478c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 44857706abcSDavid Ahern { 44957706abcSDavid Ahern struct perf_session *session = rec->session; 45057706abcSDavid Ahern int feat; 45157706abcSDavid Ahern 45257706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 45357706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 45457706abcSDavid Ahern 45557706abcSDavid Ahern if (rec->no_buildid) 45657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 45757706abcSDavid Ahern 4583e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 45957706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 46057706abcSDavid Ahern 46157706abcSDavid Ahern if (!rec->opts.branch_stack) 46257706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 463ef149c25SAdrian Hunter 464ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 465ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 466ffa517adSJiri Olsa 467ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 46857706abcSDavid Ahern } 46957706abcSDavid Ahern 470f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 471f33cbe72SArnaldo Carvalho de Melo 472f33cbe72SArnaldo Carvalho de Melo /* 473f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 474f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 475f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 476f33cbe72SArnaldo Carvalho de Melo */ 47745604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 47845604710SNamhyung Kim siginfo_t *info, 479f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 480f33cbe72SArnaldo Carvalho de Melo { 481f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 482f33cbe72SArnaldo Carvalho de Melo done = 1; 483f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 484f33cbe72SArnaldo Carvalho de Melo } 485f33cbe72SArnaldo Carvalho de Melo 4862dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 4872dd6d8a1SAdrian Hunter 4888c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 48986470930SIngo Molnar { 49057706abcSDavid Ahern int err; 49145604710SNamhyung Kim int status = 0; 4928b412664SPeter Zijlstra unsigned long waking = 0; 49346be604bSZhang, Yanmin const bool forks = argc > 0; 49423346f21SArnaldo Carvalho de Melo struct machine *machine; 49545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 496b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 497f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 498d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 4996dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 50042aa276fSNamhyung Kim int fd; 50186470930SIngo Molnar 502d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 50333e49ea7SAndi Kleen 50445604710SNamhyung Kim atexit(record__sig_exit); 505f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 506f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 507804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 5082dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 5092dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 5102dd6d8a1SAdrian Hunter else 5112dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 512f5970550SPeter Zijlstra 513b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 51494c744b6SArnaldo Carvalho de Melo if (session == NULL) { 515ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 516a9a70bbcSArnaldo Carvalho de Melo return -1; 517a9a70bbcSArnaldo Carvalho de Melo } 518a9a70bbcSArnaldo Carvalho de Melo 51942aa276fSNamhyung Kim fd = perf_data_file__fd(file); 520d20deb64SArnaldo Carvalho de Melo rec->session = session; 521d20deb64SArnaldo Carvalho de Melo 5228c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 523330aa675SStephane Eranian 524d4db3f16SArnaldo Carvalho de Melo if (forks) { 5253e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 526f5fc1412SJiri Olsa argv, file->is_pipe, 527735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 52835b9d88eSArnaldo Carvalho de Melo if (err < 0) { 52935b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 53045604710SNamhyung Kim status = err; 53135b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 532856e9660SPeter Zijlstra } 533856e9660SPeter Zijlstra } 534856e9660SPeter Zijlstra 5358c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 5368d3eca20SDavid Ahern err = -1; 53745604710SNamhyung Kim goto out_child; 5388d3eca20SDavid Ahern } 53986470930SIngo Molnar 540*8690a2a7SWang Nan err = bpf__apply_obj_config(); 541*8690a2a7SWang Nan if (err) { 542*8690a2a7SWang Nan char errbuf[BUFSIZ]; 543*8690a2a7SWang Nan 544*8690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 545*8690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 546*8690a2a7SWang Nan errbuf); 547*8690a2a7SWang Nan goto out_child; 548*8690a2a7SWang Nan } 549*8690a2a7SWang Nan 550cca8482cSAdrian Hunter /* 551cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 552cca8482cSAdrian Hunter * evlist. 553cca8482cSAdrian Hunter */ 554cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 555cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 556cca8482cSAdrian Hunter rec->tool.ordered_events = false; 557cca8482cSAdrian Hunter } 558cca8482cSAdrian Hunter 5593e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 560a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 561a8bb559bSNamhyung Kim 562f5fc1412SJiri Olsa if (file->is_pipe) { 56342aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 564529870e3STom Zanussi if (err < 0) 56545604710SNamhyung Kim goto out_child; 566563aecb2SJiri Olsa } else { 56742aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 568d5eed904SArnaldo Carvalho de Melo if (err < 0) 56945604710SNamhyung Kim goto out_child; 570d5eed904SArnaldo Carvalho de Melo } 5717c6a1c65SPeter Zijlstra 572d3665498SDavid Ahern if (!rec->no_buildid 573e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 574d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 575e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5768d3eca20SDavid Ahern err = -1; 57745604710SNamhyung Kim goto out_child; 578e20960c0SRobert Richter } 579e20960c0SRobert Richter 58034ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 581743eb868SArnaldo Carvalho de Melo 582f5fc1412SJiri Olsa if (file->is_pipe) { 58345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 584a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5852c46dbb5STom Zanussi if (err < 0) { 5862c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 58745604710SNamhyung Kim goto out_child; 5882c46dbb5STom Zanussi } 589cd19a035STom Zanussi 5903e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 59163e0c771STom Zanussi /* 59263e0c771STom Zanussi * FIXME err <= 0 here actually means that 59363e0c771STom Zanussi * there were no tracepoints so its not really 59463e0c771STom Zanussi * an error, just that we don't need to 59563e0c771STom Zanussi * synthesize anything. We really have to 59663e0c771STom Zanussi * return this more properly and also 59763e0c771STom Zanussi * propagate errors that now are calling die() 59863e0c771STom Zanussi */ 59942aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 600743eb868SArnaldo Carvalho de Melo process_synthesized_event); 60163e0c771STom Zanussi if (err <= 0) { 60263e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 60345604710SNamhyung Kim goto out_child; 60463e0c771STom Zanussi } 605f34b9001SDavid Ahern rec->bytes_written += err; 6062c46dbb5STom Zanussi } 60763e0c771STom Zanussi } 6082c46dbb5STom Zanussi 609ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 610ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 611ef149c25SAdrian Hunter session, process_synthesized_event); 612ef149c25SAdrian Hunter if (err) 613ef149c25SAdrian Hunter goto out_delete_session; 614ef149c25SAdrian Hunter } 615ef149c25SAdrian Hunter 61645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 6170ae617beSAdrian Hunter machine); 618c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 619c1a3a4b9SArnaldo Carvalho de Melo pr_err("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); 625c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 626c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 627c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 628c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 629c1a3a4b9SArnaldo Carvalho de Melo 6307e383de4SArnaldo Carvalho de Melo if (perf_guest) { 631876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 6327e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 6337e383de4SArnaldo Carvalho de Melo } 634b7cece76SArnaldo Carvalho de Melo 6353e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 6369d9cad76SKan Liang process_synthesized_event, opts->sample_address, 6379d9cad76SKan Liang opts->proc_map_timeout); 6388d3eca20SDavid Ahern if (err != 0) 63945604710SNamhyung Kim goto out_child; 6408d3eca20SDavid Ahern 641d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 64286470930SIngo Molnar struct sched_param param; 64386470930SIngo Molnar 644d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 64586470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6466beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6478d3eca20SDavid Ahern err = -1; 64845604710SNamhyung Kim goto out_child; 64986470930SIngo Molnar } 65086470930SIngo Molnar } 65186470930SIngo Molnar 652774cb499SJiri Olsa /* 653774cb499SJiri Olsa * When perf is starting the traced process, all the events 654774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 655774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 656774cb499SJiri Olsa */ 6576619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6583e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 659764e16a3SDavid Ahern 660856e9660SPeter Zijlstra /* 661856e9660SPeter Zijlstra * Let the child rip 662856e9660SPeter Zijlstra */ 663e803cf97SNamhyung Kim if (forks) { 664e5bed564SNamhyung Kim union perf_event *event; 665e5bed564SNamhyung Kim 666e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 667e5bed564SNamhyung Kim if (event == NULL) { 668e5bed564SNamhyung Kim err = -ENOMEM; 669e5bed564SNamhyung Kim goto out_child; 670e5bed564SNamhyung Kim } 671e5bed564SNamhyung Kim 672e803cf97SNamhyung Kim /* 673e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 674e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 675e803cf97SNamhyung Kim * cannot see a correct process name for those events. 676e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 677e803cf97SNamhyung Kim */ 678e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 679e803cf97SNamhyung Kim rec->evlist->workload.pid, 680e803cf97SNamhyung Kim process_synthesized_event, 681e803cf97SNamhyung Kim machine); 682e5bed564SNamhyung Kim free(event); 683e803cf97SNamhyung Kim 6843e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 685e803cf97SNamhyung Kim } 686856e9660SPeter Zijlstra 6876619a53eSAndi Kleen if (opts->initial_delay) { 6886619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 6896619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 6906619a53eSAndi Kleen } 6916619a53eSAndi Kleen 6922dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 693649c48a9SPeter Zijlstra for (;;) { 6949f065194SYang Shi unsigned long long hits = rec->samples; 69586470930SIngo Molnar 6968c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 6972dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6988d3eca20SDavid Ahern err = -1; 69945604710SNamhyung Kim goto out_child; 7008d3eca20SDavid Ahern } 70186470930SIngo Molnar 7022dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 7032dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 7042dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 7052dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 7062dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 7072dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 7082dd6d8a1SAdrian Hunter err = -1; 7092dd6d8a1SAdrian Hunter goto out_child; 7102dd6d8a1SAdrian Hunter } 7112dd6d8a1SAdrian Hunter } 7122dd6d8a1SAdrian Hunter 713d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 7146dcf45efSArnaldo Carvalho de Melo if (done || draining) 715649c48a9SPeter Zijlstra break; 716f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 717a515114fSJiri Olsa /* 718a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 719a515114fSJiri Olsa * number of returned events and interrupt error. 720a515114fSJiri Olsa */ 721a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 72245604710SNamhyung Kim err = 0; 7238b412664SPeter Zijlstra waking++; 7246dcf45efSArnaldo Carvalho de Melo 7256dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7266dcf45efSArnaldo Carvalho de Melo draining = true; 7278b412664SPeter Zijlstra } 7288b412664SPeter Zijlstra 729774cb499SJiri Olsa /* 730774cb499SJiri Olsa * When perf is starting the traced process, at the end events 731774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 732774cb499SJiri Olsa * disable events in this case. 733774cb499SJiri Olsa */ 734602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7352dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7363e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7372711926aSJiri Olsa disabled = true; 7382711926aSJiri Olsa } 7398b412664SPeter Zijlstra } 7402dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7418b412664SPeter Zijlstra 742f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 74335550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 744f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 745f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 746f33cbe72SArnaldo Carvalho de Melo err = -1; 74745604710SNamhyung Kim goto out_child; 748f33cbe72SArnaldo Carvalho de Melo } 749f33cbe72SArnaldo Carvalho de Melo 750e3d59112SNamhyung Kim if (!quiet) 7518b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 75286470930SIngo Molnar 75345604710SNamhyung Kim out_child: 75445604710SNamhyung Kim if (forks) { 75545604710SNamhyung Kim int exit_status; 75645604710SNamhyung Kim 75745604710SNamhyung Kim if (!child_finished) 75845604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 75945604710SNamhyung Kim 76045604710SNamhyung Kim wait(&exit_status); 76145604710SNamhyung Kim 76245604710SNamhyung Kim if (err < 0) 76345604710SNamhyung Kim status = err; 76445604710SNamhyung Kim else if (WIFEXITED(exit_status)) 76545604710SNamhyung Kim status = WEXITSTATUS(exit_status); 76645604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 76745604710SNamhyung Kim signr = WTERMSIG(exit_status); 76845604710SNamhyung Kim } else 76945604710SNamhyung Kim status = err; 77045604710SNamhyung Kim 771e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 772e3d59112SNamhyung Kim rec->samples = 0; 773e3d59112SNamhyung Kim 77445604710SNamhyung Kim if (!err && !file->is_pipe) { 77545604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 776457ae94aSHe Kuang file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 77745604710SNamhyung Kim 778cd10b289SAdrian Hunter if (!rec->no_buildid) { 77945604710SNamhyung Kim process_buildids(rec); 7806156681bSNamhyung Kim 7816156681bSNamhyung Kim if (rec->buildid_all) 782cd10b289SAdrian Hunter dsos__hit_all(rec->session); 783cd10b289SAdrian Hunter } 78442aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 78545604710SNamhyung Kim } 78639d17dacSArnaldo Carvalho de Melo 787e3d59112SNamhyung Kim if (!err && !quiet) { 788e3d59112SNamhyung Kim char samples[128]; 789e3d59112SNamhyung Kim 790ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 791e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 792e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 793e3d59112SNamhyung Kim else 794e3d59112SNamhyung Kim samples[0] = '\0'; 795e3d59112SNamhyung Kim 796e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 797e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 798e3d59112SNamhyung Kim file->path, samples); 799e3d59112SNamhyung Kim } 800e3d59112SNamhyung Kim 80139d17dacSArnaldo Carvalho de Melo out_delete_session: 80239d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 80345604710SNamhyung Kim return status; 80486470930SIngo Molnar } 80586470930SIngo Molnar 80672a128aaSNamhyung Kim static void callchain_debug(void) 80709b0fd45SJiri Olsa { 808aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 809a601fdffSJiri Olsa 81072a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 81126d33022SJiri Olsa 81272a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 81309b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 81472a128aaSNamhyung Kim callchain_param.dump_size); 81509b0fd45SJiri Olsa } 81609b0fd45SJiri Olsa 817c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 81809b0fd45SJiri Olsa const char *arg, 81909b0fd45SJiri Olsa int unset) 82009b0fd45SJiri Olsa { 82109b0fd45SJiri Olsa int ret; 822c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 82309b0fd45SJiri Olsa 824c421e80bSKan Liang record->callgraph_set = true; 82572a128aaSNamhyung Kim callchain_param.enabled = !unset; 826eb853e80SJiri Olsa 82709b0fd45SJiri Olsa /* --no-call-graph */ 82809b0fd45SJiri Olsa if (unset) { 82972a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 83009b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 83109b0fd45SJiri Olsa return 0; 83209b0fd45SJiri Olsa } 83309b0fd45SJiri Olsa 834c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 8355c0cf224SJiri Olsa if (!ret) { 8365c0cf224SJiri Olsa /* Enable data address sampling for DWARF unwind. */ 8375c0cf224SJiri Olsa if (callchain_param.record_mode == CALLCHAIN_DWARF) 8385c0cf224SJiri Olsa record->sample_address = true; 83972a128aaSNamhyung Kim callchain_debug(); 8405c0cf224SJiri Olsa } 84109b0fd45SJiri Olsa 84226d33022SJiri Olsa return ret; 84326d33022SJiri Olsa } 84426d33022SJiri Olsa 845c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 84609b0fd45SJiri Olsa const char *arg __maybe_unused, 84709b0fd45SJiri Olsa int unset __maybe_unused) 84809b0fd45SJiri Olsa { 849c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 850c421e80bSKan Liang 851c421e80bSKan Liang record->callgraph_set = true; 85272a128aaSNamhyung Kim callchain_param.enabled = true; 85309b0fd45SJiri Olsa 85472a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 85572a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 856eb853e80SJiri Olsa 85772a128aaSNamhyung Kim callchain_debug(); 85809b0fd45SJiri Olsa return 0; 85909b0fd45SJiri Olsa } 86009b0fd45SJiri Olsa 861eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 862eb853e80SJiri Olsa { 8637a29c087SNamhyung Kim struct record *rec = cb; 8647a29c087SNamhyung Kim 8657a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 8667a29c087SNamhyung Kim if (!strcmp(value, "cache")) 8677a29c087SNamhyung Kim rec->no_buildid_cache = false; 8687a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 8697a29c087SNamhyung Kim rec->no_buildid_cache = true; 8707a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 8717a29c087SNamhyung Kim rec->no_buildid = true; 8727a29c087SNamhyung Kim else 8737a29c087SNamhyung Kim return -1; 8747a29c087SNamhyung Kim return 0; 8757a29c087SNamhyung Kim } 876eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 8775a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 878eb853e80SJiri Olsa 879eb853e80SJiri Olsa return perf_default_config(var, value, cb); 880eb853e80SJiri Olsa } 881eb853e80SJiri Olsa 882814c8c38SPeter Zijlstra struct clockid_map { 883814c8c38SPeter Zijlstra const char *name; 884814c8c38SPeter Zijlstra int clockid; 885814c8c38SPeter Zijlstra }; 886814c8c38SPeter Zijlstra 887814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 888814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 889814c8c38SPeter Zijlstra 890814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 891814c8c38SPeter Zijlstra 892814c8c38SPeter Zijlstra 893814c8c38SPeter Zijlstra /* 894814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 895814c8c38SPeter Zijlstra */ 896814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 897814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 898814c8c38SPeter Zijlstra #endif 899814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 900814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 901814c8c38SPeter Zijlstra #endif 902814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 903814c8c38SPeter Zijlstra #define CLOCK_TAI 11 904814c8c38SPeter Zijlstra #endif 905814c8c38SPeter Zijlstra 906814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 907814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 908814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 909814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 910814c8c38SPeter Zijlstra 911814c8c38SPeter Zijlstra /* available for some events */ 912814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 913814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 914814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 915814c8c38SPeter Zijlstra 916814c8c38SPeter Zijlstra /* available for the lazy */ 917814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 918814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 919814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 920814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 921814c8c38SPeter Zijlstra 922814c8c38SPeter Zijlstra CLOCKID_END, 923814c8c38SPeter Zijlstra }; 924814c8c38SPeter Zijlstra 925814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 926814c8c38SPeter Zijlstra { 927814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 928814c8c38SPeter Zijlstra const struct clockid_map *cm; 929814c8c38SPeter Zijlstra const char *ostr = str; 930814c8c38SPeter Zijlstra 931814c8c38SPeter Zijlstra if (unset) { 932814c8c38SPeter Zijlstra opts->use_clockid = 0; 933814c8c38SPeter Zijlstra return 0; 934814c8c38SPeter Zijlstra } 935814c8c38SPeter Zijlstra 936814c8c38SPeter Zijlstra /* no arg passed */ 937814c8c38SPeter Zijlstra if (!str) 938814c8c38SPeter Zijlstra return 0; 939814c8c38SPeter Zijlstra 940814c8c38SPeter Zijlstra /* no setting it twice */ 941814c8c38SPeter Zijlstra if (opts->use_clockid) 942814c8c38SPeter Zijlstra return -1; 943814c8c38SPeter Zijlstra 944814c8c38SPeter Zijlstra opts->use_clockid = true; 945814c8c38SPeter Zijlstra 946814c8c38SPeter Zijlstra /* if its a number, we're done */ 947814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 948814c8c38SPeter Zijlstra return 0; 949814c8c38SPeter Zijlstra 950814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 951814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 952814c8c38SPeter Zijlstra str += 6; 953814c8c38SPeter Zijlstra 954814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 955814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 956814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 957814c8c38SPeter Zijlstra return 0; 958814c8c38SPeter Zijlstra } 959814c8c38SPeter Zijlstra } 960814c8c38SPeter Zijlstra 961814c8c38SPeter Zijlstra opts->use_clockid = false; 962814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 963814c8c38SPeter Zijlstra return -1; 964814c8c38SPeter Zijlstra } 965814c8c38SPeter Zijlstra 966e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 967e9db1310SAdrian Hunter const char *str, 968e9db1310SAdrian Hunter int unset __maybe_unused) 969e9db1310SAdrian Hunter { 970e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 971e9db1310SAdrian Hunter char *s, *p; 972e9db1310SAdrian Hunter unsigned int mmap_pages; 973e9db1310SAdrian Hunter int ret; 974e9db1310SAdrian Hunter 975e9db1310SAdrian Hunter if (!str) 976e9db1310SAdrian Hunter return -EINVAL; 977e9db1310SAdrian Hunter 978e9db1310SAdrian Hunter s = strdup(str); 979e9db1310SAdrian Hunter if (!s) 980e9db1310SAdrian Hunter return -ENOMEM; 981e9db1310SAdrian Hunter 982e9db1310SAdrian Hunter p = strchr(s, ','); 983e9db1310SAdrian Hunter if (p) 984e9db1310SAdrian Hunter *p = '\0'; 985e9db1310SAdrian Hunter 986e9db1310SAdrian Hunter if (*s) { 987e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 988e9db1310SAdrian Hunter if (ret) 989e9db1310SAdrian Hunter goto out_free; 990e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 991e9db1310SAdrian Hunter } 992e9db1310SAdrian Hunter 993e9db1310SAdrian Hunter if (!p) { 994e9db1310SAdrian Hunter ret = 0; 995e9db1310SAdrian Hunter goto out_free; 996e9db1310SAdrian Hunter } 997e9db1310SAdrian Hunter 998e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 999e9db1310SAdrian Hunter if (ret) 1000e9db1310SAdrian Hunter goto out_free; 1001e9db1310SAdrian Hunter 1002e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1003e9db1310SAdrian Hunter 1004e9db1310SAdrian Hunter out_free: 1005e9db1310SAdrian Hunter free(s); 1006e9db1310SAdrian Hunter return ret; 1007e9db1310SAdrian Hunter } 1008e9db1310SAdrian Hunter 1009e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 101086470930SIngo Molnar "perf record [<options>] [<command>]", 101186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 101286470930SIngo Molnar NULL 101386470930SIngo Molnar }; 1014e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 101586470930SIngo Molnar 1016d20deb64SArnaldo Carvalho de Melo /* 10178c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 10188c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1019d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1020d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1021d20deb64SArnaldo Carvalho de Melo * 1022d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1023d20deb64SArnaldo Carvalho de Melo * 1024d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1025d20deb64SArnaldo Carvalho de Melo */ 10268c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1027d20deb64SArnaldo Carvalho de Melo .opts = { 10288affc2b8SAndi Kleen .sample_time = true, 1029d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1030d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1031d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1032447a6013SArnaldo Carvalho de Melo .freq = 4000, 1033d1cb9fceSNamhyung Kim .target = { 1034d1cb9fceSNamhyung Kim .uses_mmap = true, 10353aa5939dSAdrian Hunter .default_per_cpu = true, 1036d1cb9fceSNamhyung Kim }, 10379d9cad76SKan Liang .proc_map_timeout = 500, 1038d20deb64SArnaldo Carvalho de Melo }, 1039e3d59112SNamhyung Kim .tool = { 1040e3d59112SNamhyung Kim .sample = process_sample_event, 1041e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1042cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1043e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1044e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1045e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1046cca8482cSAdrian Hunter .ordered_events = true, 1047e3d59112SNamhyung Kim }, 1048d20deb64SArnaldo Carvalho de Melo }; 10497865e817SFrederic Weisbecker 105076a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 105176a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 105261eaa3beSArnaldo Carvalho de Melo 1053d20deb64SArnaldo Carvalho de Melo /* 1054d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1055d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1056b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1057d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1058d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1059d20deb64SArnaldo Carvalho de Melo */ 1060e5b2c207SNamhyung Kim struct option __record_options[] = { 1061d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 106286470930SIngo Molnar "event selector. use 'perf list' to list available events", 1063f120f9d5SJiri Olsa parse_events_option), 1064d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1065c171b552SLi Zefan "event filter", parse_filter), 10664ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10674ba1faa1SWang Nan NULL, "don't record events from perf itself", 10684ba1faa1SWang Nan exclude_perf), 1069bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1070d6d901c2SZhang, Yanmin "record events on existing process id"), 1071bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1072d6d901c2SZhang, Yanmin "record events on existing thread id"), 1073d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 107486470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1075509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1076acac03faSKirill Smelkov "collect data without buffering"), 1077d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1078daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1079bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 108086470930SIngo Molnar "system-wide collection from all CPUs"), 1081bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1082c45c6ea2SStephane Eranian "list of cpus to monitor"), 1083d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1084f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 108586470930SIngo Molnar "output file name"), 108669e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 108769e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 10882e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1089d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1090e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1091e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1092e9db1310SAdrian Hunter record__parse_mmap_pages), 1093d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 109443bece79SLin Ming "put the counters into a counter group"), 109509b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 109609b0fd45SJiri Olsa NULL, "enables call-graph recording" , 109709b0fd45SJiri Olsa &record_callchain_opt), 109809b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 109976a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 110009b0fd45SJiri Olsa &record_parse_callchain_opt), 1101c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 11023da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1103b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1104d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1105649c48a9SPeter Zijlstra "per thread counts"), 110656100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 11073abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 11083abebc55SAdrian Hunter &record.opts.sample_time_set, 11093abebc55SAdrian Hunter "Record the sample timestamps"), 111056100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1111d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1112649c48a9SPeter Zijlstra "don't sample"), 1113d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1114d2db9a98SWang Nan &record.no_buildid_cache_set, 1115a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1116d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1117d2db9a98SWang Nan &record.no_buildid_set, 1118baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1119d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1120023695d9SStephane Eranian "monitor event in cgroup name only", 1121023695d9SStephane Eranian parse_cgroups), 1122a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 11236619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1124bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1125bea03405SNamhyung Kim "user to profile"), 1126a5aabdacSStephane Eranian 1127a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1128a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1129a5aabdacSStephane Eranian parse_branch_stack), 1130a5aabdacSStephane Eranian 1131a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1132a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1133bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 113405484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 113505484298SAndi Kleen "sample by weight (on special events only)"), 1136475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1137475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11383aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11393aa5939dSAdrian Hunter "use per-thread mmaps"), 1140bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1141bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1142bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 114385c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 114485c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1145814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1146814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1147814c8c38SPeter Zijlstra parse_clockid), 11482dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11492dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11509d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11519d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1152b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1153b757bb09SAdrian Hunter "Record context switch events"), 115485723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 115585723885SJiri Olsa "Configure all used events to run in kernel space.", 115685723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 115785723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 115885723885SJiri Olsa "Configure all used events to run in user space.", 115985723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 116071dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 116171dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 116271dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 116371dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 11647efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 11657efe0e03SHe Kuang "file", "vmlinux pathname"), 11666156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 11676156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 116886470930SIngo Molnar OPT_END() 116986470930SIngo Molnar }; 117086470930SIngo Molnar 1171e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1172e5b2c207SNamhyung Kim 11731d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 117486470930SIngo Molnar { 1175ef149c25SAdrian Hunter int err; 11768c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 117716ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 117886470930SIngo Molnar 117948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 118048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 118148e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 118248e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 118348e1cab1SWang Nan # undef set_nobuild 118448e1cab1SWang Nan #endif 118548e1cab1SWang Nan 11867efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 11877efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 11887efe0e03SHe Kuang # define REASON "NO_DWARF=1" 11897efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 11907efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 11917efe0e03SHe Kuang # else 11927efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 11937efe0e03SHe Kuang # endif 11947efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 11957efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 11967efe0e03SHe Kuang # undef set_nobuild 11977efe0e03SHe Kuang # undef REASON 11987efe0e03SHe Kuang #endif 11997efe0e03SHe Kuang 12003e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 12013e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1202361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1203361c99a6SArnaldo Carvalho de Melo 1204eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1205eb853e80SJiri Olsa 1206bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1207a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1208602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1209bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 121086470930SIngo Molnar 1211bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1212c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1213c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1214c7118369SNamhyung Kim 1215023695d9SStephane Eranian } 1216b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1217b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1218c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1219c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1220c7118369SNamhyung Kim return -EINVAL; 1221b757bb09SAdrian Hunter } 1222023695d9SStephane Eranian 1223ef149c25SAdrian Hunter if (!rec->itr) { 1224ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1225ef149c25SAdrian Hunter if (err) 1226ef149c25SAdrian Hunter return err; 1227ef149c25SAdrian Hunter } 1228ef149c25SAdrian Hunter 12292dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 12302dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 12312dd6d8a1SAdrian Hunter if (err) 12322dd6d8a1SAdrian Hunter return err; 12332dd6d8a1SAdrian Hunter 1234ef149c25SAdrian Hunter err = -ENOMEM; 1235ef149c25SAdrian Hunter 12360a7e6d1bSNamhyung Kim symbol__init(NULL); 1237baa2f6ceSArnaldo Carvalho de Melo 1238ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1239646aaea6SArnaldo Carvalho de Melo pr_warning( 1240646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1241ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1242646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1243646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1244646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1245646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1246646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1247ec80fde7SArnaldo Carvalho de Melo 1248d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1249a1ac1d3cSStephane Eranian disable_buildid_cache(); 1250655000e7SArnaldo Carvalho de Melo 12513e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 12523e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 125369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 125469aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1255bbd36e5eSPeter Zijlstra } 125686470930SIngo Molnar 125769e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 125869e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 125969e7e5b0SAdrian Hunter 1260602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 126116ad2ffbSNamhyung Kim if (err) { 1262602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 126316ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 126416ad2ffbSNamhyung Kim } 12654bd0f2d2SNamhyung Kim 1266602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 126716ad2ffbSNamhyung Kim if (err) { 126816ad2ffbSNamhyung Kim int saved_errno = errno; 126916ad2ffbSNamhyung Kim 1270602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 12713780f488SNamhyung Kim ui__error("%s", errbuf); 127216ad2ffbSNamhyung Kim 127316ad2ffbSNamhyung Kim err = -saved_errno; 12748fa60e1fSNamhyung Kim goto out_symbol_exit; 127516ad2ffbSNamhyung Kim } 12760d37aa34SArnaldo Carvalho de Melo 127716ad2ffbSNamhyung Kim err = -ENOMEM; 12783e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1279dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 128069aad6f1SArnaldo Carvalho de Melo 1281ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1282ef149c25SAdrian Hunter if (err) 1283ef149c25SAdrian Hunter goto out_symbol_exit; 1284ef149c25SAdrian Hunter 12856156681bSNamhyung Kim /* 12866156681bSNamhyung Kim * We take all buildids when the file contains 12876156681bSNamhyung Kim * AUX area tracing data because we do not decode the 12886156681bSNamhyung Kim * trace because it would take too long. 12896156681bSNamhyung Kim */ 12906156681bSNamhyung Kim if (rec->opts.full_auxtrace) 12916156681bSNamhyung Kim rec->buildid_all = true; 12926156681bSNamhyung Kim 1293b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 129439d17dacSArnaldo Carvalho de Melo err = -EINVAL; 129503ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 12967e4ff9e3SMike Galbraith } 12977e4ff9e3SMike Galbraith 1298d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1299d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 130045604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1301d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1302ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 130339d17dacSArnaldo Carvalho de Melo return err; 130486470930SIngo Molnar } 13052dd6d8a1SAdrian Hunter 13062dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 13072dd6d8a1SAdrian Hunter { 13082dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 13092dd6d8a1SAdrian Hunter return; 13102dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 13112dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 13122dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 13132dd6d8a1SAdrian Hunter } 1314