diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a41ac41546c9..d04651484640 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size) | |||
712 | } | 712 | } |
713 | #endif /* LIBUNWIND_SUPPORT */ | 713 | #endif /* LIBUNWIND_SUPPORT */ |
714 | 714 | ||
715 | int record_parse_callchain_opt(const struct option *opt, | 715 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts) |
716 | const char *arg, int unset) | ||
717 | { | 716 | { |
718 | struct perf_record_opts *opts = opt->value; | ||
719 | char *tok, *name, *saveptr = NULL; | 717 | char *tok, *name, *saveptr = NULL; |
720 | char *buf; | 718 | char *buf; |
721 | int ret = -1; | 719 | int ret = -1; |
722 | 720 | ||
723 | /* --no-call-graph */ | ||
724 | if (unset) | ||
725 | return 0; | ||
726 | |||
727 | /* We specified default option if none is provided. */ | ||
728 | BUG_ON(!arg); | ||
729 | |||
730 | /* We need buffer that we know we can write to. */ | 721 | /* We need buffer that we know we can write to. */ |
731 | buf = malloc(strlen(arg) + 1); | 722 | buf = malloc(strlen(arg) + 1); |
732 | if (!buf) | 723 | if (!buf) |
@@ -764,13 +755,9 @@ int record_parse_callchain_opt(const struct option *opt, | |||
764 | ret = get_stack_size(tok, &size); | 755 | ret = get_stack_size(tok, &size); |
765 | opts->stack_dump_size = size; | 756 | opts->stack_dump_size = size; |
766 | } | 757 | } |
767 | |||
768 | if (!ret) | ||
769 | pr_debug("callchain: stack dump size %d\n", | ||
770 | opts->stack_dump_size); | ||
771 | #endif /* LIBUNWIND_SUPPORT */ | 758 | #endif /* LIBUNWIND_SUPPORT */ |
772 | } else { | 759 | } else { |
773 | pr_err("callchain: Unknown -g option " | 760 | pr_err("callchain: Unknown --call-graph option " |
774 | "value: %s\n", arg); | 761 | "value: %s\n", arg); |
775 | break; | 762 | break; |
776 | } | 763 | } |
@@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt, | |||
778 | } while (0); | 765 | } while (0); |
779 | 766 | ||
780 | free(buf); | 767 | free(buf); |
768 | return ret; | ||
769 | } | ||
770 | |||
771 | static void callchain_debug(struct perf_record_opts *opts) | ||
772 | { | ||
773 | pr_debug("callchain: type %d\n", opts->call_graph); | ||
781 | 774 | ||
775 | if (opts->call_graph == CALLCHAIN_DWARF) | ||
776 | pr_debug("callchain: stack dump size %d\n", | ||
777 | opts->stack_dump_size); | ||
778 | } | ||
779 | |||
780 | int record_parse_callchain_opt(const struct option *opt, | ||
781 | const char *arg, | ||
782 | int unset) | ||
783 | { | ||
784 | struct perf_record_opts *opts = opt->value; | ||
785 | int ret; | ||
786 | |||
787 | /* --no-call-graph */ | ||
788 | if (unset) { | ||
789 | opts->call_graph = CALLCHAIN_NONE; | ||
790 | pr_debug("callchain: disabled\n"); | ||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | ret = record_parse_callchain(arg, opts); | ||
782 | if (!ret) | 795 | if (!ret) |
783 | pr_debug("callchain: type %d\n", opts->call_graph); | 796 | callchain_debug(opts); |
784 | 797 | ||
785 | return ret; | 798 | return ret; |
786 | } | 799 | } |
787 | 800 | ||
801 | int record_callchain_opt(const struct option *opt, | ||
802 | const char *arg __maybe_unused, | ||
803 | int unset __maybe_unused) | ||
804 | { | ||
805 | struct perf_record_opts *opts = opt->value; | ||
806 | |||
807 | if (opts->call_graph == CALLCHAIN_NONE) | ||
808 | opts->call_graph = CALLCHAIN_FP; | ||
809 | |||
810 | callchain_debug(opts); | ||
811 | return 0; | ||
812 | } | ||
813 | |||
788 | static const char * const record_usage[] = { | 814 | static const char * const record_usage[] = { |
789 | "perf record [<options>] [<command>]", | 815 | "perf record [<options>] [<command>]", |
790 | "perf record [<options>] -- <command> [<options>]", | 816 | "perf record [<options>] -- <command> [<options>]", |
@@ -813,12 +839,12 @@ static struct perf_record record = { | |||
813 | }, | 839 | }, |
814 | }; | 840 | }; |
815 | 841 | ||
816 | #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " | 842 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " |
817 | 843 | ||
818 | #ifdef LIBUNWIND_SUPPORT | 844 | #ifdef LIBUNWIND_SUPPORT |
819 | const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; | 845 | const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; |
820 | #else | 846 | #else |
821 | const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; | 847 | const char record_callchain_help[] = CALLCHAIN_HELP "fp"; |
822 | #endif | 848 | #endif |
823 | 849 | ||
824 | /* | 850 | /* |
@@ -858,9 +884,12 @@ const struct option record_options[] = { | |||
858 | "number of mmap data pages"), | 884 | "number of mmap data pages"), |
859 | OPT_BOOLEAN(0, "group", &record.opts.group, | 885 | OPT_BOOLEAN(0, "group", &record.opts.group, |
860 | "put the counters into a counter group"), | 886 | "put the counters into a counter group"), |
861 | OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, | 887 | OPT_CALLBACK_NOOPT('g', NULL, &record.opts, |
862 | "mode[,dump_size]", record_callchain_help, | 888 | NULL, "enables call-graph recording" , |
863 | &record_parse_callchain_opt, "fp"), | 889 | &record_callchain_opt), |
890 | OPT_CALLBACK(0, "call-graph", &record.opts, | ||
891 | "mode[,dump_size]", record_callchain_help, | ||
892 | &record_parse_callchain_opt), | ||
864 | OPT_INCR('v', "verbose", &verbose, | 893 | OPT_INCR('v', "verbose", &verbose, |
865 | "be more verbose (show counter open errors, etc)"), | 894 | "be more verbose (show counter open errors, etc)"), |
866 | OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), | 895 | OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), |