186470930SIngo Molnar /* 286470930SIngo Molnar * builtin-record.c 386470930SIngo Molnar * 486470930SIngo Molnar * Builtin record command: Record the profile of a workload 586470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for 686470930SIngo Molnar * later analysis via perf report. 786470930SIngo Molnar */ 886470930SIngo Molnar #include "builtin.h" 986470930SIngo Molnar 1086470930SIngo Molnar #include "perf.h" 1186470930SIngo Molnar 126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1386470930SIngo Molnar #include "util/util.h" 144b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1586470930SIngo Molnar #include "util/parse-events.h" 1686470930SIngo Molnar 178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 197c6a1c65SPeter Zijlstra #include "util/header.h" 2066e274f3SFrederic Weisbecker #include "util/event.h" 21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 238f28827aSFrederic Weisbecker #include "util/debug.h" 2494c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 27a12b51c4SPaul Mackerras #include "util/cpumap.h" 28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 29f5fc1412SJiri Olsa #include "util/data.h" 30bcc84ec6SStephane Eranian #include "util/perf_regs.h" 31ef149c25SAdrian Hunter #include "util/auxtrace.h" 3246bc29b9SAdrian Hunter #include "util/tsc.h" 33f00898f4SAndi Kleen #include "util/parse-branch-options.h" 34bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3571dc2326SWang Nan #include "util/llvm-utils.h" 368690a2a7SWang Nan #include "util/bpf-loader.h" 375f9cf599SWang Nan #include "util/trigger.h" 38d8871ea7SWang Nan #include "asm/bug.h" 397c6a1c65SPeter Zijlstra 4086470930SIngo Molnar #include <unistd.h> 4186470930SIngo Molnar #include <sched.h> 42a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 43*2d11c650SWang Nan #include <asm/bug.h> 4486470930SIngo Molnar 4578da39faSBernhard Rosenkraenzer 468c6f45a7SArnaldo Carvalho de Melo struct record { 4745694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 48b4006796SArnaldo Carvalho de Melo struct record_opts opts; 49d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 50f5fc1412SJiri Olsa struct perf_data_file file; 51ef149c25SAdrian Hunter struct auxtrace_record *itr; 52d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 53d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 54d20deb64SArnaldo Carvalho de Melo const char *progname; 55d20deb64SArnaldo Carvalho de Melo int realtime_prio; 56d20deb64SArnaldo Carvalho de Melo bool no_buildid; 57d2db9a98SWang Nan bool no_buildid_set; 58d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 59d2db9a98SWang Nan bool no_buildid_cache_set; 606156681bSNamhyung Kim bool buildid_all; 61ecfd7a9cSWang Nan bool timestamp_filename; 623c1cb7e3SWang Nan bool switch_output; 639f065194SYang Shi unsigned long long samples; 640f82ebc4SArnaldo Carvalho de Melo }; 6586470930SIngo Molnar 668c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 67f5970550SPeter Zijlstra { 68cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 694f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 708d3eca20SDavid Ahern return -1; 718d3eca20SDavid Ahern } 72f5970550SPeter Zijlstra 73cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 748d3eca20SDavid Ahern return 0; 75f5970550SPeter Zijlstra } 76f5970550SPeter Zijlstra 7745694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 78d20deb64SArnaldo Carvalho de Melo union perf_event *event, 791d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 801d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 81234fbbf5SArnaldo Carvalho de Melo { 828c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 838c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 84234fbbf5SArnaldo Carvalho de Melo } 85234fbbf5SArnaldo Carvalho de Melo 86e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 8786470930SIngo Molnar { 88e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 897b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 907b8283b5SDavid Ahern u64 old = md->prev; 91918512b4SJiri Olsa unsigned char *data = md->base + page_size; 9286470930SIngo Molnar unsigned long size; 9386470930SIngo Molnar void *buf; 948d3eca20SDavid Ahern int rc = 0; 9586470930SIngo Molnar 96dc82009aSArnaldo Carvalho de Melo if (old == head) 978d3eca20SDavid Ahern return 0; 9886470930SIngo Molnar 99d20deb64SArnaldo Carvalho de Melo rec->samples++; 10086470930SIngo Molnar 10186470930SIngo Molnar size = head - old; 102*2d11c650SWang Nan if (size > (unsigned long)(md->mask) + 1) { 103*2d11c650SWang Nan WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 104*2d11c650SWang Nan 105*2d11c650SWang Nan md->prev = head; 106*2d11c650SWang Nan perf_evlist__mmap_consume(rec->evlist, idx); 107*2d11c650SWang Nan return 0; 108*2d11c650SWang Nan } 10986470930SIngo Molnar 11086470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 11186470930SIngo Molnar buf = &data[old & md->mask]; 11286470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 11386470930SIngo Molnar old += size; 11486470930SIngo Molnar 1158c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1168d3eca20SDavid Ahern rc = -1; 1178d3eca20SDavid Ahern goto out; 1188d3eca20SDavid Ahern } 11986470930SIngo Molnar } 12086470930SIngo Molnar 12186470930SIngo Molnar buf = &data[old & md->mask]; 12286470930SIngo Molnar size = head - old; 12386470930SIngo Molnar old += size; 12486470930SIngo Molnar 1258c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1268d3eca20SDavid Ahern rc = -1; 1278d3eca20SDavid Ahern goto out; 1288d3eca20SDavid Ahern } 12986470930SIngo Molnar 13086470930SIngo Molnar md->prev = old; 131e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1328d3eca20SDavid Ahern out: 1338d3eca20SDavid Ahern return rc; 13486470930SIngo Molnar } 13586470930SIngo Molnar 1362dd6d8a1SAdrian Hunter static volatile int done; 1372dd6d8a1SAdrian Hunter static volatile int signr = -1; 1382dd6d8a1SAdrian Hunter static volatile int child_finished; 139c0bdc1c4SWang Nan 1402dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1415f9cf599SWang Nan static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 1423c1cb7e3SWang Nan static DEFINE_TRIGGER(switch_output_trigger); 1432dd6d8a1SAdrian Hunter 1442dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1452dd6d8a1SAdrian Hunter { 1462dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1472dd6d8a1SAdrian Hunter child_finished = 1; 1482dd6d8a1SAdrian Hunter else 1492dd6d8a1SAdrian Hunter signr = sig; 1502dd6d8a1SAdrian Hunter 1512dd6d8a1SAdrian Hunter done = 1; 1522dd6d8a1SAdrian Hunter } 1532dd6d8a1SAdrian Hunter 1542dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1552dd6d8a1SAdrian Hunter { 1562dd6d8a1SAdrian Hunter if (signr == -1) 1572dd6d8a1SAdrian Hunter return; 1582dd6d8a1SAdrian Hunter 1592dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1602dd6d8a1SAdrian Hunter raise(signr); 1612dd6d8a1SAdrian Hunter } 1622dd6d8a1SAdrian Hunter 163e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 164e31f0d01SAdrian Hunter 165ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 166ef149c25SAdrian Hunter union perf_event *event, void *data1, 167ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 168ef149c25SAdrian Hunter { 169ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 17099fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 171ef149c25SAdrian Hunter size_t padding; 172ef149c25SAdrian Hunter u8 pad[8] = {0}; 173ef149c25SAdrian Hunter 17499fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 17599fa2984SAdrian Hunter off_t file_offset; 17699fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 17799fa2984SAdrian Hunter int err; 17899fa2984SAdrian Hunter 17999fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 18099fa2984SAdrian Hunter if (file_offset == -1) 18199fa2984SAdrian Hunter return -1; 18299fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 18399fa2984SAdrian Hunter event, file_offset); 18499fa2984SAdrian Hunter if (err) 18599fa2984SAdrian Hunter return err; 18699fa2984SAdrian Hunter } 18799fa2984SAdrian Hunter 188ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 189ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 190ef149c25SAdrian Hunter if (padding) 191ef149c25SAdrian Hunter padding = 8 - padding; 192ef149c25SAdrian Hunter 193ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 194ef149c25SAdrian Hunter record__write(rec, data1, len1); 195ef149c25SAdrian Hunter if (len2) 196ef149c25SAdrian Hunter record__write(rec, data2, len2); 197ef149c25SAdrian Hunter record__write(rec, &pad, padding); 198ef149c25SAdrian Hunter 199ef149c25SAdrian Hunter return 0; 200ef149c25SAdrian Hunter } 201ef149c25SAdrian Hunter 202ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 203ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 204ef149c25SAdrian Hunter { 205ef149c25SAdrian Hunter int ret; 206ef149c25SAdrian Hunter 207ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 208ef149c25SAdrian Hunter record__process_auxtrace); 209ef149c25SAdrian Hunter if (ret < 0) 210ef149c25SAdrian Hunter return ret; 211ef149c25SAdrian Hunter 212ef149c25SAdrian Hunter if (ret) 213ef149c25SAdrian Hunter rec->samples++; 214ef149c25SAdrian Hunter 215ef149c25SAdrian Hunter return 0; 216ef149c25SAdrian Hunter } 217ef149c25SAdrian Hunter 2182dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2192dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2202dd6d8a1SAdrian Hunter { 2212dd6d8a1SAdrian Hunter int ret; 2222dd6d8a1SAdrian Hunter 2232dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2242dd6d8a1SAdrian Hunter record__process_auxtrace, 2252dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2262dd6d8a1SAdrian Hunter if (ret < 0) 2272dd6d8a1SAdrian Hunter return ret; 2282dd6d8a1SAdrian Hunter 2292dd6d8a1SAdrian Hunter if (ret) 2302dd6d8a1SAdrian Hunter rec->samples++; 2312dd6d8a1SAdrian Hunter 2322dd6d8a1SAdrian Hunter return 0; 2332dd6d8a1SAdrian Hunter } 2342dd6d8a1SAdrian Hunter 2352dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2362dd6d8a1SAdrian Hunter { 2372dd6d8a1SAdrian Hunter int i; 2382dd6d8a1SAdrian Hunter int rc = 0; 2392dd6d8a1SAdrian Hunter 2402dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2412dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2422dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2432dd6d8a1SAdrian Hunter 2442dd6d8a1SAdrian Hunter if (!mm->base) 2452dd6d8a1SAdrian Hunter continue; 2462dd6d8a1SAdrian Hunter 2472dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2482dd6d8a1SAdrian Hunter rc = -1; 2492dd6d8a1SAdrian Hunter goto out; 2502dd6d8a1SAdrian Hunter } 2512dd6d8a1SAdrian Hunter } 2522dd6d8a1SAdrian Hunter out: 2532dd6d8a1SAdrian Hunter return rc; 2542dd6d8a1SAdrian Hunter } 2552dd6d8a1SAdrian Hunter 2562dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2572dd6d8a1SAdrian Hunter { 2582dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2592dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2605f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 2612dd6d8a1SAdrian Hunter } else { 2625f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 2635f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 2645f9cf599SWang Nan else 2655f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 2662dd6d8a1SAdrian Hunter } 2672dd6d8a1SAdrian Hunter } 2682dd6d8a1SAdrian Hunter 269e31f0d01SAdrian Hunter #else 270e31f0d01SAdrian Hunter 271e31f0d01SAdrian Hunter static inline 272e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 273e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 274e31f0d01SAdrian Hunter { 275e31f0d01SAdrian Hunter return 0; 276e31f0d01SAdrian Hunter } 277e31f0d01SAdrian Hunter 2782dd6d8a1SAdrian Hunter static inline 2792dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2802dd6d8a1SAdrian Hunter { 2812dd6d8a1SAdrian Hunter } 2822dd6d8a1SAdrian Hunter 2832dd6d8a1SAdrian Hunter static inline 2842dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2852dd6d8a1SAdrian Hunter { 2862dd6d8a1SAdrian Hunter return 0; 2872dd6d8a1SAdrian Hunter } 2882dd6d8a1SAdrian Hunter 289e31f0d01SAdrian Hunter #endif 290e31f0d01SAdrian Hunter 2918c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 292dd7927f4SArnaldo Carvalho de Melo { 29356e52e85SArnaldo Carvalho de Melo char msg[512]; 2946a4bb04cSJiri Olsa struct perf_evsel *pos; 295d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 296d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 297b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2988d3eca20SDavid Ahern int rc = 0; 299dd7927f4SArnaldo Carvalho de Melo 300e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 301cac21425SJiri Olsa 3020050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 3033da297a6SIngo Molnar try_again: 304d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 30556e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 3063da297a6SIngo Molnar if (verbose) 307c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 3083da297a6SIngo Molnar goto try_again; 3093da297a6SIngo Molnar } 310ca6a4258SDavid Ahern 31156e52e85SArnaldo Carvalho de Melo rc = -errno; 31256e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 31356e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 31456e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3158d3eca20SDavid Ahern goto out; 3167c6a1c65SPeter Zijlstra } 3177c6a1c65SPeter Zijlstra } 3187c6a1c65SPeter Zijlstra 31923d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 32023d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 32123d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 32235550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3238d3eca20SDavid Ahern rc = -1; 3248d3eca20SDavid Ahern goto out; 3250a102479SFrederic Weisbecker } 3260a102479SFrederic Weisbecker 327ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3282dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3292dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3308d3eca20SDavid Ahern if (errno == EPERM) { 3318d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 33218e60939SNelson Elhage "Consider increasing " 33318e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 33418e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 335ef149c25SAdrian Hunter "(current value: %u,%u)\n", 336ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3378d3eca20SDavid Ahern rc = -errno; 3388d3eca20SDavid Ahern } else { 33935550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 34035550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 34195c36561SWang Nan if (errno) 3428d3eca20SDavid Ahern rc = -errno; 34395c36561SWang Nan else 34495c36561SWang Nan rc = -EINVAL; 3458d3eca20SDavid Ahern } 3468d3eca20SDavid Ahern goto out; 34718e60939SNelson Elhage } 3480a27d7f9SArnaldo Carvalho de Melo 349a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3507b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3518d3eca20SDavid Ahern out: 3528d3eca20SDavid Ahern return rc; 353a91e5431SArnaldo Carvalho de Melo } 354a91e5431SArnaldo Carvalho de Melo 355e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 356e3d59112SNamhyung Kim union perf_event *event, 357e3d59112SNamhyung Kim struct perf_sample *sample, 358e3d59112SNamhyung Kim struct perf_evsel *evsel, 359e3d59112SNamhyung Kim struct machine *machine) 360e3d59112SNamhyung Kim { 361e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 362e3d59112SNamhyung Kim 363e3d59112SNamhyung Kim rec->samples++; 364e3d59112SNamhyung Kim 365e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 366e3d59112SNamhyung Kim } 367e3d59112SNamhyung Kim 3688c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3696122e4e4SArnaldo Carvalho de Melo { 370f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 371f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3726122e4e4SArnaldo Carvalho de Melo 373457ae94aSHe Kuang if (file->size == 0) 3749f591fd7SArnaldo Carvalho de Melo return 0; 3759f591fd7SArnaldo Carvalho de Melo 37600dc8657SNamhyung Kim /* 37700dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 37800dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 37900dc8657SNamhyung Kim * we prefer the vmlinux path like 38000dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 38100dc8657SNamhyung Kim * 38200dc8657SNamhyung Kim * rather than build-id path (in debug directory). 38300dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 38400dc8657SNamhyung Kim */ 38500dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 38600dc8657SNamhyung Kim 3876156681bSNamhyung Kim /* 3886156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 3896156681bSNamhyung Kim * so no need to process samples. 3906156681bSNamhyung Kim */ 3916156681bSNamhyung Kim if (rec->buildid_all) 3926156681bSNamhyung Kim rec->tool.sample = NULL; 3936156681bSNamhyung Kim 394b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3956122e4e4SArnaldo Carvalho de Melo } 3966122e4e4SArnaldo Carvalho de Melo 3978115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 398a1645ce1SZhang, Yanmin { 399a1645ce1SZhang, Yanmin int err; 40045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 401a1645ce1SZhang, Yanmin /* 402a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 403a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 404a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 405a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 406a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 407a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 408a1645ce1SZhang, Yanmin */ 40945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 410743eb868SArnaldo Carvalho de Melo machine); 411a1645ce1SZhang, Yanmin if (err < 0) 412a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 41323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 414a1645ce1SZhang, Yanmin 415a1645ce1SZhang, Yanmin /* 416a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 417a1645ce1SZhang, Yanmin * have no _text sometimes. 418a1645ce1SZhang, Yanmin */ 41945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4200ae617beSAdrian Hunter machine); 421a1645ce1SZhang, Yanmin if (err < 0) 422a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 42323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 424a1645ce1SZhang, Yanmin } 425a1645ce1SZhang, Yanmin 42698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 42798402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 42898402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 42998402807SFrederic Weisbecker }; 43098402807SFrederic Weisbecker 4318c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 43298402807SFrederic Weisbecker { 433dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4340e2e63ddSPeter Zijlstra int i; 4358d3eca20SDavid Ahern int rc = 0; 43698402807SFrederic Weisbecker 437d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 438ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 439ef149c25SAdrian Hunter 4408d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 441e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4428d3eca20SDavid Ahern rc = -1; 4438d3eca20SDavid Ahern goto out; 4448d3eca20SDavid Ahern } 4458d3eca20SDavid Ahern } 446ef149c25SAdrian Hunter 4472dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 448ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 449ef149c25SAdrian Hunter rc = -1; 450ef149c25SAdrian Hunter goto out; 451ef149c25SAdrian Hunter } 45298402807SFrederic Weisbecker } 45398402807SFrederic Weisbecker 454dcabb507SJiri Olsa /* 455dcabb507SJiri Olsa * Mark the round finished in case we wrote 456dcabb507SJiri Olsa * at least one event. 457dcabb507SJiri Olsa */ 458dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4598c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4608d3eca20SDavid Ahern 4618d3eca20SDavid Ahern out: 4628d3eca20SDavid Ahern return rc; 46398402807SFrederic Weisbecker } 46498402807SFrederic Weisbecker 4658c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 46657706abcSDavid Ahern { 46757706abcSDavid Ahern struct perf_session *session = rec->session; 46857706abcSDavid Ahern int feat; 46957706abcSDavid Ahern 47057706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 47157706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 47257706abcSDavid Ahern 47357706abcSDavid Ahern if (rec->no_buildid) 47457706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 47557706abcSDavid Ahern 4763e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 47757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 47857706abcSDavid Ahern 47957706abcSDavid Ahern if (!rec->opts.branch_stack) 48057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 481ef149c25SAdrian Hunter 482ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 483ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 484ffa517adSJiri Olsa 485ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 48657706abcSDavid Ahern } 48757706abcSDavid Ahern 488e1ab48baSWang Nan static void 489e1ab48baSWang Nan record__finish_output(struct record *rec) 490e1ab48baSWang Nan { 491e1ab48baSWang Nan struct perf_data_file *file = &rec->file; 492e1ab48baSWang Nan int fd = perf_data_file__fd(file); 493e1ab48baSWang Nan 494e1ab48baSWang Nan if (file->is_pipe) 495e1ab48baSWang Nan return; 496e1ab48baSWang Nan 497e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 498e1ab48baSWang Nan file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 499e1ab48baSWang Nan 500e1ab48baSWang Nan if (!rec->no_buildid) { 501e1ab48baSWang Nan process_buildids(rec); 502e1ab48baSWang Nan 503e1ab48baSWang Nan if (rec->buildid_all) 504e1ab48baSWang Nan dsos__hit_all(rec->session); 505e1ab48baSWang Nan } 506e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 507e1ab48baSWang Nan 508e1ab48baSWang Nan return; 509e1ab48baSWang Nan } 510e1ab48baSWang Nan 511be7b0c9eSWang Nan static int record__synthesize_workload(struct record *rec) 512be7b0c9eSWang Nan { 513be7b0c9eSWang Nan struct { 514be7b0c9eSWang Nan struct thread_map map; 515be7b0c9eSWang Nan struct thread_map_data map_data; 516be7b0c9eSWang Nan } thread_map; 517be7b0c9eSWang Nan 518be7b0c9eSWang Nan thread_map.map.nr = 1; 519be7b0c9eSWang Nan thread_map.map.map[0].pid = rec->evlist->workload.pid; 520be7b0c9eSWang Nan thread_map.map.map[0].comm = NULL; 521be7b0c9eSWang Nan return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map, 522be7b0c9eSWang Nan process_synthesized_event, 523be7b0c9eSWang Nan &rec->session->machines.host, 524be7b0c9eSWang Nan rec->opts.sample_address, 525be7b0c9eSWang Nan rec->opts.proc_map_timeout); 526be7b0c9eSWang Nan } 527be7b0c9eSWang Nan 5283c1cb7e3SWang Nan static int record__synthesize(struct record *rec); 5293c1cb7e3SWang Nan 530ecfd7a9cSWang Nan static int 531ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 532ecfd7a9cSWang Nan { 533ecfd7a9cSWang Nan struct perf_data_file *file = &rec->file; 534ecfd7a9cSWang Nan int fd, err; 535ecfd7a9cSWang Nan 536ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 537ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 538ecfd7a9cSWang Nan 539ecfd7a9cSWang Nan rec->samples = 0; 540ecfd7a9cSWang Nan record__finish_output(rec); 541ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 542ecfd7a9cSWang Nan if (err) { 543ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 544ecfd7a9cSWang Nan return -EINVAL; 545ecfd7a9cSWang Nan } 546ecfd7a9cSWang Nan 547ecfd7a9cSWang Nan fd = perf_data_file__switch(file, timestamp, 548ecfd7a9cSWang Nan rec->session->header.data_offset, 549ecfd7a9cSWang Nan at_exit); 550ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 551ecfd7a9cSWang Nan rec->bytes_written = 0; 552ecfd7a9cSWang Nan rec->session->header.data_size = 0; 553ecfd7a9cSWang Nan } 554ecfd7a9cSWang Nan 555ecfd7a9cSWang Nan if (!quiet) 556ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 557ecfd7a9cSWang Nan file->path, timestamp); 5583c1cb7e3SWang Nan 5593c1cb7e3SWang Nan /* Output tracking events */ 560be7b0c9eSWang Nan if (!at_exit) { 5613c1cb7e3SWang Nan record__synthesize(rec); 5623c1cb7e3SWang Nan 563be7b0c9eSWang Nan /* 564be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 565be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 566be7b0c9eSWang Nan * generate tracking events because there's no thread_map 567be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 568be7b0c9eSWang Nan * contain map and comm information. 569be7b0c9eSWang Nan * Create a fake thread_map and directly call 570be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 571be7b0c9eSWang Nan */ 572be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 573be7b0c9eSWang Nan record__synthesize_workload(rec); 574be7b0c9eSWang Nan } 575ecfd7a9cSWang Nan return fd; 576ecfd7a9cSWang Nan } 577ecfd7a9cSWang Nan 578f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 579f33cbe72SArnaldo Carvalho de Melo 580f33cbe72SArnaldo Carvalho de Melo /* 581f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 582f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 583f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 584f33cbe72SArnaldo Carvalho de Melo */ 58545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 58645604710SNamhyung Kim siginfo_t *info, 587f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 588f33cbe72SArnaldo Carvalho de Melo { 589f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 590f33cbe72SArnaldo Carvalho de Melo done = 1; 591f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 592f33cbe72SArnaldo Carvalho de Melo } 593f33cbe72SArnaldo Carvalho de Melo 5942dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 5952dd6d8a1SAdrian Hunter 59646bc29b9SAdrian Hunter int __weak 59746bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 59846bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 59946bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 60046bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 60146bc29b9SAdrian Hunter { 60246bc29b9SAdrian Hunter return 0; 60346bc29b9SAdrian Hunter } 60446bc29b9SAdrian Hunter 605c45c86ebSWang Nan static int record__synthesize(struct record *rec) 606c45c86ebSWang Nan { 607c45c86ebSWang Nan struct perf_session *session = rec->session; 608c45c86ebSWang Nan struct machine *machine = &session->machines.host; 609c45c86ebSWang Nan struct perf_data_file *file = &rec->file; 610c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 611c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 612c45c86ebSWang Nan int fd = perf_data_file__fd(file); 613c45c86ebSWang Nan int err = 0; 614c45c86ebSWang Nan 615c45c86ebSWang Nan if (file->is_pipe) { 616c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 617c45c86ebSWang Nan process_synthesized_event); 618c45c86ebSWang Nan if (err < 0) { 619c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 620c45c86ebSWang Nan goto out; 621c45c86ebSWang Nan } 622c45c86ebSWang Nan 623c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 624c45c86ebSWang Nan /* 625c45c86ebSWang Nan * FIXME err <= 0 here actually means that 626c45c86ebSWang Nan * there were no tracepoints so its not really 627c45c86ebSWang Nan * an error, just that we don't need to 628c45c86ebSWang Nan * synthesize anything. We really have to 629c45c86ebSWang Nan * return this more properly and also 630c45c86ebSWang Nan * propagate errors that now are calling die() 631c45c86ebSWang Nan */ 632c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 633c45c86ebSWang Nan process_synthesized_event); 634c45c86ebSWang Nan if (err <= 0) { 635c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 636c45c86ebSWang Nan goto out; 637c45c86ebSWang Nan } 638c45c86ebSWang Nan rec->bytes_written += err; 639c45c86ebSWang Nan } 640c45c86ebSWang Nan } 641c45c86ebSWang Nan 64246bc29b9SAdrian Hunter err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool, 64346bc29b9SAdrian Hunter process_synthesized_event, machine); 64446bc29b9SAdrian Hunter if (err) 64546bc29b9SAdrian Hunter goto out; 64646bc29b9SAdrian Hunter 647c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 648c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 649c45c86ebSWang Nan session, process_synthesized_event); 650c45c86ebSWang Nan if (err) 651c45c86ebSWang Nan goto out; 652c45c86ebSWang Nan } 653c45c86ebSWang Nan 654c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 655c45c86ebSWang Nan machine); 656c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 657c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 658c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 659c45c86ebSWang Nan 660c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 661c45c86ebSWang Nan machine); 662c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 663c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 664c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 665c45c86ebSWang Nan 666c45c86ebSWang Nan if (perf_guest) { 667c45c86ebSWang Nan machines__process_guests(&session->machines, 668c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 669c45c86ebSWang Nan } 670c45c86ebSWang Nan 671c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 672c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 673c45c86ebSWang Nan opts->proc_map_timeout); 674c45c86ebSWang Nan out: 675c45c86ebSWang Nan return err; 676c45c86ebSWang Nan } 677c45c86ebSWang Nan 6788c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 67986470930SIngo Molnar { 68057706abcSDavid Ahern int err; 68145604710SNamhyung Kim int status = 0; 6828b412664SPeter Zijlstra unsigned long waking = 0; 68346be604bSZhang, Yanmin const bool forks = argc > 0; 68423346f21SArnaldo Carvalho de Melo struct machine *machine; 68545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 686b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 687f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 688d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 6896dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 69042aa276fSNamhyung Kim int fd; 69186470930SIngo Molnar 692d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 69333e49ea7SAndi Kleen 69445604710SNamhyung Kim atexit(record__sig_exit); 695f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 696f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 697804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 698c0bdc1c4SWang Nan 6993c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) { 7002dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 7013c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 7025f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 7033c1cb7e3SWang Nan if (rec->switch_output) 7043c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 705c0bdc1c4SWang Nan } else { 7062dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 707c0bdc1c4SWang Nan } 708f5970550SPeter Zijlstra 709b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 71094c744b6SArnaldo Carvalho de Melo if (session == NULL) { 711ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 712a9a70bbcSArnaldo Carvalho de Melo return -1; 713a9a70bbcSArnaldo Carvalho de Melo } 714a9a70bbcSArnaldo Carvalho de Melo 71542aa276fSNamhyung Kim fd = perf_data_file__fd(file); 716d20deb64SArnaldo Carvalho de Melo rec->session = session; 717d20deb64SArnaldo Carvalho de Melo 7188c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 719330aa675SStephane Eranian 720d4db3f16SArnaldo Carvalho de Melo if (forks) { 7213e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 722f5fc1412SJiri Olsa argv, file->is_pipe, 723735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 72435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 72535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 72645604710SNamhyung Kim status = err; 72735b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 728856e9660SPeter Zijlstra } 729856e9660SPeter Zijlstra } 730856e9660SPeter Zijlstra 7318c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 7328d3eca20SDavid Ahern err = -1; 73345604710SNamhyung Kim goto out_child; 7348d3eca20SDavid Ahern } 73586470930SIngo Molnar 7368690a2a7SWang Nan err = bpf__apply_obj_config(); 7378690a2a7SWang Nan if (err) { 7388690a2a7SWang Nan char errbuf[BUFSIZ]; 7398690a2a7SWang Nan 7408690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 7418690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 7428690a2a7SWang Nan errbuf); 7438690a2a7SWang Nan goto out_child; 7448690a2a7SWang Nan } 7458690a2a7SWang Nan 746cca8482cSAdrian Hunter /* 747cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 748cca8482cSAdrian Hunter * evlist. 749cca8482cSAdrian Hunter */ 750cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 751cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 752cca8482cSAdrian Hunter rec->tool.ordered_events = false; 753cca8482cSAdrian Hunter } 754cca8482cSAdrian Hunter 7553e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 756a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 757a8bb559bSNamhyung Kim 758f5fc1412SJiri Olsa if (file->is_pipe) { 75942aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 760529870e3STom Zanussi if (err < 0) 76145604710SNamhyung Kim goto out_child; 762563aecb2SJiri Olsa } else { 76342aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 764d5eed904SArnaldo Carvalho de Melo if (err < 0) 76545604710SNamhyung Kim goto out_child; 766d5eed904SArnaldo Carvalho de Melo } 7677c6a1c65SPeter Zijlstra 768d3665498SDavid Ahern if (!rec->no_buildid 769e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 770d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 771e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 7728d3eca20SDavid Ahern err = -1; 77345604710SNamhyung Kim goto out_child; 774e20960c0SRobert Richter } 775e20960c0SRobert Richter 77634ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 777743eb868SArnaldo Carvalho de Melo 778c45c86ebSWang Nan err = record__synthesize(rec); 779c45c86ebSWang Nan if (err < 0) 78045604710SNamhyung Kim goto out_child; 7818d3eca20SDavid Ahern 782d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 78386470930SIngo Molnar struct sched_param param; 78486470930SIngo Molnar 785d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 78686470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 7876beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 7888d3eca20SDavid Ahern err = -1; 78945604710SNamhyung Kim goto out_child; 79086470930SIngo Molnar } 79186470930SIngo Molnar } 79286470930SIngo Molnar 793774cb499SJiri Olsa /* 794774cb499SJiri Olsa * When perf is starting the traced process, all the events 795774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 796774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 797774cb499SJiri Olsa */ 7986619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 7993e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 800764e16a3SDavid Ahern 801856e9660SPeter Zijlstra /* 802856e9660SPeter Zijlstra * Let the child rip 803856e9660SPeter Zijlstra */ 804e803cf97SNamhyung Kim if (forks) { 805e5bed564SNamhyung Kim union perf_event *event; 806e5bed564SNamhyung Kim 807e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 808e5bed564SNamhyung Kim if (event == NULL) { 809e5bed564SNamhyung Kim err = -ENOMEM; 810e5bed564SNamhyung Kim goto out_child; 811e5bed564SNamhyung Kim } 812e5bed564SNamhyung Kim 813e803cf97SNamhyung Kim /* 814e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 815e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 816e803cf97SNamhyung Kim * cannot see a correct process name for those events. 817e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 818e803cf97SNamhyung Kim */ 819e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 820e803cf97SNamhyung Kim rec->evlist->workload.pid, 821e803cf97SNamhyung Kim process_synthesized_event, 822e803cf97SNamhyung Kim machine); 823e5bed564SNamhyung Kim free(event); 824e803cf97SNamhyung Kim 8253e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 826e803cf97SNamhyung Kim } 827856e9660SPeter Zijlstra 8286619a53eSAndi Kleen if (opts->initial_delay) { 8296619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 8306619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 8316619a53eSAndi Kleen } 8326619a53eSAndi Kleen 8335f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 8343c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 835649c48a9SPeter Zijlstra for (;;) { 8369f065194SYang Shi unsigned long long hits = rec->samples; 83786470930SIngo Molnar 8388c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 8395f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 8403c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 8418d3eca20SDavid Ahern err = -1; 84245604710SNamhyung Kim goto out_child; 8438d3eca20SDavid Ahern } 84486470930SIngo Molnar 8452dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 8462dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 8475f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 8482dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 8495f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 8502dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 8512dd6d8a1SAdrian Hunter err = -1; 8522dd6d8a1SAdrian Hunter goto out_child; 8532dd6d8a1SAdrian Hunter } 8542dd6d8a1SAdrian Hunter } 8552dd6d8a1SAdrian Hunter 8563c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 8573c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 8583c1cb7e3SWang Nan 8593c1cb7e3SWang Nan if (!quiet) 8603c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 8613c1cb7e3SWang Nan waking); 8623c1cb7e3SWang Nan waking = 0; 8633c1cb7e3SWang Nan fd = record__switch_output(rec, false); 8643c1cb7e3SWang Nan if (fd < 0) { 8653c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 8663c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 8673c1cb7e3SWang Nan err = fd; 8683c1cb7e3SWang Nan goto out_child; 8693c1cb7e3SWang Nan } 8703c1cb7e3SWang Nan } 8713c1cb7e3SWang Nan 872d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 8736dcf45efSArnaldo Carvalho de Melo if (done || draining) 874649c48a9SPeter Zijlstra break; 875f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 876a515114fSJiri Olsa /* 877a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 878a515114fSJiri Olsa * number of returned events and interrupt error. 879a515114fSJiri Olsa */ 880a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 88145604710SNamhyung Kim err = 0; 8828b412664SPeter Zijlstra waking++; 8836dcf45efSArnaldo Carvalho de Melo 8846dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 8856dcf45efSArnaldo Carvalho de Melo draining = true; 8868b412664SPeter Zijlstra } 8878b412664SPeter Zijlstra 888774cb499SJiri Olsa /* 889774cb499SJiri Olsa * When perf is starting the traced process, at the end events 890774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 891774cb499SJiri Olsa * disable events in this case. 892774cb499SJiri Olsa */ 893602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 8945f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 8953e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 8962711926aSJiri Olsa disabled = true; 8972711926aSJiri Olsa } 8988b412664SPeter Zijlstra } 8995f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 9003c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 9018b412664SPeter Zijlstra 902f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 90335550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 904f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 905f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 906f33cbe72SArnaldo Carvalho de Melo err = -1; 90745604710SNamhyung Kim goto out_child; 908f33cbe72SArnaldo Carvalho de Melo } 909f33cbe72SArnaldo Carvalho de Melo 910e3d59112SNamhyung Kim if (!quiet) 9118b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 91286470930SIngo Molnar 91345604710SNamhyung Kim out_child: 91445604710SNamhyung Kim if (forks) { 91545604710SNamhyung Kim int exit_status; 91645604710SNamhyung Kim 91745604710SNamhyung Kim if (!child_finished) 91845604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 91945604710SNamhyung Kim 92045604710SNamhyung Kim wait(&exit_status); 92145604710SNamhyung Kim 92245604710SNamhyung Kim if (err < 0) 92345604710SNamhyung Kim status = err; 92445604710SNamhyung Kim else if (WIFEXITED(exit_status)) 92545604710SNamhyung Kim status = WEXITSTATUS(exit_status); 92645604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 92745604710SNamhyung Kim signr = WTERMSIG(exit_status); 92845604710SNamhyung Kim } else 92945604710SNamhyung Kim status = err; 93045604710SNamhyung Kim 931e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 932e3d59112SNamhyung Kim rec->samples = 0; 933e3d59112SNamhyung Kim 934ecfd7a9cSWang Nan if (!err) { 935ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 936e1ab48baSWang Nan record__finish_output(rec); 937ecfd7a9cSWang Nan } else { 938ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 939ecfd7a9cSWang Nan if (fd < 0) { 940ecfd7a9cSWang Nan status = fd; 941ecfd7a9cSWang Nan goto out_delete_session; 942ecfd7a9cSWang Nan } 943ecfd7a9cSWang Nan } 944ecfd7a9cSWang Nan } 94539d17dacSArnaldo Carvalho de Melo 946e3d59112SNamhyung Kim if (!err && !quiet) { 947e3d59112SNamhyung Kim char samples[128]; 948ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 949ecfd7a9cSWang Nan ".<timestamp>" : ""; 950e3d59112SNamhyung Kim 951ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 952e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 953e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 954e3d59112SNamhyung Kim else 955e3d59112SNamhyung Kim samples[0] = '\0'; 956e3d59112SNamhyung Kim 957ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 958e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 959ecfd7a9cSWang Nan file->path, postfix, samples); 960e3d59112SNamhyung Kim } 961e3d59112SNamhyung Kim 96239d17dacSArnaldo Carvalho de Melo out_delete_session: 96339d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 96445604710SNamhyung Kim return status; 96586470930SIngo Molnar } 96686470930SIngo Molnar 9670883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 96809b0fd45SJiri Olsa { 969aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 970a601fdffSJiri Olsa 9710883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 97226d33022SJiri Olsa 9730883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 97409b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 9750883e820SArnaldo Carvalho de Melo callchain->dump_size); 9760883e820SArnaldo Carvalho de Melo } 9770883e820SArnaldo Carvalho de Melo 9780883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 9790883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 9800883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 9810883e820SArnaldo Carvalho de Melo { 9820883e820SArnaldo Carvalho de Melo int ret; 9830883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 9840883e820SArnaldo Carvalho de Melo 9850883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 9860883e820SArnaldo Carvalho de Melo if (unset) { 9870883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 9880883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 9890883e820SArnaldo Carvalho de Melo return 0; 9900883e820SArnaldo Carvalho de Melo } 9910883e820SArnaldo Carvalho de Melo 9920883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 9930883e820SArnaldo Carvalho de Melo if (!ret) { 9940883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 9950883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 9960883e820SArnaldo Carvalho de Melo record->sample_address = true; 9970883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 9980883e820SArnaldo Carvalho de Melo } 9990883e820SArnaldo Carvalho de Melo 10000883e820SArnaldo Carvalho de Melo return ret; 100109b0fd45SJiri Olsa } 100209b0fd45SJiri Olsa 1003c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 100409b0fd45SJiri Olsa const char *arg, 100509b0fd45SJiri Olsa int unset) 100609b0fd45SJiri Olsa { 10070883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 100826d33022SJiri Olsa } 100926d33022SJiri Olsa 1010c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 101109b0fd45SJiri Olsa const char *arg __maybe_unused, 101209b0fd45SJiri Olsa int unset __maybe_unused) 101309b0fd45SJiri Olsa { 10142ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1015c421e80bSKan Liang 10162ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 101709b0fd45SJiri Olsa 10182ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 10192ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1020eb853e80SJiri Olsa 10212ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 102209b0fd45SJiri Olsa return 0; 102309b0fd45SJiri Olsa } 102409b0fd45SJiri Olsa 1025eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1026eb853e80SJiri Olsa { 10277a29c087SNamhyung Kim struct record *rec = cb; 10287a29c087SNamhyung Kim 10297a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 10307a29c087SNamhyung Kim if (!strcmp(value, "cache")) 10317a29c087SNamhyung Kim rec->no_buildid_cache = false; 10327a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 10337a29c087SNamhyung Kim rec->no_buildid_cache = true; 10347a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 10357a29c087SNamhyung Kim rec->no_buildid = true; 10367a29c087SNamhyung Kim else 10377a29c087SNamhyung Kim return -1; 10387a29c087SNamhyung Kim return 0; 10397a29c087SNamhyung Kim } 1040eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 10415a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 1042eb853e80SJiri Olsa 1043eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1044eb853e80SJiri Olsa } 1045eb853e80SJiri Olsa 1046814c8c38SPeter Zijlstra struct clockid_map { 1047814c8c38SPeter Zijlstra const char *name; 1048814c8c38SPeter Zijlstra int clockid; 1049814c8c38SPeter Zijlstra }; 1050814c8c38SPeter Zijlstra 1051814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1052814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1053814c8c38SPeter Zijlstra 1054814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1055814c8c38SPeter Zijlstra 1056814c8c38SPeter Zijlstra 1057814c8c38SPeter Zijlstra /* 1058814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1059814c8c38SPeter Zijlstra */ 1060814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1061814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1062814c8c38SPeter Zijlstra #endif 1063814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1064814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1065814c8c38SPeter Zijlstra #endif 1066814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1067814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1068814c8c38SPeter Zijlstra #endif 1069814c8c38SPeter Zijlstra 1070814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1071814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1072814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1073814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1074814c8c38SPeter Zijlstra 1075814c8c38SPeter Zijlstra /* available for some events */ 1076814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1077814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1078814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1079814c8c38SPeter Zijlstra 1080814c8c38SPeter Zijlstra /* available for the lazy */ 1081814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1082814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1083814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1084814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1085814c8c38SPeter Zijlstra 1086814c8c38SPeter Zijlstra CLOCKID_END, 1087814c8c38SPeter Zijlstra }; 1088814c8c38SPeter Zijlstra 1089814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1090814c8c38SPeter Zijlstra { 1091814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1092814c8c38SPeter Zijlstra const struct clockid_map *cm; 1093814c8c38SPeter Zijlstra const char *ostr = str; 1094814c8c38SPeter Zijlstra 1095814c8c38SPeter Zijlstra if (unset) { 1096814c8c38SPeter Zijlstra opts->use_clockid = 0; 1097814c8c38SPeter Zijlstra return 0; 1098814c8c38SPeter Zijlstra } 1099814c8c38SPeter Zijlstra 1100814c8c38SPeter Zijlstra /* no arg passed */ 1101814c8c38SPeter Zijlstra if (!str) 1102814c8c38SPeter Zijlstra return 0; 1103814c8c38SPeter Zijlstra 1104814c8c38SPeter Zijlstra /* no setting it twice */ 1105814c8c38SPeter Zijlstra if (opts->use_clockid) 1106814c8c38SPeter Zijlstra return -1; 1107814c8c38SPeter Zijlstra 1108814c8c38SPeter Zijlstra opts->use_clockid = true; 1109814c8c38SPeter Zijlstra 1110814c8c38SPeter Zijlstra /* if its a number, we're done */ 1111814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1112814c8c38SPeter Zijlstra return 0; 1113814c8c38SPeter Zijlstra 1114814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1115814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1116814c8c38SPeter Zijlstra str += 6; 1117814c8c38SPeter Zijlstra 1118814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1119814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1120814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1121814c8c38SPeter Zijlstra return 0; 1122814c8c38SPeter Zijlstra } 1123814c8c38SPeter Zijlstra } 1124814c8c38SPeter Zijlstra 1125814c8c38SPeter Zijlstra opts->use_clockid = false; 1126814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1127814c8c38SPeter Zijlstra return -1; 1128814c8c38SPeter Zijlstra } 1129814c8c38SPeter Zijlstra 1130e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1131e9db1310SAdrian Hunter const char *str, 1132e9db1310SAdrian Hunter int unset __maybe_unused) 1133e9db1310SAdrian Hunter { 1134e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1135e9db1310SAdrian Hunter char *s, *p; 1136e9db1310SAdrian Hunter unsigned int mmap_pages; 1137e9db1310SAdrian Hunter int ret; 1138e9db1310SAdrian Hunter 1139e9db1310SAdrian Hunter if (!str) 1140e9db1310SAdrian Hunter return -EINVAL; 1141e9db1310SAdrian Hunter 1142e9db1310SAdrian Hunter s = strdup(str); 1143e9db1310SAdrian Hunter if (!s) 1144e9db1310SAdrian Hunter return -ENOMEM; 1145e9db1310SAdrian Hunter 1146e9db1310SAdrian Hunter p = strchr(s, ','); 1147e9db1310SAdrian Hunter if (p) 1148e9db1310SAdrian Hunter *p = '\0'; 1149e9db1310SAdrian Hunter 1150e9db1310SAdrian Hunter if (*s) { 1151e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1152e9db1310SAdrian Hunter if (ret) 1153e9db1310SAdrian Hunter goto out_free; 1154e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1155e9db1310SAdrian Hunter } 1156e9db1310SAdrian Hunter 1157e9db1310SAdrian Hunter if (!p) { 1158e9db1310SAdrian Hunter ret = 0; 1159e9db1310SAdrian Hunter goto out_free; 1160e9db1310SAdrian Hunter } 1161e9db1310SAdrian Hunter 1162e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1163e9db1310SAdrian Hunter if (ret) 1164e9db1310SAdrian Hunter goto out_free; 1165e9db1310SAdrian Hunter 1166e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1167e9db1310SAdrian Hunter 1168e9db1310SAdrian Hunter out_free: 1169e9db1310SAdrian Hunter free(s); 1170e9db1310SAdrian Hunter return ret; 1171e9db1310SAdrian Hunter } 1172e9db1310SAdrian Hunter 1173e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 117486470930SIngo Molnar "perf record [<options>] [<command>]", 117586470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 117686470930SIngo Molnar NULL 117786470930SIngo Molnar }; 1178e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 117986470930SIngo Molnar 1180d20deb64SArnaldo Carvalho de Melo /* 11818c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 11828c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1183d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1184d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1185d20deb64SArnaldo Carvalho de Melo * 1186d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1187d20deb64SArnaldo Carvalho de Melo * 1188d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1189d20deb64SArnaldo Carvalho de Melo */ 11908c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1191d20deb64SArnaldo Carvalho de Melo .opts = { 11928affc2b8SAndi Kleen .sample_time = true, 1193d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1194d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1195d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1196447a6013SArnaldo Carvalho de Melo .freq = 4000, 1197d1cb9fceSNamhyung Kim .target = { 1198d1cb9fceSNamhyung Kim .uses_mmap = true, 11993aa5939dSAdrian Hunter .default_per_cpu = true, 1200d1cb9fceSNamhyung Kim }, 12019d9cad76SKan Liang .proc_map_timeout = 500, 1202d20deb64SArnaldo Carvalho de Melo }, 1203e3d59112SNamhyung Kim .tool = { 1204e3d59112SNamhyung Kim .sample = process_sample_event, 1205e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1206cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1207e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1208e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1209e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1210cca8482cSAdrian Hunter .ordered_events = true, 1211e3d59112SNamhyung Kim }, 1212d20deb64SArnaldo Carvalho de Melo }; 12137865e817SFrederic Weisbecker 121476a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 121576a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 121661eaa3beSArnaldo Carvalho de Melo 1217d20deb64SArnaldo Carvalho de Melo /* 1218d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1219d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1220b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1221d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1222d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1223d20deb64SArnaldo Carvalho de Melo */ 1224e5b2c207SNamhyung Kim struct option __record_options[] = { 1225d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 122686470930SIngo Molnar "event selector. use 'perf list' to list available events", 1227f120f9d5SJiri Olsa parse_events_option), 1228d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1229c171b552SLi Zefan "event filter", parse_filter), 12304ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 12314ba1faa1SWang Nan NULL, "don't record events from perf itself", 12324ba1faa1SWang Nan exclude_perf), 1233bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1234d6d901c2SZhang, Yanmin "record events on existing process id"), 1235bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1236d6d901c2SZhang, Yanmin "record events on existing thread id"), 1237d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 123886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1239509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1240acac03faSKirill Smelkov "collect data without buffering"), 1241d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1242daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1243bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 124486470930SIngo Molnar "system-wide collection from all CPUs"), 1245bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1246c45c6ea2SStephane Eranian "list of cpus to monitor"), 1247d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1248f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 124986470930SIngo Molnar "output file name"), 125069e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 125169e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 12522e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1253d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1254e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1255e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1256e9db1310SAdrian Hunter record__parse_mmap_pages), 1257d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 125843bece79SLin Ming "put the counters into a counter group"), 12592ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 126009b0fd45SJiri Olsa NULL, "enables call-graph recording" , 126109b0fd45SJiri Olsa &record_callchain_opt), 126209b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 126376a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 126409b0fd45SJiri Olsa &record_parse_callchain_opt), 1265c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 12663da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1267b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1268d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1269649c48a9SPeter Zijlstra "per thread counts"), 127056100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 12713abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 12723abebc55SAdrian Hunter &record.opts.sample_time_set, 12733abebc55SAdrian Hunter "Record the sample timestamps"), 127456100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1275d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1276649c48a9SPeter Zijlstra "don't sample"), 1277d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1278d2db9a98SWang Nan &record.no_buildid_cache_set, 1279a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1280d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1281d2db9a98SWang Nan &record.no_buildid_set, 1282baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1283d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1284023695d9SStephane Eranian "monitor event in cgroup name only", 1285023695d9SStephane Eranian parse_cgroups), 1286a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 12876619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1288bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1289bea03405SNamhyung Kim "user to profile"), 1290a5aabdacSStephane Eranian 1291a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1292a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1293a5aabdacSStephane Eranian parse_branch_stack), 1294a5aabdacSStephane Eranian 1295a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1296a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1297bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 129805484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 129905484298SAndi Kleen "sample by weight (on special events only)"), 1300475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1301475eeab9SAndi Kleen "sample transaction flags (special events only)"), 13023aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 13033aa5939dSAdrian Hunter "use per-thread mmaps"), 1304bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1305bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1306bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 130785c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 130885c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1309814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1310814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1311814c8c38SPeter Zijlstra parse_clockid), 13122dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 13132dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 13149d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 13159d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1316b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1317b757bb09SAdrian Hunter "Record context switch events"), 131885723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 131985723885SJiri Olsa "Configure all used events to run in kernel space.", 132085723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 132185723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 132285723885SJiri Olsa "Configure all used events to run in user space.", 132385723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 132471dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 132571dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 132671dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 132771dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 13287efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 13297efe0e03SHe Kuang "file", "vmlinux pathname"), 13306156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 13316156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1332ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1333ecfd7a9cSWang Nan "append timestamp to output filename"), 13343c1cb7e3SWang Nan OPT_BOOLEAN(0, "switch-output", &record.switch_output, 13353c1cb7e3SWang Nan "Switch output when receive SIGUSR2"), 133686470930SIngo Molnar OPT_END() 133786470930SIngo Molnar }; 133886470930SIngo Molnar 1339e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1340e5b2c207SNamhyung Kim 13411d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 134286470930SIngo Molnar { 1343ef149c25SAdrian Hunter int err; 13448c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 134516ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 134686470930SIngo Molnar 134748e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 134848e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 134948e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 135048e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 135148e1cab1SWang Nan # undef set_nobuild 135248e1cab1SWang Nan #endif 135348e1cab1SWang Nan 13547efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 13557efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 13567efe0e03SHe Kuang # define REASON "NO_DWARF=1" 13577efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 13587efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 13597efe0e03SHe Kuang # else 13607efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 13617efe0e03SHe Kuang # endif 13627efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 13637efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 13647efe0e03SHe Kuang # undef set_nobuild 13657efe0e03SHe Kuang # undef REASON 13667efe0e03SHe Kuang #endif 13677efe0e03SHe Kuang 13683e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 13693e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1370361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1371361c99a6SArnaldo Carvalho de Melo 1372eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1373eb853e80SJiri Olsa 1374bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1375a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1376602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1377bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 137886470930SIngo Molnar 1379bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1380c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1381c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1382c7118369SNamhyung Kim 1383023695d9SStephane Eranian } 1384b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1385b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1386c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1387c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1388c7118369SNamhyung Kim return -EINVAL; 1389b757bb09SAdrian Hunter } 1390023695d9SStephane Eranian 1391eca857abSWang Nan if (rec->switch_output) 1392eca857abSWang Nan rec->timestamp_filename = true; 1393eca857abSWang Nan 1394ef149c25SAdrian Hunter if (!rec->itr) { 1395ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1396ef149c25SAdrian Hunter if (err) 1397ef149c25SAdrian Hunter return err; 1398ef149c25SAdrian Hunter } 1399ef149c25SAdrian Hunter 14002dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 14012dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 14022dd6d8a1SAdrian Hunter if (err) 14032dd6d8a1SAdrian Hunter return err; 14042dd6d8a1SAdrian Hunter 1405d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 1406d7888573SWang Nan if (err) { 1407d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1408d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 1409d7888573SWang Nan errbuf); 1410d7888573SWang Nan return err; 1411d7888573SWang Nan } 1412d7888573SWang Nan 1413ef149c25SAdrian Hunter err = -ENOMEM; 1414ef149c25SAdrian Hunter 14150a7e6d1bSNamhyung Kim symbol__init(NULL); 1416baa2f6ceSArnaldo Carvalho de Melo 1417ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1418646aaea6SArnaldo Carvalho de Melo pr_warning( 1419646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1420ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1421646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1422646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1423646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1424646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1425646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1426ec80fde7SArnaldo Carvalho de Melo 14270c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 1428a1ac1d3cSStephane Eranian disable_buildid_cache(); 14290c1d46a8SWang Nan } else if (rec->switch_output) { 14300c1d46a8SWang Nan /* 14310c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 14320c1d46a8SWang Nan * generation by default to reduce data file switching 14330c1d46a8SWang Nan * overhead. Still generate buildid if they are required 14340c1d46a8SWang Nan * explicitly using 14350c1d46a8SWang Nan * 14360c1d46a8SWang Nan * perf record --signal-trigger --no-no-buildid \ 14370c1d46a8SWang Nan * --no-no-buildid-cache 14380c1d46a8SWang Nan * 14390c1d46a8SWang Nan * Following code equals to: 14400c1d46a8SWang Nan * 14410c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 14420c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 14430c1d46a8SWang Nan * disable_buildid_cache(); 14440c1d46a8SWang Nan */ 14450c1d46a8SWang Nan bool disable = true; 14460c1d46a8SWang Nan 14470c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 14480c1d46a8SWang Nan disable = false; 14490c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 14500c1d46a8SWang Nan disable = false; 14510c1d46a8SWang Nan if (disable) { 14520c1d46a8SWang Nan rec->no_buildid = true; 14530c1d46a8SWang Nan rec->no_buildid_cache = true; 14540c1d46a8SWang Nan disable_buildid_cache(); 14550c1d46a8SWang Nan } 14560c1d46a8SWang Nan } 1457655000e7SArnaldo Carvalho de Melo 14583e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 14593e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 146069aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 146169aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1462bbd36e5eSPeter Zijlstra } 146386470930SIngo Molnar 146469e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 146569e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 146669e7e5b0SAdrian Hunter 1467602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 146816ad2ffbSNamhyung Kim if (err) { 1469602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 147016ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 147116ad2ffbSNamhyung Kim } 14724bd0f2d2SNamhyung Kim 1473602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 147416ad2ffbSNamhyung Kim if (err) { 147516ad2ffbSNamhyung Kim int saved_errno = errno; 147616ad2ffbSNamhyung Kim 1477602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 14783780f488SNamhyung Kim ui__error("%s", errbuf); 147916ad2ffbSNamhyung Kim 148016ad2ffbSNamhyung Kim err = -saved_errno; 14818fa60e1fSNamhyung Kim goto out_symbol_exit; 148216ad2ffbSNamhyung Kim } 14830d37aa34SArnaldo Carvalho de Melo 148416ad2ffbSNamhyung Kim err = -ENOMEM; 14853e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1486dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 148769aad6f1SArnaldo Carvalho de Melo 1488ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1489ef149c25SAdrian Hunter if (err) 1490ef149c25SAdrian Hunter goto out_symbol_exit; 1491ef149c25SAdrian Hunter 14926156681bSNamhyung Kim /* 14936156681bSNamhyung Kim * We take all buildids when the file contains 14946156681bSNamhyung Kim * AUX area tracing data because we do not decode the 14956156681bSNamhyung Kim * trace because it would take too long. 14966156681bSNamhyung Kim */ 14976156681bSNamhyung Kim if (rec->opts.full_auxtrace) 14986156681bSNamhyung Kim rec->buildid_all = true; 14996156681bSNamhyung Kim 1500b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 150139d17dacSArnaldo Carvalho de Melo err = -EINVAL; 150203ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 15037e4ff9e3SMike Galbraith } 15047e4ff9e3SMike Galbraith 1505d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1506d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 150745604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1508d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1509ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 151039d17dacSArnaldo Carvalho de Melo return err; 151186470930SIngo Molnar } 15122dd6d8a1SAdrian Hunter 15132dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 15142dd6d8a1SAdrian Hunter { 15155f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 15165f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 15172dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 15185f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 15195f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 15205f9cf599SWang Nan } 15213c1cb7e3SWang Nan 15223c1cb7e3SWang Nan if (trigger_is_ready(&switch_output_trigger)) 15233c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 15242dd6d8a1SAdrian Hunter } 1525