elf.c revision 38928
11556Srgrimes#include <sys/types.h> 21556Srgrimes#include <sys/mman.h> 31556Srgrimes#include <sys/stat.h> 41556Srgrimes 51556Srgrimes#include <elf.h> 61556Srgrimes#include <err.h> 71556Srgrimes#include <fcntl.h> 81556Srgrimes#include <string.h> 91556Srgrimes#include <unistd.h> 101556Srgrimes 111556Srgrimes#include "gprof.h" 121556Srgrimes 131556Srgrimesstatic bool wantsym(const Elf_Sym *, const char *); 141556Srgrimes 151556Srgrimes/* Things which get -E excluded by default. */ 161556Srgrimesstatic char *excludes[] = { ".mcount", "_mcleanup", NULL }; 171556Srgrimes 181556Srgrimesint 191556Srgrimeself_getnfile(const char *filename, char ***defaultEs) 201556Srgrimes{ 211556Srgrimes int fd; 221556Srgrimes Elf_Ehdr h; 231556Srgrimes struct stat s; 241556Srgrimes void *mapbase; 251556Srgrimes const char *base; 261556Srgrimes const Elf_Shdr *shdrs; 271556Srgrimes const Elf_Shdr *sh_symtab; 28127499Sgad const Elf_Shdr *sh_strtab; 29127499Sgad const char *strtab; 30127499Sgad const Elf_Sym *symtab; 31127499Sgad int symtabct; 32127499Sgad int i; 33127499Sgad 34127499Sgad if ((fd = open(filename, O_RDONLY)) == -1) 351556Srgrimes err(1, "%s", filename); 361556Srgrimes if (read(fd, &h, sizeof h) != sizeof h || !IS_ELF(h)) { 371556Srgrimes close(fd); 3890143Smarkm return -1; 391556Srgrimes } 401556Srgrimes if (fstat(fd, &s) == -1) 411556Srgrimes err(1, "Cannot fstat %s", filename); 421556Srgrimes if ((mapbase = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0)) == 4390143Smarkm MAP_FAILED) 441556Srgrimes err(1, "Cannot mmap %s", filename); 4536049Scharnier close(fd); 4690143Smarkm 4736049Scharnier base = (const char *)mapbase; 48110391Scharnier shdrs = (const Elf_Shdr *)(base + h.e_shoff); 4999110Sobrien 5099110Sobrien /* Find the symbol table and associated string table section. */ 511556Srgrimes for (i = 1; i < h.e_shnum; i++) 521556Srgrimes if (shdrs[i].sh_type == SHT_SYMTAB) 53127546Sgad break; 543296Sdg if (i == h.e_shnum) 551556Srgrimes errx(1, "%s has no symbol table", filename); 561556Srgrimes sh_symtab = &shdrs[i]; 571556Srgrimes sh_strtab = &shdrs[sh_symtab->sh_link]; 581556Srgrimes 591556Srgrimes symtab = (const Elf_Sym *)(base + sh_symtab->sh_offset); 601556Srgrimes symtabct = sh_symtab->sh_size / sh_symtab->sh_entsize; 61127149Sgad strtab = (const char *)(base + sh_strtab->sh_offset); 621556Srgrimes 63127499Sgad /* Count the symbols that we're interested in. */ 641556Srgrimes nname = 0; 6513514Smpp for (i = 1; i < symtabct; i++) 6673367Sache if (wantsym(&symtab[i], strtab)) 671556Srgrimes nname++; 6890143Smarkm 691556Srgrimes /* Allocate memory for them, plus a terminating entry. */ 701556Srgrimes if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL) 711556Srgrimes errx(1, "Insufficient memory for symbol table"); 721556Srgrimes 731556Srgrimes /* Read them in. */ 741556Srgrimes npe = nl; 751556Srgrimes for (i = 1; i < symtabct; i++) { 76127499Sgad const Elf_Sym *sym = &symtab[i]; 77127499Sgad 7866377Sbrian if (wantsym(sym, strtab)) { 79127537Sgad npe->value = sym->st_value; 80127555Sgad npe->name = strtab + sym->st_name; 81127537Sgad npe++; 82127537Sgad } 83127555Sgad } 84127537Sgad npe->value = -1; 85127537Sgad 86127537Sgad *defaultEs = excludes; 87129914Sgad return 0; 88129971Sgad} 89129971Sgad 90129914Sgadstatic bool 91129971Sgadwantsym(const Elf_Sym *sym, const char *strtab) 92129914Sgad{ 93127537Sgad int type; 94127537Sgad int bind; 95127537Sgad 96127537Sgad type = ELF_ST_TYPE(sym->st_info); 97127537Sgad bind = ELF_ST_BIND(sym->st_info); 98127537Sgad 99127537Sgad if (type != STT_FUNC || 100127537Sgad bind == STB_WEAK || 101130999Sgad (aflag && bind == STB_LOCAL) || 1021556Srgrimes (uflag && strchr(strtab + sym->st_name, '.') != NULL)) 103127537Sgad return 0; 104127537Sgad 105127537Sgad return 1; 106127537Sgad} 107127537Sgad