aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c197
1 files changed, 124 insertions, 73 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 319712a4e02b..515510ecc76a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -32,6 +32,8 @@
32#include "util/parse-branch-options.h" 32#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h" 33#include "util/parse-regs-options.h"
34#include "util/llvm-utils.h" 34#include "util/llvm-utils.h"
35#include "util/bpf-loader.h"
36#include "asm/bug.h"
35 37
36#include <unistd.h> 38#include <unistd.h>
37#include <sched.h> 39#include <sched.h>
@@ -49,7 +51,9 @@ struct record {
49 const char *progname; 51 const char *progname;
50 int realtime_prio; 52 int realtime_prio;
51 bool no_buildid; 53 bool no_buildid;
54 bool no_buildid_set;
52 bool no_buildid_cache; 55 bool no_buildid_cache;
56 bool no_buildid_cache_set;
53 bool buildid_all; 57 bool buildid_all;
54 unsigned long long samples; 58 unsigned long long samples;
55}; 59};
@@ -320,7 +324,10 @@ try_again:
320 } else { 324 } else {
321 pr_err("failed to mmap with %d (%s)\n", errno, 325 pr_err("failed to mmap with %d (%s)\n", errno,
322 strerror_r(errno, msg, sizeof(msg))); 326 strerror_r(errno, msg, sizeof(msg)));
323 rc = -errno; 327 if (errno)
328 rc = -errno;
329 else
330 rc = -EINVAL;
324 } 331 }
325 goto out; 332 goto out;
326 } 333 }
@@ -464,6 +471,29 @@ static void record__init_features(struct record *rec)
464 perf_header__clear_feat(&session->header, HEADER_STAT); 471 perf_header__clear_feat(&session->header, HEADER_STAT);
465} 472}
466 473
474static void
475record__finish_output(struct record *rec)
476{
477 struct perf_data_file *file = &rec->file;
478 int fd = perf_data_file__fd(file);
479
480 if (file->is_pipe)
481 return;
482
483 rec->session->header.data_size += rec->bytes_written;
484 file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
485
486 if (!rec->no_buildid) {
487 process_buildids(rec);
488
489 if (rec->buildid_all)
490 dsos__hit_all(rec->session);
491 }
492 perf_session__write_header(rec->session, rec->evlist, fd, true);
493
494 return;
495}
496
467static volatile int workload_exec_errno; 497static volatile int workload_exec_errno;
468 498
469/* 499/*
@@ -482,6 +512,74 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
482 512
483static void snapshot_sig_handler(int sig); 513static void snapshot_sig_handler(int sig);
484 514
515static int record__synthesize(struct record *rec)
516{
517 struct perf_session *session = rec->session;
518 struct machine *machine = &session->machines.host;
519 struct perf_data_file *file = &rec->file;
520 struct record_opts *opts = &rec->opts;
521 struct perf_tool *tool = &rec->tool;
522 int fd = perf_data_file__fd(file);
523 int err = 0;
524
525 if (file->is_pipe) {
526 err = perf_event__synthesize_attrs(tool, session,
527 process_synthesized_event);
528 if (err < 0) {
529 pr_err("Couldn't synthesize attrs.\n");
530 goto out;
531 }
532
533 if (have_tracepoints(&rec->evlist->entries)) {
534 /*
535 * FIXME err <= 0 here actually means that
536 * there were no tracepoints so its not really
537 * an error, just that we don't need to
538 * synthesize anything. We really have to
539 * return this more properly and also
540 * propagate errors that now are calling die()
541 */
542 err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
543 process_synthesized_event);
544 if (err <= 0) {
545 pr_err("Couldn't record tracing data.\n");
546 goto out;
547 }
548 rec->bytes_written += err;
549 }
550 }
551
552 if (rec->opts.full_auxtrace) {
553 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
554 session, process_synthesized_event);
555 if (err)
556 goto out;
557 }
558
559 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
560 machine);
561 WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
562 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
563 "Check /proc/kallsyms permission or run as root.\n");
564
565 err = perf_event__synthesize_modules(tool, process_synthesized_event,
566 machine);
567 WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
568 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
569 "Check /proc/modules permission or run as root.\n");
570
571 if (perf_guest) {
572 machines__process_guests(&session->machines,
573 perf_event__synthesize_guest_os, tool);
574 }
575
576 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
577 process_synthesized_event, opts->sample_address,
578 opts->proc_map_timeout);
579out:
580 return err;
581}
582
485static int __cmd_record(struct record *rec, int argc, const char **argv) 583static int __cmd_record(struct record *rec, int argc, const char **argv)
486{ 584{
487 int err; 585 int err;
@@ -534,6 +632,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
534 goto out_child; 632 goto out_child;
535 } 633 }
536 634
635 err = bpf__apply_obj_config();
636 if (err) {
637 char errbuf[BUFSIZ];
638
639 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
640 pr_err("ERROR: Apply config to BPF failed: %s\n",
641 errbuf);
642 goto out_child;
643 }
644
537 /* 645 /*
538 * Normally perf_session__new would do this, but it doesn't have the 646 * Normally perf_session__new would do this, but it doesn't have the
539 * evlist. 647 * evlist.
@@ -566,63 +674,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
566 674
567 machine = &session->machines.host; 675 machine = &session->machines.host;
568 676
569 if (file->is_pipe) { 677 err = record__synthesize(rec);
570 err = perf_event__synthesize_attrs(tool, session,
571 process_synthesized_event);
572 if (err < 0) {
573 pr_err("Couldn't synthesize attrs.\n");
574 goto out_child;
575 }
576
577 if (have_tracepoints(&rec->evlist->entries)) {
578 /*
579 * FIXME err <= 0 here actually means that
580 * there were no tracepoints so its not really
581 * an error, just that we don't need to
582 * synthesize anything. We really have to
583 * return this more properly and also
584 * propagate errors that now are calling die()
585 */
586 err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
587 process_synthesized_event);
588 if (err <= 0) {
589 pr_err("Couldn't record tracing data.\n");
590 goto out_child;
591 }
592 rec->bytes_written += err;
593 }
594 }
595
596 if (rec->opts.full_auxtrace) {
597 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
598 session, process_synthesized_event);
599 if (err)
600 goto out_delete_session;
601 }
602
603 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
604 machine);
605 if (err < 0)
606 pr_err("Couldn't record kernel reference relocation symbol\n"
607 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
608 "Check /proc/kallsyms permission or run as root.\n");
609
610 err = perf_event__synthesize_modules(tool, process_synthesized_event,
611 machine);
612 if (err < 0) 678 if (err < 0)
613 pr_err("Couldn't record kernel module information.\n"
614 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
615 "Check /proc/modules permission or run as root.\n");
616
617 if (perf_guest) {
618 machines__process_guests(&session->machines,
619 perf_event__synthesize_guest_os, tool);
620 }
621
622 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
623 process_synthesized_event, opts->sample_address,
624 opts->proc_map_timeout);
625 if (err != 0)
626 goto out_child; 679 goto out_child;
627 680
628 if (rec->realtime_prio) { 681 if (rec->realtime_prio) {
@@ -758,18 +811,8 @@ out_child:
758 /* this will be recalculated during process_buildids() */ 811 /* this will be recalculated during process_buildids() */
759 rec->samples = 0; 812 rec->samples = 0;
760 813
761 if (!err && !file->is_pipe) { 814 if (!err)
762 rec->session->header.data_size += rec->bytes_written; 815 record__finish_output(rec);
763 file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
764
765 if (!rec->no_buildid) {
766 process_buildids(rec);
767
768 if (rec->buildid_all)
769 dsos__hit_all(rec->session);
770 }
771 perf_session__write_header(rec->session, rec->evlist, fd, true);
772 }
773 816
774 if (!err && !quiet) { 817 if (!err && !quiet) {
775 char samples[128]; 818 char samples[128];
@@ -1097,10 +1140,12 @@ struct option __record_options[] = {
1097 OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1140 OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
1098 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1141 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1099 "don't sample"), 1142 "don't sample"),
1100 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1143 OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1101 "do not update the buildid cache"), 1144 &record.no_buildid_cache_set,
1102 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1145 "do not update the buildid cache"),
1103 "do not collect buildids in perf.data"), 1146 OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1147 &record.no_buildid_set,
1148 "do not collect buildids in perf.data"),
1104 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1149 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1105 "monitor event in cgroup name only", 1150 "monitor event in cgroup name only",
1106 parse_cgroups), 1151 parse_cgroups),
@@ -1136,6 +1181,12 @@ struct option __record_options[] = {
1136 "per thread proc mmap processing timeout in ms"), 1181 "per thread proc mmap processing timeout in ms"),
1137 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1182 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1138 "Record context switch events"), 1183 "Record context switch events"),
1184 OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
1185 "Configure all used events to run in kernel space.",
1186 PARSE_OPT_EXCLUSIVE),
1187 OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
1188 "Configure all used events to run in user space.",
1189 PARSE_OPT_EXCLUSIVE),
1139 OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 1190 OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
1140 "clang binary to use for compiling BPF scriptlets"), 1191 "clang binary to use for compiling BPF scriptlets"),
1141 OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 1192 OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",