aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2011-08-11 07:03:05 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-08-12 08:29:34 -0400
commitf182e3e13ca71b64b40fab1aef31fa6a78271648 (patch)
tree6432a921ffc434d475093dca76bca745f9bc10b9 /tools/perf
parent221d061182b8ff5507d5768aeeecbc74f01c5dfa (diff)
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@fedora15 Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/probe-finder.c44
1 files changed, 13 insertions, 31 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 5c83b7d3d8ef..114542a5a99c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -615,9 +615,9 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
615/* Find a variable in a scope DIE */ 615/* Find a variable in a scope DIE */
616static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) 616static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
617{ 617{
618 Dwarf_Die vr_die, *scopes; 618 Dwarf_Die vr_die;
619 char buf[32], *ptr; 619 char buf[32], *ptr;
620 int ret, nscopes; 620 int ret = 0;
621 621
622 if (!is_c_varname(pf->pvar->var)) { 622 if (!is_c_varname(pf->pvar->var)) {
623 /* Copy raw parameters */ 623 /* Copy raw parameters */
@@ -652,29 +652,16 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
652 if (pf->tvar->name == NULL) 652 if (pf->tvar->name == NULL)
653 return -ENOMEM; 653 return -ENOMEM;
654 654
655 pr_debug("Searching '%s' variable in context.\n", 655 pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
656 pf->pvar->var);
657 /* Search child die for local variables and parameters. */ 656 /* Search child die for local variables and parameters. */
658 if (die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) 657 if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
659 ret = convert_variable(&vr_die, pf); 658 /* Search again in global variables */
660 else { 659 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
661 /* Search upper class */ 660 ret = -ENOENT;
662 nscopes = dwarf_getscopes_die(sc_die, &scopes);
663 ret = -ENOENT;
664 while (nscopes-- > 1) {
665 pr_debug("Searching variables in %s\n",
666 dwarf_diename(&scopes[nscopes]));
667 /* We should check this scope, so give dummy address */
668 if (die_find_variable_at(&scopes[nscopes],
669 pf->pvar->var, 0,
670 &vr_die)) {
671 ret = convert_variable(&vr_die, pf);
672 break;
673 }
674 }
675 if (scopes)
676 free(scopes);
677 } 661 }
662 if (ret == 0)
663 ret = convert_variable(&vr_die, pf);
664
678 if (ret < 0) 665 if (ret < 0)
679 pr_warning("Failed to find '%s' in this function.\n", 666 pr_warning("Failed to find '%s' in this function.\n",
680 pf->pvar->var); 667 pf->pvar->var);
@@ -1242,8 +1229,8 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1242 struct available_var_finder *af = 1229 struct available_var_finder *af =
1243 container_of(pf, struct available_var_finder, pf); 1230 container_of(pf, struct available_var_finder, pf);
1244 struct variable_list *vl; 1231 struct variable_list *vl;
1245 Dwarf_Die die_mem, *scopes = NULL; 1232 Dwarf_Die die_mem;
1246 int ret, nscopes; 1233 int ret;
1247 1234
1248 /* Check number of tevs */ 1235 /* Check number of tevs */
1249 if (af->nvls == af->max_vls) { 1236 if (af->nvls == af->max_vls) {
@@ -1273,12 +1260,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1273 goto out; 1260 goto out;
1274 /* Don't need to search child DIE for externs. */ 1261 /* Don't need to search child DIE for externs. */
1275 af->child = false; 1262 af->child = false;
1276 nscopes = dwarf_getscopes_die(sc_die, &scopes); 1263 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1277 while (nscopes-- > 1)
1278 die_find_child(&scopes[nscopes], collect_variables_cb,
1279 (void *)af, &die_mem);
1280 if (scopes)
1281 free(scopes);
1282 1264
1283out: 1265out:
1284 if (strlist__empty(vl->vars)) { 1266 if (strlist__empty(vl->vars)) {