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, u64 start, u64 end, u64 pgoff, 24 struct dso *dso) 25 { 26 self->start = start; 27 self->end = end; 28 self->pgoff = pgoff; 29 self->dso = dso; 30 self->map_ip = map__map_ip; 31 self->unmap_ip = map__unmap_ip; 32 RB_CLEAR_NODE(&self->rb_node); 33 } 34 35 struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) 36 { 37 struct map *self = malloc(sizeof(*self)); 38 39 if (self != NULL) { 40 const char *filename = event->filename; 41 char newfilename[PATH_MAX]; 42 struct dso *dso; 43 int anon; 44 45 if (cwd) { 46 int n = strcommon(filename, cwd, cwdlen); 47 48 if (n == cwdlen) { 49 snprintf(newfilename, sizeof(newfilename), 50 ".%s", filename + n); 51 filename = newfilename; 52 } 53 } 54 55 anon = is_anon_memory(filename); 56 57 if (anon) { 58 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); 59 filename = newfilename; 60 } 61 62 dso = dsos__findnew(filename); 63 if (dso == NULL) 64 goto out_delete; 65 66 map__init(self, event->start, event->start + event->len, 67 event->pgoff, dso); 68 69 if (self->dso == vdso || anon) 70 self->map_ip = self->unmap_ip = identity__map_ip; 71 } 72 return self; 73 out_delete: 74 free(self); 75 return NULL; 76 } 77 78 #define DSO__DELETED "(deleted)" 79 80 struct symbol * 81 map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter) 82 { 83 if (!self->dso->loaded) { 84 int nr = dso__load(self->dso, self, filter); 85 86 if (nr < 0) { 87 pr_warning("Failed to open %s, continuing without symbols\n", 88 self->dso->long_name); 89 return NULL; 90 } else if (nr == 0) { 91 const char *name = self->dso->long_name; 92 const size_t len = strlen(name); 93 const size_t real_len = len - sizeof(DSO__DELETED); 94 95 if (len > sizeof(DSO__DELETED) && 96 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 97 pr_warning("%.*s was updated, restart the long running apps that use it!\n", 98 (int)real_len, name); 99 } else { 100 pr_warning("no symbols found in %s, maybe install a debug package?\n", name); 101 } 102 return NULL; 103 } 104 } 105 106 return self->dso->find_symbol(self->dso, ip); 107 } 108 109 struct map *map__clone(struct map *self) 110 { 111 struct map *map = malloc(sizeof(*self)); 112 113 if (!map) 114 return NULL; 115 116 memcpy(map, self, sizeof(*self)); 117 118 return map; 119 } 120 121 int map__overlap(struct map *l, struct map *r) 122 { 123 if (l->start > r->start) { 124 struct map *t = l; 125 l = r; 126 r = t; 127 } 128 129 if (l->end > r->start) 130 return 1; 131 132 return 0; 133 } 134 135 size_t map__fprintf(struct map *self, FILE *fp) 136 { 137 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 138 self->start, self->end, self->pgoff, self->dso->name); 139 } 140