Commit 09b0fd45 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

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: default avatarJiri Olsa <jolsa@redhat.com>
Tested-by: default avatarDavid Ahern <dsahern@gmail.com>
Tested-by: default avatarIngo Molnar <mingo@kernel.org>
Reviewed-by: default avatarDavid Ahern <dsahern@gmail.com>
Acked-by: default avatarIngo 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 9754c4f9
...@@ -90,8 +90,20 @@ OPTIONS ...@@ -90,8 +90,20 @@ OPTIONS
Number of mmap data pages. Must be a power of two. Number of mmap data pages. Must be a power of two.
-g:: -g::
Enables call-graph (stack chain/backtrace) recording.
--call-graph:: --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:: -q::
--quiet:: --quiet::
......
...@@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size) ...@@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size)
} }
#endif /* LIBUNWIND_SUPPORT */ #endif /* LIBUNWIND_SUPPORT */
int record_parse_callchain_opt(const struct option *opt, int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
const char *arg, int unset)
{ {
struct perf_record_opts *opts = opt->value;
char *tok, *name, *saveptr = NULL; char *tok, *name, *saveptr = NULL;
char *buf; char *buf;
int ret = -1; 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. */ /* We need buffer that we know we can write to. */
buf = malloc(strlen(arg) + 1); buf = malloc(strlen(arg) + 1);
if (!buf) if (!buf)
...@@ -764,13 +755,9 @@ int record_parse_callchain_opt(const struct option *opt, ...@@ -764,13 +755,9 @@ int record_parse_callchain_opt(const struct option *opt,
ret = get_stack_size(tok, &size); ret = get_stack_size(tok, &size);
opts->stack_dump_size = size; opts->stack_dump_size = size;
} }
if (!ret)
pr_debug("callchain: stack dump size %d\n",
opts->stack_dump_size);
#endif /* LIBUNWIND_SUPPORT */ #endif /* LIBUNWIND_SUPPORT */
} else { } else {
pr_err("callchain: Unknown -g option " pr_err("callchain: Unknown --call-graph option "
"value: %s\n", arg); "value: %s\n", arg);
break; break;
} }
...@@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt, ...@@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt,
} while (0); } while (0);
free(buf); 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) if (!ret)
pr_debug("callchain: type %d\n", opts->call_graph); callchain_debug(opts);
return ret; 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[] = { static const char * const record_usage[] = {
"perf record [<options>] [<command>]", "perf record [<options>] [<command>]",
"perf record [<options>] -- <command> [<options>]", "perf record [<options>] -- <command> [<options>]",
...@@ -813,12 +839,12 @@ static struct perf_record record = { ...@@ -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 #ifdef LIBUNWIND_SUPPORT
const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
#else #else
const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; const char record_callchain_help[] = CALLCHAIN_HELP "fp";
#endif #endif
/* /*
...@@ -858,9 +884,12 @@ const struct option record_options[] = { ...@@ -858,9 +884,12 @@ const struct option record_options[] = {
"number of mmap data pages"), "number of mmap data pages"),
OPT_BOOLEAN(0, "group", &record.opts.group, OPT_BOOLEAN(0, "group", &record.opts.group,
"put the counters into a counter group"), "put the counters into a counter group"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
"mode[,dump_size]", record_callchain_help, NULL, "enables call-graph recording" ,
&record_parse_callchain_opt, "fp"), &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, OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"), "be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
......
...@@ -147,6 +147,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor) ...@@ -147,6 +147,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
struct option; 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_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[]; extern const char record_callchain_help[];
#endif /* __PERF_CALLCHAIN_H */ #endif /* __PERF_CALLCHAIN_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment