diff options
Diffstat (limited to 'tools/perf/util/map.c')
-rw-r--r-- | tools/perf/util/map.c | 121 |
1 files changed, 58 insertions, 63 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 0328d45c4f2a..6fcb9de62340 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "strlist.h" | 11 | #include "strlist.h" |
12 | #include "vdso.h" | 12 | #include "vdso.h" |
13 | #include "build-id.h" | 13 | #include "build-id.h" |
14 | #include <linux/string.h> | ||
14 | 15 | ||
15 | const char *map_type__name[MAP__NR_TYPES] = { | 16 | const char *map_type__name[MAP__NR_TYPES] = { |
16 | [MAP__FUNCTION] = "Functions", | 17 | [MAP__FUNCTION] = "Functions", |
@@ -19,7 +20,8 @@ const char *map_type__name[MAP__NR_TYPES] = { | |||
19 | 20 | ||
20 | static inline int is_anon_memory(const char *filename) | 21 | static inline int is_anon_memory(const char *filename) |
21 | { | 22 | { |
22 | return strcmp(filename, "//anon") == 0; | 23 | return !strcmp(filename, "//anon") || |
24 | !strcmp(filename, "/anon_hugepage (deleted)"); | ||
23 | } | 25 | } |
24 | 26 | ||
25 | static inline int is_no_dso_memory(const char *filename) | 27 | static inline int is_no_dso_memory(const char *filename) |
@@ -28,29 +30,29 @@ static inline int is_no_dso_memory(const char *filename) | |||
28 | !strcmp(filename, "[heap]"); | 30 | !strcmp(filename, "[heap]"); |
29 | } | 31 | } |
30 | 32 | ||
31 | void map__init(struct map *self, enum map_type type, | 33 | void map__init(struct map *map, enum map_type type, |
32 | u64 start, u64 end, u64 pgoff, struct dso *dso) | 34 | u64 start, u64 end, u64 pgoff, struct dso *dso) |
33 | { | 35 | { |
34 | self->type = type; | 36 | map->type = type; |
35 | self->start = start; | 37 | map->start = start; |
36 | self->end = end; | 38 | map->end = end; |
37 | self->pgoff = pgoff; | 39 | map->pgoff = pgoff; |
38 | self->dso = dso; | 40 | map->dso = dso; |
39 | self->map_ip = map__map_ip; | 41 | map->map_ip = map__map_ip; |
40 | self->unmap_ip = map__unmap_ip; | 42 | map->unmap_ip = map__unmap_ip; |
41 | RB_CLEAR_NODE(&self->rb_node); | 43 | RB_CLEAR_NODE(&map->rb_node); |
42 | self->groups = NULL; | 44 | map->groups = NULL; |
43 | self->referenced = false; | 45 | map->referenced = false; |
44 | self->erange_warned = false; | 46 | map->erange_warned = false; |
45 | } | 47 | } |
46 | 48 | ||
47 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 49 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
48 | u64 pgoff, u32 pid, char *filename, | 50 | u64 pgoff, u32 pid, char *filename, |
49 | enum map_type type) | 51 | enum map_type type) |
50 | { | 52 | { |
51 | struct map *self = malloc(sizeof(*self)); | 53 | struct map *map = malloc(sizeof(*map)); |
52 | 54 | ||
53 | if (self != NULL) { | 55 | if (map != NULL) { |
54 | char newfilename[PATH_MAX]; | 56 | char newfilename[PATH_MAX]; |
55 | struct dso *dso; | 57 | struct dso *dso; |
56 | int anon, no_dso, vdso; | 58 | int anon, no_dso, vdso; |
@@ -73,10 +75,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
73 | if (dso == NULL) | 75 | if (dso == NULL) |
74 | goto out_delete; | 76 | goto out_delete; |
75 | 77 | ||
76 | map__init(self, type, start, start + len, pgoff, dso); | 78 | map__init(map, type, start, start + len, pgoff, dso); |
77 | 79 | ||
78 | if (anon || no_dso) { | 80 | if (anon || no_dso) { |
79 | self->map_ip = self->unmap_ip = identity__map_ip; | 81 | map->map_ip = map->unmap_ip = identity__map_ip; |
80 | 82 | ||
81 | /* | 83 | /* |
82 | * Set memory without DSO as loaded. All map__find_* | 84 | * Set memory without DSO as loaded. All map__find_* |
@@ -84,12 +86,12 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
84 | * unnecessary map__load warning. | 86 | * unnecessary map__load warning. |
85 | */ | 87 | */ |
86 | if (no_dso) | 88 | if (no_dso) |
87 | dso__set_loaded(dso, self->type); | 89 | dso__set_loaded(dso, map->type); |
88 | } | 90 | } |
89 | } | 91 | } |
90 | return self; | 92 | return map; |
91 | out_delete: | 93 | out_delete: |
92 | free(self); | 94 | free(map); |
93 | return NULL; | 95 | return NULL; |
94 | } | 96 | } |
95 | 97 | ||
@@ -112,48 +114,48 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
112 | return map; | 114 | return map; |
113 | } | 115 | } |
114 | 116 | ||
115 | void map__delete(struct map *self) | 117 | void map__delete(struct map *map) |
116 | { | 118 | { |
117 | free(self); | 119 | free(map); |
118 | } | 120 | } |
119 | 121 | ||
120 | void map__fixup_start(struct map *self) | 122 | void map__fixup_start(struct map *map) |
121 | { | 123 | { |
122 | struct rb_root *symbols = &self->dso->symbols[self->type]; | 124 | struct rb_root *symbols = &map->dso->symbols[map->type]; |
123 | struct rb_node *nd = rb_first(symbols); | 125 | struct rb_node *nd = rb_first(symbols); |
124 | if (nd != NULL) { | 126 | if (nd != NULL) { |
125 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 127 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); |
126 | self->start = sym->start; | 128 | map->start = sym->start; |
127 | } | 129 | } |
128 | } | 130 | } |
129 | 131 | ||
130 | void map__fixup_end(struct map *self) | 132 | void map__fixup_end(struct map *map) |
131 | { | 133 | { |
132 | struct rb_root *symbols = &self->dso->symbols[self->type]; | 134 | struct rb_root *symbols = &map->dso->symbols[map->type]; |
133 | struct rb_node *nd = rb_last(symbols); | 135 | struct rb_node *nd = rb_last(symbols); |
134 | if (nd != NULL) { | 136 | if (nd != NULL) { |
135 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 137 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); |
136 | self->end = sym->end; | 138 | map->end = sym->end; |
137 | } | 139 | } |
138 | } | 140 | } |
139 | 141 | ||
140 | #define DSO__DELETED "(deleted)" | 142 | #define DSO__DELETED "(deleted)" |
141 | 143 | ||
142 | int map__load(struct map *self, symbol_filter_t filter) | 144 | int map__load(struct map *map, symbol_filter_t filter) |
143 | { | 145 | { |
144 | const char *name = self->dso->long_name; | 146 | const char *name = map->dso->long_name; |
145 | int nr; | 147 | int nr; |
146 | 148 | ||
147 | if (dso__loaded(self->dso, self->type)) | 149 | if (dso__loaded(map->dso, map->type)) |
148 | return 0; | 150 | return 0; |
149 | 151 | ||
150 | nr = dso__load(self->dso, self, filter); | 152 | nr = dso__load(map->dso, map, filter); |
151 | if (nr < 0) { | 153 | if (nr < 0) { |
152 | if (self->dso->has_build_id) { | 154 | if (map->dso->has_build_id) { |
153 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | 155 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; |
154 | 156 | ||
155 | build_id__sprintf(self->dso->build_id, | 157 | build_id__sprintf(map->dso->build_id, |
156 | sizeof(self->dso->build_id), | 158 | sizeof(map->dso->build_id), |
157 | sbuild_id); | 159 | sbuild_id); |
158 | pr_warning("%s with build id %s not found", | 160 | pr_warning("%s with build id %s not found", |
159 | name, sbuild_id); | 161 | name, sbuild_id); |
@@ -183,43 +185,36 @@ int map__load(struct map *self, symbol_filter_t filter) | |||
183 | * Only applies to the kernel, as its symtabs aren't relative like the | 185 | * Only applies to the kernel, as its symtabs aren't relative like the |
184 | * module ones. | 186 | * module ones. |
185 | */ | 187 | */ |
186 | if (self->dso->kernel) | 188 | if (map->dso->kernel) |
187 | map__reloc_vmlinux(self); | 189 | map__reloc_vmlinux(map); |
188 | 190 | ||
189 | return 0; | 191 | return 0; |
190 | } | 192 | } |
191 | 193 | ||
192 | struct symbol *map__find_symbol(struct map *self, u64 addr, | 194 | struct symbol *map__find_symbol(struct map *map, u64 addr, |
193 | symbol_filter_t filter) | 195 | symbol_filter_t filter) |
194 | { | 196 | { |
195 | if (map__load(self, filter) < 0) | 197 | if (map__load(map, filter) < 0) |
196 | return NULL; | 198 | return NULL; |
197 | 199 | ||
198 | return dso__find_symbol(self->dso, self->type, addr); | 200 | return dso__find_symbol(map->dso, map->type, addr); |
199 | } | 201 | } |
200 | 202 | ||
201 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, | 203 | struct symbol *map__find_symbol_by_name(struct map *map, const char *name, |
202 | symbol_filter_t filter) | 204 | symbol_filter_t filter) |
203 | { | 205 | { |
204 | if (map__load(self, filter) < 0) | 206 | if (map__load(map, filter) < 0) |
205 | return NULL; | 207 | return NULL; |
206 | 208 | ||
207 | if (!dso__sorted_by_name(self->dso, self->type)) | 209 | if (!dso__sorted_by_name(map->dso, map->type)) |
208 | dso__sort_by_name(self->dso, self->type); | 210 | dso__sort_by_name(map->dso, map->type); |
209 | 211 | ||
210 | return dso__find_symbol_by_name(self->dso, self->type, name); | 212 | return dso__find_symbol_by_name(map->dso, map->type, name); |
211 | } | 213 | } |
212 | 214 | ||
213 | struct map *map__clone(struct map *self) | 215 | struct map *map__clone(struct map *map) |
214 | { | 216 | { |
215 | struct map *map = malloc(sizeof(*self)); | 217 | return memdup(map, sizeof(*map)); |
216 | |||
217 | if (!map) | ||
218 | return NULL; | ||
219 | |||
220 | memcpy(map, self, sizeof(*self)); | ||
221 | |||
222 | return map; | ||
223 | } | 218 | } |
224 | 219 | ||
225 | int map__overlap(struct map *l, struct map *r) | 220 | int map__overlap(struct map *l, struct map *r) |
@@ -236,10 +231,10 @@ int map__overlap(struct map *l, struct map *r) | |||
236 | return 0; | 231 | return 0; |
237 | } | 232 | } |
238 | 233 | ||
239 | size_t map__fprintf(struct map *self, FILE *fp) | 234 | size_t map__fprintf(struct map *map, FILE *fp) |
240 | { | 235 | { |
241 | return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", | 236 | return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", |
242 | self->start, self->end, self->pgoff, self->dso->name); | 237 | map->start, map->end, map->pgoff, map->dso->name); |
243 | } | 238 | } |
244 | 239 | ||
245 | size_t map__fprintf_dsoname(struct map *map, FILE *fp) | 240 | size_t map__fprintf_dsoname(struct map *map, FILE *fp) |
@@ -527,9 +522,9 @@ static u64 map__reloc_unmap_ip(struct map *map, u64 ip) | |||
527 | return ip - (s64)map->pgoff; | 522 | return ip - (s64)map->pgoff; |
528 | } | 523 | } |
529 | 524 | ||
530 | void map__reloc_vmlinux(struct map *self) | 525 | void map__reloc_vmlinux(struct map *map) |
531 | { | 526 | { |
532 | struct kmap *kmap = map__kmap(self); | 527 | struct kmap *kmap = map__kmap(map); |
533 | s64 reloc; | 528 | s64 reloc; |
534 | 529 | ||
535 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr) | 530 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr) |
@@ -541,9 +536,9 @@ void map__reloc_vmlinux(struct map *self) | |||
541 | if (!reloc) | 536 | if (!reloc) |
542 | return; | 537 | return; |
543 | 538 | ||
544 | self->map_ip = map__reloc_map_ip; | 539 | map->map_ip = map__reloc_map_ip; |
545 | self->unmap_ip = map__reloc_unmap_ip; | 540 | map->unmap_ip = map__reloc_unmap_ip; |
546 | self->pgoff = reloc; | 541 | map->pgoff = reloc; |
547 | } | 542 | } |
548 | 543 | ||
549 | void maps__insert(struct rb_root *maps, struct map *map) | 544 | void maps__insert(struct rb_root *maps, struct map *map) |
@@ -566,9 +561,9 @@ void maps__insert(struct rb_root *maps, struct map *map) | |||
566 | rb_insert_color(&map->rb_node, maps); | 561 | rb_insert_color(&map->rb_node, maps); |
567 | } | 562 | } |
568 | 563 | ||
569 | void maps__remove(struct rb_root *self, struct map *map) | 564 | void maps__remove(struct rb_root *maps, struct map *map) |
570 | { | 565 | { |
571 | rb_erase(&map->rb_node, self); | 566 | rb_erase(&map->rb_node, maps); |
572 | } | 567 | } |
573 | 568 | ||
574 | struct map *maps__find(struct rb_root *maps, u64 ip) | 569 | struct map *maps__find(struct rb_root *maps, u64 ip) |