1*86470930SIngo Molnar #include "util.h" 2*86470930SIngo Molnar #include "../perf.h" 3*86470930SIngo Molnar #include "string.h" 4*86470930SIngo Molnar #include "symbol.h" 5*86470930SIngo Molnar 6*86470930SIngo Molnar #include <libelf.h> 7*86470930SIngo Molnar #include <gelf.h> 8*86470930SIngo Molnar #include <elf.h> 9*86470930SIngo Molnar 10*86470930SIngo Molnar const char *sym_hist_filter; 11*86470930SIngo Molnar 12*86470930SIngo Molnar static struct symbol *symbol__new(uint64_t start, uint64_t len, 13*86470930SIngo Molnar const char *name, unsigned int priv_size, 14*86470930SIngo Molnar uint64_t obj_start, int verbose) 15*86470930SIngo Molnar { 16*86470930SIngo Molnar size_t namelen = strlen(name) + 1; 17*86470930SIngo Molnar struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 18*86470930SIngo Molnar 19*86470930SIngo Molnar if (!self) 20*86470930SIngo Molnar return NULL; 21*86470930SIngo Molnar 22*86470930SIngo Molnar if (verbose >= 2) 23*86470930SIngo Molnar printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 24*86470930SIngo Molnar (__u64)start, len, name, self->hist, (void *)obj_start); 25*86470930SIngo Molnar 26*86470930SIngo Molnar self->obj_start= obj_start; 27*86470930SIngo Molnar self->hist = NULL; 28*86470930SIngo Molnar self->hist_sum = 0; 29*86470930SIngo Molnar 30*86470930SIngo Molnar if (sym_hist_filter && !strcmp(name, sym_hist_filter)) 31*86470930SIngo Molnar self->hist = calloc(sizeof(__u64), len); 32*86470930SIngo Molnar 33*86470930SIngo Molnar if (priv_size) { 34*86470930SIngo Molnar memset(self, 0, priv_size); 35*86470930SIngo Molnar self = ((void *)self) + priv_size; 36*86470930SIngo Molnar } 37*86470930SIngo Molnar self->start = start; 38*86470930SIngo Molnar self->end = start + len - 1; 39*86470930SIngo Molnar memcpy(self->name, name, namelen); 40*86470930SIngo Molnar 41*86470930SIngo Molnar return self; 42*86470930SIngo Molnar } 43*86470930SIngo Molnar 44*86470930SIngo Molnar static void symbol__delete(struct symbol *self, unsigned int priv_size) 45*86470930SIngo Molnar { 46*86470930SIngo Molnar free(((void *)self) - priv_size); 47*86470930SIngo Molnar } 48*86470930SIngo Molnar 49*86470930SIngo Molnar static size_t symbol__fprintf(struct symbol *self, FILE *fp) 50*86470930SIngo Molnar { 51*86470930SIngo Molnar return fprintf(fp, " %llx-%llx %s\n", 52*86470930SIngo Molnar self->start, self->end, self->name); 53*86470930SIngo Molnar } 54*86470930SIngo Molnar 55*86470930SIngo Molnar struct dso *dso__new(const char *name, unsigned int sym_priv_size) 56*86470930SIngo Molnar { 57*86470930SIngo Molnar struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 58*86470930SIngo Molnar 59*86470930SIngo Molnar if (self != NULL) { 60*86470930SIngo Molnar strcpy(self->name, name); 61*86470930SIngo Molnar self->syms = RB_ROOT; 62*86470930SIngo Molnar self->sym_priv_size = sym_priv_size; 63*86470930SIngo Molnar self->find_symbol = dso__find_symbol; 64*86470930SIngo Molnar } 65*86470930SIngo Molnar 66*86470930SIngo Molnar return self; 67*86470930SIngo Molnar } 68*86470930SIngo Molnar 69*86470930SIngo Molnar static void dso__delete_symbols(struct dso *self) 70*86470930SIngo Molnar { 71*86470930SIngo Molnar struct symbol *pos; 72*86470930SIngo Molnar struct rb_node *next = rb_first(&self->syms); 73*86470930SIngo Molnar 74*86470930SIngo Molnar while (next) { 75*86470930SIngo Molnar pos = rb_entry(next, struct symbol, rb_node); 76*86470930SIngo Molnar next = rb_next(&pos->rb_node); 77*86470930SIngo Molnar rb_erase(&pos->rb_node, &self->syms); 78*86470930SIngo Molnar symbol__delete(pos, self->sym_priv_size); 79*86470930SIngo Molnar } 80*86470930SIngo Molnar } 81*86470930SIngo Molnar 82*86470930SIngo Molnar void dso__delete(struct dso *self) 83*86470930SIngo Molnar { 84*86470930SIngo Molnar dso__delete_symbols(self); 85*86470930SIngo Molnar free(self); 86*86470930SIngo Molnar } 87*86470930SIngo Molnar 88*86470930SIngo Molnar static void dso__insert_symbol(struct dso *self, struct symbol *sym) 89*86470930SIngo Molnar { 90*86470930SIngo Molnar struct rb_node **p = &self->syms.rb_node; 91*86470930SIngo Molnar struct rb_node *parent = NULL; 92*86470930SIngo Molnar const uint64_t ip = sym->start; 93*86470930SIngo Molnar struct symbol *s; 94*86470930SIngo Molnar 95*86470930SIngo Molnar while (*p != NULL) { 96*86470930SIngo Molnar parent = *p; 97*86470930SIngo Molnar s = rb_entry(parent, struct symbol, rb_node); 98*86470930SIngo Molnar if (ip < s->start) 99*86470930SIngo Molnar p = &(*p)->rb_left; 100*86470930SIngo Molnar else 101*86470930SIngo Molnar p = &(*p)->rb_right; 102*86470930SIngo Molnar } 103*86470930SIngo Molnar rb_link_node(&sym->rb_node, parent, p); 104*86470930SIngo Molnar rb_insert_color(&sym->rb_node, &self->syms); 105*86470930SIngo Molnar } 106*86470930SIngo Molnar 107*86470930SIngo Molnar struct symbol *dso__find_symbol(struct dso *self, uint64_t ip) 108*86470930SIngo Molnar { 109*86470930SIngo Molnar struct rb_node *n; 110*86470930SIngo Molnar 111*86470930SIngo Molnar if (self == NULL) 112*86470930SIngo Molnar return NULL; 113*86470930SIngo Molnar 114*86470930SIngo Molnar n = self->syms.rb_node; 115*86470930SIngo Molnar 116*86470930SIngo Molnar while (n) { 117*86470930SIngo Molnar struct symbol *s = rb_entry(n, struct symbol, rb_node); 118*86470930SIngo Molnar 119*86470930SIngo Molnar if (ip < s->start) 120*86470930SIngo Molnar n = n->rb_left; 121*86470930SIngo Molnar else if (ip > s->end) 122*86470930SIngo Molnar n = n->rb_right; 123*86470930SIngo Molnar else 124*86470930SIngo Molnar return s; 125*86470930SIngo Molnar } 126*86470930SIngo Molnar 127*86470930SIngo Molnar return NULL; 128*86470930SIngo Molnar } 129*86470930SIngo Molnar 130*86470930SIngo Molnar size_t dso__fprintf(struct dso *self, FILE *fp) 131*86470930SIngo Molnar { 132*86470930SIngo Molnar size_t ret = fprintf(fp, "dso: %s\n", self->name); 133*86470930SIngo Molnar 134*86470930SIngo Molnar struct rb_node *nd; 135*86470930SIngo Molnar for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 136*86470930SIngo Molnar struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 137*86470930SIngo Molnar ret += symbol__fprintf(pos, fp); 138*86470930SIngo Molnar } 139*86470930SIngo Molnar 140*86470930SIngo Molnar return ret; 141*86470930SIngo Molnar } 142*86470930SIngo Molnar 143*86470930SIngo Molnar static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) 144*86470930SIngo Molnar { 145*86470930SIngo Molnar struct rb_node *nd, *prevnd; 146*86470930SIngo Molnar char *line = NULL; 147*86470930SIngo Molnar size_t n; 148*86470930SIngo Molnar FILE *file = fopen("/proc/kallsyms", "r"); 149*86470930SIngo Molnar 150*86470930SIngo Molnar if (file == NULL) 151*86470930SIngo Molnar goto out_failure; 152*86470930SIngo Molnar 153*86470930SIngo Molnar while (!feof(file)) { 154*86470930SIngo Molnar __u64 start; 155*86470930SIngo Molnar struct symbol *sym; 156*86470930SIngo Molnar int line_len, len; 157*86470930SIngo Molnar char symbol_type; 158*86470930SIngo Molnar 159*86470930SIngo Molnar line_len = getline(&line, &n, file); 160*86470930SIngo Molnar if (line_len < 0) 161*86470930SIngo Molnar break; 162*86470930SIngo Molnar 163*86470930SIngo Molnar if (!line) 164*86470930SIngo Molnar goto out_failure; 165*86470930SIngo Molnar 166*86470930SIngo Molnar line[--line_len] = '\0'; /* \n */ 167*86470930SIngo Molnar 168*86470930SIngo Molnar len = hex2u64(line, &start); 169*86470930SIngo Molnar 170*86470930SIngo Molnar len++; 171*86470930SIngo Molnar if (len + 2 >= line_len) 172*86470930SIngo Molnar continue; 173*86470930SIngo Molnar 174*86470930SIngo Molnar symbol_type = toupper(line[len]); 175*86470930SIngo Molnar /* 176*86470930SIngo Molnar * We're interested only in code ('T'ext) 177*86470930SIngo Molnar */ 178*86470930SIngo Molnar if (symbol_type != 'T' && symbol_type != 'W') 179*86470930SIngo Molnar continue; 180*86470930SIngo Molnar /* 181*86470930SIngo Molnar * Well fix up the end later, when we have all sorted. 182*86470930SIngo Molnar */ 183*86470930SIngo Molnar sym = symbol__new(start, 0xdead, line + len + 2, 184*86470930SIngo Molnar self->sym_priv_size, 0, verbose); 185*86470930SIngo Molnar 186*86470930SIngo Molnar if (sym == NULL) 187*86470930SIngo Molnar goto out_delete_line; 188*86470930SIngo Molnar 189*86470930SIngo Molnar if (filter && filter(self, sym)) 190*86470930SIngo Molnar symbol__delete(sym, self->sym_priv_size); 191*86470930SIngo Molnar else 192*86470930SIngo Molnar dso__insert_symbol(self, sym); 193*86470930SIngo Molnar } 194*86470930SIngo Molnar 195*86470930SIngo Molnar /* 196*86470930SIngo Molnar * Now that we have all sorted out, just set the ->end of all 197*86470930SIngo Molnar * symbols 198*86470930SIngo Molnar */ 199*86470930SIngo Molnar prevnd = rb_first(&self->syms); 200*86470930SIngo Molnar 201*86470930SIngo Molnar if (prevnd == NULL) 202*86470930SIngo Molnar goto out_delete_line; 203*86470930SIngo Molnar 204*86470930SIngo Molnar for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 205*86470930SIngo Molnar struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node), 206*86470930SIngo Molnar *curr = rb_entry(nd, struct symbol, rb_node); 207*86470930SIngo Molnar 208*86470930SIngo Molnar prev->end = curr->start - 1; 209*86470930SIngo Molnar prevnd = nd; 210*86470930SIngo Molnar } 211*86470930SIngo Molnar 212*86470930SIngo Molnar free(line); 213*86470930SIngo Molnar fclose(file); 214*86470930SIngo Molnar 215*86470930SIngo Molnar return 0; 216*86470930SIngo Molnar 217*86470930SIngo Molnar out_delete_line: 218*86470930SIngo Molnar free(line); 219*86470930SIngo Molnar out_failure: 220*86470930SIngo Molnar return -1; 221*86470930SIngo Molnar } 222*86470930SIngo Molnar 223*86470930SIngo Molnar /** 224*86470930SIngo Molnar * elf_symtab__for_each_symbol - iterate thru all the symbols 225*86470930SIngo Molnar * 226*86470930SIngo Molnar * @self: struct elf_symtab instance to iterate 227*86470930SIngo Molnar * @index: uint32_t index 228*86470930SIngo Molnar * @sym: GElf_Sym iterator 229*86470930SIngo Molnar */ 230*86470930SIngo Molnar #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \ 231*86470930SIngo Molnar for (index = 0, gelf_getsym(syms, index, &sym);\ 232*86470930SIngo Molnar index < nr_syms; \ 233*86470930SIngo Molnar index++, gelf_getsym(syms, index, &sym)) 234*86470930SIngo Molnar 235*86470930SIngo Molnar static inline uint8_t elf_sym__type(const GElf_Sym *sym) 236*86470930SIngo Molnar { 237*86470930SIngo Molnar return GELF_ST_TYPE(sym->st_info); 238*86470930SIngo Molnar } 239*86470930SIngo Molnar 240*86470930SIngo Molnar static inline int elf_sym__is_function(const GElf_Sym *sym) 241*86470930SIngo Molnar { 242*86470930SIngo Molnar return elf_sym__type(sym) == STT_FUNC && 243*86470930SIngo Molnar sym->st_name != 0 && 244*86470930SIngo Molnar sym->st_shndx != SHN_UNDEF && 245*86470930SIngo Molnar sym->st_size != 0; 246*86470930SIngo Molnar } 247*86470930SIngo Molnar 248*86470930SIngo Molnar static inline const char *elf_sym__name(const GElf_Sym *sym, 249*86470930SIngo Molnar const Elf_Data *symstrs) 250*86470930SIngo Molnar { 251*86470930SIngo Molnar return symstrs->d_buf + sym->st_name; 252*86470930SIngo Molnar } 253*86470930SIngo Molnar 254*86470930SIngo Molnar static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 255*86470930SIngo Molnar GElf_Shdr *shp, const char *name, 256*86470930SIngo Molnar size_t *index) 257*86470930SIngo Molnar { 258*86470930SIngo Molnar Elf_Scn *sec = NULL; 259*86470930SIngo Molnar size_t cnt = 1; 260*86470930SIngo Molnar 261*86470930SIngo Molnar while ((sec = elf_nextscn(elf, sec)) != NULL) { 262*86470930SIngo Molnar char *str; 263*86470930SIngo Molnar 264*86470930SIngo Molnar gelf_getshdr(sec, shp); 265*86470930SIngo Molnar str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 266*86470930SIngo Molnar if (!strcmp(name, str)) { 267*86470930SIngo Molnar if (index) 268*86470930SIngo Molnar *index = cnt; 269*86470930SIngo Molnar break; 270*86470930SIngo Molnar } 271*86470930SIngo Molnar ++cnt; 272*86470930SIngo Molnar } 273*86470930SIngo Molnar 274*86470930SIngo Molnar return sec; 275*86470930SIngo Molnar } 276*86470930SIngo Molnar 277*86470930SIngo Molnar #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 278*86470930SIngo Molnar for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 279*86470930SIngo Molnar idx < nr_entries; \ 280*86470930SIngo Molnar ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) 281*86470930SIngo Molnar 282*86470930SIngo Molnar #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ 283*86470930SIngo Molnar for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ 284*86470930SIngo Molnar idx < nr_entries; \ 285*86470930SIngo Molnar ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 286*86470930SIngo Molnar 287*86470930SIngo Molnar static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 288*86470930SIngo Molnar GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 289*86470930SIngo Molnar GElf_Shdr *shdr_dynsym, 290*86470930SIngo Molnar size_t dynsym_idx, int verbose) 291*86470930SIngo Molnar { 292*86470930SIngo Molnar uint32_t nr_rel_entries, idx; 293*86470930SIngo Molnar GElf_Sym sym; 294*86470930SIngo Molnar __u64 plt_offset; 295*86470930SIngo Molnar GElf_Shdr shdr_plt; 296*86470930SIngo Molnar struct symbol *f; 297*86470930SIngo Molnar GElf_Shdr shdr_rel_plt; 298*86470930SIngo Molnar Elf_Data *reldata, *syms, *symstrs; 299*86470930SIngo Molnar Elf_Scn *scn_plt_rel, *scn_symstrs; 300*86470930SIngo Molnar char sympltname[1024]; 301*86470930SIngo Molnar int nr = 0, symidx; 302*86470930SIngo Molnar 303*86470930SIngo Molnar scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 304*86470930SIngo Molnar ".rela.plt", NULL); 305*86470930SIngo Molnar if (scn_plt_rel == NULL) { 306*86470930SIngo Molnar scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 307*86470930SIngo Molnar ".rel.plt", NULL); 308*86470930SIngo Molnar if (scn_plt_rel == NULL) 309*86470930SIngo Molnar return 0; 310*86470930SIngo Molnar } 311*86470930SIngo Molnar 312*86470930SIngo Molnar if (shdr_rel_plt.sh_link != dynsym_idx) 313*86470930SIngo Molnar return 0; 314*86470930SIngo Molnar 315*86470930SIngo Molnar if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 316*86470930SIngo Molnar return 0; 317*86470930SIngo Molnar 318*86470930SIngo Molnar /* 319*86470930SIngo Molnar * Fetch the relocation section to find the indexes to the GOT 320*86470930SIngo Molnar * and the symbols in the .dynsym they refer to. 321*86470930SIngo Molnar */ 322*86470930SIngo Molnar reldata = elf_getdata(scn_plt_rel, NULL); 323*86470930SIngo Molnar if (reldata == NULL) 324*86470930SIngo Molnar return -1; 325*86470930SIngo Molnar 326*86470930SIngo Molnar syms = elf_getdata(scn_dynsym, NULL); 327*86470930SIngo Molnar if (syms == NULL) 328*86470930SIngo Molnar return -1; 329*86470930SIngo Molnar 330*86470930SIngo Molnar scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 331*86470930SIngo Molnar if (scn_symstrs == NULL) 332*86470930SIngo Molnar return -1; 333*86470930SIngo Molnar 334*86470930SIngo Molnar symstrs = elf_getdata(scn_symstrs, NULL); 335*86470930SIngo Molnar if (symstrs == NULL) 336*86470930SIngo Molnar return -1; 337*86470930SIngo Molnar 338*86470930SIngo Molnar nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 339*86470930SIngo Molnar plt_offset = shdr_plt.sh_offset; 340*86470930SIngo Molnar 341*86470930SIngo Molnar if (shdr_rel_plt.sh_type == SHT_RELA) { 342*86470930SIngo Molnar GElf_Rela pos_mem, *pos; 343*86470930SIngo Molnar 344*86470930SIngo Molnar elf_section__for_each_rela(reldata, pos, pos_mem, idx, 345*86470930SIngo Molnar nr_rel_entries) { 346*86470930SIngo Molnar symidx = GELF_R_SYM(pos->r_info); 347*86470930SIngo Molnar plt_offset += shdr_plt.sh_entsize; 348*86470930SIngo Molnar gelf_getsym(syms, symidx, &sym); 349*86470930SIngo Molnar snprintf(sympltname, sizeof(sympltname), 350*86470930SIngo Molnar "%s@plt", elf_sym__name(&sym, symstrs)); 351*86470930SIngo Molnar 352*86470930SIngo Molnar f = symbol__new(plt_offset, shdr_plt.sh_entsize, 353*86470930SIngo Molnar sympltname, self->sym_priv_size, 0, verbose); 354*86470930SIngo Molnar if (!f) 355*86470930SIngo Molnar return -1; 356*86470930SIngo Molnar 357*86470930SIngo Molnar dso__insert_symbol(self, f); 358*86470930SIngo Molnar ++nr; 359*86470930SIngo Molnar } 360*86470930SIngo Molnar } else if (shdr_rel_plt.sh_type == SHT_REL) { 361*86470930SIngo Molnar GElf_Rel pos_mem, *pos; 362*86470930SIngo Molnar elf_section__for_each_rel(reldata, pos, pos_mem, idx, 363*86470930SIngo Molnar nr_rel_entries) { 364*86470930SIngo Molnar symidx = GELF_R_SYM(pos->r_info); 365*86470930SIngo Molnar plt_offset += shdr_plt.sh_entsize; 366*86470930SIngo Molnar gelf_getsym(syms, symidx, &sym); 367*86470930SIngo Molnar snprintf(sympltname, sizeof(sympltname), 368*86470930SIngo Molnar "%s@plt", elf_sym__name(&sym, symstrs)); 369*86470930SIngo Molnar 370*86470930SIngo Molnar f = symbol__new(plt_offset, shdr_plt.sh_entsize, 371*86470930SIngo Molnar sympltname, self->sym_priv_size, 0, verbose); 372*86470930SIngo Molnar if (!f) 373*86470930SIngo Molnar return -1; 374*86470930SIngo Molnar 375*86470930SIngo Molnar dso__insert_symbol(self, f); 376*86470930SIngo Molnar ++nr; 377*86470930SIngo Molnar } 378*86470930SIngo Molnar } else { 379*86470930SIngo Molnar /* 380*86470930SIngo Molnar * TODO: There are still one more shdr_rel_plt.sh_type 381*86470930SIngo Molnar * I have to investigate, but probably should be ignored. 382*86470930SIngo Molnar */ 383*86470930SIngo Molnar } 384*86470930SIngo Molnar 385*86470930SIngo Molnar return nr; 386*86470930SIngo Molnar } 387*86470930SIngo Molnar 388*86470930SIngo Molnar static int dso__load_sym(struct dso *self, int fd, const char *name, 389*86470930SIngo Molnar symbol_filter_t filter, int verbose) 390*86470930SIngo Molnar { 391*86470930SIngo Molnar Elf_Data *symstrs; 392*86470930SIngo Molnar uint32_t nr_syms; 393*86470930SIngo Molnar int err = -1; 394*86470930SIngo Molnar uint32_t index; 395*86470930SIngo Molnar GElf_Ehdr ehdr; 396*86470930SIngo Molnar GElf_Shdr shdr; 397*86470930SIngo Molnar Elf_Data *syms; 398*86470930SIngo Molnar GElf_Sym sym; 399*86470930SIngo Molnar Elf_Scn *sec, *sec_dynsym; 400*86470930SIngo Molnar Elf *elf; 401*86470930SIngo Molnar size_t dynsym_idx; 402*86470930SIngo Molnar int nr = 0; 403*86470930SIngo Molnar 404*86470930SIngo Molnar elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 405*86470930SIngo Molnar if (elf == NULL) { 406*86470930SIngo Molnar if (verbose) 407*86470930SIngo Molnar fprintf(stderr, "%s: cannot read %s ELF file.\n", 408*86470930SIngo Molnar __func__, name); 409*86470930SIngo Molnar goto out_close; 410*86470930SIngo Molnar } 411*86470930SIngo Molnar 412*86470930SIngo Molnar if (gelf_getehdr(elf, &ehdr) == NULL) { 413*86470930SIngo Molnar if (verbose) 414*86470930SIngo Molnar fprintf(stderr, "%s: cannot get elf header.\n", __func__); 415*86470930SIngo Molnar goto out_elf_end; 416*86470930SIngo Molnar } 417*86470930SIngo Molnar 418*86470930SIngo Molnar /* 419*86470930SIngo Molnar * We need to check if we have a .dynsym, so that we can handle the 420*86470930SIngo Molnar * .plt, synthesizing its symbols, that aren't on the symtabs (be it 421*86470930SIngo Molnar * .dynsym or .symtab) 422*86470930SIngo Molnar */ 423*86470930SIngo Molnar sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr, 424*86470930SIngo Molnar ".dynsym", &dynsym_idx); 425*86470930SIngo Molnar if (sec_dynsym != NULL) { 426*86470930SIngo Molnar nr = dso__synthesize_plt_symbols(self, elf, &ehdr, 427*86470930SIngo Molnar sec_dynsym, &shdr, 428*86470930SIngo Molnar dynsym_idx, verbose); 429*86470930SIngo Molnar if (nr < 0) 430*86470930SIngo Molnar goto out_elf_end; 431*86470930SIngo Molnar } 432*86470930SIngo Molnar 433*86470930SIngo Molnar /* 434*86470930SIngo Molnar * But if we have a full .symtab (that is a superset of .dynsym) we 435*86470930SIngo Molnar * should add the symbols not in the .dynsyn 436*86470930SIngo Molnar */ 437*86470930SIngo Molnar sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 438*86470930SIngo Molnar if (sec == NULL) { 439*86470930SIngo Molnar if (sec_dynsym == NULL) 440*86470930SIngo Molnar goto out_elf_end; 441*86470930SIngo Molnar 442*86470930SIngo Molnar sec = sec_dynsym; 443*86470930SIngo Molnar gelf_getshdr(sec, &shdr); 444*86470930SIngo Molnar } 445*86470930SIngo Molnar 446*86470930SIngo Molnar syms = elf_getdata(sec, NULL); 447*86470930SIngo Molnar if (syms == NULL) 448*86470930SIngo Molnar goto out_elf_end; 449*86470930SIngo Molnar 450*86470930SIngo Molnar sec = elf_getscn(elf, shdr.sh_link); 451*86470930SIngo Molnar if (sec == NULL) 452*86470930SIngo Molnar goto out_elf_end; 453*86470930SIngo Molnar 454*86470930SIngo Molnar symstrs = elf_getdata(sec, NULL); 455*86470930SIngo Molnar if (symstrs == NULL) 456*86470930SIngo Molnar goto out_elf_end; 457*86470930SIngo Molnar 458*86470930SIngo Molnar nr_syms = shdr.sh_size / shdr.sh_entsize; 459*86470930SIngo Molnar 460*86470930SIngo Molnar elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 461*86470930SIngo Molnar struct symbol *f; 462*86470930SIngo Molnar uint64_t obj_start; 463*86470930SIngo Molnar 464*86470930SIngo Molnar if (!elf_sym__is_function(&sym)) 465*86470930SIngo Molnar continue; 466*86470930SIngo Molnar 467*86470930SIngo Molnar sec = elf_getscn(elf, sym.st_shndx); 468*86470930SIngo Molnar if (!sec) 469*86470930SIngo Molnar goto out_elf_end; 470*86470930SIngo Molnar 471*86470930SIngo Molnar gelf_getshdr(sec, &shdr); 472*86470930SIngo Molnar obj_start = sym.st_value; 473*86470930SIngo Molnar 474*86470930SIngo Molnar sym.st_value -= shdr.sh_addr - shdr.sh_offset; 475*86470930SIngo Molnar 476*86470930SIngo Molnar f = symbol__new(sym.st_value, sym.st_size, 477*86470930SIngo Molnar elf_sym__name(&sym, symstrs), 478*86470930SIngo Molnar self->sym_priv_size, obj_start, verbose); 479*86470930SIngo Molnar if (!f) 480*86470930SIngo Molnar goto out_elf_end; 481*86470930SIngo Molnar 482*86470930SIngo Molnar if (filter && filter(self, f)) 483*86470930SIngo Molnar symbol__delete(f, self->sym_priv_size); 484*86470930SIngo Molnar else { 485*86470930SIngo Molnar dso__insert_symbol(self, f); 486*86470930SIngo Molnar nr++; 487*86470930SIngo Molnar } 488*86470930SIngo Molnar } 489*86470930SIngo Molnar 490*86470930SIngo Molnar err = nr; 491*86470930SIngo Molnar out_elf_end: 492*86470930SIngo Molnar elf_end(elf); 493*86470930SIngo Molnar out_close: 494*86470930SIngo Molnar return err; 495*86470930SIngo Molnar } 496*86470930SIngo Molnar 497*86470930SIngo Molnar int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 498*86470930SIngo Molnar { 499*86470930SIngo Molnar int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 500*86470930SIngo Molnar char *name = malloc(size); 501*86470930SIngo Molnar int variant = 0; 502*86470930SIngo Molnar int ret = -1; 503*86470930SIngo Molnar int fd; 504*86470930SIngo Molnar 505*86470930SIngo Molnar if (!name) 506*86470930SIngo Molnar return -1; 507*86470930SIngo Molnar 508*86470930SIngo Molnar more: 509*86470930SIngo Molnar do { 510*86470930SIngo Molnar switch (variant) { 511*86470930SIngo Molnar case 0: /* Fedora */ 512*86470930SIngo Molnar snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 513*86470930SIngo Molnar break; 514*86470930SIngo Molnar case 1: /* Ubuntu */ 515*86470930SIngo Molnar snprintf(name, size, "/usr/lib/debug%s", self->name); 516*86470930SIngo Molnar break; 517*86470930SIngo Molnar case 2: /* Sane people */ 518*86470930SIngo Molnar snprintf(name, size, "%s", self->name); 519*86470930SIngo Molnar break; 520*86470930SIngo Molnar 521*86470930SIngo Molnar default: 522*86470930SIngo Molnar goto out; 523*86470930SIngo Molnar } 524*86470930SIngo Molnar variant++; 525*86470930SIngo Molnar 526*86470930SIngo Molnar fd = open(name, O_RDONLY); 527*86470930SIngo Molnar } while (fd < 0); 528*86470930SIngo Molnar 529*86470930SIngo Molnar ret = dso__load_sym(self, fd, name, filter, verbose); 530*86470930SIngo Molnar close(fd); 531*86470930SIngo Molnar 532*86470930SIngo Molnar /* 533*86470930SIngo Molnar * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 534*86470930SIngo Molnar */ 535*86470930SIngo Molnar if (!ret) 536*86470930SIngo Molnar goto more; 537*86470930SIngo Molnar 538*86470930SIngo Molnar out: 539*86470930SIngo Molnar free(name); 540*86470930SIngo Molnar return ret; 541*86470930SIngo Molnar } 542*86470930SIngo Molnar 543*86470930SIngo Molnar static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 544*86470930SIngo Molnar symbol_filter_t filter, int verbose) 545*86470930SIngo Molnar { 546*86470930SIngo Molnar int err, fd = open(vmlinux, O_RDONLY); 547*86470930SIngo Molnar 548*86470930SIngo Molnar if (fd < 0) 549*86470930SIngo Molnar return -1; 550*86470930SIngo Molnar 551*86470930SIngo Molnar err = dso__load_sym(self, fd, vmlinux, filter, verbose); 552*86470930SIngo Molnar close(fd); 553*86470930SIngo Molnar 554*86470930SIngo Molnar return err; 555*86470930SIngo Molnar } 556*86470930SIngo Molnar 557*86470930SIngo Molnar int dso__load_kernel(struct dso *self, const char *vmlinux, 558*86470930SIngo Molnar symbol_filter_t filter, int verbose) 559*86470930SIngo Molnar { 560*86470930SIngo Molnar int err = -1; 561*86470930SIngo Molnar 562*86470930SIngo Molnar if (vmlinux) 563*86470930SIngo Molnar err = dso__load_vmlinux(self, vmlinux, filter, verbose); 564*86470930SIngo Molnar 565*86470930SIngo Molnar if (err) 566*86470930SIngo Molnar err = dso__load_kallsyms(self, filter, verbose); 567*86470930SIngo Molnar 568*86470930SIngo Molnar return err; 569*86470930SIngo Molnar } 570*86470930SIngo Molnar 571*86470930SIngo Molnar void symbol__init(void) 572*86470930SIngo Molnar { 573*86470930SIngo Molnar elf_version(EV_CURRENT); 574*86470930SIngo Molnar } 575