perf probe: Find compilation directory path for lazy matching
authorNaohiro Aota <naota@elisp.net>
Fri, 13 Mar 2015 05:18:40 +0000 (14:18 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 13 Apr 2015 23:11:05 +0000 (20:11 -0300)
If we use lazy matching, it failed to open a souce file if perf command
is invoked outside of compilation directory:

$ perf probe -a '__schedule;clear_*'
Failed to open kernel/sched/core.c: No such file or directory
  Error: Failed to add events. (-2)

OTOH, other commands like "probe -L" can solve the souce directory by
themselves. Let's make it possible for lazy matching too!

Signed-off-by: Naohiro Aota <naota@elisp.net>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1426223923-1493-1-git-send-email-naota@elisp.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h

index 5483d98236d387428d21d107662dc6b1ecd84267..d8bb616ff57c29b38c05ac134d35e88f646f42cd 100644 (file)
@@ -655,65 +655,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
        return ntevs;
 }
 
-/*
- * 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, const char *comp_dir,
-                        char **new_path)
-{
-       const char *prefix = symbol_conf.source_prefix;
-
-       if (!prefix) {
-               if (raw_path[0] != '/' && comp_dir)
-                       /* If not an absolute path, try to use comp_dir */
-                       prefix = comp_dir;
-               else {
-                       if (access(raw_path, R_OK) == 0) {
-                               *new_path = strdup(raw_path);
-                               return *new_path ? 0 : -ENOMEM;
-                       } else
-                               return -errno;
-               }
-       }
-
-       *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
-       if (!*new_path)
-               return -ENOMEM;
-
-       for (;;) {
-               sprintf(*new_path, "%s/%s", prefix, raw_path);
-
-               if (access(*new_path, R_OK) == 0)
-                       return 0;
-
-               if (!symbol_conf.source_prefix) {
-                       /* In case of searching comp_dir, don't retry */
-                       zfree(new_path);
-                       return -errno;
-               }
-
-               switch (errno) {
-               case ENAMETOOLONG:
-               case ENOENT:
-               case EROFS:
-               case EFAULT:
-                       raw_path = strchr(++raw_path, '/');
-                       if (!raw_path) {
-                               zfree(new_path);
-                               return -ENOENT;
-                       }
-                       continue;
-
-               default:
-                       zfree(new_path);
-                       return -errno;
-               }
-       }
-}
-
 #define LINEBUF_SIZE 256
 #define NR_ADDITIONAL_LINES 2
 
index 7831e2d939498fc2600bade0b513d06aed0d7d91..ff7865ca3ca3529a12a48ad175d5a18791bc7018 100644 (file)
@@ -855,11 +855,22 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
        int ret = 0;
+       char *fpath;
 
        if (intlist__empty(pf->lcache)) {
+               const char *comp_dir;
+
+               comp_dir = cu_get_comp_dir(&pf->cu_die);
+               ret = get_real_path(pf->fname, comp_dir, &fpath);
+               if (ret < 0) {
+                       pr_warning("Failed to find source file path.\n");
+                       return ret;
+               }
+
                /* Matching lazy line pattern */
-               ret = find_lazy_match_lines(pf->lcache, pf->fname,
+               ret = find_lazy_match_lines(pf->lcache, fpath,
                                            pf->pev->point.lazy_line);
+               free(fpath);
                if (ret <= 0)
                        return ret;
        }
@@ -1622,3 +1633,61 @@ found:
        return (ret < 0) ? ret : lf.found;
 }
 
+/*
+ * 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.
+ */
+int get_real_path(const char *raw_path, const char *comp_dir,
+                        char **new_path)
+{
+       const char *prefix = symbol_conf.source_prefix;
+
+       if (!prefix) {
+               if (raw_path[0] != '/' && comp_dir)
+                       /* If not an absolute path, try to use comp_dir */
+                       prefix = comp_dir;
+               else {
+                       if (access(raw_path, R_OK) == 0) {
+                               *new_path = strdup(raw_path);
+                               return *new_path ? 0 : -ENOMEM;
+                       } else
+                               return -errno;
+               }
+       }
+
+       *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
+       if (!*new_path)
+               return -ENOMEM;
+
+       for (;;) {
+               sprintf(*new_path, "%s/%s", prefix, raw_path);
+
+               if (access(*new_path, R_OK) == 0)
+                       return 0;
+
+               if (!symbol_conf.source_prefix) {
+                       /* In case of searching comp_dir, don't retry */
+                       zfree(new_path);
+                       return -errno;
+               }
+
+               switch (errno) {
+               case ENAMETOOLONG:
+               case ENOENT:
+               case EROFS:
+               case EFAULT:
+                       raw_path = strchr(++raw_path, '/');
+                       if (!raw_path) {
+                               zfree(new_path);
+                               return -ENOENT;
+                       }
+                       continue;
+
+               default:
+                       zfree(new_path);
+                       return -errno;
+               }
+       }
+}
index 92590b2c7e1ce650080652839e5506bf98d9093c..ebf8c8c814531ff4efaf5a7461c2ef6a7414df69 100644 (file)
@@ -55,6 +55,10 @@ extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
                                             struct variable_list **vls,
                                             int max_points, bool externs);
 
+/* Find a src file from a DWARF tag path */
+int get_real_path(const char *raw_path, const char *comp_dir,
+                        char **new_path);
+
 struct probe_finder {
        struct perf_probe_event *pev;           /* Target probe event */