diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2010-10-21 06:13:35 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-10-21 14:06:42 -0400 |
commit | fb8c5a56c7ddbc2b0d2ee7a8da60fe1355f75141 (patch) | |
tree | 0d7575627d9fbcdeb642fbcb6ed84744fe9763f5 | |
parent | c82ec0a2bd7725a2d2ac3065d8cde13e1f717d3c (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.txt | 6 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 8 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 8 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 2 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 26 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 5 |
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 | |||
18 | or | 18 | or |
19 | 'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]' | 19 | 'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]' |
20 | or | 20 | or |
21 | 'perf probe' --vars='PROBEPOINT' | 21 | 'perf probe' [--externs] --vars='PROBEPOINT' |
22 | 22 | ||
23 | DESCRIPTION | 23 | DESCRIPTION |
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", ¶ms.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 | ||
381 | static int show_available_vars_at(int fd, struct perf_probe_event *pev, | 381 | static 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 */ |
423 | int show_available_vars(struct perf_probe_event *pevs, int npevs, | 423 | int 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); | |||
122 | extern int show_perf_probe_events(void); | 122 | extern int show_perf_probe_events(void); |
123 | extern int show_line_range(struct line_range *lr); | 123 | extern int show_line_range(struct line_range *lr); |
124 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, | 124 | extern 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 | |||
1370 | out: | ||
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 */ |
1365 | int find_available_vars_at(int fd, struct perf_probe_event *pev, | 1380 | int 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 */ |
32 | extern int find_available_vars_at(int fd, struct perf_probe_event *pev, | 32 | extern 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 | ||
75 | struct line_finder { | 78 | struct line_finder { |