1312a529bSBruce Evans /*- 2312a529bSBruce Evans * Copyright (c) 1983, 1993 3312a529bSBruce Evans * The Regents of the University of California. All rights reserved. 4312a529bSBruce Evans * 5312a529bSBruce Evans * Redistribution and use in source and binary forms, with or without 6312a529bSBruce Evans * modification, are permitted provided that the following conditions 7312a529bSBruce Evans * are met: 8312a529bSBruce Evans * 1. Redistributions of source code must retain the above copyright 9312a529bSBruce Evans * notice, this list of conditions and the following disclaimer. 10312a529bSBruce Evans * 2. Redistributions in binary form must reproduce the above copyright 11312a529bSBruce Evans * notice, this list of conditions and the following disclaimer in the 12312a529bSBruce Evans * documentation and/or other materials provided with the distribution. 13*fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 14312a529bSBruce Evans * may be used to endorse or promote products derived from this software 15312a529bSBruce Evans * without specific prior written permission. 16312a529bSBruce Evans * 17312a529bSBruce Evans * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18312a529bSBruce Evans * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19312a529bSBruce Evans * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20312a529bSBruce Evans * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21312a529bSBruce Evans * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22312a529bSBruce Evans * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23312a529bSBruce Evans * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24312a529bSBruce Evans * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25312a529bSBruce Evans * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26312a529bSBruce Evans * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27312a529bSBruce Evans * SUCH DAMAGE. 28312a529bSBruce Evans */ 29312a529bSBruce Evans 30312a529bSBruce Evans #if 0 31312a529bSBruce Evans /* From: */ 325e6220d9SDavid E. O'Brien #ifndef lint 33312a529bSBruce Evans static char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; 345e6220d9SDavid E. O'Brien #endif /* not lint */ 35312a529bSBruce Evans #endif 36312a529bSBruce Evans 37312a529bSBruce Evans #include <sys/cdefs.h> 38312a529bSBruce Evans __FBSDID("$FreeBSD$"); 395e6220d9SDavid E. O'Brien 405584f22bSJohn Polstra #include <sys/types.h> 415584f22bSJohn Polstra #include <sys/mman.h> 425584f22bSJohn Polstra #include <sys/stat.h> 435e6220d9SDavid E. O'Brien #include <machine/elf.h> 445584f22bSJohn Polstra 455584f22bSJohn Polstra #include <err.h> 465584f22bSJohn Polstra #include <fcntl.h> 475584f22bSJohn Polstra #include <string.h> 485584f22bSJohn Polstra #include <unistd.h> 495584f22bSJohn Polstra 505584f22bSJohn Polstra #include "gprof.h" 515584f22bSJohn Polstra 525584f22bSJohn Polstra static bool wantsym(const Elf_Sym *, const char *); 535584f22bSJohn Polstra 545584f22bSJohn Polstra /* Things which get -E excluded by default. */ 555584f22bSJohn Polstra static char *excludes[] = { ".mcount", "_mcleanup", NULL }; 565584f22bSJohn Polstra 575584f22bSJohn Polstra int 585584f22bSJohn Polstra elf_getnfile(const char *filename, char ***defaultEs) 595584f22bSJohn Polstra { 605584f22bSJohn Polstra int fd; 615584f22bSJohn Polstra Elf_Ehdr h; 625584f22bSJohn Polstra struct stat s; 635584f22bSJohn Polstra void *mapbase; 645584f22bSJohn Polstra const char *base; 655584f22bSJohn Polstra const Elf_Shdr *shdrs; 665584f22bSJohn Polstra const Elf_Shdr *sh_symtab; 675584f22bSJohn Polstra const Elf_Shdr *sh_strtab; 685584f22bSJohn Polstra const char *strtab; 695584f22bSJohn Polstra const Elf_Sym *symtab; 705584f22bSJohn Polstra int symtabct; 715584f22bSJohn Polstra int i; 725584f22bSJohn Polstra 735584f22bSJohn Polstra if ((fd = open(filename, O_RDONLY)) == -1) 745584f22bSJohn Polstra err(1, "%s", filename); 755584f22bSJohn Polstra if (read(fd, &h, sizeof h) != sizeof h || !IS_ELF(h)) { 765584f22bSJohn Polstra close(fd); 775584f22bSJohn Polstra return -1; 785584f22bSJohn Polstra } 795584f22bSJohn Polstra if (fstat(fd, &s) == -1) 8097fa9b77SPhilippe Charnier err(1, "cannot fstat %s", filename); 815584f22bSJohn Polstra if ((mapbase = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0)) == 825584f22bSJohn Polstra MAP_FAILED) 8397fa9b77SPhilippe Charnier err(1, "cannot mmap %s", filename); 845584f22bSJohn Polstra close(fd); 855584f22bSJohn Polstra 865584f22bSJohn Polstra base = (const char *)mapbase; 875584f22bSJohn Polstra shdrs = (const Elf_Shdr *)(base + h.e_shoff); 885584f22bSJohn Polstra 895584f22bSJohn Polstra /* Find the symbol table and associated string table section. */ 905584f22bSJohn Polstra for (i = 1; i < h.e_shnum; i++) 915584f22bSJohn Polstra if (shdrs[i].sh_type == SHT_SYMTAB) 925584f22bSJohn Polstra break; 935584f22bSJohn Polstra if (i == h.e_shnum) 945584f22bSJohn Polstra errx(1, "%s has no symbol table", filename); 955584f22bSJohn Polstra sh_symtab = &shdrs[i]; 965584f22bSJohn Polstra sh_strtab = &shdrs[sh_symtab->sh_link]; 975584f22bSJohn Polstra 985584f22bSJohn Polstra symtab = (const Elf_Sym *)(base + sh_symtab->sh_offset); 995584f22bSJohn Polstra symtabct = sh_symtab->sh_size / sh_symtab->sh_entsize; 1005584f22bSJohn Polstra strtab = (const char *)(base + sh_strtab->sh_offset); 1015584f22bSJohn Polstra 1025584f22bSJohn Polstra /* Count the symbols that we're interested in. */ 1035584f22bSJohn Polstra nname = 0; 1045584f22bSJohn Polstra for (i = 1; i < symtabct; i++) 1055584f22bSJohn Polstra if (wantsym(&symtab[i], strtab)) 1065584f22bSJohn Polstra nname++; 1075584f22bSJohn Polstra 1085584f22bSJohn Polstra /* Allocate memory for them, plus a terminating entry. */ 1095584f22bSJohn Polstra if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL) 11097fa9b77SPhilippe Charnier errx(1, "insufficient memory for symbol table"); 1115584f22bSJohn Polstra 1125584f22bSJohn Polstra /* Read them in. */ 1135584f22bSJohn Polstra npe = nl; 1145584f22bSJohn Polstra for (i = 1; i < symtabct; i++) { 1155584f22bSJohn Polstra const Elf_Sym *sym = &symtab[i]; 1165584f22bSJohn Polstra 1175584f22bSJohn Polstra if (wantsym(sym, strtab)) { 1185584f22bSJohn Polstra npe->value = sym->st_value; 1195584f22bSJohn Polstra npe->name = strtab + sym->st_name; 1205584f22bSJohn Polstra npe++; 1215584f22bSJohn Polstra } 1225584f22bSJohn Polstra } 1235584f22bSJohn Polstra npe->value = -1; 1245584f22bSJohn Polstra 1255584f22bSJohn Polstra *defaultEs = excludes; 1265584f22bSJohn Polstra return 0; 1275584f22bSJohn Polstra } 1285584f22bSJohn Polstra 1295584f22bSJohn Polstra static bool 1305584f22bSJohn Polstra wantsym(const Elf_Sym *sym, const char *strtab) 1315584f22bSJohn Polstra { 1325584f22bSJohn Polstra int type; 1335584f22bSJohn Polstra int bind; 1345584f22bSJohn Polstra 1355584f22bSJohn Polstra type = ELF_ST_TYPE(sym->st_info); 1365584f22bSJohn Polstra bind = ELF_ST_BIND(sym->st_info); 1375584f22bSJohn Polstra 1385584f22bSJohn Polstra if (type != STT_FUNC || 1395584f22bSJohn Polstra (aflag && bind == STB_LOCAL) || 1405584f22bSJohn Polstra (uflag && strchr(strtab + sym->st_name, '.') != NULL)) 1415584f22bSJohn Polstra return 0; 1425584f22bSJohn Polstra 1435584f22bSJohn Polstra return 1; 1445584f22bSJohn Polstra } 145