1 #include "event.h" 2 #include "symbol.h" 3 #include <stdlib.h> 4 #include <string.h> 5 #include <stdio.h> 6 #include "debug.h" 7 8 static inline int is_anon_memory(const char *filename) 9 { 10 return strcmp(filename, "//anon") == 0; 11 } 12 13 static int strcommon(const char *pathname, char *cwd, int cwdlen) 14 { 15 int n = 0; 16 17 while (n < cwdlen && pathname[n] == cwd[n]) 18 ++n; 19 20 return n; 21 } 22 23 void map__init(struct map *self, enum map_type type, 24 u64 start, u64 end, u64 pgoff, struct dso *dso) 25 { 26 self->type = type; 27 self->start = start; 28 self->end = end; 29 self->pgoff = pgoff; 30 self->dso = dso; 31 self->map_ip = map__map_ip; 32 self->unmap_ip = map__unmap_ip; 33 RB_CLEAR_NODE(&self->rb_node); 34 } 35 36 struct map *map__new(struct mmap_event *event, enum map_type type, 37 char *cwd, int cwdlen) 38 { 39 struct map *self = malloc(sizeof(*self)); 40 41 if (self != NULL) { 42 const char *filename = event->filename; 43 char newfilename[PATH_MAX]; 44 struct dso *dso; 45 int anon; 46 47 if (cwd) { 48 int n = strcommon(filename, cwd, cwdlen); 49 50 if (n == cwdlen) { 51 snprintf(newfilename, sizeof(newfilename), 52 ".%s", filename + n); 53 filename = newfilename; 54 } 55 } 56 57 anon = is_anon_memory(filename); 58 59 if (anon) { 60 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); 61 filename = newfilename; 62 } 63 64 dso = dsos__findnew(filename); 65 if (dso == NULL) 66 goto out_delete; 67 68 map__init(self, type, event->start, event->start + event->len, 69 event->pgoff, dso); 70 71 if (self->dso == vdso || anon) 72 self->map_ip = self->unmap_ip = identity__map_ip; 73 } 74 return self; 75 out_delete: 76 free(self); 77 return NULL; 78 } 79 80 void map__delete(struct map *self) 81 { 82 free(self); 83 } 84 85 void map__fixup_start(struct map *self) 86 { 87 struct rb_root *symbols = &self->dso->symbols[self->type]; 88 struct rb_node *nd = rb_first(symbols); 89 if (nd != NULL) { 90 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 91 self->start = sym->start; 92 } 93 } 94 95 void map__fixup_end(struct map *self) 96 { 97 struct rb_root *symbols = &self->dso->symbols[self->type]; 98 struct rb_node *nd = rb_last(symbols); 99 if (nd != NULL) { 100 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 101 self->end = sym->end; 102 } 103 } 104 105 #define DSO__DELETED "(deleted)" 106 107 int map__load(struct map *self, struct perf_session *session, 108 symbol_filter_t filter) 109 { 110 const char *name = self->dso->long_name; 111 int nr; 112 113 if (dso__loaded(self->dso, self->type)) 114 return 0; 115 116 nr = dso__load(self->dso, self, session, filter); 117 if (nr < 0) { 118 if (self->dso->has_build_id) { 119 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 120 121 build_id__sprintf(self->dso->build_id, 122 sizeof(self->dso->build_id), 123 sbuild_id); 124 pr_warning("%s with build id %s not found", 125 name, sbuild_id); 126 } else 127 pr_warning("Failed to open %s", name); 128 129 pr_warning(", continuing without symbols\n"); 130 return -1; 131 } else if (nr == 0) { 132 const size_t len = strlen(name); 133 const size_t real_len = len - sizeof(DSO__DELETED); 134 135 if (len > sizeof(DSO__DELETED) && 136 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 137 pr_warning("%.*s was updated, restart the long " 138 "running apps that use it!\n", 139 (int)real_len, name); 140 } else { 141 pr_warning("no symbols found in %s, maybe install " 142 "a debug package?\n", name); 143 } 144 145 return -1; 146 } 147 148 return 0; 149 } 150 151 struct symbol *map__find_symbol(struct map *self, struct perf_session *session, 152 u64 addr, symbol_filter_t filter) 153 { 154 if (map__load(self, session, filter) < 0) 155 return NULL; 156 157 return dso__find_symbol(self->dso, self->type, addr); 158 } 159 160 struct symbol *map__find_symbol_by_name(struct map *self, const char *name, 161 struct perf_session *session, 162 symbol_filter_t filter) 163 { 164 if (map__load(self, session, filter) < 0) 165 return NULL; 166 167 if (!dso__sorted_by_name(self->dso, self->type)) 168 dso__sort_by_name(self->dso, self->type); 169 170 return dso__find_symbol_by_name(self->dso, self->type, name); 171 } 172 173 struct map *map__clone(struct map *self) 174 { 175 struct map *map = malloc(sizeof(*self)); 176 177 if (!map) 178 return NULL; 179 180 memcpy(map, self, sizeof(*self)); 181 182 return map; 183 } 184 185 int map__overlap(struct map *l, struct map *r) 186 { 187 if (l->start > r->start) { 188 struct map *t = l; 189 l = r; 190 r = t; 191 } 192 193 if (l->end > r->start) 194 return 1; 195 196 return 0; 197 } 198 199 size_t map__fprintf(struct map *self, FILE *fp) 200 { 201 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 202 self->start, self->end, self->pgoff, self->dso->name); 203 } 204