diff options
author | Naohiro Aota <naota@elisp.net> | 2015-03-13 01:18:40 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-04-13 19:11:05 -0400 |
commit | 09ed8975c4b13be4469899b210f0e0936021ee8f (patch) | |
tree | a43f72cd4225a93992fcaf7e0f670e4ead95826c /tools/perf/util/probe-finder.c | |
parent | 9d7b45c5721dfd524666bc1f07cf7d0855edb4d5 (diff) |
perf probe: Find compilation directory path for lazy matching
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>
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r-- | tools/perf/util/probe-finder.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 7831e2d93949..ff7865ca3ca3 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -855,11 +855,22 @@ static int probe_point_lazy_walker(const char *fname, int lineno, | |||
855 | static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) | 855 | static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) |
856 | { | 856 | { |
857 | int ret = 0; | 857 | int ret = 0; |
858 | char *fpath; | ||
858 | 859 | ||
859 | if (intlist__empty(pf->lcache)) { | 860 | if (intlist__empty(pf->lcache)) { |
861 | const char *comp_dir; | ||
862 | |||
863 | comp_dir = cu_get_comp_dir(&pf->cu_die); | ||
864 | ret = get_real_path(pf->fname, comp_dir, &fpath); | ||
865 | if (ret < 0) { | ||
866 | pr_warning("Failed to find source file path.\n"); | ||
867 | return ret; | ||
868 | } | ||
869 | |||
860 | /* Matching lazy line pattern */ | 870 | /* Matching lazy line pattern */ |
861 | ret = find_lazy_match_lines(pf->lcache, pf->fname, | 871 | ret = find_lazy_match_lines(pf->lcache, fpath, |
862 | pf->pev->point.lazy_line); | 872 | pf->pev->point.lazy_line); |
873 | free(fpath); | ||
863 | if (ret <= 0) | 874 | if (ret <= 0) |
864 | return ret; | 875 | return ret; |
865 | } | 876 | } |
@@ -1622,3 +1633,61 @@ found: | |||
1622 | return (ret < 0) ? ret : lf.found; | 1633 | return (ret < 0) ? ret : lf.found; |
1623 | } | 1634 | } |
1624 | 1635 | ||
1636 | /* | ||
1637 | * Find a src file from a DWARF tag path. Prepend optional source path prefix | ||
1638 | * and chop off leading directories that do not exist. Result is passed back as | ||
1639 | * a newly allocated path on success. | ||
1640 | * Return 0 if file was found and readable, -errno otherwise. | ||
1641 | */ | ||
1642 | int get_real_path(const char *raw_path, const char *comp_dir, | ||
1643 | char **new_path) | ||
1644 | { | ||
1645 | const char *prefix = symbol_conf.source_prefix; | ||
1646 | |||
1647 | if (!prefix) { | ||
1648 | if (raw_path[0] != '/' && comp_dir) | ||
1649 | /* If not an absolute path, try to use comp_dir */ | ||
1650 | prefix = comp_dir; | ||
1651 | else { | ||
1652 | if (access(raw_path, R_OK) == 0) { | ||
1653 | *new_path = strdup(raw_path); | ||
1654 | return *new_path ? 0 : -ENOMEM; | ||
1655 | } else | ||
1656 | return -errno; | ||
1657 | } | ||
1658 | } | ||
1659 | |||
1660 | *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); | ||
1661 | if (!*new_path) | ||
1662 | return -ENOMEM; | ||
1663 | |||
1664 | for (;;) { | ||
1665 | sprintf(*new_path, "%s/%s", prefix, raw_path); | ||
1666 | |||
1667 | if (access(*new_path, R_OK) == 0) | ||
1668 | return 0; | ||
1669 | |||
1670 | if (!symbol_conf.source_prefix) { | ||
1671 | /* In case of searching comp_dir, don't retry */ | ||
1672 | zfree(new_path); | ||
1673 | return -errno; | ||
1674 | } | ||
1675 | |||
1676 | switch (errno) { | ||
1677 | case ENAMETOOLONG: | ||
1678 | case ENOENT: | ||
1679 | case EROFS: | ||
1680 | case EFAULT: | ||
1681 | raw_path = strchr(++raw_path, '/'); | ||
1682 | if (!raw_path) { | ||
1683 | zfree(new_path); | ||
1684 | return -ENOENT; | ||
1685 | } | ||
1686 | continue; | ||
1687 | |||
1688 | default: | ||
1689 | zfree(new_path); | ||
1690 | return -errno; | ||
1691 | } | ||
1692 | } | ||
1693 | } | ||