diff options
Diffstat (limited to 'tools/perf/util/map.c')
-rw-r--r-- | tools/perf/util/map.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index c1c556825343..94ca95073c40 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -20,16 +20,27 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen) | |||
20 | return n; | 20 | return n; |
21 | } | 21 | } |
22 | 22 | ||
23 | struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen, | 23 | void map__init(struct map *self, u64 start, u64 end, u64 pgoff, |
24 | unsigned int sym_priv_size, symbol_filter_t filter) | 24 | struct dso *dso) |
25 | { | ||
26 | self->start = start; | ||
27 | self->end = end; | ||
28 | self->pgoff = pgoff; | ||
29 | self->dso = dso; | ||
30 | self->map_ip = map__map_ip; | ||
31 | self->unmap_ip = map__unmap_ip; | ||
32 | RB_CLEAR_NODE(&self->rb_node); | ||
33 | } | ||
34 | |||
35 | struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) | ||
25 | { | 36 | { |
26 | struct map *self = malloc(sizeof(*self)); | 37 | struct map *self = malloc(sizeof(*self)); |
27 | 38 | ||
28 | if (self != NULL) { | 39 | if (self != NULL) { |
29 | const char *filename = event->filename; | 40 | const char *filename = event->filename; |
30 | char newfilename[PATH_MAX]; | 41 | char newfilename[PATH_MAX]; |
42 | struct dso *dso; | ||
31 | int anon; | 43 | int anon; |
32 | bool new_dso; | ||
33 | 44 | ||
34 | if (cwd) { | 45 | if (cwd) { |
35 | int n = strcommon(filename, cwd, cwdlen); | 46 | int n = strcommon(filename, cwd, cwdlen); |
@@ -48,33 +59,15 @@ struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen, | |||
48 | filename = newfilename; | 59 | filename = newfilename; |
49 | } | 60 | } |
50 | 61 | ||
51 | self->start = event->start; | 62 | dso = dsos__findnew(filename); |
52 | self->end = event->start + event->len; | 63 | if (dso == NULL) |
53 | self->pgoff = event->pgoff; | ||
54 | |||
55 | self->dso = dsos__findnew(filename, sym_priv_size, &new_dso); | ||
56 | if (self->dso == NULL) | ||
57 | goto out_delete; | 64 | goto out_delete; |
58 | 65 | ||
59 | if (new_dso) { | 66 | map__init(self, event->start, event->start + event->len, |
60 | int nr = dso__load(self->dso, self, filter); | 67 | event->pgoff, dso); |
61 | |||
62 | if (nr < 0) | ||
63 | pr_warning("Failed to open %s, continuing " | ||
64 | "without symbols\n", | ||
65 | self->dso->long_name); | ||
66 | else if (nr == 0) | ||
67 | pr_warning("No symbols found in %s, maybe " | ||
68 | "install a debug package?\n", | ||
69 | self->dso->long_name); | ||
70 | } | ||
71 | 68 | ||
72 | if (self->dso == vdso || anon) | 69 | if (self->dso == vdso || anon) |
73 | self->map_ip = self->unmap_ip = identity__map_ip; | 70 | self->map_ip = self->unmap_ip = identity__map_ip; |
74 | else { | ||
75 | self->map_ip = map__map_ip; | ||
76 | self->unmap_ip = map__unmap_ip; | ||
77 | } | ||
78 | } | 71 | } |
79 | return self; | 72 | return self; |
80 | out_delete: | 73 | out_delete: |
@@ -82,6 +75,47 @@ out_delete: | |||
82 | return NULL; | 75 | return NULL; |
83 | } | 76 | } |
84 | 77 | ||
78 | #define DSO__DELETED "(deleted)" | ||
79 | |||
80 | struct symbol * | ||
81 | map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter) | ||
82 | { | ||
83 | if (!self->dso->loaded) { | ||
84 | int nr = dso__load(self->dso, self, filter); | ||
85 | |||
86 | if (nr < 0) { | ||
87 | if (self->dso->has_build_id) { | ||
88 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
89 | |||
90 | build_id__sprintf(self->dso->build_id, | ||
91 | sizeof(self->dso->build_id), | ||
92 | sbuild_id); | ||
93 | pr_warning("%s with build id %s not found", | ||
94 | self->dso->long_name, sbuild_id); | ||
95 | } else | ||
96 | pr_warning("Failed to open %s", | ||
97 | self->dso->long_name); | ||
98 | pr_warning(", continuing without symbols\n"); | ||
99 | return NULL; | ||
100 | } else if (nr == 0) { | ||
101 | const char *name = self->dso->long_name; | ||
102 | const size_t len = strlen(name); | ||
103 | const size_t real_len = len - sizeof(DSO__DELETED); | ||
104 | |||
105 | if (len > sizeof(DSO__DELETED) && | ||
106 | strcmp(name + real_len + 1, DSO__DELETED) == 0) { | ||
107 | pr_warning("%.*s was updated, restart the long running apps that use it!\n", | ||
108 | (int)real_len, name); | ||
109 | } else { | ||
110 | pr_warning("no symbols found in %s, maybe install a debug package?\n", name); | ||
111 | } | ||
112 | return NULL; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | return self->dso->find_symbol(self->dso, ip); | ||
117 | } | ||
118 | |||
85 | struct map *map__clone(struct map *self) | 119 | struct map *map__clone(struct map *self) |
86 | { | 120 | { |
87 | struct map *map = malloc(sizeof(*self)); | 121 | struct map *map = malloc(sizeof(*self)); |