aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-08-02 17:18:28 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-08-02 17:18:28 -0400
commit076c6e45215aea0de1ed34d3d5079fabeaabf5e1 (patch)
treea07e78f58e625eb69dfda8f32ab46e5316551025 /tools/perf/util
parent3772b734720e1a3f2dc1d95cfdfaa5332f4ccf01 (diff)
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 <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/map.c18
-rw-r--r--tools/perf/util/map.h7
-rw-r--r--tools/perf/util/session.c7
-rw-r--r--tools/perf/util/symbol.c43
-rw-r--r--tools/perf/util/symbol.h2
5 files changed, 70 insertions, 7 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 15d6a6dd50c5..801e6962b0a6 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -506,6 +506,11 @@ void maps__insert(struct rb_root *maps, struct map *map)
506 rb_insert_color(&map->rb_node, maps); 506 rb_insert_color(&map->rb_node, maps);
507} 507}
508 508
509void maps__remove(struct rb_root *self, struct map *map)
510{
511 rb_erase(&map->rb_node, self);
512}
513
509struct map *maps__find(struct rb_root *maps, u64 ip) 514struct map *maps__find(struct rb_root *maps, u64 ip)
510{ 515{
511 struct rb_node **p = &maps->rb_node; 516 struct rb_node **p = &maps->rb_node;
@@ -551,13 +556,6 @@ static void dsos__delete(struct list_head *self)
551 556
552void machine__exit(struct machine *self) 557void machine__exit(struct machine *self)
553{ 558{
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); 559 map_groups__exit(&self->kmaps);
562 dsos__delete(&self->user_dsos); 560 dsos__delete(&self->user_dsos);
563 dsos__delete(&self->kernel_dsos); 561 dsos__delete(&self->kernel_dsos);
@@ -565,6 +563,12 @@ void machine__exit(struct machine *self)
565 self->root_dir = NULL; 563 self->root_dir = NULL;
566} 564}
567 565
566void machine__delete(struct machine *self)
567{
568 machine__exit(self);
569 free(self);
570}
571
568struct machine *machines__add(struct rb_root *self, pid_t pid, 572struct machine *machines__add(struct rb_root *self, pid_t pid,
569 const char *root_dir) 573 const char *root_dir)
570{ 574{
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 0e0984e86fce..5b51bbd2f734 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -125,6 +125,7 @@ void map__reloc_vmlinux(struct map *self);
125size_t __map_groups__fprintf_maps(struct map_groups *self, 125size_t __map_groups__fprintf_maps(struct map_groups *self,
126 enum map_type type, int verbose, FILE *fp); 126 enum map_type type, int verbose, FILE *fp);
127void maps__insert(struct rb_root *maps, struct map *map); 127void maps__insert(struct rb_root *maps, struct map *map);
128void maps__remove(struct rb_root *self, struct map *map);
128struct map *maps__find(struct rb_root *maps, u64 addr); 129struct map *maps__find(struct rb_root *maps, u64 addr);
129void map_groups__init(struct map_groups *self); 130void map_groups__init(struct map_groups *self);
130void map_groups__exit(struct map_groups *self); 131void map_groups__exit(struct map_groups *self);
@@ -144,6 +145,7 @@ struct machine *machines__findnew(struct rb_root *self, pid_t pid);
144char *machine__mmap_name(struct machine *self, char *bf, size_t size); 145char *machine__mmap_name(struct machine *self, char *bf, size_t size);
145int machine__init(struct machine *self, const char *root_dir, pid_t pid); 146int machine__init(struct machine *self, const char *root_dir, pid_t pid);
146void machine__exit(struct machine *self); 147void machine__exit(struct machine *self);
148void machine__delete(struct machine *self);
147 149
148/* 150/*
149 * Default guest kernel is defined by parameter --guestkallsyms 151 * Default guest kernel is defined by parameter --guestkallsyms
@@ -165,6 +167,11 @@ static inline void map_groups__insert(struct map_groups *self, struct map *map)
165 map->groups = self; 167 map->groups = self;
166} 168}
167 169
170static inline void map_groups__remove(struct map_groups *self, struct map *map)
171{
172 maps__remove(&self->maps[map->type], map);
173}
174
168static inline struct map *map_groups__find(struct map_groups *self, 175static inline struct map *map_groups__find(struct map_groups *self,
169 enum map_type type, u64 addr) 176 enum map_type type, u64 addr)
170{ 177{
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 04a3b3db9e90..5d2fd52fe7b5 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
82static 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
82struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) 88struct 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)
150void perf_session__delete(struct perf_session *self) 156void 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);
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
2110void 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
2110int machine__create_kernel_maps(struct machine *self) 2140int 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
2384void 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
2354int machine__load_kallsyms(struct machine *self, const char *filename, 2397int 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
215void machine__destroy_kernel_maps(struct machine *self);
215int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); 216int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
216int machine__create_kernel_maps(struct machine *self); 217int machine__create_kernel_maps(struct machine *self);
217 218
218int machines__create_kernel_maps(struct rb_root *self, pid_t pid); 219int machines__create_kernel_maps(struct rb_root *self, pid_t pid);
219int machines__create_guest_kernel_maps(struct rb_root *self); 220int machines__create_guest_kernel_maps(struct rb_root *self);
221void machines__destroy_guest_kernel_maps(struct rb_root *self);
220 222
221int symbol__init(void); 223int symbol__init(void);
222void symbol__exit(void); 224void symbol__exit(void);