diff options
-rw-r--r-- | lib/libc/gen/nlist.c | 123 |
1 files changed, 75 insertions, 48 deletions
diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c index 535ac5bb690..8f7556634e8 100644 --- a/lib/libc/gen/nlist.c +++ b/lib/libc/gen/nlist.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nlist.c,v 1.11 1996/06/14 05:01:36 deraadt Exp $ */ +/* $OpenBSD: nlist.c,v 1.12 1996/06/17 06:40:53 etheisen Exp $ */ /* $NetBSD: nlist.c,v 1.7 1996/05/16 20:49:20 cgd Exp $ */ /* @@ -35,7 +35,8 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: nlist.c,v 1.11 1996/06/14 05:01:36 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: nlist.c,v 1.11 1996/06/14 05:01:36 deraadt Exp +$"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -289,50 +290,57 @@ __elf_fdnlist(fd, list) { register struct nlist *p; register caddr_t strtab; - register off_t symstroff, symoff; - register u_long symsize; - register int nent, cc, i; + register Elf32_Off symoff = 0, symstroff; + register Elf32_Word symsize, symstrsize; + register Elf32_Sword nent, cc, i; Elf32_Sym sbuf[1024]; Elf32_Sym *s; - size_t symstrsize; - char *shstr; - Elf32_Ehdr eh; - Elf32_Shdr *sh = NULL; + 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, &eh, sizeof(eh)) != sizeof(eh) || - !__elf_is_okay__(&eh) || + read(fd, &ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr) || + !__elf_is_okay__(&ehdr) || fstat(fd, &st) < 0) return (-1); - sh = (Elf32_Shdr *)malloc(sizeof(Elf32_Shdr) * eh.e_shnum); + /* calculate section header table size */ + shdr_size = ehdr.e_shentsize * ehdr.e_shnum; - if (lseek (fd, eh.e_shoff, SEEK_SET) < 0) - return(-1); + /* Make sure it's not too big to mmap */ + if (shdr_size > SIZE_T_MAX) { + errno = EFBIG; + return (-1); + } - if (read(fd, sh, sizeof(Elf32_Shdr) * eh.e_shnum) < - sizeof(Elf32_Shdr) * eh.e_shnum) + /* mmap section header table */ + shdr = (Elf32_Shdr *)mmap(NULL, (size_t)shdr_size, + PROT_READ, 0, fd, ehdr.e_shoff); + if (shdr == (Elf32_Shdr *)-1) return (-1); - shstr = (char *)malloc(sh[eh.e_shstrndx].sh_size); - if (lseek (fd, sh[eh.e_shstrndx].sh_offset, SEEK_SET) < 0) - return(-1); - if (read(fd, shstr, sh[eh.e_shstrndx].sh_size) < - sh[eh.e_shstrndx].sh_size) - return(-1); - - for (i = 0; i < eh.e_shnum; i++) { - if (strcmp (shstr + sh[i].sh_name, ".strtab") == 0) { - symstroff = sh[i].sh_offset; - symstrsize = sh[i].sh_size; - } - else if (strcmp (shstr + sh[i].sh_name, ".symtab") == 0) { - symoff = sh[i].sh_offset; - symsize = sh[i].sh_size; - } - } - + /* + * 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. */ /* XXX is this really possible? */ if (symstrsize > SIZE_T_MAX) { @@ -366,9 +374,17 @@ __elf_fdnlist(fd, list) p->n_value = 0; ++nent; } - if (lseek(fd, symoff, SEEK_SET) == -1) - return (-1); + /* 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, symoff, SEEK_SET) == -1) { + nent = -1; + goto done; + } + while (symsize > 0) { cc = MIN(symsize, sizeof(sbuf)); if (read(fd, sbuf, cc) != cc) @@ -380,25 +396,35 @@ __elf_fdnlist(fd, list) if (soff == 0) continue; for (p = list; !ISLAST(p); p++) { + /* + * XXX - ABI crap, they + * really fucked this up + * for MIPS and PowerPC + */ if (!strcmp(&strtab[soff], - eh.e_machine == EM_MIPS ? + ehdr.e_machine == EM_MIPS ? p->n_un.n_name+1 : p->n_un.n_name)) { p->n_value = s->st_value; - /*XXX type conversion is pretty rude... */ + /* XXX - type conversion */ + /* is pretty rude. */ switch(ELF32_ST_TYPE(s->st_info)) { - case STT_NOTYPE: - p->n_type = N_UNDF; - break; - case STT_FUNC: - p->n_type = N_TEXT; - break; - case STT_OBJECT: - p->n_type = N_DATA; - break; + 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) + if (ELF32_ST_BIND(s->st_info) == + STB_LOCAL) p->n_type = N_EXT; p->n_desc = 0; p->n_other = 0; @@ -408,6 +434,7 @@ __elf_fdnlist(fd, list) } } } + done: munmap(strtab, symstrsize); return (nent); |