diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2004-10-09 20:26:58 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2004-10-09 20:26:58 +0000 |
commit | 2ced20bb78be745adf16d007a60bff20a8fadf99 (patch) | |
tree | 461f81ab0bf942e459a8aa76eb1f5b9aadc1ea19 /usr.bin/nm | |
parent | a4ed20475a9978c9bb289ccf04dfe087ff4cda69 (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/Makefile | 11 | ||||
-rw-r--r-- | usr.bin/nm/byte.c | 4 | ||||
-rw-r--r-- | usr.bin/nm/elf.c | 206 | ||||
-rw-r--r-- | usr.bin/nm/elfuncs.h | 47 | ||||
-rw-r--r-- | usr.bin/nm/nm.c | 281 | ||||
-rw-r--r-- | usr.bin/nm/util.h | 26 |
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; |