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" 1641840d21STaeung Song #include "util/config.h" 1786470930SIngo Molnar 188f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 19f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 207c6a1c65SPeter Zijlstra #include "util/header.h" 2166e274f3SFrederic Weisbecker #include "util/event.h" 22361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2369aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 248f28827aSFrederic Weisbecker #include "util/debug.h" 255d8bb1ecSMathieu Poirier #include "util/drv_configs.h" 2694c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2745694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 288d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 29a12b51c4SPaul Mackerras #include "util/cpumap.h" 30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 31f5fc1412SJiri Olsa #include "util/data.h" 32bcc84ec6SStephane Eranian #include "util/perf_regs.h" 33ef149c25SAdrian Hunter #include "util/auxtrace.h" 3446bc29b9SAdrian Hunter #include "util/tsc.h" 35f00898f4SAndi Kleen #include "util/parse-branch-options.h" 36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3771dc2326SWang Nan #include "util/llvm-utils.h" 388690a2a7SWang Nan #include "util/bpf-loader.h" 395f9cf599SWang Nan #include "util/trigger.h" 40a074865eSWang Nan #include "util/perf-hooks.h" 41c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4258db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 43d8871ea7SWang Nan #include "asm/bug.h" 447c6a1c65SPeter Zijlstra 45a43783aeSArnaldo Carvalho de Melo #include <errno.h> 46fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 474208735dSArnaldo Carvalho de Melo #include <poll.h> 4886470930SIngo Molnar #include <unistd.h> 4986470930SIngo Molnar #include <sched.h> 509607ad3aSArnaldo Carvalho de Melo #include <signal.h> 51a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 524208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 532d11c650SWang Nan #include <asm/bug.h> 540693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 5578da39faSBernhard Rosenkraenzer 561b43b704SJiri Olsa struct switch_output { 57dc0c6127SJiri Olsa bool enabled; 581b43b704SJiri Olsa bool signal; 59dc0c6127SJiri Olsa unsigned long size; 60bfacbe3bSJiri Olsa unsigned long time; 61cb4e1ebbSJiri Olsa const char *str; 62cb4e1ebbSJiri Olsa bool set; 631b43b704SJiri Olsa }; 641b43b704SJiri Olsa 658c6f45a7SArnaldo Carvalho de Melo struct record { 6645694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 67b4006796SArnaldo Carvalho de Melo struct record_opts opts; 68d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 69*8ceb41d7SJiri Olsa struct perf_data data; 70ef149c25SAdrian Hunter struct auxtrace_record *itr; 71d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 72d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 73d20deb64SArnaldo Carvalho de Melo const char *progname; 74d20deb64SArnaldo Carvalho de Melo int realtime_prio; 75d20deb64SArnaldo Carvalho de Melo bool no_buildid; 76d2db9a98SWang Nan bool no_buildid_set; 77d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 78d2db9a98SWang Nan bool no_buildid_cache_set; 796156681bSNamhyung Kim bool buildid_all; 80ecfd7a9cSWang Nan bool timestamp_filename; 811b43b704SJiri Olsa struct switch_output switch_output; 829f065194SYang Shi unsigned long long samples; 830f82ebc4SArnaldo Carvalho de Melo }; 8486470930SIngo Molnar 85dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 86dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 87dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 88dc0c6127SJiri Olsa 89dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 90dc0c6127SJiri Olsa { 91dc0c6127SJiri Olsa return rec->switch_output.signal && 92dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 93dc0c6127SJiri Olsa } 94dc0c6127SJiri Olsa 95dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 96dc0c6127SJiri Olsa { 97dc0c6127SJiri Olsa return rec->switch_output.size && 98dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 99dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 100dc0c6127SJiri Olsa } 101dc0c6127SJiri Olsa 102bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 103bfacbe3bSJiri Olsa { 104bfacbe3bSJiri Olsa return rec->switch_output.time && 105bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 106bfacbe3bSJiri Olsa } 107bfacbe3bSJiri Olsa 1088c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 109f5970550SPeter Zijlstra { 110*8ceb41d7SJiri Olsa if (perf_data__write(rec->session->data, bf, size) < 0) { 1114f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1128d3eca20SDavid Ahern return -1; 1138d3eca20SDavid Ahern } 114f5970550SPeter Zijlstra 115cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 116dc0c6127SJiri Olsa 117dc0c6127SJiri Olsa if (switch_output_size(rec)) 118dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 119dc0c6127SJiri Olsa 1208d3eca20SDavid Ahern return 0; 121f5970550SPeter Zijlstra } 122f5970550SPeter Zijlstra 12345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 124d20deb64SArnaldo Carvalho de Melo union perf_event *event, 1251d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 1261d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 127234fbbf5SArnaldo Carvalho de Melo { 1288c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 1298c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 130234fbbf5SArnaldo Carvalho de Melo } 131234fbbf5SArnaldo Carvalho de Melo 132d37f1586SArnaldo Carvalho de Melo static int record__pushfn(void *to, void *bf, size_t size) 133d37f1586SArnaldo Carvalho de Melo { 134d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 135d37f1586SArnaldo Carvalho de Melo 136d37f1586SArnaldo Carvalho de Melo rec->samples++; 137d37f1586SArnaldo Carvalho de Melo return record__write(rec, bf, size); 138d37f1586SArnaldo Carvalho de Melo } 139d37f1586SArnaldo Carvalho de Melo 1402dd6d8a1SAdrian Hunter static volatile int done; 1412dd6d8a1SAdrian Hunter static volatile int signr = -1; 1422dd6d8a1SAdrian Hunter static volatile int child_finished; 143c0bdc1c4SWang Nan 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 154a074865eSWang Nan static void sigsegv_handler(int sig) 155a074865eSWang Nan { 156a074865eSWang Nan perf_hooks__recover(); 157a074865eSWang Nan sighandler_dump_stack(sig); 158a074865eSWang Nan } 159a074865eSWang Nan 1602dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1612dd6d8a1SAdrian Hunter { 1622dd6d8a1SAdrian Hunter if (signr == -1) 1632dd6d8a1SAdrian Hunter return; 1642dd6d8a1SAdrian Hunter 1652dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1662dd6d8a1SAdrian Hunter raise(signr); 1672dd6d8a1SAdrian Hunter } 1682dd6d8a1SAdrian Hunter 169e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 170e31f0d01SAdrian Hunter 171ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 172ef149c25SAdrian Hunter union perf_event *event, void *data1, 173ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 174ef149c25SAdrian Hunter { 175ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 176*8ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 177ef149c25SAdrian Hunter size_t padding; 178ef149c25SAdrian Hunter u8 pad[8] = {0}; 179ef149c25SAdrian Hunter 180*8ceb41d7SJiri Olsa if (!perf_data__is_pipe(data)) { 18199fa2984SAdrian Hunter off_t file_offset; 182*8ceb41d7SJiri Olsa int fd = perf_data__fd(data); 18399fa2984SAdrian Hunter int err; 18499fa2984SAdrian Hunter 18599fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 18699fa2984SAdrian Hunter if (file_offset == -1) 18799fa2984SAdrian Hunter return -1; 18899fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 18999fa2984SAdrian Hunter event, file_offset); 19099fa2984SAdrian Hunter if (err) 19199fa2984SAdrian Hunter return err; 19299fa2984SAdrian Hunter } 19399fa2984SAdrian Hunter 194ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 195ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 196ef149c25SAdrian Hunter if (padding) 197ef149c25SAdrian Hunter padding = 8 - padding; 198ef149c25SAdrian Hunter 199ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 200ef149c25SAdrian Hunter record__write(rec, data1, len1); 201ef149c25SAdrian Hunter if (len2) 202ef149c25SAdrian Hunter record__write(rec, data2, len2); 203ef149c25SAdrian Hunter record__write(rec, &pad, padding); 204ef149c25SAdrian Hunter 205ef149c25SAdrian Hunter return 0; 206ef149c25SAdrian Hunter } 207ef149c25SAdrian Hunter 208ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 209ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 210ef149c25SAdrian Hunter { 211ef149c25SAdrian Hunter int ret; 212ef149c25SAdrian Hunter 213ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 214ef149c25SAdrian Hunter record__process_auxtrace); 215ef149c25SAdrian Hunter if (ret < 0) 216ef149c25SAdrian Hunter return ret; 217ef149c25SAdrian Hunter 218ef149c25SAdrian Hunter if (ret) 219ef149c25SAdrian Hunter rec->samples++; 220ef149c25SAdrian Hunter 221ef149c25SAdrian Hunter return 0; 222ef149c25SAdrian Hunter } 223ef149c25SAdrian Hunter 2242dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2252dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2262dd6d8a1SAdrian Hunter { 2272dd6d8a1SAdrian Hunter int ret; 2282dd6d8a1SAdrian Hunter 2292dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2302dd6d8a1SAdrian Hunter record__process_auxtrace, 2312dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2322dd6d8a1SAdrian Hunter if (ret < 0) 2332dd6d8a1SAdrian Hunter return ret; 2342dd6d8a1SAdrian Hunter 2352dd6d8a1SAdrian Hunter if (ret) 2362dd6d8a1SAdrian Hunter rec->samples++; 2372dd6d8a1SAdrian Hunter 2382dd6d8a1SAdrian Hunter return 0; 2392dd6d8a1SAdrian Hunter } 2402dd6d8a1SAdrian Hunter 2412dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2422dd6d8a1SAdrian Hunter { 2432dd6d8a1SAdrian Hunter int i; 2442dd6d8a1SAdrian Hunter int rc = 0; 2452dd6d8a1SAdrian Hunter 2462dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2472dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2482dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2492dd6d8a1SAdrian Hunter 2502dd6d8a1SAdrian Hunter if (!mm->base) 2512dd6d8a1SAdrian Hunter continue; 2522dd6d8a1SAdrian Hunter 2532dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2542dd6d8a1SAdrian Hunter rc = -1; 2552dd6d8a1SAdrian Hunter goto out; 2562dd6d8a1SAdrian Hunter } 2572dd6d8a1SAdrian Hunter } 2582dd6d8a1SAdrian Hunter out: 2592dd6d8a1SAdrian Hunter return rc; 2602dd6d8a1SAdrian Hunter } 2612dd6d8a1SAdrian Hunter 2622dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2632dd6d8a1SAdrian Hunter { 2642dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2652dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2665f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 2672dd6d8a1SAdrian Hunter } else { 2685f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 2695f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 2705f9cf599SWang Nan else 2715f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 2722dd6d8a1SAdrian Hunter } 2732dd6d8a1SAdrian Hunter } 2742dd6d8a1SAdrian Hunter 275e31f0d01SAdrian Hunter #else 276e31f0d01SAdrian Hunter 277e31f0d01SAdrian Hunter static inline 278e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 279e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 280e31f0d01SAdrian Hunter { 281e31f0d01SAdrian Hunter return 0; 282e31f0d01SAdrian Hunter } 283e31f0d01SAdrian Hunter 2842dd6d8a1SAdrian Hunter static inline 2852dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2862dd6d8a1SAdrian Hunter { 2872dd6d8a1SAdrian Hunter } 2882dd6d8a1SAdrian Hunter 2892dd6d8a1SAdrian Hunter static inline 2902dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2912dd6d8a1SAdrian Hunter { 2922dd6d8a1SAdrian Hunter return 0; 2932dd6d8a1SAdrian Hunter } 2942dd6d8a1SAdrian Hunter 295e31f0d01SAdrian Hunter #endif 296e31f0d01SAdrian Hunter 297cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 298cda57a8cSWang Nan struct perf_evlist *evlist) 299cda57a8cSWang Nan { 300cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 301cda57a8cSWang Nan char msg[512]; 302cda57a8cSWang Nan 303cda57a8cSWang Nan if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 304cda57a8cSWang Nan opts->auxtrace_mmap_pages, 305cda57a8cSWang Nan opts->auxtrace_snapshot_mode) < 0) { 306cda57a8cSWang Nan if (errno == EPERM) { 307cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 308cda57a8cSWang Nan "Consider increasing " 309cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 310cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 311cda57a8cSWang Nan "(current value: %u,%u)\n", 312cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 313cda57a8cSWang Nan return -errno; 314cda57a8cSWang Nan } else { 315cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 316c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 317cda57a8cSWang Nan if (errno) 318cda57a8cSWang Nan return -errno; 319cda57a8cSWang Nan else 320cda57a8cSWang Nan return -EINVAL; 321cda57a8cSWang Nan } 322cda57a8cSWang Nan } 323cda57a8cSWang Nan return 0; 324cda57a8cSWang Nan } 325cda57a8cSWang Nan 326cda57a8cSWang Nan static int record__mmap(struct record *rec) 327cda57a8cSWang Nan { 328cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 329cda57a8cSWang Nan } 330cda57a8cSWang Nan 3318c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 332dd7927f4SArnaldo Carvalho de Melo { 333d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 3346a4bb04cSJiri Olsa struct perf_evsel *pos; 335d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 336d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 337b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 3385d8bb1ecSMathieu Poirier struct perf_evsel_config_term *err_term; 3398d3eca20SDavid Ahern int rc = 0; 340dd7927f4SArnaldo Carvalho de Melo 341e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 342cac21425SJiri Olsa 343e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 3443da297a6SIngo Molnar try_again: 345d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 34656e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 347bb963e16SNamhyung Kim if (verbose > 0) 348c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 3493da297a6SIngo Molnar goto try_again; 3503da297a6SIngo Molnar } 351ca6a4258SDavid Ahern 35256e52e85SArnaldo Carvalho de Melo rc = -errno; 35356e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 35456e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 35556e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3568d3eca20SDavid Ahern goto out; 3577c6a1c65SPeter Zijlstra } 3587c6a1c65SPeter Zijlstra } 3597c6a1c65SPeter Zijlstra 36023d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 36162d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 36223d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 363c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 3648d3eca20SDavid Ahern rc = -1; 3658d3eca20SDavid Ahern goto out; 3660a102479SFrederic Weisbecker } 3670a102479SFrederic Weisbecker 3685d8bb1ecSMathieu Poirier if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) { 36962d94b00SArnaldo Carvalho de Melo pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", 3705d8bb1ecSMathieu Poirier err_term->val.drv_cfg, perf_evsel__name(pos), errno, 3715d8bb1ecSMathieu Poirier str_error_r(errno, msg, sizeof(msg))); 3725d8bb1ecSMathieu Poirier rc = -1; 3735d8bb1ecSMathieu Poirier goto out; 3745d8bb1ecSMathieu Poirier } 3755d8bb1ecSMathieu Poirier 376cda57a8cSWang Nan rc = record__mmap(rec); 377cda57a8cSWang Nan if (rc) 3788d3eca20SDavid Ahern goto out; 3790a27d7f9SArnaldo Carvalho de Melo 380a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3817b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3828d3eca20SDavid Ahern out: 3838d3eca20SDavid Ahern return rc; 384a91e5431SArnaldo Carvalho de Melo } 385a91e5431SArnaldo Carvalho de Melo 386e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 387e3d59112SNamhyung Kim union perf_event *event, 388e3d59112SNamhyung Kim struct perf_sample *sample, 389e3d59112SNamhyung Kim struct perf_evsel *evsel, 390e3d59112SNamhyung Kim struct machine *machine) 391e3d59112SNamhyung Kim { 392e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 393e3d59112SNamhyung Kim 394e3d59112SNamhyung Kim rec->samples++; 395e3d59112SNamhyung Kim 396e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 397e3d59112SNamhyung Kim } 398e3d59112SNamhyung Kim 3998c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 4006122e4e4SArnaldo Carvalho de Melo { 401*8ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 402f5fc1412SJiri Olsa struct perf_session *session = rec->session; 4036122e4e4SArnaldo Carvalho de Melo 404*8ceb41d7SJiri Olsa if (data->size == 0) 4059f591fd7SArnaldo Carvalho de Melo return 0; 4069f591fd7SArnaldo Carvalho de Melo 40700dc8657SNamhyung Kim /* 40800dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 40900dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 41000dc8657SNamhyung Kim * we prefer the vmlinux path like 41100dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 41200dc8657SNamhyung Kim * 41300dc8657SNamhyung Kim * rather than build-id path (in debug directory). 41400dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 41500dc8657SNamhyung Kim */ 41600dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 41700dc8657SNamhyung Kim 4186156681bSNamhyung Kim /* 4196156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 4206156681bSNamhyung Kim * so no need to process samples. 4216156681bSNamhyung Kim */ 4226156681bSNamhyung Kim if (rec->buildid_all) 4236156681bSNamhyung Kim rec->tool.sample = NULL; 4246156681bSNamhyung Kim 425b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 4266122e4e4SArnaldo Carvalho de Melo } 4276122e4e4SArnaldo Carvalho de Melo 4288115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 429a1645ce1SZhang, Yanmin { 430a1645ce1SZhang, Yanmin int err; 43145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 432a1645ce1SZhang, Yanmin /* 433a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 434a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 435a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 436a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 437a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 438a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 439a1645ce1SZhang, Yanmin */ 44045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 441743eb868SArnaldo Carvalho de Melo machine); 442a1645ce1SZhang, Yanmin if (err < 0) 443a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 44423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 445a1645ce1SZhang, Yanmin 446a1645ce1SZhang, Yanmin /* 447a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 448a1645ce1SZhang, Yanmin * have no _text sometimes. 449a1645ce1SZhang, Yanmin */ 45045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4510ae617beSAdrian Hunter machine); 452a1645ce1SZhang, Yanmin if (err < 0) 453a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 45423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 455a1645ce1SZhang, Yanmin } 456a1645ce1SZhang, Yanmin 45798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 45898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 45998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 46098402807SFrederic Weisbecker }; 46198402807SFrederic Weisbecker 462a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 463a4ea0ec4SWang Nan bool backward) 46498402807SFrederic Weisbecker { 465dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4660e2e63ddSPeter Zijlstra int i; 4678d3eca20SDavid Ahern int rc = 0; 468a4ea0ec4SWang Nan struct perf_mmap *maps; 46998402807SFrederic Weisbecker 470cb21686bSWang Nan if (!evlist) 471cb21686bSWang Nan return 0; 472ef149c25SAdrian Hunter 473b2cb615dSWang Nan maps = backward ? evlist->backward_mmap : evlist->mmap; 474a4ea0ec4SWang Nan if (!maps) 475a4ea0ec4SWang Nan return 0; 476cb21686bSWang Nan 47754cc54deSWang Nan if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 47854cc54deSWang Nan return 0; 47954cc54deSWang Nan 480a4ea0ec4SWang Nan for (i = 0; i < evlist->nr_mmaps; i++) { 481a4ea0ec4SWang Nan struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 482a4ea0ec4SWang Nan 483a4ea0ec4SWang Nan if (maps[i].base) { 484d37f1586SArnaldo Carvalho de Melo if (perf_mmap__push(&maps[i], evlist->overwrite, backward, rec, record__pushfn) != 0) { 4858d3eca20SDavid Ahern rc = -1; 4868d3eca20SDavid Ahern goto out; 4878d3eca20SDavid Ahern } 4888d3eca20SDavid Ahern } 489ef149c25SAdrian Hunter 4902dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 491ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 492ef149c25SAdrian Hunter rc = -1; 493ef149c25SAdrian Hunter goto out; 494ef149c25SAdrian Hunter } 49598402807SFrederic Weisbecker } 49698402807SFrederic Weisbecker 497dcabb507SJiri Olsa /* 498dcabb507SJiri Olsa * Mark the round finished in case we wrote 499dcabb507SJiri Olsa * at least one event. 500dcabb507SJiri Olsa */ 501dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 5028c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 5038d3eca20SDavid Ahern 50454cc54deSWang Nan if (backward) 50554cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 5068d3eca20SDavid Ahern out: 5078d3eca20SDavid Ahern return rc; 50898402807SFrederic Weisbecker } 50998402807SFrederic Weisbecker 510cb21686bSWang Nan static int record__mmap_read_all(struct record *rec) 511cb21686bSWang Nan { 512cb21686bSWang Nan int err; 513cb21686bSWang Nan 514a4ea0ec4SWang Nan err = record__mmap_read_evlist(rec, rec->evlist, false); 515cb21686bSWang Nan if (err) 516cb21686bSWang Nan return err; 517cb21686bSWang Nan 51805737464SWang Nan return record__mmap_read_evlist(rec, rec->evlist, true); 519cb21686bSWang Nan } 520cb21686bSWang Nan 5218c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 52257706abcSDavid Ahern { 52357706abcSDavid Ahern struct perf_session *session = rec->session; 52457706abcSDavid Ahern int feat; 52557706abcSDavid Ahern 52657706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 52757706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 52857706abcSDavid Ahern 52957706abcSDavid Ahern if (rec->no_buildid) 53057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 53157706abcSDavid Ahern 5323e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 53357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 53457706abcSDavid Ahern 53557706abcSDavid Ahern if (!rec->opts.branch_stack) 53657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 537ef149c25SAdrian Hunter 538ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 539ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 540ffa517adSJiri Olsa 541ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 54257706abcSDavid Ahern } 54357706abcSDavid Ahern 544e1ab48baSWang Nan static void 545e1ab48baSWang Nan record__finish_output(struct record *rec) 546e1ab48baSWang Nan { 547*8ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 548*8ceb41d7SJiri Olsa int fd = perf_data__fd(data); 549e1ab48baSWang Nan 550*8ceb41d7SJiri Olsa if (data->is_pipe) 551e1ab48baSWang Nan return; 552e1ab48baSWang Nan 553e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 554*8ceb41d7SJiri Olsa data->size = lseek(perf_data__fd(data), 0, SEEK_CUR); 555e1ab48baSWang Nan 556e1ab48baSWang Nan if (!rec->no_buildid) { 557e1ab48baSWang Nan process_buildids(rec); 558e1ab48baSWang Nan 559e1ab48baSWang Nan if (rec->buildid_all) 560e1ab48baSWang Nan dsos__hit_all(rec->session); 561e1ab48baSWang Nan } 562e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 563e1ab48baSWang Nan 564e1ab48baSWang Nan return; 565e1ab48baSWang Nan } 566e1ab48baSWang Nan 5674ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 568be7b0c9eSWang Nan { 5699d6aae72SArnaldo Carvalho de Melo int err; 5709d6aae72SArnaldo Carvalho de Melo struct thread_map *thread_map; 571be7b0c9eSWang Nan 5724ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 5734ea648aeSWang Nan return 0; 5744ea648aeSWang Nan 5759d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 5769d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 5779d6aae72SArnaldo Carvalho de Melo return -1; 5789d6aae72SArnaldo Carvalho de Melo 5799d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 580be7b0c9eSWang Nan process_synthesized_event, 581be7b0c9eSWang Nan &rec->session->machines.host, 582be7b0c9eSWang Nan rec->opts.sample_address, 583be7b0c9eSWang Nan rec->opts.proc_map_timeout); 5849d6aae72SArnaldo Carvalho de Melo thread_map__put(thread_map); 5859d6aae72SArnaldo Carvalho de Melo return err; 586be7b0c9eSWang Nan } 587be7b0c9eSWang Nan 5884ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 5893c1cb7e3SWang Nan 590ecfd7a9cSWang Nan static int 591ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 592ecfd7a9cSWang Nan { 593*8ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 594ecfd7a9cSWang Nan int fd, err; 595ecfd7a9cSWang Nan 596ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 597ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 598ecfd7a9cSWang Nan 5994ea648aeSWang Nan record__synthesize(rec, true); 6004ea648aeSWang Nan if (target__none(&rec->opts.target)) 6014ea648aeSWang Nan record__synthesize_workload(rec, true); 6024ea648aeSWang Nan 603ecfd7a9cSWang Nan rec->samples = 0; 604ecfd7a9cSWang Nan record__finish_output(rec); 605ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 606ecfd7a9cSWang Nan if (err) { 607ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 608ecfd7a9cSWang Nan return -EINVAL; 609ecfd7a9cSWang Nan } 610ecfd7a9cSWang Nan 611*8ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 612ecfd7a9cSWang Nan rec->session->header.data_offset, 613ecfd7a9cSWang Nan at_exit); 614ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 615ecfd7a9cSWang Nan rec->bytes_written = 0; 616ecfd7a9cSWang Nan rec->session->header.data_size = 0; 617ecfd7a9cSWang Nan } 618ecfd7a9cSWang Nan 619ecfd7a9cSWang Nan if (!quiet) 620ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 621*8ceb41d7SJiri Olsa data->path, timestamp); 6223c1cb7e3SWang Nan 6233c1cb7e3SWang Nan /* Output tracking events */ 624be7b0c9eSWang Nan if (!at_exit) { 6254ea648aeSWang Nan record__synthesize(rec, false); 6263c1cb7e3SWang Nan 627be7b0c9eSWang Nan /* 628be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 629be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 630be7b0c9eSWang Nan * generate tracking events because there's no thread_map 631be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 632be7b0c9eSWang Nan * contain map and comm information. 633be7b0c9eSWang Nan * Create a fake thread_map and directly call 634be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 635be7b0c9eSWang Nan */ 636be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 6374ea648aeSWang Nan record__synthesize_workload(rec, false); 638be7b0c9eSWang Nan } 639ecfd7a9cSWang Nan return fd; 640ecfd7a9cSWang Nan } 641ecfd7a9cSWang Nan 642f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 643f33cbe72SArnaldo Carvalho de Melo 644f33cbe72SArnaldo Carvalho de Melo /* 645f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 646f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 647f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 648f33cbe72SArnaldo Carvalho de Melo */ 64945604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 65045604710SNamhyung Kim siginfo_t *info, 651f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 652f33cbe72SArnaldo Carvalho de Melo { 653f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 654f33cbe72SArnaldo Carvalho de Melo done = 1; 655f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 656f33cbe72SArnaldo Carvalho de Melo } 657f33cbe72SArnaldo Carvalho de Melo 6582dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 659bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 6602dd6d8a1SAdrian Hunter 66146bc29b9SAdrian Hunter int __weak 66246bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 66346bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 66446bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 66546bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 66646bc29b9SAdrian Hunter { 66746bc29b9SAdrian Hunter return 0; 66846bc29b9SAdrian Hunter } 66946bc29b9SAdrian Hunter 670ee667f94SWang Nan static const struct perf_event_mmap_page * 671ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist) 672ee667f94SWang Nan { 673b2cb615dSWang Nan if (evlist) { 674b2cb615dSWang Nan if (evlist->mmap && evlist->mmap[0].base) 675ee667f94SWang Nan return evlist->mmap[0].base; 676b2cb615dSWang Nan if (evlist->backward_mmap && evlist->backward_mmap[0].base) 677b2cb615dSWang Nan return evlist->backward_mmap[0].base; 678b2cb615dSWang Nan } 679ee667f94SWang Nan return NULL; 680ee667f94SWang Nan } 681ee667f94SWang Nan 682c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 683c45628b0SWang Nan { 684ee667f94SWang Nan const struct perf_event_mmap_page *pc; 685ee667f94SWang Nan 686ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 687ee667f94SWang Nan if (pc) 688ee667f94SWang Nan return pc; 689c45628b0SWang Nan return NULL; 690c45628b0SWang Nan } 691c45628b0SWang Nan 6924ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 693c45c86ebSWang Nan { 694c45c86ebSWang Nan struct perf_session *session = rec->session; 695c45c86ebSWang Nan struct machine *machine = &session->machines.host; 696*8ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 697c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 698c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 699*8ceb41d7SJiri Olsa int fd = perf_data__fd(data); 700c45c86ebSWang Nan int err = 0; 701c45c86ebSWang Nan 7024ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 7034ea648aeSWang Nan return 0; 7044ea648aeSWang Nan 705*8ceb41d7SJiri Olsa if (data->is_pipe) { 706e9def1b2SDavid Carrillo-Cisneros err = perf_event__synthesize_features( 707e9def1b2SDavid Carrillo-Cisneros tool, session, rec->evlist, process_synthesized_event); 708e9def1b2SDavid Carrillo-Cisneros if (err < 0) { 709e9def1b2SDavid Carrillo-Cisneros pr_err("Couldn't synthesize features.\n"); 710e9def1b2SDavid Carrillo-Cisneros return err; 711e9def1b2SDavid Carrillo-Cisneros } 712e9def1b2SDavid Carrillo-Cisneros 713c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 714c45c86ebSWang Nan process_synthesized_event); 715c45c86ebSWang Nan if (err < 0) { 716c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 717c45c86ebSWang Nan goto out; 718c45c86ebSWang Nan } 719c45c86ebSWang Nan 720c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 721c45c86ebSWang Nan /* 722c45c86ebSWang Nan * FIXME err <= 0 here actually means that 723c45c86ebSWang Nan * there were no tracepoints so its not really 724c45c86ebSWang Nan * an error, just that we don't need to 725c45c86ebSWang Nan * synthesize anything. We really have to 726c45c86ebSWang Nan * return this more properly and also 727c45c86ebSWang Nan * propagate errors that now are calling die() 728c45c86ebSWang Nan */ 729c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 730c45c86ebSWang Nan process_synthesized_event); 731c45c86ebSWang Nan if (err <= 0) { 732c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 733c45c86ebSWang Nan goto out; 734c45c86ebSWang Nan } 735c45c86ebSWang Nan rec->bytes_written += err; 736c45c86ebSWang Nan } 737c45c86ebSWang Nan } 738c45c86ebSWang Nan 739c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 74046bc29b9SAdrian Hunter process_synthesized_event, machine); 74146bc29b9SAdrian Hunter if (err) 74246bc29b9SAdrian Hunter goto out; 74346bc29b9SAdrian Hunter 744c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 745c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 746c45c86ebSWang Nan session, process_synthesized_event); 747c45c86ebSWang Nan if (err) 748c45c86ebSWang Nan goto out; 749c45c86ebSWang Nan } 750c45c86ebSWang Nan 751c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 752c45c86ebSWang Nan machine); 753c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 754c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 755c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 756c45c86ebSWang Nan 757c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 758c45c86ebSWang Nan machine); 759c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 760c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 761c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 762c45c86ebSWang Nan 763c45c86ebSWang Nan if (perf_guest) { 764c45c86ebSWang Nan machines__process_guests(&session->machines, 765c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 766c45c86ebSWang Nan } 767c45c86ebSWang Nan 768c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 769c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 770340b47f5SKan Liang opts->proc_map_timeout, 1); 771c45c86ebSWang Nan out: 772c45c86ebSWang Nan return err; 773c45c86ebSWang Nan } 774c45c86ebSWang Nan 7758c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 77686470930SIngo Molnar { 77757706abcSDavid Ahern int err; 77845604710SNamhyung Kim int status = 0; 7798b412664SPeter Zijlstra unsigned long waking = 0; 78046be604bSZhang, Yanmin const bool forks = argc > 0; 78123346f21SArnaldo Carvalho de Melo struct machine *machine; 78245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 783b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 784*8ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 785d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 7866dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 78742aa276fSNamhyung Kim int fd; 78886470930SIngo Molnar 789d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 79033e49ea7SAndi Kleen 79145604710SNamhyung Kim atexit(record__sig_exit); 792f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 793f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 794804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 795a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 796c0bdc1c4SWang Nan 797f3b3614aSHari Bathini if (rec->opts.record_namespaces) 798f3b3614aSHari Bathini tool->namespace_events = true; 799f3b3614aSHari Bathini 800dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 8012dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 8023c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 8035f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 804dc0c6127SJiri Olsa if (rec->switch_output.enabled) 8053c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 806c0bdc1c4SWang Nan } else { 8072dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 808c0bdc1c4SWang Nan } 809f5970550SPeter Zijlstra 810*8ceb41d7SJiri Olsa session = perf_session__new(data, false, tool); 81194c744b6SArnaldo Carvalho de Melo if (session == NULL) { 812ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 813a9a70bbcSArnaldo Carvalho de Melo return -1; 814a9a70bbcSArnaldo Carvalho de Melo } 815a9a70bbcSArnaldo Carvalho de Melo 816*8ceb41d7SJiri Olsa fd = perf_data__fd(data); 817d20deb64SArnaldo Carvalho de Melo rec->session = session; 818d20deb64SArnaldo Carvalho de Melo 8198c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 820330aa675SStephane Eranian 821d4db3f16SArnaldo Carvalho de Melo if (forks) { 8223e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 823*8ceb41d7SJiri Olsa argv, data->is_pipe, 824735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 82535b9d88eSArnaldo Carvalho de Melo if (err < 0) { 82635b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 82745604710SNamhyung Kim status = err; 82835b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 829856e9660SPeter Zijlstra } 830856e9660SPeter Zijlstra } 831856e9660SPeter Zijlstra 8328c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 8338d3eca20SDavid Ahern err = -1; 83445604710SNamhyung Kim goto out_child; 8358d3eca20SDavid Ahern } 83686470930SIngo Molnar 8378690a2a7SWang Nan err = bpf__apply_obj_config(); 8388690a2a7SWang Nan if (err) { 8398690a2a7SWang Nan char errbuf[BUFSIZ]; 8408690a2a7SWang Nan 8418690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 8428690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 8438690a2a7SWang Nan errbuf); 8448690a2a7SWang Nan goto out_child; 8458690a2a7SWang Nan } 8468690a2a7SWang Nan 847cca8482cSAdrian Hunter /* 848cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 849cca8482cSAdrian Hunter * evlist. 850cca8482cSAdrian Hunter */ 851cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 852cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 853cca8482cSAdrian Hunter rec->tool.ordered_events = false; 854cca8482cSAdrian Hunter } 855cca8482cSAdrian Hunter 8563e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 857a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 858a8bb559bSNamhyung Kim 859*8ceb41d7SJiri Olsa if (data->is_pipe) { 86042aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 861529870e3STom Zanussi if (err < 0) 86245604710SNamhyung Kim goto out_child; 863563aecb2SJiri Olsa } else { 86442aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 865d5eed904SArnaldo Carvalho de Melo if (err < 0) 86645604710SNamhyung Kim goto out_child; 867d5eed904SArnaldo Carvalho de Melo } 8687c6a1c65SPeter Zijlstra 869d3665498SDavid Ahern if (!rec->no_buildid 870e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 871d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 872e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 8738d3eca20SDavid Ahern err = -1; 87445604710SNamhyung Kim goto out_child; 875e20960c0SRobert Richter } 876e20960c0SRobert Richter 87734ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 878743eb868SArnaldo Carvalho de Melo 8794ea648aeSWang Nan err = record__synthesize(rec, false); 880c45c86ebSWang Nan if (err < 0) 88145604710SNamhyung Kim goto out_child; 8828d3eca20SDavid Ahern 883d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 88486470930SIngo Molnar struct sched_param param; 88586470930SIngo Molnar 886d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 88786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 8886beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 8898d3eca20SDavid Ahern err = -1; 89045604710SNamhyung Kim goto out_child; 89186470930SIngo Molnar } 89286470930SIngo Molnar } 89386470930SIngo Molnar 894774cb499SJiri Olsa /* 895774cb499SJiri Olsa * When perf is starting the traced process, all the events 896774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 897774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 898774cb499SJiri Olsa */ 8996619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 9003e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 901764e16a3SDavid Ahern 902856e9660SPeter Zijlstra /* 903856e9660SPeter Zijlstra * Let the child rip 904856e9660SPeter Zijlstra */ 905e803cf97SNamhyung Kim if (forks) { 906e5bed564SNamhyung Kim union perf_event *event; 907e907caf3SHari Bathini pid_t tgid; 908e5bed564SNamhyung Kim 909e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 910e5bed564SNamhyung Kim if (event == NULL) { 911e5bed564SNamhyung Kim err = -ENOMEM; 912e5bed564SNamhyung Kim goto out_child; 913e5bed564SNamhyung Kim } 914e5bed564SNamhyung Kim 915e803cf97SNamhyung Kim /* 916e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 917e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 918e803cf97SNamhyung Kim * cannot see a correct process name for those events. 919e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 920e803cf97SNamhyung Kim */ 921e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 922e803cf97SNamhyung Kim rec->evlist->workload.pid, 923e803cf97SNamhyung Kim process_synthesized_event, 924e803cf97SNamhyung Kim machine); 925e5bed564SNamhyung Kim free(event); 926e803cf97SNamhyung Kim 927e907caf3SHari Bathini if (tgid == -1) 928e907caf3SHari Bathini goto out_child; 929e907caf3SHari Bathini 930e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 931e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 932e907caf3SHari Bathini machine->id_hdr_size); 933e907caf3SHari Bathini if (event == NULL) { 934e907caf3SHari Bathini err = -ENOMEM; 935e907caf3SHari Bathini goto out_child; 936e907caf3SHari Bathini } 937e907caf3SHari Bathini 938e907caf3SHari Bathini /* 939e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 940e907caf3SHari Bathini */ 941e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 942e907caf3SHari Bathini rec->evlist->workload.pid, 943e907caf3SHari Bathini tgid, process_synthesized_event, 944e907caf3SHari Bathini machine); 945e907caf3SHari Bathini free(event); 946e907caf3SHari Bathini 9473e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 948e803cf97SNamhyung Kim } 949856e9660SPeter Zijlstra 9506619a53eSAndi Kleen if (opts->initial_delay) { 9510693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 9526619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 9536619a53eSAndi Kleen } 9546619a53eSAndi Kleen 9555f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 9563c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 957a074865eSWang Nan perf_hooks__invoke_record_start(); 958649c48a9SPeter Zijlstra for (;;) { 9599f065194SYang Shi unsigned long long hits = rec->samples; 96086470930SIngo Molnar 96105737464SWang Nan /* 96205737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 96305737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 96405737464SWang Nan * hits != rec->samples in previous round. 96505737464SWang Nan * 96605737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 96705737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 96805737464SWang Nan */ 96905737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 97005737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 97105737464SWang Nan 9728c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 9735f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 9743c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 9758d3eca20SDavid Ahern err = -1; 97645604710SNamhyung Kim goto out_child; 9778d3eca20SDavid Ahern } 97886470930SIngo Molnar 9792dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 9802dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 9815f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 9822dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 9835f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 9842dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 9852dd6d8a1SAdrian Hunter err = -1; 9862dd6d8a1SAdrian Hunter goto out_child; 9872dd6d8a1SAdrian Hunter } 9882dd6d8a1SAdrian Hunter } 9892dd6d8a1SAdrian Hunter 9903c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 99105737464SWang Nan /* 99205737464SWang Nan * If switch_output_trigger is hit, the data in 99305737464SWang Nan * overwritable ring buffer should have been collected, 99405737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 99505737464SWang Nan * 99605737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 99705737464SWang Nan * record__mmap_read_all() didn't collect data from 99805737464SWang Nan * overwritable ring buffer. Read again. 99905737464SWang Nan */ 100005737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 100105737464SWang Nan continue; 10023c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 10033c1cb7e3SWang Nan 100405737464SWang Nan /* 100505737464SWang Nan * Reenable events in overwrite ring buffer after 100605737464SWang Nan * record__mmap_read_all(): we should have collected 100705737464SWang Nan * data from it. 100805737464SWang Nan */ 100905737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 101005737464SWang Nan 10113c1cb7e3SWang Nan if (!quiet) 10123c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 10133c1cb7e3SWang Nan waking); 10143c1cb7e3SWang Nan waking = 0; 10153c1cb7e3SWang Nan fd = record__switch_output(rec, false); 10163c1cb7e3SWang Nan if (fd < 0) { 10173c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 10183c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 10193c1cb7e3SWang Nan err = fd; 10203c1cb7e3SWang Nan goto out_child; 10213c1cb7e3SWang Nan } 1022bfacbe3bSJiri Olsa 1023bfacbe3bSJiri Olsa /* re-arm the alarm */ 1024bfacbe3bSJiri Olsa if (rec->switch_output.time) 1025bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 10263c1cb7e3SWang Nan } 10273c1cb7e3SWang Nan 1028d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 10296dcf45efSArnaldo Carvalho de Melo if (done || draining) 1030649c48a9SPeter Zijlstra break; 1031f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 1032a515114fSJiri Olsa /* 1033a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1034a515114fSJiri Olsa * number of returned events and interrupt error. 1035a515114fSJiri Olsa */ 1036a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 103745604710SNamhyung Kim err = 0; 10388b412664SPeter Zijlstra waking++; 10396dcf45efSArnaldo Carvalho de Melo 10406dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 10416dcf45efSArnaldo Carvalho de Melo draining = true; 10428b412664SPeter Zijlstra } 10438b412664SPeter Zijlstra 1044774cb499SJiri Olsa /* 1045774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1046774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1047774cb499SJiri Olsa * disable events in this case. 1048774cb499SJiri Olsa */ 1049602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 10505f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 10513e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 10522711926aSJiri Olsa disabled = true; 10532711926aSJiri Olsa } 10548b412664SPeter Zijlstra } 10555f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 10563c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 10578b412664SPeter Zijlstra 1058f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 105935550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1060c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1061f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1062f33cbe72SArnaldo Carvalho de Melo err = -1; 106345604710SNamhyung Kim goto out_child; 1064f33cbe72SArnaldo Carvalho de Melo } 1065f33cbe72SArnaldo Carvalho de Melo 1066e3d59112SNamhyung Kim if (!quiet) 10678b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 106886470930SIngo Molnar 10694ea648aeSWang Nan if (target__none(&rec->opts.target)) 10704ea648aeSWang Nan record__synthesize_workload(rec, true); 10714ea648aeSWang Nan 107245604710SNamhyung Kim out_child: 107345604710SNamhyung Kim if (forks) { 107445604710SNamhyung Kim int exit_status; 107545604710SNamhyung Kim 107645604710SNamhyung Kim if (!child_finished) 107745604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 107845604710SNamhyung Kim 107945604710SNamhyung Kim wait(&exit_status); 108045604710SNamhyung Kim 108145604710SNamhyung Kim if (err < 0) 108245604710SNamhyung Kim status = err; 108345604710SNamhyung Kim else if (WIFEXITED(exit_status)) 108445604710SNamhyung Kim status = WEXITSTATUS(exit_status); 108545604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 108645604710SNamhyung Kim signr = WTERMSIG(exit_status); 108745604710SNamhyung Kim } else 108845604710SNamhyung Kim status = err; 108945604710SNamhyung Kim 10904ea648aeSWang Nan record__synthesize(rec, true); 1091e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1092e3d59112SNamhyung Kim rec->samples = 0; 1093e3d59112SNamhyung Kim 1094ecfd7a9cSWang Nan if (!err) { 1095ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1096e1ab48baSWang Nan record__finish_output(rec); 1097ecfd7a9cSWang Nan } else { 1098ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1099ecfd7a9cSWang Nan if (fd < 0) { 1100ecfd7a9cSWang Nan status = fd; 1101ecfd7a9cSWang Nan goto out_delete_session; 1102ecfd7a9cSWang Nan } 1103ecfd7a9cSWang Nan } 1104ecfd7a9cSWang Nan } 110539d17dacSArnaldo Carvalho de Melo 1106a074865eSWang Nan perf_hooks__invoke_record_end(); 1107a074865eSWang Nan 1108e3d59112SNamhyung Kim if (!err && !quiet) { 1109e3d59112SNamhyung Kim char samples[128]; 1110ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1111ecfd7a9cSWang Nan ".<timestamp>" : ""; 1112e3d59112SNamhyung Kim 1113ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1114e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1115e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1116e3d59112SNamhyung Kim else 1117e3d59112SNamhyung Kim samples[0] = '\0'; 1118e3d59112SNamhyung Kim 1119ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1120*8ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 1121*8ceb41d7SJiri Olsa data->path, postfix, samples); 1122e3d59112SNamhyung Kim } 1123e3d59112SNamhyung Kim 112439d17dacSArnaldo Carvalho de Melo out_delete_session: 112539d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 112645604710SNamhyung Kim return status; 112786470930SIngo Molnar } 112886470930SIngo Molnar 11290883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 113009b0fd45SJiri Olsa { 1131aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1132a601fdffSJiri Olsa 11330883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 113426d33022SJiri Olsa 11350883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 113609b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 11370883e820SArnaldo Carvalho de Melo callchain->dump_size); 11380883e820SArnaldo Carvalho de Melo } 11390883e820SArnaldo Carvalho de Melo 11400883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 11410883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 11420883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 11430883e820SArnaldo Carvalho de Melo { 11440883e820SArnaldo Carvalho de Melo int ret; 11450883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 11460883e820SArnaldo Carvalho de Melo 11470883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 11480883e820SArnaldo Carvalho de Melo if (unset) { 11490883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 11500883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 11510883e820SArnaldo Carvalho de Melo return 0; 11520883e820SArnaldo Carvalho de Melo } 11530883e820SArnaldo Carvalho de Melo 11540883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 11550883e820SArnaldo Carvalho de Melo if (!ret) { 11560883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 11570883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 11580883e820SArnaldo Carvalho de Melo record->sample_address = true; 11590883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 11600883e820SArnaldo Carvalho de Melo } 11610883e820SArnaldo Carvalho de Melo 11620883e820SArnaldo Carvalho de Melo return ret; 116309b0fd45SJiri Olsa } 116409b0fd45SJiri Olsa 1165c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 116609b0fd45SJiri Olsa const char *arg, 116709b0fd45SJiri Olsa int unset) 116809b0fd45SJiri Olsa { 11690883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 117026d33022SJiri Olsa } 117126d33022SJiri Olsa 1172c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 117309b0fd45SJiri Olsa const char *arg __maybe_unused, 117409b0fd45SJiri Olsa int unset __maybe_unused) 117509b0fd45SJiri Olsa { 11762ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1177c421e80bSKan Liang 11782ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 117909b0fd45SJiri Olsa 11802ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 11812ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1182eb853e80SJiri Olsa 11832ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 118409b0fd45SJiri Olsa return 0; 118509b0fd45SJiri Olsa } 118609b0fd45SJiri Olsa 1187eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1188eb853e80SJiri Olsa { 11897a29c087SNamhyung Kim struct record *rec = cb; 11907a29c087SNamhyung Kim 11917a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 11927a29c087SNamhyung Kim if (!strcmp(value, "cache")) 11937a29c087SNamhyung Kim rec->no_buildid_cache = false; 11947a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 11957a29c087SNamhyung Kim rec->no_buildid_cache = true; 11967a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 11977a29c087SNamhyung Kim rec->no_buildid = true; 11987a29c087SNamhyung Kim else 11997a29c087SNamhyung Kim return -1; 12007a29c087SNamhyung Kim return 0; 12017a29c087SNamhyung Kim } 1202eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 12035a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 1204eb853e80SJiri Olsa 1205eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1206eb853e80SJiri Olsa } 1207eb853e80SJiri Olsa 1208814c8c38SPeter Zijlstra struct clockid_map { 1209814c8c38SPeter Zijlstra const char *name; 1210814c8c38SPeter Zijlstra int clockid; 1211814c8c38SPeter Zijlstra }; 1212814c8c38SPeter Zijlstra 1213814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1214814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1215814c8c38SPeter Zijlstra 1216814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1217814c8c38SPeter Zijlstra 1218814c8c38SPeter Zijlstra 1219814c8c38SPeter Zijlstra /* 1220814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1221814c8c38SPeter Zijlstra */ 1222814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1223814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1224814c8c38SPeter Zijlstra #endif 1225814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1226814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1227814c8c38SPeter Zijlstra #endif 1228814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1229814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1230814c8c38SPeter Zijlstra #endif 1231814c8c38SPeter Zijlstra 1232814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1233814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1234814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1235814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1236814c8c38SPeter Zijlstra 1237814c8c38SPeter Zijlstra /* available for some events */ 1238814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1239814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1240814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1241814c8c38SPeter Zijlstra 1242814c8c38SPeter Zijlstra /* available for the lazy */ 1243814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1244814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1245814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1246814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1247814c8c38SPeter Zijlstra 1248814c8c38SPeter Zijlstra CLOCKID_END, 1249814c8c38SPeter Zijlstra }; 1250814c8c38SPeter Zijlstra 1251814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1252814c8c38SPeter Zijlstra { 1253814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1254814c8c38SPeter Zijlstra const struct clockid_map *cm; 1255814c8c38SPeter Zijlstra const char *ostr = str; 1256814c8c38SPeter Zijlstra 1257814c8c38SPeter Zijlstra if (unset) { 1258814c8c38SPeter Zijlstra opts->use_clockid = 0; 1259814c8c38SPeter Zijlstra return 0; 1260814c8c38SPeter Zijlstra } 1261814c8c38SPeter Zijlstra 1262814c8c38SPeter Zijlstra /* no arg passed */ 1263814c8c38SPeter Zijlstra if (!str) 1264814c8c38SPeter Zijlstra return 0; 1265814c8c38SPeter Zijlstra 1266814c8c38SPeter Zijlstra /* no setting it twice */ 1267814c8c38SPeter Zijlstra if (opts->use_clockid) 1268814c8c38SPeter Zijlstra return -1; 1269814c8c38SPeter Zijlstra 1270814c8c38SPeter Zijlstra opts->use_clockid = true; 1271814c8c38SPeter Zijlstra 1272814c8c38SPeter Zijlstra /* if its a number, we're done */ 1273814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1274814c8c38SPeter Zijlstra return 0; 1275814c8c38SPeter Zijlstra 1276814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1277814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1278814c8c38SPeter Zijlstra str += 6; 1279814c8c38SPeter Zijlstra 1280814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1281814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1282814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1283814c8c38SPeter Zijlstra return 0; 1284814c8c38SPeter Zijlstra } 1285814c8c38SPeter Zijlstra } 1286814c8c38SPeter Zijlstra 1287814c8c38SPeter Zijlstra opts->use_clockid = false; 1288814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1289814c8c38SPeter Zijlstra return -1; 1290814c8c38SPeter Zijlstra } 1291814c8c38SPeter Zijlstra 1292e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1293e9db1310SAdrian Hunter const char *str, 1294e9db1310SAdrian Hunter int unset __maybe_unused) 1295e9db1310SAdrian Hunter { 1296e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1297e9db1310SAdrian Hunter char *s, *p; 1298e9db1310SAdrian Hunter unsigned int mmap_pages; 1299e9db1310SAdrian Hunter int ret; 1300e9db1310SAdrian Hunter 1301e9db1310SAdrian Hunter if (!str) 1302e9db1310SAdrian Hunter return -EINVAL; 1303e9db1310SAdrian Hunter 1304e9db1310SAdrian Hunter s = strdup(str); 1305e9db1310SAdrian Hunter if (!s) 1306e9db1310SAdrian Hunter return -ENOMEM; 1307e9db1310SAdrian Hunter 1308e9db1310SAdrian Hunter p = strchr(s, ','); 1309e9db1310SAdrian Hunter if (p) 1310e9db1310SAdrian Hunter *p = '\0'; 1311e9db1310SAdrian Hunter 1312e9db1310SAdrian Hunter if (*s) { 1313e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1314e9db1310SAdrian Hunter if (ret) 1315e9db1310SAdrian Hunter goto out_free; 1316e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1317e9db1310SAdrian Hunter } 1318e9db1310SAdrian Hunter 1319e9db1310SAdrian Hunter if (!p) { 1320e9db1310SAdrian Hunter ret = 0; 1321e9db1310SAdrian Hunter goto out_free; 1322e9db1310SAdrian Hunter } 1323e9db1310SAdrian Hunter 1324e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1325e9db1310SAdrian Hunter if (ret) 1326e9db1310SAdrian Hunter goto out_free; 1327e9db1310SAdrian Hunter 1328e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1329e9db1310SAdrian Hunter 1330e9db1310SAdrian Hunter out_free: 1331e9db1310SAdrian Hunter free(s); 1332e9db1310SAdrian Hunter return ret; 1333e9db1310SAdrian Hunter } 1334e9db1310SAdrian Hunter 13350c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 13360c582449SJiri Olsa { 13370c582449SJiri Olsa u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages); 13380c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 13390c582449SJiri Olsa 13400c582449SJiri Olsa wakeup_size /= 2; 13410c582449SJiri Olsa 13420c582449SJiri Olsa if (s->size < wakeup_size) { 13430c582449SJiri Olsa char buf[100]; 13440c582449SJiri Olsa 13450c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 13460c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 13470c582449SJiri Olsa "wakeup kernel buffer size (%s) " 13480c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 13490c582449SJiri Olsa } 13500c582449SJiri Olsa } 13510c582449SJiri Olsa 1352cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 1353cb4e1ebbSJiri Olsa { 1354cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 1355dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 1356dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 1357dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 1358dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 1359dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 1360dc0c6127SJiri Olsa { .tag = 0 }, 1361dc0c6127SJiri Olsa }; 1362bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 1363bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 1364bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 1365bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 1366bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 1367bfacbe3bSJiri Olsa { .tag = 0 }, 1368bfacbe3bSJiri Olsa }; 1369dc0c6127SJiri Olsa unsigned long val; 1370cb4e1ebbSJiri Olsa 1371cb4e1ebbSJiri Olsa if (!s->set) 1372cb4e1ebbSJiri Olsa return 0; 1373cb4e1ebbSJiri Olsa 1374cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 1375cb4e1ebbSJiri Olsa s->signal = true; 1376cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 1377dc0c6127SJiri Olsa goto enabled; 1378dc0c6127SJiri Olsa } 1379dc0c6127SJiri Olsa 1380dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 1381dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 1382dc0c6127SJiri Olsa s->size = val; 1383dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 1384dc0c6127SJiri Olsa goto enabled; 1385cb4e1ebbSJiri Olsa } 1386cb4e1ebbSJiri Olsa 1387bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 1388bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 1389bfacbe3bSJiri Olsa s->time = val; 1390bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 1391bfacbe3bSJiri Olsa s->str, s->time); 1392bfacbe3bSJiri Olsa goto enabled; 1393bfacbe3bSJiri Olsa } 1394bfacbe3bSJiri Olsa 1395cb4e1ebbSJiri Olsa return -1; 1396dc0c6127SJiri Olsa 1397dc0c6127SJiri Olsa enabled: 1398dc0c6127SJiri Olsa rec->timestamp_filename = true; 1399dc0c6127SJiri Olsa s->enabled = true; 14000c582449SJiri Olsa 14010c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 14020c582449SJiri Olsa switch_output_size_warn(rec); 14030c582449SJiri Olsa 1404dc0c6127SJiri Olsa return 0; 1405cb4e1ebbSJiri Olsa } 1406cb4e1ebbSJiri Olsa 1407e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 140886470930SIngo Molnar "perf record [<options>] [<command>]", 140986470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 141086470930SIngo Molnar NULL 141186470930SIngo Molnar }; 1412e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 141386470930SIngo Molnar 1414d20deb64SArnaldo Carvalho de Melo /* 14158c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 14168c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1417d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1418d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1419d20deb64SArnaldo Carvalho de Melo * 1420d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1421d20deb64SArnaldo Carvalho de Melo * 1422d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1423d20deb64SArnaldo Carvalho de Melo */ 14248c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1425d20deb64SArnaldo Carvalho de Melo .opts = { 14268affc2b8SAndi Kleen .sample_time = true, 1427d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1428d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1429d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1430447a6013SArnaldo Carvalho de Melo .freq = 4000, 1431d1cb9fceSNamhyung Kim .target = { 1432d1cb9fceSNamhyung Kim .uses_mmap = true, 14333aa5939dSAdrian Hunter .default_per_cpu = true, 1434d1cb9fceSNamhyung Kim }, 14359d9cad76SKan Liang .proc_map_timeout = 500, 1436d20deb64SArnaldo Carvalho de Melo }, 1437e3d59112SNamhyung Kim .tool = { 1438e3d59112SNamhyung Kim .sample = process_sample_event, 1439e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1440cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1441e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1442f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 1443e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1444e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1445cca8482cSAdrian Hunter .ordered_events = true, 1446e3d59112SNamhyung Kim }, 1447d20deb64SArnaldo Carvalho de Melo }; 14487865e817SFrederic Weisbecker 144976a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 145076a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 145161eaa3beSArnaldo Carvalho de Melo 14520aab2136SWang Nan static bool dry_run; 14530aab2136SWang Nan 1454d20deb64SArnaldo Carvalho de Melo /* 1455d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1456d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1457b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1458d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1459d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1460d20deb64SArnaldo Carvalho de Melo */ 1461efd21307SJiri Olsa static struct option __record_options[] = { 1462d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 146386470930SIngo Molnar "event selector. use 'perf list' to list available events", 1464f120f9d5SJiri Olsa parse_events_option), 1465d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1466c171b552SLi Zefan "event filter", parse_filter), 14674ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 14684ba1faa1SWang Nan NULL, "don't record events from perf itself", 14694ba1faa1SWang Nan exclude_perf), 1470bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1471d6d901c2SZhang, Yanmin "record events on existing process id"), 1472bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1473d6d901c2SZhang, Yanmin "record events on existing thread id"), 1474d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 147586470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1476509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1477acac03faSKirill Smelkov "collect data without buffering"), 1478d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1479daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1480bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 148186470930SIngo Molnar "system-wide collection from all CPUs"), 1482bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1483c45c6ea2SStephane Eranian "list of cpus to monitor"), 1484d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1485*8ceb41d7SJiri Olsa OPT_STRING('o', "output", &record.data.path, "file", 148686470930SIngo Molnar "output file name"), 148769e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 148869e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 14892e6cdf99SStephane Eranian "child tasks do not inherit counters"), 14904ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 14914ea648aeSWang Nan "synthesize non-sample events at the end of output"), 1492626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1493d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1494e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1495e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1496e9db1310SAdrian Hunter record__parse_mmap_pages), 1497d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 149843bece79SLin Ming "put the counters into a counter group"), 14992ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 150009b0fd45SJiri Olsa NULL, "enables call-graph recording" , 150109b0fd45SJiri Olsa &record_callchain_opt), 150209b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 150376a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 150409b0fd45SJiri Olsa &record_parse_callchain_opt), 1505c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 15063da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1507b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1508d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1509649c48a9SPeter Zijlstra "per thread counts"), 151056100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 15113b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 15123b0a5daaSKan Liang "Record the sample physical addresses"), 1513b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 15143abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 15153abebc55SAdrian Hunter &record.opts.sample_time_set, 15163abebc55SAdrian Hunter "Record the sample timestamps"), 151756100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1518d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1519649c48a9SPeter Zijlstra "don't sample"), 1520d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1521d2db9a98SWang Nan &record.no_buildid_cache_set, 1522a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1523d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1524d2db9a98SWang Nan &record.no_buildid_set, 1525baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1526d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1527023695d9SStephane Eranian "monitor event in cgroup name only", 1528023695d9SStephane Eranian parse_cgroups), 1529a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 15306619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1531bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1532bea03405SNamhyung Kim "user to profile"), 1533a5aabdacSStephane Eranian 1534a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1535a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1536a5aabdacSStephane Eranian parse_branch_stack), 1537a5aabdacSStephane Eranian 1538a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1539a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1540bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 154105484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 154205484298SAndi Kleen "sample by weight (on special events only)"), 1543475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1544475eeab9SAndi Kleen "sample transaction flags (special events only)"), 15453aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 15463aa5939dSAdrian Hunter "use per-thread mmaps"), 1547bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1548bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1549bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 155084c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 155184c41742SAndi Kleen "sample selected machine registers on interrupt," 155284c41742SAndi Kleen " use -I ? to list register names", parse_regs), 155385c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 155485c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1555814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1556814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1557814c8c38SPeter Zijlstra parse_clockid), 15582dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 15592dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 15609d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 15619d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1562f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 1563f3b3614aSHari Bathini "Record namespaces events"), 1564b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1565b757bb09SAdrian Hunter "Record context switch events"), 156685723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 156785723885SJiri Olsa "Configure all used events to run in kernel space.", 156885723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 156985723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 157085723885SJiri Olsa "Configure all used events to run in user space.", 157185723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 157271dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 157371dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 157471dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 157571dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 15767efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 15777efe0e03SHe Kuang "file", "vmlinux pathname"), 15786156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 15796156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1580ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1581ecfd7a9cSWang Nan "append timestamp to output filename"), 1582cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 1583bfacbe3bSJiri Olsa &record.switch_output.set, "signal,size,time", 1584bfacbe3bSJiri Olsa "Switch output when receive SIGUSR2 or cross size,time threshold", 1585dc0c6127SJiri Olsa "signal"), 15860aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 15870aab2136SWang Nan "Parse options then exit"), 158886470930SIngo Molnar OPT_END() 158986470930SIngo Molnar }; 159086470930SIngo Molnar 1591e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1592e5b2c207SNamhyung Kim 1593b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 159486470930SIngo Molnar { 1595ef149c25SAdrian Hunter int err; 15968c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 159716ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 159886470930SIngo Molnar 159948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 160048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 160148e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 160248e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 160348e1cab1SWang Nan # undef set_nobuild 160448e1cab1SWang Nan #endif 160548e1cab1SWang Nan 16067efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 16077efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 16087efe0e03SHe Kuang # define REASON "NO_DWARF=1" 16097efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 16107efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 16117efe0e03SHe Kuang # else 16127efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 16137efe0e03SHe Kuang # endif 16147efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 16157efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 16167efe0e03SHe Kuang # undef set_nobuild 16177efe0e03SHe Kuang # undef REASON 16187efe0e03SHe Kuang #endif 16197efe0e03SHe Kuang 16203e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 16213e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1622361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1623361c99a6SArnaldo Carvalho de Melo 1624ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 1625ecc4c561SArnaldo Carvalho de Melo if (err) 1626ecc4c561SArnaldo Carvalho de Melo return err; 1627eb853e80SJiri Olsa 1628bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1629a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 163068ba3235SNamhyung Kim if (quiet) 163168ba3235SNamhyung Kim perf_quiet_option(); 1632483635a9SJiri Olsa 1633483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 1634602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1635483635a9SJiri Olsa rec->opts.target.system_wide = true; 163686470930SIngo Molnar 1637bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1638c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1639c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1640c7118369SNamhyung Kim 1641023695d9SStephane Eranian } 1642b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1643b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1644c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1645c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1646c7118369SNamhyung Kim return -EINVAL; 1647b757bb09SAdrian Hunter } 1648023695d9SStephane Eranian 1649cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 1650cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 1651cb4e1ebbSJiri Olsa return -EINVAL; 1652cb4e1ebbSJiri Olsa } 1653cb4e1ebbSJiri Olsa 1654bfacbe3bSJiri Olsa if (rec->switch_output.time) { 1655bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 1656bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 1657bfacbe3bSJiri Olsa } 1658bfacbe3bSJiri Olsa 1659ef149c25SAdrian Hunter if (!rec->itr) { 1660ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1661ef149c25SAdrian Hunter if (err) 16625c01ad60SAdrian Hunter goto out; 1663ef149c25SAdrian Hunter } 1664ef149c25SAdrian Hunter 16652dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 16662dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 16672dd6d8a1SAdrian Hunter if (err) 16685c01ad60SAdrian Hunter goto out; 16692dd6d8a1SAdrian Hunter 16701b36c03eSAdrian Hunter /* 16711b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 16721b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 16731b36c03eSAdrian Hunter */ 16741b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 16751b36c03eSAdrian Hunter 16761b36c03eSAdrian Hunter symbol__init(NULL); 16771b36c03eSAdrian Hunter 16781b36c03eSAdrian Hunter err = auxtrace_parse_filters(rec->evlist); 16791b36c03eSAdrian Hunter if (err) 16801b36c03eSAdrian Hunter goto out; 16811b36c03eSAdrian Hunter 16820aab2136SWang Nan if (dry_run) 16835c01ad60SAdrian Hunter goto out; 16840aab2136SWang Nan 1685d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 1686d7888573SWang Nan if (err) { 1687d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1688d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 1689d7888573SWang Nan errbuf); 16905c01ad60SAdrian Hunter goto out; 1691d7888573SWang Nan } 1692d7888573SWang Nan 1693ef149c25SAdrian Hunter err = -ENOMEM; 1694ef149c25SAdrian Hunter 1695ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1696646aaea6SArnaldo Carvalho de Melo pr_warning( 1697646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1698ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1699646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1700646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1701646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1702646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1703646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1704ec80fde7SArnaldo Carvalho de Melo 17050c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 1706a1ac1d3cSStephane Eranian disable_buildid_cache(); 1707dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 17080c1d46a8SWang Nan /* 17090c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 17100c1d46a8SWang Nan * generation by default to reduce data file switching 17110c1d46a8SWang Nan * overhead. Still generate buildid if they are required 17120c1d46a8SWang Nan * explicitly using 17130c1d46a8SWang Nan * 171460437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 17150c1d46a8SWang Nan * --no-no-buildid-cache 17160c1d46a8SWang Nan * 17170c1d46a8SWang Nan * Following code equals to: 17180c1d46a8SWang Nan * 17190c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 17200c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 17210c1d46a8SWang Nan * disable_buildid_cache(); 17220c1d46a8SWang Nan */ 17230c1d46a8SWang Nan bool disable = true; 17240c1d46a8SWang Nan 17250c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 17260c1d46a8SWang Nan disable = false; 17270c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 17280c1d46a8SWang Nan disable = false; 17290c1d46a8SWang Nan if (disable) { 17300c1d46a8SWang Nan rec->no_buildid = true; 17310c1d46a8SWang Nan rec->no_buildid_cache = true; 17320c1d46a8SWang Nan disable_buildid_cache(); 17330c1d46a8SWang Nan } 17340c1d46a8SWang Nan } 1735655000e7SArnaldo Carvalho de Melo 17364ea648aeSWang Nan if (record.opts.overwrite) 17374ea648aeSWang Nan record.opts.tail_synthesize = true; 17384ea648aeSWang Nan 17393e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 17404b4cd503SArnaldo Carvalho de Melo __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 174169aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 1742394c01edSAdrian Hunter goto out; 1743bbd36e5eSPeter Zijlstra } 174486470930SIngo Molnar 174569e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 174669e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 174769e7e5b0SAdrian Hunter 1748602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 174916ad2ffbSNamhyung Kim if (err) { 1750602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 175116ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 175216ad2ffbSNamhyung Kim } 17534bd0f2d2SNamhyung Kim 1754602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 175516ad2ffbSNamhyung Kim if (err) { 175616ad2ffbSNamhyung Kim int saved_errno = errno; 175716ad2ffbSNamhyung Kim 1758602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 17593780f488SNamhyung Kim ui__error("%s", errbuf); 176016ad2ffbSNamhyung Kim 176116ad2ffbSNamhyung Kim err = -saved_errno; 1762394c01edSAdrian Hunter goto out; 176316ad2ffbSNamhyung Kim } 17640d37aa34SArnaldo Carvalho de Melo 176523dc4f15SJiri Olsa /* Enable ignoring missing threads when -u option is defined. */ 176623dc4f15SJiri Olsa rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX; 176723dc4f15SJiri Olsa 176816ad2ffbSNamhyung Kim err = -ENOMEM; 17693e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1770dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 177169aad6f1SArnaldo Carvalho de Melo 1772ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1773ef149c25SAdrian Hunter if (err) 1774394c01edSAdrian Hunter goto out; 1775ef149c25SAdrian Hunter 17766156681bSNamhyung Kim /* 17776156681bSNamhyung Kim * We take all buildids when the file contains 17786156681bSNamhyung Kim * AUX area tracing data because we do not decode the 17796156681bSNamhyung Kim * trace because it would take too long. 17806156681bSNamhyung Kim */ 17816156681bSNamhyung Kim if (rec->opts.full_auxtrace) 17826156681bSNamhyung Kim rec->buildid_all = true; 17836156681bSNamhyung Kim 1784b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 178539d17dacSArnaldo Carvalho de Melo err = -EINVAL; 1786394c01edSAdrian Hunter goto out; 17877e4ff9e3SMike Galbraith } 17887e4ff9e3SMike Galbraith 1789d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1790394c01edSAdrian Hunter out: 179145604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1792d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1793ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 179439d17dacSArnaldo Carvalho de Melo return err; 179586470930SIngo Molnar } 17962dd6d8a1SAdrian Hunter 17972dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 17982dd6d8a1SAdrian Hunter { 1799dc0c6127SJiri Olsa struct record *rec = &record; 1800dc0c6127SJiri Olsa 18015f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 18025f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 18032dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 18045f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 18055f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 18065f9cf599SWang Nan } 18073c1cb7e3SWang Nan 1808dc0c6127SJiri Olsa if (switch_output_signal(rec)) 18093c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 18102dd6d8a1SAdrian Hunter } 1811bfacbe3bSJiri Olsa 1812bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 1813bfacbe3bSJiri Olsa { 1814bfacbe3bSJiri Olsa struct record *rec = &record; 1815bfacbe3bSJiri Olsa 1816bfacbe3bSJiri Olsa if (switch_output_time(rec)) 1817bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 1818bfacbe3bSJiri Olsa } 1819