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) |
