elf.c revision 105243
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 37static 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: head/usr.bin/gprof/elf.c 105243 2002-10-16 13:50:09Z charnier $"); 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 56static bool wantsym(const Elf_Sym *, const char *); 57 58/* Things which get -E excluded by default. */ 59static char *excludes[] = { ".mcount", "_mcleanup", NULL }; 60 61int 62elf_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 133static bool 134wantsym(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