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/builtin-probe.c | |
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/builtin-probe.c')
-rw-r--r-- | tools/perf/builtin-probe.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 199d5e19554f..91bb6cf4e025 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) { | ||
285 | pr_err(" Error: Don't use --vars with" | ||
286 | " --add/--del.\n"); | ||
287 | usage_with_options(probe_usage, options); | ||
288 | } | ||
289 | ret = show_available_vars(params.events, params.nevents, | ||
290 | params.max_probe_points); | ||
291 | if (ret < 0) | ||
292 | pr_err(" Error: Failed to show vars. (%d)\n", ret); | ||
293 | return ret; | ||
294 | } | ||
248 | #endif | 295 | #endif |
249 | 296 | ||
250 | if (params.dellist) { | 297 | if (params.dellist) { |