perf probe: Show accessible local variables
Add -V (--vars) option for listing accessible local variables at given probe point. This will help finding which local variables are available for event arguments. e.g.) # perf probe -V call_timer_fn:23 Available variables at call_timer_fn:23 @<run_timer_softirq+345> function_type* fn int preempt_count long unsigned int data struct list_head work_list struct list_head* head struct timer_list* timer struct tvec_base* base Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20101021101323.3542.40282.stgit@ltc236.sdl.hitachi.co.jp> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
632941c4f8
commit
cf6eb489e5
@@ -50,6 +50,8 @@ static struct {
|
||||
bool list_events;
|
||||
bool force_add;
|
||||
bool show_lines;
|
||||
bool show_vars;
|
||||
bool mod_events;
|
||||
int nevents;
|
||||
struct perf_probe_event events[MAX_PROBES];
|
||||
struct strlist *dellist;
|
||||
@@ -57,7 +59,6 @@ static struct {
|
||||
int max_probe_points;
|
||||
} params;
|
||||
|
||||
|
||||
/* Parse an event definition. Note that any error must die. */
|
||||
static int parse_probe_event(const char *str)
|
||||
{
|
||||
@@ -92,6 +93,7 @@ static int parse_probe_event_argv(int argc, const char **argv)
|
||||
len = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
len += sprintf(&buf[len], "%s ", argv[i]);
|
||||
params.mod_events = true;
|
||||
ret = parse_probe_event(buf);
|
||||
free(buf);
|
||||
return ret;
|
||||
@@ -100,9 +102,10 @@ static int parse_probe_event_argv(int argc, const char **argv)
|
||||
static int opt_add_probe_event(const struct option *opt __used,
|
||||
const char *str, int unset __used)
|
||||
{
|
||||
if (str)
|
||||
if (str) {
|
||||
params.mod_events = true;
|
||||
return parse_probe_event(str);
|
||||
else
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,6 +113,7 @@ static int opt_del_probe_event(const struct option *opt __used,
|
||||
const char *str, int unset __used)
|
||||
{
|
||||
if (str) {
|
||||
params.mod_events = true;
|
||||
if (!params.dellist)
|
||||
params.dellist = strlist__new(true, NULL);
|
||||
strlist__add(params.dellist, str);
|
||||
@@ -130,6 +134,25 @@ static int opt_show_lines(const struct option *opt __used,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int opt_show_vars(const struct option *opt __used,
|
||||
const char *str, int unset __used)
|
||||
{
|
||||
struct perf_probe_event *pev = ¶ms.events[params.nevents];
|
||||
int ret;
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
ret = parse_probe_event(str);
|
||||
if (!ret && pev->nargs != 0) {
|
||||
pr_err(" Error: '--vars' doesn't accept arguments.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
params.show_vars = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char * const probe_usage[] = {
|
||||
@@ -139,6 +162,7 @@ static const char * const probe_usage[] = {
|
||||
"perf probe --list",
|
||||
#ifdef DWARF_SUPPORT
|
||||
"perf probe --line 'LINEDESC'",
|
||||
"perf probe --vars 'PROBEPOINT'",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -180,6 +204,9 @@ static const struct option options[] = {
|
||||
OPT_CALLBACK('L', "line", NULL,
|
||||
"FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
|
||||
"Show source code lines.", opt_show_lines),
|
||||
OPT_CALLBACK('V', "vars", NULL,
|
||||
"FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
|
||||
"Show accessible variables on PROBEDEF", opt_show_vars),
|
||||
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
||||
"file", "vmlinux pathname"),
|
||||
OPT_STRING('s', "source", &symbol_conf.source_prefix,
|
||||
@@ -217,7 +244,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
usage_with_options(probe_usage, options);
|
||||
|
||||
if (params.list_events) {
|
||||
if (params.nevents != 0 || params.dellist) {
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --list with --add/--del.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
@@ -225,6 +252,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
pr_err(" Error: Don't use --list with --line.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
if (params.show_vars) {
|
||||
pr_err(" Error: Don't use --list with --vars.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
ret = show_perf_probe_events();
|
||||
if (ret < 0)
|
||||
pr_err(" Error: Failed to show event list. (%d)\n",
|
||||
@@ -234,9 +265,13 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
|
||||
#ifdef DWARF_SUPPORT
|
||||
if (params.show_lines) {
|
||||
if (params.nevents != 0 || params.dellist) {
|
||||
pr_warning(" Error: Don't use --line with"
|
||||
" --add/--del.\n");
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --line with"
|
||||
" --add/--del.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
if (params.show_vars) {
|
||||
pr_err(" Error: Don't use --line with --vars.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
|
||||
@@ -245,6 +280,18 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
pr_err(" Error: Failed to show lines. (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (params.show_vars) {
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --vars with"
|
||||
" --add/--del.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
ret = show_available_vars(params.events, params.nevents,
|
||||
params.max_probe_points);
|
||||
if (ret < 0)
|
||||
pr_err(" Error: Failed to show vars. (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (params.dellist) {
|
||||
|
Reference in New Issue
Block a user