diff options
-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 */ |