symbol.c (9974f496782b7612e36a143bedda858f1cb953d4) | symbol.c (6cfcc53ed4f3ecb9319e73a03f34f1eddcb644dd) |
---|---|
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> --- 21 unchanged lines hidden (view full) --- 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; | 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> --- 21 unchanged lines hidden (view full) --- 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 = start + len - 1; | 38 self->end = len ? start + len - 1 : start; |
39 memcpy(self->name, name, namelen); 40 41 return self; 42} 43 44static void symbol__delete(struct symbol *self, unsigned int priv_size) 45{ 46 free(((void *)self) - priv_size); 47} 48 49static size_t symbol__fprintf(struct symbol *self, FILE *fp) 50{ | 39 memcpy(self->name, name, namelen); 40 41 return self; 42} 43 44static void symbol__delete(struct symbol *self, unsigned int priv_size) 45{ 46 free(((void *)self) - priv_size); 47} 48 49static size_t symbol__fprintf(struct symbol *self, FILE *fp) 50{ |
51 return fprintf(fp, " %llx-%llx %s\n", | 51 if (!self->module) 52 return fprintf(fp, " %llx-%llx %s\n", |
52 self->start, self->end, self->name); | 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); |
|
53} 54 55struct dso *dso__new(const char *name, unsigned int sym_priv_size) 56{ 57 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 58 59 if (self != NULL) { 60 strcpy(self->name, name); --- 244 unchanged lines hidden (view full) --- 305static inline int elf_sym__is_function(const GElf_Sym *sym) 306{ 307 return elf_sym__type(sym) == STT_FUNC && 308 sym->st_name != 0 && 309 sym->st_shndx != SHN_UNDEF && 310 sym->st_size != 0; 311} 312 | 57} 58 59struct 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); --- 244 unchanged lines hidden (view full) --- 309static 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 |
317static 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 325static 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 331static 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 |
|
313static inline const char *elf_sym__name(const GElf_Sym *sym, 314 const Elf_Data *symstrs) 315{ 316 return symstrs->d_buf + sym->st_name; 317} 318 319static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 320 GElf_Shdr *shp, const char *name, --- 125 unchanged lines hidden (view full) --- 446 * I have to investigate, but probably should be ignored. 447 */ 448 } 449 450 return nr; 451} 452 453static int dso__load_sym(struct dso *self, int fd, const char *name, | 337static 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 343static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 344 GElf_Shdr *shp, const char *name, --- 125 unchanged lines hidden (view full) --- 470 * I have to investigate, but probably should be ignored. 471 */ 472 } 473 474 return nr; 475} 476 477static int dso__load_sym(struct dso *self, int fd, const char *name, |
454 symbol_filter_t filter, int verbose) | 478 symbol_filter_t filter, int verbose, struct module *mod) |
455{ | 479{ |
456 Elf_Data *symstrs; | 480 Elf_Data *symstrs, *secstrs; |
457 uint32_t nr_syms; 458 int err = -1; 459 uint32_t index; 460 GElf_Ehdr ehdr; 461 GElf_Shdr shdr; 462 Elf_Data *syms; 463 GElf_Sym sym; | 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; |
464 Elf_Scn *sec, *sec_dynsym; | 488 Elf_Scn *sec, *sec_dynsym, *sec_strndx; |
465 Elf *elf; 466 size_t dynsym_idx; 467 int nr = 0; 468 469 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 470 if (elf == NULL) { 471 if (verbose) 472 fprintf(stderr, "%s: cannot read %s ELF file.\n", --- 42 unchanged lines hidden (view full) --- 515 sec = elf_getscn(elf, shdr.sh_link); 516 if (sec == NULL) 517 goto out_elf_end; 518 519 symstrs = elf_getdata(sec, NULL); 520 if (symstrs == NULL) 521 goto out_elf_end; 522 | 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", --- 42 unchanged lines hidden (view full) --- 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 |
|
523 nr_syms = shdr.sh_size / shdr.sh_entsize; 524 525 memset(&sym, 0, sizeof(sym)); 526 self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, 527 ".gnu.prelink_undo", 528 NULL) != NULL; 529 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 530 struct symbol *f; 531 u64 obj_start; | 555 nr_syms = shdr.sh_size / shdr.sh_entsize; 556 557 memset(&sym, 0, sizeof(sym)); 558 self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, 559 ".gnu.prelink_undo", 560 NULL) != NULL; 561 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 562 struct symbol *f; 563 u64 obj_start; |
564 struct section *section = NULL; 565 int is_label = elf_sym__is_label(&sym); 566 const char *section_name; |
|
532 | 567 |
533 if (!elf_sym__is_function(&sym)) | 568 if (!is_label && !elf_sym__is_function(&sym)) |
534 continue; 535 536 sec = elf_getscn(elf, sym.st_shndx); 537 if (!sec) 538 goto out_elf_end; 539 540 gelf_getshdr(sec, &shdr); | 569 continue; 570 571 sec = elf_getscn(elf, sym.st_shndx); 572 if (!sec) 573 goto out_elf_end; 574 575 gelf_getshdr(sec, &shdr); |
576 577 if (is_label && !elf_sec__is_text(&shdr, secstrs)) 578 continue; 579 580 section_name = elf_sec__name(&shdr, secstrs); |
|
541 obj_start = sym.st_value; 542 543 if (self->prelinked) { 544 if (verbose >= 2) 545 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 546 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 547 548 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 549 } 550 | 581 obj_start = sym.st_value; 582 583 if (self->prelinked) { 584 if (verbose >= 2) 585 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 586 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 587 588 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 589 } 590 |
591 if (mod) { 592 section = mod->sections->find_section(mod->sections, section_name); 593 if (section) 594 sym.st_value += section->vma; 595 else { 596 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n", 597 mod->name, section_name); 598 goto out_elf_end; 599 } 600 } 601 |
|
551 f = symbol__new(sym.st_value, sym.st_size, 552 elf_sym__name(&sym, symstrs), 553 self->sym_priv_size, obj_start, verbose); 554 if (!f) 555 goto out_elf_end; 556 557 if (filter && filter(self, f)) 558 symbol__delete(f, self->sym_priv_size); 559 else { | 602 f = symbol__new(sym.st_value, sym.st_size, 603 elf_sym__name(&sym, symstrs), 604 self->sym_priv_size, obj_start, verbose); 605 if (!f) 606 goto out_elf_end; 607 608 if (filter && filter(self, f)) 609 symbol__delete(f, self->sym_priv_size); 610 else { |
611 f->module = mod; |
|
560 dso__insert_symbol(self, f); 561 nr++; 562 } 563 } 564 565 err = nr; 566out_elf_end: 567 elf_end(elf); --- 33 unchanged lines hidden (view full) --- 601 default: 602 goto out; 603 } 604 variant++; 605 606 fd = open(name, O_RDONLY); 607 } while (fd < 0); 608 | 612 dso__insert_symbol(self, f); 613 nr++; 614 } 615 } 616 617 err = nr; 618out_elf_end: 619 elf_end(elf); --- 33 unchanged lines hidden (view full) --- 653 default: 654 goto out; 655 } 656 variant++; 657 658 fd = open(name, O_RDONLY); 659 } while (fd < 0); 660 |
609 ret = dso__load_sym(self, fd, name, filter, verbose); | 661 ret = dso__load_sym(self, fd, name, filter, verbose, NULL); |
610 close(fd); 611 612 /* 613 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 614 */ 615 if (!ret) 616 goto more; 617 618out: 619 free(name); 620 return ret; 621} 622 | 662 close(fd); 663 664 /* 665 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 666 */ 667 if (!ret) 668 goto more; 669 670out: 671 free(name); 672 return ret; 673} 674 |
675static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 676 symbol_filter_t filter, int verbose) 677{ 678 struct module *mod = mod_dso__find_module(mods, name); 679 int err = 0, fd; 680 681 if (mod == NULL || !mod->active) 682 return err; 683 684 fd = open(mod->path, O_RDONLY); 685 686 if (fd < 0) 687 return err; 688 689 err = dso__load_sym(self, fd, name, filter, verbose, mod); 690 close(fd); 691 692 return err; 693} 694 695int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) 696{ 697 struct mod_dso *mods = mod_dso__new_dso("modules"); 698 struct module *pos; 699 struct rb_node *next; 700 int err; 701 702 err = mod_dso__load_modules(mods); 703 704 if (err <= 0) 705 return err; 706 707 /* 708 * Iterate over modules, and load active symbols. 709 */ 710 next = rb_first(&mods->mods); 711 while (next) { 712 pos = rb_entry(next, struct module, rb_node); 713 err = dso__load_module(self, mods, pos->name, filter, verbose); 714 715 if (err < 0) 716 break; 717 718 next = rb_next(&pos->rb_node); 719 } 720 721 if (err < 0) { 722 mod_dso__delete_modules(mods); 723 mod_dso__delete_self(mods); 724 } 725 726 return err; 727} 728 729static inline void dso__fill_symbol_holes(struct dso *self) 730{ 731 struct symbol *prev = NULL; 732 struct rb_node *nd; 733 734 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 735 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 736 737 if (prev) { 738 u64 hole = 0; 739 int alias = pos->start == prev->start; 740 741 if (!alias) 742 hole = prev->start - pos->end - 1; 743 744 if (hole || alias) { 745 if (alias) 746 pos->end = prev->end; 747 else if (hole) 748 pos->end = prev->start - 1; 749 } 750 } 751 prev = pos; 752 } 753} 754 |
|
623static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 624 symbol_filter_t filter, int verbose) 625{ 626 int err, fd = open(vmlinux, O_RDONLY); 627 628 if (fd < 0) 629 return -1; 630 | 755static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 756 symbol_filter_t filter, int verbose) 757{ 758 int err, fd = open(vmlinux, O_RDONLY); 759 760 if (fd < 0) 761 return -1; 762 |
631 err = dso__load_sym(self, fd, vmlinux, filter, verbose); | 763 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); 764 765 if (err > 0) 766 dso__fill_symbol_holes(self); 767 |
632 close(fd); 633 634 return err; 635} 636 637int dso__load_kernel(struct dso *self, const char *vmlinux, | 768 close(fd); 769 770 return err; 771} 772 773int dso__load_kernel(struct dso *self, const char *vmlinux, |
638 symbol_filter_t filter, int verbose) | 774 symbol_filter_t filter, int verbose, int modules) |
639{ 640 int err = -1; 641 | 775{ 776 int err = -1; 777 |
642 if (vmlinux) | 778 if (vmlinux) { |
643 err = dso__load_vmlinux(self, vmlinux, filter, verbose); | 779 err = dso__load_vmlinux(self, vmlinux, filter, verbose); |
780 if (err > 0 && modules) 781 err = dso__load_modules(self, filter, verbose); 782 } |
|
644 645 if (err <= 0) 646 err = dso__load_kallsyms(self, filter, verbose); 647 648 return err; 649} 650 651void symbol__init(void) 652{ 653 elf_version(EV_CURRENT); 654} | 783 784 if (err <= 0) 785 err = dso__load_kallsyms(self, filter, verbose); 786 787 return err; 788} 789 790void symbol__init(void) 791{ 792 elf_version(EV_CURRENT); 793} |