diff options
| author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2010-10-21 06:13:23 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-10-21 13:59:06 -0400 |
| commit | cf6eb489e5c04c8f8d5fd7bf90b8346c987688bc (patch) | |
| tree | 3da471c3ae3f99cdcbec26cc95412a4b44506f3c /tools/perf | |
| parent | 632941c4f8fbd5b90dcb1672cd0422dfd7332bc9 (diff) | |
perf probe: Show accessible local variables
Add -V (--vars) option for listing accessible local variables at given probe
point. This will help finding which local variables are available for event
arguments.
e.g.)
# perf probe -V call_timer_fn:23
Available variables at call_timer_fn:23
@<run_timer_softirq+345>
function_type* fn
int preempt_count
long unsigned int data
struct list_head work_list
struct list_head* head
struct timer_list* timer
struct tvec_base* base
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: <20101021101323.3542.40282.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>
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 7 | ||||
| -rw-r--r-- | tools/perf/builtin-probe.c | 61 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 72 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/probe-finder.c | 412 | ||||
| -rw-r--r-- | tools/perf/util/probe-finder.h | 25 |
6 files changed, 480 insertions, 105 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 27d52dae5a4..72f5d9e2143 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
| @@ -17,6 +17,8 @@ or | |||
| 17 | 'perf probe' --list | 17 | 'perf probe' --list |
| 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 | ||
| 21 | 'perf probe' --vars='PROBEPOINT' | ||
| 20 | 22 | ||
| 21 | DESCRIPTION | 23 | DESCRIPTION |
| 22 | ----------- | 24 | ----------- |
| @@ -57,6 +59,11 @@ OPTIONS | |||
| 57 | Show source code lines which can be probed. This needs an argument | 59 | Show source code lines which can be probed. This needs an argument |
| 58 | which specifies a range of the source code. (see LINE SYNTAX for detail) | 60 | which specifies a range of the source code. (see LINE SYNTAX for detail) |
| 59 | 61 | ||
| 62 | -V:: | ||
| 63 | --vars=:: | ||
| 64 | Show available local variables at given probe point. The argument | ||
| 65 | syntax is same as PROBE SYNTAX, but NO ARGs. | ||
| 66 | |||
| 60 | -f:: | 67 | -f:: |
| 61 | --force:: | 68 | --force:: |
| 62 | Forcibly add events with existing name. | 69 | Forcibly add events with existing name. |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 199d5e19554..91bb6cf4e02 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
| @@ -50,6 +50,8 @@ static struct { | |||
| 50 | bool list_events; | 50 | bool list_events; |
| 51 | bool force_add; | 51 | bool force_add; |
| 52 | bool show_lines; | 52 | bool show_lines; |
| 53 | bool show_vars; | ||
| 54 | bool mod_events; | ||
| 53 | int nevents; | 55 | int nevents; |
| 54 | struct perf_probe_event events[MAX_PROBES]; | 56 | struct perf_probe_event events[MAX_PROBES]; |
| 55 | struct strlist *dellist; | 57 | struct strlist *dellist; |
| @@ -57,7 +59,6 @@ static struct { | |||
| 57 | int max_probe_points; | 59 | int max_probe_points; |
| 58 | } params; | 60 | } params; |
| 59 | 61 | ||
| 60 | |||
| 61 | /* Parse an event definition. Note that any error must die. */ | 62 | /* Parse an event definition. Note that any error must die. */ |
| 62 | static int parse_probe_event(const char *str) | 63 | static int parse_probe_event(const char *str) |
| 63 | { | 64 | { |
| @@ -92,6 +93,7 @@ static int parse_probe_event_argv(int argc, const char **argv) | |||
| 92 | len = 0; | 93 | len = 0; |
| 93 | for (i = 0; i < argc; i++) | 94 | for (i = 0; i < argc; i++) |
| 94 | len += sprintf(&buf[len], "%s ", argv[i]); | 95 | len += sprintf(&buf[len], "%s ", argv[i]); |
| 96 | params.mod_events = true; | ||
| 95 | ret = parse_probe_event(buf); | 97 | ret = parse_probe_event(buf); |
| 96 | free(buf); | 98 | free(buf); |
| 97 | return ret; | 99 | return ret; |
| @@ -100,9 +102,10 @@ static int parse_probe_event_argv(int argc, const char **argv) | |||
| 100 | static int opt_add_probe_event(const struct option *opt __used, | 102 | static int opt_add_probe_event(const struct option *opt __used, |
| 101 | const char *str, int unset __used) | 103 | const char *str, int unset __used) |
| 102 | { | 104 | { |
| 103 | if (str) | 105 | if (str) { |
| 106 | params.mod_events = true; | ||
| 104 | return parse_probe_event(str); | 107 | return parse_probe_event(str); |
| 105 | else | 108 | } else |
| 106 | return 0; | 109 | return 0; |
| 107 | } | 110 | } |
| 108 | 111 | ||
| @@ -110,6 +113,7 @@ static int opt_del_probe_event(const struct option *opt __used, | |||
| 110 | const char *str, int unset __used) | 113 | const char *str, int unset __used) |
| 111 | { | 114 | { |
| 112 | if (str) { | 115 | if (str) { |
| 116 | params.mod_events = true; | ||
| 113 | if (!params.dellist) | 117 | if (!params.dellist) |
| 114 | params.dellist = strlist__new(true, NULL); | 118 | params.dellist = strlist__new(true, NULL); |
| 115 | strlist__add(params.dellist, str); | 119 | strlist__add(params.dellist, str); |
| @@ -130,6 +134,25 @@ static int opt_show_lines(const struct option *opt __used, | |||
| 130 | 134 | ||
| 131 | return ret; | 135 | return ret; |
| 132 | } | 136 | } |
| 137 | |||
| 138 | static int opt_show_vars(const struct option *opt __used, | ||
| 139 | const char *str, int unset __used) | ||
| 140 | { | ||
| 141 | struct perf_probe_event *pev = ¶ms.events[params.nevents]; | ||
| 142 | int ret; | ||
| 143 | |||
| 144 | if (!str) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | ret = parse_probe_event(str); | ||
| 148 | if (!ret && pev->nargs != 0) { | ||
| 149 | pr_err(" Error: '--vars' doesn't accept arguments.\n"); | ||
| 150 | return -EINVAL; | ||
| 151 | } | ||
| 152 | params.show_vars = true; | ||
| 153 | |||
| 154 | return ret; | ||
| 155 | } | ||
| 133 | #endif | 156 | #endif |
| 134 | 157 | ||
| 135 | static const char * const probe_usage[] = { | 158 | static const char * const probe_usage[] = { |
| @@ -139,6 +162,7 @@ static const char * const probe_usage[] = { | |||
| 139 | "perf probe --list", | 162 | "perf probe --list", |
| 140 | #ifdef DWARF_SUPPORT | 163 | #ifdef DWARF_SUPPORT |
| 141 | "perf probe --line 'LINEDESC'", | 164 | "perf probe --line 'LINEDESC'", |
| 165 | "perf probe --vars 'PROBEPOINT'", | ||
| 142 | #endif | 166 | #endif |
| 143 | NULL | 167 | NULL |
| 144 | }; | 168 | }; |
| @@ -180,6 +204,9 @@ static const struct option options[] = { | |||
| 180 | OPT_CALLBACK('L', "line", NULL, | 204 | OPT_CALLBACK('L', "line", NULL, |
| 181 | "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", | 205 | "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", |
| 182 | "Show source code lines.", opt_show_lines), | 206 | "Show source code lines.", opt_show_lines), |
| 207 | OPT_CALLBACK('V', "vars", NULL, | ||
| 208 | "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", | ||
| 209 | "Show accessible variables on PROBEDEF", opt_show_vars), | ||
| 183 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | 210 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, |
| 184 | "file", "vmlinux pathname"), | 211 | "file", "vmlinux pathname"), |
| 185 | OPT_STRING('s', "source", &symbol_conf.source_prefix, | 212 | OPT_STRING('s', "source", &symbol_conf.source_prefix, |
| @@ -217,7 +244,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 217 | usage_with_options(probe_usage, options); | 244 | usage_with_options(probe_usage, options); |
| 218 | 245 | ||
| 219 | if (params.list_events) { | 246 | if (params.list_events) { |
| 220 | if (params.nevents != 0 || params.dellist) { | 247 | if (params.mod_events) { |
| 221 | pr_err(" Error: Don't use --list with --add/--del.\n"); | 248 | pr_err(" Error: Don't use --list with --add/--del.\n"); |
| 222 | usage_with_options(probe_usage, options); | 249 | usage_with_options(probe_usage, options); |
| 223 | } | 250 | } |
| @@ -225,6 +252,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 225 | pr_err(" Error: Don't use --list with --line.\n"); | 252 | pr_err(" Error: Don't use --list with --line.\n"); |
| 226 | usage_with_options(probe_usage, options); | 253 | usage_with_options(probe_usage, options); |
| 227 | } | 254 | } |
| 255 | if (params.show_vars) { | ||
| 256 | pr_err(" Error: Don't use --list with --vars.\n"); | ||
| 257 | usage_with_options(probe_usage, options); | ||
| 258 | } | ||
| 228 | ret = show_perf_probe_events(); | 259 | ret = show_perf_probe_events(); |
| 229 | if (ret < 0) | 260 | if (ret < 0) |
| 230 | pr_err(" Error: Failed to show event list. (%d)\n", | 261 | pr_err(" Error: Failed to show event list. (%d)\n", |
| @@ -234,9 +265,13 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 234 | 265 | ||
| 235 | #ifdef DWARF_SUPPORT | 266 | #ifdef DWARF_SUPPORT |
| 236 | if (params.show_lines) { | 267 | if (params.show_lines) { |
| 237 | if (params.nevents != 0 || params.dellist) { | 268 | if (params.mod_events) { |
| 238 | pr_warning(" Error: Don't use --line with" | 269 | pr_err(" Error: Don't use --line with" |
| 239 | " --add/--del.\n"); | 270 | " --add/--del.\n"); |
| 271 | usage_with_options(probe_usage, options); | ||
| 272 | } | ||
| 273 | if (params.show_vars) { | ||
| 274 | pr_err(" Error: Don't use --line with --vars.\n"); | ||
| 240 | usage_with_options(probe_usage, options); | 275 | usage_with_options(probe_usage, options); |
| 241 | } | 276 | } |
| 242 | 277 | ||
| @@ -245,6 +280,18 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 245 | pr_err(" Error: Failed to show lines. (%d)\n", ret); | 280 | pr_err(" Error: Failed to show lines. (%d)\n", ret); |
| 246 | return ret; | 281 | return ret; |
| 247 | } | 282 | } |
| 283 | if (params.show_vars) { | ||
| 284 | if (params.mod_events) { | ||
