1 /*- 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #if 0 35 /* From: */ 36 #ifndef lint 37 static char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; 38 #endif /* not lint */ 39 #endif 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/types.h> 45 #include <sys/mman.h> 46 #include <sys/stat.h> 47 #include <machine/elf.h> 48 49 #include <err.h> 50 #include <fcntl.h> 51 #include <string.h> 52 #include <unistd.h> 53 54 #include "gprof.h" 55 56 static bool wantsym(const Elf_Sym *, const char *); 57 58 /* Things which get -E excluded by default. */ 59 static char *excludes[] = { ".mcount", "_mcleanup", NULL }; 60 61 int 62 elf_getnfile(const char *filename, char ***defaultEs) 63 { 64 int fd; 65 Elf_Ehdr h; 66 struct stat s; 67 void *mapbase; 68 const char *base; 69 const Elf_Shdr *shdrs; 70 const Elf_Shdr *sh_symtab; 71 const Elf_Shdr *sh_strtab; 72 const char *strtab; 73 const Elf_Sym *symtab; 74 int symtabct; 75 int i; 76 77 if ((fd = open(filename, O_RDONLY)) == -1) 78 err(1, "%s", filename); 79 if (read(fd, &h, sizeof h) != sizeof h || !IS_ELF(h)) { 80 close(fd); 81 return -1; 82 } 83 if (fstat(fd, &s) == -1) 84 err(1, "cannot fstat %s", filename); 85 if ((mapbase = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0)) == 86 MAP_FAILED) 87 err(1, "cannot mmap %s", filename); 88 close(fd); 89 90 base = (const char *)mapbase; 91 shdrs = (const Elf_Shdr *)(base + h.e_shoff); 92 93 /* Find the symbol table and associated string table section. */ 94 for (i = 1; i < h.e_shnum; i++) 95 if (shdrs[i].sh_type == SHT_SYMTAB) 96 break; 97 if (i == h.e_shnum) 98 errx(1, "%s has no symbol table", filename); 99 sh_symtab = &shdrs[i]; 100 sh_strtab = &shdrs[sh_symtab->sh_link]; 101 102 symtab = (const Elf_Sym *)(base + sh_symtab->sh_offset); 103 symtabct = sh_symtab->sh_size / sh_symtab->sh_entsize; 104 strtab = (const char *)(base + sh_strtab->sh_offset); 105 106 /* Count the symbols that we're interested in. */ 107 nname = 0; 108 for (i = 1; i < symtabct; i++) 109 if (wantsym(&symtab[i], strtab)) 110 nname++; 111 112 /* Allocate memory for them, plus a terminating entry. */ 113 if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL) 114 errx(1, "insufficient memory for symbol table"); 115 116 /* Read them in. */ 117 npe = nl; 118 for (i = 1; i < symtabct; i++) { 119 const Elf_Sym *sym = &symtab[i]; 120 121 if (wantsym(sym, strtab)) { 122 npe->value = sym->st_value; 123 npe->name = strtab + sym->st_name; 124 npe++; 125 } 126 } 127 npe->value = -1; 128 129 *defaultEs = excludes; 130 return 0; 131 } 132 133 static bool 134 wantsym(const Elf_Sym *sym, const char *strtab) 135 { 136 int type; 137 int bind; 138 139 type = ELF_ST_TYPE(sym->st_info); 140 bind = ELF_ST_BIND(sym->st_info); 141 142 if (type != STT_FUNC || 143 (aflag && bind == STB_LOCAL) || 144 (uflag && strchr(strtab + sym->st_name, '.') != NULL)) 145 return 0; 146 147 return 1; 148 } 149