perf record: Split -g and --call-graph
Splitting -g and --call-graph for record command, so we could use '-g' with no option. The '-g' option now takes NO argument and enables the configured unwind method, which is currently the frame pointers method. It will be possible to configure unwind method via config file in upcoming patches. All current '-g' arguments is overtaken by --call-graph option. Signed-off-by: Jiri Olsa <jolsa@redhat.com> Tested-by: David Ahern <dsahern@gmail.com> Tested-by: Ingo Molnar <mingo@kernel.org> Reviewed-by: David Ahern <dsahern@gmail.com> Acked-by: Ingo Molnar <mingo@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1382797536-32303-2-git-send-email-jolsa@redhat.com [ reordered -g/--call-graph on --help and expanded the man page according to comments by David Ahern and Namhyung Kim ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
9754c4f9b2
Коммит
09b0fd45ff
|
@ -90,8 +90,20 @@ OPTIONS
|
|||
Number of mmap data pages. Must be a power of two.
|
||||
|
||||
-g::
|
||||
Enables call-graph (stack chain/backtrace) recording.
|
||||
|
||||
--call-graph::
|
||||
Do call-graph (stack chain/backtrace) recording.
|
||||
Setup and enable call-graph (stack chain/backtrace) recording,
|
||||
implies -g.
|
||||
|
||||
Allows specifying "fp" (frame pointer) or "dwarf"
|
||||
(DWARF's CFI - Call Frame Information) as the method to collect
|
||||
the information used to show the call graphs.
|
||||
|
||||
In some systems, where binaries are build with gcc
|
||||
--fomit-frame-pointer, using the "fp" method will produce bogus
|
||||
call graphs, using "dwarf", if available (perf tools linked to
|
||||
the libunwind library) should be used instead.
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
|
|
|
@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size)
|
|||
}
|
||||
#endif /* LIBUNWIND_SUPPORT */
|
||||
|
||||
int record_parse_callchain_opt(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
|
||||
{
|
||||
struct perf_record_opts *opts = opt->value;
|
||||
char *tok, *name, *saveptr = NULL;
|
||||
char *buf;
|
||||
int ret = -1;
|
||||
|
||||
/* --no-call-graph */
|
||||
if (unset)
|
||||
return 0;
|
||||
|
||||
/* We specified default option if none is provided. */
|
||||
BUG_ON(!arg);
|
||||
|
||||
/* We need buffer that we know we can write to. */
|
||||
buf = malloc(strlen(arg) + 1);
|
||||
if (!buf)
|
||||
|
@ -764,13 +755,9 @@ int record_parse_callchain_opt(const struct option *opt,
|
|||
ret = get_stack_size(tok, &size);
|
||||
opts->stack_dump_size = size;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
pr_debug("callchain: stack dump size %d\n",
|
||||
opts->stack_dump_size);
|
||||
#endif /* LIBUNWIND_SUPPORT */
|
||||
} else {
|
||||
pr_err("callchain: Unknown -g option "
|
||||
pr_err("callchain: Unknown --call-graph option "
|
||||
"value: %s\n", arg);
|
||||
break;
|
||||
}
|
||||
|
@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt,
|
|||
} while (0);
|
||||
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void callchain_debug(struct perf_record_opts *opts)
|
||||
{
|
||||
pr_debug("callchain: type %d\n", opts->call_graph);
|
||||
|
||||
if (opts->call_graph == CALLCHAIN_DWARF)
|
||||
pr_debug("callchain: stack dump size %d\n",
|
||||
opts->stack_dump_size);
|
||||
}
|
||||
|
||||
int record_parse_callchain_opt(const struct option *opt,
|
||||
const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct perf_record_opts *opts = opt->value;
|
||||
int ret;
|
||||
|
||||
/* --no-call-graph */
|
||||
if (unset) {
|
||||
opts->call_graph = CALLCHAIN_NONE;
|
||||
pr_debug("callchain: disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = record_parse_callchain(arg, opts);
|
||||
if (!ret)
|
||||
pr_debug("callchain: type %d\n", opts->call_graph);
|
||||
callchain_debug(opts);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int record_callchain_opt(const struct option *opt,
|
||||
const char *arg __maybe_unused,
|
||||
int unset __maybe_unused)
|
||||
{
|
||||
struct perf_record_opts *opts = opt->value;
|
||||
|
||||
if (opts->call_graph == CALLCHAIN_NONE)
|
||||
opts->call_graph = CALLCHAIN_FP;
|
||||
|
||||
callchain_debug(opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const record_usage[] = {
|
||||
"perf record [<options>] [<command>]",
|
||||
"perf record [<options>] -- <command> [<options>]",
|
||||
|
@ -813,12 +839,12 @@ static struct perf_record record = {
|
|||
},
|
||||
};
|
||||
|
||||
#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
|
||||
#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
|
||||
|
||||
#ifdef LIBUNWIND_SUPPORT
|
||||
const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
|
||||
const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
|
||||
#else
|
||||
const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
|
||||
const char record_callchain_help[] = CALLCHAIN_HELP "fp";
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -858,9 +884,12 @@ const struct option record_options[] = {
|
|||
"number of mmap data pages"),
|
||||
OPT_BOOLEAN(0, "group", &record.opts.group,
|
||||
"put the counters into a counter group"),
|
||||
OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
|
||||
"mode[,dump_size]", record_callchain_help,
|
||||
&record_parse_callchain_opt, "fp"),
|
||||
OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
|
||||
NULL, "enables call-graph recording" ,
|
||||
&record_callchain_opt),
|
||||
OPT_CALLBACK(0, "call-graph", &record.opts,
|
||||
"mode[,dump_size]", record_callchain_help,
|
||||
&record_parse_callchain_opt),
|
||||
OPT_INCR('v', "verbose", &verbose,
|
||||
"be more verbose (show counter open errors, etc)"),
|
||||
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
|
||||
|
|
|
@ -147,6 +147,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
|
|||
|
||||
struct option;
|
||||
|
||||
int record_parse_callchain(const char *arg, struct perf_record_opts *opts);
|
||||
int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
|
||||
int record_callchain_opt(const struct option *opt, const char *arg, int unset);
|
||||
|
||||
extern const char record_callchain_help[];
|
||||
#endif /* __PERF_CALLCHAIN_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче