166e274f3SFrederic Weisbecker #include "event.h" 266e274f3SFrederic Weisbecker #include "symbol.h" 366e274f3SFrederic Weisbecker #include <stdlib.h> 466e274f3SFrederic Weisbecker #include <string.h> 566e274f3SFrederic Weisbecker #include <stdio.h> 6e4204992SArnaldo Carvalho de Melo #include "debug.h" 766e274f3SFrederic Weisbecker 866e274f3SFrederic Weisbecker static inline int is_anon_memory(const char *filename) 966e274f3SFrederic Weisbecker { 1066e274f3SFrederic Weisbecker return strcmp(filename, "//anon") == 0; 1166e274f3SFrederic Weisbecker } 1266e274f3SFrederic Weisbecker 1366e274f3SFrederic Weisbecker static int strcommon(const char *pathname, char *cwd, int cwdlen) 1466e274f3SFrederic Weisbecker { 1566e274f3SFrederic Weisbecker int n = 0; 1666e274f3SFrederic Weisbecker 1766e274f3SFrederic Weisbecker while (n < cwdlen && pathname[n] == cwd[n]) 1866e274f3SFrederic Weisbecker ++n; 1966e274f3SFrederic Weisbecker 2066e274f3SFrederic Weisbecker return n; 2166e274f3SFrederic Weisbecker } 2266e274f3SFrederic Weisbecker 233610583cSArnaldo Carvalho de Melo void map__init(struct map *self, enum map_type type, 243610583cSArnaldo Carvalho de Melo u64 start, u64 end, u64 pgoff, struct dso *dso) 25afb7b4f0SArnaldo Carvalho de Melo { 263610583cSArnaldo Carvalho de Melo self->type = type; 27afb7b4f0SArnaldo Carvalho de Melo self->start = start; 28afb7b4f0SArnaldo Carvalho de Melo self->end = end; 29afb7b4f0SArnaldo Carvalho de Melo self->pgoff = pgoff; 30afb7b4f0SArnaldo Carvalho de Melo self->dso = dso; 31afb7b4f0SArnaldo Carvalho de Melo self->map_ip = map__map_ip; 32afb7b4f0SArnaldo Carvalho de Melo self->unmap_ip = map__unmap_ip; 33afb7b4f0SArnaldo Carvalho de Melo RB_CLEAR_NODE(&self->rb_node); 34afb7b4f0SArnaldo Carvalho de Melo } 35afb7b4f0SArnaldo Carvalho de Melo 363610583cSArnaldo Carvalho de Melo struct map *map__new(struct mmap_event *event, enum map_type type, 373610583cSArnaldo Carvalho de Melo char *cwd, int cwdlen) 3866e274f3SFrederic Weisbecker { 3966e274f3SFrederic Weisbecker struct map *self = malloc(sizeof(*self)); 4066e274f3SFrederic Weisbecker 4166e274f3SFrederic Weisbecker if (self != NULL) { 4266e274f3SFrederic Weisbecker const char *filename = event->filename; 4366e274f3SFrederic Weisbecker char newfilename[PATH_MAX]; 44afb7b4f0SArnaldo Carvalho de Melo struct dso *dso; 4566e274f3SFrederic Weisbecker int anon; 4666e274f3SFrederic Weisbecker 4766e274f3SFrederic Weisbecker if (cwd) { 4866e274f3SFrederic Weisbecker int n = strcommon(filename, cwd, cwdlen); 4966e274f3SFrederic Weisbecker 5066e274f3SFrederic Weisbecker if (n == cwdlen) { 5166e274f3SFrederic Weisbecker snprintf(newfilename, sizeof(newfilename), 5266e274f3SFrederic Weisbecker ".%s", filename + n); 5366e274f3SFrederic Weisbecker filename = newfilename; 5466e274f3SFrederic Weisbecker } 5566e274f3SFrederic Weisbecker } 5666e274f3SFrederic Weisbecker 5766e274f3SFrederic Weisbecker anon = is_anon_memory(filename); 5866e274f3SFrederic Weisbecker 5966e274f3SFrederic Weisbecker if (anon) { 6066e274f3SFrederic Weisbecker snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); 6166e274f3SFrederic Weisbecker filename = newfilename; 6266e274f3SFrederic Weisbecker } 6366e274f3SFrederic Weisbecker 6400a192b3SArnaldo Carvalho de Melo dso = dsos__findnew(filename); 65afb7b4f0SArnaldo Carvalho de Melo if (dso == NULL) 6666e274f3SFrederic Weisbecker goto out_delete; 6766e274f3SFrederic Weisbecker 683610583cSArnaldo Carvalho de Melo map__init(self, type, event->start, event->start + event->len, 69afb7b4f0SArnaldo Carvalho de Melo event->pgoff, dso); 70afb7b4f0SArnaldo Carvalho de Melo 7166e274f3SFrederic Weisbecker if (self->dso == vdso || anon) 72ed52ce2eSArnaldo Carvalho de Melo self->map_ip = self->unmap_ip = identity__map_ip; 7366e274f3SFrederic Weisbecker } 7466e274f3SFrederic Weisbecker return self; 7566e274f3SFrederic Weisbecker out_delete: 7666e274f3SFrederic Weisbecker free(self); 7766e274f3SFrederic Weisbecker return NULL; 7866e274f3SFrederic Weisbecker } 7966e274f3SFrederic Weisbecker 80c338aee8SArnaldo Carvalho de Melo void map__delete(struct map *self) 81c338aee8SArnaldo Carvalho de Melo { 82c338aee8SArnaldo Carvalho de Melo free(self); 83c338aee8SArnaldo Carvalho de Melo } 84c338aee8SArnaldo Carvalho de Melo 856a4694a4SArnaldo Carvalho de Melo void map__fixup_start(struct map *self) 86c338aee8SArnaldo Carvalho de Melo { 876a4694a4SArnaldo Carvalho de Melo struct rb_root *symbols = &self->dso->symbols[self->type]; 88fcf1203aSArnaldo Carvalho de Melo struct rb_node *nd = rb_first(symbols); 89c338aee8SArnaldo Carvalho de Melo if (nd != NULL) { 90c338aee8SArnaldo Carvalho de Melo struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 91c338aee8SArnaldo Carvalho de Melo self->start = sym->start; 92c338aee8SArnaldo Carvalho de Melo } 93c338aee8SArnaldo Carvalho de Melo } 94c338aee8SArnaldo Carvalho de Melo 956a4694a4SArnaldo Carvalho de Melo void map__fixup_end(struct map *self) 96c338aee8SArnaldo Carvalho de Melo { 976a4694a4SArnaldo Carvalho de Melo struct rb_root *symbols = &self->dso->symbols[self->type]; 98fcf1203aSArnaldo Carvalho de Melo struct rb_node *nd = rb_last(symbols); 99c338aee8SArnaldo Carvalho de Melo if (nd != NULL) { 100c338aee8SArnaldo Carvalho de Melo struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 101c338aee8SArnaldo Carvalho de Melo self->end = sym->end; 102c338aee8SArnaldo Carvalho de Melo } 103c338aee8SArnaldo Carvalho de Melo } 104c338aee8SArnaldo Carvalho de Melo 105d70a5402SArnaldo Carvalho de Melo #define DSO__DELETED "(deleted)" 106d70a5402SArnaldo Carvalho de Melo 107a128168dSMasami Hiramatsu int map__load(struct map *self, struct perf_session *session, 1084aa65636SArnaldo Carvalho de Melo symbol_filter_t filter) 10966bd8424SArnaldo Carvalho de Melo { 11079406cd7SArnaldo Carvalho de Melo const char *name = self->dso->long_name; 111a128168dSMasami Hiramatsu int nr; 11266bd8424SArnaldo Carvalho de Melo 113a128168dSMasami Hiramatsu if (dso__loaded(self->dso, self->type)) 114a128168dSMasami Hiramatsu return 0; 115a128168dSMasami Hiramatsu 116a128168dSMasami Hiramatsu nr = dso__load(self->dso, self, session, filter); 11766bd8424SArnaldo Carvalho de Melo if (nr < 0) { 1188d06367fSArnaldo Carvalho de Melo if (self->dso->has_build_id) { 1198d06367fSArnaldo Carvalho de Melo char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1208d06367fSArnaldo Carvalho de Melo 1218d06367fSArnaldo Carvalho de Melo build_id__sprintf(self->dso->build_id, 1228d06367fSArnaldo Carvalho de Melo sizeof(self->dso->build_id), 1238d06367fSArnaldo Carvalho de Melo sbuild_id); 1248d06367fSArnaldo Carvalho de Melo pr_warning("%s with build id %s not found", 12579406cd7SArnaldo Carvalho de Melo name, sbuild_id); 1268d06367fSArnaldo Carvalho de Melo } else 12779406cd7SArnaldo Carvalho de Melo pr_warning("Failed to open %s", name); 12879406cd7SArnaldo Carvalho de Melo 1298d06367fSArnaldo Carvalho de Melo pr_warning(", continuing without symbols\n"); 13079406cd7SArnaldo Carvalho de Melo return -1; 13166bd8424SArnaldo Carvalho de Melo } else if (nr == 0) { 132d70a5402SArnaldo Carvalho de Melo const size_t len = strlen(name); 133d70a5402SArnaldo Carvalho de Melo const size_t real_len = len - sizeof(DSO__DELETED); 134d70a5402SArnaldo Carvalho de Melo 135d70a5402SArnaldo Carvalho de Melo if (len > sizeof(DSO__DELETED) && 136900b20d5SIngo Molnar strcmp(name + real_len + 1, DSO__DELETED) == 0) { 13779406cd7SArnaldo Carvalho de Melo pr_warning("%.*s was updated, restart the long " 13879406cd7SArnaldo Carvalho de Melo "running apps that use it!\n", 139900b20d5SIngo Molnar (int)real_len, name); 140900b20d5SIngo Molnar } else { 14179406cd7SArnaldo Carvalho de Melo pr_warning("no symbols found in %s, maybe install " 14279406cd7SArnaldo Carvalho de Melo "a debug package?\n", name); 14366bd8424SArnaldo Carvalho de Melo } 14466bd8424SArnaldo Carvalho de Melo 14579406cd7SArnaldo Carvalho de Melo return -1; 14679406cd7SArnaldo Carvalho de Melo } 14779406cd7SArnaldo Carvalho de Melo 14879406cd7SArnaldo Carvalho de Melo return 0; 14979406cd7SArnaldo Carvalho de Melo } 15079406cd7SArnaldo Carvalho de Melo 1514aa65636SArnaldo Carvalho de Melo struct symbol *map__find_symbol(struct map *self, struct perf_session *session, 1524aa65636SArnaldo Carvalho de Melo u64 addr, symbol_filter_t filter) 15379406cd7SArnaldo Carvalho de Melo { 154a128168dSMasami Hiramatsu if (map__load(self, session, filter) < 0) 15579406cd7SArnaldo Carvalho de Melo return NULL; 15679406cd7SArnaldo Carvalho de Melo 157ea08d8cbSArnaldo Carvalho de Melo return dso__find_symbol(self->dso, self->type, addr); 15866bd8424SArnaldo Carvalho de Melo } 15966bd8424SArnaldo Carvalho de Melo 16079406cd7SArnaldo Carvalho de Melo struct symbol *map__find_symbol_by_name(struct map *self, const char *name, 1614aa65636SArnaldo Carvalho de Melo struct perf_session *session, 16279406cd7SArnaldo Carvalho de Melo symbol_filter_t filter) 16379406cd7SArnaldo Carvalho de Melo { 164a128168dSMasami Hiramatsu if (map__load(self, session, filter) < 0) 16579406cd7SArnaldo Carvalho de Melo return NULL; 16679406cd7SArnaldo Carvalho de Melo 16779406cd7SArnaldo Carvalho de Melo if (!dso__sorted_by_name(self->dso, self->type)) 16879406cd7SArnaldo Carvalho de Melo dso__sort_by_name(self->dso, self->type); 16979406cd7SArnaldo Carvalho de Melo 17079406cd7SArnaldo Carvalho de Melo return dso__find_symbol_by_name(self->dso, self->type, name); 17179406cd7SArnaldo Carvalho de Melo } 17279406cd7SArnaldo Carvalho de Melo 17366e274f3SFrederic Weisbecker struct map *map__clone(struct map *self) 17466e274f3SFrederic Weisbecker { 17566e274f3SFrederic Weisbecker struct map *map = malloc(sizeof(*self)); 17666e274f3SFrederic Weisbecker 17766e274f3SFrederic Weisbecker if (!map) 17866e274f3SFrederic Weisbecker return NULL; 17966e274f3SFrederic Weisbecker 18066e274f3SFrederic Weisbecker memcpy(map, self, sizeof(*self)); 18166e274f3SFrederic Weisbecker 18266e274f3SFrederic Weisbecker return map; 18366e274f3SFrederic Weisbecker } 18466e274f3SFrederic Weisbecker 18566e274f3SFrederic Weisbecker int map__overlap(struct map *l, struct map *r) 18666e274f3SFrederic Weisbecker { 18766e274f3SFrederic Weisbecker if (l->start > r->start) { 18866e274f3SFrederic Weisbecker struct map *t = l; 18966e274f3SFrederic Weisbecker l = r; 19066e274f3SFrederic Weisbecker r = t; 19166e274f3SFrederic Weisbecker } 19266e274f3SFrederic Weisbecker 19366e274f3SFrederic Weisbecker if (l->end > r->start) 19466e274f3SFrederic Weisbecker return 1; 19566e274f3SFrederic Weisbecker 19666e274f3SFrederic Weisbecker return 0; 19766e274f3SFrederic Weisbecker } 19866e274f3SFrederic Weisbecker 19966e274f3SFrederic Weisbecker size_t map__fprintf(struct map *self, FILE *fp) 20066e274f3SFrederic Weisbecker { 20166e274f3SFrederic Weisbecker return fprintf(fp, " %Lx-%Lx %Lx %s\n", 20266e274f3SFrederic Weisbecker self->start, self->end, self->pgoff, self->dso->name); 20366e274f3SFrederic Weisbecker } 204