perf probe: Show accessible global variables

Add --externs for allowing --vars to show accessible global (externally
defined) variables from a given probe point too.

This will give you a hint which globals can be accessible from the probe point.

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: <20101021101335.3542.31003.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:
Masami Hiramatsu 2010-10-21 19:13:35 +09:00 committed by Arnaldo Carvalho de Melo
parent c82ec0a2bd
commit fb8c5a56c7
6 changed files with 41 additions and 14 deletions

View file

@ -18,7 +18,7 @@ or
or or
'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]' 'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
or or
'perf probe' --vars='PROBEPOINT' 'perf probe' [--externs] --vars='PROBEPOINT'
DESCRIPTION DESCRIPTION
----------- -----------
@ -64,6 +64,10 @@ OPTIONS
Show available local variables at given probe point. The argument Show available local variables at given probe point. The argument
syntax is same as PROBE SYNTAX, but NO ARGs. syntax is same as PROBE SYNTAX, but NO ARGs.
--externs::
(Only for --vars) Show external defined variables in addition to local
variables.
-f:: -f::
--force:: --force::
Forcibly add events with existing name. Forcibly add events with existing name.

View file

@ -51,6 +51,7 @@ static struct {
bool force_add; bool force_add;
bool show_lines; bool show_lines;
bool show_vars; bool show_vars;
bool show_ext_vars;
bool mod_events; bool mod_events;
int nevents; int nevents;
struct perf_probe_event events[MAX_PROBES]; struct perf_probe_event events[MAX_PROBES];
@ -162,7 +163,7 @@ static const char * const probe_usage[] = {
"perf probe --list", "perf probe --list",
#ifdef DWARF_SUPPORT #ifdef DWARF_SUPPORT
"perf probe --line 'LINEDESC'", "perf probe --line 'LINEDESC'",
"perf probe --vars 'PROBEPOINT'", "perf probe [--externs] --vars 'PROBEPOINT'",
#endif #endif
NULL NULL
}; };
@ -207,6 +208,8 @@ static const struct option options[] = {
OPT_CALLBACK('V', "vars", NULL, OPT_CALLBACK('V', "vars", NULL,
"FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
"Show accessible variables on PROBEDEF", opt_show_vars), "Show accessible variables on PROBEDEF", opt_show_vars),
OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
"Show external variables too (with --vars only)"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"), "file", "vmlinux pathname"),
OPT_STRING('s', "source", &symbol_conf.source_prefix, OPT_STRING('s', "source", &symbol_conf.source_prefix,
@ -287,7 +290,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
usage_with_options(probe_usage, options); usage_with_options(probe_usage, options);
} }
ret = show_available_vars(params.events, params.nevents, ret = show_available_vars(params.events, params.nevents,
params.max_probe_points); params.max_probe_points,
params.show_ext_vars);
if (ret < 0) if (ret < 0)
pr_err(" Error: Failed to show vars. (%d)\n", ret); pr_err(" Error: Failed to show vars. (%d)\n", ret);
return ret; return ret;

View file

@ -379,7 +379,7 @@ end:
} }
static int show_available_vars_at(int fd, struct perf_probe_event *pev, static int show_available_vars_at(int fd, struct perf_probe_event *pev,
int max_vls) int max_vls, bool externs)
{ {
char *buf; char *buf;
int ret, i; int ret, i;
@ -391,7 +391,7 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
return -EINVAL; return -EINVAL;
pr_debug("Searching variables at %s\n", buf); pr_debug("Searching variables at %s\n", buf);
ret = find_available_vars_at(fd, pev, &vls, max_vls); ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
if (ret > 0) { if (ret > 0) {
/* Some variables were found */ /* Some variables were found */
fprintf(stdout, "Available variables at %s\n", buf); fprintf(stdout, "Available variables at %s\n", buf);
@ -421,7 +421,7 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
/* Show available variables on given probe point */ /* Show available variables on given probe point */
int show_available_vars(struct perf_probe_event *pevs, int npevs, int show_available_vars(struct perf_probe_event *pevs, int npevs,
int max_vls) int max_vls, bool externs)
{ {
int i, fd, ret = 0; int i, fd, ret = 0;
@ -438,7 +438,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
setup_pager(); setup_pager();
for (i = 0; i < npevs && ret >= 0; i++) for (i = 0; i < npevs && ret >= 0; i++)
ret = show_available_vars_at(fd, &pevs[i], max_vls); ret = show_available_vars_at(fd, &pevs[i], max_vls, externs);
close(fd); close(fd);
return ret; return ret;

View file

@ -122,7 +122,7 @@ extern int del_perf_probe_events(struct strlist *dellist);
extern int show_perf_probe_events(void); extern int show_perf_probe_events(void);
extern int show_line_range(struct line_range *lr); extern int show_line_range(struct line_range *lr);
extern int show_available_vars(struct perf_probe_event *pevs, int npevs, extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
int max_probe_points); int max_probe_points, bool externs);
/* Maximum index number of event-name postfix */ /* Maximum index number of event-name postfix */

View file

@ -1312,12 +1312,13 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
af->pf.fb_ops, NULL); af->pf.fb_ops, NULL);
if (ret == 0) { if (ret == 0) {
ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
pr_debug2("Add new var: %s\n", buf);
if (ret > 0) if (ret > 0)
strlist__add(vl->vars, buf); strlist__add(vl->vars, buf);
} }
} }
if (dwarf_haspc(die_mem, af->pf.addr)) if (af->child && dwarf_haspc(die_mem, af->pf.addr))
return DIE_FIND_CB_CONTINUE; return DIE_FIND_CB_CONTINUE;
else else
return DIE_FIND_CB_SIBLING; return DIE_FIND_CB_SIBLING;
@ -1329,8 +1330,8 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
struct available_var_finder *af = struct available_var_finder *af =
container_of(pf, struct available_var_finder, pf); container_of(pf, struct available_var_finder, pf);
struct variable_list *vl; struct variable_list *vl;
Dwarf_Die die_mem; Dwarf_Die die_mem, *scopes = NULL;
int ret; int ret, nscopes;
/* Check number of tevs */ /* Check number of tevs */
if (af->nvls == af->max_vls) { if (af->nvls == af->max_vls) {
@ -1351,8 +1352,22 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
vl->vars = strlist__new(true, NULL); vl->vars = strlist__new(true, NULL);
if (vl->vars == NULL) if (vl->vars == NULL)
return -ENOMEM; return -ENOMEM;
af->child = true;
die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem); die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
/* Find external variables */
if (!af->externs)
goto out;
/* Don't need to search child DIE for externs. */
af->child = false;
nscopes = dwarf_getscopes_die(sp_die, &scopes);
while (nscopes-- > 1)
die_find_child(&scopes[nscopes], collect_variables_cb,
(void *)af, &die_mem);
if (scopes)
free(scopes);
out:
if (strlist__empty(vl->vars)) { if (strlist__empty(vl->vars)) {
strlist__delete(vl->vars); strlist__delete(vl->vars);
vl->vars = NULL; vl->vars = NULL;
@ -1363,11 +1378,12 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
/* Find available variables at given probe point */ /* Find available variables at given probe point */
int find_available_vars_at(int fd, struct perf_probe_event *pev, int find_available_vars_at(int fd, struct perf_probe_event *pev,
struct variable_list **vls, int max_vls) struct variable_list **vls, int max_vls,
bool externs)
{ {
struct available_var_finder af = { struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars}, .pf = {.pev = pev, .callback = add_available_vars},
.max_vls = max_vls}; .max_vls = max_vls, .externs = externs};
int ret; int ret;
/* Allocate result vls array */ /* Allocate result vls array */

View file

@ -30,7 +30,8 @@ extern int find_line_range(int fd, struct line_range *lr);
/* Find available variables */ /* Find available variables */
extern int find_available_vars_at(int fd, struct perf_probe_event *pev, extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
struct variable_list **vls, int max_points); struct variable_list **vls, int max_points,
bool externs);
#include <dwarf.h> #include <dwarf.h>
#include <libdw.h> #include <libdw.h>
@ -70,6 +71,8 @@ struct available_var_finder {
struct variable_list *vls; /* Found variable lists */ struct variable_list *vls; /* Found variable lists */
int nvls; /* Number of variable lists */ int nvls; /* Number of variable lists */
int max_vls; /* Max no. of variable lists */ int max_vls; /* Max no. of variable lists */
bool externs; /* Find external vars too */
bool child; /* Search child scopes */
}; };
struct line_finder { struct line_finder {