aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-12-11 15:50:22 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-12 01:42:11 -0500
commit79406cd789f745ac6aa9d597895f904a98a14007 (patch)
tree99281664ea6e0fd5bd0a6f762feed4f716b356cd /tools/perf/util/symbol.c
parent22ccec57f8732de22fd87bce43e8edcb71453c72 (diff)
perf symbols: Allow lookups by symbol name too
Configurable via symbol_conf.sort_by_name, so that the cost of an extra rb_node on all 'struct symbol' instances is not paid by tools that only want to decode addresses. How to use it: symbol_conf.sort_by_name = true; symbol_init(&symbol_conf); struct map *map = map_groups__find_by_name(kmaps, MAP__VARIABLE, "[kernel.kallsyms]"); if (map == NULL) { pr_err("couldn't find map!\n"); kernel_maps__fprintf(stdout); } else { struct symbol *sym = map__find_symbol_by_name(map, sym_filter, NULL); if (sym == NULL) pr_err("couldn't find symbol %s!\n", sym_filter); else pr_info("symbol %s: %#Lx-%#Lx \n", sym_filter, sym->start, sym->end); } Looking over the vmlinux/kallsyms is common enough that I'll add a variable to the upcoming struct perf_session to avoid the need to use map_groups__find_by_name to get the main vmlinux/kallsyms map. The above example looks on the 'variable' symtab, but it is just like that for the functions one. Also the sort operation is done when we first use map__find_symbol_by_name, in a lazy way. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1260564622-12392-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c104
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
31static void dsos__add(struct list_head *head, struct dso *dso); 31static void dsos__add(struct list_head *head, struct dso *dso);
32static struct map *map_groups__find_by_name(struct map_groups *self, char *name);
33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 32static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
34struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); 33struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
35static int dso__load_kernel_sym(struct dso *self, struct map *map, 34static 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
53bool dso__sorted_by_name(const struct dso *self, enum map_type type)
54{
55 return self->sorted_by_name & (1 << type);
56}
57
54static void dso__set_loaded(struct dso *self, enum map_type type) 58static 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
63static void dso__set_sorted_by_name(struct dso *self, enum map_type type)
64{
65 self->sorted_by_name |= (1 << type);
66}
67
59static bool symbol_type__is_a(char symbol_type, enum map_type map_type) 68static 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
261struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr) 271struct symbol_name_rb_node {
272 struct rb_node rb_node;
273 struct symbol sym;
274};
275
276static 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
294static 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
304static 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
331struct 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
337struct 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
343void 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
266int build_id__sprintf(u8 *self, int len, char *bf) 350int 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
1229static struct map *map_groups__find_by_name(struct map_groups *self, char *name) 1313struct 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)