aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/map.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/map.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/map.c')
-rw-r--r--tools/perf/util/map.c85
1 files changed, 53 insertions, 32 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 69f94fe9db2..175f1f6b691 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -104,45 +104,66 @@ void map__fixup_end(struct map *self)
104 104
105#define DSO__DELETED "(deleted)" 105#define DSO__DELETED "(deleted)"
106 106
107struct symbol *map__find_symbol(struct map *self, u64 addr, 107static int map__load(struct map *self, symbol_filter_t filter)
108 symbol_filter_t filter)
109{ 108{
110 if (!dso__loaded(self->dso, self->type)) { 109 const char *name = self->dso->long_name;
111 int nr = dso__load(self->dso, self, filter); 110 int nr = dso__load(self->dso, self, filter);
112 111
113 if (nr < 0) { 112 if (nr < 0) {
114 if (self->dso->has_build_id) { 113 if (self->dso->has_build_id) {
115 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 114 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
116 115
117 build_id__sprintf(self->dso->build_id, 116 build_id__sprintf(self->dso->build_id,
118 sizeof(self->dso->build_id), 117 sizeof(self->dso->build_id),
119 sbuild_id); 118 sbuild_id);
120 pr_warning("%s with build id %s not found", 119 pr_warning("%s with build id %s not found",
121 self->dso->long_name, sbuild_id); 120 name, sbuild_id);
122 } else 121 } else
123 pr_warning("Failed to open %s", 122 pr_warning("Failed to open %s", name);
124 self->dso->long_name); 123
125 pr_warning(", continuing without symbols\n"); 124 pr_warning(", continuing without symbols\n");
126 return NULL; 125 return -1;
127 } else if (nr == 0) { 126 } else if (nr == 0) {
128 const char *name = self->dso->long_name; 127 const size_t len = strlen(name);
129 const size_t len = strlen(name); 128 const size_t real_len = len - sizeof(DSO__DELETED);
130 const size_t real_len = len - sizeof(DSO__DELETED); 129
131 130 if (len > sizeof(DSO__DELETED) &&
132 if (len > sizeof(DSO__DELETED) && 131 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
133 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 132 pr_warning("%.*s was updated, restart the long "
134 pr_warning("%.*s was updated, restart the long running apps that use it!\n", 133 "running apps that use it!\n",
135 (int)real_len, name); 134 (int)real_len, name);
136 } else { 135 } else {
137 pr_warning("no symbols found in %s, maybe install a debug package?\n", name); 136 pr_warning("no symbols found in %s, maybe install "
138 } 137 "a debug package?\n", name);
139 return NULL;
140 } 138 }
139
140 return -1;
141 } 141 }
142 142
143 return 0;
144}
145
146struct symbol *map__find_symbol(struct map *self, u64 addr,
147 symbol_filter_t filter)
148{
149 if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
150 return NULL;
151
143 return self->dso->find_symbol(self->dso, self->type, addr); 152 return self->dso->find_symbol(self->dso, self->type, addr);
144} 153}
145 154
155struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
156 symbol_filter_t filter)
157{
158 if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
159 return NULL;
160
161 if (!dso__sorted_by_name(self->dso, self->type))
162 dso__sort_by_name(self->dso, self->type);
163
164 return dso__find_symbol_by_name(self->dso, self->type, name);
165}
166
146struct map *map__clone(struct map *self) 167struct map *map__clone(struct map *self)
147{ 168{
148 struct map *map = malloc(sizeof(*self)); 169 struct map *map = malloc(sizeof(*self));