- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / tools / perf / util / map.c
index 804e023..c4d55a0 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include "debug.h"
 
 static inline int is_anon_memory(const char *filename)
 {
@@ -19,13 +20,28 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
        return n;
 }
 
- struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
+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;
+       self->dso      = dso;
+       self->map_ip   = map__map_ip;
+       self->unmap_ip = map__unmap_ip;
+       RB_CLEAR_NODE(&self->rb_node);
+}
+
+struct map *map__new(struct mmap_event *event, enum map_type type,
+                    char *cwd, int cwdlen)
 {
        struct map *self = malloc(sizeof(*self));
 
        if (self != NULL) {
                const char *filename = event->filename;
                char newfilename[PATH_MAX];
+               struct dso *dso;
                int anon;
 
                if (cwd) {
@@ -45,18 +61,15 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
                        filename = newfilename;
                }
 
-               self->start = event->start;
-               self->end   = event->start + event->len;
-               self->pgoff = event->pgoff;
-
-               self->dso = dsos__findnew(filename);
-               if (self->dso == NULL)
+               dso = dsos__findnew(filename);
+               if (dso == NULL)
                        goto out_delete;
 
+               map__init(self, type, event->start, event->start + event->len,
+                         event->pgoff, dso);
+
                if (self->dso == vdso || anon)
-                       self->map_ip = vdso__map_ip;
-               else
-                       self->map_ip = map__map_ip;
+                       self->map_ip = self->unmap_ip = identity__map_ip;
        }
        return self;
 out_delete:
@@ -64,6 +77,99 @@ 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)"
+
+int map__load(struct map *self, struct perf_session *session,
+             symbol_filter_t filter)
+{
+       const char *name = self->dso->long_name;
+       int nr;
+
+       if (dso__loaded(self->dso, self->type))
+               return 0;
+
+       nr = dso__load(self->dso, self, session, 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 0;
+}
+
+struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
+                               u64 addr, symbol_filter_t filter)
+{
+       if (map__load(self, session, filter) < 0)
+               return NULL;
+
+       return dso__find_symbol(self->dso, self->type, addr);
+}
+
+struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
+                                       struct perf_session *session,
+                                       symbol_filter_t filter)
+{
+       if (map__load(self, session, 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)
 {
        struct map *map = malloc(sizeof(*self));