Blame view
tools/perf/builtin-probe.c
11.1 KB
4ea42b181 perf: Add perf pr... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* * builtin-probe.c * * Builtin probe command: Set up probe events by C expression * * Written by Masami Hiramatsu <mhiramat@redhat.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #define _GNU_SOURCE #include <sys/utsname.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #undef _GNU_SOURCE #include "perf.h" #include "builtin.h" #include "util/util.h" |
fa28244d1 perf probe: Suppo... |
38 |
#include "util/strlist.h" |
bd09d7b5e perf probe: Add v... |
39 |
#include "util/strfilter.h" |
e0faa8d35 perf probe: Move ... |
40 |
#include "util/symbol.h" |
89c69c0ee perf: Use eprintf... |
41 |
#include "util/debug.h" |
96c96612e perf probe: Check... |
42 |
#include "util/debugfs.h" |
4ea42b181 perf: Add perf pr... |
43 |
#include "util/parse-options.h" |
4ea42b181 perf: Add perf pr... |
44 |
#include "util/probe-finder.h" |
50656eec8 perf probe: Move ... |
45 |
#include "util/probe-event.h" |
4ea42b181 perf: Add perf pr... |
46 |
|
bd09d7b5e perf probe: Add v... |
47 |
#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" |
3c42258c9 perf probe: Add f... |
48 |
#define DEFAULT_FUNC_FILTER "!_*" |
4ea42b181 perf: Add perf pr... |
49 50 51 |
/* Session management structure */ static struct { |
fac13fd54 perf probe: Clean... |
52 |
bool list_events; |
d761b08bf perf probe: Rejec... |
53 |
bool force_add; |
631c9def8 perf probe: Suppo... |
54 |
bool show_lines; |
cf6eb489e perf probe: Show ... |
55 |
bool show_vars; |
fb8c5a56c perf probe: Show ... |
56 |
bool show_ext_vars; |
e80711ca8 perf probe: Add -... |
57 |
bool show_funcs; |
cf6eb489e perf probe: Show ... |
58 |
bool mod_events; |
4235b0454 perf probe: Intro... |
59 60 |
int nevents; struct perf_probe_event events[MAX_PROBES]; |
fa28244d1 perf probe: Suppo... |
61 |
struct strlist *dellist; |
631c9def8 perf probe: Suppo... |
62 |
struct line_range line_range; |
469b9b884 perf probe: Add b... |
63 |
const char *target_module; |
ef4a35657 perf probe: Add -... |
64 |
int max_probe_points; |
bd09d7b5e perf probe: Add v... |
65 |
struct strfilter *filter; |
12a1fadb4 perf probe: Renam... |
66 |
} params; |
4ea42b181 perf: Add perf pr... |
67 |
|
253977b0d perf/probes: Impr... |
68 |
/* Parse an event definition. Note that any error must die. */ |
146a14394 perf probe: Remov... |
69 |
static int parse_probe_event(const char *str) |
4ea42b181 perf: Add perf pr... |
70 |
{ |
4235b0454 perf probe: Intro... |
71 |
struct perf_probe_event *pev = ¶ms.events[params.nevents]; |
146a14394 perf probe: Remov... |
72 |
int ret; |
4ea42b181 perf: Add perf pr... |
73 |
|
4235b0454 perf probe: Intro... |
74 75 |
pr_debug("probe-definition(%d): %s ", params.nevents, str); |
8a7ddad8e perf probe: Don't... |
76 77 78 79 |
if (++params.nevents == MAX_PROBES) { pr_err("Too many probes (> %d) were specified.", MAX_PROBES); return -1; } |
4ea42b181 perf: Add perf pr... |
80 |
|
4235b0454 perf probe: Intro... |
81 |
/* Parse a perf-probe command into event */ |
146a14394 perf probe: Remov... |
82 |
ret = parse_perf_probe_command(str, pev); |
4235b0454 perf probe: Intro... |
83 84 |
pr_debug("%d arguments ", pev->nargs); |
146a14394 perf probe: Remov... |
85 86 |
return ret; |
46ab49267 perf/probes: Impr... |
87 |
} |
146a14394 perf probe: Remov... |
88 |
static int parse_probe_event_argv(int argc, const char **argv) |
d1bde3f75 perf probe: Fix a... |
89 |
{ |
146a14394 perf probe: Remov... |
90 |
int i, len, ret; |
d1bde3f75 perf probe: Fix a... |
91 92 93 94 95 96 |
char *buf; /* Bind up rest arguments */ len = 0; for (i = 0; i < argc; i++) len += strlen(argv[i]) + 1; |
8a7ddad8e perf probe: Don't... |
97 98 99 |
buf = zalloc(len + 1); if (buf == NULL) return -ENOMEM; |
d1bde3f75 perf probe: Fix a... |
100 101 102 |
len = 0; for (i = 0; i < argc; i++) len += sprintf(&buf[len], "%s ", argv[i]); |
cf6eb489e perf probe: Show ... |
103 |
params.mod_events = true; |
146a14394 perf probe: Remov... |
104 |
ret = parse_probe_event(buf); |
d1bde3f75 perf probe: Fix a... |
105 |
free(buf); |
146a14394 perf probe: Remov... |
106 |
return ret; |
d1bde3f75 perf probe: Fix a... |
107 |
} |
253977b0d perf/probes: Impr... |
108 |
static int opt_add_probe_event(const struct option *opt __used, |
46ab49267 perf/probes: Impr... |
109 110 |
const char *str, int unset __used) { |
cf6eb489e perf probe: Show ... |
111 112 |
if (str) { params.mod_events = true; |
146a14394 perf probe: Remov... |
113 |
return parse_probe_event(str); |
cf6eb489e perf probe: Show ... |
114 |
} else |
146a14394 perf probe: Remov... |
115 |
return 0; |
4ea42b181 perf: Add perf pr... |
116 |
} |
fa28244d1 perf probe: Suppo... |
117 118 119 120 |
static int opt_del_probe_event(const struct option *opt __used, const char *str, int unset __used) { if (str) { |
cf6eb489e perf probe: Show ... |
121 |
params.mod_events = true; |
12a1fadb4 perf probe: Renam... |
122 123 124 |
if (!params.dellist) params.dellist = strlist__new(true, NULL); strlist__add(params.dellist, str); |
fa28244d1 perf probe: Suppo... |
125 126 127 |
} return 0; } |
4b4da7f76 perf probe: Clean... |
128 |
#ifdef DWARF_SUPPORT |
0eda7385d perf probe: Fix b... |
129 130 131 |
static int opt_show_lines(const struct option *opt __used, const char *str, int unset __used) { |
146a14394 perf probe: Remov... |
132 |
int ret = 0; |
13e27d768 perf probe: Warn ... |
133 134 135 136 137 138 139 140 141 |
if (!str) return 0; if (params.show_lines) { pr_warning("Warning: more than one --line options are" " detected. Only the first one is valid. "); return 0; } |
12a1fadb4 perf probe: Renam... |
142 |
params.show_lines = true; |
13e27d768 perf probe: Warn ... |
143 144 |
ret = parse_line_range_desc(str, ¶ms.line_range); INIT_LIST_HEAD(¶ms.line_range.line_list); |
146a14394 perf probe: Remov... |
145 146 |
return ret; |
0eda7385d perf probe: Fix b... |
147 |
} |
cf6eb489e perf probe: Show ... |
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
static int opt_show_vars(const struct option *opt __used, const char *str, int unset __used) { struct perf_probe_event *pev = ¶ms.events[params.nevents]; int ret; if (!str) return 0; ret = parse_probe_event(str); if (!ret && pev->nargs != 0) { pr_err(" Error: '--vars' doesn't accept arguments. "); return -EINVAL; } params.show_vars = true; return ret; } |
3c42258c9 perf probe: Add f... |
168 |
#endif |
bd09d7b5e perf probe: Add v... |
169 170 171 172 173 174 175 176 177 178 179 180 181 |
static int opt_set_filter(const struct option *opt __used, const char *str, int unset __used) { const char *err; if (str) { pr_debug2("Set filter: %s ", str); if (params.filter) strfilter__delete(params.filter); params.filter = strfilter__new(str, &err); if (!params.filter) { |
823c7164a perf probe: Use %... |
182 183 |
pr_err("Filter parse error at %td. ", err - str + 1); |
bd09d7b5e perf probe: Add v... |
184 185 186 187 188 189 190 191 192 193 |
pr_err("Source: \"%s\" ", str); pr_err(" %*c ", (int)(err - str + 1), '^'); return -EINVAL; } } return 0; } |
4ea42b181 perf: Add perf pr... |
194 195 |
static const char * const probe_usage[] = { |
46ab49267 perf/probes: Impr... |
196 197 |
"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", |
fa28244d1 perf probe: Suppo... |
198 |
"perf probe [<options>] --del '[GROUP:]EVENT' ...", |
4de189fe6 perf probe: Add -... |
199 |
"perf probe --list", |
4b4da7f76 perf probe: Clean... |
200 |
#ifdef DWARF_SUPPORT |
469b9b884 perf probe: Add b... |
201 202 |
"perf probe [<options>] --line 'LINEDESC'", "perf probe [<options>] --vars 'PROBEPOINT'", |
f3ab481ca perf probe: Do no... |
203 |
#endif |
4ea42b181 perf: Add perf pr... |
204 205 206 207 |
NULL }; static const struct option options[] = { |
c05556421 perf: Fix endiann... |
208 |
OPT_INCR('v', "verbose", &verbose, |
89c69c0ee perf: Use eprintf... |
209 |
"be more verbose (show parsed arguments, etc)"), |
12a1fadb4 perf probe: Renam... |
210 |
OPT_BOOLEAN('l', "list", ¶ms.list_events, |
fac13fd54 perf probe: Clean... |
211 |
"list up current probe events"), |
fa28244d1 perf probe: Suppo... |
212 213 |
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", opt_del_probe_event), |
46ab49267 perf/probes: Impr... |
214 |
OPT_CALLBACK('a', "add", NULL, |
4b4da7f76 perf probe: Clean... |
215 |
#ifdef DWARF_SUPPORT |
32cb0dd50 perf probe: Corre... |
216 |
"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" |
48481938b perf probe: Suppo... |
217 |
" [[NAME=]ARG ...]", |
4b4da7f76 perf probe: Clean... |
218 |
#else |
48481938b perf probe: Suppo... |
219 |
"[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]", |
23e8ec0d1 perf probe: Add p... |
220 |
#endif |
4ea42b181 perf: Add perf pr... |
221 222 |
"probe point definition, where " |
af663d75a perf probe: Suppo... |
223 224 225 226 |
"\t\tGROUP:\tGroup name (optional) " "\t\tEVENT:\tEvent name " |
4ea42b181 perf: Add perf pr... |
227 228 |
"\t\tFUNC:\tFunction name " |
2a9c8c360 perf probe: Add l... |
229 230 |
"\t\tOFF:\tOffset from function entry (in byte) " |
253977b0d perf/probes: Impr... |
231 232 |
"\t\t%return:\tPut the probe at function return " |
4b4da7f76 perf probe: Clean... |
233 |
#ifdef DWARF_SUPPORT |
4ea42b181 perf: Add perf pr... |
234 235 |
"\t\tSRC:\tSource code path " |
2a9c8c360 perf probe: Add l... |
236 237 238 239 240 241 |
"\t\tRL:\tRelative line number from function entry. " "\t\tAL:\tAbsolute line number in file. " "\t\tPT:\tLazy expression of line code. " |
4ea42b181 perf: Add perf pr... |
242 243 |
"\t\tARG:\tProbe argument (local variable name or " |
50656eec8 perf probe: Move ... |
244 245 |
"\t\t\tkprobe-tracer argument format.) ", |
4b4da7f76 perf probe: Clean... |
246 247 248 249 |
#else "\t\tARG:\tProbe argument (kprobe-tracer argument format.) ", #endif |
253977b0d perf/probes: Impr... |
250 |
opt_add_probe_event), |
12a1fadb4 perf probe: Renam... |
251 |
OPT_BOOLEAN('f', "force", ¶ms.force_add, "forcibly add events" |
d761b08bf perf probe: Rejec... |
252 |
" with existing name"), |
4b4da7f76 perf probe: Clean... |
253 |
#ifdef DWARF_SUPPORT |
631c9def8 perf probe: Suppo... |
254 |
OPT_CALLBACK('L', "line", NULL, |
085ea739a perf probe: Fix -... |
255 |
"FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", |
631c9def8 perf probe: Suppo... |
256 |
"Show source code lines.", opt_show_lines), |
cf6eb489e perf probe: Show ... |
257 258 259 |
OPT_CALLBACK('V', "vars", NULL, "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", "Show accessible variables on PROBEDEF", opt_show_vars), |
fb8c5a56c perf probe: Show ... |
260 261 |
OPT_BOOLEAN('\0', "externs", ¶ms.show_ext_vars, "Show external variables too (with --vars only)"), |
4b4da7f76 perf probe: Clean... |
262 263 |
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), |
9ed7e1b85 perf probe: Add k... |
264 265 |
OPT_STRING('s', "source", &symbol_conf.source_prefix, "directory", "path to kernel source"), |
469b9b884 perf probe: Add b... |
266 |
OPT_STRING('m', "module", ¶ms.target_module, |
14a8fd7ce perf probe: Suppo... |
267 268 |
"modname|path", "target module name (for online) or path (for offline)"), |
631c9def8 perf probe: Suppo... |
269 |
#endif |
f4d7da499 perf probe: Add -... |
270 |
OPT__DRY_RUN(&probe_event_dry_run), |
ef4a35657 perf probe: Add -... |
271 272 |
OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, "Set how many probe points can be found for a probe."), |
e80711ca8 perf probe: Add -... |
273 274 |
OPT_BOOLEAN('F', "funcs", ¶ms.show_funcs, "Show potential probe-able functions."), |
3c42258c9 perf probe: Add f... |
275 276 277 278 279 280 281 |
OPT_CALLBACK('\0', "filter", NULL, "[!]FILTER", "Set a filter (with --vars/funcs only) " "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars, " "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", opt_set_filter), |
4ea42b181 perf: Add perf pr... |
282 283 |
OPT_END() }; |
4ea42b181 perf: Add perf pr... |
284 285 |
int cmd_probe(int argc, const char **argv, const char *prefix __used) { |
146a14394 perf probe: Remov... |
286 |
int ret; |
4ea42b181 perf: Add perf pr... |
287 |
argc = parse_options(argc, argv, options, probe_usage, |
46ab49267 perf/probes: Impr... |
288 |
PARSE_OPT_STOP_AT_NON_OPTION); |
ce11a603a perf probe: Check... |
289 290 291 292 293 294 |
if (argc > 0) { if (strcmp(argv[0], "-") == 0) { pr_warning(" Error: '-' is not supported. "); usage_with_options(probe_usage, options); } |
146a14394 perf probe: Remov... |
295 296 297 298 299 300 |
ret = parse_probe_event_argv(argc, argv); if (ret < 0) { pr_err(" Error: Parse Error. (%d) ", ret); return ret; } |
ce11a603a perf probe: Check... |
301 |
} |
46ab49267 perf/probes: Impr... |
302 |
|
ef4a35657 perf probe: Add -... |
303 304 |
if (params.max_probe_points == 0) params.max_probe_points = MAX_PROBES; |
4235b0454 perf probe: Intro... |
305 |
if ((!params.nevents && !params.dellist && !params.list_events && |
e80711ca8 perf probe: Add -... |
306 |
!params.show_lines && !params.show_funcs)) |
4ea42b181 perf: Add perf pr... |
307 |
usage_with_options(probe_usage, options); |
fd930ff91 perf probe: Fix u... |
308 309 310 311 |
/* * Only consider the user's kernel image path if given. */ symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); |
12a1fadb4 perf probe: Renam... |
312 |
if (params.list_events) { |
cf6eb489e perf probe: Show ... |
313 |
if (params.mod_events) { |
146a14394 perf probe: Remov... |
314 315 |
pr_err(" Error: Don't use --list with --add/--del. "); |
fa28244d1 perf probe: Suppo... |
316 317 |
usage_with_options(probe_usage, options); } |
12a1fadb4 perf probe: Renam... |
318 |
if (params.show_lines) { |
146a14394 perf probe: Remov... |
319 320 |
pr_err(" Error: Don't use --list with --line. "); |
631c9def8 perf probe: Suppo... |
321 322 |
usage_with_options(probe_usage, options); } |
cf6eb489e perf probe: Show ... |
323 324 325 326 327 |
if (params.show_vars) { pr_err(" Error: Don't use --list with --vars. "); usage_with_options(probe_usage, options); } |
e80711ca8 perf probe: Add -... |
328 329 330 331 332 |
if (params.show_funcs) { pr_err(" Error: Don't use --list with --funcs. "); usage_with_options(probe_usage, options); } |
146a14394 perf probe: Remov... |
333 334 335 336 337 338 |
ret = show_perf_probe_events(); if (ret < 0) pr_err(" Error: Failed to show event list. (%d) ", ret); return ret; |
4de189fe6 perf probe: Add -... |
339 |
} |
e80711ca8 perf probe: Add -... |
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
if (params.show_funcs) { if (params.nevents != 0 || params.dellist) { pr_err(" Error: Don't use --funcs with" " --add/--del. "); usage_with_options(probe_usage, options); } if (params.show_lines) { pr_err(" Error: Don't use --funcs with --line. "); usage_with_options(probe_usage, options); } if (params.show_vars) { pr_err(" Error: Don't use --funcs with --vars. "); usage_with_options(probe_usage, options); } |
3c42258c9 perf probe: Add f... |
357 358 359 360 361 362 |
if (!params.filter) params.filter = strfilter__new(DEFAULT_FUNC_FILTER, NULL); ret = show_available_funcs(params.target_module, params.filter); strfilter__delete(params.filter); |
e80711ca8 perf probe: Add -... |
363 364 365 366 367 368 |
if (ret < 0) pr_err(" Error: Failed to show functions." " (%d) ", ret); return ret; } |
4de189fe6 perf probe: Add -... |
369 |
|
4b4da7f76 perf probe: Clean... |
370 |
#ifdef DWARF_SUPPORT |
12a1fadb4 perf probe: Renam... |
371 |
if (params.show_lines) { |
cf6eb489e perf probe: Show ... |
372 373 374 375 376 377 378 379 380 |
if (params.mod_events) { pr_err(" Error: Don't use --line with" " --add/--del. "); usage_with_options(probe_usage, options); } if (params.show_vars) { pr_err(" Error: Don't use --line with --vars. "); |
631c9def8 perf probe: Suppo... |
381 382 |
usage_with_options(probe_usage, options); } |
e0faa8d35 perf probe: Move ... |
383 |
|
469b9b884 perf probe: Add b... |
384 |
ret = show_line_range(¶ms.line_range, params.target_module); |
146a14394 perf probe: Remov... |
385 386 387 388 |
if (ret < 0) pr_err(" Error: Failed to show lines. (%d) ", ret); return ret; |
631c9def8 perf probe: Suppo... |
389 |
} |
cf6eb489e perf probe: Show ... |
390 391 392 393 394 395 396 |
if (params.show_vars) { if (params.mod_events) { pr_err(" Error: Don't use --vars with" " --add/--del. "); usage_with_options(probe_usage, options); } |
bd09d7b5e perf probe: Add v... |
397 398 399 |
if (!params.filter) params.filter = strfilter__new(DEFAULT_VAR_FILTER, NULL); |
cf6eb489e perf probe: Show ... |
400 |
ret = show_available_vars(params.events, params.nevents, |
fb8c5a56c perf probe: Show ... |
401 |
params.max_probe_points, |
469b9b884 perf probe: Add b... |
402 |
params.target_module, |
bd09d7b5e perf probe: Add v... |
403 |
params.filter, |
fb8c5a56c perf probe: Show ... |
404 |
params.show_ext_vars); |
bd09d7b5e perf probe: Add v... |
405 |
strfilter__delete(params.filter); |
cf6eb489e perf probe: Show ... |
406 407 408 409 410 |
if (ret < 0) pr_err(" Error: Failed to show vars. (%d) ", ret); return ret; } |
631c9def8 perf probe: Suppo... |
411 |
#endif |
12a1fadb4 perf probe: Renam... |
412 |
if (params.dellist) { |
146a14394 perf probe: Remov... |
413 |
ret = del_perf_probe_events(params.dellist); |
12a1fadb4 perf probe: Renam... |
414 |
strlist__delete(params.dellist); |
146a14394 perf probe: Remov... |
415 416 417 418 419 |
if (ret < 0) { pr_err(" Error: Failed to delete events. (%d) ", ret); return ret; } |
fa28244d1 perf probe: Suppo... |
420 |
} |
146a14394 perf probe: Remov... |
421 422 |
if (params.nevents) { ret = add_perf_probe_events(params.events, params.nevents, |
c82ec0a2b perf probe: Funct... |
423 |
params.max_probe_points, |
469b9b884 perf probe: Add b... |
424 |
params.target_module, |
c82ec0a2b perf probe: Funct... |
425 |
params.force_add); |
146a14394 perf probe: Remov... |
426 427 428 429 430 431 |
if (ret < 0) { pr_err(" Error: Failed to add events. (%d) ", ret); return ret; } } |
4ea42b181 perf: Add perf pr... |
432 433 |
return 0; } |