diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-11-27 13:29:17 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-27 14:21:59 -0500 |
commit | 6a4694a433a218c729d336b348a01bfc720da095 (patch) | |
tree | 19c166d8cb244fa0ec504cd49f7de957552ce573 | |
parent | 3610583c29563e23dd038d2870f59c88438bf7a3 (diff) |
perf symbols: Better support for multiple symbol tables per dso
By using an array of rb_roots in struct dso we can, from a
struct map instance to get the right symbol rb_tree more easily.
This way we can have just one symbol lookup method for struct
map instances, map__find_symbol, instead of one per symtab type
(functions, variables).
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-6-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.h | 12 | ||||
-rw-r--r-- | tools/perf/util/map.c | 12 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 59 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 7 |
7 files changed, 56 insertions, 40 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 0846c8a155ed..c32e7609b77b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -170,7 +170,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
170 | map = thread__find_map(thread, ip); | 170 | map = thread__find_map(thread, ip); |
171 | if (map != NULL) { | 171 | if (map != NULL) { |
172 | ip = map->map_ip(map, ip); | 172 | ip = map->map_ip(map, ip); |
173 | sym = map__find_function(map, ip, symbol_filter); | 173 | sym = map__find_symbol(map, ip, symbol_filter); |
174 | } else { | 174 | } else { |
175 | /* | 175 | /* |
176 | * If this is outside of all known maps, | 176 | * If this is outside of all known maps, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e4b1004e76ea..400bef981c6c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -455,7 +455,7 @@ got_map: | |||
455 | dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); | 455 | dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); |
456 | *ipp = ip; | 456 | *ipp = ip; |
457 | 457 | ||
458 | return map ? map__find_function(map, ip, NULL) : NULL; | 458 | return map ? map__find_symbol(map, ip, NULL) : NULL; |
459 | } | 459 | } |
460 | 460 | ||
461 | static int call__match(struct symbol *sym) | 461 | static int call__match(struct symbol *sym) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index a0168f260d06..abe78bbd154a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -948,7 +948,7 @@ static void event__process_sample(const event_t *self, int counter) | |||
948 | map = thread__find_map(thread, ip); | 948 | map = thread__find_map(thread, ip); |
949 | if (map != NULL) { | 949 | if (map != NULL) { |
950 | ip = map->map_ip(map, ip); | 950 | ip = map->map_ip(map, ip); |
951 | sym = map__find_function(map, ip, symbol_filter); | 951 | sym = map__find_symbol(map, ip, symbol_filter); |
952 | if (sym == NULL) | 952 | if (sym == NULL) |
953 | return; | 953 | return; |
954 | userspace_samples++; | 954 | userspace_samples++; |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 29543bd88007..3ae3c964c901 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -81,7 +81,9 @@ typedef union event_union { | |||
81 | } event_t; | 81 | } event_t; |
82 | 82 | ||
83 | enum map_type { | 83 | enum map_type { |
84 | MAP__FUNCTION, | 84 | MAP__FUNCTION = 0, |
85 | |||
86 | MAP__NR_TYPES, | ||
85 | }; | 87 | }; |
86 | 88 | ||
87 | struct map { | 89 | struct map { |
@@ -125,10 +127,10 @@ void map__delete(struct map *self); | |||
125 | struct map *map__clone(struct map *self); | 127 | struct map *map__clone(struct map *self); |
126 | int map__overlap(struct map *l, struct map *r); | 128 | int map__overlap(struct map *l, struct map *r); |
127 | size_t map__fprintf(struct map *self, FILE *fp); | 129 | size_t map__fprintf(struct map *self, FILE *fp); |
128 | struct symbol *map__find_function(struct map *self, u64 ip, | 130 | struct symbol *map__find_symbol(struct map *self, u64 addr, |
129 | symbol_filter_t filter); | 131 | symbol_filter_t filter); |
130 | void map__fixup_start(struct map *self, struct rb_root *symbols); | 132 | void map__fixup_start(struct map *self); |
131 | void map__fixup_end(struct map *self, struct rb_root *symbols); | 133 | void map__fixup_end(struct map *self); |
132 | 134 | ||
133 | int event__synthesize_thread(pid_t pid, int (*process)(event_t *event)); | 135 | int event__synthesize_thread(pid_t pid, int (*process)(event_t *event)); |
134 | void event__synthesize_threads(int (*process)(event_t *event)); | 136 | void event__synthesize_threads(int (*process)(event_t *event)); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 52bb4c6cf74d..69f94fe9db20 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -82,8 +82,9 @@ void map__delete(struct map *self) | |||
82 | free(self); | 82 | free(self); |
83 | } | 83 | } |
84 | 84 | ||
85 | void map__fixup_start(struct map *self, struct rb_root *symbols) | 85 | void map__fixup_start(struct map *self) |
86 | { | 86 | { |
87 | struct rb_root *symbols = &self->dso->symbols[self->type]; | ||
87 | struct rb_node *nd = rb_first(symbols); | 88 | struct rb_node *nd = rb_first(symbols); |
88 | if (nd != NULL) { | 89 | if (nd != NULL) { |
89 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 90 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); |
@@ -91,8 +92,9 @@ void map__fixup_start(struct map *self, struct rb_root *symbols) | |||
91 | } | 92 | } |
92 | } | 93 | } |
93 | 94 | ||
94 | void map__fixup_end(struct map *self, struct rb_root *symbols) | 95 | void map__fixup_end(struct map *self) |
95 | { | 96 | { |
97 | struct rb_root *symbols = &self->dso->symbols[self->type]; | ||
96 | struct rb_node *nd = rb_last(symbols); | 98 | struct rb_node *nd = rb_last(symbols); |
97 | if (nd != NULL) { | 99 | if (nd != NULL) { |
98 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 100 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); |
@@ -102,8 +104,8 @@ void map__fixup_end(struct map *self, struct rb_root *symbols) | |||
102 | 104 | ||
103 | #define DSO__DELETED "(deleted)" | 105 | #define DSO__DELETED "(deleted)" |
104 | 106 | ||
105 | struct symbol *map__find_function(struct map *self, u64 ip, | 107 | struct symbol *map__find_symbol(struct map *self, u64 addr, |
106 | symbol_filter_t filter) | 108 | symbol_filter_t filter) |
107 | { | 109 | { |
108 | if (!dso__loaded(self->dso, self->type)) { | 110 | if (!dso__loaded(self->dso, self->type)) { |
109 | int nr = dso__load(self->dso, self, filter); | 111 | int nr = dso__load(self->dso, self, filter); |
@@ -138,7 +140,7 @@ struct symbol *map__find_function(struct map *self, u64 ip, | |||
138 | } | 140 | } |
139 | } | 141 | } |
140 | 142 | ||
141 | return self->dso->find_function(self->dso, ip); | 143 | return self->dso->find_symbol(self->dso, self->type, addr); |
142 | } | 144 | } |
143 | 145 | ||
144 | struct map *map__clone(struct map *self) | 146 | struct map *map__clone(struct map *self) |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 45a4a9a7618b..9a2dd819dee4 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -31,6 +31,7 @@ enum dso_origin { | |||
31 | static void dsos__add(struct list_head *head, struct dso *dso); | 31 | static void dsos__add(struct list_head *head, struct dso *dso); |
32 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 32 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
33 | static void kernel_maps__insert(struct map *map); | 33 | static void kernel_maps__insert(struct map *map); |
34 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); | ||
34 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 35 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
35 | symbol_filter_t filter); | 36 | symbol_filter_t filter); |
36 | unsigned int symbol__priv_size; | 37 | unsigned int symbol__priv_size; |
@@ -151,11 +152,13 @@ struct dso *dso__new(const char *name) | |||
151 | struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); | 152 | struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); |
152 | 153 | ||
153 | if (self != NULL) { | 154 | if (self != NULL) { |
155 | int i; | ||
154 | strcpy(self->name, name); | 156 | strcpy(self->name, name); |
155 | dso__set_long_name(self, self->name); | 157 | dso__set_long_name(self, self->name); |
156 | self->short_name = self->name; | 158 | self->short_name = self->name; |
157 | self->functions = RB_ROOT; | 159 | for (i = 0; i < MAP__NR_TYPES; ++i) |
158 | self->find_function = dso__find_function; | 160 | self->symbols[i] = RB_ROOT; |
161 | self->find_symbol = dso__find_symbol; | ||
159 | self->slen_calculated = 0; | 162 | self->slen_calculated = 0; |
160 | self->origin = DSO__ORIG_NOT_FOUND; | 163 | self->origin = DSO__ORIG_NOT_FOUND; |
161 | self->loaded = 0; | 164 | self->loaded = 0; |
@@ -180,7 +183,9 @@ static void symbols__delete(struct rb_root *self) | |||
180 | 183 | ||
181 | void dso__delete(struct dso *self) | 184 | void dso__delete(struct dso *self) |
182 | { | 185 | { |
183 | symbols__delete(&self->functions); | 186 | int i; |
187 | for (i = 0; i < MAP__NR_TYPES; ++i) | ||
188 | symbols__delete(&self->symbols[i]); | ||
184 | if (self->long_name != self->name) | 189 | if (self->long_name != self->name) |
185 | free(self->long_name); | 190 | free(self->long_name); |
186 | free(self); | 191 | free(self); |
@@ -234,9 +239,9 @@ static struct symbol *symbols__find(struct rb_root *self, u64 ip) | |||
234 | return NULL; | 239 | return NULL; |
235 | } | 240 | } |
236 | 241 | ||
237 | struct symbol *dso__find_function(struct dso *self, u64 ip) | 242 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr) |
238 | { | 243 | { |
239 | return symbols__find(&self->functions, ip); | 244 | return symbols__find(&self->symbols[type], addr); |
240 | } | 245 | } |
241 | 246 | ||
242 | int build_id__sprintf(u8 *self, int len, char *bf) | 247 | int build_id__sprintf(u8 *self, int len, char *bf) |
@@ -262,17 +267,25 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp) | |||
262 | return fprintf(fp, "%s", sbuild_id); | 267 | return fprintf(fp, "%s", sbuild_id); |
263 | } | 268 | } |
264 | 269 | ||
270 | static const char * map_type__name[MAP__NR_TYPES] = { | ||
271 | [MAP__FUNCTION] = "Functions", | ||
272 | }; | ||
273 | |||
265 | size_t dso__fprintf(struct dso *self, FILE *fp) | 274 | size_t dso__fprintf(struct dso *self, FILE *fp) |
266 | { | 275 | { |
276 | int i; | ||
267 | struct rb_node *nd; | 277 | struct rb_node *nd; |
268 | size_t ret = fprintf(fp, "dso: %s (", self->short_name); | 278 | size_t ret = fprintf(fp, "dso: %s (", self->short_name); |
269 | 279 | ||
270 | ret += dso__fprintf_buildid(self, fp); | 280 | ret += dso__fprintf_buildid(self, fp); |
271 | ret += fprintf(fp, ")\nFunctions:\n"); | 281 | ret += fprintf(fp, ")\n"); |
282 | for (i = 0; i < MAP__NR_TYPES; ++i) { | ||
283 | ret += fprintf(fp, "%s:\n", map_type__name[i]); | ||
272 | 284 | ||
273 | for (nd = rb_first(&self->functions); nd; nd = rb_next(nd)) { | 285 | for (nd = rb_first(&self->symbols[i]); nd; nd = rb_next(nd)) { |
274 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); | 286 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); |
275 | ret += symbol__fprintf(pos, fp); | 287 | ret += symbol__fprintf(pos, fp); |
288 | } | ||
276 | } | 289 | } |
277 | 290 | ||
278 | return ret; | 291 | return ret; |
@@ -335,7 +348,7 @@ static int kernel_maps__load_all_kallsyms(void) | |||
335 | * kernel_maps__split_kallsyms, when we have split the | 348 | * kernel_maps__split_kallsyms, when we have split the |
336 | * maps per module | 349 | * maps per module |
337 | */ | 350 | */ |
338 | symbols__insert(&kernel_map__functions->dso->functions, sym); | 351 | symbols__insert(&kernel_map__functions->dso->symbols[MAP__FUNCTION], sym); |
339 | } | 352 | } |
340 | 353 | ||
341 | free(line); | 354 | free(line); |
@@ -359,7 +372,7 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter) | |||
359 | struct map *map = kernel_map__functions; | 372 | struct map *map = kernel_map__functions; |
360 | struct symbol *pos; | 373 | struct symbol *pos; |
361 | int count = 0; | 374 | int count = 0; |
362 | struct rb_node *next = rb_first(&kernel_map__functions->dso->functions); | 375 | struct rb_node *next = rb_first(&kernel_map__functions->dso->symbols[map->type]); |
363 | int kernel_range = 0; | 376 | int kernel_range = 0; |
364 | 377 | ||
365 | while (next) { | 378 | while (next) { |
@@ -409,13 +422,13 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter) | |||
409 | } | 422 | } |
410 | 423 | ||
411 | if (filter && filter(map, pos)) { | 424 | if (filter && filter(map, pos)) { |
412 | rb_erase(&pos->rb_node, &kernel_map__functions->dso->functions); | 425 | rb_erase(&pos->rb_node, &kernel_map__functions->dso->symbols[map->type]); |
413 | symbol__delete(pos); | 426 | symbol__delete(pos); |
414 | } else { | 427 | } else { |
415 | if (map != kernel_map__functions) { | 428 | if (map != kernel_map__functions) { |
416 | rb_erase(&pos->rb_node, | 429 | rb_erase(&pos->rb_node, |
417 | &kernel_map__functions->dso->functions); | 430 | &kernel_map__functions->dso->symbols[map->type]); |
418 | symbols__insert(&map->dso->functions, pos); | 431 | symbols__insert(&map->dso->symbols[map->type], pos); |
419 | } | 432 | } |
420 | count++; | 433 | count++; |
421 | } | 434 | } |
@@ -430,7 +443,7 @@ static int kernel_maps__load_kallsyms(symbol_filter_t filter) | |||
430 | if (kernel_maps__load_all_kallsyms()) | 443 | if (kernel_maps__load_all_kallsyms()) |
431 | return -1; | 444 | return -1; |
432 | 445 | ||
433 | symbols__fixup_end(&kernel_map__functions->dso->functions); | 446 | symbols__fixup_end(&kernel_map__functions->dso->symbols[MAP__FUNCTION]); |
434 | kernel_map__functions->dso->origin = DSO__ORIG_KERNEL; | 447 | kernel_map__functions->dso->origin = DSO__ORIG_KERNEL; |
435 | 448 | ||
436 | return kernel_maps__split_kallsyms(filter); | 449 | return kernel_maps__split_kallsyms(filter); |
@@ -501,7 +514,7 @@ static int dso__load_perf_map(struct dso *self, struct map *map, | |||
501 | if (filter && filter(map, sym)) | 514 | if (filter && filter(map, sym)) |
502 | symbol__delete(sym); | 515 | symbol__delete(sym); |
503 | else { | 516 | else { |
504 | symbols__insert(&self->functions, sym); | 517 | symbols__insert(&self->symbols[map->type], sym); |
505 | nr_syms++; | 518 | nr_syms++; |
506 | } | 519 | } |
507 | } | 520 | } |
@@ -699,7 +712,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, | |||
699 | if (filter && filter(map, f)) | 712 | if (filter && filter(map, f)) |
700 | symbol__delete(f); | 713 | symbol__delete(f); |
701 | else { | 714 | else { |
702 | symbols__insert(&self->functions, f); | 715 | symbols__insert(&self->symbols[map->type], f); |
703 | ++nr; | 716 | ++nr; |
704 | } | 717 | } |
705 | } | 718 | } |
@@ -721,7 +734,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, | |||
721 | if (filter && filter(map, f)) | 734 | if (filter && filter(map, f)) |
722 | symbol__delete(f); | 735 | symbol__delete(f); |
723 | else { | 736 | else { |
724 | symbols__insert(&self->functions, f); | 737 | symbols__insert(&self->symbols[map->type], f); |
725 | ++nr; | 738 | ++nr; |
726 | } | 739 | } |
727 | } | 740 | } |
@@ -896,7 +909,7 @@ new_symbol: | |||
896 | if (filter && filter(curr_map, f)) | 909 | if (filter && filter(curr_map, f)) |
897 | symbol__delete(f); | 910 | symbol__delete(f); |
898 | else { | 911 | else { |
899 | symbols__insert(&curr_dso->functions, f); | 912 | symbols__insert(&curr_dso->symbols[curr_map->type], f); |
900 | nr++; | 913 | nr++; |
901 | } | 914 | } |
902 | } | 915 | } |
@@ -905,7 +918,7 @@ new_symbol: | |||
905 | * For misannotated, zeroed, ASM function sizes. | 918 | * For misannotated, zeroed, ASM function sizes. |
906 | */ | 919 | */ |
907 | if (nr > 0) | 920 | if (nr > 0) |
908 | symbols__fixup_end(&self->functions); | 921 | symbols__fixup_end(&self->symbols[map->type]); |
909 | err = nr; | 922 | err = nr; |
910 | out_elf_end: | 923 | out_elf_end: |
911 | elf_end(elf); | 924 | elf_end(elf); |
@@ -1191,7 +1204,7 @@ struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp, | |||
1191 | 1204 | ||
1192 | if (map) { | 1205 | if (map) { |
1193 | ip = map->map_ip(map, ip); | 1206 | ip = map->map_ip(map, ip); |
1194 | return map__find_function(map, ip, filter); | 1207 | return map__find_symbol(map, ip, filter); |
1195 | } else | 1208 | } else |
1196 | WARN_ONCE(RB_EMPTY_ROOT(&kernel_maps__functions), | 1209 | WARN_ONCE(RB_EMPTY_ROOT(&kernel_maps__functions), |
1197 | "Empty kernel_maps, was symbol__init() called?\n"); | 1210 | "Empty kernel_maps, was symbol__init() called?\n"); |
@@ -1453,8 +1466,8 @@ do_kallsyms: | |||
1453 | 1466 | ||
1454 | if (err > 0) { | 1467 | if (err > 0) { |
1455 | out_fixup: | 1468 | out_fixup: |
1456 | map__fixup_start(map, &map->dso->functions); | 1469 | map__fixup_start(map); |
1457 | map__fixup_end(map, &map->dso->functions); | 1470 | map__fixup_end(map); |
1458 | } | 1471 | } |
1459 | 1472 | ||
1460 | return err; | 1473 | return err; |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 11d41952ce04..8934814d5a64 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -65,8 +65,9 @@ static inline void *symbol__priv(struct symbol *self) | |||
65 | 65 | ||
66 | struct dso { | 66 | struct dso { |
67 | struct list_head node; | 67 | struct list_head node; |
68 | struct rb_root functions; | 68 | struct rb_root symbols[MAP__NR_TYPES]; |
69 | struct symbol *(*find_function)(struct dso *, u64 ip); | 69 | struct symbol *(*find_symbol)(struct dso *self, |
70 | enum map_type type, u64 addr); | ||
70 | u8 adjust_symbols:1; | 71 | u8 adjust_symbols:1; |
71 | u8 slen_calculated:1; | 72 | u8 slen_calculated:1; |
72 | u8 has_build_id:1; | 73 | u8 has_build_id:1; |
@@ -83,8 +84,6 @@ struct dso { | |||
83 | struct dso *dso__new(const char *name); | 84 | struct dso *dso__new(const char *name); |
84 | void dso__delete(struct dso *self); | 85 | void dso__delete(struct dso *self); |
85 | 86 | ||
86 | struct symbol *dso__find_function(struct dso *self, u64 ip); | ||
87 | |||
88 | bool dso__loaded(const struct dso *self, enum map_type type); | 87 | bool dso__loaded(const struct dso *self, enum map_type type); |
89 | 88 | ||
90 | struct dso *dsos__findnew(const char *name); | 89 | struct dso *dsos__findnew(const char *name); |