aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-10-07 18:28:30 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-10-12 17:31:53 -0400
commit23e8ec0d1c410f2f1d81050ee155db229abb1707 (patch)
tree309462a3591f3239741373a413482abb03e49145
parent4ea42b181434bfc6a0a18d32214130a242d489bf (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>
-rw-r--r--tools/perf/Makefile6
-rw-r--r--tools/perf/builtin-probe.c42
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/util/probe-finder.h2
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
385BUILTIN_OBJS += builtin-timechart.o 385BUILTIN_OBJS += builtin-timechart.o
386BUILTIN_OBJS += builtin-top.o 386BUILTIN_OBJS += builtin-top.o
387BUILTIN_OBJS += builtin-trace.o 387BUILTIN_OBJS += builtin-trace.o
388BUILTIN_OBJS += builtin-probe.o
388 389
389PERFLIBS = $(LIB_FILE) 390PERFLIBS = $(LIB_FILE)
390 391
@@ -420,13 +421,12 @@ ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf *
420endif 421endif
421 422
422ifneq ($(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) 423ifneq ($(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
424else 426else
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
430endif 430endif
431 431
432ifdef NO_DEMANGLE 432ifdef 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] = {
54static struct { 54static 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
185static int open_default_vmlinux(void) 192static 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
213static const char * const probe_usage[] = { 221static 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
218static const struct option options[] = { 226static 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
280int cmd_probe(int argc, const char **argv, const char *prefix __used) 298int 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
334setup_probes: 360setup_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
47extern int find_probepoint(int fd, struct probe_point *pp); 48extern 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 */