diff options
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r-- | tools/perf/util/probe-finder.c | 73 |
1 files changed, 71 insertions, 2 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e3074230f236..b5bf9d5efeaf 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 | } |
@@ -1055,7 +1066,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg, | |||
1055 | if (pp->function) | 1066 | if (pp->function) |
1056 | ret = find_probe_point_by_func(pf); | 1067 | ret = find_probe_point_by_func(pf); |
1057 | else if (pp->lazy_line) | 1068 | else if (pp->lazy_line) |
1058 | ret = find_probe_point_lazy(NULL, pf); | 1069 | ret = find_probe_point_lazy(&pf->cu_die, pf); |
1059 | else { | 1070 | else { |
1060 | pf->lno = pp->line; | 1071 | pf->lno = pp->line; |
1061 | ret = find_probe_point_by_line(pf); | 1072 | ret = find_probe_point_by_line(pf); |
@@ -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 | } | ||