aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/map.c85
-rw-r--r--tools/perf/util/symbol.c104
-rw-r--r--tools/perf/util/symbol.h10
-rw-r--r--tools/perf/util/thread.h3
5 files changed, 163 insertions, 41 deletions
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 56640946b5a9..51a96c2effde 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -151,6 +151,8 @@ int map__overlap(struct map *l, struct map *r);
151size_t map__fprintf(struct map *self, FILE *fp); 151size_t map__fprintf(struct map *self, FILE *fp);
152struct symbol *map__find_symbol(struct map *self, u64 addr, 152struct symbol *map__find_symbol(struct map *self, u64 addr,
153 symbol_filter_t filter); 153 symbol_filter_t filter);
154struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
155 symbol_filter_t filter);
154void map__fixup_start(struct map *self); 156void map__fixup_start(struct map *self);
155void map__fixup_end(struct map *self); 157void map__fixup_end(struct map *self);
156 158
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 69f94fe9db20..175f1f6b6914 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));
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)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6e1da1ea6311..51c401307bf1 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -52,7 +52,8 @@ struct symbol {
52struct symbol_conf { 52struct symbol_conf {
53 unsigned short priv_size; 53 unsigned short priv_size;
54 bool try_vmlinux_path, 54 bool try_vmlinux_path,
55 use_modules; 55 use_modules,
56 sort_by_name;
56 const char *vmlinux_name; 57 const char *vmlinux_name;
57}; 58};
58 59
@@ -74,6 +75,7 @@ struct addr_location {
74struct dso { 75struct dso {
75 struct list_head node; 76 struct list_head node;
76 struct rb_root symbols[MAP__NR_TYPES]; 77 struct rb_root symbols[MAP__NR_TYPES];
78 struct rb_root symbol_names[MAP__NR_TYPES];
77 struct symbol *(*find_symbol)(struct dso *self, 79 struct symbol *(*find_symbol)(struct dso *self,
78 enum map_type type, u64 addr); 80 enum map_type type, u64 addr);
79 u8 adjust_symbols:1; 81 u8 adjust_symbols:1;
@@ -81,6 +83,7 @@ struct dso {
81 u8 has_build_id:1; 83 u8 has_build_id:1;
82 u8 kernel:1; 84 u8 kernel:1;
83 unsigned char origin; 85 unsigned char origin;
86 u8 sorted_by_name;
84 u8 loaded; 87 u8 loaded;
85 u8 build_id[BUILD_ID_SIZE]; 88 u8 build_id[BUILD_ID_SIZE];
86 u16 long_name_len; 89 u16 long_name_len;
@@ -93,6 +96,9 @@ struct dso *dso__new(const char *name);
93void dso__delete(struct dso *self); 96void dso__delete(struct dso *self);
94 97
95bool dso__loaded(const struct dso *self, enum map_type type); 98bool dso__loaded(const struct dso *self, enum map_type type);
99bool dso__sorted_by_name(const struct dso *self, enum map_type type);
100
101void dso__sort_by_name(struct dso *self, enum map_type type);
96 102
97struct dso *dsos__findnew(const char *name); 103struct dso *dsos__findnew(const char *name);
98int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 104int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
@@ -103,6 +109,8 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
103size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); 109size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
104char dso__symtab_origin(const struct dso *self); 110char dso__symtab_origin(const struct dso *self);
105void dso__set_build_id(struct dso *self, void *build_id); 111void dso__set_build_id(struct dso *self, void *build_id);
112struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
113 const char *name);
106 114
107int filename__read_build_id(const char *filename, void *bf, size_t size); 115int filename__read_build_id(const char *filename, void *bf, size_t size);
108int sysfs__read_build_id(const char *filename, void *bf, size_t size); 116int sysfs__read_build_id(const char *filename, void *bf, size_t size);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index a6333f3716af..1751802a09ba 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -64,4 +64,7 @@ map_groups__find_function(struct map_groups *self, u64 addr,
64{ 64{
65 return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); 65 return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter);
66} 66}
67
68struct map *map_groups__find_by_name(struct map_groups *self,
69 enum map_type type, const char *name);
67#endif /* __PERF_THREAD_H */ 70#endif /* __PERF_THREAD_H */