186470930SIngo Molnar #include "util.h" 286470930SIngo Molnar #include "../perf.h" 386470930SIngo Molnar #include "string.h" 486470930SIngo Molnar #include "symbol.h" 5439d473bSArnaldo Carvalho de Melo #include "thread.h" 686470930SIngo Molnar 78f28827aSFrederic Weisbecker #include "debug.h" 88f28827aSFrederic Weisbecker 986470930SIngo Molnar #include <libelf.h> 1086470930SIngo Molnar #include <gelf.h> 1186470930SIngo Molnar #include <elf.h> 12439d473bSArnaldo Carvalho de Melo #include <sys/utsname.h> 132cdbc46dSPeter Zijlstra 1494cb9e38SArnaldo Carvalho de Melo enum dso_origin { 1594cb9e38SArnaldo Carvalho de Melo DSO__ORIG_KERNEL = 0, 1694cb9e38SArnaldo Carvalho de Melo DSO__ORIG_JAVA_JIT, 1794cb9e38SArnaldo Carvalho de Melo DSO__ORIG_FEDORA, 1894cb9e38SArnaldo Carvalho de Melo DSO__ORIG_UBUNTU, 1994cb9e38SArnaldo Carvalho de Melo DSO__ORIG_BUILDID, 2094cb9e38SArnaldo Carvalho de Melo DSO__ORIG_DSO, 21439d473bSArnaldo Carvalho de Melo DSO__ORIG_KMODULE, 2294cb9e38SArnaldo Carvalho de Melo DSO__ORIG_NOT_FOUND, 2394cb9e38SArnaldo Carvalho de Melo }; 2494cb9e38SArnaldo Carvalho de Melo 25439d473bSArnaldo Carvalho de Melo static void dsos__add(struct dso *dso); 26439d473bSArnaldo Carvalho de Melo static struct dso *dsos__find(const char *name); 272e538c4aSArnaldo Carvalho de Melo static struct map *map__new2(u64 start, struct dso *dso); 282e538c4aSArnaldo Carvalho de Melo static void kernel_maps__insert(struct map *map); 2900a192b3SArnaldo Carvalho de Melo unsigned int symbol__priv_size; 30439d473bSArnaldo Carvalho de Melo 31af427bf5SArnaldo Carvalho de Melo static struct rb_root kernel_maps; 32af427bf5SArnaldo Carvalho de Melo 332e538c4aSArnaldo Carvalho de Melo static void dso__fixup_sym_end(struct dso *self) 34af427bf5SArnaldo Carvalho de Melo { 35af427bf5SArnaldo Carvalho de Melo struct rb_node *nd, *prevnd = rb_first(&self->syms); 362e538c4aSArnaldo Carvalho de Melo struct symbol *curr, *prev; 37af427bf5SArnaldo Carvalho de Melo 38af427bf5SArnaldo Carvalho de Melo if (prevnd == NULL) 39af427bf5SArnaldo Carvalho de Melo return; 40af427bf5SArnaldo Carvalho de Melo 412e538c4aSArnaldo Carvalho de Melo curr = rb_entry(prevnd, struct symbol, rb_node); 422e538c4aSArnaldo Carvalho de Melo 43af427bf5SArnaldo Carvalho de Melo for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 442e538c4aSArnaldo Carvalho de Melo prev = curr; 452e538c4aSArnaldo Carvalho de Melo curr = rb_entry(nd, struct symbol, rb_node); 46af427bf5SArnaldo Carvalho de Melo 47af427bf5SArnaldo Carvalho de Melo if (prev->end == prev->start) 48af427bf5SArnaldo Carvalho de Melo prev->end = curr->start - 1; 49af427bf5SArnaldo Carvalho de Melo } 50af427bf5SArnaldo Carvalho de Melo 512e538c4aSArnaldo Carvalho de Melo /* Last entry */ 522e538c4aSArnaldo Carvalho de Melo if (curr->end == curr->start) 532e538c4aSArnaldo Carvalho de Melo curr->end = roundup(curr->start, 4096); 542e538c4aSArnaldo Carvalho de Melo } 552e538c4aSArnaldo Carvalho de Melo 562e538c4aSArnaldo Carvalho de Melo static void kernel_maps__fixup_end(void) 57af427bf5SArnaldo Carvalho de Melo { 58af427bf5SArnaldo Carvalho de Melo struct map *prev, *curr; 59af427bf5SArnaldo Carvalho de Melo struct rb_node *nd, *prevnd = rb_first(&kernel_maps); 60af427bf5SArnaldo Carvalho de Melo 61af427bf5SArnaldo Carvalho de Melo if (prevnd == NULL) 62af427bf5SArnaldo Carvalho de Melo return; 63af427bf5SArnaldo Carvalho de Melo 64af427bf5SArnaldo Carvalho de Melo curr = rb_entry(prevnd, struct map, rb_node); 65af427bf5SArnaldo Carvalho de Melo 66af427bf5SArnaldo Carvalho de Melo for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 67af427bf5SArnaldo Carvalho de Melo prev = curr; 68af427bf5SArnaldo Carvalho de Melo curr = rb_entry(nd, struct map, rb_node); 69af427bf5SArnaldo Carvalho de Melo prev->end = curr->start - 1; 702e538c4aSArnaldo Carvalho de Melo } 712e538c4aSArnaldo Carvalho de Melo 722e538c4aSArnaldo Carvalho de Melo nd = rb_last(&curr->dso->syms); 732e538c4aSArnaldo Carvalho de Melo if (nd) { 742e538c4aSArnaldo Carvalho de Melo struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 752e538c4aSArnaldo Carvalho de Melo curr->end = sym->end; 76af427bf5SArnaldo Carvalho de Melo } 77af427bf5SArnaldo Carvalho de Melo } 78af427bf5SArnaldo Carvalho de Melo 7900a192b3SArnaldo Carvalho de Melo static struct symbol *symbol__new(u64 start, u64 len, const char *name) 8086470930SIngo Molnar { 8186470930SIngo Molnar size_t namelen = strlen(name) + 1; 8200a192b3SArnaldo Carvalho de Melo struct symbol *self = calloc(1, (symbol__priv_size + 8300a192b3SArnaldo Carvalho de Melo sizeof(*self) + namelen)); 8486470930SIngo Molnar if (!self) 8586470930SIngo Molnar return NULL; 8686470930SIngo Molnar 8700a192b3SArnaldo Carvalho de Melo if (symbol__priv_size) { 8800a192b3SArnaldo Carvalho de Melo memset(self, 0, symbol__priv_size); 8900a192b3SArnaldo Carvalho de Melo self = ((void *)self) + symbol__priv_size; 9086470930SIngo Molnar } 9186470930SIngo Molnar self->start = start; 926cfcc53eSMike Galbraith self->end = len ? start + len - 1 : start; 93e4204992SArnaldo Carvalho de Melo 946beba7adSArnaldo Carvalho de Melo pr_debug3("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); 95e4204992SArnaldo Carvalho de Melo 9686470930SIngo Molnar memcpy(self->name, name, namelen); 9786470930SIngo Molnar 9886470930SIngo Molnar return self; 9986470930SIngo Molnar } 10086470930SIngo Molnar 10100a192b3SArnaldo Carvalho de Melo static void symbol__delete(struct symbol *self) 10286470930SIngo Molnar { 10300a192b3SArnaldo Carvalho de Melo free(((void *)self) - symbol__priv_size); 10486470930SIngo Molnar } 10586470930SIngo Molnar 10686470930SIngo Molnar static size_t symbol__fprintf(struct symbol *self, FILE *fp) 10786470930SIngo Molnar { 10886470930SIngo Molnar return fprintf(fp, " %llx-%llx %s\n", 10986470930SIngo Molnar self->start, self->end, self->name); 11086470930SIngo Molnar } 11186470930SIngo Molnar 112cfc10d3bSArnaldo Carvalho de Melo static void dso__set_long_name(struct dso *self, char *name) 113cfc10d3bSArnaldo Carvalho de Melo { 114cfc10d3bSArnaldo Carvalho de Melo self->long_name = name; 115cfc10d3bSArnaldo Carvalho de Melo self->long_name_len = strlen(name); 116cfc10d3bSArnaldo Carvalho de Melo } 117cfc10d3bSArnaldo Carvalho de Melo 118cfc10d3bSArnaldo Carvalho de Melo static void dso__set_basename(struct dso *self) 119cfc10d3bSArnaldo Carvalho de Melo { 120cfc10d3bSArnaldo Carvalho de Melo self->short_name = basename(self->long_name); 121cfc10d3bSArnaldo Carvalho de Melo } 122cfc10d3bSArnaldo Carvalho de Melo 12300a192b3SArnaldo Carvalho de Melo struct dso *dso__new(const char *name) 12486470930SIngo Molnar { 12586470930SIngo Molnar struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 12686470930SIngo Molnar 12786470930SIngo Molnar if (self != NULL) { 12886470930SIngo Molnar strcpy(self->name, name); 129cfc10d3bSArnaldo Carvalho de Melo dso__set_long_name(self, self->name); 130439d473bSArnaldo Carvalho de Melo self->short_name = self->name; 13186470930SIngo Molnar self->syms = RB_ROOT; 13286470930SIngo Molnar self->find_symbol = dso__find_symbol; 13352d422deSArnaldo Carvalho de Melo self->slen_calculated = 0; 13494cb9e38SArnaldo Carvalho de Melo self->origin = DSO__ORIG_NOT_FOUND; 1358d06367fSArnaldo Carvalho de Melo self->loaded = 0; 1368d06367fSArnaldo Carvalho de Melo self->has_build_id = 0; 13786470930SIngo Molnar } 13886470930SIngo Molnar 13986470930SIngo Molnar return self; 14086470930SIngo Molnar } 14186470930SIngo Molnar 14286470930SIngo Molnar static void dso__delete_symbols(struct dso *self) 14386470930SIngo Molnar { 14486470930SIngo Molnar struct symbol *pos; 14586470930SIngo Molnar struct rb_node *next = rb_first(&self->syms); 14686470930SIngo Molnar 14786470930SIngo Molnar while (next) { 14886470930SIngo Molnar pos = rb_entry(next, struct symbol, rb_node); 14986470930SIngo Molnar next = rb_next(&pos->rb_node); 15086470930SIngo Molnar rb_erase(&pos->rb_node, &self->syms); 15100a192b3SArnaldo Carvalho de Melo symbol__delete(pos); 15286470930SIngo Molnar } 15386470930SIngo Molnar } 15486470930SIngo Molnar 15586470930SIngo Molnar void dso__delete(struct dso *self) 15686470930SIngo Molnar { 15786470930SIngo Molnar dso__delete_symbols(self); 158439d473bSArnaldo Carvalho de Melo if (self->long_name != self->name) 159439d473bSArnaldo Carvalho de Melo free(self->long_name); 16086470930SIngo Molnar free(self); 16186470930SIngo Molnar } 16286470930SIngo Molnar 1638d06367fSArnaldo Carvalho de Melo void dso__set_build_id(struct dso *self, void *build_id) 1648d06367fSArnaldo Carvalho de Melo { 1658d06367fSArnaldo Carvalho de Melo memcpy(self->build_id, build_id, sizeof(self->build_id)); 1668d06367fSArnaldo Carvalho de Melo self->has_build_id = 1; 1678d06367fSArnaldo Carvalho de Melo } 1688d06367fSArnaldo Carvalho de Melo 16986470930SIngo Molnar static void dso__insert_symbol(struct dso *self, struct symbol *sym) 17086470930SIngo Molnar { 17186470930SIngo Molnar struct rb_node **p = &self->syms.rb_node; 17286470930SIngo Molnar struct rb_node *parent = NULL; 1739cffa8d5SPaul Mackerras const u64 ip = sym->start; 17486470930SIngo Molnar struct symbol *s; 17586470930SIngo Molnar 17686470930SIngo Molnar while (*p != NULL) { 17786470930SIngo Molnar parent = *p; 17886470930SIngo Molnar s = rb_entry(parent, struct symbol, rb_node); 17986470930SIngo Molnar if (ip < s->start) 18086470930SIngo Molnar p = &(*p)->rb_left; 18186470930SIngo Molnar else 18286470930SIngo Molnar p = &(*p)->rb_right; 18386470930SIngo Molnar } 18486470930SIngo Molnar rb_link_node(&sym->rb_node, parent, p); 18586470930SIngo Molnar rb_insert_color(&sym->rb_node, &self->syms); 18686470930SIngo Molnar } 18786470930SIngo Molnar 1889cffa8d5SPaul Mackerras struct symbol *dso__find_symbol(struct dso *self, u64 ip) 18986470930SIngo Molnar { 19086470930SIngo Molnar struct rb_node *n; 19186470930SIngo Molnar 19286470930SIngo Molnar if (self == NULL) 19386470930SIngo Molnar return NULL; 19486470930SIngo Molnar 19586470930SIngo Molnar n = self->syms.rb_node; 19686470930SIngo Molnar 19786470930SIngo Molnar while (n) { 19886470930SIngo Molnar struct symbol *s = rb_entry(n, struct symbol, rb_node); 19986470930SIngo Molnar 20086470930SIngo Molnar if (ip < s->start) 20186470930SIngo Molnar n = n->rb_left; 20286470930SIngo Molnar else if (ip > s->end) 20386470930SIngo Molnar n = n->rb_right; 20486470930SIngo Molnar else 20586470930SIngo Molnar return s; 20686470930SIngo Molnar } 20786470930SIngo Molnar 20886470930SIngo Molnar return NULL; 20986470930SIngo Molnar } 21086470930SIngo Molnar 2118d06367fSArnaldo Carvalho de Melo int build_id__sprintf(u8 *self, int len, char *bf) 2128d06367fSArnaldo Carvalho de Melo { 2138d06367fSArnaldo Carvalho de Melo char *bid = bf; 2148d06367fSArnaldo Carvalho de Melo u8 *raw = self; 2158d06367fSArnaldo Carvalho de Melo int i; 2168d06367fSArnaldo Carvalho de Melo 2178d06367fSArnaldo Carvalho de Melo for (i = 0; i < len; ++i) { 2188d06367fSArnaldo Carvalho de Melo sprintf(bid, "%02x", *raw); 2198d06367fSArnaldo Carvalho de Melo ++raw; 2208d06367fSArnaldo Carvalho de Melo bid += 2; 2218d06367fSArnaldo Carvalho de Melo } 2228d06367fSArnaldo Carvalho de Melo 2238d06367fSArnaldo Carvalho de Melo return raw - self; 2248d06367fSArnaldo Carvalho de Melo } 2258d06367fSArnaldo Carvalho de Melo 2269e03eb2dSArnaldo Carvalho de Melo size_t dso__fprintf_buildid(struct dso *self, FILE *fp) 22786470930SIngo Molnar { 2288d06367fSArnaldo Carvalho de Melo char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 2298d06367fSArnaldo Carvalho de Melo 2308d06367fSArnaldo Carvalho de Melo build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id); 2319e03eb2dSArnaldo Carvalho de Melo return fprintf(fp, "%s", sbuild_id); 2329e03eb2dSArnaldo Carvalho de Melo } 2339e03eb2dSArnaldo Carvalho de Melo 2349e03eb2dSArnaldo Carvalho de Melo size_t dso__fprintf(struct dso *self, FILE *fp) 2359e03eb2dSArnaldo Carvalho de Melo { 2369e03eb2dSArnaldo Carvalho de Melo struct rb_node *nd; 2379e03eb2dSArnaldo Carvalho de Melo size_t ret = fprintf(fp, "dso: %s (", self->short_name); 2389e03eb2dSArnaldo Carvalho de Melo 2399e03eb2dSArnaldo Carvalho de Melo ret += dso__fprintf_buildid(self, fp); 2409e03eb2dSArnaldo Carvalho de Melo ret += fprintf(fp, ")\n"); 2418d06367fSArnaldo Carvalho de Melo 24286470930SIngo Molnar for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 24386470930SIngo Molnar struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 24486470930SIngo Molnar ret += symbol__fprintf(pos, fp); 24586470930SIngo Molnar } 24686470930SIngo Molnar 24786470930SIngo Molnar return ret; 24886470930SIngo Molnar } 24986470930SIngo Molnar 2502e538c4aSArnaldo Carvalho de Melo /* 2512e538c4aSArnaldo Carvalho de Melo * Loads the function entries in /proc/kallsyms into kernel_map->dso, 2522e538c4aSArnaldo Carvalho de Melo * so that we can in the next step set the symbol ->end address and then 2532e538c4aSArnaldo Carvalho de Melo * call kernel_maps__split_kallsyms. 2542e538c4aSArnaldo Carvalho de Melo */ 2556beba7adSArnaldo Carvalho de Melo static int kernel_maps__load_all_kallsyms(void) 25686470930SIngo Molnar { 25786470930SIngo Molnar char *line = NULL; 25886470930SIngo Molnar size_t n; 25986470930SIngo Molnar FILE *file = fopen("/proc/kallsyms", "r"); 26086470930SIngo Molnar 26186470930SIngo Molnar if (file == NULL) 26286470930SIngo Molnar goto out_failure; 26386470930SIngo Molnar 26486470930SIngo Molnar while (!feof(file)) { 2659cffa8d5SPaul Mackerras u64 start; 26686470930SIngo Molnar struct symbol *sym; 26786470930SIngo Molnar int line_len, len; 26886470930SIngo Molnar char symbol_type; 2692e538c4aSArnaldo Carvalho de Melo char *symbol_name; 27086470930SIngo Molnar 27186470930SIngo Molnar line_len = getline(&line, &n, file); 27286470930SIngo Molnar if (line_len < 0) 27386470930SIngo Molnar break; 27486470930SIngo Molnar 27586470930SIngo Molnar if (!line) 27686470930SIngo Molnar goto out_failure; 27786470930SIngo Molnar 27886470930SIngo Molnar line[--line_len] = '\0'; /* \n */ 27986470930SIngo Molnar 28086470930SIngo Molnar len = hex2u64(line, &start); 28186470930SIngo Molnar 28286470930SIngo Molnar len++; 28386470930SIngo Molnar if (len + 2 >= line_len) 28486470930SIngo Molnar continue; 28586470930SIngo Molnar 28686470930SIngo Molnar symbol_type = toupper(line[len]); 28786470930SIngo Molnar /* 28886470930SIngo Molnar * We're interested only in code ('T'ext) 28986470930SIngo Molnar */ 29086470930SIngo Molnar if (symbol_type != 'T' && symbol_type != 'W') 29186470930SIngo Molnar continue; 292af427bf5SArnaldo Carvalho de Melo 293af427bf5SArnaldo Carvalho de Melo symbol_name = line + len + 2; 2942e538c4aSArnaldo Carvalho de Melo /* 2952e538c4aSArnaldo Carvalho de Melo * Will fix up the end later, when we have all symbols sorted. 2962e538c4aSArnaldo Carvalho de Melo */ 29700a192b3SArnaldo Carvalho de Melo sym = symbol__new(start, 0, symbol_name); 298af427bf5SArnaldo Carvalho de Melo 2992e538c4aSArnaldo Carvalho de Melo if (sym == NULL) 3002e538c4aSArnaldo Carvalho de Melo goto out_delete_line; 3012e538c4aSArnaldo Carvalho de Melo 30282164161SArnaldo Carvalho de Melo /* 30382164161SArnaldo Carvalho de Melo * We will pass the symbols to the filter later, in 30482164161SArnaldo Carvalho de Melo * kernel_maps__split_kallsyms, when we have split the 30582164161SArnaldo Carvalho de Melo * maps per module 30682164161SArnaldo Carvalho de Melo */ 3072e538c4aSArnaldo Carvalho de Melo dso__insert_symbol(kernel_map->dso, sym); 3082e538c4aSArnaldo Carvalho de Melo } 3092e538c4aSArnaldo Carvalho de Melo 3102e538c4aSArnaldo Carvalho de Melo free(line); 3112e538c4aSArnaldo Carvalho de Melo fclose(file); 3122e538c4aSArnaldo Carvalho de Melo 3132e538c4aSArnaldo Carvalho de Melo return 0; 3142e538c4aSArnaldo Carvalho de Melo 3152e538c4aSArnaldo Carvalho de Melo out_delete_line: 3162e538c4aSArnaldo Carvalho de Melo free(line); 3172e538c4aSArnaldo Carvalho de Melo out_failure: 3182e538c4aSArnaldo Carvalho de Melo return -1; 3192e538c4aSArnaldo Carvalho de Melo } 3202e538c4aSArnaldo Carvalho de Melo 3212e538c4aSArnaldo Carvalho de Melo /* 3222e538c4aSArnaldo Carvalho de Melo * Split the symbols into maps, making sure there are no overlaps, i.e. the 3232e538c4aSArnaldo Carvalho de Melo * kernel range is broken in several maps, named [kernel].N, as we don't have 3242e538c4aSArnaldo Carvalho de Melo * the original ELF section names vmlinux have. 3252e538c4aSArnaldo Carvalho de Melo */ 3262e538c4aSArnaldo Carvalho de Melo static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules) 3272e538c4aSArnaldo Carvalho de Melo { 3282e538c4aSArnaldo Carvalho de Melo struct map *map = kernel_map; 3292e538c4aSArnaldo Carvalho de Melo struct symbol *pos; 3302e538c4aSArnaldo Carvalho de Melo int count = 0; 3312e538c4aSArnaldo Carvalho de Melo struct rb_node *next = rb_first(&kernel_map->dso->syms); 3322e538c4aSArnaldo Carvalho de Melo int kernel_range = 0; 3332e538c4aSArnaldo Carvalho de Melo 3342e538c4aSArnaldo Carvalho de Melo while (next) { 3352e538c4aSArnaldo Carvalho de Melo char *module; 3362e538c4aSArnaldo Carvalho de Melo 3372e538c4aSArnaldo Carvalho de Melo pos = rb_entry(next, struct symbol, rb_node); 3382e538c4aSArnaldo Carvalho de Melo next = rb_next(&pos->rb_node); 3392e538c4aSArnaldo Carvalho de Melo 3402e538c4aSArnaldo Carvalho de Melo module = strchr(pos->name, '\t'); 3412e538c4aSArnaldo Carvalho de Melo if (module) { 342af427bf5SArnaldo Carvalho de Melo if (!use_modules) 3432e538c4aSArnaldo Carvalho de Melo goto delete_symbol; 3442e538c4aSArnaldo Carvalho de Melo 3452e538c4aSArnaldo Carvalho de Melo *module++ = '\0'; 3462e538c4aSArnaldo Carvalho de Melo 347af427bf5SArnaldo Carvalho de Melo if (strcmp(map->dso->name, module)) { 348af427bf5SArnaldo Carvalho de Melo map = kernel_maps__find_by_dso_name(module); 349af427bf5SArnaldo Carvalho de Melo if (!map) { 3506beba7adSArnaldo Carvalho de Melo pr_err("/proc/{kallsyms,modules} " 3516beba7adSArnaldo Carvalho de Melo "inconsistency!\n"); 352af427bf5SArnaldo Carvalho de Melo return -1; 353af427bf5SArnaldo Carvalho de Melo } 354af427bf5SArnaldo Carvalho de Melo } 35586470930SIngo Molnar /* 3562e538c4aSArnaldo Carvalho de Melo * So that we look just like we get from .ko files, 3572e538c4aSArnaldo Carvalho de Melo * i.e. not prelinked, relative to map->start. 35886470930SIngo Molnar */ 3592e538c4aSArnaldo Carvalho de Melo pos->start = map->map_ip(map, pos->start); 3602e538c4aSArnaldo Carvalho de Melo pos->end = map->map_ip(map, pos->end); 3612e538c4aSArnaldo Carvalho de Melo } else if (map != kernel_map) { 3622e538c4aSArnaldo Carvalho de Melo char dso_name[PATH_MAX]; 3632e538c4aSArnaldo Carvalho de Melo struct dso *dso; 36486470930SIngo Molnar 3652e538c4aSArnaldo Carvalho de Melo snprintf(dso_name, sizeof(dso_name), "[kernel].%d", 3662e538c4aSArnaldo Carvalho de Melo kernel_range++); 36786470930SIngo Molnar 36800a192b3SArnaldo Carvalho de Melo dso = dso__new(dso_name); 3692e538c4aSArnaldo Carvalho de Melo if (dso == NULL) 3702e538c4aSArnaldo Carvalho de Melo return -1; 3712e538c4aSArnaldo Carvalho de Melo 3722e538c4aSArnaldo Carvalho de Melo map = map__new2(pos->start, dso); 3732e538c4aSArnaldo Carvalho de Melo if (map == NULL) { 3742e538c4aSArnaldo Carvalho de Melo dso__delete(dso); 3752e538c4aSArnaldo Carvalho de Melo return -1; 3762e538c4aSArnaldo Carvalho de Melo } 3772e538c4aSArnaldo Carvalho de Melo 378ed52ce2eSArnaldo Carvalho de Melo map->map_ip = map->unmap_ip = identity__map_ip; 3792e538c4aSArnaldo Carvalho de Melo kernel_maps__insert(map); 3802e538c4aSArnaldo Carvalho de Melo ++kernel_range; 3812e538c4aSArnaldo Carvalho de Melo } 3822e538c4aSArnaldo Carvalho de Melo 3832e538c4aSArnaldo Carvalho de Melo if (filter && filter(map, pos)) { 3842e538c4aSArnaldo Carvalho de Melo delete_symbol: 3852e538c4aSArnaldo Carvalho de Melo rb_erase(&pos->rb_node, &kernel_map->dso->syms); 38600a192b3SArnaldo Carvalho de Melo symbol__delete(pos); 3872e538c4aSArnaldo Carvalho de Melo } else { 3882e538c4aSArnaldo Carvalho de Melo if (map != kernel_map) { 3892e538c4aSArnaldo Carvalho de Melo rb_erase(&pos->rb_node, &kernel_map->dso->syms); 3902e538c4aSArnaldo Carvalho de Melo dso__insert_symbol(map->dso, pos); 3912e538c4aSArnaldo Carvalho de Melo } 3929974f496SMike Galbraith count++; 3939974f496SMike Galbraith } 39486470930SIngo Molnar } 39586470930SIngo Molnar 3969974f496SMike Galbraith return count; 39786470930SIngo Molnar } 39886470930SIngo Molnar 3992e538c4aSArnaldo Carvalho de Melo 4006beba7adSArnaldo Carvalho de Melo static int kernel_maps__load_kallsyms(symbol_filter_t filter, int use_modules) 4012e538c4aSArnaldo Carvalho de Melo { 4026beba7adSArnaldo Carvalho de Melo if (kernel_maps__load_all_kallsyms()) 4032e538c4aSArnaldo Carvalho de Melo return -1; 4042e538c4aSArnaldo Carvalho de Melo 4052e538c4aSArnaldo Carvalho de Melo dso__fixup_sym_end(kernel_map->dso); 4062e538c4aSArnaldo Carvalho de Melo 4072e538c4aSArnaldo Carvalho de Melo return kernel_maps__split_kallsyms(filter, use_modules); 4082e538c4aSArnaldo Carvalho de Melo } 4092e538c4aSArnaldo Carvalho de Melo 4106beba7adSArnaldo Carvalho de Melo static size_t kernel_maps__fprintf(FILE *fp) 411af427bf5SArnaldo Carvalho de Melo { 4126beba7adSArnaldo Carvalho de Melo size_t printed = fprintf(fp, "Kernel maps:\n"); 413af427bf5SArnaldo Carvalho de Melo struct rb_node *nd; 414af427bf5SArnaldo Carvalho de Melo 415af427bf5SArnaldo Carvalho de Melo for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) { 416af427bf5SArnaldo Carvalho de Melo struct map *pos = rb_entry(nd, struct map, rb_node); 417af427bf5SArnaldo Carvalho de Melo 4182e538c4aSArnaldo Carvalho de Melo printed += fprintf(fp, "Map:"); 419af427bf5SArnaldo Carvalho de Melo printed += map__fprintf(pos, fp); 4206beba7adSArnaldo Carvalho de Melo if (verbose > 1) { 421af427bf5SArnaldo Carvalho de Melo printed += dso__fprintf(pos->dso, fp); 4222e538c4aSArnaldo Carvalho de Melo printed += fprintf(fp, "--\n"); 4232e538c4aSArnaldo Carvalho de Melo } 424af427bf5SArnaldo Carvalho de Melo } 425af427bf5SArnaldo Carvalho de Melo 4266beba7adSArnaldo Carvalho de Melo return printed + fprintf(fp, "END kernel maps\n"); 427af427bf5SArnaldo Carvalho de Melo } 428af427bf5SArnaldo Carvalho de Melo 429439d473bSArnaldo Carvalho de Melo static int dso__load_perf_map(struct dso *self, struct map *map, 4306beba7adSArnaldo Carvalho de Melo symbol_filter_t filter) 43180d496beSPekka Enberg { 43280d496beSPekka Enberg char *line = NULL; 43380d496beSPekka Enberg size_t n; 43480d496beSPekka Enberg FILE *file; 43580d496beSPekka Enberg int nr_syms = 0; 43680d496beSPekka Enberg 437439d473bSArnaldo Carvalho de Melo file = fopen(self->long_name, "r"); 43880d496beSPekka Enberg if (file == NULL) 43980d496beSPekka Enberg goto out_failure; 44080d496beSPekka Enberg 44180d496beSPekka Enberg while (!feof(file)) { 4429cffa8d5SPaul Mackerras u64 start, size; 44380d496beSPekka Enberg struct symbol *sym; 44480d496beSPekka Enberg int line_len, len; 44580d496beSPekka Enberg 44680d496beSPekka Enberg line_len = getline(&line, &n, file); 44780d496beSPekka Enberg if (line_len < 0) 44880d496beSPekka Enberg break; 44980d496beSPekka Enberg 45080d496beSPekka Enberg if (!line) 45180d496beSPekka Enberg goto out_failure; 45280d496beSPekka Enberg 45380d496beSPekka Enberg line[--line_len] = '\0'; /* \n */ 45480d496beSPekka Enberg 45580d496beSPekka Enberg len = hex2u64(line, &start); 45680d496beSPekka Enberg 45780d496beSPekka Enberg len++; 45880d496beSPekka Enberg if (len + 2 >= line_len) 45980d496beSPekka Enberg continue; 46080d496beSPekka Enberg 46180d496beSPekka Enberg len += hex2u64(line + len, &size); 46280d496beSPekka Enberg 46380d496beSPekka Enberg len++; 46480d496beSPekka Enberg if (len + 2 >= line_len) 46580d496beSPekka Enberg continue; 46680d496beSPekka Enberg 46700a192b3SArnaldo Carvalho de Melo sym = symbol__new(start, size, line + len); 46880d496beSPekka Enberg 46980d496beSPekka Enberg if (sym == NULL) 47080d496beSPekka Enberg goto out_delete_line; 47180d496beSPekka Enberg 472439d473bSArnaldo Carvalho de Melo if (filter && filter(map, sym)) 47300a192b3SArnaldo Carvalho de Melo symbol__delete(sym); 47480d496beSPekka Enberg else { 47580d496beSPekka Enberg dso__insert_symbol(self, sym); 47680d496beSPekka Enberg nr_syms++; 47780d496beSPekka Enberg } 47880d496beSPekka Enberg } 47980d496beSPekka Enberg 48080d496beSPekka Enberg free(line); 48180d496beSPekka Enberg fclose(file); 48280d496beSPekka Enberg 48380d496beSPekka Enberg return nr_syms; 48480d496beSPekka Enberg 48580d496beSPekka Enberg out_delete_line: 48680d496beSPekka Enberg free(line); 48780d496beSPekka Enberg out_failure: 48880d496beSPekka Enberg return -1; 48980d496beSPekka Enberg } 49080d496beSPekka Enberg 49186470930SIngo Molnar /** 49286470930SIngo Molnar * elf_symtab__for_each_symbol - iterate thru all the symbols 49386470930SIngo Molnar * 49486470930SIngo Molnar * @self: struct elf_symtab instance to iterate 49583a0944fSIngo Molnar * @idx: uint32_t idx 49686470930SIngo Molnar * @sym: GElf_Sym iterator 49786470930SIngo Molnar */ 49883a0944fSIngo Molnar #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \ 49983a0944fSIngo Molnar for (idx = 0, gelf_getsym(syms, idx, &sym);\ 50083a0944fSIngo Molnar idx < nr_syms; \ 50183a0944fSIngo Molnar idx++, gelf_getsym(syms, idx, &sym)) 50286470930SIngo Molnar 50386470930SIngo Molnar static inline uint8_t elf_sym__type(const GElf_Sym *sym) 50486470930SIngo Molnar { 50586470930SIngo Molnar return GELF_ST_TYPE(sym->st_info); 50686470930SIngo Molnar } 50786470930SIngo Molnar 50886470930SIngo Molnar static inline int elf_sym__is_function(const GElf_Sym *sym) 50986470930SIngo Molnar { 51086470930SIngo Molnar return elf_sym__type(sym) == STT_FUNC && 51186470930SIngo Molnar sym->st_name != 0 && 51281833130SArnaldo Carvalho de Melo sym->st_shndx != SHN_UNDEF; 51386470930SIngo Molnar } 51486470930SIngo Molnar 5156cfcc53eSMike Galbraith static inline int elf_sym__is_label(const GElf_Sym *sym) 5166cfcc53eSMike Galbraith { 5176cfcc53eSMike Galbraith return elf_sym__type(sym) == STT_NOTYPE && 5186cfcc53eSMike Galbraith sym->st_name != 0 && 5196cfcc53eSMike Galbraith sym->st_shndx != SHN_UNDEF && 5206cfcc53eSMike Galbraith sym->st_shndx != SHN_ABS; 5216cfcc53eSMike Galbraith } 5226cfcc53eSMike Galbraith 5236cfcc53eSMike Galbraith static inline const char *elf_sec__name(const GElf_Shdr *shdr, 5246cfcc53eSMike Galbraith const Elf_Data *secstrs) 5256cfcc53eSMike Galbraith { 5266cfcc53eSMike Galbraith return secstrs->d_buf + shdr->sh_name; 5276cfcc53eSMike Galbraith } 5286cfcc53eSMike Galbraith 5296cfcc53eSMike Galbraith static inline int elf_sec__is_text(const GElf_Shdr *shdr, 5306cfcc53eSMike Galbraith const Elf_Data *secstrs) 5316cfcc53eSMike Galbraith { 5326cfcc53eSMike Galbraith return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; 5336cfcc53eSMike Galbraith } 5346cfcc53eSMike Galbraith 53586470930SIngo Molnar static inline const char *elf_sym__name(const GElf_Sym *sym, 53686470930SIngo Molnar const Elf_Data *symstrs) 53786470930SIngo Molnar { 53886470930SIngo Molnar return symstrs->d_buf + sym->st_name; 53986470930SIngo Molnar } 54086470930SIngo Molnar 54186470930SIngo Molnar static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 54286470930SIngo Molnar GElf_Shdr *shp, const char *name, 54383a0944fSIngo Molnar size_t *idx) 54486470930SIngo Molnar { 54586470930SIngo Molnar Elf_Scn *sec = NULL; 54686470930SIngo Molnar size_t cnt = 1; 54786470930SIngo Molnar 54886470930SIngo Molnar while ((sec = elf_nextscn(elf, sec)) != NULL) { 54986470930SIngo Molnar char *str; 55086470930SIngo Molnar 55186470930SIngo Molnar gelf_getshdr(sec, shp); 55286470930SIngo Molnar str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 55386470930SIngo Molnar if (!strcmp(name, str)) { 55483a0944fSIngo Molnar if (idx) 55583a0944fSIngo Molnar *idx = cnt; 55686470930SIngo Molnar break; 55786470930SIngo Molnar } 55886470930SIngo Molnar ++cnt; 55986470930SIngo Molnar } 56086470930SIngo Molnar 56186470930SIngo Molnar return sec; 56286470930SIngo Molnar } 56386470930SIngo Molnar 56486470930SIngo Molnar #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 56586470930SIngo Molnar for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 56686470930SIngo Molnar idx < nr_entries; \ 56786470930SIngo Molnar ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) 56886470930SIngo Molnar 56986470930SIngo Molnar #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ 57086470930SIngo Molnar for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ 57186470930SIngo Molnar idx < nr_entries; \ 57286470930SIngo Molnar ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 57386470930SIngo Molnar 574a25e46c4SArnaldo Carvalho de Melo /* 575a25e46c4SArnaldo Carvalho de Melo * We need to check if we have a .dynsym, so that we can handle the 576a25e46c4SArnaldo Carvalho de Melo * .plt, synthesizing its symbols, that aren't on the symtabs (be it 577a25e46c4SArnaldo Carvalho de Melo * .dynsym or .symtab). 578a25e46c4SArnaldo Carvalho de Melo * And always look at the original dso, not at debuginfo packages, that 579a25e46c4SArnaldo Carvalho de Melo * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 580a25e46c4SArnaldo Carvalho de Melo */ 58182164161SArnaldo Carvalho de Melo static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, 58282164161SArnaldo Carvalho de Melo symbol_filter_t filter) 58386470930SIngo Molnar { 58486470930SIngo Molnar uint32_t nr_rel_entries, idx; 58586470930SIngo Molnar GElf_Sym sym; 5869cffa8d5SPaul Mackerras u64 plt_offset; 58786470930SIngo Molnar GElf_Shdr shdr_plt; 58886470930SIngo Molnar struct symbol *f; 589a25e46c4SArnaldo Carvalho de Melo GElf_Shdr shdr_rel_plt, shdr_dynsym; 59086470930SIngo Molnar Elf_Data *reldata, *syms, *symstrs; 591a25e46c4SArnaldo Carvalho de Melo Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; 592a25e46c4SArnaldo Carvalho de Melo size_t dynsym_idx; 593a25e46c4SArnaldo Carvalho de Melo GElf_Ehdr ehdr; 59486470930SIngo Molnar char sympltname[1024]; 595a25e46c4SArnaldo Carvalho de Melo Elf *elf; 596a25e46c4SArnaldo Carvalho de Melo int nr = 0, symidx, fd, err = 0; 59786470930SIngo Molnar 598439d473bSArnaldo Carvalho de Melo fd = open(self->long_name, O_RDONLY); 599a25e46c4SArnaldo Carvalho de Melo if (fd < 0) 600a25e46c4SArnaldo Carvalho de Melo goto out; 601a25e46c4SArnaldo Carvalho de Melo 60284087126SMarti Raudsepp elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 603a25e46c4SArnaldo Carvalho de Melo if (elf == NULL) 604a25e46c4SArnaldo Carvalho de Melo goto out_close; 605a25e46c4SArnaldo Carvalho de Melo 606a25e46c4SArnaldo Carvalho de Melo if (gelf_getehdr(elf, &ehdr) == NULL) 607a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 608a25e46c4SArnaldo Carvalho de Melo 609a25e46c4SArnaldo Carvalho de Melo scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym, 610a25e46c4SArnaldo Carvalho de Melo ".dynsym", &dynsym_idx); 611a25e46c4SArnaldo Carvalho de Melo if (scn_dynsym == NULL) 612a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 613a25e46c4SArnaldo Carvalho de Melo 614a25e46c4SArnaldo Carvalho de Melo scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, 61586470930SIngo Molnar ".rela.plt", NULL); 61686470930SIngo Molnar if (scn_plt_rel == NULL) { 617a25e46c4SArnaldo Carvalho de Melo scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, 61886470930SIngo Molnar ".rel.plt", NULL); 61986470930SIngo Molnar if (scn_plt_rel == NULL) 620a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 62186470930SIngo Molnar } 62286470930SIngo Molnar 623a25e46c4SArnaldo Carvalho de Melo err = -1; 62486470930SIngo Molnar 625a25e46c4SArnaldo Carvalho de Melo if (shdr_rel_plt.sh_link != dynsym_idx) 626a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 627a25e46c4SArnaldo Carvalho de Melo 628a25e46c4SArnaldo Carvalho de Melo if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) 629a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 63086470930SIngo Molnar 63186470930SIngo Molnar /* 63283a0944fSIngo Molnar * Fetch the relocation section to find the idxes to the GOT 63386470930SIngo Molnar * and the symbols in the .dynsym they refer to. 63486470930SIngo Molnar */ 63586470930SIngo Molnar reldata = elf_getdata(scn_plt_rel, NULL); 63686470930SIngo Molnar if (reldata == NULL) 637a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 63886470930SIngo Molnar 63986470930SIngo Molnar syms = elf_getdata(scn_dynsym, NULL); 64086470930SIngo Molnar if (syms == NULL) 641a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 64286470930SIngo Molnar 643a25e46c4SArnaldo Carvalho de Melo scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); 64486470930SIngo Molnar if (scn_symstrs == NULL) 645a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 64686470930SIngo Molnar 64786470930SIngo Molnar symstrs = elf_getdata(scn_symstrs, NULL); 64886470930SIngo Molnar if (symstrs == NULL) 649a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 65086470930SIngo Molnar 65186470930SIngo Molnar nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 65286470930SIngo Molnar plt_offset = shdr_plt.sh_offset; 65386470930SIngo Molnar 65486470930SIngo Molnar if (shdr_rel_plt.sh_type == SHT_RELA) { 65586470930SIngo Molnar GElf_Rela pos_mem, *pos; 65686470930SIngo Molnar 65786470930SIngo Molnar elf_section__for_each_rela(reldata, pos, pos_mem, idx, 65886470930SIngo Molnar nr_rel_entries) { 65986470930SIngo Molnar symidx = GELF_R_SYM(pos->r_info); 66086470930SIngo Molnar plt_offset += shdr_plt.sh_entsize; 66186470930SIngo Molnar gelf_getsym(syms, symidx, &sym); 66286470930SIngo Molnar snprintf(sympltname, sizeof(sympltname), 66386470930SIngo Molnar "%s@plt", elf_sym__name(&sym, symstrs)); 66486470930SIngo Molnar 66586470930SIngo Molnar f = symbol__new(plt_offset, shdr_plt.sh_entsize, 66600a192b3SArnaldo Carvalho de Melo sympltname); 66786470930SIngo Molnar if (!f) 668a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 66986470930SIngo Molnar 67082164161SArnaldo Carvalho de Melo if (filter && filter(map, f)) 67182164161SArnaldo Carvalho de Melo symbol__delete(f); 67282164161SArnaldo Carvalho de Melo else { 67386470930SIngo Molnar dso__insert_symbol(self, f); 67486470930SIngo Molnar ++nr; 67586470930SIngo Molnar } 67682164161SArnaldo Carvalho de Melo } 67786470930SIngo Molnar } else if (shdr_rel_plt.sh_type == SHT_REL) { 67886470930SIngo Molnar GElf_Rel pos_mem, *pos; 67986470930SIngo Molnar elf_section__for_each_rel(reldata, pos, pos_mem, idx, 68086470930SIngo Molnar nr_rel_entries) { 68186470930SIngo Molnar symidx = GELF_R_SYM(pos->r_info); 68286470930SIngo Molnar plt_offset += shdr_plt.sh_entsize; 68386470930SIngo Molnar gelf_getsym(syms, symidx, &sym); 68486470930SIngo Molnar snprintf(sympltname, sizeof(sympltname), 68586470930SIngo Molnar "%s@plt", elf_sym__name(&sym, symstrs)); 68686470930SIngo Molnar 68786470930SIngo Molnar f = symbol__new(plt_offset, shdr_plt.sh_entsize, 68800a192b3SArnaldo Carvalho de Melo sympltname); 68986470930SIngo Molnar if (!f) 690a25e46c4SArnaldo Carvalho de Melo goto out_elf_end; 69186470930SIngo Molnar 69282164161SArnaldo Carvalho de Melo if (filter && filter(map, f)) 69382164161SArnaldo Carvalho de Melo symbol__delete(f); 69482164161SArnaldo Carvalho de Melo else { 69586470930SIngo Molnar dso__insert_symbol(self, f); 69686470930SIngo Molnar ++nr; 69786470930SIngo Molnar } 69886470930SIngo Molnar } 69982164161SArnaldo Carvalho de Melo } 70086470930SIngo Molnar 701a25e46c4SArnaldo Carvalho de Melo err = 0; 702a25e46c4SArnaldo Carvalho de Melo out_elf_end: 703a25e46c4SArnaldo Carvalho de Melo elf_end(elf); 704a25e46c4SArnaldo Carvalho de Melo out_close: 705a25e46c4SArnaldo Carvalho de Melo close(fd); 706a25e46c4SArnaldo Carvalho de Melo 707a25e46c4SArnaldo Carvalho de Melo if (err == 0) 70886470930SIngo Molnar return nr; 709a25e46c4SArnaldo Carvalho de Melo out: 7106beba7adSArnaldo Carvalho de Melo pr_warning("%s: problems reading %s PLT info.\n", 711439d473bSArnaldo Carvalho de Melo __func__, self->long_name); 712a25e46c4SArnaldo Carvalho de Melo return 0; 71386470930SIngo Molnar } 71486470930SIngo Molnar 715439d473bSArnaldo Carvalho de Melo static int dso__load_sym(struct dso *self, struct map *map, const char *name, 716439d473bSArnaldo Carvalho de Melo int fd, symbol_filter_t filter, int kernel, 7176beba7adSArnaldo Carvalho de Melo int kmodule) 71886470930SIngo Molnar { 7192e538c4aSArnaldo Carvalho de Melo struct map *curr_map = map; 7202e538c4aSArnaldo Carvalho de Melo struct dso *curr_dso = self; 7212e538c4aSArnaldo Carvalho de Melo size_t dso_name_len = strlen(self->short_name); 7226cfcc53eSMike Galbraith Elf_Data *symstrs, *secstrs; 72386470930SIngo Molnar uint32_t nr_syms; 72486470930SIngo Molnar int err = -1; 72583a0944fSIngo Molnar uint32_t idx; 72686470930SIngo Molnar GElf_Ehdr ehdr; 72786470930SIngo Molnar GElf_Shdr shdr; 72886470930SIngo Molnar Elf_Data *syms; 72986470930SIngo Molnar GElf_Sym sym; 730a25e46c4SArnaldo Carvalho de Melo Elf_Scn *sec, *sec_strndx; 73186470930SIngo Molnar Elf *elf; 732439d473bSArnaldo Carvalho de Melo int nr = 0; 73386470930SIngo Molnar 73484087126SMarti Raudsepp elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 73586470930SIngo Molnar if (elf == NULL) { 7366beba7adSArnaldo Carvalho de Melo pr_err("%s: cannot read %s ELF file.\n", __func__, name); 73786470930SIngo Molnar goto out_close; 73886470930SIngo Molnar } 73986470930SIngo Molnar 74086470930SIngo Molnar if (gelf_getehdr(elf, &ehdr) == NULL) { 7416beba7adSArnaldo Carvalho de Melo pr_err("%s: cannot get elf header.\n", __func__); 74286470930SIngo Molnar goto out_elf_end; 74386470930SIngo Molnar } 74486470930SIngo Molnar 74586470930SIngo Molnar sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 74686470930SIngo Molnar if (sec == NULL) { 747a25e46c4SArnaldo Carvalho de Melo sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); 748a25e46c4SArnaldo Carvalho de Melo if (sec == NULL) 74986470930SIngo Molnar goto out_elf_end; 75086470930SIngo Molnar } 75186470930SIngo Molnar 75286470930SIngo Molnar syms = elf_getdata(sec, NULL); 75386470930SIngo Molnar if (syms == NULL) 75486470930SIngo Molnar goto out_elf_end; 75586470930SIngo Molnar 75686470930SIngo Molnar sec = elf_getscn(elf, shdr.sh_link); 75786470930SIngo Molnar if (sec == NULL) 75886470930SIngo Molnar goto out_elf_end; 75986470930SIngo Molnar 76086470930SIngo Molnar symstrs = elf_getdata(sec, NULL); 76186470930SIngo Molnar if (symstrs == NULL) 76286470930SIngo Molnar goto out_elf_end; 76386470930SIngo Molnar 7646cfcc53eSMike Galbraith sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 7656cfcc53eSMike Galbraith if (sec_strndx == NULL) 7666cfcc53eSMike Galbraith goto out_elf_end; 7676cfcc53eSMike Galbraith 7686cfcc53eSMike Galbraith secstrs = elf_getdata(sec_strndx, NULL); 7699b30a26bSStoyan Gaydarov if (secstrs == NULL) 7706cfcc53eSMike Galbraith goto out_elf_end; 7716cfcc53eSMike Galbraith 77286470930SIngo Molnar nr_syms = shdr.sh_size / shdr.sh_entsize; 77386470930SIngo Molnar 774e9fbc9dcSArjan van de Ven memset(&sym, 0, sizeof(sym)); 775d20ff6bdSMike Galbraith if (!kernel) { 77630d7a77dSArnaldo Carvalho de Melo self->adjust_symbols = (ehdr.e_type == ET_EXEC || 77730d7a77dSArnaldo Carvalho de Melo elf_section_by_name(elf, &ehdr, &shdr, 778f5812a7aSArnaldo Carvalho de Melo ".gnu.prelink_undo", 77930d7a77dSArnaldo Carvalho de Melo NULL) != NULL); 780d20ff6bdSMike Galbraith } else self->adjust_symbols = 0; 781d20ff6bdSMike Galbraith 78283a0944fSIngo Molnar elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 78386470930SIngo Molnar struct symbol *f; 78483a0944fSIngo Molnar const char *elf_name; 7852e538c4aSArnaldo Carvalho de Melo char *demangled = NULL; 7866cfcc53eSMike Galbraith int is_label = elf_sym__is_label(&sym); 7876cfcc53eSMike Galbraith const char *section_name; 78886470930SIngo Molnar 7896cfcc53eSMike Galbraith if (!is_label && !elf_sym__is_function(&sym)) 79086470930SIngo Molnar continue; 79186470930SIngo Molnar 79286470930SIngo Molnar sec = elf_getscn(elf, sym.st_shndx); 79386470930SIngo Molnar if (!sec) 79486470930SIngo Molnar goto out_elf_end; 79586470930SIngo Molnar 79686470930SIngo Molnar gelf_getshdr(sec, &shdr); 7976cfcc53eSMike Galbraith 7986cfcc53eSMike Galbraith if (is_label && !elf_sec__is_text(&shdr, secstrs)) 7996cfcc53eSMike Galbraith continue; 8006cfcc53eSMike Galbraith 8012e538c4aSArnaldo Carvalho de Melo elf_name = elf_sym__name(&sym, symstrs); 8026cfcc53eSMike Galbraith section_name = elf_sec__name(&shdr, secstrs); 80386470930SIngo Molnar 8042e538c4aSArnaldo Carvalho de Melo if (kernel || kmodule) { 8052e538c4aSArnaldo Carvalho de Melo char dso_name[PATH_MAX]; 8062e538c4aSArnaldo Carvalho de Melo 8072e538c4aSArnaldo Carvalho de Melo if (strcmp(section_name, 8082e538c4aSArnaldo Carvalho de Melo curr_dso->short_name + dso_name_len) == 0) 8092e538c4aSArnaldo Carvalho de Melo goto new_symbol; 8102e538c4aSArnaldo Carvalho de Melo 8112e538c4aSArnaldo Carvalho de Melo if (strcmp(section_name, ".text") == 0) { 8122e538c4aSArnaldo Carvalho de Melo curr_map = map; 8132e538c4aSArnaldo Carvalho de Melo curr_dso = self; 8142e538c4aSArnaldo Carvalho de Melo goto new_symbol; 815af427bf5SArnaldo Carvalho de Melo } 816af427bf5SArnaldo Carvalho de Melo 8172e538c4aSArnaldo Carvalho de Melo snprintf(dso_name, sizeof(dso_name), 8182e538c4aSArnaldo Carvalho de Melo "%s%s", self->short_name, section_name); 8192e538c4aSArnaldo Carvalho de Melo 8202e538c4aSArnaldo Carvalho de Melo curr_map = kernel_maps__find_by_dso_name(dso_name); 8212e538c4aSArnaldo Carvalho de Melo if (curr_map == NULL) { 8222e538c4aSArnaldo Carvalho de Melo u64 start = sym.st_value; 8232e538c4aSArnaldo Carvalho de Melo 8242e538c4aSArnaldo Carvalho de Melo if (kmodule) 8252e538c4aSArnaldo Carvalho de Melo start += map->start + shdr.sh_offset; 8262e538c4aSArnaldo Carvalho de Melo 82700a192b3SArnaldo Carvalho de Melo curr_dso = dso__new(dso_name); 8282e538c4aSArnaldo Carvalho de Melo if (curr_dso == NULL) 8292e538c4aSArnaldo Carvalho de Melo goto out_elf_end; 8302e538c4aSArnaldo Carvalho de Melo curr_map = map__new2(start, curr_dso); 8312e538c4aSArnaldo Carvalho de Melo if (curr_map == NULL) { 8322e538c4aSArnaldo Carvalho de Melo dso__delete(curr_dso); 8332e538c4aSArnaldo Carvalho de Melo goto out_elf_end; 8342e538c4aSArnaldo Carvalho de Melo } 835ed52ce2eSArnaldo Carvalho de Melo curr_map->map_ip = identity__map_ip; 836ed52ce2eSArnaldo Carvalho de Melo curr_map->unmap_ip = identity__map_ip; 8372e538c4aSArnaldo Carvalho de Melo curr_dso->origin = DSO__ORIG_KERNEL; 8382e538c4aSArnaldo Carvalho de Melo kernel_maps__insert(curr_map); 8392e538c4aSArnaldo Carvalho de Melo dsos__add(curr_dso); 8402e538c4aSArnaldo Carvalho de Melo } else 8412e538c4aSArnaldo Carvalho de Melo curr_dso = curr_map->dso; 8422e538c4aSArnaldo Carvalho de Melo 8432e538c4aSArnaldo Carvalho de Melo goto new_symbol; 8442e538c4aSArnaldo Carvalho de Melo } 8452e538c4aSArnaldo Carvalho de Melo 8462e538c4aSArnaldo Carvalho de Melo if (curr_dso->adjust_symbols) { 8476beba7adSArnaldo Carvalho de Melo pr_debug2("adjusting symbol: st_value: %Lx sh_addr: " 8486beba7adSArnaldo Carvalho de Melo "%Lx sh_offset: %Lx\n", (u64)sym.st_value, 8496beba7adSArnaldo Carvalho de Melo (u64)shdr.sh_addr, (u64)shdr.sh_offset); 85086470930SIngo Molnar sym.st_value -= shdr.sh_addr - shdr.sh_offset; 851af427bf5SArnaldo Carvalho de Melo } 85228ac909bSArnaldo Carvalho de Melo /* 85328ac909bSArnaldo Carvalho de Melo * We need to figure out if the object was created from C++ sources 85428ac909bSArnaldo Carvalho de Melo * DWARF DW_compile_unit has this, but we don't always have access 85528ac909bSArnaldo Carvalho de Melo * to it... 85628ac909bSArnaldo Carvalho de Melo */ 85783a0944fSIngo Molnar demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); 85828ac909bSArnaldo Carvalho de Melo if (demangled != NULL) 85983a0944fSIngo Molnar elf_name = demangled; 8602e538c4aSArnaldo Carvalho de Melo new_symbol: 86100a192b3SArnaldo Carvalho de Melo f = symbol__new(sym.st_value, sym.st_size, elf_name); 86228ac909bSArnaldo Carvalho de Melo free(demangled); 86386470930SIngo Molnar if (!f) 86486470930SIngo Molnar goto out_elf_end; 86586470930SIngo Molnar 8662e538c4aSArnaldo Carvalho de Melo if (filter && filter(curr_map, f)) 86700a192b3SArnaldo Carvalho de Melo symbol__delete(f); 86886470930SIngo Molnar else { 8692e538c4aSArnaldo Carvalho de Melo dso__insert_symbol(curr_dso, f); 87086470930SIngo Molnar nr++; 87186470930SIngo Molnar } 87286470930SIngo Molnar } 87386470930SIngo Molnar 8742e538c4aSArnaldo Carvalho de Melo /* 8752e538c4aSArnaldo Carvalho de Melo * For misannotated, zeroed, ASM function sizes. 8762e538c4aSArnaldo Carvalho de Melo */ 8772e538c4aSArnaldo Carvalho de Melo if (nr > 0) 8782e538c4aSArnaldo Carvalho de Melo dso__fixup_sym_end(self); 87986470930SIngo Molnar err = nr; 88086470930SIngo Molnar out_elf_end: 88186470930SIngo Molnar elf_end(elf); 88286470930SIngo Molnar out_close: 88386470930SIngo Molnar return err; 88486470930SIngo Molnar } 88586470930SIngo Molnar 886*e30a3d12SArnaldo Carvalho de Melo bool dsos__read_build_ids(void) 88757f395a7SFrederic Weisbecker { 888*e30a3d12SArnaldo Carvalho de Melo bool have_build_id = false; 88957f395a7SFrederic Weisbecker struct dso *pos; 89057f395a7SFrederic Weisbecker 891*e30a3d12SArnaldo Carvalho de Melo list_for_each_entry(pos, &dsos, node) 892*e30a3d12SArnaldo Carvalho de Melo if (filename__read_build_id(pos->long_name, pos->build_id, 893*e30a3d12SArnaldo Carvalho de Melo sizeof(pos->build_id)) > 0) { 894*e30a3d12SArnaldo Carvalho de Melo have_build_id = true; 895*e30a3d12SArnaldo Carvalho de Melo pos->has_build_id = true; 89657f395a7SFrederic Weisbecker } 89757f395a7SFrederic Weisbecker 898*e30a3d12SArnaldo Carvalho de Melo return have_build_id; 89957f395a7SFrederic Weisbecker } 90057f395a7SFrederic Weisbecker 9012643ce11SArnaldo Carvalho de Melo int filename__read_build_id(const char *filename, void *bf, size_t size) 9024d1e00a8SArnaldo Carvalho de Melo { 9032643ce11SArnaldo Carvalho de Melo int fd, err = -1; 9044d1e00a8SArnaldo Carvalho de Melo GElf_Ehdr ehdr; 9054d1e00a8SArnaldo Carvalho de Melo GElf_Shdr shdr; 9064d1e00a8SArnaldo Carvalho de Melo Elf_Data *build_id_data; 9074d1e00a8SArnaldo Carvalho de Melo Elf_Scn *sec; 9084d1e00a8SArnaldo Carvalho de Melo Elf *elf; 9094d1e00a8SArnaldo Carvalho de Melo 9102643ce11SArnaldo Carvalho de Melo if (size < BUILD_ID_SIZE) 9112643ce11SArnaldo Carvalho de Melo goto out; 9122643ce11SArnaldo Carvalho de Melo 9132643ce11SArnaldo Carvalho de Melo fd = open(filename, O_RDONLY); 9144d1e00a8SArnaldo Carvalho de Melo if (fd < 0) 9154d1e00a8SArnaldo Carvalho de Melo goto out; 9164d1e00a8SArnaldo Carvalho de Melo 91784087126SMarti Raudsepp elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 9184d1e00a8SArnaldo Carvalho de Melo if (elf == NULL) { 9198d06367fSArnaldo Carvalho de Melo pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); 9204d1e00a8SArnaldo Carvalho de Melo goto out_close; 9214d1e00a8SArnaldo Carvalho de Melo } 9224d1e00a8SArnaldo Carvalho de Melo 9234d1e00a8SArnaldo Carvalho de Melo if (gelf_getehdr(elf, &ehdr) == NULL) { 9246beba7adSArnaldo Carvalho de Melo pr_err("%s: cannot get elf header.\n", __func__); 9254d1e00a8SArnaldo Carvalho de Melo goto out_elf_end; 9264d1e00a8SArnaldo Carvalho de Melo } 9274d1e00a8SArnaldo Carvalho de Melo 9282643ce11SArnaldo Carvalho de Melo sec = elf_section_by_name(elf, &ehdr, &shdr, 9292643ce11SArnaldo Carvalho de Melo ".note.gnu.build-id", NULL); 9304d1e00a8SArnaldo Carvalho de Melo if (sec == NULL) 9314d1e00a8SArnaldo Carvalho de Melo goto out_elf_end; 9324d1e00a8SArnaldo Carvalho de Melo 9334d1e00a8SArnaldo Carvalho de Melo build_id_data = elf_getdata(sec, NULL); 9344d1e00a8SArnaldo Carvalho de Melo if (build_id_data == NULL) 9354d1e00a8SArnaldo Carvalho de Melo goto out_elf_end; 9362643ce11SArnaldo Carvalho de Melo memcpy(bf, build_id_data->d_buf + 16, BUILD_ID_SIZE); 9372643ce11SArnaldo Carvalho de Melo err = BUILD_ID_SIZE; 9382643ce11SArnaldo Carvalho de Melo out_elf_end: 9392643ce11SArnaldo Carvalho de Melo elf_end(elf); 9402643ce11SArnaldo Carvalho de Melo out_close: 9412643ce11SArnaldo Carvalho de Melo close(fd); 9422643ce11SArnaldo Carvalho de Melo out: 9432643ce11SArnaldo Carvalho de Melo return err; 9442643ce11SArnaldo Carvalho de Melo } 9452643ce11SArnaldo Carvalho de Melo 94694cb9e38SArnaldo Carvalho de Melo char dso__symtab_origin(const struct dso *self) 94794cb9e38SArnaldo Carvalho de Melo { 94894cb9e38SArnaldo Carvalho de Melo static const char origin[] = { 94994cb9e38SArnaldo Carvalho de Melo [DSO__ORIG_KERNEL] = 'k', 95094cb9e38SArnaldo Carvalho de Melo [DSO__ORIG_JAVA_JIT] = 'j', 95194cb9e38SArnaldo Carvalho de Melo [DSO__ORIG_FEDORA] = 'f', 95294cb9e38SArnaldo Carvalho de Melo [DSO__ORIG_UBUNTU] = 'u', 95394cb9e38SArnaldo Carvalho de Melo [DSO__ORIG_BUILDID] = 'b', 95494cb9e38SArnaldo Carvalho de Melo [DSO__ORIG_DSO] = 'd', 955439d473bSArnaldo Carvalho de Melo [DSO__ORIG_KMODULE] = 'K', 95694cb9e38SArnaldo Carvalho de Melo }; 95794cb9e38SArnaldo Carvalho de Melo 95894cb9e38SArnaldo Carvalho de Melo if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 95994cb9e38SArnaldo Carvalho de Melo return '!'; 96094cb9e38SArnaldo Carvalho de Melo return origin[self->origin]; 96194cb9e38SArnaldo Carvalho de Melo } 96294cb9e38SArnaldo Carvalho de Melo 9636beba7adSArnaldo Carvalho de Melo int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) 96486470930SIngo Molnar { 9654d1e00a8SArnaldo Carvalho de Melo int size = PATH_MAX; 966d3379ab9SArnaldo Carvalho de Melo char *name = malloc(size); 967d3379ab9SArnaldo Carvalho de Melo u8 build_id[BUILD_ID_SIZE]; 96886470930SIngo Molnar int ret = -1; 96986470930SIngo Molnar int fd; 97086470930SIngo Molnar 9718d06367fSArnaldo Carvalho de Melo self->loaded = 1; 97266bd8424SArnaldo Carvalho de Melo 97386470930SIngo Molnar if (!name) 97486470930SIngo Molnar return -1; 97586470930SIngo Molnar 97630d7a77dSArnaldo Carvalho de Melo self->adjust_symbols = 0; 977f5812a7aSArnaldo Carvalho de Melo 97894cb9e38SArnaldo Carvalho de Melo if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 9796beba7adSArnaldo Carvalho de Melo ret = dso__load_perf_map(self, map, filter); 98094cb9e38SArnaldo Carvalho de Melo self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 98194cb9e38SArnaldo Carvalho de Melo DSO__ORIG_NOT_FOUND; 98294cb9e38SArnaldo Carvalho de Melo return ret; 98394cb9e38SArnaldo Carvalho de Melo } 98494cb9e38SArnaldo Carvalho de Melo 98594cb9e38SArnaldo Carvalho de Melo self->origin = DSO__ORIG_FEDORA - 1; 98680d496beSPekka Enberg 98786470930SIngo Molnar more: 98886470930SIngo Molnar do { 98994cb9e38SArnaldo Carvalho de Melo self->origin++; 99094cb9e38SArnaldo Carvalho de Melo switch (self->origin) { 99194cb9e38SArnaldo Carvalho de Melo case DSO__ORIG_FEDORA: 992439d473bSArnaldo Carvalho de Melo snprintf(name, size, "/usr/lib/debug%s.debug", 993439d473bSArnaldo Carvalho de Melo self->long_name); 99486470930SIngo Molnar break; 99594cb9e38SArnaldo Carvalho de Melo case DSO__ORIG_UBUNTU: 996439d473bSArnaldo Carvalho de Melo snprintf(name, size, "/usr/lib/debug%s", 997439d473bSArnaldo Carvalho de Melo self->long_name); 99886470930SIngo Molnar break; 99994cb9e38SArnaldo Carvalho de Melo case DSO__ORIG_BUILDID: 1000d3379ab9SArnaldo Carvalho de Melo if (filename__read_build_id(self->long_name, build_id, 1001d3379ab9SArnaldo Carvalho de Melo sizeof(build_id))) { 1002d3379ab9SArnaldo Carvalho de Melo char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1003d3379ab9SArnaldo Carvalho de Melo 1004d3379ab9SArnaldo Carvalho de Melo build_id__sprintf(build_id, sizeof(build_id), 1005d3379ab9SArnaldo Carvalho de Melo build_id_hex); 10064d1e00a8SArnaldo Carvalho de Melo snprintf(name, size, 10074d1e00a8SArnaldo Carvalho de Melo "/usr/lib/debug/.build-id/%.2s/%s.debug", 1008d3379ab9SArnaldo Carvalho de Melo build_id_hex, build_id_hex + 2); 1009d3379ab9SArnaldo Carvalho de Melo if (self->has_build_id) 10108d06367fSArnaldo Carvalho de Melo goto compare_build_id; 1011d3379ab9SArnaldo Carvalho de Melo break; 10124d1e00a8SArnaldo Carvalho de Melo } 101394cb9e38SArnaldo Carvalho de Melo self->origin++; 10144d1e00a8SArnaldo Carvalho de Melo /* Fall thru */ 101594cb9e38SArnaldo Carvalho de Melo case DSO__ORIG_DSO: 1016439d473bSArnaldo Carvalho de Melo snprintf(name, size, "%s", self->long_name); 101786470930SIngo Molnar break; 101886470930SIngo Molnar 101986470930SIngo Molnar default: 102086470930SIngo Molnar goto out; 102186470930SIngo Molnar } 102286470930SIngo Molnar 10238d06367fSArnaldo Carvalho de Melo if (self->has_build_id) { 1024d3379ab9SArnaldo Carvalho de Melo if (filename__read_build_id(name, build_id, 1025d3379ab9SArnaldo Carvalho de Melo sizeof(build_id)) < 0) 10268d06367fSArnaldo Carvalho de Melo goto more; 10278d06367fSArnaldo Carvalho de Melo compare_build_id: 1028d3379ab9SArnaldo Carvalho de Melo if (memcmp(build_id, self->build_id, 1029d3379ab9SArnaldo Carvalho de Melo sizeof(self->build_id)) != 0) 10308d06367fSArnaldo Carvalho de Melo goto more; 10318d06367fSArnaldo Carvalho de Melo } 10328d06367fSArnaldo Carvalho de Melo 103386470930SIngo Molnar fd = open(name, O_RDONLY); 103486470930SIngo Molnar } while (fd < 0); 103586470930SIngo Molnar 10366beba7adSArnaldo Carvalho de Melo ret = dso__load_sym(self, map, name, fd, filter, 0, 0); 103786470930SIngo Molnar close(fd); 103886470930SIngo Molnar 103986470930SIngo Molnar /* 104086470930SIngo Molnar * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 104186470930SIngo Molnar */ 104286470930SIngo Molnar if (!ret) 104386470930SIngo Molnar goto more; 104486470930SIngo Molnar 1045a25e46c4SArnaldo Carvalho de Melo if (ret > 0) { 104682164161SArnaldo Carvalho de Melo int nr_plt = dso__synthesize_plt_symbols(self, map, filter); 1047a25e46c4SArnaldo Carvalho de Melo if (nr_plt > 0) 1048a25e46c4SArnaldo Carvalho de Melo ret += nr_plt; 1049a25e46c4SArnaldo Carvalho de Melo } 105086470930SIngo Molnar out: 105186470930SIngo Molnar free(name); 10521340e6bbSArnaldo Carvalho de Melo if (ret < 0 && strstr(self->name, " (deleted)") != NULL) 10531340e6bbSArnaldo Carvalho de Melo return 0; 105486470930SIngo Molnar return ret; 105586470930SIngo Molnar } 105686470930SIngo Molnar 1057439d473bSArnaldo Carvalho de Melo struct map *kernel_map; 1058439d473bSArnaldo Carvalho de Melo 1059439d473bSArnaldo Carvalho de Melo static void kernel_maps__insert(struct map *map) 1060439d473bSArnaldo Carvalho de Melo { 1061439d473bSArnaldo Carvalho de Melo maps__insert(&kernel_maps, map); 1062439d473bSArnaldo Carvalho de Melo } 1063439d473bSArnaldo Carvalho de Melo 1064439d473bSArnaldo Carvalho de Melo struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp) 1065439d473bSArnaldo Carvalho de Melo { 1066439d473bSArnaldo Carvalho de Melo struct map *map = maps__find(&kernel_maps, ip); 1067439d473bSArnaldo Carvalho de Melo 1068439d473bSArnaldo Carvalho de Melo if (mapp) 1069439d473bSArnaldo Carvalho de Melo *mapp = map; 1070439d473bSArnaldo Carvalho de Melo 10712e538c4aSArnaldo Carvalho de Melo if (map) { 10722e538c4aSArnaldo Carvalho de Melo ip = map->map_ip(map, ip); 10732e538c4aSArnaldo Carvalho de Melo return map->dso->find_symbol(map->dso, ip); 10742e538c4aSArnaldo Carvalho de Melo } 10752e538c4aSArnaldo Carvalho de Melo 10762e538c4aSArnaldo Carvalho de Melo return NULL; 1077439d473bSArnaldo Carvalho de Melo } 1078439d473bSArnaldo Carvalho de Melo 1079439d473bSArnaldo Carvalho de Melo struct map *kernel_maps__find_by_dso_name(const char *name) 1080439d473bSArnaldo Carvalho de Melo { 1081439d473bSArnaldo Carvalho de Melo struct rb_node *nd; 1082439d473bSArnaldo Carvalho de Melo 1083439d473bSArnaldo Carvalho de Melo for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) { 1084439d473bSArnaldo Carvalho de Melo struct map *map = rb_entry(nd, struct map, rb_node); 1085439d473bSArnaldo Carvalho de Melo 1086439d473bSArnaldo Carvalho de Melo if (map->dso && strcmp(map->dso->name, name) == 0) 1087439d473bSArnaldo Carvalho de Melo return map; 1088439d473bSArnaldo Carvalho de Melo } 1089439d473bSArnaldo Carvalho de Melo 1090439d473bSArnaldo Carvalho de Melo return NULL; 1091439d473bSArnaldo Carvalho de Melo } 1092439d473bSArnaldo Carvalho de Melo 1093439d473bSArnaldo Carvalho de Melo static int dso__load_module_sym(struct dso *self, struct map *map, 10946beba7adSArnaldo Carvalho de Melo symbol_filter_t filter) 10956cfcc53eSMike Galbraith { 1096439d473bSArnaldo Carvalho de Melo int err = 0, fd = open(self->long_name, O_RDONLY); 10976cfcc53eSMike Galbraith 10988d06367fSArnaldo Carvalho de Melo self->loaded = 1; 109966bd8424SArnaldo Carvalho de Melo 1100439d473bSArnaldo Carvalho de Melo if (fd < 0) { 11016beba7adSArnaldo Carvalho de Melo pr_err("%s: cannot open %s\n", __func__, self->long_name); 11026cfcc53eSMike Galbraith return err; 1103439d473bSArnaldo Carvalho de Melo } 11046cfcc53eSMike Galbraith 11056beba7adSArnaldo Carvalho de Melo err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1); 11066cfcc53eSMike Galbraith close(fd); 11076cfcc53eSMike Galbraith 11086cfcc53eSMike Galbraith return err; 11096cfcc53eSMike Galbraith } 11106cfcc53eSMike Galbraith 11116beba7adSArnaldo Carvalho de Melo static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter) 11126cfcc53eSMike Galbraith { 1113439d473bSArnaldo Carvalho de Melo struct dirent *dent; 1114439d473bSArnaldo Carvalho de Melo int nr_symbols = 0, err; 1115439d473bSArnaldo Carvalho de Melo DIR *dir = opendir(dirname); 11166cfcc53eSMike Galbraith 1117439d473bSArnaldo Carvalho de Melo if (!dir) { 11186beba7adSArnaldo Carvalho de Melo pr_err("%s: cannot open %s dir\n", __func__, dirname); 1119439d473bSArnaldo Carvalho de Melo return -1; 1120439d473bSArnaldo Carvalho de Melo } 11216cfcc53eSMike Galbraith 1122439d473bSArnaldo Carvalho de Melo while ((dent = readdir(dir)) != NULL) { 1123439d473bSArnaldo Carvalho de Melo char path[PATH_MAX]; 1124439d473bSArnaldo Carvalho de Melo 1125439d473bSArnaldo Carvalho de Melo if (dent->d_type == DT_DIR) { 1126439d473bSArnaldo Carvalho de Melo if (!strcmp(dent->d_name, ".") || 1127439d473bSArnaldo Carvalho de Melo !strcmp(dent->d_name, "..")) 1128439d473bSArnaldo Carvalho de Melo continue; 1129439d473bSArnaldo Carvalho de Melo 1130439d473bSArnaldo Carvalho de Melo snprintf(path, sizeof(path), "%s/%s", 1131439d473bSArnaldo Carvalho de Melo dirname, dent->d_name); 11326beba7adSArnaldo Carvalho de Melo err = dsos__load_modules_sym_dir(path, filter); 1133439d473bSArnaldo Carvalho de Melo if (err < 0) 1134439d473bSArnaldo Carvalho de Melo goto failure; 1135439d473bSArnaldo Carvalho de Melo } else { 1136439d473bSArnaldo Carvalho de Melo char *dot = strrchr(dent->d_name, '.'), 1137439d473bSArnaldo Carvalho de Melo dso_name[PATH_MAX]; 1138439d473bSArnaldo Carvalho de Melo struct map *map; 1139439d473bSArnaldo Carvalho de Melo struct rb_node *last; 1140cfc10d3bSArnaldo Carvalho de Melo char *long_name; 1141439d473bSArnaldo Carvalho de Melo 1142439d473bSArnaldo Carvalho de Melo if (dot == NULL || strcmp(dot, ".ko")) 1143439d473bSArnaldo Carvalho de Melo continue; 1144439d473bSArnaldo Carvalho de Melo snprintf(dso_name, sizeof(dso_name), "[%.*s]", 1145439d473bSArnaldo Carvalho de Melo (int)(dot - dent->d_name), dent->d_name); 1146439d473bSArnaldo Carvalho de Melo 1147a2a99e8eSArnaldo Carvalho de Melo strxfrchar(dso_name, '-', '_'); 1148439d473bSArnaldo Carvalho de Melo map = kernel_maps__find_by_dso_name(dso_name); 1149439d473bSArnaldo Carvalho de Melo if (map == NULL) 1150439d473bSArnaldo Carvalho de Melo continue; 1151439d473bSArnaldo Carvalho de Melo 1152439d473bSArnaldo Carvalho de Melo snprintf(path, sizeof(path), "%s/%s", 1153439d473bSArnaldo Carvalho de Melo dirname, dent->d_name); 1154439d473bSArnaldo Carvalho de Melo 1155cfc10d3bSArnaldo Carvalho de Melo long_name = strdup(path); 1156cfc10d3bSArnaldo Carvalho de Melo if (long_name == NULL) 1157439d473bSArnaldo Carvalho de Melo goto failure; 1158cfc10d3bSArnaldo Carvalho de Melo dso__set_long_name(map->dso, long_name); 1159cfc10d3bSArnaldo Carvalho de Melo dso__set_basename(map->dso); 1160439d473bSArnaldo Carvalho de Melo 11616beba7adSArnaldo Carvalho de Melo err = dso__load_module_sym(map->dso, map, filter); 1162439d473bSArnaldo Carvalho de Melo if (err < 0) 1163439d473bSArnaldo Carvalho de Melo goto failure; 1164439d473bSArnaldo Carvalho de Melo last = rb_last(&map->dso->syms); 1165439d473bSArnaldo Carvalho de Melo if (last) { 1166439d473bSArnaldo Carvalho de Melo struct symbol *sym; 11672e538c4aSArnaldo Carvalho de Melo /* 11682e538c4aSArnaldo Carvalho de Melo * We do this here as well, even having the 11692e538c4aSArnaldo Carvalho de Melo * symbol size found in the symtab because 11702e538c4aSArnaldo Carvalho de Melo * misannotated ASM symbols may have the size 11712e538c4aSArnaldo Carvalho de Melo * set to zero. 11722e538c4aSArnaldo Carvalho de Melo */ 11732e538c4aSArnaldo Carvalho de Melo dso__fixup_sym_end(map->dso); 11742e538c4aSArnaldo Carvalho de Melo 1175439d473bSArnaldo Carvalho de Melo sym = rb_entry(last, struct symbol, rb_node); 1176439d473bSArnaldo Carvalho de Melo map->end = map->start + sym->end; 1177439d473bSArnaldo Carvalho de Melo } 1178439d473bSArnaldo Carvalho de Melo } 1179439d473bSArnaldo Carvalho de Melo nr_symbols += err; 1180439d473bSArnaldo Carvalho de Melo } 1181439d473bSArnaldo Carvalho de Melo 1182439d473bSArnaldo Carvalho de Melo return nr_symbols; 1183439d473bSArnaldo Carvalho de Melo failure: 1184439d473bSArnaldo Carvalho de Melo closedir(dir); 1185439d473bSArnaldo Carvalho de Melo return -1; 1186439d473bSArnaldo Carvalho de Melo } 1187439d473bSArnaldo Carvalho de Melo 11886beba7adSArnaldo Carvalho de Melo static int dsos__load_modules_sym(symbol_filter_t filter) 1189439d473bSArnaldo Carvalho de Melo { 1190439d473bSArnaldo Carvalho de Melo struct utsname uts; 1191439d473bSArnaldo Carvalho de Melo char modules_path[PATH_MAX]; 1192439d473bSArnaldo Carvalho de Melo 1193439d473bSArnaldo Carvalho de Melo if (uname(&uts) < 0) 1194439d473bSArnaldo Carvalho de Melo return -1; 1195439d473bSArnaldo Carvalho de Melo 1196439d473bSArnaldo Carvalho de Melo snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", 1197439d473bSArnaldo Carvalho de Melo uts.release); 1198439d473bSArnaldo Carvalho de Melo 11996beba7adSArnaldo Carvalho de Melo return dsos__load_modules_sym_dir(modules_path, filter); 1200439d473bSArnaldo Carvalho de Melo } 12016cfcc53eSMike Galbraith 12026cfcc53eSMike Galbraith /* 1203439d473bSArnaldo Carvalho de Melo * Constructor variant for modules (where we know from /proc/modules where 1204439d473bSArnaldo Carvalho de Melo * they are loaded) and for vmlinux, where only after we load all the 1205439d473bSArnaldo Carvalho de Melo * symbols we'll know where it starts and ends. 12066cfcc53eSMike Galbraith */ 1207439d473bSArnaldo Carvalho de Melo static struct map *map__new2(u64 start, struct dso *dso) 1208439d473bSArnaldo Carvalho de Melo { 1209439d473bSArnaldo Carvalho de Melo struct map *self = malloc(sizeof(*self)); 12106cfcc53eSMike Galbraith 1211439d473bSArnaldo Carvalho de Melo if (self != NULL) { 1212439d473bSArnaldo Carvalho de Melo /* 1213afb7b4f0SArnaldo Carvalho de Melo * ->end will be filled after we load all the symbols 1214439d473bSArnaldo Carvalho de Melo */ 1215afb7b4f0SArnaldo Carvalho de Melo map__init(self, start, 0, 0, dso); 1216439d473bSArnaldo Carvalho de Melo } 1217afb7b4f0SArnaldo Carvalho de Melo 1218439d473bSArnaldo Carvalho de Melo return self; 1219439d473bSArnaldo Carvalho de Melo } 1220439d473bSArnaldo Carvalho de Melo 122100a192b3SArnaldo Carvalho de Melo static int dsos__load_modules(void) 1222439d473bSArnaldo Carvalho de Melo { 1223439d473bSArnaldo Carvalho de Melo char *line = NULL; 1224439d473bSArnaldo Carvalho de Melo size_t n; 1225439d473bSArnaldo Carvalho de Melo FILE *file = fopen("/proc/modules", "r"); 1226439d473bSArnaldo Carvalho de Melo struct map *map; 1227439d473bSArnaldo Carvalho de Melo 1228439d473bSArnaldo Carvalho de Melo if (file == NULL) 1229439d473bSArnaldo Carvalho de Melo return -1; 1230439d473bSArnaldo Carvalho de Melo 1231439d473bSArnaldo Carvalho de Melo while (!feof(file)) { 1232439d473bSArnaldo Carvalho de Melo char name[PATH_MAX]; 1233439d473bSArnaldo Carvalho de Melo u64 start; 1234439d473bSArnaldo Carvalho de Melo struct dso *dso; 1235439d473bSArnaldo Carvalho de Melo char *sep; 1236439d473bSArnaldo Carvalho de Melo int line_len; 1237439d473bSArnaldo Carvalho de Melo 1238439d473bSArnaldo Carvalho de Melo line_len = getline(&line, &n, file); 1239439d473bSArnaldo Carvalho de Melo if (line_len < 0) 12406cfcc53eSMike Galbraith break; 12416cfcc53eSMike Galbraith 1242439d473bSArnaldo Carvalho de Melo if (!line) 1243439d473bSArnaldo Carvalho de Melo goto out_failure; 1244439d473bSArnaldo Carvalho de Melo 1245439d473bSArnaldo Carvalho de Melo line[--line_len] = '\0'; /* \n */ 1246439d473bSArnaldo Carvalho de Melo 1247439d473bSArnaldo Carvalho de Melo sep = strrchr(line, 'x'); 1248439d473bSArnaldo Carvalho de Melo if (sep == NULL) 1249439d473bSArnaldo Carvalho de Melo continue; 1250439d473bSArnaldo Carvalho de Melo 1251439d473bSArnaldo Carvalho de Melo hex2u64(sep + 1, &start); 1252439d473bSArnaldo Carvalho de Melo 1253439d473bSArnaldo Carvalho de Melo sep = strchr(line, ' '); 1254439d473bSArnaldo Carvalho de Melo if (sep == NULL) 1255439d473bSArnaldo Carvalho de Melo continue; 1256439d473bSArnaldo Carvalho de Melo 1257439d473bSArnaldo Carvalho de Melo *sep = '\0'; 1258439d473bSArnaldo Carvalho de Melo 1259439d473bSArnaldo Carvalho de Melo snprintf(name, sizeof(name), "[%s]", line); 126000a192b3SArnaldo Carvalho de Melo dso = dso__new(name); 1261439d473bSArnaldo Carvalho de Melo 1262439d473bSArnaldo Carvalho de Melo if (dso == NULL) 1263439d473bSArnaldo Carvalho de Melo goto out_delete_line; 1264439d473bSArnaldo Carvalho de Melo 1265439d473bSArnaldo Carvalho de Melo map = map__new2(start, dso); 1266439d473bSArnaldo Carvalho de Melo if (map == NULL) { 1267439d473bSArnaldo Carvalho de Melo dso__delete(dso); 1268439d473bSArnaldo Carvalho de Melo goto out_delete_line; 12696cfcc53eSMike Galbraith } 12706cfcc53eSMike Galbraith 1271439d473bSArnaldo Carvalho de Melo dso->origin = DSO__ORIG_KMODULE; 1272439d473bSArnaldo Carvalho de Melo kernel_maps__insert(map); 1273439d473bSArnaldo Carvalho de Melo dsos__add(dso); 12746cfcc53eSMike Galbraith } 12756cfcc53eSMike Galbraith 1276439d473bSArnaldo Carvalho de Melo free(line); 1277439d473bSArnaldo Carvalho de Melo fclose(file); 1278439d473bSArnaldo Carvalho de Melo 1279af427bf5SArnaldo Carvalho de Melo return 0; 1280439d473bSArnaldo Carvalho de Melo 1281439d473bSArnaldo Carvalho de Melo out_delete_line: 1282439d473bSArnaldo Carvalho de Melo free(line); 1283439d473bSArnaldo Carvalho de Melo out_failure: 1284439d473bSArnaldo Carvalho de Melo return -1; 12856cfcc53eSMike Galbraith } 12866cfcc53eSMike Galbraith 1287439d473bSArnaldo Carvalho de Melo static int dso__load_vmlinux(struct dso *self, struct map *map, 12886beba7adSArnaldo Carvalho de Melo const char *vmlinux, symbol_filter_t filter) 128986470930SIngo Molnar { 129086470930SIngo Molnar int err, fd = open(vmlinux, O_RDONLY); 129186470930SIngo Molnar 12928d06367fSArnaldo Carvalho de Melo self->loaded = 1; 129366bd8424SArnaldo Carvalho de Melo 129486470930SIngo Molnar if (fd < 0) 129586470930SIngo Molnar return -1; 129686470930SIngo Molnar 12976beba7adSArnaldo Carvalho de Melo err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0); 12986cfcc53eSMike Galbraith 129986470930SIngo Molnar close(fd); 130086470930SIngo Molnar 130186470930SIngo Molnar return err; 130286470930SIngo Molnar } 130386470930SIngo Molnar 130400a192b3SArnaldo Carvalho de Melo int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter, 130500a192b3SArnaldo Carvalho de Melo int use_modules) 130686470930SIngo Molnar { 130786470930SIngo Molnar int err = -1; 130800a192b3SArnaldo Carvalho de Melo struct dso *dso = dso__new(vmlinux); 1309439d473bSArnaldo Carvalho de Melo 1310439d473bSArnaldo Carvalho de Melo if (dso == NULL) 1311439d473bSArnaldo Carvalho de Melo return -1; 1312439d473bSArnaldo Carvalho de Melo 1313439d473bSArnaldo Carvalho de Melo dso->short_name = "[kernel]"; 1314439d473bSArnaldo Carvalho de Melo kernel_map = map__new2(0, dso); 1315439d473bSArnaldo Carvalho de Melo if (kernel_map == NULL) 1316439d473bSArnaldo Carvalho de Melo goto out_delete_dso; 1317439d473bSArnaldo Carvalho de Melo 1318ed52ce2eSArnaldo Carvalho de Melo kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip; 131986470930SIngo Molnar 132000a192b3SArnaldo Carvalho de Melo if (use_modules && dsos__load_modules() < 0) { 13216beba7adSArnaldo Carvalho de Melo pr_warning("Failed to load list of modules in use! " 1322af427bf5SArnaldo Carvalho de Melo "Continuing...\n"); 1323af427bf5SArnaldo Carvalho de Melo use_modules = 0; 1324af427bf5SArnaldo Carvalho de Melo } 1325af427bf5SArnaldo Carvalho de Melo 13266cfcc53eSMike Galbraith if (vmlinux) { 13276beba7adSArnaldo Carvalho de Melo err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter); 1328508c4d08SMike Galbraith if (err > 0 && use_modules) { 13296beba7adSArnaldo Carvalho de Melo int syms = dsos__load_modules_sym(filter); 1330508c4d08SMike Galbraith 1331af427bf5SArnaldo Carvalho de Melo if (syms < 0) 13326beba7adSArnaldo Carvalho de Melo pr_warning("Failed to read module symbols!" 1333af427bf5SArnaldo Carvalho de Melo " Continuing...\n"); 1334af427bf5SArnaldo Carvalho de Melo else 1335508c4d08SMike Galbraith err += syms; 1336508c4d08SMike Galbraith } 13376cfcc53eSMike Galbraith } 133886470930SIngo Molnar 13399974f496SMike Galbraith if (err <= 0) 13406beba7adSArnaldo Carvalho de Melo err = kernel_maps__load_kallsyms(filter, use_modules); 134186470930SIngo Molnar 1342439d473bSArnaldo Carvalho de Melo if (err > 0) { 1343439d473bSArnaldo Carvalho de Melo struct rb_node *node = rb_first(&dso->syms); 1344439d473bSArnaldo Carvalho de Melo struct symbol *sym = rb_entry(node, struct symbol, rb_node); 1345439d473bSArnaldo Carvalho de Melo 1346439d473bSArnaldo Carvalho de Melo kernel_map->start = sym->start; 1347439d473bSArnaldo Carvalho de Melo node = rb_last(&dso->syms); 1348439d473bSArnaldo Carvalho de Melo sym = rb_entry(node, struct symbol, rb_node); 1349439d473bSArnaldo Carvalho de Melo kernel_map->end = sym->end; 1350439d473bSArnaldo Carvalho de Melo 1351439d473bSArnaldo Carvalho de Melo dso->origin = DSO__ORIG_KERNEL; 13522e538c4aSArnaldo Carvalho de Melo kernel_maps__insert(kernel_map); 1353439d473bSArnaldo Carvalho de Melo /* 13542e538c4aSArnaldo Carvalho de Melo * Now that we have all sorted out, just set the ->end of all 13552e538c4aSArnaldo Carvalho de Melo * maps: 1356439d473bSArnaldo Carvalho de Melo */ 13572e538c4aSArnaldo Carvalho de Melo kernel_maps__fixup_end(); 1358439d473bSArnaldo Carvalho de Melo dsos__add(dso); 1359af427bf5SArnaldo Carvalho de Melo 13606beba7adSArnaldo Carvalho de Melo if (verbose) 13616beba7adSArnaldo Carvalho de Melo kernel_maps__fprintf(stderr); 1362439d473bSArnaldo Carvalho de Melo } 136394cb9e38SArnaldo Carvalho de Melo 136486470930SIngo Molnar return err; 1365439d473bSArnaldo Carvalho de Melo 1366439d473bSArnaldo Carvalho de Melo out_delete_dso: 1367439d473bSArnaldo Carvalho de Melo dso__delete(dso); 1368439d473bSArnaldo Carvalho de Melo return -1; 136986470930SIngo Molnar } 137086470930SIngo Molnar 1371cd84c2acSFrederic Weisbecker LIST_HEAD(dsos); 1372cd84c2acSFrederic Weisbecker struct dso *vdso; 1373cd84c2acSFrederic Weisbecker 137483a0944fSIngo Molnar const char *vmlinux_name = "vmlinux"; 1375cd84c2acSFrederic Weisbecker int modules; 1376cd84c2acSFrederic Weisbecker 1377cd84c2acSFrederic Weisbecker static void dsos__add(struct dso *dso) 1378cd84c2acSFrederic Weisbecker { 1379cd84c2acSFrederic Weisbecker list_add_tail(&dso->node, &dsos); 1380cd84c2acSFrederic Weisbecker } 1381cd84c2acSFrederic Weisbecker 1382cd84c2acSFrederic Weisbecker static struct dso *dsos__find(const char *name) 1383cd84c2acSFrederic Weisbecker { 1384cd84c2acSFrederic Weisbecker struct dso *pos; 1385cd84c2acSFrederic Weisbecker 1386cd84c2acSFrederic Weisbecker list_for_each_entry(pos, &dsos, node) 1387cd84c2acSFrederic Weisbecker if (strcmp(pos->name, name) == 0) 1388cd84c2acSFrederic Weisbecker return pos; 1389cd84c2acSFrederic Weisbecker return NULL; 1390cd84c2acSFrederic Weisbecker } 1391cd84c2acSFrederic Weisbecker 139200a192b3SArnaldo Carvalho de Melo struct dso *dsos__findnew(const char *name) 1393cd84c2acSFrederic Weisbecker { 1394cd84c2acSFrederic Weisbecker struct dso *dso = dsos__find(name); 1395cd84c2acSFrederic Weisbecker 1396e4204992SArnaldo Carvalho de Melo if (!dso) { 139700a192b3SArnaldo Carvalho de Melo dso = dso__new(name); 1398cfc10d3bSArnaldo Carvalho de Melo if (dso != NULL) { 1399cd84c2acSFrederic Weisbecker dsos__add(dso); 1400cfc10d3bSArnaldo Carvalho de Melo dso__set_basename(dso); 1401cfc10d3bSArnaldo Carvalho de Melo } 1402e4204992SArnaldo Carvalho de Melo } 1403cd84c2acSFrederic Weisbecker 1404cd84c2acSFrederic Weisbecker return dso; 1405cd84c2acSFrederic Weisbecker } 1406cd84c2acSFrederic Weisbecker 1407cd84c2acSFrederic Weisbecker void dsos__fprintf(FILE *fp) 1408cd84c2acSFrederic Weisbecker { 1409cd84c2acSFrederic Weisbecker struct dso *pos; 1410cd84c2acSFrederic Weisbecker 1411cd84c2acSFrederic Weisbecker list_for_each_entry(pos, &dsos, node) 1412cd84c2acSFrederic Weisbecker dso__fprintf(pos, fp); 1413cd84c2acSFrederic Weisbecker } 1414cd84c2acSFrederic Weisbecker 14159e03eb2dSArnaldo Carvalho de Melo size_t dsos__fprintf_buildid(FILE *fp) 14169e03eb2dSArnaldo Carvalho de Melo { 14179e03eb2dSArnaldo Carvalho de Melo struct dso *pos; 14189e03eb2dSArnaldo Carvalho de Melo size_t ret = 0; 14199e03eb2dSArnaldo Carvalho de Melo 14209e03eb2dSArnaldo Carvalho de Melo list_for_each_entry(pos, &dsos, node) { 14219e03eb2dSArnaldo Carvalho de Melo ret += dso__fprintf_buildid(pos, fp); 14229e03eb2dSArnaldo Carvalho de Melo ret += fprintf(fp, " %s\n", pos->long_name); 14239e03eb2dSArnaldo Carvalho de Melo } 14249e03eb2dSArnaldo Carvalho de Melo return ret; 14259e03eb2dSArnaldo Carvalho de Melo } 14269e03eb2dSArnaldo Carvalho de Melo 142700a192b3SArnaldo Carvalho de Melo int load_kernel(symbol_filter_t filter) 1428cd84c2acSFrederic Weisbecker { 142900a192b3SArnaldo Carvalho de Melo if (dsos__load_kernel(vmlinux_name, filter, modules) <= 0) 1430cd84c2acSFrederic Weisbecker return -1; 1431cd84c2acSFrederic Weisbecker 143200a192b3SArnaldo Carvalho de Melo vdso = dso__new("[vdso]"); 1433cd84c2acSFrederic Weisbecker if (!vdso) 1434cd84c2acSFrederic Weisbecker return -1; 1435cd84c2acSFrederic Weisbecker 1436cd84c2acSFrederic Weisbecker dsos__add(vdso); 1437cd84c2acSFrederic Weisbecker 1438439d473bSArnaldo Carvalho de Melo return 0; 1439cd84c2acSFrederic Weisbecker } 1440cd84c2acSFrederic Weisbecker 144100a192b3SArnaldo Carvalho de Melo void symbol__init(unsigned int priv_size) 144286470930SIngo Molnar { 144386470930SIngo Molnar elf_version(EV_CURRENT); 144400a192b3SArnaldo Carvalho de Melo symbol__priv_size = priv_size; 144586470930SIngo Molnar } 1446