diff options
| -rw-r--r-- | tools/perf/util/hist.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/map.c | 49 | ||||
| -rw-r--r-- | tools/perf/util/map.h | 10 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 43 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 2 |
6 files changed, 96 insertions, 18 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a6cea2894d12..e7263d49bcf0 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -93,6 +93,8 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) | |||
| 93 | if (self != NULL) { | 93 | if (self != NULL) { |
| 94 | *self = *template; | 94 | *self = *template; |
| 95 | self->nr_events = 1; | 95 | self->nr_events = 1; |
| 96 | if (self->ms.map) | ||
| 97 | self->ms.map->referenced = true; | ||
| 96 | if (symbol_conf.use_callchain) | 98 | if (symbol_conf.use_callchain) |
| 97 | callchain_init(self->callchain); | 99 | callchain_init(self->callchain); |
| 98 | } | 100 | } |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 15d6a6dd50c5..3a7eb6ec0eec 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -29,6 +29,7 @@ void map__init(struct map *self, enum map_type type, | |||
| 29 | self->unmap_ip = map__unmap_ip; | 29 | self->unmap_ip = map__unmap_ip; |
| 30 | RB_CLEAR_NODE(&self->rb_node); | 30 | RB_CLEAR_NODE(&self->rb_node); |
| 31 | self->groups = NULL; | 31 | self->groups = NULL; |
| 32 | self->referenced = false; | ||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 35 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
| @@ -387,6 +388,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
| 387 | { | 388 | { |
| 388 | struct rb_root *root = &self->maps[map->type]; | 389 | struct rb_root *root = &self->maps[map->type]; |
| 389 | struct rb_node *next = rb_first(root); | 390 | struct rb_node *next = rb_first(root); |
| 391 | int err = 0; | ||
| 390 | 392 | ||
| 391 | while (next) { | 393 | while (next) { |
| 392 | struct map *pos = rb_entry(next, struct map, rb_node); | 394 | struct map *pos = rb_entry(next, struct map, rb_node); |
| @@ -403,20 +405,16 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
| 403 | 405 | ||
| 404 | rb_erase(&pos->rb_node, root); | 406 | rb_erase(&pos->rb_node, root); |
| 405 | /* | 407 | /* |
| 406 | * We may have references to this map, for instance in some | ||
| 407 | * hist_entry instances, so just move them to a separate | ||
| 408 | * list. | ||
| 409 | */ | ||
| 410 | list_add_tail(&pos->node, &self->removed_maps[map->type]); | ||
| 411 | /* | ||
| 412 | * Now check if we need to create new maps for areas not | 408 | * Now check if we need to create new maps for areas not |
| 413 | * overlapped by the new map: | 409 | * overlapped by the new map: |
| 414 | */ | 410 | */ |
| 415 | if (map->start > pos->start) { | 411 | if (map->start > pos->start) { |
| 416 | struct map *before = map__clone(pos); | 412 | struct map *before = map__clone(pos); |
| 417 | 413 | ||
| 418 | if (before == NULL) | 414 | if (before == NULL) { |
| 419 | return -ENOMEM; | 415 | err = -ENOMEM; |
| 416 | goto move_map; | ||
| 417 | } | ||
| 420 | 418 | ||
| 421 | before->end = map->start - 1; | 419 | before->end = map->start - 1; |
| 422 | map_groups__insert(self, before); | 420 | map_groups__insert(self, before); |
| @@ -427,14 +425,27 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
| 427 | if (map->end < pos->end) { | 425 | if (map->end < pos->end) { |
| 428 | struct map *after = map__clone(pos); | 426 | struct map *after = map__clone(pos); |
| 429 | 427 | ||
| 430 | if (after == NULL) | 428 | if (after == NULL) { |
| 431 | return -ENOMEM; | 429 | err = -ENOMEM; |
| 430 | goto move_map; | ||
| 431 | } | ||
| 432 | 432 | ||
| 433 | after->start = map->end + 1; | 433 | after->start = map->end + 1; |
| 434 | map_groups__insert(self, after); | 434 | map_groups__insert(self, after); |
| 435 | if (verbose >= 2) | 435 | if (verbose >= 2) |
| 436 | map__fprintf(after, fp); | 436 | map__fprintf(after, fp); |
| 437 | } | 437 | } |
| 438 | move_map: | ||
| 439 | /* | ||
| 440 | * If we have references, just move them to a separate list. | ||
| 441 | */ | ||
| 442 | if (pos->referenced) | ||
| 443 | list_add_tail(&pos->node, &self->removed_maps[map->type]); | ||
| 444 | else | ||
| 445 | map__delete(pos); | ||
| 446 | |||
| 447 | if (err) | ||
| 448 | return err; | ||
| 438 | } | 449 | } |
| 439 | 450 | ||
| 440 | return 0; | 451 | return 0; |
| @@ -506,6 +517,11 @@ void maps__insert(struct rb_root *maps, struct map *map) | |||
| 506 | rb_insert_color(&map->rb_node, maps); | 517 | rb_insert_color(&map->rb_node, maps); |
| 507 | } | 518 | } |
| 508 | 519 | ||
| 520 | void maps__remove(struct rb_root *self, struct map *map) | ||
| 521 | { | ||
| 522 | rb_erase(&map->rb_node, self); | ||
| 523 | } | ||
| 524 | |||
| 509 | struct map *maps__find(struct rb_root *maps, u64 ip) | 525 | struct map *maps__find(struct rb_root *maps, u64 ip) |
| 510 | { | 526 | { |
| 511 | struct rb_node **p = &maps->rb_node; | 527 | struct rb_node **p = &maps->rb_node; |
| @@ -551,13 +567,6 @@ static void dsos__delete(struct list_head *self) | |||
| 551 | 567 | ||
| 552 | void machine__exit(struct machine *self) | 568 | void machine__exit(struct machine *self) |
| 553 | { | 569 | { |
| 554 | struct kmap *kmap = map__kmap(self->vmlinux_maps[MAP__FUNCTION]); | ||
| 555 | |||
| 556 | if (kmap->ref_reloc_sym) { | ||
| 557 | free((char *)kmap->ref_reloc_sym->name); | ||
| 558 | free(kmap->ref_reloc_sym); | ||
| 559 | } | ||
| 560 | |||
| 561 | map_groups__exit(&self->kmaps); | 570 | map_groups__exit(&self->kmaps); |
| 562 | dsos__delete(&self->user_dsos); | 571 | dsos__delete(&self->user_dsos); |
| 563 | dsos__delete(&self->kernel_dsos); | 572 | dsos__delete(&self->kernel_dsos); |
| @@ -565,6 +574,12 @@ void machine__exit(struct machine *self) | |||
| 565 | self->root_dir = NULL; | 574 | self->root_dir = NULL; |
| 566 | } | 575 | } |
| 567 | 576 | ||
| 577 | void machine__delete(struct machine *self) | ||
| 578 | { | ||
| 579 | machine__exit(self); | ||
| 580 | free(self); | ||
| 581 | } | ||
| 582 | |||
| 568 | struct machine *machines__add(struct rb_root *self, pid_t pid, | 583 | struct machine *machines__add(struct rb_root *self, pid_t pid, |
| 569 | const char *root_dir) | 584 | const char *root_dir) |
| 570 | { | 585 | { |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 0e0984e86fce..78575796d5f3 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -29,7 +29,8 @@ struct map { | |||
| 29 | }; | 29 | }; |
| 30 | u64 start; | 30 | u64 start; |
| 31 | u64 end; | 31 | u64 end; |
| 32 | enum map_type type; | 32 | u8 /* enum map_type */ type; |
| 33 | bool referenced; | ||
| 33 | u32 priv; | 34 | u32 priv; |
| 34 | u64 pgoff; | 35 | u64 pgoff; |
| 35 | 36 | ||
| @@ -125,6 +126,7 @@ void map__reloc_vmlinux(struct map *self); | |||
| 125 | size_t __map_groups__fprintf_maps(struct map_groups *self, | 126 | size_t __map_groups__fprintf_maps(struct map_groups *self, |
| 126 | enum map_type type, int verbose, FILE *fp); | 127 | enum map_type type, int verbose, FILE *fp); |
| 127 | void maps__insert(struct rb_root *maps, struct map *map); | 128 | void maps__insert(struct rb_root *maps, struct map *map); |
| 129 | void maps__remove(struct rb_root *self, struct map *map); | ||
| 128 | struct map *maps__find(struct rb_root *maps, u64 addr); | 130 | struct map *maps__find(struct rb_root *maps, u64 addr); |
| 129 | void map_groups__init(struct map_groups *self); | 131 | void map_groups__init(struct map_groups *self); |
| 130 | void map_groups__exit(struct map_groups *self); | 132 | void map_groups__exit(struct map_groups *self); |
| @@ -144,6 +146,7 @@ struct machine *machines__findnew(struct rb_root *self, pid_t pid); | |||
| 144 | char *machine__mmap_name(struct machine *self, char *bf, size_t size); | 146 | char *machine__mmap_name(struct machine *self, char *bf, size_t size); |
| 145 | int machine__init(struct machine *self, const char *root_dir, pid_t pid); | 147 | int machine__init(struct machine *self, const char *root_dir, pid_t pid); |
| 146 | void machine__exit(struct machine *self); | 148 | void machine__exit(struct machine *self); |
| 149 | void machine__delete(struct machine *self); | ||
| 147 | 150 | ||
| 148 | /* | 151 | /* |
| 149 | * Default guest kernel is defined by parameter --guestkallsyms | 152 | * Default guest kernel is defined by parameter --guestkallsyms |
| @@ -165,6 +168,11 @@ static inline void map_groups__insert(struct map_groups *self, struct map *map) | |||
| 165 | map->groups = self; | 168 | map->groups = self; |
| 166 | } | 169 | } |
| 167 | 170 | ||
| 171 | static inline void map_groups__remove(struct map_groups *self, struct map *map) | ||
| 172 | { | ||
| 173 | maps__remove(&self->maps[map->type], map); | ||
| 174 | } | ||
| 175 | |||
| 168 | static inline struct map *map_groups__find(struct map_groups *self, | 176 | static inline struct map *map_groups__find(struct map_groups *self, |
| 169 | enum map_type type, u64 addr) | 177 | enum map_type type, u64 addr) |
| 170 | { | 178 | { |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 04a3b3db9e90..fa9d652c2dc3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -79,6 +79,12 @@ int perf_session__create_kernel_maps(struct perf_session *self) | |||
| 79 | return ret; | 79 | return ret; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static void perf_session__destroy_kernel_maps(struct perf_session *self) | ||
| 83 | { | ||
| 84 | machine__destroy_kernel_maps(&self->host_machine); | ||
| 85 | machines__destroy_guest_kernel_maps(&self->machines); | ||
| 86 | } | ||
| 87 | |||
| 82 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) | 88 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) |
| 83 | { | 89 | { |
| 84 | size_t len = filename ? strlen(filename) + 1 : 0; | 90 | size_t len = filename ? strlen(filename) + 1 : 0; |
| @@ -150,6 +156,7 @@ static void perf_session__delete_threads(struct perf_session *self) | |||
| 150 | void perf_session__delete(struct perf_session *self) | 156 | void perf_session__delete(struct perf_session *self) |
| 151 | { | 157 | { |
| 152 | perf_header__exit(&self->header); | 158 | perf_header__exit(&self->header); |
| 159 | perf_session__destroy_kernel_maps(self); | ||
| 153 | perf_session__delete_dead_threads(self); | 160 | perf_session__delete_dead_threads(self); |
| 154 | perf_session__delete_threads(self); | 161 | perf_session__delete_threads(self); |
| 155 | machine__exit(&self->host_machine); | 162 | machine__exit(&self->host_machine); |
| @@ -159,6 +166,7 @@ void perf_session__delete(struct perf_session *self) | |||
| 159 | 166 | ||
| 160 | void perf_session__remove_thread(struct perf_session *self, struct thread *th) | 167 | void perf_session__remove_thread(struct perf_session *self, struct thread *th) |
| 161 | { | 168 | { |
| 169 | self->last_match = NULL; | ||
| 162 | rb_erase(&th->rb_node, &self->threads); | 170 | rb_erase(&th->rb_node, &self->threads); |
| 163 | /* | 171 | /* |
| 164 | * We may have references to this thread, for instance in some hist_entry | 172 | * We may have references to this thread, for instance in some hist_entry |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3b8c00506672..6f0dd90c36ce 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -2107,6 +2107,36 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) | |||
| 2107 | return 0; | 2107 | return 0; |
| 2108 | } | 2108 | } |
| 2109 | 2109 | ||
| 2110 | void machine__destroy_kernel_maps(struct machine *self) | ||
| 2111 | { | ||
| 2112 | enum map_type type; | ||
| 2113 | |||
| 2114 | for (type = 0; type < MAP__NR_TYPES; ++type) { | ||
| 2115 | struct kmap *kmap; | ||
| 2116 | |||
| 2117 | if (self->vmlinux_maps[type] == NULL) | ||
| 2118 | continue; | ||
| 2119 | |||
| 2120 | kmap = map__kmap(self->vmlinux_maps[type]); | ||
| 2121 | map_groups__remove(&self->kmaps, self->vmlinux_maps[type]); | ||
| 2122 | if (kmap->ref_reloc_sym) { | ||
| 2123 | /* | ||
| 2124 | * ref_reloc_sym is shared among all maps, so free just | ||
| 2125 | * on one of them. | ||
| 2126 | */ | ||
| 2127 | if (type == MAP__FUNCTION) { | ||
| 2128 | free((char *)kmap->ref_reloc_sym->name); | ||
| 2129 | kmap->ref_reloc_sym->name = NULL; | ||
| 2130 | free(kmap->ref_reloc_sym); | ||
| 2131 | } | ||
| 2132 | kmap->ref_reloc_sym = NULL; | ||
| 2133 | } | ||
| 2134 | |||
| 2135 | map__delete(self->vmlinux_maps[type]); | ||
| 2136 | self->vmlinux_maps[type] = NULL; | ||
| 2137 | } | ||
| 2138 | } | ||
| 2139 | |||
| 2110 | int machine__create_kernel_maps(struct machine *self) | 2140 | int machine__create_kernel_maps(struct machine *self) |
| 2111 | { | 2141 | { |
| 2112 | struct dso *kernel = machine__create_kernel(self); | 2142 | struct dso *kernel = machine__create_kernel(self); |
| @@ -2351,6 +2381,19 @@ failure: | |||
| 2351 | return ret; | 2381 | return ret; |
| 2352 | } | 2382 | } |
| 2353 | 2383 | ||
| 2384 | void machines__destroy_guest_kernel_maps(struct rb_root *self) | ||
| 2385 | { | ||
| 2386 | struct rb_node *next = rb_first(self); | ||
| 2387 | |||
| 2388 | while (next) { | ||
| 2389 | struct machine *pos = rb_entry(next, struct machine, rb_node); | ||
| 2390 | |||
| 2391 | next = rb_next(&pos->rb_node); | ||
| 2392 | rb_erase(&pos->rb_node, self); | ||
| 2393 | machine__delete(pos); | ||
| 2394 | } | ||
| 2395 | } | ||
| 2396 | |||
| 2354 | int machine__load_kallsyms(struct machine *self, const char *filename, | 2397 | int machine__load_kallsyms(struct machine *self, const char *filename, |
| 2355 | enum map_type type, symbol_filter_t filter) | 2398 | enum map_type type, symbol_filter_t filter) |
| 2356 | { | 2399 | { |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 33d53ce28958..906be20011d9 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -212,11 +212,13 @@ int kallsyms__parse(const char *filename, void *arg, | |||
| 212 | int (*process_symbol)(void *arg, const char *name, | 212 | int (*process_symbol)(void *arg, const char *name, |
| 213 | char type, u64 start)); | 213 | char type, u64 start)); |
| 214 | 214 | ||
| 215 | void machine__destroy_kernel_maps(struct machine *self); | ||
| 215 | int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); | 216 | int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); |
| 216 | int machine__create_kernel_maps(struct machine *self); | 217 | int machine__create_kernel_maps(struct machine *self); |
| 217 | 218 | ||
| 218 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid); | 219 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid); |
| 219 | int machines__create_guest_kernel_maps(struct rb_root *self); | 220 | int machines__create_guest_kernel_maps(struct rb_root *self); |
| 221 | void machines__destroy_guest_kernel_maps(struct rb_root *self); | ||
| 220 | 222 | ||
| 221 | int symbol__init(void); | 223 | int symbol__init(void); |
| 222 | void symbol__exit(void); | 224 | void symbol__exit(void); |
