diff options
Diffstat (limited to 'lib/libc/gen/nlist.c')
-rw-r--r-- | lib/libc/gen/nlist.c | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c deleted file mode 100644 index 3100a12..0000000 --- a/lib/libc/gen/nlist.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/file.h> - -#include <errno.h> -#include <a.out.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#define _NLIST_DO_AOUT - -#ifdef _NLIST_DO_ELF -#include <elf.h> -#endif - -int __fdnlist __P((int, struct nlist *)); -int __aout_fdnlist __P((int, struct nlist *)); -int __elf_fdnlist __P((int, struct nlist *)); - -int -nlist(name, list) - const char *name; - struct nlist *list; -{ - int fd, n; - - fd = open(name, O_RDONLY, 0); - if (fd < 0) - return (-1); - n = __fdnlist(fd, list); - (void)close(fd); - return (n); -} - -static struct nlist_handlers { - int (*fn) __P((int fd, struct nlist *list)); -} nlist_fn[] = { -#ifdef _NLIST_DO_AOUT - { __aout_fdnlist }, -#endif -#ifdef _NLIST_DO_ELF - { __elf_fdnlist }, -#endif -}; - -int -__fdnlist(fd, list) - register int fd; - register struct nlist *list; -{ - int n = -1, i; - - for (i = 0; i < sizeof(nlist_fn) / sizeof(nlist_fn[0]); i++) { - n = (nlist_fn[i].fn)(fd, list); - if (n != -1) - break; - } - return (n); -} - -#define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0) - -#ifdef _NLIST_DO_AOUT -int -__aout_fdnlist(fd, list) - register int fd; - register struct nlist *list; -{ - register struct nlist *p, *symtab; - register caddr_t strtab, a_out_mmap; - register off_t stroff, symoff; - register u_long symsize; - register int nent; - struct exec * exec; - struct stat st; - - /* check that file is at least as large as struct exec! */ - if ((fstat(fd, &st) < 0) || (st.st_size < sizeof(struct exec))) - return (-1); - - /* Check for files too large to mmap. */ - if (st.st_size > SIZE_T_MAX) { - errno = EFBIG; - return (-1); - } - - /* - * Map the whole a.out file into our address space. - * We then find the string table withing this area. - * We do not just mmap the string table, as it probably - * does not start at a page boundary - we save ourselves a - * lot of nastiness by mmapping the whole file. - * - * This gives us an easy way to randomly access all the strings, - * without making the memory allocation permanent as with - * malloc/free (i.e., munmap will return it to the system). - */ - a_out_mmap = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t)0); - if (a_out_mmap == MAP_FAILED) - return (-1); - - exec = (struct exec *)a_out_mmap; - if (N_BADMAG(*exec)) { - munmap(a_out_mmap, (size_t)st.st_size); - return (-1); - } - - symoff = N_SYMOFF(*exec); - symsize = exec->a_syms; - stroff = symoff + symsize; - - /* find the string table in our mmapped area */ - strtab = a_out_mmap + stroff; - symtab = (struct nlist *)(a_out_mmap + symoff); - - /* - * clean out any left-over information for all valid entries. - * Type and value defined to be 0 if not found; historical - * versions cleared other and desc as well. Also figure out - * the largest string length so don't read any more of the - * string table than we have to. - * - * XXX clearing anything other than n_type and n_value violates - * the semantics given in the man page. - */ - nent = 0; - for (p = list; !ISLAST(p); ++p) { - p->n_type = 0; - p->n_other = 0; - p->n_desc = 0; - p->n_value = 0; - ++nent; - } - - while (symsize > 0) { - register int soff; - - symsize-= sizeof(struct nlist); - soff = symtab->n_un.n_strx; - - - if (soff != 0 && (symtab->n_type & N_STAB) == 0) - for (p = list; !ISLAST(p); p++) - if (!strcmp(&strtab[soff], p->n_un.n_name)) { - p->n_value = symtab->n_value; - p->n_type = symtab->n_type; - p->n_desc = symtab->n_desc; - p->n_other = symtab->n_other; - if (--nent <= 0) - break; - } - symtab++; - } - munmap(a_out_mmap, (size_t)st.st_size); - return (nent); -} -#endif - -#ifdef _NLIST_DO_ELF -/* - * __elf_is_okay__ - Determine if ehdr really - * is ELF and valid for the target platform. - * - * WARNING: This is NOT a ELF ABI function and - * as such it's use should be restricted. - */ -int -__elf_is_okay__(ehdr) - register Elf32_Ehdr *ehdr; -{ - register int retval = 0; - /* - * We need to check magic, class size, endianess, - * and version before we look at the rest of the - * Elf32_Ehdr structure. These few elements are - * represented in a machine independant fashion. - */ - if (IS_ELF(*ehdr) && - ehdr->e_ident[EI_CLASS] == ELF_TARG_CLASS && - ehdr->e_ident[EI_DATA] == ELF_TARG_DATA && - ehdr->e_ident[EI_VERSION] == ELF_TARG_VER) { - - /* Now check the machine dependant header */ - if (ehdr->e_machine == ELF_TARG_MACH && - ehdr->e_version == ELF_TARG_VER) - retval = 1; - } - return retval; -} - -int -__elf_fdnlist(fd, list) - register int fd; - register struct nlist *list; -{ - register struct nlist *p; - register caddr_t strtab; - register Elf32_Off symoff = 0, symstroff = 0; - register Elf32_Word symsize = 0, symstrsize = 0; - register Elf32_Sword nent, cc, i; - Elf32_Sym sbuf[1024]; - Elf32_Sym *s; - Elf32_Ehdr ehdr; - Elf32_Shdr *shdr = NULL; - Elf32_Word shdr_size; - struct stat st; - - /* Make sure obj is OK */ - if (lseek(fd, (off_t)0, SEEK_SET) == -1 || - read(fd, &ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr) || - !__elf_is_okay__(&ehdr) || - fstat(fd, &st) < 0) - return (-1); - - /* calculate section header table size */ - shdr_size = ehdr.e_shentsize * ehdr.e_shnum; - - /* Make sure it's not too big to mmap */ - if (shdr_size > SIZE_T_MAX) { - errno = EFBIG; - return (-1); - } - - /* mmap section header table */ - shdr = (Elf32_Shdr *)mmap(NULL, (size_t)shdr_size, - PROT_READ, 0, fd, (off_t) ehdr.e_shoff); - if (shdr == (Elf32_Shdr *)-1) - return (-1); - - /* - * Find the symbol table entry and it's corresponding - * string table entry. Version 1.1 of the ABI states - * that there is only one symbol table but that this - * could change in the future. - */ - for (i = 0; i < ehdr.e_shnum; i++) { - if (shdr[i].sh_type == SHT_SYMTAB) { - symoff = shdr[i].sh_offset; - symsize = shdr[i].sh_size; - symstroff = shdr[shdr[i].sh_link].sh_offset; - symstrsize = shdr[shdr[i].sh_link].sh_size; - break; - } - } - - /* Flush the section header table */ - munmap((caddr_t)shdr, shdr_size); - - /* Check for files too large to mmap. */ - if (symstrsize > SIZE_T_MAX) { - errno = EFBIG; - return (-1); - } - /* - * Map string table into our address space. This gives us - * an easy way to randomly access all the strings, without - * making the memory allocation permanent as with malloc/free - * (i.e., munmap will return it to the system). - */ - strtab = mmap(NULL, (size_t)symstrsize, PROT_READ, 0, fd, - (off_t) symstroff); - if (strtab == (char *)-1) - return (-1); - - /* - * clean out any left-over information for all valid entries. - * Type and value defined to be 0 if not found; historical - * versions cleared other and desc as well. Also figure out - * the largest string length so don't read any more of the - * string table than we have to. - * - * XXX clearing anything other than n_type and n_value violates - * the semantics given in the man page. - */ - nent = 0; - for (p = list; !ISLAST(p); ++p) { - p->n_type = 0; - p->n_other = 0; - p->n_desc = 0; - p->n_value = 0; - ++nent; - } - - /* Don't process any further if object is stripped. */ - /* ELFism - dunno if stripped by looking at header */ - if (symoff == 0) - goto done; - - if (lseek(fd, (off_t) symoff, SEEK_SET) == -1) { - nent = -1; - goto done; - } - - while (symsize > 0) { - cc = MIN(symsize, sizeof(sbuf)); - if (read(fd, sbuf, cc) != cc) - break; - symsize -= cc; - for (s = sbuf; cc > 0; ++s, cc -= sizeof(*s)) { - register int soff = s->st_name; - - if (soff == 0) - continue; - for (p = list; !ISLAST(p); p++) { - if ((p->n_un.n_name[0] == '_' && - !strcmp(&strtab[soff], p->n_un.n_name+1)) - || !strcmp(&strtab[soff], p->n_un.n_name)) { - p->n_value = s->st_value; - - /* XXX - type conversion */ - /* is pretty rude. */ - switch(ELF32_ST_TYPE(s->st_info)) { - case STT_NOTYPE: - p->n_type = N_UNDF; - break; - case STT_OBJECT: - p->n_type = N_DATA; - break; - case STT_FUNC: - p->n_type = N_TEXT; - break; - case STT_FILE: - p->n_type = N_FN; - break; - } - if (ELF32_ST_BIND(s->st_info) == - STB_LOCAL) - p->n_type = N_EXT; - p->n_desc = 0; - p->n_other = 0; - if (--nent <= 0) - break; - } - } - } - } - done: - munmap(strtab, symstrsize); - - return (nent); -} -#endif /* _NLIST_DO_ELF */ |