diff options
Diffstat (limited to 'tools/perf/util/hist.c')
-rw-r--r-- | tools/perf/util/hist.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 9a71c94f057a..cbf7eae2ce09 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "util.h" | 1 | #include "util.h" |
2 | #include "build-id.h" | ||
2 | #include "hist.h" | 3 | #include "hist.h" |
3 | #include "session.h" | 4 | #include "session.h" |
4 | #include "sort.h" | 5 | #include "sort.h" |
@@ -988,22 +989,42 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) | |||
988 | struct symbol *sym = self->ms.sym; | 989 | struct symbol *sym = self->ms.sym; |
989 | struct map *map = self->ms.map; | 990 | struct map *map = self->ms.map; |
990 | struct dso *dso = map->dso; | 991 | struct dso *dso = map->dso; |
991 | const char *filename = dso->long_name; | 992 | char *filename = dso__build_id_filename(dso, NULL, 0); |
993 | bool free_filename = true; | ||
992 | char command[PATH_MAX * 2]; | 994 | char command[PATH_MAX * 2]; |
993 | FILE *file; | 995 | FILE *file; |
996 | int err = 0; | ||
994 | u64 len; | 997 | u64 len; |
995 | 998 | ||
996 | if (!filename) | 999 | if (filename == NULL) { |
997 | return -1; | 1000 | if (dso->has_build_id) { |
1001 | pr_err("Can't annotate %s: not enough memory\n", | ||
1002 | sym->name); | ||
1003 | return -ENOMEM; | ||
1004 | } | ||
1005 | goto fallback; | ||
1006 | } else if (readlink(filename, command, sizeof(command)) < 0 || | ||
1007 | strstr(command, "[kernel.kallsyms]") || | ||
1008 | access(filename, R_OK)) { | ||
1009 | free(filename); | ||
1010 | fallback: | ||
1011 | /* | ||
1012 | * If we don't have build-ids or the build-id file isn't in the | ||
1013 | * cache, or is just a kallsyms file, well, lets hope that this | ||
1014 | * DSO is the same as when 'perf record' ran. | ||
1015 | */ | ||
1016 | filename = dso->long_name; | ||
1017 | free_filename = false; | ||
1018 | } | ||
998 | 1019 | ||
999 | if (dso->origin == DSO__ORIG_KERNEL) { | 1020 | if (dso->origin == DSO__ORIG_KERNEL) { |
1000 | if (dso->annotate_warned) | 1021 | if (dso->annotate_warned) |
1001 | return 0; | 1022 | goto out_free_filename; |
1023 | err = -ENOENT; | ||
1002 | dso->annotate_warned = 1; | 1024 | dso->annotate_warned = 1; |
1003 | pr_err("Can't annotate %s: No vmlinux file was found in the " | 1025 | pr_err("Can't annotate %s: No vmlinux file was found in the " |
1004 | "path:\n", sym->name); | 1026 | "path\n", sym->name); |
1005 | vmlinux_path__fprintf(stderr); | 1027 | goto out_free_filename; |
1006 | return -1; | ||
1007 | } | 1028 | } |
1008 | 1029 | ||
1009 | pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, | 1030 | pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, |
@@ -1025,14 +1046,17 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) | |||
1025 | 1046 | ||
1026 | file = popen(command, "r"); | 1047 | file = popen(command, "r"); |
1027 | if (!file) | 1048 | if (!file) |
1028 | return -1; | 1049 | goto out_free_filename; |
1029 | 1050 | ||
1030 | while (!feof(file)) | 1051 | while (!feof(file)) |
1031 | if (hist_entry__parse_objdump_line(self, file, head) < 0) | 1052 | if (hist_entry__parse_objdump_line(self, file, head) < 0) |
1032 | break; | 1053 | break; |
1033 | 1054 | ||
1034 | pclose(file); | 1055 | pclose(file); |
1035 | return 0; | 1056 | out_free_filename: |
1057 | if (free_filename) | ||
1058 | free(filename); | ||
1059 | return err; | ||
1036 | } | 1060 | } |
1037 | 1061 | ||
1038 | void hists__inc_nr_events(struct hists *self, u32 type) | 1062 | void hists__inc_nr_events(struct hists *self, u32 type) |