perf probe: Add kernel source path option
authorChase Douglas <chase.douglas@canonical.com>
Mon, 14 Jun 2010 19:26:30 +0000 (15:26 -0400)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 17 Jun 2010 13:27:57 +0000 (10:27 -0300)
The probe plugin requires access to the source code for some operations.  The
source code must be in the exact same location as specified by the DWARF tags,
but sometimes the location is an absolute path that cannot be replicated by a
normal user. This change adds the -s|--source option to allow the user to
specify the root of the kernel source tree.

Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
LKML-Reference: <1276543590-10486-1-git-send-email-chase.douglas@canonical.com>
Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/Documentation/perf-probe.txt
tools/perf/builtin-probe.c
tools/perf/util/probe-finder.c
tools/perf/util/symbol.h

index 94a258c96a440b091616264fb2a7d0fd8b515967..ea531d9d975ce23f6f75d8ca61bf7fc38c3915ea 100644 (file)
@@ -31,6 +31,10 @@ OPTIONS
 --vmlinux=PATH::
        Specify vmlinux path which has debuginfo (Dwarf binary).
 
+-s::
+--source=PATH::
+       Specify path to kernel source.
+
 -v::
 --verbose::
         Be more verbose (show parsed arguments, etc).
index e4a4da32a56864a7c1d95ec44a5b603f4f541e92..54551867e7e086234fc525afe790789800cdaece 100644 (file)
@@ -182,6 +182,8 @@ static const struct option options[] = {
                     "Show source code lines.", opt_show_lines),
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
                   "file", "vmlinux pathname"),
+       OPT_STRING('s', "source", &symbol_conf.source_prefix,
+                  "directory", "path to kernel source"),
 #endif
        OPT__DRY_RUN(&probe_event_dry_run),
        OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
index d964cb199c672f96712c4125ba036b7bfe038687..baf665383498ec54042edee05ea7783c3398967f 100644 (file)
@@ -37,6 +37,7 @@
 #include "event.h"
 #include "debug.h"
 #include "util.h"
+#include "symbol.h"
 #include "probe-finder.h"
 
 /* Kprobe tracer basic type is up to u64 */
@@ -57,6 +58,55 @@ static int strtailcmp(const char *s1, const char *s2)
        return 0;
 }
 
+/*
+ * Find a src file from a DWARF tag path. Prepend optional source path prefix
+ * and chop off leading directories that do not exist. Result is passed back as
+ * a newly allocated path on success.
+ * Return 0 if file was found and readable, -errno otherwise.
+ */
+static int get_real_path(const char *raw_path, char **new_path)
+{
+       if (!symbol_conf.source_prefix) {
+               if (access(raw_path, R_OK) == 0) {
+                       *new_path = strdup(raw_path);
+                       return 0;
+               } else
+                       return -errno;
+       }
+
+       *new_path = malloc((strlen(symbol_conf.source_prefix) +
+                           strlen(raw_path) + 2));
+       if (!*new_path)
+               return -ENOMEM;
+
+       for (;;) {
+               sprintf(*new_path, "%s/%s", symbol_conf.source_prefix,
+                       raw_path);
+
+               if (access(*new_path, R_OK) == 0)
+                       return 0;
+
+               switch (errno) {
+               case ENAMETOOLONG:
+               case ENOENT:
+               case EROFS:
+               case EFAULT:
+                       raw_path = strchr(++raw_path, '/');
+                       if (!raw_path) {
+                               free(*new_path);
+                               *new_path = NULL;
+                               return -ENOENT;
+                       }
+                       continue;
+
+               default:
+                       free(*new_path);
+                       *new_path = NULL;
+                       return -errno;
+               }
+       }
+}
+
 /* Line number list operations */
 
 /* Add a line to line number list */
@@ -1096,11 +1146,13 @@ end:
 static int line_range_add_line(const char *src, unsigned int lineno,
                               struct line_range *lr)
 {
+       int ret;
+
        /* Copy real path */
        if (!lr->path) {
-               lr->path = strdup(src);
-               if (lr->path == NULL)
-                       return -ENOMEM;
+               ret = get_real_path(src, &lr->path);
+               if (ret != 0)
+                       return ret;
        }
        return line_list__add_line(&lr->line_list, lineno);
 }
index 10b7ff859ce03b4d60b49f19c174584101cf92e9..80e569bbdecc4bd0ea37a7898035b9c52d0c0793 100644 (file)
@@ -71,6 +71,7 @@ struct symbol_conf {
                        full_paths,
                        show_cpu_utilization;
        const char      *vmlinux_name,
+                       *source_prefix,
                        *field_sep;
        const char      *default_guest_vmlinux_name,
                        *default_guest_kallsyms,