1 #include "util.h" 2 #include "../perf.h" 3 #include "string.h" 4 #include "symbol.h" 5 6 #include <libelf.h> 7 #include <gelf.h> 8 #include <elf.h> 9 10 const char *sym_hist_filter; 11 12 static struct symbol *symbol__new(u64 start, u64 len, 13 const char *name, unsigned int priv_size, 14 u64 obj_start, int verbose) 15 { 16 size_t namelen = strlen(name) + 1; 17 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 18 19 if (!self) 20 return NULL; 21 22 if (verbose >= 2) 23 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 24 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 25 26 self->obj_start= obj_start; 27 self->hist = NULL; 28 self->hist_sum = 0; 29 30 if (sym_hist_filter && !strcmp(name, sym_hist_filter)) 31 self->hist = calloc(sizeof(u64), len); 32 33 if (priv_size) { 34 memset(self, 0, priv_size); 35 self = ((void *)self) + priv_size; 36 } 37 self->start = start; 38 self->end = len ? start + len - 1 : start; 39 memcpy(self->name, name, namelen); 40 41 return self; 42 } 43 44 static void symbol__delete(struct symbol *self, unsigned int priv_size) 45 { 46 free(((void *)self) - priv_size); 47 } 48 49 static size_t symbol__fprintf(struct symbol *self, FILE *fp) 50 { 51 if (!self->module) 52 return fprintf(fp, " %llx-%llx %s\n", 53 self->start, self->end, self->name); 54 else 55 return fprintf(fp, " %llx-%llx %s \t[%s]\n", 56 self->start, self->end, self->name, self->module->name); 57 } 58 59 struct dso *dso__new(const char *name, unsigned int sym_priv_size) 60 { 61 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 62 63 if (self != NULL) { 64 strcpy(self->name, name); 65 self->syms = RB_ROOT; 66 self->sym_priv_size = sym_priv_size; 67 self->find_symbol = dso__find_symbol; 68 } 69 70 return self; 71 } 72 73 static void dso__delete_symbols(struct dso *self) 74 { 75 struct symbol *pos; 76 struct rb_node *next = rb_first(&self->syms); 77 78 while (next) { 79 pos = rb_entry(next, struct symbol, rb_node); 80 next = rb_next(&pos->rb_node); 81 rb_erase(&pos->rb_node, &self->syms); 82 symbol__delete(pos, self->sym_priv_size); 83 } 84 } 85 86 void dso__delete(struct dso *self) 87 { 88 dso__delete_symbols(self); 89 free(self); 90 } 91 92 static void dso__insert_symbol(struct dso *self, struct symbol *sym) 93 { 94 struct rb_node **p = &self->syms.rb_node; 95 struct rb_node *parent = NULL; 96 const u64 ip = sym->start; 97 struct symbol *s; 98 99 while (*p != NULL) { 100 parent = *p; 101 s = rb_entry(parent, struct symbol, rb_node); 102 if (ip < s->start) 103 p = &(*p)->rb_left; 104 else 105 p = &(*p)->rb_right; 106 } 107 rb_link_node(&sym->rb_node, parent, p); 108 rb_insert_color(&sym->rb_node, &self->syms); 109 } 110 111 struct symbol *dso__find_symbol(struct dso *self, u64 ip) 112 { 113 struct rb_node *n; 114 115 if (self == NULL) 116 return NULL; 117 118 n = self->syms.rb_node; 119 120 while (n) { 121 struct symbol *s = rb_entry(n, struct symbol, rb_node); 122 123 if (ip < s->start) 124 n = n->rb_left; 125 else if (ip > s->end) 126 n = n->rb_right; 127 else 128 return s; 129 } 130 131 return NULL; 132 } 133 134 size_t dso__fprintf(struct dso *self, FILE *fp) 135 { 136 size_t ret = fprintf(fp, "dso: %s\n", self->name); 137 138 struct rb_node *nd; 139 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 140 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 141 ret += symbol__fprintf(pos, fp); 142 } 143 144 return ret; 145 } 146 147 static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) 148 { 149 struct rb_node *nd, *prevnd; 150 char *line = NULL; 151 size_t n; 152 FILE *file = fopen("/proc/kallsyms", "r"); 153 int count = 0; 154 155 if (file == NULL) 156 goto out_failure; 157 158 while (!feof(file)) { 159 u64 start; 160 struct symbol *sym; 161 int line_len, len; 162 char symbol_type; 163 164 line_len = getline(&line, &n, file); 165 if (line_len < 0) 166 break; 167 168 if (!line) 169 goto out_failure; 170 171 line[--line_len] = '\0'; /* \n */ 172 173 len = hex2u64(line, &start); 174 175 len++; 176 if (len + 2 >= line_len) 177 continue; 178 179 symbol_type = toupper(line[len]); 180 /* 181 * We're interested only in code ('T'ext) 182 */ 183 if (symbol_type != 'T' && symbol_type != 'W') 184 continue; 185 /* 186 * Well fix up the end later, when we have all sorted. 187 */ 188 sym = symbol__new(start, 0xdead, line + len + 2, 189 self->sym_priv_size, 0, verbose); 190 191 if (sym == NULL) 192 goto out_delete_line; 193 194 if (filter && filter(self, sym)) 195 symbol__delete(sym, self->sym_priv_size); 196 else { 197 dso__insert_symbol(self, sym); 198 count++; 199 } 200 } 201 202 /* 203 * Now that we have all sorted out, just set the ->end of all 204 * symbols 205 */ 206 prevnd = rb_first(&self->syms); 207 208 if (prevnd == NULL) 209 goto out_delete_line; 210 211 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 212 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node), 213 *curr = rb_entry(nd, struct symbol, rb_node); 214 215 prev->end = curr->start - 1; 216 prevnd = nd; 217 } 218 219 free(line); 220 fclose(file); 221 222 return count; 223 224 out_delete_line: 225 free(line); 226 out_failure: 227 return -1; 228 } 229 230 static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) 231 { 232 char *line = NULL; 233 size_t n; 234 FILE *file; 235 int nr_syms = 0; 236 237 file = fopen(self->name, "r"); 238 if (file == NULL) 239 goto out_failure; 240 241 while (!feof(file)) { 242 u64 start, size; 243 struct symbol *sym; 244 int line_len, len; 245 246 line_len = getline(&line, &n, file); 247 if (line_len < 0) 248 break; 249 250 if (!line) 251 goto out_failure; 252 253 line[--line_len] = '\0'; /* \n */ 254 255 len = hex2u64(line, &start); 256 257 len++; 258 if (len + 2 >= line_len) 259 continue; 260 261 len += hex2u64(line + len, &size); 262 263 len++; 264 if (len + 2 >= line_len) 265 continue; 266 267 sym = symbol__new(start, size, line + len, 268 self->sym_priv_size, start, verbose); 269 270 if (sym == NULL) 271 goto out_delete_line; 272 273 if (filter && filter(self, sym)) 274 symbol__delete(sym, self->sym_priv_size); 275 else { 276 dso__insert_symbol(self, sym); 277 nr_syms++; 278 } 279 } 280 281 free(line); 282 fclose(file); 283 284 return nr_syms; 285 286 out_delete_line: 287 free(line); 288 out_failure: 289 return -1; 290 } 291 292 /** 293 * elf_symtab__for_each_symbol - iterate thru all the symbols 294 * 295 * @self: struct elf_symtab instance to iterate 296 * @index: uint32_t index 297 * @sym: GElf_Sym iterator 298 */ 299 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \ 300 for (index = 0, gelf_getsym(syms, index, &sym);\ 301 index < nr_syms; \ 302 index++, gelf_getsym(syms, index, &sym)) 303 304 static inline uint8_t elf_sym__type(const GElf_Sym *sym) 305 { 306 return GELF_ST_TYPE(sym->st_info); 307 } 308 309 static inline int elf_sym__is_function(const GElf_Sym *sym) 310 { 311 return elf_sym__type(sym) == STT_FUNC && 312 sym->st_name != 0 && 313 sym->st_shndx != SHN_UNDEF && 314 sym->st_size != 0; 315 } 316 317 static inline int elf_sym__is_label(const GElf_Sym *sym) 318 { 319 return elf_sym__type(sym) == STT_NOTYPE && 320 sym->st_name != 0 && 321 sym->st_shndx != SHN_UNDEF && 322 sym->st_shndx != SHN_ABS; 323 } 324 325 static inline const char *elf_sec__name(const GElf_Shdr *shdr, 326 const Elf_Data *secstrs) 327 { 328 return secstrs->d_buf + shdr->sh_name; 329 } 330 331 static inline int elf_sec__is_text(const GElf_Shdr *shdr, 332 const Elf_Data *secstrs) 333 { 334 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; 335 } 336 337 static inline const char *elf_sym__name(const GElf_Sym *sym, 338 const Elf_Data *symstrs) 339 { 340 return symstrs->d_buf + sym->st_name; 341 } 342 343 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 344 GElf_Shdr *shp, const char *name, 345 size_t *index) 346 { 347 Elf_Scn *sec = NULL; 348 size_t cnt = 1; 349 350 while ((sec = elf_nextscn(elf, sec)) != NULL) { 351 char *str; 352 353 gelf_getshdr(sec, shp); 354 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 355 if (!strcmp(name, str)) { 356 if (index) 357 *index = cnt; 358 break; 359 } 360 ++cnt; 361 } 362 363 return sec; 364 } 365 366 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 367 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 368 idx < nr_entries; \ 369 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) 370 371 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ 372 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ 373 idx < nr_entries; \ 374 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 375 376 static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 377 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 378 GElf_Shdr *shdr_dynsym, 379 size_t dynsym_idx, int verbose) 380 { 381 uint32_t nr_rel_entries, idx; 382 GElf_Sym sym; 383 u64 plt_offset; 384 GElf_Shdr shdr_plt; 385 struct symbol *f; 386 GElf_Shdr shdr_rel_plt; 387 Elf_Data *reldata, *syms, *symstrs; 388 Elf_Scn *scn_plt_rel, *scn_symstrs; 389 char sympltname[1024]; 390 int nr = 0, symidx; 391 392 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 393 ".rela.plt", NULL); 394 if (scn_plt_rel == NULL) { 395 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 396 ".rel.plt", NULL); 397 if (scn_plt_rel == NULL) 398 return 0; 399 } 400 401 if (shdr_rel_plt.sh_link != dynsym_idx) 402 return 0; 403 404 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 405 return 0; 406 407 /* 408 * Fetch the relocation section to find the indexes to the GOT 409 * and the symbols in the .dynsym they refer to. 410 */ 411 reldata = elf_getdata(scn_plt_rel, NULL); 412 if (reldata == NULL) 413 return -1; 414 415 syms = elf_getdata(scn_dynsym, NULL); 416 if (syms == NULL) 417 return -1; 418 419 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 420 if (scn_symstrs == NULL) 421 return -1; 422 423 symstrs = elf_getdata(scn_symstrs, NULL); 424 if (symstrs == NULL) 425 return -1; 426 427 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 428 plt_offset = shdr_plt.sh_offset; 429 430 if (shdr_rel_plt.sh_type == SHT_RELA) { 431 GElf_Rela pos_mem, *pos; 432 433 elf_section__for_each_rela(reldata, pos, pos_mem, idx, 434 nr_rel_entries) { 435 symidx = GELF_R_SYM(pos->r_info); 436 plt_offset += shdr_plt.sh_entsize; 437 gelf_getsym(syms, symidx, &sym); 438 snprintf(sympltname, sizeof(sympltname), 439 "%s@plt", elf_sym__name(&sym, symstrs)); 440 441 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 442 sympltname, self->sym_priv_size, 0, verbose); 443 if (!f) 444 return -1; 445 446 dso__insert_symbol(self, f); 447 ++nr; 448 } 449 } else if (shdr_rel_plt.sh_type == SHT_REL) { 450 GElf_Rel pos_mem, *pos; 451 elf_section__for_each_rel(reldata, pos, pos_mem, idx, 452 nr_rel_entries) { 453 symidx = GELF_R_SYM(pos->r_info); 454 plt_offset += shdr_plt.sh_entsize; 455 gelf_getsym(syms, symidx, &sym); 456 snprintf(sympltname, sizeof(sympltname), 457 "%s@plt", elf_sym__name(&sym, symstrs)); 458 459 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 460 sympltname, self->sym_priv_size, 0, verbose); 461 if (!f) 462 return -1; 463 464 dso__insert_symbol(self, f); 465 ++nr; 466 } 467 } else { 468 /* 469 * TODO: There are still one more shdr_rel_plt.sh_type 470 * I have to investigate, but probably should be ignored. 471 */ 472 } 473 474 return nr; 475 } 476 477 static int dso__load_sym(struct dso *self, int fd, const char *name, 478 symbol_filter_t filter, int verbose, struct module *mod) 479 { 480 Elf_Data *symstrs, *secstrs; 481 uint32_t nr_syms; 482 int err = -1; 483 uint32_t index; 484 GElf_Ehdr ehdr; 485 GElf_Shdr shdr; 486 Elf_Data *syms; 487 GElf_Sym sym; 488 Elf_Scn *sec, *sec_dynsym, *sec_strndx; 489 Elf *elf; 490 size_t dynsym_idx; 491 int nr = 0; 492 493 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 494 if (elf == NULL) { 495 if (verbose) 496 fprintf(stderr, "%s: cannot read %s ELF file.\n", 497 __func__, name); 498 goto out_close; 499 } 500 501 if (gelf_getehdr(elf, &ehdr) == NULL) { 502 if (verbose) 503 fprintf(stderr, "%s: cannot get elf header.\n", __func__); 504 goto out_elf_end; 505 } 506 507 /* 508 * We need to check if we have a .dynsym, so that we can handle the 509 * .plt, synthesizing its symbols, that aren't on the symtabs (be it 510 * .dynsym or .symtab) 511 */ 512 sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr, 513 ".dynsym", &dynsym_idx); 514 if (sec_dynsym != NULL) { 515 nr = dso__synthesize_plt_symbols(self, elf, &ehdr, 516 sec_dynsym, &shdr, 517 dynsym_idx, verbose); 518 if (nr < 0) 519 goto out_elf_end; 520 } 521 522 /* 523 * But if we have a full .symtab (that is a superset of .dynsym) we 524 * should add the symbols not in the .dynsyn 525 */ 526 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 527 if (sec == NULL) { 528 if (sec_dynsym == NULL) 529 goto out_elf_end; 530 531 sec = sec_dynsym; 532 gelf_getshdr(sec, &shdr); 533 } 534 535 syms = elf_getdata(sec, NULL); 536 if (syms == NULL) 537 goto out_elf_end; 538 539 sec = elf_getscn(elf, shdr.sh_link); 540 if (sec == NULL) 541 goto out_elf_end; 542 543 symstrs = elf_getdata(sec, NULL); 544 if (symstrs == NULL) 545 goto out_elf_end; 546 547 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 548 if (sec_strndx == NULL) 549 goto out_elf_end; 550 551 secstrs = elf_getdata(sec_strndx, NULL); 552 if (symstrs == NULL) 553 goto out_elf_end; 554 555 nr_syms = shdr.sh_size / shdr.sh_entsize; 556 557 memset(&sym, 0, sizeof(sym)); 558 self->adjust_symbols = (ehdr.e_type == ET_EXEC || 559 elf_section_by_name(elf, &ehdr, &shdr, 560 ".gnu.prelink_undo", 561 NULL) != NULL); 562 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 563 struct symbol *f; 564 u64 obj_start; 565 struct section *section = NULL; 566 int is_label = elf_sym__is_label(&sym); 567 const char *section_name; 568 569 if (!is_label && !elf_sym__is_function(&sym)) 570 continue; 571 572 sec = elf_getscn(elf, sym.st_shndx); 573 if (!sec) 574 goto out_elf_end; 575 576 gelf_getshdr(sec, &shdr); 577 578 if (is_label && !elf_sec__is_text(&shdr, secstrs)) 579 continue; 580 581 section_name = elf_sec__name(&shdr, secstrs); 582 obj_start = sym.st_value; 583 584 if (self->adjust_symbols) { 585 if (verbose >= 2) 586 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 587 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 588 589 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 590 } 591 592 if (mod) { 593 section = mod->sections->find_section(mod->sections, section_name); 594 if (section) 595 sym.st_value += section->vma; 596 else { 597 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n", 598 mod->name, section_name); 599 goto out_elf_end; 600 } 601 } 602 603 f = symbol__new(sym.st_value, sym.st_size, 604 elf_sym__name(&sym, symstrs), 605 self->sym_priv_size, obj_start, verbose); 606 if (!f) 607 goto out_elf_end; 608 609 if (filter && filter(self, f)) 610 symbol__delete(f, self->sym_priv_size); 611 else { 612 f->module = mod; 613 dso__insert_symbol(self, f); 614 nr++; 615 } 616 } 617 618 err = nr; 619 out_elf_end: 620 elf_end(elf); 621 out_close: 622 return err; 623 } 624 625 int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 626 { 627 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 628 char *name = malloc(size); 629 int variant = 0; 630 int ret = -1; 631 int fd; 632 633 if (!name) 634 return -1; 635 636 self->adjust_symbols = 0; 637 638 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 639 return dso__load_perf_map(self, filter, verbose); 640 641 more: 642 do { 643 switch (variant) { 644 case 0: /* Fedora */ 645 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 646 break; 647 case 1: /* Ubuntu */ 648 snprintf(name, size, "/usr/lib/debug%s", self->name); 649 break; 650 case 2: /* Sane people */ 651 snprintf(name, size, "%s", self->name); 652 break; 653 654 default: 655 goto out; 656 } 657 variant++; 658 659 fd = open(name, O_RDONLY); 660 } while (fd < 0); 661 662 ret = dso__load_sym(self, fd, name, filter, verbose, NULL); 663 close(fd); 664 665 /* 666 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 667 */ 668 if (!ret) 669 goto more; 670 671 out: 672 free(name); 673 return ret; 674 } 675 676 static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 677 symbol_filter_t filter, int verbose) 678 { 679 struct module *mod = mod_dso__find_module(mods, name); 680 int err = 0, fd; 681 682 if (mod == NULL || !mod->active) 683 return err; 684 685 fd = open(mod->path, O_RDONLY); 686 687 if (fd < 0) 688 return err; 689 690 err = dso__load_sym(self, fd, name, filter, verbose, mod); 691 close(fd); 692 693 return err; 694 } 695 696 int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) 697 { 698 struct mod_dso *mods = mod_dso__new_dso("modules"); 699 struct module *pos; 700 struct rb_node *next; 701 int err; 702 703 err = mod_dso__load_modules(mods); 704 705 if (err <= 0) 706 return err; 707 708 /* 709 * Iterate over modules, and load active symbols. 710 */ 711 next = rb_first(&mods->mods); 712 while (next) { 713 pos = rb_entry(next, struct module, rb_node); 714 err = dso__load_module(self, mods, pos->name, filter, verbose); 715 716 if (err < 0) 717 break; 718 719 next = rb_next(&pos->rb_node); 720 } 721 722 if (err < 0) { 723 mod_dso__delete_modules(mods); 724 mod_dso__delete_self(mods); 725 } 726 727 return err; 728 } 729 730 static inline void dso__fill_symbol_holes(struct dso *self) 731 { 732 struct symbol *prev = NULL; 733 struct rb_node *nd; 734 735 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 736 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 737 738 if (prev) { 739 u64 hole = 0; 740 int alias = pos->start == prev->start; 741 742 if (!alias) 743 hole = prev->start - pos->end - 1; 744 745 if (hole || alias) { 746 if (alias) 747 pos->end = prev->end; 748 else if (hole) 749 pos->end = prev->start - 1; 750 } 751 } 752 prev = pos; 753 } 754 } 755 756 static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 757 symbol_filter_t filter, int verbose) 758 { 759 int err, fd = open(vmlinux, O_RDONLY); 760 761 if (fd < 0) 762 return -1; 763 764 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); 765 766 if (err > 0) 767 dso__fill_symbol_holes(self); 768 769 close(fd); 770 771 return err; 772 } 773 774 int dso__load_kernel(struct dso *self, const char *vmlinux, 775 symbol_filter_t filter, int verbose, int modules) 776 { 777 int err = -1; 778 779 if (vmlinux) { 780 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 781 if (err > 0 && modules) 782 err = dso__load_modules(self, filter, verbose); 783 } 784 785 if (err <= 0) 786 err = dso__load_kallsyms(self, filter, verbose); 787 788 return err; 789 } 790 791 void symbol__init(void) 792 { 793 elf_version(EV_CURRENT); 794 } 795