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 { |
