diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 104 |
1 files changed, 96 insertions, 8 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e63ddb469de7..8134c49deae6 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -29,7 +29,6 @@ enum dso_origin { | |||
29 | }; | 29 | }; |
30 | 30 | ||
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_groups__find_by_name(struct map_groups *self, char *name); | ||
33 | 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); |
34 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); | 33 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); |
35 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 34 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
@@ -51,11 +50,21 @@ bool dso__loaded(const struct dso *self, enum map_type type) | |||
51 | return self->loaded & (1 << type); | 50 | return self->loaded & (1 << type); |
52 | } | 51 | } |
53 | 52 | ||
53 | bool dso__sorted_by_name(const struct dso *self, enum map_type type) | ||
54 | { | ||
55 | return self->sorted_by_name & (1 << type); | ||
56 | } | ||
57 | |||
54 | static void dso__set_loaded(struct dso *self, enum map_type type) | 58 | static void dso__set_loaded(struct dso *self, enum map_type type) |
55 | { | 59 | { |
56 | self->loaded |= (1 << type); | 60 | self->loaded |= (1 << type); |
57 | } | 61 | } |
58 | 62 | ||
63 | static void dso__set_sorted_by_name(struct dso *self, enum map_type type) | ||
64 | { | ||
65 | self->sorted_by_name |= (1 << type); | ||
66 | } | ||
67 | |||
59 | static bool symbol_type__is_a(char symbol_type, enum map_type map_type) | 68 | static bool symbol_type__is_a(char symbol_type, enum map_type map_type) |
60 | { | 69 | { |
61 | switch (map_type) { | 70 | switch (map_type) { |
@@ -176,11 +185,12 @@ struct dso *dso__new(const char *name) | |||
176 | dso__set_long_name(self, self->name); | 185 | dso__set_long_name(self, self->name); |
177 | self->short_name = self->name; | 186 | self->short_name = self->name; |
178 | for (i = 0; i < MAP__NR_TYPES; ++i) | 187 | for (i = 0; i < MAP__NR_TYPES; ++i) |
179 | self->symbols[i] = RB_ROOT; | 188 | self->symbols[i] = self->symbol_names[i] = RB_ROOT; |
180 | self->find_symbol = dso__find_symbol; | 189 | self->find_symbol = dso__find_symbol; |
181 | self->slen_calculated = 0; | 190 | self->slen_calculated = 0; |
182 | self->origin = DSO__ORIG_NOT_FOUND; | 191 | self->origin = DSO__ORIG_NOT_FOUND; |
183 | self->loaded = 0; | 192 | self->loaded = 0; |
193 | self->sorted_by_name = 0; | ||
184 | self->has_build_id = 0; | 194 | self->has_build_id = 0; |
185 | } | 195 | } |
186 | 196 | ||
@@ -258,11 +268,85 @@ static struct symbol *symbols__find(struct rb_root *self, u64 ip) | |||
258 | return NULL; | 268 | return NULL; |
259 | } | 269 | } |
260 | 270 | ||
261 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr) | 271 | struct symbol_name_rb_node { |
272 | struct rb_node rb_node; | ||
273 | struct symbol sym; | ||
274 | }; | ||
275 | |||
276 | static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym) | ||
277 | { | ||
278 | struct rb_node **p = &self->rb_node; | ||
279 | struct rb_node *parent = NULL; | ||
280 | struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s; | ||
281 | |||
282 | while (*p != NULL) { | ||
283 | parent = *p; | ||
284 | s = rb_entry(parent, struct symbol_name_rb_node, rb_node); | ||
285 | if (strcmp(sym->name, s->sym.name) < 0) | ||
286 | p = &(*p)->rb_left; | ||
287 | else | ||
288 | p = &(*p)->rb_right; | ||
289 | } | ||
290 | rb_link_node(&symn->rb_node, parent, p); | ||
291 | rb_insert_color(&symn->rb_node, self); | ||
292 | } | ||
293 | |||
294 | static void symbols__sort_by_name(struct rb_root *self, struct rb_root *source) | ||
295 | { | ||
296 | struct rb_node *nd; | ||
297 | |||
298 | for (nd = rb_first(source); nd; nd = rb_next(nd)) { | ||
299 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); | ||
300 | symbols__insert_by_name(self, pos); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | static struct symbol *symbols__find_by_name(struct rb_root *self, const char *name) | ||
305 | { | ||
306 | struct rb_node *n; | ||
307 | |||
308 | if (self == NULL) | ||
309 | return NULL; | ||
310 | |||
311 | n = self->rb_node; | ||
312 | |||
313 | while (n) { | ||
314 | struct symbol_name_rb_node *s; | ||
315 | int cmp; | ||
316 | |||
317 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); | ||
318 | cmp = strcmp(name, s->sym.name); | ||
319 | |||
320 | if (cmp < 0) | ||
321 | n = n->rb_left; | ||
322 | else if (cmp > 0) | ||
323 | n = n->rb_right; | ||
324 | else | ||
325 | return &s->sym; | ||
326 | } | ||
327 | |||
328 | return NULL; | ||
329 | } | ||
330 | |||
331 | struct symbol *dso__find_symbol(struct dso *self, | ||
332 | enum map_type type, u64 addr) | ||
262 | { | 333 | { |
263 | return symbols__find(&self->symbols[type], addr); | 334 | return symbols__find(&self->symbols[type], addr); |
264 | } | 335 | } |
265 | 336 | ||
337 | struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, | ||
338 | const char *name) | ||
339 | { | ||
340 | return symbols__find_by_name(&self->symbol_names[type], name); | ||
341 | } | ||
342 | |||
343 | void dso__sort_by_name(struct dso *self, enum map_type type) | ||
344 | { | ||
345 | dso__set_sorted_by_name(self, type); | ||
346 | return symbols__sort_by_name(&self->symbol_names[type], | ||
347 | &self->symbols[type]); | ||
348 | } | ||
349 | |||
266 | int build_id__sprintf(u8 *self, int len, char *bf) | 350 | int build_id__sprintf(u8 *self, int len, char *bf) |
267 | { | 351 | { |
268 | char *bid = bf; | 352 | char *bid = bf; |
@@ -397,7 +481,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
397 | *module++ = '\0'; | 481 | *module++ = '\0'; |
398 | 482 | ||
399 | if (strcmp(self->name, module)) { | 483 | if (strcmp(self->name, module)) { |
400 | curr_map = map_groups__find_by_name(mg, module); | 484 | curr_map = map_groups__find_by_name(mg, map->type, module); |
401 | if (curr_map == NULL) { | 485 | if (curr_map == NULL) { |
402 | pr_debug("/proc/{kallsyms,modules} " | 486 | pr_debug("/proc/{kallsyms,modules} " |
403 | "inconsistency!\n"); | 487 | "inconsistency!\n"); |
@@ -895,7 +979,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
895 | snprintf(dso_name, sizeof(dso_name), | 979 | snprintf(dso_name, sizeof(dso_name), |
896 | "%s%s", self->short_name, section_name); | 980 | "%s%s", self->short_name, section_name); |
897 | 981 | ||
898 | curr_map = map_groups__find_by_name(mg, dso_name); | 982 | curr_map = map_groups__find_by_name(mg, map->type, dso_name); |
899 | if (curr_map == NULL) { | 983 | if (curr_map == NULL) { |
900 | u64 start = sym.st_value; | 984 | u64 start = sym.st_value; |
901 | 985 | ||
@@ -1226,11 +1310,12 @@ out: | |||
1226 | return ret; | 1310 | return ret; |
1227 | } | 1311 | } |
1228 | 1312 | ||
1229 | static struct map *map_groups__find_by_name(struct map_groups *self, char *name) | 1313 | struct map *map_groups__find_by_name(struct map_groups *self, |
1314 | enum map_type type, const char *name) | ||
1230 | { | 1315 | { |
1231 | struct rb_node *nd; | 1316 | struct rb_node *nd; |
1232 | 1317 | ||
1233 | for (nd = rb_first(&self->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { | 1318 | for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { |
1234 | struct map *map = rb_entry(nd, struct map, rb_node); | 1319 | struct map *map = rb_entry(nd, struct map, rb_node); |
1235 | 1320 | ||
1236 | if (map->dso && strcmp(map->dso->name, name) == 0) | 1321 | if (map->dso && strcmp(map->dso->name, name) == 0) |
@@ -1274,7 +1359,7 @@ static int dsos__set_modules_path_dir(char *dirname) | |||
1274 | (int)(dot - dent->d_name), dent->d_name); | 1359 | (int)(dot - dent->d_name), dent->d_name); |
1275 | 1360 | ||
1276 | strxfrchar(dso_name, '-', '_'); | 1361 | strxfrchar(dso_name, '-', '_'); |
1277 | map = map_groups__find_by_name(kmaps, dso_name); | 1362 | map = map_groups__find_by_name(kmaps, MAP__FUNCTION, dso_name); |
1278 | if (map == NULL) | 1363 | if (map == NULL) |
1279 | continue; | 1364 | continue; |
1280 | 1365 | ||
@@ -1671,6 +1756,9 @@ int symbol__init(struct symbol_conf *conf) | |||
1671 | 1756 | ||
1672 | elf_version(EV_CURRENT); | 1757 | elf_version(EV_CURRENT); |
1673 | symbol__priv_size = pconf->priv_size; | 1758 | symbol__priv_size = pconf->priv_size; |
1759 | if (pconf->sort_by_name) | ||
1760 | symbol__priv_size += (sizeof(struct symbol_name_rb_node) - | ||
1761 | sizeof(struct symbol)); | ||
1674 | map_groups__init(kmaps); | 1762 | map_groups__init(kmaps); |
1675 | 1763 | ||
1676 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) | 1764 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) |