Commit f182e3e1 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo

perf probe: Avoid searching variables in intermediate scopes

Fix variable searching logic to search one in inner than local scope or
global(CU) scope. In the other words, skip searching in intermediate
scopes.

e.g., in the following code,

int var1;

void inline infunc(int i)
{
    i++;   <--- [A]
}

void func(void)
{
   int var1, var2;
   infunc(var2);
}

At [A], "var1" should point the global variable "var1", however, if user
mis-typed as "var2", variable search should be failed. However, current
logic searches variable infunc() scope, global scope, and then func()
scope. Thus, it can find "var2" variable in func() scope. This may not
be what user expects.

So, it would better not search outer scopes except outermost (compile
unit) scope which contains only global variables, when it failed to find
given variable in local scope.

E.g.

Without this:
$ perf probe -V pre_schedule --externs > without.vars

With this:
$ perf probe -V pre_schedule --externs > with.vars

Check the diff:
$ diff without.vars with.vars
88d87
<               int     cpu
133d131
<               long unsigned int*      switch_count

These vars are actually in the scope of schedule(), the caller of
pre_schedule().

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: yrl.pp-manager.tt@hitachi.com
Link: http://lkml.kernel.org/r/20110811110305.19900.94374.stgit@fedora15Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 221d0611
...@@ -615,9 +615,9 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) ...@@ -615,9 +615,9 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
/* Find a variable in a scope DIE */ /* Find a variable in a scope DIE */
static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
{ {
Dwarf_Die vr_die, *scopes; Dwarf_Die vr_die;
char buf[32], *ptr; char buf[32], *ptr;
int ret, nscopes; int ret = 0;
if (!is_c_varname(pf->pvar->var)) { if (!is_c_varname(pf->pvar->var)) {
/* Copy raw parameters */ /* Copy raw parameters */
...@@ -652,29 +652,16 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -652,29 +652,16 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
if (pf->tvar->name == NULL) if (pf->tvar->name == NULL)
return -ENOMEM; return -ENOMEM;
pr_debug("Searching '%s' variable in context.\n", pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
pf->pvar->var);
/* Search child die for local variables and parameters. */ /* Search child die for local variables and parameters. */
if (die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
ret = convert_variable(&vr_die, pf); /* Search again in global variables */
else { if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
/* Search upper class */ ret = -ENOENT;
nscopes = dwarf_getscopes_die(sc_die, &scopes);
ret = -ENOENT;
while (nscopes-- > 1) {
pr_debug("Searching variables in %s\n",
dwarf_diename(&scopes[nscopes]));
/* We should check this scope, so give dummy address */
if (die_find_variable_at(&scopes[nscopes],
pf->pvar->var, 0,
&vr_die)) {
ret = convert_variable(&vr_die, pf);
break;
}
}
if (scopes)
free(scopes);
} }
if (ret == 0)
ret = convert_variable(&vr_die, pf);
if (ret < 0) if (ret < 0)
pr_warning("Failed to find '%s' in this function.\n", pr_warning("Failed to find '%s' in this function.\n",
pf->pvar->var); pf->pvar->var);
...@@ -1242,8 +1229,8 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -1242,8 +1229,8 @@ static int add_available_vars(Dwarf_Die *sc_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, *scopes = NULL; Dwarf_Die die_mem;
int ret, nscopes; int ret;
/* Check number of tevs */ /* Check number of tevs */
if (af->nvls == af->max_vls) { if (af->nvls == af->max_vls) {
...@@ -1273,12 +1260,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -1273,12 +1260,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
goto out; goto out;
/* Don't need to search child DIE for externs. */ /* Don't need to search child DIE for externs. */
af->child = false; af->child = false;
nscopes = dwarf_getscopes_die(sc_die, &scopes); die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
while (nscopes-- > 1)
die_find_child(&scopes[nscopes], collect_variables_cb,
(void *)af, &die_mem);
if (scopes)
free(scopes);
out: out:
if (strlist__empty(vl->vars)) { if (strlist__empty(vl->vars)) {
......
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