]> Pileus Git - ~andy/linux/blobdiff - tools/perf/util/map.c
perf symbols: Allow lookups by symbol name too
[~andy/linux] / tools / perf / util / map.c
index f1e2169554202843487521aa23a194026b1b4933..175f1f6b691494fbf2ebc01fa91b946d0508a236 100644 (file)
@@ -20,9 +20,10 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
        return n;
 }
 
-void map__init(struct map *self, u64 start, u64 end, u64 pgoff,
-              struct dso *dso)
+void map__init(struct map *self, enum map_type type,
+              u64 start, u64 end, u64 pgoff, struct dso *dso)
 {
+       self->type     = type;
        self->start    = start;
        self->end      = end;
        self->pgoff    = pgoff;
@@ -32,7 +33,8 @@ void map__init(struct map *self, u64 start, u64 end, u64 pgoff,
        RB_CLEAR_NODE(&self->rb_node);
 }
 
-struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
+struct map *map__new(struct mmap_event *event, enum map_type type,
+                    char *cwd, int cwdlen)
 {
        struct map *self = malloc(sizeof(*self));
 
@@ -63,7 +65,7 @@ struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
                if (dso == NULL)
                        goto out_delete;
 
-               map__init(self, event->start, event->start + event->len,
+               map__init(self, type, event->start, event->start + event->len,
                          event->pgoff, dso);
 
                if (self->dso == vdso || anon)
@@ -75,36 +77,91 @@ out_delete:
        return NULL;
 }
 
+void map__delete(struct map *self)
+{
+       free(self);
+}
+
+void map__fixup_start(struct map *self)
+{
+       struct rb_root *symbols = &self->dso->symbols[self->type];
+       struct rb_node *nd = rb_first(symbols);
+       if (nd != NULL) {
+               struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
+               self->start = sym->start;
+       }
+}
+
+void map__fixup_end(struct map *self)
+{
+       struct rb_root *symbols = &self->dso->symbols[self->type];
+       struct rb_node *nd = rb_last(symbols);
+       if (nd != NULL) {
+               struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
+               self->end = sym->end;
+       }
+}
+
 #define DSO__DELETED "(deleted)"
 
-struct symbol *
-map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter)
+static int map__load(struct map *self, symbol_filter_t filter)
 {
-       if (!self->dso->loaded) {
-               int nr = dso__load(self->dso, self, filter);
-
-               if (nr < 0) {
-                       pr_warning("Failed to open %s, continuing without symbols\n",
-                                  self->dso->long_name);
-                       return NULL;
-               } else if (nr == 0) {
-                       const char *name = self->dso->long_name;
-                       const size_t len = strlen(name);
-                       const size_t real_len = len - sizeof(DSO__DELETED);
-
-                       if (len > sizeof(DSO__DELETED) &&
-                           strcmp(name + real_len + 1, DSO__DELETED) == 0)
-                               pr_warning("%.*s was updated, restart the "
-                                          "long running apps that use it!\n",
-                                          real_len, name);
-                       else
-                               pr_warning("no symbols found in %s, maybe "
-                                          "install a debug package?\n", name);
-                       return NULL;
+       const char *name = self->dso->long_name;
+       int nr = dso__load(self->dso, self, filter);
+
+       if (nr < 0) {
+               if (self->dso->has_build_id) {
+                       char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+
+                       build_id__sprintf(self->dso->build_id,
+                                         sizeof(self->dso->build_id),
+                                         sbuild_id);
+                       pr_warning("%s with build id %s not found",
+                                  name, sbuild_id);
+               } else
+                       pr_warning("Failed to open %s", name);
+
+               pr_warning(", continuing without symbols\n");
+               return -1;
+       } else if (nr == 0) {
+               const size_t len = strlen(name);
+               const size_t real_len = len - sizeof(DSO__DELETED);
+
+               if (len > sizeof(DSO__DELETED) &&
+                   strcmp(name + real_len + 1, DSO__DELETED) == 0) {
+                       pr_warning("%.*s was updated, restart the long "
+                                  "running apps that use it!\n",
+                                  (int)real_len, name);
+               } else {
+                       pr_warning("no symbols found in %s, maybe install "
+                                  "a debug package?\n", name);
                }
+
+               return -1;
        }
 
-       return self->dso->find_symbol(self->dso, ip);
+       return 0;
+}
+
+struct symbol *map__find_symbol(struct map *self, u64 addr,
+                               symbol_filter_t filter)
+{
+       if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
+               return NULL;
+
+       return self->dso->find_symbol(self->dso, self->type, addr);
+}
+
+struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
+                                       symbol_filter_t filter)
+{
+       if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
+               return NULL;
+
+       if (!dso__sorted_by_name(self->dso, self->type))
+               dso__sort_by_name(self->dso, self->type);
+
+       return dso__find_symbol_by_name(self->dso, self->type, name);
 }
 
 struct map *map__clone(struct map *self)