summaryrefslogtreecommitdiff
path: root/usr.bin/nm
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2004-10-09 20:26:58 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2004-10-09 20:26:58 +0000
commit2ced20bb78be745adf16d007a60bff20a8fadf99 (patch)
tree461f81ab0bf942e459a8aa76eb1f5b9aadc1ea19 /usr.bin/nm
parenta4ed20475a9978c9bb289ccf04dfe087ff4cda69 (diff)
move out elf code into elf.c and generate 32 and 64 versions of it;
allow operation on size-mixed host-target as well as ensianess for both a.out and elf (though a.out 64bit probably does not exist ;) tested on hppa-sparc64-i386-vax intermixen
Diffstat (limited to 'usr.bin/nm')
-rw-r--r--usr.bin/nm/Makefile11
-rw-r--r--usr.bin/nm/byte.c4
-rw-r--r--usr.bin/nm/elf.c206
-rw-r--r--usr.bin/nm/elfuncs.h47
-rw-r--r--usr.bin/nm/nm.c281
-rw-r--r--usr.bin/nm/util.h26
6 files changed, 371 insertions, 204 deletions
diff --git a/usr.bin/nm/Makefile b/usr.bin/nm/Makefile
index fec731c8eb3..ac566c9c0ef 100644
--- a/usr.bin/nm/Makefile
+++ b/usr.bin/nm/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.5 2004/01/05 01:27:22 mickey Exp $
+# $OpenBSD: Makefile,v 1.6 2004/10/09 20:26:57 mickey Exp $
TARGET_MACHINE_ARCH?= ${MACHINE_ARCH}
@@ -18,7 +18,16 @@ CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_VAX
.endif
PROG= nm
+SRCS= nm.c elf32.c elf64.c
+CLEANFILES+=elf32.c elf64.c
+CPPFLAGS+=-I${.CURDIR}
LINKS= ${BINDIR}/nm ${BINDIR}/size
MAN= nm.1 size.1
+elf32.c: ${.CURDIR}/elf.c
+ echo '#define ELFSIZE 32' | cat - $> > ${.TARGET}
+
+elf64.c: ${.CURDIR}/elf.c
+ echo '#define ELFSIZE 64' | cat - $> > ${.TARGET}
+
.include <bsd.prog.mk>
diff --git a/usr.bin/nm/byte.c b/usr.bin/nm/byte.c
index ab4d37ebfe9..b5556088bbf 100644
--- a/usr.bin/nm/byte.c
+++ b/usr.bin/nm/byte.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: byte.c,v 1.5 2004/01/28 18:05:10 deraadt Exp $ */
+/* $OpenBSD: byte.c,v 1.6 2004/10/09 20:26:57 mickey Exp $ */
/*
* Copyright (c) 1999
* Marc Espie. All rights reserved.
@@ -64,7 +64,7 @@ fix_header_order(struct exec *h)
}
static long
-fix_long_order(long l, int mid)
+fix_32_order(u_int32_t l, int mid)
{
if (byte_sex(mid) != BYTE_ORDER)
return swap32(l);
diff --git a/usr.bin/nm/elf.c b/usr.bin/nm/elf.c
index 9214eb12648..b5cd2e22aa4 100644
--- a/usr.bin/nm/elf.c
+++ b/usr.bin/nm/elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: elf.c,v 1.9 2004/10/09 20:17:52 mickey Exp $ */
+/* $OpenBSD: elf.c,v 1.10 2004/10/09 20:26:57 mickey Exp $ */
/*
* Copyright (c) 2003 Michael Shalayeff
@@ -26,7 +26,21 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if ELF_TARG_CLASS == ELFCLASS32
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <a.out.h>
+#include <elf_abi.h>
+#include <errno.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "elfuncs.h"
+#include "util.h"
+
+#if ELFSIZE == 32
#define swap_addr swap32
#define swap_off swap32
#define swap_sword swap32
@@ -35,7 +49,16 @@
#define swap_xword swap32
#define swap_half swap16
#define swap_quarter swap16
-#elif ELF_TARG_CLASS == ELFCLASS64
+#define elf_fix_header elf32_fix_header
+#define elf_load_shdrs elf32_load_shdrs
+#define elf_fix_shdrs elf32_fix_shdrs
+#define elf_fix_phdrs elf32_fix_phdrs
+#define elf_fix_sym elf32_fix_sym
+#define elf_size elf32_size
+#define elf_symload elf32_symload
+#define elf2nlist elf32_2nlist
+#define elf_shn2type elf32_shn2type
+#elif ELFSIZE == 64
#define swap_addr swap64
#define swap_off swap64
#ifdef __alpha__
@@ -49,6 +72,15 @@
#define swap_xword swap64
#define swap_half swap64
#define swap_quarter swap16
+#define elf_fix_header elf64_fix_header
+#define elf_load_shdrs elf64_load_shdrs
+#define elf_fix_shdrs elf64_fix_shdrs
+#define elf_fix_phdrs elf64_fix_phdrs
+#define elf_fix_sym elf64_fix_sym
+#define elf_size elf64_size
+#define elf_symload elf64_symload
+#define elf2nlist elf64_2nlist
+#define elf_shn2type elf64_shn2type
#else
#error "Unsupported ELF class"
#endif
@@ -81,6 +113,34 @@ elf_fix_header(Elf_Ehdr *eh)
return (1);
}
+Elf_Shdr *
+elf_load_shdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head)
+{
+ Elf_Shdr *shdr;
+
+ elf_fix_header(head);
+
+ if ((shdr = malloc(head->e_shentsize * head->e_shnum)) == NULL) {
+ warn("%s: malloc shdr", name);
+ return (NULL);
+ }
+
+ if (fseeko(fp, foff + head->e_shoff, SEEK_SET)) {
+ warn("%s: fseeko", name);
+ free(shdr);
+ return (NULL);
+ }
+
+ if (fread(shdr, head->e_shentsize, head->e_shnum, fp) != head->e_shnum) {
+ warnx("%s: premature EOF", name);
+ free(shdr);
+ return (NULL);
+ }
+
+ elf_fix_shdrs(head, shdr);
+ return (shdr);
+}
+
int
elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr)
{
@@ -280,3 +340,143 @@ elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr, struct nlist
return (0);
}
+
+int
+elf_size(Elf_Ehdr *head, Elf_Shdr *shdr,
+ u_long *ptext, u_long *pdata, u_long *pbss)
+{
+ int i;
+
+ *ptext = *pdata = *pbss = 0;
+
+ for (i = 0; i < head->e_shnum; i++) {
+ if (!(shdr[i].sh_flags & SHF_ALLOC))
+ ;
+ else if (shdr[i].sh_flags & SHF_EXECINSTR ||
+ !(shdr[i].sh_flags & SHF_WRITE))
+ *ptext += shdr[i].sh_size;
+ else if (shdr[i].sh_type == SHT_NOBITS)
+ *pbss += shdr[i].sh_size;
+ else
+ *pdata += shdr[i].sh_size;
+ }
+
+ return (0);
+}
+
+int
+elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh,
+ Elf_Shdr *shdr, struct nlist **pnames, struct nlist ***psnames,
+ size_t *pstabsize, int *pnrawnames)
+{
+ long symsize, shstrsize;
+ struct nlist *np;
+ Elf_Sym sbuf;
+ char *shstr;
+ int i;
+
+ shstrsize = shdr[eh->e_shstrndx].sh_size;
+ if ((shstr = malloc(shstrsize)) == NULL) {
+ warn("%s: malloc shsrt", name);
+ return (1);
+ }
+
+ if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) {
+ warn("%s: fseeko", name);
+ free(shstr);
+ return (1);
+ }
+
+ if (fread(shstr, 1, shstrsize, fp) != shstrsize) {
+ warnx("%s: premature EOF", name);
+ free(shstr);
+ return(1);
+ }
+
+ stab = NULL;
+ *pnames = NULL; *psnames = NULL;
+ for (i = 0; i < eh->e_shnum; i++) {
+ if (!strcmp(shstr + shdr[i].sh_name, ELF_STRTAB)) {
+ *pstabsize = shdr[i].sh_size;
+ if (*pstabsize > SIZE_T_MAX) {
+ warnx("%s: corrupt file", name);
+ free(shstr);
+ return (1);
+ }
+
+ MMAP(stab, *pstabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
+ fileno(fp), foff + shdr[i].sh_offset);
+ if (stab == MAP_FAILED) {
+ free(shstr);
+ return (1);
+ }
+ }
+ }
+ for (i = 0; i < eh->e_shnum; i++) {
+ if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) {
+ symsize = shdr[i].sh_size;
+ if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) {
+ warn("%s: fseeko", name);
+ if (stab)
+ MUNMAP(stab, *pstabsize);
+ free(shstr);
+ return (1);
+ }
+
+ *pnrawnames = symsize / sizeof(sbuf);
+ if ((*pnames = calloc(*pnrawnames, sizeof(*np))) == NULL) {
+ warn("%s: malloc names", name);
+ if (stab)
+ MUNMAP(stab, *pstabsize);
+ free(*pnames);
+ free(shstr);
+ return (1);
+ }
+ if ((*psnames = malloc(*pnrawnames * sizeof(np))) == NULL) {
+ warn("%s: malloc snames", name);
+ if (stab)
+ MUNMAP(stab, *pstabsize);
+ free(shstr);
+ free(*pnames);
+ free(*psnames);
+ return (1);
+ }
+
+ for (np = *pnames; symsize > 0; symsize -= sizeof(sbuf)) {
+ if (fread(&sbuf, 1, sizeof(sbuf),
+ fp) != sizeof(sbuf)) {
+ warn("%s: read symbol", name);
+ if (stab)
+ MUNMAP(stab, *pstabsize);
+ free(shstr);
+ free(*pnames);
+ free(*psnames);
+ return (1);
+ }
+
+ elf_fix_sym(eh, &sbuf);
+
+ if (!sbuf.st_name)
+ continue;
+
+ elf2nlist(&sbuf, eh, shdr, shstr, np);
+ np->n_value = sbuf.st_value;
+ np->n_un.n_strx = sbuf.st_name;
+ np++;
+ }
+ *pnrawnames = np - *pnames;
+ }
+ }
+
+ free(shstr);
+ if (stab == NULL) {
+ warnx("%s: no name list", name);
+ if (*pnames)
+ free(*pnames);
+ if (*psnames)
+ free(*psnames);
+ return (1);
+ }
+
+ return (0);
+}
diff --git a/usr.bin/nm/elfuncs.h b/usr.bin/nm/elfuncs.h
new file mode 100644
index 00000000000..269833066f4
--- /dev/null
+++ b/usr.bin/nm/elfuncs.h
@@ -0,0 +1,47 @@
+/* $OpenBSD: elfuncs.h,v 1.1 2004/10/09 20:26:57 mickey Exp $ */
+
+/*
+ * Copyright (c) 2004 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+extern char *stab;
+
+int elf32_fix_header(Elf32_Ehdr *eh);
+Elf32_Shdr*elf32_load_shdrs(const char *, FILE *, off_t, Elf32_Ehdr *);
+int elf32_fix_shdrs(Elf32_Ehdr *eh, Elf32_Shdr *shdr);
+int elf32_fix_phdrs(Elf32_Ehdr *eh, Elf32_Phdr *phdr);
+int elf32_fix_sym(Elf32_Ehdr *eh, Elf32_Sym *sym);
+int elf32_size(Elf32_Ehdr *, Elf32_Shdr *, u_long *, u_long *, u_long *);
+int elf32_symload(const char *, FILE *, off_t, Elf32_Ehdr *, Elf32_Shdr *,
+ struct nlist **, struct nlist ***, size_t *, int *);
+
+int elf64_fix_header(Elf64_Ehdr *eh);
+Elf64_Shdr*elf64_load_shdrs(const char *, FILE *, off_t, Elf64_Ehdr *);
+int elf64_fix_shdrs(Elf64_Ehdr *eh, Elf64_Shdr *shdr);
+int elf64_fix_phdrs(Elf64_Ehdr *eh, Elf64_Phdr *phdr);
+int elf64_fix_sym(Elf64_Ehdr *eh, Elf64_Sym *sym);
+int elf64_size(Elf64_Ehdr *, Elf64_Shdr *, u_long *, u_long *, u_long *);
+int elf64_symload(const char *, FILE *, off_t, Elf64_Ehdr *, Elf64_Shdr *,
+ struct nlist **, struct nlist ***, size_t *, int *);
diff --git a/usr.bin/nm/nm.c b/usr.bin/nm/nm.c
index 4049c752cad..3837f241681 100644
--- a/usr.bin/nm/nm.c
+++ b/usr.bin/nm/nm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nm.c,v 1.26 2004/07/11 07:08:46 mickey Exp $ */
+/* $OpenBSD: nm.c,v 1.27 2004/10/09 20:26:57 mickey Exp $ */
/* $NetBSD: nm.c,v 1.7 1996/01/14 23:04:03 pk Exp $ */
/*
@@ -42,7 +42,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)nm.c 8.1 (Berkeley) 6/6/93";
#endif
-static const char rcsid[] = "$OpenBSD: nm.c,v 1.26 2004/07/11 07:08:46 mickey Exp $";
+static const char rcsid[] = "$OpenBSD: nm.c,v 1.27 2004/10/09 20:26:57 mickey Exp $";
#include <sys/param.h>
#include <sys/mman.h>
@@ -63,9 +63,11 @@ static const char rcsid[] = "$OpenBSD: nm.c,v 1.26 2004/07/11 07:08:46 mickey Ex
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
-/* XXX get shared code to handle byte-order swaps */
+#include "elfuncs.h"
+#include "util.h"
+
+/* XXX get shared code to handle a.out byte-order swaps */
#include "byte.c"
-#include "elf.c"
#ifdef MID_MACHINE_OVERRIDE
#undef MID_MACHINE
@@ -77,9 +79,19 @@ static const char rcsid[] = "$OpenBSD: nm.c,v 1.26 2004/07/11 07:08:46 mickey Ex
union hdr {
struct exec aout;
- Elf_Ehdr elf;
+ Elf32_Ehdr elf32;
+ Elf64_Ehdr elf64;
};
+/* a funky nlist overload for reading 32bit a.out on 64bit toys */
+struct nlist32 {
+ u_int32_t strx;
+ u_int8_t type;
+ u_int8_t other;
+ u_int16_t desc;
+ u_int32_t value;
+} __packed;
+
int armap;
int demangle;
int non_object_warning;
@@ -116,7 +128,6 @@ int process_file(int, const char *);
int show_archive(int, const char *, FILE *);
int show_file(int, int, const char *, FILE *fp, off_t, union hdr *);
void print_symbol(const char *, struct nlist *, int);
-int elf_symload(const char *, FILE *, off_t, Elf_Ehdr *, Elf_Shdr *);
#define OPTSTRING_NM "aABCegnoprsuvVw"
const struct option longopts_nm[] = {
@@ -265,7 +276,7 @@ process_file(int count, const char *fname)
bzero(&exec_head, sizeof(exec_head));
bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);
if (bytes < sizeof(exec_head)) {
- if (bytes < sizeof(exec_head.aout) || IS_ELF(exec_head.elf)) {
+ if (bytes < sizeof(exec_head.aout) || IS_ELF(exec_head.elf32)) {
warnx("%s: bad format", fname);
(void)fclose(fp);
return(1);
@@ -274,7 +285,7 @@ process_file(int count, const char *fname)
rewind(fp);
/* this could be an archive */
- if (!IS_ELF(exec_head.elf) && N_BADMAG(exec_head.aout)) {
+ if (!IS_ELF(exec_head.elf32) && N_BADMAG(exec_head.aout)) {
if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
strncmp(magic, ARMAG, SARMAG)) {
warnx("%s: not object file or archive", fname);
@@ -351,29 +362,6 @@ mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)
return (0);
}
-#define MMAP(ptr, len, prot, flags, fd, off) do { \
- if ((ptr = mmap(NULL, len, prot, flags, fd, off)) == MAP_FAILED) { \
- usemmap = 0; \
- if (errno != EINVAL) \
- warn("mmap"); \
- else if ((ptr = malloc(len)) == NULL) { \
- ptr = MAP_FAILED; \
- warn("malloc"); \
- } else if (pread(fd, ptr, len, off) != len) { \
- free(ptr); \
- ptr = MAP_FAILED; \
- warn("pread"); \
- } \
- } \
-} while (0)
-
-#define MUNMAP(addr, len) do { \
- if (usemmap) \
- munmap(addr, len); \
- else \
- free(addr); \
-} while (0)
-
/*
* show_symtab()
* show archive ranlib index (fs5)
@@ -624,10 +612,7 @@ skip: if (fseeko(fp, last_ar_off + even(mmbrlen), SEEK_SET)) {
return(rval);
}
-struct nlist *names;
-struct nlist **snames;
char *stab;
-int nnames, nrawnames, stabsize;
/*
* show_file()
@@ -639,65 +624,51 @@ int
show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
{
u_long text, data, bss, total;
- struct nlist *np;
- Elf_Shdr *shdr;
+ struct nlist *np, *names, **snames;
+ int i, aout, nrawnames, nnames;
+ size_t stabsize;
off_t staboff;
- int i, aout;
aout = 0;
- if (IS_ELF(head->elf) &&
- head->elf.e_ident[EI_CLASS] == ELF_TARG_CLASS &&
- head->elf.e_ident[EI_VERSION] == ELF_TARG_VER) {
+ if (IS_ELF(head->elf32) &&
+ head->elf32.e_ident[EI_CLASS] == ELFCLASS32 &&
+ head->elf32.e_ident[EI_VERSION] == ELF_TARG_VER) {
+ void *shdr;
- elf_fix_header(&head->elf);
-
- if ((shdr = malloc(head->elf.e_shentsize *
- head->elf.e_shnum)) == NULL) {
- warn("%s: malloc shdr", name);
+ if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
return (1);
- }
- if (fseeko(fp, foff + head->elf.e_shoff, SEEK_SET)) {
- warn("%s: fseeko", name);
- free(shdr);
- return (1);
- }
+ i = issize?
+ elf32_size(&head->elf32, shdr, &text, &data, &bss) :
+ elf32_symload(name, fp, foff, &head->elf32, shdr,
+ &names, &snames, &stabsize, &nrawnames);
+ free(shdr);
+ if (i)
+ return (i);
- if (fread(shdr, head->elf.e_shentsize, head->elf.e_shnum,
- fp) != head->elf.e_shnum) {
- warnx("%s: premature EOF", name);
- free(shdr);
- return(1);
- }
+ } else if (IS_ELF(head->elf64) &&
+ head->elf64.e_ident[EI_CLASS] == ELFCLASS64 &&
+ head->elf64.e_ident[EI_VERSION] == ELF_TARG_VER) {
+ void *shdr;
- elf_fix_shdrs(&head->elf, shdr);
+ if (!(shdr = elf64_load_shdrs(name, fp, foff, &head->elf64)))
+ return (1);
- if (issize) {
- text = data = bss = 0;
- for (i = 0; i < head->elf.e_shnum; i++) {
- if (!(shdr[i].sh_flags & SHF_ALLOC))
- ;
- else if (shdr[i].sh_flags & SHF_EXECINSTR ||
- !(shdr[i].sh_flags & SHF_WRITE))
- text += shdr[i].sh_size;
- else if (shdr[i].sh_type == SHT_NOBITS)
- bss += shdr[i].sh_size;
- else
- data += shdr[i].sh_size;
- }
- free(shdr);
- } else {
- i = elf_symload(name, fp, foff, &head->elf, shdr);
- free(shdr);
- if (i)
- return (i);
- }
+ i = issize?
+ elf64_size(&head->elf64, shdr, &text, &data, &bss) :
+ elf64_symload(name, fp, foff, &head->elf64, shdr,
+ &names, &snames, &stabsize, &nrawnames);
+ free(shdr);
+ if (i)
+ return (i);
} else if (BAD_OBJECT(head->aout)) {
if (warn_fmt)
warnx("%s: bad format", name);
return (1);
} else do {
+ u_int32_t w;
+
aout++;
fix_header_order(&head->aout);
@@ -720,25 +691,54 @@ show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union
return(1);
}
+#ifdef __LP64__
+ nrawnames = head->aout.a_syms / sizeof(struct nlist32);
+#else
+ nrawnames = head->aout.a_syms / sizeof(*names);
+#endif
/* get memory for the symbol table */
- if ((names = malloc(head->aout.a_syms)) == NULL) {
+ if ((names = malloc(nrawnames * sizeof(struct nlist))) == NULL) {
warn("%s: malloc names", name);
return (1);
}
- nrawnames = head->aout.a_syms / sizeof(*names);
+
if ((snames = malloc(nrawnames * sizeof(struct nlist *))) == NULL) {
warn("%s: malloc snames", name);
free(names);
return (1);
}
+#ifdef __LP64__
+ for (np = names, i = nrawnames; i--; np++) {
+ struct nlist32 nl32;
+
+ if (fread(&nl32, sizeof(nl32), 1, fp) != 1) {
+ warnx("%s: cannot read symbol table", name);
+ free(snames);
+ free(names);
+ return (1);
+ }
+ np->n_type = nl32.type;
+ np->n_other = nl32.other;
+ if (byte_sex(N_GETMID(head->aout)) != BYTE_ORDER) {
+ np->n_un.n_strx = swap32(nl32.strx);
+ np->n_desc = swap16(nl32.desc);
+ np->n_value = swap32(nl32.value);
+ } else {
+ np->n_un.n_strx = nl32.strx;
+ np->n_desc = nl32.desc;
+ np->n_value = nl32.value;
+ }
+ }
+#else
if (fread(names, head->aout.a_syms, 1, fp) != 1) {
warnx("%s: cannot read symbol table", name);
free(snames);
free(names);
- return(1);
+ return (1);
}
fix_nlists_order(names, nrawnames, N_GETMID(head->aout));
+#endif
staboff = ftello(fp);
/*
@@ -746,13 +746,13 @@ show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union
* The first 4-byte-integer gives the total size of the
* string table _including_ the size specification itself.
*/
- if (fread(&stabsize, sizeof(stabsize), (size_t)1, fp) != 1) {
+ if (fread(&w, sizeof(w), (size_t)1, fp) != 1) {
warnx("%s: cannot read stab size", name);
free(snames);
free(names);
return(1);
}
- stabsize = fix_long_order(stabsize, N_GETMID(head->aout));
+ stabsize = fix_32_order(w, N_GETMID(head->aout));
MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
fileno(fp), staboff);
if (stab == MAP_FAILED) {
@@ -849,121 +849,6 @@ show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union
return(0);
}
-int
-elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, Elf_Shdr *shdr)
-{
- long symsize, shstrsize;
- struct nlist *np;
- Elf_Sym sbuf;
- char *shstr;
- int i;
-
- shstrsize = shdr[eh->e_shstrndx].sh_size;
- if ((shstr = malloc(shstrsize)) == NULL) {
- warn("%s: malloc shsrt", name);
- return (1);
- }
-
- if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) {
- warn("%s: fseeko", name);
- free(shstr);
- return (1);
- }
-
- if (fread(shstr, 1, shstrsize, fp) != shstrsize) {
- warnx("%s: premature EOF", name);
- free(shstr);
- return(1);
- }
-
- stab = NULL;
- names = NULL; snames = NULL;
- for (i = 0; i < eh->e_shnum; i++) {
- if (!strcmp(shstr + shdr[i].sh_name, ELF_STRTAB)) {
- stabsize = shdr[i].sh_size;
- if (stabsize > SIZE_T_MAX) {
- warnx("%s: corrupt file", name);
- free(shstr);
- return (1);
- }
-
- MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
- fileno(fp), foff + shdr[i].sh_offset);
- if (stab == MAP_FAILED) {
- free(shstr);
- return (1);
- }
- }
- }
- for (i = 0; i < eh->e_shnum; i++) {
- if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) {
- symsize = shdr[i].sh_size;
- if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) {
- warn("%s: fseeko", name);
- if (stab)
- MUNMAP(stab, stabsize);
- free(shstr);
- return (1);
- }
-
- nrawnames = symsize / sizeof(sbuf);
- if ((names = calloc(nrawnames, sizeof(*np))) == NULL) {
- warn("%s: malloc names", name);
- if (stab)
- MUNMAP(stab, stabsize);
- free(names);
- free(shstr);
- return (1);
- }
- if ((snames = malloc(nrawnames * sizeof(np))) == NULL) {
- warn("%s: malloc snames", name);
- if (stab)
- MUNMAP(stab, stabsize);
- free(shstr);
- free(names);
- free(snames);
- return (1);
- }
-
- for (np = names; symsize > 0; symsize -= sizeof(sbuf)) {
- if (fread(&sbuf, 1, sizeof(sbuf),
- fp) != sizeof(sbuf)) {
- warn("%s: read symbol", name);
- if (stab)
- MUNMAP(stab, stabsize);
- free(shstr);
- free(names);
- free(snames);
- return (1);
- }
-
- elf_fix_sym(eh, &sbuf);
-
- if (!sbuf.st_name)
- continue;
-
- elf2nlist(&sbuf, eh, shdr, shstr, np);
- np->n_value = sbuf.st_value;
- np->n_un.n_strx = sbuf.st_name;
- np++;
- }
- nrawnames = np - names;
- }
- }
-
- free(shstr);
- if (stab == NULL) {
- warnx("%s: no name list", name);
- if (names)
- free(names);
- if (snames)
- free(snames);
- return (1);
- }
-
- return (0);
-}
-
char *
symname(struct nlist *sym)
{
diff --git a/usr.bin/nm/util.h b/usr.bin/nm/util.h
new file mode 100644
index 00000000000..bdc6636122f
--- /dev/null
+++ b/usr.bin/nm/util.h
@@ -0,0 +1,26 @@
+/* $OpenBSD: util.h,v 1.1 2004/10/09 20:26:57 mickey Exp $ */
+
+#define MMAP(ptr, len, prot, flags, fd, off) do { \
+ if ((ptr = mmap(NULL, len, prot, flags, fd, off)) == MAP_FAILED) { \
+ usemmap = 0; \
+ if (errno != EINVAL) \
+ warn("mmap"); \
+ else if ((ptr = malloc(len)) == NULL) { \
+ ptr = MAP_FAILED; \
+ warn("malloc"); \
+ } else if (pread(fd, ptr, len, off) != len) { \
+ free(ptr); \
+ ptr = MAP_FAILED; \
+ warn("pread"); \
+ } \
+ } \
+} while (0)
+
+#define MUNMAP(addr, len) do { \
+ if (usemmap) \
+ munmap(addr, len); \
+ else \
+ free(addr); \
+} while (0)
+
+extern int usemmap;