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" 357c6a1c65SPeter Zijlstra 3686470930SIngo Molnar #include <unistd.h> 3786470930SIngo Molnar #include <sched.h> 38a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3986470930SIngo Molnar 4078da39faSBernhard Rosenkraenzer 418c6f45a7SArnaldo Carvalho de Melo struct record { 4245694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 43b4006796SArnaldo Carvalho de Melo struct record_opts opts; 44d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 45f5fc1412SJiri Olsa struct perf_data_file file; 46ef149c25SAdrian Hunter struct auxtrace_record *itr; 47d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 48d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 49d20deb64SArnaldo Carvalho de Melo const char *progname; 50d20deb64SArnaldo Carvalho de Melo int realtime_prio; 51d20deb64SArnaldo Carvalho de Melo bool no_buildid; 52d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 53*6156681bSNamhyung Kim bool buildid_all; 549f065194SYang Shi unsigned long long samples; 550f82ebc4SArnaldo Carvalho de Melo }; 5686470930SIngo Molnar 578c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 58f5970550SPeter Zijlstra { 59cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 604f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 618d3eca20SDavid Ahern return -1; 628d3eca20SDavid Ahern } 63f5970550SPeter Zijlstra 64cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 658d3eca20SDavid Ahern return 0; 66f5970550SPeter Zijlstra } 67f5970550SPeter Zijlstra 6845694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 69d20deb64SArnaldo Carvalho de Melo union perf_event *event, 701d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 711d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 72234fbbf5SArnaldo Carvalho de Melo { 738c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 748c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 75234fbbf5SArnaldo Carvalho de Melo } 76234fbbf5SArnaldo Carvalho de Melo 77e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7886470930SIngo Molnar { 79e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 807b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 817b8283b5SDavid Ahern u64 old = md->prev; 82918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8386470930SIngo Molnar unsigned long size; 8486470930SIngo Molnar void *buf; 858d3eca20SDavid Ahern int rc = 0; 8686470930SIngo Molnar 87dc82009aSArnaldo Carvalho de Melo if (old == head) 888d3eca20SDavid Ahern return 0; 8986470930SIngo Molnar 90d20deb64SArnaldo Carvalho de Melo rec->samples++; 9186470930SIngo Molnar 9286470930SIngo Molnar size = head - old; 9386470930SIngo Molnar 9486470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9586470930SIngo Molnar buf = &data[old & md->mask]; 9686470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9786470930SIngo Molnar old += size; 9886470930SIngo Molnar 998c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1008d3eca20SDavid Ahern rc = -1; 1018d3eca20SDavid Ahern goto out; 1028d3eca20SDavid Ahern } 10386470930SIngo Molnar } 10486470930SIngo Molnar 10586470930SIngo Molnar buf = &data[old & md->mask]; 10686470930SIngo Molnar size = head - old; 10786470930SIngo Molnar old += size; 10886470930SIngo Molnar 1098c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1108d3eca20SDavid Ahern rc = -1; 1118d3eca20SDavid Ahern goto out; 1128d3eca20SDavid Ahern } 11386470930SIngo Molnar 11486470930SIngo Molnar md->prev = old; 115e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1168d3eca20SDavid Ahern out: 1178d3eca20SDavid Ahern return rc; 11886470930SIngo Molnar } 11986470930SIngo Molnar 1202dd6d8a1SAdrian Hunter static volatile int done; 1212dd6d8a1SAdrian Hunter static volatile int signr = -1; 1222dd6d8a1SAdrian Hunter static volatile int child_finished; 1232dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1242dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1252dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1262dd6d8a1SAdrian Hunter 1272dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1282dd6d8a1SAdrian Hunter { 1292dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1302dd6d8a1SAdrian Hunter child_finished = 1; 1312dd6d8a1SAdrian Hunter else 1322dd6d8a1SAdrian Hunter signr = sig; 1332dd6d8a1SAdrian Hunter 1342dd6d8a1SAdrian Hunter done = 1; 1352dd6d8a1SAdrian Hunter } 1362dd6d8a1SAdrian Hunter 1372dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1382dd6d8a1SAdrian Hunter { 1392dd6d8a1SAdrian Hunter if (signr == -1) 1402dd6d8a1SAdrian Hunter return; 1412dd6d8a1SAdrian Hunter 1422dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1432dd6d8a1SAdrian Hunter raise(signr); 1442dd6d8a1SAdrian Hunter } 1452dd6d8a1SAdrian Hunter 146e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 147e31f0d01SAdrian Hunter 148ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 149ef149c25SAdrian Hunter union perf_event *event, void *data1, 150ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 151ef149c25SAdrian Hunter { 152ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15399fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 154ef149c25SAdrian Hunter size_t padding; 155ef149c25SAdrian Hunter u8 pad[8] = {0}; 156ef149c25SAdrian Hunter 15799fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 15899fa2984SAdrian Hunter off_t file_offset; 15999fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 16099fa2984SAdrian Hunter int err; 16199fa2984SAdrian Hunter 16299fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16399fa2984SAdrian Hunter if (file_offset == -1) 16499fa2984SAdrian Hunter return -1; 16599fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 16699fa2984SAdrian Hunter event, file_offset); 16799fa2984SAdrian Hunter if (err) 16899fa2984SAdrian Hunter return err; 16999fa2984SAdrian Hunter } 17099fa2984SAdrian Hunter 171ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 172ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 173ef149c25SAdrian Hunter if (padding) 174ef149c25SAdrian Hunter padding = 8 - padding; 175ef149c25SAdrian Hunter 176ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 177ef149c25SAdrian Hunter record__write(rec, data1, len1); 178ef149c25SAdrian Hunter if (len2) 179ef149c25SAdrian Hunter record__write(rec, data2, len2); 180ef149c25SAdrian Hunter record__write(rec, &pad, padding); 181ef149c25SAdrian Hunter 182ef149c25SAdrian Hunter return 0; 183ef149c25SAdrian Hunter } 184ef149c25SAdrian Hunter 185ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 186ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 187ef149c25SAdrian Hunter { 188ef149c25SAdrian Hunter int ret; 189ef149c25SAdrian Hunter 190ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 191ef149c25SAdrian Hunter record__process_auxtrace); 192ef149c25SAdrian Hunter if (ret < 0) 193ef149c25SAdrian Hunter return ret; 194ef149c25SAdrian Hunter 195ef149c25SAdrian Hunter if (ret) 196ef149c25SAdrian Hunter rec->samples++; 197ef149c25SAdrian Hunter 198ef149c25SAdrian Hunter return 0; 199ef149c25SAdrian Hunter } 200ef149c25SAdrian Hunter 2012dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2022dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2032dd6d8a1SAdrian Hunter { 2042dd6d8a1SAdrian Hunter int ret; 2052dd6d8a1SAdrian Hunter 2062dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2072dd6d8a1SAdrian Hunter record__process_auxtrace, 2082dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2092dd6d8a1SAdrian Hunter if (ret < 0) 2102dd6d8a1SAdrian Hunter return ret; 2112dd6d8a1SAdrian Hunter 2122dd6d8a1SAdrian Hunter if (ret) 2132dd6d8a1SAdrian Hunter rec->samples++; 2142dd6d8a1SAdrian Hunter 2152dd6d8a1SAdrian Hunter return 0; 2162dd6d8a1SAdrian Hunter } 2172dd6d8a1SAdrian Hunter 2182dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2192dd6d8a1SAdrian Hunter { 2202dd6d8a1SAdrian Hunter int i; 2212dd6d8a1SAdrian Hunter int rc = 0; 2222dd6d8a1SAdrian Hunter 2232dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2242dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2252dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2262dd6d8a1SAdrian Hunter 2272dd6d8a1SAdrian Hunter if (!mm->base) 2282dd6d8a1SAdrian Hunter continue; 2292dd6d8a1SAdrian Hunter 2302dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2312dd6d8a1SAdrian Hunter rc = -1; 2322dd6d8a1SAdrian Hunter goto out; 2332dd6d8a1SAdrian Hunter } 2342dd6d8a1SAdrian Hunter } 2352dd6d8a1SAdrian Hunter out: 2362dd6d8a1SAdrian Hunter return rc; 2372dd6d8a1SAdrian Hunter } 2382dd6d8a1SAdrian Hunter 2392dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2402dd6d8a1SAdrian Hunter { 2412dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2422dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2432dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2442dd6d8a1SAdrian Hunter } else { 2452dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2462dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2472dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2482dd6d8a1SAdrian Hunter } 2492dd6d8a1SAdrian Hunter } 2502dd6d8a1SAdrian Hunter 251e31f0d01SAdrian Hunter #else 252e31f0d01SAdrian Hunter 253e31f0d01SAdrian Hunter static inline 254e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 255e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 256e31f0d01SAdrian Hunter { 257e31f0d01SAdrian Hunter return 0; 258e31f0d01SAdrian Hunter } 259e31f0d01SAdrian Hunter 2602dd6d8a1SAdrian Hunter static inline 2612dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2622dd6d8a1SAdrian Hunter { 2632dd6d8a1SAdrian Hunter } 2642dd6d8a1SAdrian Hunter 2652dd6d8a1SAdrian Hunter static inline 2662dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2672dd6d8a1SAdrian Hunter { 2682dd6d8a1SAdrian Hunter return 0; 2692dd6d8a1SAdrian Hunter } 2702dd6d8a1SAdrian Hunter 271e31f0d01SAdrian Hunter #endif 272e31f0d01SAdrian Hunter 2738c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 274dd7927f4SArnaldo Carvalho de Melo { 27556e52e85SArnaldo Carvalho de Melo char msg[512]; 2766a4bb04cSJiri Olsa struct perf_evsel *pos; 277d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 278d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 279b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2808d3eca20SDavid Ahern int rc = 0; 281dd7927f4SArnaldo Carvalho de Melo 282f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 283cac21425SJiri Olsa 2840050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2853da297a6SIngo Molnar try_again: 286d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 28756e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2883da297a6SIngo Molnar if (verbose) 289c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2903da297a6SIngo Molnar goto try_again; 2913da297a6SIngo Molnar } 292ca6a4258SDavid Ahern 29356e52e85SArnaldo Carvalho de Melo rc = -errno; 29456e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29556e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 29656e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2978d3eca20SDavid Ahern goto out; 2987c6a1c65SPeter Zijlstra } 2997c6a1c65SPeter Zijlstra } 3007c6a1c65SPeter Zijlstra 30123d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30223d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30323d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30435550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3058d3eca20SDavid Ahern rc = -1; 3068d3eca20SDavid Ahern goto out; 3070a102479SFrederic Weisbecker } 3080a102479SFrederic Weisbecker 309ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3102dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3112dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3128d3eca20SDavid Ahern if (errno == EPERM) { 3138d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31418e60939SNelson Elhage "Consider increasing " 31518e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 31618e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 317ef149c25SAdrian Hunter "(current value: %u,%u)\n", 318ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3198d3eca20SDavid Ahern rc = -errno; 3208d3eca20SDavid Ahern } else { 32135550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32235550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3238d3eca20SDavid Ahern rc = -errno; 3248d3eca20SDavid Ahern } 3258d3eca20SDavid Ahern goto out; 32618e60939SNelson Elhage } 3270a27d7f9SArnaldo Carvalho de Melo 328a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3297b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3308d3eca20SDavid Ahern out: 3318d3eca20SDavid Ahern return rc; 332a91e5431SArnaldo Carvalho de Melo } 333a91e5431SArnaldo Carvalho de Melo 334e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 335e3d59112SNamhyung Kim union perf_event *event, 336e3d59112SNamhyung Kim struct perf_sample *sample, 337e3d59112SNamhyung Kim struct perf_evsel *evsel, 338e3d59112SNamhyung Kim struct machine *machine) 339e3d59112SNamhyung Kim { 340e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 341e3d59112SNamhyung Kim 342e3d59112SNamhyung Kim rec->samples++; 343e3d59112SNamhyung Kim 344e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 345e3d59112SNamhyung Kim } 346e3d59112SNamhyung Kim 3478c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3486122e4e4SArnaldo Carvalho de Melo { 349f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 350f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3516122e4e4SArnaldo Carvalho de Melo 352457ae94aSHe Kuang if (file->size == 0) 3539f591fd7SArnaldo Carvalho de Melo return 0; 3549f591fd7SArnaldo Carvalho de Melo 35500dc8657SNamhyung Kim /* 35600dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 35700dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 35800dc8657SNamhyung Kim * we prefer the vmlinux path like 35900dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 36000dc8657SNamhyung Kim * 36100dc8657SNamhyung Kim * rather than build-id path (in debug directory). 36200dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 36300dc8657SNamhyung Kim */ 36400dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 36500dc8657SNamhyung Kim 366*6156681bSNamhyung Kim /* 367*6156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 368*6156681bSNamhyung Kim * so no need to process samples. 369*6156681bSNamhyung Kim */ 370*6156681bSNamhyung Kim if (rec->buildid_all) 371*6156681bSNamhyung Kim rec->tool.sample = NULL; 372*6156681bSNamhyung Kim 373b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3746122e4e4SArnaldo Carvalho de Melo } 3756122e4e4SArnaldo Carvalho de Melo 3768115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 377a1645ce1SZhang, Yanmin { 378a1645ce1SZhang, Yanmin int err; 37945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 380a1645ce1SZhang, Yanmin /* 381a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 382a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 383a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 384a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 385a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 386a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 387a1645ce1SZhang, Yanmin */ 38845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 389743eb868SArnaldo Carvalho de Melo machine); 390a1645ce1SZhang, Yanmin if (err < 0) 391a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 393a1645ce1SZhang, Yanmin 394a1645ce1SZhang, Yanmin /* 395a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 396a1645ce1SZhang, Yanmin * have no _text sometimes. 397a1645ce1SZhang, Yanmin */ 39845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 3990ae617beSAdrian Hunter machine); 400a1645ce1SZhang, Yanmin if (err < 0) 401a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 403a1645ce1SZhang, Yanmin } 404a1645ce1SZhang, Yanmin 40598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 40698402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 40798402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 40898402807SFrederic Weisbecker }; 40998402807SFrederic Weisbecker 4108c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 41198402807SFrederic Weisbecker { 412dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4130e2e63ddSPeter Zijlstra int i; 4148d3eca20SDavid Ahern int rc = 0; 41598402807SFrederic Weisbecker 416d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 417ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 418ef149c25SAdrian Hunter 4198d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 420e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4218d3eca20SDavid Ahern rc = -1; 4228d3eca20SDavid Ahern goto out; 4238d3eca20SDavid Ahern } 4248d3eca20SDavid Ahern } 425ef149c25SAdrian Hunter 4262dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 427ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 428ef149c25SAdrian Hunter rc = -1; 429ef149c25SAdrian Hunter goto out; 430ef149c25SAdrian Hunter } 43198402807SFrederic Weisbecker } 43298402807SFrederic Weisbecker 433dcabb507SJiri Olsa /* 434dcabb507SJiri Olsa * Mark the round finished in case we wrote 435dcabb507SJiri Olsa * at least one event. 436dcabb507SJiri Olsa */ 437dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4388c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4398d3eca20SDavid Ahern 4408d3eca20SDavid Ahern out: 4418d3eca20SDavid Ahern return rc; 44298402807SFrederic Weisbecker } 44398402807SFrederic Weisbecker 4448c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 44557706abcSDavid Ahern { 44657706abcSDavid Ahern struct perf_session *session = rec->session; 44757706abcSDavid Ahern int feat; 44857706abcSDavid Ahern 44957706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 45057706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 45157706abcSDavid Ahern 45257706abcSDavid Ahern if (rec->no_buildid) 45357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 45457706abcSDavid Ahern 4553e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 45657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 45757706abcSDavid Ahern 45857706abcSDavid Ahern if (!rec->opts.branch_stack) 45957706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 460ef149c25SAdrian Hunter 461ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 462ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 463ffa517adSJiri Olsa 464ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 46557706abcSDavid Ahern } 46657706abcSDavid Ahern 467f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 468f33cbe72SArnaldo Carvalho de Melo 469f33cbe72SArnaldo Carvalho de Melo /* 470f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 471f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 472f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 473f33cbe72SArnaldo Carvalho de Melo */ 47445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 47545604710SNamhyung Kim siginfo_t *info, 476f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 477f33cbe72SArnaldo Carvalho de Melo { 478f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 479f33cbe72SArnaldo Carvalho de Melo done = 1; 480f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 481f33cbe72SArnaldo Carvalho de Melo } 482f33cbe72SArnaldo Carvalho de Melo 4832dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 4842dd6d8a1SAdrian Hunter 4858c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 48686470930SIngo Molnar { 48757706abcSDavid Ahern int err; 48845604710SNamhyung Kim int status = 0; 4898b412664SPeter Zijlstra unsigned long waking = 0; 49046be604bSZhang, Yanmin const bool forks = argc > 0; 49123346f21SArnaldo Carvalho de Melo struct machine *machine; 49245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 493b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 494f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 495d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 4966dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 49742aa276fSNamhyung Kim int fd; 49886470930SIngo Molnar 499d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 50033e49ea7SAndi Kleen 50145604710SNamhyung Kim atexit(record__sig_exit); 502f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 503f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 504804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 5052dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 5062dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 5072dd6d8a1SAdrian Hunter else 5082dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 509f5970550SPeter Zijlstra 510b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 51194c744b6SArnaldo Carvalho de Melo if (session == NULL) { 512ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 513a9a70bbcSArnaldo Carvalho de Melo return -1; 514a9a70bbcSArnaldo Carvalho de Melo } 515a9a70bbcSArnaldo Carvalho de Melo 51642aa276fSNamhyung Kim fd = perf_data_file__fd(file); 517d20deb64SArnaldo Carvalho de Melo rec->session = session; 518d20deb64SArnaldo Carvalho de Melo 5198c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 520330aa675SStephane Eranian 521d4db3f16SArnaldo Carvalho de Melo if (forks) { 5223e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 523f5fc1412SJiri Olsa argv, file->is_pipe, 524735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 52535b9d88eSArnaldo Carvalho de Melo if (err < 0) { 52635b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 52745604710SNamhyung Kim status = err; 52835b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 529856e9660SPeter Zijlstra } 530856e9660SPeter Zijlstra } 531856e9660SPeter Zijlstra 5328c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 5338d3eca20SDavid Ahern err = -1; 53445604710SNamhyung Kim goto out_child; 5358d3eca20SDavid Ahern } 53686470930SIngo Molnar 537cca8482cSAdrian Hunter /* 538cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 539cca8482cSAdrian Hunter * evlist. 540cca8482cSAdrian Hunter */ 541cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 542cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 543cca8482cSAdrian Hunter rec->tool.ordered_events = false; 544cca8482cSAdrian Hunter } 545cca8482cSAdrian Hunter 5463e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 547a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 548a8bb559bSNamhyung Kim 549f5fc1412SJiri Olsa if (file->is_pipe) { 55042aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 551529870e3STom Zanussi if (err < 0) 55245604710SNamhyung Kim goto out_child; 553563aecb2SJiri Olsa } else { 55442aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 555d5eed904SArnaldo Carvalho de Melo if (err < 0) 55645604710SNamhyung Kim goto out_child; 557d5eed904SArnaldo Carvalho de Melo } 5587c6a1c65SPeter Zijlstra 559d3665498SDavid Ahern if (!rec->no_buildid 560e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 561d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 562e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5638d3eca20SDavid Ahern err = -1; 56445604710SNamhyung Kim goto out_child; 565e20960c0SRobert Richter } 566e20960c0SRobert Richter 56734ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 568743eb868SArnaldo Carvalho de Melo 569f5fc1412SJiri Olsa if (file->is_pipe) { 57045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 571a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5722c46dbb5STom Zanussi if (err < 0) { 5732c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 57445604710SNamhyung Kim goto out_child; 5752c46dbb5STom Zanussi } 576cd19a035STom Zanussi 5773e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 57863e0c771STom Zanussi /* 57963e0c771STom Zanussi * FIXME err <= 0 here actually means that 58063e0c771STom Zanussi * there were no tracepoints so its not really 58163e0c771STom Zanussi * an error, just that we don't need to 58263e0c771STom Zanussi * synthesize anything. We really have to 58363e0c771STom Zanussi * return this more properly and also 58463e0c771STom Zanussi * propagate errors that now are calling die() 58563e0c771STom Zanussi */ 58642aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 587743eb868SArnaldo Carvalho de Melo process_synthesized_event); 58863e0c771STom Zanussi if (err <= 0) { 58963e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 59045604710SNamhyung Kim goto out_child; 59163e0c771STom Zanussi } 592f34b9001SDavid Ahern rec->bytes_written += err; 5932c46dbb5STom Zanussi } 59463e0c771STom Zanussi } 5952c46dbb5STom Zanussi 596ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 597ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 598ef149c25SAdrian Hunter session, process_synthesized_event); 599ef149c25SAdrian Hunter if (err) 600ef149c25SAdrian Hunter goto out_delete_session; 601ef149c25SAdrian Hunter } 602ef149c25SAdrian Hunter 60345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 6040ae617beSAdrian Hunter machine); 605c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 606c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 607c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 608c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 60956b03f3cSArnaldo Carvalho de Melo 61045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 611743eb868SArnaldo Carvalho de Melo machine); 612c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 613c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 614c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 615c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 616c1a3a4b9SArnaldo Carvalho de Melo 6177e383de4SArnaldo Carvalho de Melo if (perf_guest) { 618876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 6197e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 6207e383de4SArnaldo Carvalho de Melo } 621b7cece76SArnaldo Carvalho de Melo 6223e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 6239d9cad76SKan Liang process_synthesized_event, opts->sample_address, 6249d9cad76SKan Liang opts->proc_map_timeout); 6258d3eca20SDavid Ahern if (err != 0) 62645604710SNamhyung Kim goto out_child; 6278d3eca20SDavid Ahern 628d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 62986470930SIngo Molnar struct sched_param param; 63086470930SIngo Molnar 631d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 63286470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6336beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6348d3eca20SDavid Ahern err = -1; 63545604710SNamhyung Kim goto out_child; 63686470930SIngo Molnar } 63786470930SIngo Molnar } 63886470930SIngo Molnar 639774cb499SJiri Olsa /* 640774cb499SJiri Olsa * When perf is starting the traced process, all the events 641774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 642774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 643774cb499SJiri Olsa */ 6446619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6453e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 646764e16a3SDavid Ahern 647856e9660SPeter Zijlstra /* 648856e9660SPeter Zijlstra * Let the child rip 649856e9660SPeter Zijlstra */ 650e803cf97SNamhyung Kim if (forks) { 651e5bed564SNamhyung Kim union perf_event *event; 652e5bed564SNamhyung Kim 653e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 654e5bed564SNamhyung Kim if (event == NULL) { 655e5bed564SNamhyung Kim err = -ENOMEM; 656e5bed564SNamhyung Kim goto out_child; 657e5bed564SNamhyung Kim } 658e5bed564SNamhyung Kim 659e803cf97SNamhyung Kim /* 660e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 661e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 662e803cf97SNamhyung Kim * cannot see a correct process name for those events. 663e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 664e803cf97SNamhyung Kim */ 665e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 666e803cf97SNamhyung Kim rec->evlist->workload.pid, 667e803cf97SNamhyung Kim process_synthesized_event, 668e803cf97SNamhyung Kim machine); 669e5bed564SNamhyung Kim free(event); 670e803cf97SNamhyung Kim 6713e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 672e803cf97SNamhyung Kim } 673856e9660SPeter Zijlstra 6746619a53eSAndi Kleen if (opts->initial_delay) { 6756619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 6766619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 6776619a53eSAndi Kleen } 6786619a53eSAndi Kleen 6792dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 680649c48a9SPeter Zijlstra for (;;) { 6819f065194SYang Shi unsigned long long hits = rec->samples; 68286470930SIngo Molnar 6838c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 6842dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6858d3eca20SDavid Ahern err = -1; 68645604710SNamhyung Kim goto out_child; 6878d3eca20SDavid Ahern } 68886470930SIngo Molnar 6892dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 6902dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 6912dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 6922dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 6932dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 6942dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 6952dd6d8a1SAdrian Hunter err = -1; 6962dd6d8a1SAdrian Hunter goto out_child; 6972dd6d8a1SAdrian Hunter } 6982dd6d8a1SAdrian Hunter } 6992dd6d8a1SAdrian Hunter 700d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 7016dcf45efSArnaldo Carvalho de Melo if (done || draining) 702649c48a9SPeter Zijlstra break; 703f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 704a515114fSJiri Olsa /* 705a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 706a515114fSJiri Olsa * number of returned events and interrupt error. 707a515114fSJiri Olsa */ 708a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 70945604710SNamhyung Kim err = 0; 7108b412664SPeter Zijlstra waking++; 7116dcf45efSArnaldo Carvalho de Melo 7126dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7136dcf45efSArnaldo Carvalho de Melo draining = true; 7148b412664SPeter Zijlstra } 7158b412664SPeter Zijlstra 716774cb499SJiri Olsa /* 717774cb499SJiri Olsa * When perf is starting the traced process, at the end events 718774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 719774cb499SJiri Olsa * disable events in this case. 720774cb499SJiri Olsa */ 721602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7222dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7233e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7242711926aSJiri Olsa disabled = true; 7252711926aSJiri Olsa } 7268b412664SPeter Zijlstra } 7272dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7288b412664SPeter Zijlstra 729f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 73035550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 731f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 732f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 733f33cbe72SArnaldo Carvalho de Melo err = -1; 73445604710SNamhyung Kim goto out_child; 735f33cbe72SArnaldo Carvalho de Melo } 736f33cbe72SArnaldo Carvalho de Melo 737e3d59112SNamhyung Kim if (!quiet) 7388b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 73986470930SIngo Molnar 74045604710SNamhyung Kim out_child: 74145604710SNamhyung Kim if (forks) { 74245604710SNamhyung Kim int exit_status; 74345604710SNamhyung Kim 74445604710SNamhyung Kim if (!child_finished) 74545604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 74645604710SNamhyung Kim 74745604710SNamhyung Kim wait(&exit_status); 74845604710SNamhyung Kim 74945604710SNamhyung Kim if (err < 0) 75045604710SNamhyung Kim status = err; 75145604710SNamhyung Kim else if (WIFEXITED(exit_status)) 75245604710SNamhyung Kim status = WEXITSTATUS(exit_status); 75345604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 75445604710SNamhyung Kim signr = WTERMSIG(exit_status); 75545604710SNamhyung Kim } else 75645604710SNamhyung Kim status = err; 75745604710SNamhyung Kim 758e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 759e3d59112SNamhyung Kim rec->samples = 0; 760e3d59112SNamhyung Kim 76145604710SNamhyung Kim if (!err && !file->is_pipe) { 76245604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 763457ae94aSHe Kuang file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 76445604710SNamhyung Kim 765cd10b289SAdrian Hunter if (!rec->no_buildid) { 76645604710SNamhyung Kim process_buildids(rec); 767*6156681bSNamhyung Kim 768*6156681bSNamhyung Kim if (rec->buildid_all) 769cd10b289SAdrian Hunter dsos__hit_all(rec->session); 770cd10b289SAdrian Hunter } 77142aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 77245604710SNamhyung Kim } 77339d17dacSArnaldo Carvalho de Melo 774e3d59112SNamhyung Kim if (!err && !quiet) { 775e3d59112SNamhyung Kim char samples[128]; 776e3d59112SNamhyung Kim 777ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 778e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 779e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 780e3d59112SNamhyung Kim else 781e3d59112SNamhyung Kim samples[0] = '\0'; 782e3d59112SNamhyung Kim 783e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 784e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 785e3d59112SNamhyung Kim file->path, samples); 786e3d59112SNamhyung Kim } 787e3d59112SNamhyung Kim 78839d17dacSArnaldo Carvalho de Melo out_delete_session: 78939d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 79045604710SNamhyung Kim return status; 79186470930SIngo Molnar } 79286470930SIngo Molnar 79372a128aaSNamhyung Kim static void callchain_debug(void) 79409b0fd45SJiri Olsa { 795aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 796a601fdffSJiri Olsa 79772a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 79826d33022SJiri Olsa 79972a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 80009b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 80172a128aaSNamhyung Kim callchain_param.dump_size); 80209b0fd45SJiri Olsa } 80309b0fd45SJiri Olsa 804c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 80509b0fd45SJiri Olsa const char *arg, 80609b0fd45SJiri Olsa int unset) 80709b0fd45SJiri Olsa { 80809b0fd45SJiri Olsa int ret; 809c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 81009b0fd45SJiri Olsa 811c421e80bSKan Liang record->callgraph_set = true; 81272a128aaSNamhyung Kim callchain_param.enabled = !unset; 813eb853e80SJiri Olsa 81409b0fd45SJiri Olsa /* --no-call-graph */ 81509b0fd45SJiri Olsa if (unset) { 81672a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 81709b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 81809b0fd45SJiri Olsa return 0; 81909b0fd45SJiri Olsa } 82009b0fd45SJiri Olsa 821c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 8225c0cf224SJiri Olsa if (!ret) { 8235c0cf224SJiri Olsa /* Enable data address sampling for DWARF unwind. */ 8245c0cf224SJiri Olsa if (callchain_param.record_mode == CALLCHAIN_DWARF) 8255c0cf224SJiri Olsa record->sample_address = true; 82672a128aaSNamhyung Kim callchain_debug(); 8275c0cf224SJiri Olsa } 82809b0fd45SJiri Olsa 82926d33022SJiri Olsa return ret; 83026d33022SJiri Olsa } 83126d33022SJiri Olsa 832c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 83309b0fd45SJiri Olsa const char *arg __maybe_unused, 83409b0fd45SJiri Olsa int unset __maybe_unused) 83509b0fd45SJiri Olsa { 836c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 837c421e80bSKan Liang 838c421e80bSKan Liang record->callgraph_set = true; 83972a128aaSNamhyung Kim callchain_param.enabled = true; 84009b0fd45SJiri Olsa 84172a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 84272a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 843eb853e80SJiri Olsa 84472a128aaSNamhyung Kim callchain_debug(); 84509b0fd45SJiri Olsa return 0; 84609b0fd45SJiri Olsa } 84709b0fd45SJiri Olsa 848eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 849eb853e80SJiri Olsa { 8507a29c087SNamhyung Kim struct record *rec = cb; 8517a29c087SNamhyung Kim 8527a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 8537a29c087SNamhyung Kim if (!strcmp(value, "cache")) 8547a29c087SNamhyung Kim rec->no_buildid_cache = false; 8557a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 8567a29c087SNamhyung Kim rec->no_buildid_cache = true; 8577a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 8587a29c087SNamhyung Kim rec->no_buildid = true; 8597a29c087SNamhyung Kim else 8607a29c087SNamhyung Kim return -1; 8617a29c087SNamhyung Kim return 0; 8627a29c087SNamhyung Kim } 863eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 8645a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 865eb853e80SJiri Olsa 866eb853e80SJiri Olsa return perf_default_config(var, value, cb); 867eb853e80SJiri Olsa } 868eb853e80SJiri Olsa 869814c8c38SPeter Zijlstra struct clockid_map { 870814c8c38SPeter Zijlstra const char *name; 871814c8c38SPeter Zijlstra int clockid; 872814c8c38SPeter Zijlstra }; 873814c8c38SPeter Zijlstra 874814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 875814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 876814c8c38SPeter Zijlstra 877814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 878814c8c38SPeter Zijlstra 879814c8c38SPeter Zijlstra 880814c8c38SPeter Zijlstra /* 881814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 882814c8c38SPeter Zijlstra */ 883814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 884814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 885814c8c38SPeter Zijlstra #endif 886814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 887814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 888814c8c38SPeter Zijlstra #endif 889814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 890814c8c38SPeter Zijlstra #define CLOCK_TAI 11 891814c8c38SPeter Zijlstra #endif 892814c8c38SPeter Zijlstra 893814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 894814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 895814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 896814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 897814c8c38SPeter Zijlstra 898814c8c38SPeter Zijlstra /* available for some events */ 899814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 900814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 901814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 902814c8c38SPeter Zijlstra 903814c8c38SPeter Zijlstra /* available for the lazy */ 904814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 905814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 906814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 907814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 908814c8c38SPeter Zijlstra 909814c8c38SPeter Zijlstra CLOCKID_END, 910814c8c38SPeter Zijlstra }; 911814c8c38SPeter Zijlstra 912814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 913814c8c38SPeter Zijlstra { 914814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 915814c8c38SPeter Zijlstra const struct clockid_map *cm; 916814c8c38SPeter Zijlstra const char *ostr = str; 917814c8c38SPeter Zijlstra 918814c8c38SPeter Zijlstra if (unset) { 919814c8c38SPeter Zijlstra opts->use_clockid = 0; 920814c8c38SPeter Zijlstra return 0; 921814c8c38SPeter Zijlstra } 922814c8c38SPeter Zijlstra 923814c8c38SPeter Zijlstra /* no arg passed */ 924814c8c38SPeter Zijlstra if (!str) 925814c8c38SPeter Zijlstra return 0; 926814c8c38SPeter Zijlstra 927814c8c38SPeter Zijlstra /* no setting it twice */ 928814c8c38SPeter Zijlstra if (opts->use_clockid) 929814c8c38SPeter Zijlstra return -1; 930814c8c38SPeter Zijlstra 931814c8c38SPeter Zijlstra opts->use_clockid = true; 932814c8c38SPeter Zijlstra 933814c8c38SPeter Zijlstra /* if its a number, we're done */ 934814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 935814c8c38SPeter Zijlstra return 0; 936814c8c38SPeter Zijlstra 937814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 938814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 939814c8c38SPeter Zijlstra str += 6; 940814c8c38SPeter Zijlstra 941814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 942814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 943814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 944814c8c38SPeter Zijlstra return 0; 945814c8c38SPeter Zijlstra } 946814c8c38SPeter Zijlstra } 947814c8c38SPeter Zijlstra 948814c8c38SPeter Zijlstra opts->use_clockid = false; 949814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 950814c8c38SPeter Zijlstra return -1; 951814c8c38SPeter Zijlstra } 952814c8c38SPeter Zijlstra 953e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 954e9db1310SAdrian Hunter const char *str, 955e9db1310SAdrian Hunter int unset __maybe_unused) 956e9db1310SAdrian Hunter { 957e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 958e9db1310SAdrian Hunter char *s, *p; 959e9db1310SAdrian Hunter unsigned int mmap_pages; 960e9db1310SAdrian Hunter int ret; 961e9db1310SAdrian Hunter 962e9db1310SAdrian Hunter if (!str) 963e9db1310SAdrian Hunter return -EINVAL; 964e9db1310SAdrian Hunter 965e9db1310SAdrian Hunter s = strdup(str); 966e9db1310SAdrian Hunter if (!s) 967e9db1310SAdrian Hunter return -ENOMEM; 968e9db1310SAdrian Hunter 969e9db1310SAdrian Hunter p = strchr(s, ','); 970e9db1310SAdrian Hunter if (p) 971e9db1310SAdrian Hunter *p = '\0'; 972e9db1310SAdrian Hunter 973e9db1310SAdrian Hunter if (*s) { 974e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 975e9db1310SAdrian Hunter if (ret) 976e9db1310SAdrian Hunter goto out_free; 977e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 978e9db1310SAdrian Hunter } 979e9db1310SAdrian Hunter 980e9db1310SAdrian Hunter if (!p) { 981e9db1310SAdrian Hunter ret = 0; 982e9db1310SAdrian Hunter goto out_free; 983e9db1310SAdrian Hunter } 984e9db1310SAdrian Hunter 985e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 986e9db1310SAdrian Hunter if (ret) 987e9db1310SAdrian Hunter goto out_free; 988e9db1310SAdrian Hunter 989e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 990e9db1310SAdrian Hunter 991e9db1310SAdrian Hunter out_free: 992e9db1310SAdrian Hunter free(s); 993e9db1310SAdrian Hunter return ret; 994e9db1310SAdrian Hunter } 995e9db1310SAdrian Hunter 996e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 99786470930SIngo Molnar "perf record [<options>] [<command>]", 99886470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 99986470930SIngo Molnar NULL 100086470930SIngo Molnar }; 1001e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 100286470930SIngo Molnar 1003d20deb64SArnaldo Carvalho de Melo /* 10048c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 10058c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1006d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1007d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1008d20deb64SArnaldo Carvalho de Melo * 1009d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1010d20deb64SArnaldo Carvalho de Melo * 1011d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1012d20deb64SArnaldo Carvalho de Melo */ 10138c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1014d20deb64SArnaldo Carvalho de Melo .opts = { 10158affc2b8SAndi Kleen .sample_time = true, 1016d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1017d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1018d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1019447a6013SArnaldo Carvalho de Melo .freq = 4000, 1020d1cb9fceSNamhyung Kim .target = { 1021d1cb9fceSNamhyung Kim .uses_mmap = true, 10223aa5939dSAdrian Hunter .default_per_cpu = true, 1023d1cb9fceSNamhyung Kim }, 10249d9cad76SKan Liang .proc_map_timeout = 500, 1025d20deb64SArnaldo Carvalho de Melo }, 1026e3d59112SNamhyung Kim .tool = { 1027e3d59112SNamhyung Kim .sample = process_sample_event, 1028e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1029cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1030e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1031e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1032e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1033cca8482cSAdrian Hunter .ordered_events = true, 1034e3d59112SNamhyung Kim }, 1035d20deb64SArnaldo Carvalho de Melo }; 10367865e817SFrederic Weisbecker 103776a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 103876a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 103961eaa3beSArnaldo Carvalho de Melo 1040d20deb64SArnaldo Carvalho de Melo /* 1041d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1042d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1043b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1044d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1045d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1046d20deb64SArnaldo Carvalho de Melo */ 1047e5b2c207SNamhyung Kim struct option __record_options[] = { 1048d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 104986470930SIngo Molnar "event selector. use 'perf list' to list available events", 1050f120f9d5SJiri Olsa parse_events_option), 1051d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1052c171b552SLi Zefan "event filter", parse_filter), 10534ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10544ba1faa1SWang Nan NULL, "don't record events from perf itself", 10554ba1faa1SWang Nan exclude_perf), 1056bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1057d6d901c2SZhang, Yanmin "record events on existing process id"), 1058bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1059d6d901c2SZhang, Yanmin "record events on existing thread id"), 1060d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 106186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1062509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1063acac03faSKirill Smelkov "collect data without buffering"), 1064d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1065daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1066bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 106786470930SIngo Molnar "system-wide collection from all CPUs"), 1068bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1069c45c6ea2SStephane Eranian "list of cpus to monitor"), 1070d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1071f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 107286470930SIngo Molnar "output file name"), 107369e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 107469e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 10752e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1076d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1077e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1078e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1079e9db1310SAdrian Hunter record__parse_mmap_pages), 1080d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 108143bece79SLin Ming "put the counters into a counter group"), 108209b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 108309b0fd45SJiri Olsa NULL, "enables call-graph recording" , 108409b0fd45SJiri Olsa &record_callchain_opt), 108509b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 108676a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 108709b0fd45SJiri Olsa &record_parse_callchain_opt), 1088c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10893da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1090b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1091d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1092649c48a9SPeter Zijlstra "per thread counts"), 109356100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 10943abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 10953abebc55SAdrian Hunter &record.opts.sample_time_set, 10963abebc55SAdrian Hunter "Record the sample timestamps"), 109756100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1098d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1099649c48a9SPeter Zijlstra "don't sample"), 1100d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1101a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1102d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1103baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1104d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1105023695d9SStephane Eranian "monitor event in cgroup name only", 1106023695d9SStephane Eranian parse_cgroups), 1107a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 11086619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1109bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1110bea03405SNamhyung Kim "user to profile"), 1111a5aabdacSStephane Eranian 1112a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1113a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1114a5aabdacSStephane Eranian parse_branch_stack), 1115a5aabdacSStephane Eranian 1116a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1117a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1118bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 111905484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 112005484298SAndi Kleen "sample by weight (on special events only)"), 1121475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1122475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11233aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11243aa5939dSAdrian Hunter "use per-thread mmaps"), 1125bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1126bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1127bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 112885c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 112985c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1130814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1131814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1132814c8c38SPeter Zijlstra parse_clockid), 11332dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11342dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11359d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11369d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1137b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1138b757bb09SAdrian Hunter "Record context switch events"), 113971dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 114071dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 114171dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 114271dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 11437efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 11447efe0e03SHe Kuang "file", "vmlinux pathname"), 1145*6156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 1146*6156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 114786470930SIngo Molnar OPT_END() 114886470930SIngo Molnar }; 114986470930SIngo Molnar 1150e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1151e5b2c207SNamhyung Kim 11521d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 115386470930SIngo Molnar { 1154ef149c25SAdrian Hunter int err; 11558c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 115616ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 115786470930SIngo Molnar 115848e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 115948e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 116048e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 116148e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 116248e1cab1SWang Nan # undef set_nobuild 116348e1cab1SWang Nan #endif 116448e1cab1SWang Nan 11657efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 11667efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 11677efe0e03SHe Kuang # define REASON "NO_DWARF=1" 11687efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 11697efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 11707efe0e03SHe Kuang # else 11717efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 11727efe0e03SHe Kuang # endif 11737efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 11747efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 11757efe0e03SHe Kuang # undef set_nobuild 11767efe0e03SHe Kuang # undef REASON 11777efe0e03SHe Kuang #endif 11787efe0e03SHe Kuang 11793e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 11803e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1181361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1182361c99a6SArnaldo Carvalho de Melo 1183eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1184eb853e80SJiri Olsa 1185bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1186a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1187602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1188bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 118986470930SIngo Molnar 1190bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1191c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1192c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1193c7118369SNamhyung Kim 1194023695d9SStephane Eranian } 1195b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1196b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1197c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1198c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1199c7118369SNamhyung Kim return -EINVAL; 1200b757bb09SAdrian Hunter } 1201023695d9SStephane Eranian 1202ef149c25SAdrian Hunter if (!rec->itr) { 1203ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1204ef149c25SAdrian Hunter if (err) 1205ef149c25SAdrian Hunter return err; 1206ef149c25SAdrian Hunter } 1207ef149c25SAdrian Hunter 12082dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 12092dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 12102dd6d8a1SAdrian Hunter if (err) 12112dd6d8a1SAdrian Hunter return err; 12122dd6d8a1SAdrian Hunter 1213ef149c25SAdrian Hunter err = -ENOMEM; 1214ef149c25SAdrian Hunter 12150a7e6d1bSNamhyung Kim symbol__init(NULL); 1216baa2f6ceSArnaldo Carvalho de Melo 1217ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1218646aaea6SArnaldo Carvalho de Melo pr_warning( 1219646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1220ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1221646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1222646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1223646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1224646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1225646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1226ec80fde7SArnaldo Carvalho de Melo 1227d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1228a1ac1d3cSStephane Eranian disable_buildid_cache(); 1229655000e7SArnaldo Carvalho de Melo 12303e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 12313e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 123269aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 123369aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1234bbd36e5eSPeter Zijlstra } 123586470930SIngo Molnar 123669e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 123769e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 123869e7e5b0SAdrian Hunter 1239602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 124016ad2ffbSNamhyung Kim if (err) { 1241602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 124216ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 124316ad2ffbSNamhyung Kim } 12444bd0f2d2SNamhyung Kim 1245602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 124616ad2ffbSNamhyung Kim if (err) { 124716ad2ffbSNamhyung Kim int saved_errno = errno; 124816ad2ffbSNamhyung Kim 1249602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 12503780f488SNamhyung Kim ui__error("%s", errbuf); 125116ad2ffbSNamhyung Kim 125216ad2ffbSNamhyung Kim err = -saved_errno; 12538fa60e1fSNamhyung Kim goto out_symbol_exit; 125416ad2ffbSNamhyung Kim } 12550d37aa34SArnaldo Carvalho de Melo 125616ad2ffbSNamhyung Kim err = -ENOMEM; 12573e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1258dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 125969aad6f1SArnaldo Carvalho de Melo 1260ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1261ef149c25SAdrian Hunter if (err) 1262ef149c25SAdrian Hunter goto out_symbol_exit; 1263ef149c25SAdrian Hunter 1264*6156681bSNamhyung Kim /* 1265*6156681bSNamhyung Kim * We take all buildids when the file contains 1266*6156681bSNamhyung Kim * AUX area tracing data because we do not decode the 1267*6156681bSNamhyung Kim * trace because it would take too long. 1268*6156681bSNamhyung Kim */ 1269*6156681bSNamhyung Kim if (rec->opts.full_auxtrace) 1270*6156681bSNamhyung Kim rec->buildid_all = true; 1271*6156681bSNamhyung Kim 1272b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 127339d17dacSArnaldo Carvalho de Melo err = -EINVAL; 127403ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 12757e4ff9e3SMike Galbraith } 12767e4ff9e3SMike Galbraith 1277d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1278d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 127945604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1280d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1281ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 128239d17dacSArnaldo Carvalho de Melo return err; 128386470930SIngo Molnar } 12842dd6d8a1SAdrian Hunter 12852dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 12862dd6d8a1SAdrian Hunter { 12872dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 12882dd6d8a1SAdrian Hunter return; 12892dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 12902dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 12912dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 12922dd6d8a1SAdrian Hunter } 1293