#include <sys/cdefs.h>
-#if __has_include(<a.out.h>)
-#include <a.out.h>
-#elif __has_include(<linux/a.out.h>)
-#include <linux/a.out.h>
-#endif
+struct nlist {
+ union {
+ char *n_name;
+ struct n_list *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+
+#define n_hash n_desc /* used internally by ld(1); XXX */
+
+/*
+ * Defines for n_type.
+ */
+#define N_UNDF 0x00 /* Undefined */
+#define N_ABS 0x02 /* Absolute address */
+#define N_TEXT 0x04 /* Text segment */
+#define N_DATA 0x06 /* Data segment */
+#define N_BSS 0x08 /* Bss segment */
+#define N_INDR 0x0a /* Alias definition */
+#define N_SIZE 0x0c /* Pseudo type, defines a symbol's size */
+#define N_COMM 0x12 /* Common reference */
+/* GNU extensions */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1a /* Bss set element symbol */
+#define N_SETV 0x1c /* Set vector symbol */
+/* end GNU extensions */
+#define N_FN 0x1e /* File name (N_EXT on) */
+#define N_WARN 0x1e /* Warning message (N_EXT off) */
+
+#define N_EXT 0x01 /* External (global) bit, OR'ed in */
+#define N_TYPE 0x1e /* Mask for all the type bits */
+#define N_STAB 0xe0 /* Mask for debugger symbols -- stab(5) */
+
+#define N_NAME(p) ((p)->n_un.n_name)
+
+/*
+ * Defines for n_other. It contains the ".type" (AUX) field in the least
+ * significant 4 bits, and the binding (for weak symbols) in the most
+ * significant 4 bits.
+ */
+#define N_AUX(p) ((p)->n_other & 0xf)
+#define N_BIND(p) (((unsigned int)(p)->n_other >> 4) & 0xf)
+#define N_OTHER(r, v) (((unsigned int)(r) << 4) | ((v) & 0xf))
+
+#define AUX_OBJECT 1 /* Data object */
+#define AUX_FUNC 2 /* Function */
+
+/*#define BIND_LOCAL 0 Not used */
+/*#define BIND_GLOBAL 1 Not used */
+#define BIND_WEAK 2 /* Weak binding */
+
+#define N_FORMAT "%08x" /* namelist value format; XXX */
__BEGIN_DECLS
extern int nlist(const char *filename, struct nlist *list);
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. 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.
*
* 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/cdefs.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <sys/file.h>
-#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
-#include <a.out.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <nlist.h>
-#if !defined(__NO_A_OUT_SUPPORT)
-#define _NLIST_DO_AOUT
-#endif
-#define _NLIST_DO_ELF
-
-#ifdef _NLIST_DO_ELF
#include "local-elf.h"
-#endif
#define SIZE_T_MAX 0xffffffffU
-#ifdef _NLIST_DO_AOUT
-static int __aout_fdnlist(int, struct nlist *);
-#ifndef N_SYMSIZE
-#define N_SYMSIZE(a) ((a).a_syms)
-#endif
-#endif
-#ifdef _NLIST_DO_ELF
-static int __elf_fdnlist(int, struct nlist *);
-#endif
-
-/* FIXME: This function is used by libkvm0, so we need to export it.
- It is not declared in the include files though. */
+/* Note: This function is used by libkvm0, so we need to export it.
+ * It is not declared in the include files though. */
int __fdnlist(int, struct nlist *);
-int
-nlist(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)(int fd, struct nlist *list);
-} nlist_fn[] = {
-#ifdef _NLIST_DO_AOUT
- { __aout_fdnlist },
-#endif
-#ifdef _NLIST_DO_ELF
- { __elf_fdnlist },
-#endif
-};
-
-int
-__fdnlist(int fd, struct nlist *list)
-{
- size_t i;
- int n = -1;
-
- 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
-static int
-__aout_fdnlist(int fd, struct nlist *list)
-{
- struct nlist *p, *symtab;
- caddr_t strtab, a_out_mmap;
- off_t stroff, symoff;
- unsigned long symsize;
- 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 within 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 = N_SYMSIZE(*exec);
- 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) {
- 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
-static void elf_sym_to_nlist(struct nlist *, Elf_Sym *, Elf_Shdr *, int);
-
/*
* __elf_is_okay__ - Determine if ehdr really
* is ELF and valid for the target platform.
return retval;
}
-static int
-__elf_fdnlist(int fd, struct nlist *list)
+/*
+ * Convert an Elf_Sym into an nlist structure. This fills in only the
+ * n_value and n_type members.
+ */
+static void
+elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum)
+{
+ nl->n_value = s->st_value;
+
+ switch (s->st_shndx) {
+ case SHN_UNDEF:
+ case SHN_COMMON:
+ nl->n_type = N_UNDF;
+ break;
+ case SHN_ABS:
+ nl->n_type = ELF_ST_TYPE(s->st_info) == STT_FILE ?
+ N_FN : N_ABS;
+ break;
+ default:
+ if (s->st_shndx >= shnum)
+ nl->n_type = N_UNDF;
+ else {
+ Elf_Shdr *sh = shdr + s->st_shndx;
+
+ nl->n_type = sh->sh_type == SHT_PROGBITS ?
+ (sh->sh_flags & SHF_WRITE ? N_DATA : N_TEXT) :
+ (sh->sh_type == SHT_NOBITS ? N_BSS : N_UNDF);
+ }
+ break;
+ }
+
+ if (ELF_ST_BIND(s->st_info) == STB_GLOBAL ||
+ ELF_ST_BIND(s->st_info) == STB_WEAK)
+ nl->n_type |= N_EXT;
+}
+
+int
+__fdnlist(int fd, struct nlist *list)
{
struct nlist *p;
Elf_Off symoff = 0, symstroff = 0;
return (nent);
}
-/*
- * Convert an Elf_Sym into an nlist structure. This fills in only the
- * n_value and n_type members.
- */
-static void
-elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum)
+int
+nlist(const char *name, struct nlist *list)
{
- nl->n_value = s->st_value;
-
- switch (s->st_shndx) {
- case SHN_UNDEF:
- case SHN_COMMON:
- nl->n_type = N_UNDF;
- break;
- case SHN_ABS:
- nl->n_type = ELF_ST_TYPE(s->st_info) == STT_FILE ?
- N_FN : N_ABS;
- break;
- default:
- if (s->st_shndx >= shnum)
- nl->n_type = N_UNDF;
- else {
- Elf_Shdr *sh = shdr + s->st_shndx;
-
- nl->n_type = sh->sh_type == SHT_PROGBITS ?
- (sh->sh_flags & SHF_WRITE ? N_DATA : N_TEXT) :
- (sh->sh_type == SHT_NOBITS ? N_BSS : N_UNDF);
- }
- break;
- }
+ int fd, n;
- if (ELF_ST_BIND(s->st_info) == STB_GLOBAL ||
- ELF_ST_BIND(s->st_info) == STB_WEAK)
- nl->n_type |= N_EXT;
+ fd = open(name, O_RDONLY, 0);
+ if (fd < 0)
+ return (-1);
+ n = __fdnlist(fd, list);
+ (void)close(fd);
+ return (n);
}
-#endif /* _NLIST_DO_ELF */