diff options
author | csgr <csgr@FreeBSD.org> | 1994-07-22 12:22:51 +0000 |
---|---|---|
committer | csgr <csgr@FreeBSD.org> | 1994-07-22 12:22:51 +0000 |
commit | a22e08d7639eb3fd20b2a774c131b065dfd85508 (patch) | |
tree | 598698785b5bd1ffd0cdf5522ece368a661b65f1 /lib/libc/gen/nlist.c | |
parent | cae4aac15c44f759dd6b6c877ede4cac060b4e77 (diff) | |
download | FreeBSD-src-a22e08d7639eb3fd20b2a774c131b065dfd85508.zip FreeBSD-src-a22e08d7639eb3fd20b2a774c131b065dfd85508.tar.gz |
Rewrite nlist to mmap the whole a.out file (at Davidg's suggestion).
This means that we don't have to do rounding calculations for page
boundaries. (We do all our accesses via the mmapped area now.)
Reviewed by:
Diffstat (limited to 'lib/libc/gen/nlist.c')
-rw-r--r-- | lib/libc/gen/nlist.c | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c index 874f26e..5dc3de1 100644 --- a/lib/libc/gen/nlist.c +++ b/lib/libc/gen/nlist.c @@ -68,40 +68,55 @@ __fdnlist(fd, list) register int fd; register struct nlist *list; { - register struct nlist *p, *s; - register caddr_t strtab; + register struct nlist *p, *symtab; + register caddr_t strtab, a_out_mmap; register off_t stroff, symoff; register u_long symsize; - register int nent, cc; + register int nent; size_t strsize; struct nlist nbuf[1024]; - struct exec exec; + struct exec * exec; struct stat st; - if (lseek(fd, (off_t)0, SEEK_SET) == -1 || - read(fd, &exec, sizeof(exec)) != sizeof(exec) || - N_BADMAG(exec) || fstat(fd, &st) < 0) + /* check that file is at least as large as struct exec! */ + if ((fstat(fd, &st) < 0) || (st.st_size < sizeof(struct exec))) return (-1); - symoff = N_SYMOFF(exec); - symsize = exec.a_syms; - stroff = symoff + symsize; - /* Check for files too large to mmap. */ - if (st.st_size - stroff > SIZE_T_MAX) { + if (st.st_size > 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). + * 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). */ - strsize = st.st_size - stroff; - strtab = mmap(NULL, (size_t)strsize, PROT_READ, 0, fd, stroff); - if (strtab == (char *)-1) + a_out_mmap = mmap(NULL, (size_t)st.st_size, PROT_READ, 0, fd, (off_t)0); + if (a_out_mmap == (char *)-1) 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 @@ -120,30 +135,26 @@ __fdnlist(fd, list) p->n_value = 0; ++nent; } - if (lseek(fd, symoff, SEEK_SET) == -1) - return (-1); while (symsize > 0) { - cc = MIN(symsize, sizeof(nbuf)); - if (read(fd, nbuf, cc) != cc) - break; - symsize -= cc; - for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) { - register int soff = s->n_un.n_strx; - - if (soff == 0 || (s->n_type & N_STAB) != 0) - continue; + 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 = s->n_value; - p->n_type = s->n_type; - p->n_desc = s->n_desc; - p->n_other = s->n_other; + 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(strtab, strsize); + munmap(a_out_mmap, (size_t)st.st_size); return (nent); } |