diff options
Diffstat (limited to 'tools/perf/builtin-probe.c')
-rw-r--r-- | tools/perf/builtin-probe.c | 78 |
1 files changed, 67 insertions, 11 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 199d5e19554f..2e000c068cc5 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -50,14 +50,17 @@ 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 show_ext_vars; | ||
55 | bool mod_events; | ||
53 | int nevents; | 56 | int nevents; |
54 | struct perf_probe_event events[MAX_PROBES]; | 57 | struct perf_probe_event events[MAX_PROBES]; |
55 | struct strlist *dellist; | 58 | struct strlist *dellist; |
56 | struct line_range line_range; | 59 | struct line_range line_range; |
60 | const char *target_module; | ||
57 | int max_probe_points; | 61 | int max_probe_points; |
58 | } params; | 62 | } params; |
59 | 63 | ||
60 | |||
61 | /* Parse an event definition. Note that any error must die. */ | 64 | /* Parse an event definition. Note that any error must die. */ |
62 | static int parse_probe_event(const char *str) | 65 | static int parse_probe_event(const char *str) |
63 | { | 66 | { |
@@ -92,6 +95,7 @@ static int parse_probe_event_argv(int argc, const char **argv) | |||
92 | len = 0; | 95 | len = 0; |
93 | for (i = 0; i < argc; i++) | 96 | for (i = 0; i < argc; i++) |
94 | len += sprintf(&buf[len], "%s ", argv[i]); | 97 | len += sprintf(&buf[len], "%s ", argv[i]); |
98 | params.mod_events = true; | ||
95 | ret = parse_probe_event(buf); | 99 | ret = parse_probe_event(buf); |
96 | free(buf); | 100 | free(buf); |
97 | return ret; | 101 | return ret; |
@@ -100,9 +104,10 @@ static int parse_probe_event_argv(int argc, const char **argv) | |||
100 | static int opt_add_probe_event(const struct option *opt __used, | 104 | static int opt_add_probe_event(const struct option *opt __used, |
101 | const char *str, int unset __used) | 105 | const char *str, int unset __used) |
102 | { | 106 | { |
103 | if (str) | 107 | if (str) { |
108 | params.mod_events = true; | ||
104 | return parse_probe_event(str); | 109 | return parse_probe_event(str); |
105 | else | 110 | } else |
106 | return 0; | 111 | return 0; |
107 | } | 112 | } |
108 | 113 | ||
@@ -110,6 +115,7 @@ static int opt_del_probe_event(const struct option *opt __used, | |||
110 | const char *str, int unset __used) | 115 | const char *str, int unset __used) |
111 | { | 116 | { |
112 | if (str) { | 117 | if (str) { |
118 | params.mod_events = true; | ||
113 | if (!params.dellist) | 119 | if (!params.dellist) |
114 | params.dellist = strlist__new(true, NULL); | 120 | params.dellist = strlist__new(true, NULL); |
115 | strlist__add(params.dellist, str); | 121 | strlist__add(params.dellist, str); |
@@ -130,6 +136,25 @@ static int opt_show_lines(const struct option *opt __used, | |||
130 | 136 | ||
131 | return ret; | 137 | return ret; |
132 | } | 138 | } |
139 | |||
140 | static int opt_show_vars(const struct option *opt __used, | ||
141 | const char *str, int unset __used) | ||
142 | { | ||
143 | struct perf_probe_event *pev = ¶ms.events[params.nevents]; | ||
144 | int ret; | ||
145 | |||
146 | if (!str) | ||
147 | return 0; | ||
148 | |||
149 | ret = parse_probe_event(str); | ||
150 | if (!ret && pev->nargs != 0) { | ||
151 | pr_err(" Error: '--vars' doesn't accept arguments.\n"); | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | params.show_vars = true; | ||
155 | |||
156 | return ret; | ||
157 | } | ||
133 | #endif | 158 | #endif |
134 | 159 | ||
135 | static const char * const probe_usage[] = { | 160 | static const char * const probe_usage[] = { |
@@ -138,7 +163,8 @@ static const char * const probe_usage[] = { | |||
138 | "perf probe [<options>] --del '[GROUP:]EVENT' ...", | 163 | "perf probe [<options>] --del '[GROUP:]EVENT' ...", |
139 | "perf probe --list", | 164 | "perf probe --list", |
140 | #ifdef DWARF_SUPPORT | 165 | #ifdef DWARF_SUPPORT |
141 | "perf probe --line 'LINEDESC'", | 166 | "perf probe [<options>] --line 'LINEDESC'", |
167 | "perf probe [<options>] --vars 'PROBEPOINT'", | ||
142 | #endif | 168 | #endif |
143 | NULL | 169 | NULL |
144 | }; | 170 | }; |
@@ -180,10 +206,17 @@ static const struct option options[] = { | |||
180 | OPT_CALLBACK('L', "line", NULL, | 206 | OPT_CALLBACK('L', "line", NULL, |
181 | "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", | 207 | "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", |
182 | "Show source code lines.", opt_show_lines), | 208 | "Show source code lines.", opt_show_lines), |
209 | OPT_CALLBACK('V', "vars", NULL, | ||
210 | "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", | ||
211 | "Show accessible variables on PROBEDEF", opt_show_vars), | ||
212 | OPT_BOOLEAN('\0', "externs", ¶ms.show_ext_vars, | ||
213 | "Show external variables too (with --vars only)"), | ||
183 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | 214 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, |
184 | "file", "vmlinux pathname"), | 215 | "file", "vmlinux pathname"), |
185 | OPT_STRING('s', "source", &symbol_conf.source_prefix, | 216 | OPT_STRING('s', "source", &symbol_conf.source_prefix, |
186 | "directory", "path to kernel source"), | 217 | "directory", "path to kernel source"), |
218 | OPT_STRING('m', "module", ¶ms.target_module, | ||
219 | "modname", "target module name"), | ||
187 | #endif | 220 | #endif |
188 | OPT__DRY_RUN(&probe_event_dry_run), | 221 | OPT__DRY_RUN(&probe_event_dry_run), |
189 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, | 222 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, |
@@ -217,7 +250,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
217 | usage_with_options(probe_usage, options); | 250 | usage_with_options(probe_usage, options); |
218 | 251 | ||
219 | if (params.list_events) { | 252 | if (params.list_events) { |
220 | if (params.nevents != 0 || params.dellist) { | 253 | if (params.mod_events) { |
221 | pr_err(" Error: Don't use --list with --add/--del.\n"); | 254 | pr_err(" Error: Don't use --list with --add/--del.\n"); |
222 | usage_with_options(probe_usage, options); | 255 | usage_with_options(probe_usage, options); |
223 | } | 256 | } |
@@ -225,6 +258,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
225 | pr_err(" Error: Don't use --list with --line.\n"); | 258 | pr_err(" Error: Don't use --list with --line.\n"); |
226 | usage_with_options(probe_usage, options); | 259 | usage_with_options(probe_usage, options); |
227 | } | 260 | } |
261 | if (params.show_vars) { | ||
262 | pr_err(" Error: Don't use --list with --vars.\n"); | ||
263 | usage_with_options(probe_usage, options); | ||
264 | } | ||
228 | ret = show_perf_probe_events(); | 265 | ret = show_perf_probe_events(); |
229 | if (ret < 0) | 266 | if (ret < 0) |
230 | pr_err(" Error: Failed to show event list. (%d)\n", | 267 | pr_err(" Error: Failed to show event list. (%d)\n", |
@@ -234,17 +271,35 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
234 | 271 | ||
235 | #ifdef DWARF_SUPPORT | 272 | #ifdef DWARF_SUPPORT |
236 | if (params.show_lines) { | 273 | if (params.show_lines) { |
237 | if (params.nevents != 0 || params.dellist) { | 274 | if (params.mod_events) { |
238 | pr_warning(" Error: Don't use --line with" | 275 | pr_err(" Error: Don't use --line with" |
239 | " --add/--del.\n"); | 276 | " --add/--del.\n"); |
277 | usage_with_options(probe_usage, options); | ||
278 | } | ||
279 | if (params.show_vars) { | ||
280 | pr_err(" Error: Don't use --line with --vars.\n"); | ||
240 | usage_with_options(probe_usage, options); | 281 | usage_with_options(probe_usage, options); |
241 | } | 282 | } |
242 | 283 | ||
243 | ret = show_line_range(¶ms.line_range); | 284 | ret = show_line_range(¶ms.line_range, params.target_module); |
244 | if (ret < 0) | 285 | if (ret < 0) |
245 | pr_err(" Error: Failed to show lines. (%d)\n", ret); | 286 | pr_err(" Error: Failed to show lines. (%d)\n", ret); |
246 | return ret; | 287 | return ret; |
247 | } | 288 | } |
289 | if (params.show_vars) { | ||
290 | if (params.mod_events) { | ||
291 | pr_err(" Error: Don't use --vars with" | ||
292 | " --add/--del.\n"); | ||
293 | usage_with_options(probe_usage, options); | ||
294 | } | ||
295 | ret = show_available_vars(params.events, params.nevents, | ||
296 | params.max_probe_points, | ||
297 | params.target_module, | ||
298 | params.show_ext_vars); | ||
299 | if (ret < 0) | ||
300 | pr_err(" Error: Failed to show vars. (%d)\n", ret); | ||
301 | return ret; | ||
302 | } | ||
248 | #endif | 303 | #endif |
249 | 304 | ||
250 | if (params.dellist) { | 305 | if (params.dellist) { |
@@ -258,8 +313,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
258 | 313 | ||
259 | if (params.nevents) { | 314 | if (params.nevents) { |
260 | ret = add_perf_probe_events(params.events, params.nevents, | 315 | ret = add_perf_probe_events(params.events, params.nevents, |
261 | params.force_add, | 316 | params.max_probe_points, |
262 | params.max_probe_points); | 317 | params.target_module, |
318 | params.force_add); | ||
263 | if (ret < 0) { | 319 | if (ret < 0) { |
264 | pr_err(" Error: Failed to add events. (%d)\n", ret); | 320 | pr_err(" Error: Failed to add events. (%d)\n", ret); |
265 | return ret; | 321 | return ret; |