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 struct symbol *map__find_symbol(struct map *self, u64 addr, 108 symbol_filter_t filter) 109 { 110 if (!dso__loaded(self->dso, self->type)) { 111 int nr = dso__load(self->dso, self, filter); 112 113 if (nr < 0) { 114 if (self->dso->has_build_id) { 115 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 116 117 build_id__sprintf(self->dso->build_id, 118 sizeof(self->dso->build_id), 119 sbuild_id); 120 pr_warning("%s with build id %s not found", 121 self->dso->long_name, sbuild_id); 122 } else 123 pr_warning("Failed to open %s", 124 self->dso->long_name); 125 pr_warning(", continuing without symbols\n"); 126 return NULL; 127 } else if (nr == 0) { 128 const char *name = self->dso->long_name; 129 const size_t len = strlen(name); 130 const size_t real_len = len - sizeof(DSO__DELETED); 131 132 if (len > sizeof(DSO__DELETED) && 133 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 134 pr_warning("%.*s was updated, restart the long running apps that use it!\n", 135 (int)real_len, name); 136 } else { 137 pr_warning("no symbols found in %s, maybe install a debug package?\n", name); 138 } 139 return NULL; 140 } 141 } 142 143 return self->dso->find_symbol(self->dso, self->type, addr); 144 } 145 146 struct map *map__clone(struct map *self) 147 { 148 struct map *map = malloc(sizeof(*self)); 149 150 if (!map) 151 return NULL; 152 153 memcpy(map, self, sizeof(*self)); 154 155 return map; 156 } 157 158 int map__overlap(struct map *l, struct map *r) 159 { 160 if (l->start > r->start) { 161 struct map *t = l; 162 l = r; 163 r = t; 164 } 165 166 if (l->end > r->start) 167 return 1; 168 169 return 0; 170 } 171 172 size_t map__fprintf(struct map *self, FILE *fp) 173 { 174 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 175 self->start, self->end, self->pgoff, self->dso->name); 176 } 177