aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2010-10-21 06:13:35 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-10-21 14:06:42 -0400
commitfb8c5a56c7ddbc2b0d2ee7a8da60fe1355f75141 (patch)
tree0d7575627d9fbcdeb642fbcb6ed84744fe9763f5
parentc82ec0a2bd7725a2d2ac3065d8cde13e1f717d3c (diff)
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>
-rw-r--r--tools/perf/Documentation/perf-probe.txt6
-rw-r--r--tools/perf/builtin-probe.c8
-rw-r--r--tools/perf/util/probe-event.c8
-rw-r--r--tools/perf/util/probe-event.h2
-rw-r--r--tools/perf/util/probe-finder.c26
-rw-r--r--tools/perf/util/probe-finder.h5
6 files changed, 41 insertions, 14 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 72f5d9e21432..148c178a35aa 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -18,7 +18,7 @@ or
18or 18or
19'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]' 19'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
20or 20or
21'perf probe' --vars='PROBEPOINT' 21'perf probe' [--externs] --vars='PROBEPOINT'
22 22
23DESCRIPTION 23DESCRIPTION
24----------- 24-----------
@@ -64,6 +64,10 @@ OPTIONS
64 Show available local variables at given probe point. The argument 64 Show available local variables at given probe point. The argument
65 syntax is same as PROBE SYNTAX, but NO ARGs. 65 syntax is same as PROBE SYNTAX, but NO ARGs.
66 66
67--externs::
68 (Only for --vars) Show external defined variables in addition to local
69 variables.
70
67-f:: 71-f::
68--force:: 72--force::
69 Forcibly add events with existing name. 73 Forcibly add events with existing name.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c777bec28466..bdf60cfdf70f 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -51,6 +51,7 @@ static struct {
51 bool force_add; 51 bool force_add;
52 bool show_lines; 52 bool show_lines;
53 bool show_vars; 53 bool show_vars;
54 bool show_ext_vars;
54 bool mod_events; 55 bool mod_events;
55 int nevents; 56 int nevents;
56 struct perf_probe_event events[MAX_PROBES]; 57 struct perf_probe_event events[MAX_PROBES];
@@ -162,7 +163,7 @@ static const char * const probe_usage[] = {
162 "perf probe --list", 163 "perf probe --list",
163#ifdef DWARF_SUPPORT 164#ifdef DWARF_SUPPORT
164 "perf probe --line 'LINEDESC'", 165 "perf probe --line 'LINEDESC'",
165 "perf probe --vars 'PROBEPOINT'", 166 "perf probe [--externs] --vars 'PROBEPOINT'",
166#endif 167#endif
167 NULL 168 NULL
168}; 169};
@@ -207,6 +208,8 @@ static const struct option options[] = {
207 OPT_CALLBACK('V', "vars", NULL, 208 OPT_CALLBACK('V', "vars", NULL,
208 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", 209 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
209 "Show accessible variables on PROBEDEF", opt_show_vars), 210 "Show accessible variables on PROBEDEF", opt_show_vars),
211 OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
212 "Show external variables too (with --vars only)"),
210 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 213 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
211 "file", "vmlinux pathname"), 214 "file", "vmlinux pathname"),
212 OPT_STRING('s', "source", &symbol_conf.source_prefix, 215 OPT_STRING('s', "source", &symbol_conf.source_prefix,
@@ -287,7 +290,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
287 usage_with_options(probe_usage, options); 290 usage_with_options(probe_usage, options);
288 } 291 }
289 ret = show_available_vars(params.events, params.nevents, 292 ret = show_available_vars(params.events, params.nevents,
290 params.max_probe_points); 293 params.max_probe_points,
294 params.show_ext_vars);
291 if (ret < 0) 295 if (ret < 0)
292 pr_err(" Error: Failed to show vars. (%d)\n", ret); 296 pr_err(" Error: Failed to show vars. (%d)\n", ret);
293 return ret; 297 return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 83192a59f02a..82b0976e2053 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -379,7 +379,7 @@ end:
379} 379}
380 380
381static int show_available_vars_at(int fd, struct perf_probe_event *pev, 381static int show_available_vars_at(int fd, struct perf_probe_event *pev,
382 int max_vls) 382 int max_vls, bool externs)
383{ 383{
384 char *buf; 384 char *buf;
385 int ret, i; 385 int ret, i;
@@ -391,7 +391,7 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
391 return -EINVAL; 391 return -EINVAL;
392 pr_debug("Searching variables at %s\n", buf); 392 pr_debug("Searching variables at %s\n", buf);
393 393
394 ret = find_available_vars_at(fd, pev, &vls, max_vls); 394 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
395 if (ret > 0) { 395 if (ret > 0) {
396 /* Some variables were found */ 396 /* Some variables were found */
397 fprintf(stdout, "Available variables at %s\n", buf); 397 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,
421 421
422/* Show available variables on given probe point */ 422/* Show available variables on given probe point */
423int show_available_vars(struct perf_probe_event *pevs, int npevs, 423int show_available_vars(struct perf_probe_event *pevs, int npevs,
424 int max_vls) 424 int max_vls, bool externs)
425{ 425{
426 int i, fd, ret = 0; 426 int i, fd, ret = 0;
427 427
@@ -438,7 +438,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
438 setup_pager(); 438 setup_pager();
439 439
440 for (i = 0; i < npevs && ret >= 0; i++) 440 for (i = 0; i < npevs && ret >= 0; i++)
441 ret = show_available_vars_at(fd, &pevs[i], max_vls); 441 ret = show_available_vars_at(fd, &pevs[i], max_vls, externs);
442 442
443 close(fd); 443 close(fd);
444 return ret; 444 return ret;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 83130f634f01..c74b1fd2c1fa 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -122,7 +122,7 @@ extern int del_perf_probe_events(struct strlist *dellist);
122extern int show_perf_probe_events(void); 122extern int show_perf_probe_events(void);
123extern int show_line_range(struct line_range *lr); 123extern int show_line_range(struct line_range *lr);
124extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 124extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
125 int max_probe_points); 125 int max_probe_points, bool externs);
126 126
127 127
128/* Maximum index number of event-name postfix */ 128/* Maximum index number of event-name postfix */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 986027fa495f..a274fd0c143e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1312,12 +1312,13 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1312 af->pf.fb_ops, NULL); 1312 af->pf.fb_ops, NULL);
1313 if (ret == 0) { 1313 if (ret == 0) {
1314 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); 1314 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1315 pr_debug2("Add new var: %s\n", buf);
1315 if (ret > 0) 1316 if (ret > 0)
1316 strlist__add(vl->vars, buf); 1317 strlist__add(vl->vars, buf);
1317 } 1318 }
1318 } 1319 }
1319 1320
1320 if (dwarf_haspc(die_mem, af->pf.addr)) 1321 if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1321 return DIE_FIND_CB_CONTINUE; 1322 return DIE_FIND_CB_CONTINUE;
1322 else 1323 else
1323 return DIE_FIND_CB_SIBLING; 1324 return DIE_FIND_CB_SIBLING;
@@ -1329,8 +1330,8 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1329 struct available_var_finder *af = 1330 struct available_var_finder *af =
1330 container_of(pf, struct available_var_finder, pf); 1331 container_of(pf, struct available_var_finder, pf);
1331 struct variable_list *vl; 1332 struct variable_list *vl;
1332 Dwarf_Die die_mem; 1333 Dwarf_Die die_mem, *scopes = NULL;
1333 int ret; 1334 int ret, nscopes;
1334 1335
1335 /* Check number of tevs */ 1336 /* Check number of tevs */
1336 if (af->nvls == af->max_vls) { 1337 if (af->nvls == af->max_vls) {
@@ -1351,8 +1352,22 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1351 vl->vars = strlist__new(true, NULL); 1352 vl->vars = strlist__new(true, NULL);
1352 if (vl->vars == NULL) 1353 if (vl->vars == NULL)
1353 return -ENOMEM; 1354 return -ENOMEM;
1355 af->child = true;
1354 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem); 1356 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
1355 1357
1358 /* Find external variables */
1359 if (!af->externs)
1360 goto out;
1361 /* Don't need to search child DIE for externs. */
1362 af->child = false;
1363 nscopes = dwarf_getscopes_die(sp_die, &scopes);
1364 while (nscopes-- > 1)
1365 die_find_child(&scopes[nscopes], collect_variables_cb,
1366 (void *)af, &die_mem);
1367 if (scopes)
1368 free(scopes);
1369
1370out:
1356 if (strlist__empty(vl->vars)) { 1371 if (strlist__empty(vl->vars)) {
1357 strlist__delete(vl->vars); 1372 strlist__delete(vl->vars);
1358 vl->vars = NULL; 1373 vl->vars = NULL;
@@ -1363,11 +1378,12 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1363 1378
1364/* Find available variables at given probe point */ 1379/* Find available variables at given probe point */
1365int find_available_vars_at(int fd, struct perf_probe_event *pev, 1380int find_available_vars_at(int fd, struct perf_probe_event *pev,
1366 struct variable_list **vls, int max_vls) 1381 struct variable_list **vls, int max_vls,
1382 bool externs)
1367{ 1383{
1368 struct available_var_finder af = { 1384 struct available_var_finder af = {
1369 .pf = {.pev = pev, .callback = add_available_vars}, 1385 .pf = {.pev = pev, .callback = add_available_vars},
1370 .max_vls = max_vls}; 1386 .max_vls = max_vls, .externs = externs};
1371 int ret; 1387 int ret;
1372 1388
1373 /* Allocate result vls array */ 1389 /* Allocate result vls array */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index baffd25f39c9..516912a04011 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -30,7 +30,8 @@ extern int find_line_range(int fd, struct line_range *lr);
30 30
31/* Find available variables */ 31/* Find available variables */
32extern int find_available_vars_at(int fd, struct perf_probe_event *pev, 32extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
33 struct variable_list **vls, int max_points); 33 struct variable_list **vls, int max_points,
34 bool externs);
34 35
35#include <dwarf.h> 36#include <dwarf.h>
36#include <libdw.h> 37#include <libdw.h>
@@ -70,6 +71,8 @@ struct available_var_finder {
70 struct variable_list *vls; /* Found variable lists */ 71 struct variable_list *vls; /* Found variable lists */
71 int nvls; /* Number of variable lists */ 72 int nvls; /* Number of variable lists */
72 int max_vls; /* Max no. of variable lists */ 73 int max_vls; /* Max no. of variable lists */
74 bool externs; /* Find external vars too */
75 bool child; /* Search child scopes */
73}; 76};
74 77
75struct line_finder { 78struct line_finder {