new nlist routines
This commit is contained in:
parent
221bc33ccd
commit
e23e45bcfc
|
@ -1,5 +1,5 @@
|
|||
.\" Copyright (c) 1980, 1991 Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
.\" Copyright (c) 1980, 1991, 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
|
||||
|
@ -29,10 +29,9 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" from: @(#)nlist.3 6.2 (Berkeley) 4/19/91
|
||||
.\" $Id: nlist.3,v 1.3 1994/01/10 23:32:31 jtc Exp $
|
||||
.\" @(#)nlist.3 8.3 (Berkeley) 4/19/94
|
||||
.\"
|
||||
.Dd April 19, 1991
|
||||
.Dd April 19, 1994
|
||||
.Dt NLIST 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 1989 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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
|
||||
|
@ -32,92 +32,118 @@
|
|||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
/*static char *sccsid = "from: @(#)nlist.c 5.8 (Berkeley) 2/23/91";*/
|
||||
static char *rcsid = "$Id: nlist.c,v 1.3 1993/08/26 00:44:52 jtc Exp $";
|
||||
static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#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>
|
||||
|
||||
typedef struct nlist NLIST;
|
||||
#define _strx n_un.n_strx
|
||||
#define _name n_un.n_name
|
||||
#define ISVALID(p) (p->_name && p->_name[0])
|
||||
|
||||
int
|
||||
nlist(name, list)
|
||||
const char *name;
|
||||
NLIST *list;
|
||||
struct nlist *list;
|
||||
{
|
||||
register NLIST *p, *s;
|
||||
struct exec ebuf;
|
||||
FILE *fstr, *fsym;
|
||||
NLIST nbuf;
|
||||
off_t strings_offset, symbol_offset, symbol_size, lseek();
|
||||
int entries, len, maxlen;
|
||||
char sbuf[256];
|
||||
int fd, n;
|
||||
|
||||
entries = -1;
|
||||
fd = open(name, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return (-1);
|
||||
n = __fdnlist(fd, list);
|
||||
(void)close(fd);
|
||||
return (n);
|
||||
}
|
||||
|
||||
if (!(fsym = fopen(name, "r")))
|
||||
return(-1);
|
||||
if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 ||
|
||||
N_BADMAG(ebuf))
|
||||
goto done1;
|
||||
#define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
|
||||
|
||||
symbol_offset = N_SYMOFF(ebuf);
|
||||
symbol_size = ebuf.a_syms;
|
||||
strings_offset = symbol_offset + symbol_size;
|
||||
if (fseek(fsym, symbol_offset, SEEK_SET))
|
||||
goto done1;
|
||||
int
|
||||
__fdnlist(fd, list)
|
||||
register int fd;
|
||||
register struct nlist *list;
|
||||
{
|
||||
register struct nlist *p, *s;
|
||||
register caddr_t strtab;
|
||||
register off_t stroff, symoff;
|
||||
register u_long symsize;
|
||||
register int nent, cc;
|
||||
size_t strsize;
|
||||
struct nlist nbuf[1024];
|
||||
struct exec exec;
|
||||
struct stat st;
|
||||
|
||||
if (!(fstr = fopen(name, "r")))
|
||||
goto done1;
|
||||
if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
|
||||
read(fd, &exec, sizeof(exec)) != sizeof(exec) ||
|
||||
N_BADMAG(exec) || fstat(fd, &st) < 0)
|
||||
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) {
|
||||
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).
|
||||
*/
|
||||
strsize = st.st_size - stroff;
|
||||
strtab = mmap(NULL, (size_t)strsize, PROT_READ, 0, fd, stroff);
|
||||
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.
|
||||
*/
|
||||
for (p = list, entries = maxlen = 0; ISVALID(p); ++p, ++entries) {
|
||||
nent = 0;
|
||||
for (p = list; !ISLAST(p); ++p) {
|
||||
p->n_type = 0;
|
||||
p->n_other = 0;
|
||||
p->n_desc = 0;
|
||||
p->n_value = 0;
|
||||
if ((len = strlen(p->_name)) > maxlen)
|
||||
maxlen = len;
|
||||
}
|
||||
if (++maxlen > sizeof(sbuf)) { /* for the NULL */
|
||||
(void)fprintf(stderr, "nlist: symbol too large.\n");
|
||||
entries = -1;
|
||||
goto done2;
|
||||
++nent;
|
||||
}
|
||||
if (lseek(fd, symoff, SEEK_SET) == -1)
|
||||
return (-1);
|
||||
|
||||
for (s = &nbuf; symbol_size; symbol_size -= sizeof(NLIST)) {
|
||||
if (fread((char *)s, sizeof(NLIST), 1, fsym) != 1)
|
||||
goto done2;
|
||||
if (!s->_strx || s->n_type&N_STAB)
|
||||
continue;
|
||||
if (fseek(fstr, strings_offset + s->_strx, SEEK_SET))
|
||||
goto done2;
|
||||
(void)fread(sbuf, sizeof(sbuf[0]), maxlen, fstr);
|
||||
for (p = list; ISVALID(p); p++)
|
||||
if (!strcmp(p->_name, sbuf)) {
|
||||
p->n_value = s->n_value;
|
||||
p->n_type = s->n_type;
|
||||
p->n_desc = s->n_desc;
|
||||
p->n_other = s->n_other;
|
||||
if (!--entries)
|
||||
goto done2;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
if (--nent <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
done2: (void)fclose(fstr);
|
||||
done1: (void)fclose(fsym);
|
||||
return(entries);
|
||||
munmap(strtab, strsize);
|
||||
return (nent);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue