diff options
author | Srikar Dronamraju <srikar@linux.vnet.ibm.com> | 2012-04-16 08:09:09 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-05-11 12:58:17 -0400 |
commit | 225466f1c2d816c33b4341008f45dfdc83a9f0cb (patch) | |
tree | 72cd2adf96464922e64fc86dc76bf321f426bbf1 /tools/perf/builtin-probe.c | |
parent | 5dcefda0fd87fefa440abc9b9d3f1089229f8911 (diff) |
perf probe: Provide perf interface for uprobes
- Enhances perf to probe user space executables and libraries.
- Enhances -F/--funcs option of "perf probe" to list possible probe points in
an executable file or library.
- Documents userspace probing support in perf.
[ Probing a function in the executable using function name ]
perf probe -x /bin/zsh zfree
[ Probing a library function using function name ]
perf probe -x /lib64/libc.so.6 malloc
[ list probe-able functions in an executable ]
perf probe -F -x /bin/zsh
[ list probe-able functions in an library]
perf probe -F -x /lib/libc.so.6
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Anton Arapov <anton@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jim Keniston <jkenisto@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Linux-mm <linux-mm@kvack.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120416120909.30661.99781.sendpatchset@srdronam.in.ibm.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 | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 4935c09dd5b5..ee3d84a7c895 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -54,6 +54,7 @@ static struct { | |||
54 | bool show_ext_vars; | 54 | bool show_ext_vars; |
55 | bool show_funcs; | 55 | bool show_funcs; |
56 | bool mod_events; | 56 | bool mod_events; |
57 | bool uprobes; | ||
57 | int nevents; | 58 | int nevents; |
58 | struct perf_probe_event events[MAX_PROBES]; | 59 | struct perf_probe_event events[MAX_PROBES]; |
59 | struct strlist *dellist; | 60 | struct strlist *dellist; |
@@ -75,6 +76,8 @@ static int parse_probe_event(const char *str) | |||
75 | return -1; | 76 | return -1; |
76 | } | 77 | } |
77 | 78 | ||
79 | pev->uprobes = params.uprobes; | ||
80 | |||
78 | /* Parse a perf-probe command into event */ | 81 | /* Parse a perf-probe command into event */ |
79 | ret = parse_perf_probe_command(str, pev); | 82 | ret = parse_perf_probe_command(str, pev); |
80 | pr_debug("%d arguments\n", pev->nargs); | 83 | pr_debug("%d arguments\n", pev->nargs); |
@@ -125,6 +128,28 @@ static int opt_del_probe_event(const struct option *opt __used, | |||
125 | return 0; | 128 | return 0; |
126 | } | 129 | } |
127 | 130 | ||
131 | static int opt_set_target(const struct option *opt, const char *str, | ||
132 | int unset __used) | ||
133 | { | ||
134 | int ret = -ENOENT; | ||
135 | |||
136 | if (str && !params.target) { | ||
137 | if (!strcmp(opt->long_name, "exec")) | ||
138 | params.uprobes = true; | ||
139 | #ifdef DWARF_SUPPORT | ||
140 | else if (!strcmp(opt->long_name, "module")) | ||
141 | params.uprobes = false; | ||
142 | #endif | ||
143 | else | ||
144 | return ret; | ||
145 | |||
146 | params.target = str; | ||
147 | ret = 0; | ||
148 | } | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
128 | #ifdef DWARF_SUPPORT | 153 | #ifdef DWARF_SUPPORT |
129 | static int opt_show_lines(const struct option *opt __used, | 154 | static int opt_show_lines(const struct option *opt __used, |
130 | const char *str, int unset __used) | 155 | const char *str, int unset __used) |
@@ -246,9 +271,9 @@ static const struct option options[] = { | |||
246 | "file", "vmlinux pathname"), | 271 | "file", "vmlinux pathname"), |
247 | OPT_STRING('s', "source", &symbol_conf.source_prefix, | 272 | OPT_STRING('s', "source", &symbol_conf.source_prefix, |
248 | "directory", "path to kernel source"), | 273 | "directory", "path to kernel source"), |
249 | OPT_STRING('m', "module", ¶ms.target, | 274 | OPT_CALLBACK('m', "module", NULL, "modname|path", |
250 | "modname|path", | 275 | "target module name (for online) or path (for offline)", |
251 | "target module name (for online) or path (for offline)"), | 276 | opt_set_target), |
252 | #endif | 277 | #endif |
253 | OPT__DRY_RUN(&probe_event_dry_run), | 278 | OPT__DRY_RUN(&probe_event_dry_run), |
254 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, | 279 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, |
@@ -260,6 +285,8 @@ static const struct option options[] = { | |||
260 | "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" | 285 | "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" |
261 | "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", | 286 | "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", |
262 | opt_set_filter), | 287 | opt_set_filter), |
288 | OPT_CALLBACK('x', "exec", NULL, "executable|path", | ||
289 | "target executable name or path", opt_set_target), | ||
263 | OPT_END() | 290 | OPT_END() |
264 | }; | 291 | }; |
265 | 292 | ||
@@ -310,6 +337,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
310 | pr_err(" Error: Don't use --list with --funcs.\n"); | 337 | pr_err(" Error: Don't use --list with --funcs.\n"); |
311 | usage_with_options(probe_usage, options); | 338 | usage_with_options(probe_usage, options); |
312 | } | 339 | } |
340 | if (params.uprobes) { | ||
341 | pr_warning(" Error: Don't use --list with --exec.\n"); | ||
342 | usage_with_options(probe_usage, options); | ||
343 | } | ||
313 | ret = show_perf_probe_events(); | 344 | ret = show_perf_probe_events(); |
314 | if (ret < 0) | 345 | if (ret < 0) |
315 | pr_err(" Error: Failed to show event list. (%d)\n", | 346 | pr_err(" Error: Failed to show event list. (%d)\n", |
@@ -333,8 +364,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
333 | if (!params.filter) | 364 | if (!params.filter) |
334 | params.filter = strfilter__new(DEFAULT_FUNC_FILTER, | 365 | params.filter = strfilter__new(DEFAULT_FUNC_FILTER, |
335 | NULL); | 366 | NULL); |
336 | ret = show_available_funcs(params.target, | 367 | ret = show_available_funcs(params.target, params.filter, |
337 | params.filter); | 368 | params.uprobes); |
338 | strfilter__delete(params.filter); | 369 | strfilter__delete(params.filter); |
339 | if (ret < 0) | 370 | if (ret < 0) |
340 | pr_err(" Error: Failed to show functions." | 371 | pr_err(" Error: Failed to show functions." |
@@ -343,7 +374,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
343 | } | 374 | } |
344 | 375 | ||
345 | #ifdef DWARF_SUPPORT | 376 | #ifdef DWARF_SUPPORT |
346 | if (params.show_lines) { | 377 | if (params.show_lines && !params.uprobes) { |
347 | if (params.mod_events) { | 378 | if (params.mod_events) { |
348 | pr_err(" Error: Don't use --line with" | 379 | pr_err(" Error: Don't use --line with" |
349 | " --add/--del.\n"); | 380 | " --add/--del.\n"); |