diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-10-07 18:28:30 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-10-12 17:31:53 -0400 |
commit | 23e8ec0d1c410f2f1d81050ee155db229abb1707 (patch) | |
tree | 309462a3591f3239741373a413482abb03e49145 /tools | |
parent | 4ea42b181434bfc6a0a18d32214130a242d489bf (diff) |
perf probe: Add perf probe command support without libdwarf
Enables 'perf probe' even if libdwarf is not installed. If libdwarf is
not found, 'perf probe' just disables dwarf support. Users can use
'perf probe' to set up new events by using kprobe_events format.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Frank Ch. Eigler <fche@redhat.com>
LKML-Reference: <20091007222830.1684.25665.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Makefile | 6 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 42 | ||||
-rw-r--r-- | tools/perf/perf.c | 2 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 2 |
4 files changed, 40 insertions, 12 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 6dabcf1a4df6..52b1f438e71a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -385,6 +385,7 @@ BUILTIN_OBJS += builtin-stat.o | |||
385 | BUILTIN_OBJS += builtin-timechart.o | 385 | BUILTIN_OBJS += builtin-timechart.o |
386 | BUILTIN_OBJS += builtin-top.o | 386 | BUILTIN_OBJS += builtin-top.o |
387 | BUILTIN_OBJS += builtin-trace.o | 387 | BUILTIN_OBJS += builtin-trace.o |
388 | BUILTIN_OBJS += builtin-probe.o | ||
388 | 389 | ||
389 | PERFLIBS = $(LIB_FILE) | 390 | PERFLIBS = $(LIB_FILE) |
390 | 391 | ||
@@ -420,13 +421,12 @@ ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * | |||
420 | endif | 421 | endif |
421 | 422 | ||
422 | ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y) | 423 | ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y) |
423 | msg := $(warning No libdwarf.h found, disables probe subcommand. Please install libdwarf-dev/libdwarf-devel); | 424 | msg := $(warning No libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel); |
425 | BASIC_CFLAGS += -DNO_LIBDWARF | ||
424 | else | 426 | else |
425 | EXTLIBS += -lelf -ldwarf | 427 | EXTLIBS += -lelf -ldwarf |
426 | LIB_H += util/probe-finder.h | 428 | LIB_H += util/probe-finder.h |
427 | LIB_OBJS += util/probe-finder.o | 429 | LIB_OBJS += util/probe-finder.o |
428 | BUILTIN_OBJS += builtin-probe.o | ||
429 | BASIC_CFLAGS += -DSUPPORT_DWARF | ||
430 | endif | 430 | endif |
431 | 431 | ||
432 | ifdef NO_DEMANGLE | 432 | ifdef NO_DEMANGLE |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 24b64b5cefce..73c883b715cc 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -54,6 +54,7 @@ const char *default_search_path[NR_SEARCH_PATH] = { | |||
54 | static struct { | 54 | static struct { |
55 | char *vmlinux; | 55 | char *vmlinux; |
56 | char *release; | 56 | char *release; |
57 | int need_dwarf; | ||
57 | int nr_probe; | 58 | int nr_probe; |
58 | struct probe_point probes[MAX_PROBES]; | 59 | struct probe_point probes[MAX_PROBES]; |
59 | char *events[MAX_PROBES]; | 60 | char *events[MAX_PROBES]; |
@@ -162,6 +163,8 @@ static int parse_probepoint(const struct option *opt __used, | |||
162 | pp->function, pp->file, pp->offset); | 163 | pp->function, pp->file, pp->offset); |
163 | } | 164 | } |
164 | free(argv[1]); | 165 | free(argv[1]); |
166 | if (pp->file) | ||
167 | session.need_dwarf = 1; | ||
165 | 168 | ||
166 | /* Copy arguments */ | 169 | /* Copy arguments */ |
167 | pp->nr_args = argc - 2; | 170 | pp->nr_args = argc - 2; |
@@ -173,15 +176,19 @@ static int parse_probepoint(const struct option *opt __used, | |||
173 | } | 176 | } |
174 | 177 | ||
175 | /* Ensure return probe has no C argument */ | 178 | /* Ensure return probe has no C argument */ |
176 | if (retp) | 179 | for (i = 0; i < pp->nr_args; i++) |
177 | for (i = 0; i < pp->nr_args; i++) | 180 | if (is_c_varname(pp->args[i])) { |
178 | if (is_c_varname(pp->args[i])) | 181 | if (retp) |
179 | semantic_error("You can't specify local" | 182 | semantic_error("You can't specify local" |
180 | " variable for kretprobe"); | 183 | " variable for kretprobe"); |
184 | session.need_dwarf = 1; | ||
185 | } | ||
186 | |||
181 | debug("%d arguments\n", pp->nr_args); | 187 | debug("%d arguments\n", pp->nr_args); |
182 | return 0; | 188 | return 0; |
183 | } | 189 | } |
184 | 190 | ||
191 | #ifndef NO_LIBDWARF | ||
185 | static int open_default_vmlinux(void) | 192 | static int open_default_vmlinux(void) |
186 | { | 193 | { |
187 | struct utsname uts; | 194 | struct utsname uts; |
@@ -209,6 +216,7 @@ static int open_default_vmlinux(void) | |||
209 | } | 216 | } |
210 | return fd; | 217 | return fd; |
211 | } | 218 | } |
219 | #endif | ||
212 | 220 | ||
213 | static const char * const probe_usage[] = { | 221 | static const char * const probe_usage[] = { |
214 | "perf probe [<options>] -P 'PROBEDEF' [-P 'PROBEDEF' ...]", | 222 | "perf probe [<options>] -P 'PROBEDEF' [-P 'PROBEDEF' ...]", |
@@ -216,10 +224,16 @@ static const char * const probe_usage[] = { | |||
216 | }; | 224 | }; |
217 | 225 | ||
218 | static const struct option options[] = { | 226 | static const struct option options[] = { |
227 | #ifndef NO_LIBDWARF | ||
219 | OPT_STRING('k', "vmlinux", &session.vmlinux, "file", | 228 | OPT_STRING('k', "vmlinux", &session.vmlinux, "file", |
220 | "vmlinux/module pathname"), | 229 | "vmlinux/module pathname"), |
230 | #endif | ||
221 | OPT_CALLBACK('P', "probe", NULL, | 231 | OPT_CALLBACK('P', "probe", NULL, |
232 | #ifdef NO_LIBDWARF | ||
233 | "p|r:[GRP/]NAME FUNC[+OFFS] [ARG ...]", | ||
234 | #else | ||
222 | "p|r:[GRP/]NAME FUNC[+OFFS][@SRC]|@SRC:LINE [ARG ...]", | 235 | "p|r:[GRP/]NAME FUNC[+OFFS][@SRC]|@SRC:LINE [ARG ...]", |
236 | #endif | ||
223 | "probe point definition, where\n" | 237 | "probe point definition, where\n" |
224 | "\t\tp:\tkprobe probe\n" | 238 | "\t\tp:\tkprobe probe\n" |
225 | "\t\tr:\tkretprobe probe\n" | 239 | "\t\tr:\tkretprobe probe\n" |
@@ -227,9 +241,13 @@ static const struct option options[] = { | |||
227 | "\t\tNAME:\tEvent name\n" | 241 | "\t\tNAME:\tEvent name\n" |
228 | "\t\tFUNC:\tFunction name\n" | 242 | "\t\tFUNC:\tFunction name\n" |
229 | "\t\tOFFS:\tOffset from function entry (in byte)\n" | 243 | "\t\tOFFS:\tOffset from function entry (in byte)\n" |
244 | #ifdef NO_LIBDWARF | ||
245 | "\t\tARG:\tProbe argument (only \n" | ||
246 | #else | ||
230 | "\t\tSRC:\tSource code path\n" | 247 | "\t\tSRC:\tSource code path\n" |
231 | "\t\tLINE:\tLine number\n" | 248 | "\t\tLINE:\tLine number\n" |
232 | "\t\tARG:\tProbe argument (local variable name or\n" | 249 | "\t\tARG:\tProbe argument (local variable name or\n" |
250 | #endif | ||
233 | "\t\t\tkprobe-tracer argument format is supported.)\n", | 251 | "\t\t\tkprobe-tracer argument format is supported.)\n", |
234 | parse_probepoint), | 252 | parse_probepoint), |
235 | OPT_END() | 253 | OPT_END() |
@@ -279,7 +297,7 @@ error: | |||
279 | 297 | ||
280 | int cmd_probe(int argc, const char **argv, const char *prefix __used) | 298 | int cmd_probe(int argc, const char **argv, const char *prefix __used) |
281 | { | 299 | { |
282 | int i, j, fd, ret, need_dwarf = 0; | 300 | int i, j, fd, ret; |
283 | struct probe_point *pp; | 301 | struct probe_point *pp; |
284 | char buf[MAX_CMDLEN]; | 302 | char buf[MAX_CMDLEN]; |
285 | 303 | ||
@@ -288,12 +306,19 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
288 | if (argc || session.nr_probe == 0) | 306 | if (argc || session.nr_probe == 0) |
289 | usage_with_options(probe_usage, options); | 307 | usage_with_options(probe_usage, options); |
290 | 308 | ||
291 | /* Synthesize return probes */ | 309 | #ifdef NO_LIBDWARF |
310 | if (session.need_dwarf) | ||
311 | semantic_error("Dwarf-analysis is not supported"); | ||
312 | #endif | ||
313 | |||
314 | /* Synthesize probes without dwarf */ | ||
292 | for (j = 0; j < session.nr_probe; j++) { | 315 | for (j = 0; j < session.nr_probe; j++) { |
316 | #ifndef NO_LIBDWARF | ||
293 | if (session.events[j][0] != 'r') { | 317 | if (session.events[j][0] != 'r') { |
294 | need_dwarf = 1; | 318 | session.need_dwarf = 1; |
295 | continue; | 319 | continue; |
296 | } | 320 | } |
321 | #endif | ||
297 | ret = synthesize_probepoint(&session.probes[j]); | 322 | ret = synthesize_probepoint(&session.probes[j]); |
298 | if (ret == -E2BIG) | 323 | if (ret == -E2BIG) |
299 | semantic_error("probe point is too long."); | 324 | semantic_error("probe point is too long."); |
@@ -303,7 +328,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
303 | } | 328 | } |
304 | } | 329 | } |
305 | 330 | ||
306 | if (!need_dwarf) | 331 | #ifndef NO_LIBDWARF |
332 | if (!session.need_dwarf) | ||
307 | goto setup_probes; | 333 | goto setup_probes; |
308 | 334 | ||
309 | if (session.vmlinux) | 335 | if (session.vmlinux) |
@@ -332,6 +358,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
332 | close(fd); | 358 | close(fd); |
333 | 359 | ||
334 | setup_probes: | 360 | setup_probes: |
361 | #endif /* !NO_LIBDWARF */ | ||
362 | |||
335 | /* Settng up probe points */ | 363 | /* Settng up probe points */ |
336 | snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path); | 364 | snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path); |
337 | fd = open(buf, O_WRONLY, O_APPEND); | 365 | fd = open(buf, O_WRONLY, O_APPEND); |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index f598120c0097..c570d177d5c6 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -295,9 +295,7 @@ static void handle_internal_command(int argc, const char **argv) | |||
295 | { "version", cmd_version, 0 }, | 295 | { "version", cmd_version, 0 }, |
296 | { "trace", cmd_trace, 0 }, | 296 | { "trace", cmd_trace, 0 }, |
297 | { "sched", cmd_sched, 0 }, | 297 | { "sched", cmd_sched, 0 }, |
298 | #ifdef SUPPORT_DWARF | ||
299 | { "probe", cmd_probe, 0 }, | 298 | { "probe", cmd_probe, 0 }, |
300 | #endif | ||
301 | }; | 299 | }; |
302 | unsigned int i; | 300 | unsigned int i; |
303 | static const char ext[] = STRIP_EXTENSION; | 301 | static const char ext[] = STRIP_EXTENSION; |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index af920de64866..306810c32f6b 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -44,6 +44,7 @@ struct probe_point { | |||
44 | char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ | 44 | char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #ifndef NO_LIBDWARF | ||
47 | extern int find_probepoint(int fd, struct probe_point *pp); | 48 | extern int find_probepoint(int fd, struct probe_point *pp); |
48 | 49 | ||
49 | #include <libdwarf/dwarf.h> | 50 | #include <libdwarf/dwarf.h> |
@@ -64,5 +65,6 @@ struct probe_finder { | |||
64 | char *buf; /* Current output buffer */ | 65 | char *buf; /* Current output buffer */ |
65 | int len; /* Length of output buffer */ | 66 | int len; /* Length of output buffer */ |
66 | }; | 67 | }; |
68 | #endif /* NO_LIBDWARF */ | ||
67 | 69 | ||
68 | #endif /*_PROBE_FINDER_H */ | 70 | #endif /*_PROBE_FINDER_H */ |