summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/nlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/gen/nlist.c')
-rw-r--r--lib/libc/gen/nlist.c83
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);
}
OpenPOWER on IntegriCloud