From 076c6e45215aea0de1ed34d3d5079fabeaabf5e1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Aug 2010 18:18:28 -0300 Subject: perf session: Free the ref_reloc_sym memory at the right place Which is at perf_session__destroy_kernel_maps, counterpart to the perf_session__create_kernel_maps where the kmap structure is located, just after the vmlinux_maps. Make it also check if the kernel maps were actually created, which may not be the case if, for instance, perf_session__new can't complete due to permission problems in, for instance, a 'perf report' case, when a segfault will take place, that is how this was noticed. The problem was introduced in d65a458, thus post .35. This also adds code to release guest machines as them are also created in perf_session__create_kernel_maps, so should be deleted on this newly introduced counterpart, perf_session__destroy_kernel_maps. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Stephane Eranian LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'tools/perf/util/symbol.c') diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3b8c0050667..6f0dd90c36c 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) return 0; } +void machine__destroy_kernel_maps(struct machine *self) +{ + enum map_type type; + + for (type = 0; type < MAP__NR_TYPES; ++type) { + struct kmap *kmap; + + if (self->vmlinux_maps[type] == NULL) + continue; + + kmap = map__kmap(self->vmlinux_maps[type]); + map_groups__remove(&self->kmaps, self->vmlinux_maps[type]); + if (kmap->ref_reloc_sym) { + /* + * ref_reloc_sym is shared among all maps, so free just + * on one of them. + */ + if (type == MAP__FUNCTION) { + free((char *)kmap->ref_reloc_sym->name); + kmap->ref_reloc_sym->name = NULL; + free(kmap->ref_reloc_sym); + } + kmap->ref_reloc_sym = NULL; + } + + map__delete(self->vmlinux_maps[type]); + self->vmlinux_maps[type] = NULL; + } +} + int machine__create_kernel_maps(struct machine *self) { struct dso *kernel = machine__create_kernel(self); @@ -2351,6 +2381,19 @@ failure: return ret; } +void machines__destroy_guest_kernel_maps(struct rb_root *self) +{ + struct rb_node *next = rb_first(self); + + while (next) { + struct machine *pos = rb_entry(next, struct machine, rb_node); + + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, self); + machine__delete(pos); + } +} + int machine__load_kallsyms(struct machine *self, const char *filename, enum map_type type, symbol_filter_t filter) { -- cgit v1.2.2