summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2004-01-05 01:27:23 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2004-01-05 01:27:23 +0000
commitdfc9ddd923d2d6ea7c0d9435c946ed7580b0c6f3 (patch)
tree94a87b24a1478fc9452f30921277617bd67469b8 /usr.bin
parent726cebb18378814de049deadea0b06bcd4e46a46 (diff)
nm digs elf and merges w/ size; millert@ ok
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/Makefile4
-rw-r--r--usr.bin/nm/Makefile4
-rw-r--r--usr.bin/nm/elf.c236
-rw-r--r--usr.bin/nm/nm.19
-rw-r--r--usr.bin/nm/nm.c886
-rw-r--r--usr.bin/nm/size.1 (renamed from usr.bin/size/size.1)2
-rw-r--r--usr.bin/size/Makefile24
-rw-r--r--usr.bin/size/size.c392
8 files changed, 937 insertions, 620 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
index 99336903c66..75034224245 100644
--- a/usr.bin/Makefile
+++ b/usr.bin/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.86 2003/09/26 07:33:03 otto Exp $
+# $OpenBSD: Makefile,v 1.87 2004/01/05 01:27:22 mickey Exp $
.include <bsd.own.mk>
@@ -29,7 +29,7 @@ SUBDIR+=ypcat ypmatch ypwhich
.endif
.if (${ELF_TOOLCHAIN:L} == "no")
-SUBDIR+= ar nm ranlib size strip strings
+SUBDIR+= ar nm ranlib strip strings
.endif
.if make(clean) || make(cleandir) || make(obj)
diff --git a/usr.bin/nm/Makefile b/usr.bin/nm/Makefile
index 6dd341df3d3..fec731c8eb3 100644
--- a/usr.bin/nm/Makefile
+++ b/usr.bin/nm/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.4 1998/05/11 20:34:56 niklas Exp $
+# $OpenBSD: Makefile,v 1.5 2004/01/05 01:27:22 mickey Exp $
TARGET_MACHINE_ARCH?= ${MACHINE_ARCH}
@@ -18,5 +18,7 @@ CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_VAX
.endif
PROG= nm
+LINKS= ${BINDIR}/nm ${BINDIR}/size
+MAN= nm.1 size.1
.include <bsd.prog.mk>
diff --git a/usr.bin/nm/elf.c b/usr.bin/nm/elf.c
new file mode 100644
index 00000000000..da99cf0513c
--- /dev/null
+++ b/usr.bin/nm/elf.c
@@ -0,0 +1,236 @@
+/* $OpenBSD: elf.c,v 1.1 2004/01/05 01:27:22 mickey Exp $ */
+
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#if ELF_TARG_CLASS == ELFCLASS32
+#define swap_addr swap32
+#define swap_off swap32
+#define swap_sword swap32
+#define swap_word swap32
+#define swap_sxword swap32
+#define swap_xword swap32
+#define swap_half swap16
+#define swap_quarter swap16
+#elif ELF_TARG_CLASS == ELFCLASS64
+#define swap_addr swap64
+#define swap_off swap64
+#ifdef __alpha__
+#define swap_sword swap64
+#define swap_word swap64
+#else
+#define swap_sword swap32
+#define swap_word swap32
+#endif
+#define swap_sxword swap64
+#define swap_xword swap64
+#define swap_half swap64
+#define swap_quarter swap16
+#else
+#error "Unsupported ELF class"
+#endif
+
+int
+elf_fix_header(Elf_Ehdr *eh)
+{
+ /* nothing to do */
+ if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
+ return (0);
+
+ eh->e_type = swap16(eh->e_type);
+ eh->e_machine = swap16(eh->e_machine);
+ eh->e_version = swap32(eh->e_version);
+ eh->e_entry = swap_addr(eh->e_entry);
+ eh->e_phoff = swap_off(eh->e_phoff);
+ eh->e_shoff = swap_off(eh->e_shoff);
+ eh->e_flags = swap32(eh->e_flags);
+ eh->e_ehsize = swap16(eh->e_ehsize);
+ eh->e_phentsize = swap16(eh->e_phentsize);
+ eh->e_phnum = swap16(eh->e_phnum);
+ eh->e_shentsize = swap16(eh->e_shentsize);
+ eh->e_shnum = swap16(eh->e_shnum);
+ eh->e_shstrndx = swap16(eh->e_shstrndx);
+
+ return (1);
+}
+
+int
+elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr)
+{
+ int i;
+
+ /* nothing to do */
+ if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
+ return (0);
+
+ for (i = eh->e_shnum; i--; shdr++) {
+ shdr->sh_name = swap32(shdr->sh_name);
+ shdr->sh_type = swap32(shdr->sh_type);
+ shdr->sh_flags = swap_xword(shdr->sh_flags);
+ shdr->sh_addr = swap_addr(shdr->sh_addr);
+ shdr->sh_offset = swap_off(shdr->sh_offset);
+ shdr->sh_size = swap_xword(shdr->sh_size);
+ shdr->sh_link = swap32(shdr->sh_link);
+ shdr->sh_info = swap32(shdr->sh_info);
+ shdr->sh_addralign = swap_xword(shdr->sh_addralign);
+ shdr->sh_entsize = swap_xword(shdr->sh_entsize);
+ }
+
+ return (1);
+}
+
+int
+elf_fix_phdrs(Elf_Ehdr *eh, Elf_Phdr *phdr)
+{
+ int i;
+
+ /* nothing to do */
+ if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
+ return (0);
+
+ for (i = eh->e_phnum; i--; phdr++) {
+ phdr->p_type = swap32(phdr->p_type);
+ phdr->p_flags = swap32(phdr->p_flags);
+ phdr->p_offset = swap_off(phdr->p_offset);
+ phdr->p_vaddr = swap_addr(phdr->p_vaddr);
+ phdr->p_paddr = swap_addr(phdr->p_paddr);
+ phdr->p_filesz = swap_xword(phdr->p_filesz);
+ phdr->p_memsz = swap_xword(phdr->p_memsz);
+ phdr->p_align = swap_xword(phdr->p_align);
+ }
+
+ return (1);
+}
+
+int
+elf_fix_sym(Elf_Ehdr *eh, Elf_Sym *sym)
+{
+ /* nothing to do */
+ if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
+ return (0);
+
+ sym->st_name = swap32(sym->st_name);
+ sym->st_shndx = swap16(sym->st_shndx);
+ sym->st_value = swap_addr(sym->st_value);
+ sym->st_size = swap_xword(sym->st_size);
+
+ return (1);
+}
+
+/*
+ * Devise nlist's type from Elf_Sym.
+ * XXX this task is done as well in libc and kvm_mkdb.
+ */
+int
+elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr, struct nlist *np)
+{
+ /* extern char *stab; */
+ unsigned char n_type;
+ const char *sn;
+
+ if (sym->st_shndx < eh->e_shnum)
+ sn = shstr + shdr[sym->st_shndx].sh_name;
+ else
+ sn = "";
+
+/* printf("%s 0x%x %s(0x%x)\n", stab + sym->st_name, sym->st_info, sn, sym->st_shndx); */
+ switch(ELF_ST_TYPE(sym->st_info)) {
+ case STT_NOTYPE:
+ switch (sym->st_shndx) {
+ case SHN_UNDEF:
+ np->n_type = N_UNDF | N_EXT;
+ break;
+ case SHN_ABS:
+ np->n_type = N_ABS;
+ break;
+ case SHN_COMMON:
+ np->n_type = N_COMM;
+ break;
+ default:
+ if (sym->st_shndx >= eh->e_shnum)
+ np->n_type = N_COMM | N_EXT;
+ else if (!strcmp(sn, ELF_TEXT))
+ np->n_type = N_TEXT;
+ else if (!strcmp(sn, ELF_RODATA)) {
+ np->n_type = N_DATA;
+ np->n_other = 'r';
+ } else if (!strcmp(sn, ELF_DATA))
+ np->n_type = N_DATA;
+ else if (!strcmp(sn, ELF_BSS))
+ np->n_type = N_BSS;
+ else
+ np->n_other = '?';
+ break;
+ }
+ break;
+
+ case STT_FUNC:
+ np->n_type = N_TEXT;
+ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
+ np->n_type = N_INDR;
+ np->n_other = 'W';
+ } else if (sym->st_shndx == SHN_UNDEF)
+ np->n_type = N_UNDF | N_EXT;
+ else if (strcmp(sn, ELF_TEXT)) /* XXX GNU compat */
+ np->n_other = '?';
+ break;
+
+ case STT_OBJECT:
+ np->n_type = N_DATA;
+ if (sym->st_shndx == SHN_ABS)
+ np->n_type = N_ABS;
+ if (sym->st_shndx == SHN_COMMON)
+ np->n_type = N_COMM;
+ else if (sym->st_shndx >= eh->e_shnum)
+ break;
+ else if (!strcmp(sn, ELF_BSS))
+ np->n_type = N_BSS;
+ else if (!strcmp(sn, ELF_RODATA))
+ np->n_other = 'r';
+ break;
+
+ case STT_FILE:
+ np->n_type = N_FN | N_EXT;
+ break;
+
+ /* XXX how about cross-nm then ? */
+#ifdef STT_PARISC_MILLI
+ case STT_PARISC_MILLI:
+ np->n_type = N_TEXT;
+ break;
+#endif
+ default:
+ np->n_other = '?';
+ break;
+ }
+ if (np->n_type != N_UNDF && ELF_ST_BIND(sym->st_info) != STB_LOCAL) {
+ np->n_type |= N_EXT;
+ if (np->n_other)
+ np->n_other = toupper(np->n_other);
+ }
+
+ return (0);
+}
diff --git a/usr.bin/nm/nm.1 b/usr.bin/nm/nm.1
index ad486b304e1..41f9c307323 100644
--- a/usr.bin/nm/nm.1
+++ b/usr.bin/nm/nm.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: nm.1,v 1.12 2003/06/03 02:56:14 millert Exp $
+.\" $OpenBSD: nm.1,v 1.13 2004/01/05 01:27:22 mickey Exp $
.\" $NetBSD: nm.1,v 1.3 1995/08/31 23:41:58 jtc Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
@@ -38,7 +38,7 @@
.Nd display name list (symbol table)
.Sh SYNOPSIS
.Nm nm
-.Op Fl aCegnopruw
+.Op Fl aCegnoprsuVw
.Op Ar file ...
.Sh DESCRIPTION
The symbol table (name list) of each object in
@@ -76,8 +76,12 @@ Display full path or library name of object on every line.
Do not sort at all.
.It Fl r
Reverse order sort.
+.It Fl s
+Show archive index.
.It Fl u
Display undefined symbols only.
+.It Fl V
+Show program version.
.It Fl w
Warn about non-object archive members.
Normally,
@@ -118,6 +122,7 @@ The output is sorted alphabetically.
.Xr ar 1 ,
.Xr a.out 5 ,
.Xr ar 5 ,
+.Xr elf 5 ,
.Xr stab 5
.Sh HISTORY
An
diff --git a/usr.bin/nm/nm.c b/usr.bin/nm/nm.c
index cb69fc4c2fa..78ffb7d1ece 100644
--- a/usr.bin/nm/nm.c
+++ b/usr.bin/nm/nm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nm.c,v 1.19 2003/06/10 22:20:49 deraadt Exp $ */
+/* $OpenBSD: nm.c,v 1.20 2004/01/05 01:27:22 mickey Exp $ */
/* $NetBSD: nm.c,v 1.7 1996/01/14 23:04:03 pk Exp $ */
/*
@@ -34,21 +34,20 @@
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1989, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
-#ifndef lint
#if 0
-static char sccsid[] = "@(#)nm.c 8.1 (Berkeley) 6/6/93";
+static const char sccsid[] = "@(#)nm.c 8.1 (Berkeley) 6/6/93";
#endif
-static char rcsid[] = "$OpenBSD: nm.c,v 1.19 2003/06/10 22:20:49 deraadt Exp $";
-#endif /* not lint */
+static const char rcsid[] = "$OpenBSD: nm.c,v 1.20 2004/01/05 01:27:22 mickey Exp $";
#include <sys/param.h>
-#include <sys/types.h>
+#include <sys/mman.h>
#include <a.out.h>
+#include <elf_abi.h>
#include <stab.h>
#include <ar.h>
#include <ranlib.h>
@@ -56,21 +55,43 @@ static char rcsid[] = "$OpenBSD: nm.c,v 1.19 2003/06/10 22:20:49 deraadt Exp $";
#include <err.h>
#include <ctype.h>
#include <link.h>
+#ifdef __ELF__
+#include <link_aout.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
/* XXX get shared code to handle byte-order swaps */
#include "byte.c"
+#include "elf.c"
+#ifdef MID_MACHINE_OVERRIDE
+#undef MID_MACHINE
+#define MID_MACHINE MID_MACHINE_OVERRIDE
+#endif
-int demangle = 0;
-int ignore_bad_archive_entries = 1;
+#define SYMTABMAG "/ "
+#define STRTABMAG "//"
+
+union hdr {
+ struct exec aout;
+ Elf_Ehdr elf;
+};
+
+int armap;
+int demangle;
+int non_object_warning;
int print_only_external_symbols;
int print_only_undefined_symbols;
int print_all_symbols;
int print_file_each_line;
-int show_extensions = 0;
-int fcount;
+int show_extensions;
+int issize;
+
+/* size vars */
+unsigned long total_text, total_data, total_bss, total_total;
+int non_object_warning, print_totals;
int rev;
int fname(const void *, const void *);
@@ -79,31 +100,64 @@ int value(const void *, const void *);
int (*sfunc)(const void *, const void *) = fname;
char *otherstring(struct nlist *);
char *typestring(unsigned int);
-char typeletter(unsigned int);
-
+char typeletter(struct nlist *, int);
/* some macros for symbol type (nlist.n_type) handling */
#define IS_DEBUGGER_SYMBOL(x) ((x) & N_STAB)
#define IS_EXTERNAL(x) ((x) & N_EXT)
#define SYMBOL_TYPE(x) ((x) & (N_TYPE | N_STAB))
-void *emalloc(size_t);
void pipe2cppfilt(void);
void usage(void);
char *symname(struct nlist *);
-void print_symbol(const char *, struct nlist *);
+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[] = {
+ { "debug-syms", no_argument, 0, 'a' },
+ { "demangle", no_argument, 0, 'C' },
+/* { "dynamic", no_argument, 0, 'D' }, */
+ { "extern-only", no_argument, 0, 'g' },
+/* { "line-numbers", no_argument, 0, 'l' }, */
+ { "no-sort", no_argument, 0, 'p' },
+ { "numeric-sort", no_argument, 0, 'n' },
+ { "print-armap", no_argument, 0, 's' },
+ { "print-file-name", no_argument, 0, 'o' },
+ { "reverse-sort", no_argument, 0, 'r' },
+/* { "size-sort", no_argument, &szval, 1 }, */
+ { "undefined-only", no_argument, 0, 'u' },
+ { "version", no_argument, 0, 'V' },
+ { "help", no_argument, 0, '?' },
+ { NULL }
+};
/*
* main()
* parse command line, execute process_file() for each file
* specified on the command line.
*/
+int
main(int argc, char *argv[])
{
+ extern char *__progname;
extern int optind;
- int ch, errors;
+ const char *optstr;
+ const struct option *lopts;
+ int ch, eval;
+
+ optstr = OPTSTRING_NM;
+ lopts = longopts_nm;
+ if (!strcmp(__progname, "size")) {
+ issize++;
+ optstr = "tw";
+ lopts = NULL;
+ }
- while ((ch = getopt(argc, argv, "aBCegnopruw")) != -1) {
+ while ((ch = getopt_long(argc, argv, optstr, lopts, NULL)) != -1) {
switch (ch) {
case 'a':
print_all_symbols = 1;
@@ -121,8 +175,10 @@ main(int argc, char *argv[])
print_only_external_symbols = 1;
break;
case 'n':
+ case 'v':
sfunc = value;
break;
+ case 'A':
case 'o':
print_file_each_line = 1;
break;
@@ -132,12 +188,23 @@ main(int argc, char *argv[])
case 'r':
rev = 1;
break;
+ case 's':
+ armap = 1;
+ break;
case 'u':
print_only_undefined_symbols = 1;
break;
+ case 'V':
+ fprintf(stderr, "%s\n", rcsid);
+ exit(0);
case 'w':
- ignore_bad_archive_entries = 0;
+ non_object_warning = 1;
break;
+ case 't':
+ if (issize) {
+ print_totals = 1;
+ break;
+ }
case '?':
default:
usage();
@@ -146,21 +213,25 @@ main(int argc, char *argv[])
if (demangle)
pipe2cppfilt();
- fcount = argc - optind;
argv += optind;
+ argc -= optind;
if (rev && sfunc == fname)
sfunc = rname;
- if (!fcount)
- errors = process_file("a.out");
- else {
- errors = 0;
+ eval = 0;
+ if (*argv)
do {
- errors |= process_file(*argv);
+ eval |= process_file(argc, *argv);
} while (*++argv);
- }
- exit(errors);
+ else
+ eval |= process_file(1, "a.out");
+
+ if (issize && print_totals)
+ printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
+ total_text, total_data, total_bss,
+ total_total, total_total);
+ exit(eval);
}
/*
@@ -168,9 +239,10 @@ main(int argc, char *argv[])
* show symbols in the file given as an argument. Accepts archive and
* object files as input.
*/
-process_file(char *fname)
+int
+process_file(int count, const char *fname)
{
- struct exec exec_head;
+ union hdr exec_head;
FILE *fp;
int retval;
char magic[SARMAG];
@@ -180,7 +252,7 @@ process_file(char *fname)
return(1);
}
- if (fcount > 1)
+ if (!issize && count > 1)
(void)printf("\n%s:\n", fname);
/*
@@ -194,218 +266,517 @@ process_file(char *fname)
}
rewind(fp);
- if (BAD_OBJECT(exec_head)) {
/* this could be an archive */
+ if (!IS_ELF(exec_head.elf) && 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);
(void)fclose(fp);
return(1);
}
- retval = show_archive(fname, fp);
+ retval = show_archive(count, fname, fp);
} else
- retval = show_objfile(fname, fp);
+ retval = show_file(count, 1, fname, fp, 0, &exec_head);
(void)fclose(fp);
return(retval);
}
+char *nametab;
+
+/*
+ *
+ * given the archive member header -- produce member name
+ */
+int
+mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)
+{
+ char *p = *name + strlen(*name);
+ long i;
+
+ if (nametab && arh->ar_name[0] == '/') {
+ int len;
+
+ i = atol(&arh->ar_name[1]);
+ len = strlen(&nametab[i]);
+ if (len > *namelen) {
+ p -= (long)*name;
+ if ((*name = realloc(*name, baselen+len)) == NULL)
+ err(1, NULL);
+ *namelen = len;
+ p += (long)*name;
+ }
+ strlcpy(p, &nametab[i], len);
+ p += len;
+ } else
+#ifdef AR_EFMT1
+ /*
+ * BSD 4.4 extended AR format: #1/<namelen>, with name as the
+ * first <namelen> bytes of the file
+ */
+ if ((arh->ar_name[0] == '#') &&
+ (arh->ar_name[1] == '1') &&
+ (arh->ar_name[2] == '/') &&
+ (isdigit(arh->ar_name[3]))) {
+ int len = atoi(&arh->ar_name[3]);
+
+ if (len > *namelen) {
+ p -= (long)*name;
+ if ((*name = realloc(*name, baselen+len)) == NULL)
+ err(1, NULL);
+ *namelen = len;
+ p += (long)*name;
+ }
+ if (fread(p, len, 1, fp) != 1) {
+ warnx("%s: premature EOF", *name);
+ free(*name);
+ return(1);
+ }
+ p += len;
+ } else
+#endif
+ for (i = 0; i < sizeof(arh->ar_name); ++i)
+ if (arh->ar_name[i] && arh->ar_name[i] != ' ')
+ *p++ = arh->ar_name[i];
+ *p = '\0';
+ if (p[-1] == '/')
+ *--p = '\0';
+
+ return (0);
+}
+
+/*
+ * show_symtab()
+ * show archive ranlib index (fs5)
+ */
+int
+show_symtab(off_t off, u_long len, const char *name, FILE *fp)
+{
+ struct ar_hdr ar_head;
+ int *symtab, *ps;
+ char *strtab, *p;
+ int num, rval = 0;
+ int namelen;
+
+ if ((symtab = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE|MAP_FILE, fileno(fp), off)) == MAP_FAILED) {
+ warn("%s: mmap", name);
+ return (1);
+ }
+
+ namelen = sizeof(ar_head.ar_name);
+ if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) {
+ warn("%s: malloc", name);
+ munmap(symtab, len);
+ return (1);
+ }
+
+ printf("\nArchive index:\n");
+ num = betoh32(*symtab);
+ strtab = (char *)(symtab + num + 1);
+ for (ps = symtab + 1; num--; ps++, strtab += strlen(strtab) + 1) {
+ if (fseeko(fp, betoh32(*ps), SEEK_SET)) {
+ warn("%s: fseeko", name);
+ rval = 1;
+ break;
+ }
+
+ if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
+ memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
+ warnx("%s: member fseeko", name);
+ rval = 1;
+ break;
+ }
+
+ *p = '\0';
+ if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
+ rval = 1;
+ break;
+ }
+
+ printf("%s in %s\n", strtab, p);
+ }
+
+ free(p);
+ munmap(symtab, len);
+ return (rval);
+}
+
+/*
+ * show_symdef()
+ * show archive ranlib index (gob)
+ */
+int
+show_symdef(off_t off, u_long len, const char *name, FILE *fp)
+{
+ struct ranlib *prn, *eprn;
+ struct ar_hdr ar_head;
+ void *symdef;
+ char *strtab, *p;
+ u_long size;
+ int namelen, rval = 0;
+
+ if ((symdef = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE|MAP_FILE, fileno(fp), off)) == MAP_FAILED) {
+ warn("%s: mmap", name);
+ return (1);
+ }
+
+ if (madvise(symdef, len, MADV_SEQUENTIAL)) {
+ warn("%s: madvise", name);
+ munmap(symdef, len);
+ return (1);
+ }
+
+ namelen = sizeof(ar_head.ar_name);
+ if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) {
+ warn("%s: malloc", name);
+ munmap(symdef, len);
+ return (1);
+ }
+
+ size = *(u_long *)symdef;
+ prn = symdef + sizeof(u_long);
+ eprn = prn + size / sizeof(*prn);
+ strtab = symdef + sizeof(u_long) + size + sizeof(u_long);
+
+ printf("\nArchive index:\n");
+ for (; prn < eprn; prn++) {
+ if (fseeko(fp, prn->ran_off, SEEK_SET)) {
+ warn("%s: fseeko", name);
+ rval = 1;
+ break;
+ }
+
+ if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
+ memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
+ warnx("%s: member fseeko", name);
+ rval = 1;
+ break;
+ }
+
+ *p = '\0';
+ if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
+ rval = 1;
+ break;
+ }
+
+ printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p);
+ }
+
+ free(p);
+ munmap(symdef, len);
+ return (rval);
+}
+
/*
* show_archive()
* show symbols in the given archive file
*/
-show_archive(char *fname, FILE *fp)
+int
+show_archive(int count, const char *fname, FILE *fp)
{
struct ar_hdr ar_head;
- struct exec exec_head;
+ union hdr exec_head;
int i, rval;
- long last_ar_off;
- char *p, *name;
+ off_t last_ar_off, foff, symtaboff;
+ char *name;
int baselen, namelen;
+ u_long mmbrlen, symtablen;
baselen = strlen(fname) + 3;
namelen = sizeof(ar_head.ar_name);
- name = emalloc(baselen + namelen);
+ if ((name = malloc(baselen + namelen)) == NULL)
+ err(1, NULL);
rval = 0;
+ nametab = NULL;
+ symtaboff = 0;
+ symtablen = 0;
/* while there are more entries in the archive */
- while (fread((char *)&ar_head, sizeof(ar_head), (size_t)1, fp) == 1) {
+ while (fread(&ar_head, sizeof(ar_head), 1, fp) == 1) {
/* bad archive entry - stop processing this archive */
- if (strncmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
+ if (memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
warnx("%s: bad format archive header", fname);
- (void)free(name);
- return(1);
+ rval = 1;
+ break;
}
/* remember start position of current archive object */
- last_ar_off = ftell(fp);
+ last_ar_off = ftello(fp);
+ mmbrlen = atol(ar_head.ar_size);
- /* skip ranlib entries */
- if (!strncmp(ar_head.ar_name, RANLIBMAG, sizeof(RANLIBMAG) - 1))
+ if (strncmp(ar_head.ar_name, RANLIBMAG,
+ sizeof(RANLIBMAG) - 1) == 0) {
+ if (!issize && armap &&
+ show_symdef(last_ar_off, mmbrlen, fname, fp)) {
+ rval = 1;
+ break;
+ }
goto skip;
+ } else if (strncmp(ar_head.ar_name, SYMTABMAG,
+ sizeof(SYMTABMAG) - 1) == 0) {
+ /* if nametab hasn't been seen yet -- doit later */
+ if (!nametab) {
+ symtablen = mmbrlen;
+ symtaboff = last_ar_off;
+ goto skip;
+ }
+
+ /* load the Sys5 long names table */
+ } else if (strncmp(ar_head.ar_name, STRTABMAG,
+ sizeof(STRTABMAG) - 1) == 0) {
+ char *p;
+
+ if ((nametab = malloc(mmbrlen)) == NULL) {
+ warn("%s: nametab", fname);
+ rval = 1;
+ break;
+ }
+
+ if (fread(nametab, mmbrlen, (size_t)1, fp) != 1) {
+ warnx("%s: premature EOF", fname);
+ rval = 1;
+ break;
+ }
+
+ for (p = nametab, i = mmbrlen; i--; p++)
+ if (*p == '\n')
+ *p = '\0';
+
+ if (issize || !armap || !symtablen || !symtaboff)
+ goto skip;
+ }
+
+ if (!issize && armap && symtablen && symtaboff) {
+ if (show_symtab(symtaboff, symtablen, fname, fp)) {
+ rval = 1;
+ break;
+ } else {
+ symtaboff = 0;
+ symtablen = 0;
+ goto skip;
+ }
+ }
/*
* construct a name of the form "archive.a:obj.o:" for the
* current archive entry if the object name is to be printed
* on each output line
*/
- p = name;
- if (print_file_each_line) {
- snprintf(p, baselen, "%s:", fname);
- p += strlen(p);
+ *name = '\0';
+ if (count > 1)
+ snprintf(name, baselen - 1, "%s:", fname);
+
+ if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
+ rval = 1;
+ break;
}
-#ifdef AR_EFMT1
- /*
- * BSD 4.4 extended AR format: #1/<namelen>, with name as the
- * first <namelen> bytes of the file
- */
- if ( (ar_head.ar_name[0] == '#') &&
- (ar_head.ar_name[1] == '1') &&
- (ar_head.ar_name[2] == '/') &&
- (isdigit(ar_head.ar_name[3]))) {
-
- int len = atoi(&ar_head.ar_name[3]);
- if (len > namelen) {
- p -= (long)name;
- if ((name = realloc(name, baselen+len)) == NULL)
- err(1, NULL);
- namelen = len;
- p += (long)name;
- }
- if (fread(p, len, 1, fp) != 1) {
- warnx("%s: premature EOF", name);
- (void)free(name);
- return 1;
- }
- p += len;
- } else
-#endif
- for (i = 0; i < sizeof(ar_head.ar_name); ++i)
- if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ')
- *p++ = ar_head.ar_name[i];
- *p++ = '\0';
+
+ foff = ftello(fp);
/* get and check current object's header */
if (fread((char *)&exec_head, sizeof(exec_head),
(size_t)1, fp) != 1) {
- warnx("%s: premature EOF", name);
- (void)free(name);
- return(1);
- }
-
- if (BAD_OBJECT(exec_head)) {
- if (!ignore_bad_archive_entries) {
- warnx("%s: bad format", name);
- rval = 1;
- }
- } else {
- (void)fseek(fp, (long)-sizeof(exec_head), SEEK_CUR);
- if (!print_file_each_line)
- (void)printf("\n%s:\n", name);
- rval |= show_objfile(name, fp);
+ warnx("%s: premature EOF", fname);
+ rval = 1;
+ break;
}
+ rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);
/*
* skip to next archive object - it starts at the next
* even byte boundary
*/
#define even(x) (((x) + 1) & ~1)
-skip: if (fseek(fp, last_ar_off + even(atol(ar_head.ar_size)),
- SEEK_SET)) {
+skip: if (fseeko(fp, last_ar_off + even(mmbrlen), SEEK_SET)) {
warn("%s", fname);
- (void)free(name);
- return(1);
+ rval = 1;
+ break;
}
}
- (void)free(name);
+ if (nametab) {
+ free(nametab);
+ nametab = NULL;
+ }
+ free(name);
return(rval);
}
+struct nlist *names;
+struct nlist **snames;
+char *stab;
+int nnames, nrawnames, stabsize;
+
/*
- * show_objfile()
+ * show_file()
* show symbols from the object file pointed to by fp. The current
* file pointer for fp is expected to be at the beginning of an a.out
* header.
*/
-show_objfile(char *objname, FILE *fp)
+int
+show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
{
- struct nlist *names, *np;
- struct nlist **snames;
- int i, nnames, nrawnames;
- struct exec head;
- long stabsize;
- char *stab;
-
- /* read a.out header */
- if (fread((char *)&head, sizeof(head), (size_t)1, fp) != 1) {
- warnx("%s: cannot read header", objname);
- return(1);
- }
+ u_long text, data, bss, total;
+ struct nlist *np;
+ Elf_Shdr *shdr;
+ 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) {
+
+ elf_fix_header(&head->elf);
+
+ if ((shdr = malloc(head->elf.e_shentsize *
+ head->elf.e_shnum)) == NULL) {
+ warn("%s: malloc shdr", name);
+ return (1);
+ }
- /*
- * skip back to the header - the N_-macros return values relative
- * to the beginning of the a.out header
- */
- if (fseek(fp, (long)-sizeof(head), SEEK_CUR)) {
- warn("%s", objname);
- return(1);
- }
+ if (fseeko(fp, foff + head->elf.e_shoff, SEEK_SET)) {
+ warn("%s: fseeko", name);
+ free(shdr);
+ return (1);
+ }
- /* stop if this is no valid object file, or a format we don't dare
- * playing with
- */
- if (BAD_OBJECT(head)) {
- warnx("%s: bad format", objname);
- return(1);
- }
+ 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);
+ }
- fix_header_order(&head);
+ elf_fix_shdrs(&head->elf, shdr);
+
+ 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);
+ }
- /* stop if the object file contains no symbol table */
- if (!head.a_syms) {
- warnx("%s: no name list", objname);
- return(1);
- }
+ } else if (BAD_OBJECT(head->aout)) {
+ if (warn_fmt)
+ warnx("%s: bad format", name);
+ return (1);
+ } else do {
+ aout++;
- if (fseek(fp, (long)N_SYMOFF(head), SEEK_CUR)) {
- warn("%s", objname);
- return(1);
- }
+ fix_header_order(&head->aout);
- /* get memory for the symbol table */
- names = emalloc((size_t)head.a_syms);
- nrawnames = head.a_syms / sizeof(*names);
- snames = emalloc(nrawnames*sizeof(struct nlist *));
- if (fread((char *)names, (size_t)head.a_syms, (size_t)1, fp) != 1) {
- warnx("%s: cannot read symbol table", objname);
- (void)free((char *)names);
- return(1);
- }
- fix_nlists_order(names, nrawnames, N_GETMID(head));
+ if (issize) {
+ text = head->aout.a_text;
+ data = head->aout.a_data;
+ bss = head->aout.a_bss;
+ break;
+ }
- /*
- * Following the symbol table comes the string table. The first
- * 4-byte-integer gives the total size of the string table
- * _including_ the size specification itself.
- */
- if (fread((char *)&stabsize, sizeof(stabsize), (size_t)1, fp) != 1) {
- warnx("%s: cannot read stab size", objname);
- (void)free((char *)names);
- return(1);
+ /* stop if the object file contains no symbol table */
+ if (!head->aout.a_syms) {
+ warnx("%s: no name list", name);
+ return(1);
+ }
+
+ if (fseeko(fp, foff + N_SYMOFF(head->aout), SEEK_SET)) {
+ warn("%s", name);
+ return(1);
+ }
+
+ /* get memory for the symbol table */
+ if ((names = malloc(head->aout.a_syms)) == 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);
+ }
+
+ if (fread(names, head->aout.a_syms, 1, fp) != 1) {
+ warnx("%s: cannot read symbol table", name);
+ free(snames);
+ free(names);
+ return(1);
+ }
+ fix_nlists_order(names, nrawnames, N_GETMID(head->aout));
+
+ staboff = ftello(fp);
+ /*
+ * Following the symbol table comes the string table.
+ * 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) {
+ warnx("%s: cannot read stab size", name);
+ free(snames);
+ free(names);
+ return(1);
+ }
+ stabsize = fix_long_order(stabsize, N_GETMID(head->aout));
+ if ((stab = mmap(NULL, stabsize, PROT_READ,
+ MAP_PRIVATE|MAP_FILE, fileno(fp), staboff)) == MAP_FAILED) {
+ warn("%s: mmap", name);
+ free(snames);
+ free(names);
+ return (1);
+ }
+
+ stabsize -= 4; /* we already have the size */
+ } while (0);
+
+ if (issize) {
+ static int first = 1;
+
+ if (first) {
+ first = 0;
+ printf("text\tdata\tbss\tdec\thex\n");
+ }
+
+ total = text + data + bss;
+ printf("%lu\t%lu\t%lu\t%lu\t%lx",
+ text, data, bss, total, total);
+ if (count > 1)
+ (void)printf("\t%s", name);
+
+ total_text += text;
+ total_data += data;
+ total_bss += bss;
+ total_total += total;
+
+ printf("\n");
+ return (0);
}
- stabsize = fix_long_order(stabsize, N_GETMID(head));
- stab = emalloc((size_t)stabsize);
+ /* else we are nm */
/*
- * read the string table offset by 4 - all indices into the string
- * table include the size specification.
+ * it seems that string table is sequential
+ * relative to the symbol table order
*/
- stabsize -= 4; /* we already have the size */
- if (fread(stab + 4, (size_t)stabsize, (size_t)1, fp) != 1) {
- warnx("%s: stab truncated..", objname);
- (void)free((char *)names);
- (void)free(stab);
- return(1);
+ if (sfunc == NULL && madvise(stab, stabsize, MADV_SEQUENTIAL)) {
+ warn("%s: madvise", name);
+ free(snames);
+ free(names);
+ munmap(stab, stabsize);
+ return (1);
}
/*
@@ -428,7 +799,7 @@ show_objfile(char *objname, FILE *fp)
np->n_un.n_name = stab + np->n_un.n_strx;
else
np->n_un.n_name = "";
- if (SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value)
+ if (aout && SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value)
np->n_type = N_COMM | (np->n_type & N_EXT);
if (!print_all_symbols && IS_DEBUGGER_SYMBOL(np->n_type))
continue;
@@ -445,20 +816,139 @@ show_objfile(char *objname, FILE *fp)
if (sfunc)
qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);
+ if (count > 1)
+ (void)printf("\n%s:\n", name);
+
/* print out symbols */
for (i = 0; i < nnames; i++) {
if (show_extensions && snames[i] != names &&
SYMBOL_TYPE((snames[i] -1)->n_type) == N_INDR)
continue;
- print_symbol(objname, snames[i]);
+ print_symbol(name, snames[i], aout);
}
- (void)free(snames);
- (void)free(names);
- (void)free(stab);
+ free(snames);
+ free(names);
+ munmap(stab, stabsize);
return(0);
}
+int
+elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, Elf_Shdr *shdr)
+{
+ long symsize, shstrsize, nlistsize;
+ 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);
+ }
+
+ if ((stab = mmap(NULL, stabsize, PROT_READ,
+ MAP_PRIVATE|MAP_FILE, fileno(fp),
+ foff + shdr[i].sh_offset)) == MAP_FAILED) {
+ warn("%s: mmap", name);
+ 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)
{
@@ -473,10 +963,10 @@ symname(struct nlist *sym)
* show one symbol
*/
void
-print_symbol(const char *objname, struct nlist *sym)
+print_symbol(const char *name, struct nlist *sym, int aout)
{
if (print_file_each_line)
- (void)printf("%s:", objname);
+ (void)printf("%s:", name);
/*
* handle undefined-only format especially (no space is
@@ -496,10 +986,10 @@ print_symbol(const char *objname, struct nlist *sym)
(void)printf(" - %02x %04x %5s ", sym->n_other,
sym->n_desc&0xffff, typestring(sym->n_type));
else if (show_extensions)
- (void)printf(" %c%2s ", typeletter(sym->n_type),
+ (void)printf(" %c%2s ", typeletter(sym, aout),
otherstring(sym));
else
- (void)printf(" %c ", typeletter(sym->n_type));
+ (void)printf(" %c ", typeletter(sym, aout));
}
if (SYMBOL_TYPE(sym->n_type) == N_INDR && show_extensions) {
@@ -586,31 +1076,36 @@ typestring(unsigned int type)
* external, lower case for internal symbols.
*/
char
-typeletter(unsigned int type)
+typeletter(struct nlist *np, int aout)
{
- switch(SYMBOL_TYPE(type)) {
+ int ext = IS_EXTERNAL(np->n_type);
+
+ if (!aout && !IS_DEBUGGER_SYMBOL(np->n_type) && np->n_other)
+ return np->n_other;
+
+ switch(SYMBOL_TYPE(np->n_type)) {
case N_ABS:
- return(IS_EXTERNAL(type) ? 'A' : 'a');
+ return(ext? 'A' : 'a');
case N_BSS:
- return(IS_EXTERNAL(type) ? 'B' : 'b');
+ return(ext? 'B' : 'b');
case N_COMM:
- return(IS_EXTERNAL(type) ? 'C' : 'c');
+ return(ext? 'C' : 'c');
case N_DATA:
- return(IS_EXTERNAL(type) ? 'D' : 'd');
+ return(ext? 'D' : 'd');
case N_FN:
/* NOTE: N_FN == N_WARNING,
* in this case, the N_EXT bit is to considered as
* part of the symbol's type itself.
*/
- return(IS_EXTERNAL(type) ? 'F' : 'W');
+ return(ext? 'F' : 'W');
case N_TEXT:
- return(IS_EXTERNAL(type) ? 'T' : 't');
+ return(ext? 'T' : 't');
case N_INDR:
- return(IS_EXTERNAL(type) ? 'I' : 'i');
+ return(ext? 'I' : 'i');
case N_SIZE:
- return(IS_EXTERNAL(type) ? 'S' : 's');
+ return(ext? 'S' : 's');
case N_UNDF:
- return(IS_EXTERNAL(type) ? 'U' : 'u');
+ return(ext? 'U' : 'u');
}
return('?');
}
@@ -654,17 +1149,6 @@ value(const void *a0, const void *b0)
}
}
-void *
-emalloc(size_t size)
-{
- char *p;
-
- /* NOSTRICT */
- if (p = malloc(size))
- return(p);
- err(1, NULL);
-}
-
#define CPPFILT "/usr/bin/c++filt"
void
@@ -697,6 +1181,12 @@ pipe2cppfilt(void)
void
usage(void)
{
- (void)fprintf(stderr, "usage: nm [-aCgnopruw] [file ...]\n");
+ extern char *__progname;
+
+ if (issize)
+ fprintf(stderr, "usage: %s [-tw] [file ...]\n", __progname);
+ else
+ fprintf(stderr, "usage: %s [-aABCegnoprsuvVw] [file ...]\n",
+ __progname);
exit(1);
}
diff --git a/usr.bin/size/size.1 b/usr.bin/nm/size.1
index 5e62f5f3503..9c1cebe3301 100644
--- a/usr.bin/size/size.1
+++ b/usr.bin/nm/size.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: size.1,v 1.10 2003/06/03 02:56:16 millert Exp $
+.\" $OpenBSD: size.1,v 1.1 2004/01/05 01:27:22 mickey Exp $
.\" $NetBSD: size.1,v 1.6 1996/01/14 23:07:11 pk Exp $
.\"
.\" Copyright (c) 1990, 1993, 1994
diff --git a/usr.bin/size/Makefile b/usr.bin/size/Makefile
deleted file mode 100644
index 273c3c12b76..00000000000
--- a/usr.bin/size/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-# $OpenBSD: Makefile,v 1.5 1999/05/10 16:14:07 espie Exp $
-
-TARGET_MACHINE_ARCH?= ${MACHINE_ARCH}
-
-.if ${TARGET_MACHINE_ARCH} != ${MACHINE_ARCH}
-# XXX should make this automatic
-.if ${TARGET_MACHINE_ARCH} == "i386"
-CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_I386
-.elif ${TARGET_MACHINE_ARCH} == "m68k"
-CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_M68K
-.elif ${TARGET_MACHINE_ARCH} == "ns32k"
-CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_NS32K
-.elif ${TARGET_MACHINE_ARCH} == "sparc"
-CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_SPARC
-.elif ${TARGET_MACHINE_ARCH} == "vax"
-CFLAGS+= -DMID_MACHINE_OVERRIDE=MID_VAX
-.endif
-.endif
-
-CFLAGS+= -I${.CURDIR}/../nm
-
-PROG= size
-
-.include <bsd.prog.mk>
diff --git a/usr.bin/size/size.c b/usr.bin/size/size.c
deleted file mode 100644
index b0bf58269dc..00000000000
--- a/usr.bin/size/size.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/* $OpenBSD: size.c,v 1.20 2003/09/30 19:00:14 mickey Exp $ */
-/* $NetBSD: size.c,v 1.7 1996/01/14 23:07:12 pk Exp $ */
-
-/*
- * Copyright (c) 1988, 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
- * 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.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 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.
- */
-
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1988, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)size.c 8.2 (Berkeley) 12/9/93";
-#endif
-static const char rcsid[] = "$OpenBSD: size.c,v 1.20 2003/09/30 19:00:14 mickey Exp $";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <elf_abi.h>
-#include <a.out.h>
-#include <ar.h>
-#include <ranlib.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <err.h>
-#include "byte.c"
-
-#ifdef MID_MACHINE_OVERRIDE
-#undef MID_MACHINE
-#define MID_MACHINE MID_MACHINE_OVERRIDE
-#endif
-
-#define STRTABMAG "//"
-
-union hdr {
- struct exec aout;
- Elf_Ehdr elf;
-};
-
-unsigned long total_text, total_data, total_bss, total_total;
-int non_object_warning, print_totals;
-
-int process_file(int, char *);
-int show_archive(int, char *, FILE *);
-int show_file(int, int, char *, FILE *, off_t, union hdr *);
-void usage(void);
-
-int
-main(int argc, char *argv[])
-{
- int ch, eval;
-
- while ((ch = getopt(argc, argv, "wt")) != -1)
- switch(ch) {
- case 'w':
- non_object_warning = 1;
- break;
- case 't':
- print_totals = 1;
- break;
- case '?':
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
-
- eval = 0;
- if (*argv)
- do {
- eval |= process_file(argc, *argv);
- } while (*++argv);
- else
- eval |= process_file(1, "a.out");
-
- if (print_totals)
- (void)printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
- total_text, total_data, total_bss,
- total_total, total_total);
- exit(eval);
-}
-
-/*
- * process_file()
- * show symbols in the file given as an argument. Accepts archive and
- * object files as input.
- */
-int
-process_file(int count, char *fname)
-{
- union hdr exec_head;
- FILE *fp;
- int retval;
- char magic[SARMAG];
-
- if (!(fp = fopen(fname, "r"))) {
- warnx("cannot read %s", fname);
- return(1);
- }
-
- /*
- * first check whether this is an object file - read a object
- * header, and skip back to the beginning
- */
- if (fread((char *)&exec_head, sizeof(exec_head), (size_t)1, fp) != 1) {
- warnx("%s: bad format", fname);
- (void)fclose(fp);
- return(1);
- }
- rewind(fp);
-
- /* this could be an archive */
- if (!IS_ELF(exec_head.elf) && 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);
- (void)fclose(fp);
- return(1);
- }
- retval = show_archive(count, fname, fp);
- } else
- retval = show_file(count, 1, fname, fp, 0, &exec_head);
- (void)fclose(fp);
- return(retval);
-}
-
-/*
- * show_archive()
- * show symbols in the given archive file
- */
-int
-show_archive(int count, char *fname, FILE *fp)
-{
- struct ar_hdr ar_head;
- union hdr exec_head;
- int i, rval;
- off_t last_ar_off, foff;
- char *p, *name, *strtab;
- int baselen, namelen;
-
- baselen = strlen(fname) + 3;
- namelen = sizeof(ar_head.ar_name);
- if ((name = malloc(baselen + namelen)) == NULL)
- err(1, NULL);
-
- rval = 0;
- strtab = NULL;
-
- /* while there are more entries in the archive */
- while (fread((char *)&ar_head, sizeof(ar_head), (size_t)1, fp) == 1) {
- /* bad archive entry - stop processing this archive */
- if (strncmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
- warnx("%s: bad format archive header", fname);
- free(name);
- free(strtab);
- return(1);
- }
-
- /* remember start position of current archive object */
- last_ar_off = ftello(fp);
-
- /* skip ranlib entries */
- if (!strncmp(ar_head.ar_name, RANLIBMAG, sizeof(RANLIBMAG) - 1))
- goto skip;
-
- /* load the Sys5 long names table */
- if (!strncmp(ar_head.ar_name, STRTABMAG,
- sizeof(STRTABMAG) - 1)) {
-
- i = atol(ar_head.ar_size);
- if ((strtab = malloc(i)) == NULL) {
- warn("%s: strtab", name);
- free(name);
- return(1);
- }
-
- if (fread(strtab, i, (size_t)1, fp) != 1) {
- warnx("%s: premature EOF", name);
- free(strtab);
- free(name);
- return(1);
- }
-
- for (p = strtab; i--; p++)
- if (*p == '\n')
- *p = '\0';
- goto skip;
- }
-
- /*
- * construct a name of the form "archive.a:obj.o:" for the
- * current archive entry if the object name is to be printed
- * on each output line
- */
- p = name;
- if (count > 1) {
- snprintf(name, baselen - 1, "%s:", fname);
- p += strlen(name);
- }
-
- if (strtab && ar_head.ar_name[0] == '/') {
- int len;
-
- i = atol(&ar_head.ar_name[1]);
- len = strlen(&strtab[i]);
- if (len > namelen) {
- p -= (long)name;
- if ((name = realloc(name, baselen+len)) == NULL)
- err(1, NULL);
- namelen = len;
- p += (long)name;
- }
- strlcpy(p, &strtab[i], len);
- p += len;
- } else
-#ifdef AR_EFMT1
- /*
- * BSD 4.4 extended AR format: #1/<namelen>, with name as the
- * first <namelen> bytes of the file
- */
- if ((ar_head.ar_name[0] == '#') &&
- (ar_head.ar_name[1] == '1') &&
- (ar_head.ar_name[2] == '/') &&
- (isdigit(ar_head.ar_name[3]))) {
- int len = atoi(&ar_head.ar_name[3]);
-
- if (len > namelen) {
- p -= (long)name;
- if ((name = realloc(name, baselen+len)) == NULL)
- err(1, NULL);
- namelen = len;
- p += (long)name;
- }
- if (fread(p, len, 1, fp) != 1) {
- warnx("%s: premature EOF", name);
- free(name);
- return(1);
- }
- p += len;
- } else
-#endif
- for (i = 0; i < sizeof(ar_head.ar_name); ++i)
- if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ')
- *p++ = ar_head.ar_name[i];
- *p = '\0';
- if (p[-1] == '/')
- *--p = '\0';
-
- foff = ftello(fp);
-
- /* get and check current object's header */
- if (fread((char *)&exec_head, sizeof(exec_head),
- (size_t)1, fp) != 1) {
- warnx("%s: premature EOF", name);
- free(name);
- return(1);
- }
-
- rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);
- /*
- * skip to next archive object - it starts at the next
- * even byte boundary
- */
-#define even(x) (((x) + 1) & ~1)
-skip: if (fseeko(fp, last_ar_off + even(atol(ar_head.ar_size)),
- SEEK_SET)) {
- warn("%s", fname);
- free(name);
- return(1);
- }
- }
- free(name);
- return(rval);
-}
-
-int
-show_file(int count, int warn_fmt, char *name, FILE *fp, off_t foff, union hdr *head)
-{
- static int first = 1;
- Elf_Shdr *shdr;
- u_long text, data, bss, total;
- int i;
-
- if (IS_ELF(head->elf) &&
- head->elf.e_ident[EI_CLASS] == ELF_TARG_CLASS &&
- head->elf.e_ident[EI_DATA] == ELF_TARG_DATA &&
- head->elf.e_ident[EI_VERSION] == ELF_TARG_VER &&
- head->elf.e_machine == ELF_TARG_MACH &&
- head->elf.e_version == ELF_TARG_VER) {
-
- if ((shdr = malloc(head->elf.e_shentsize *
- head->elf.e_shnum)) == NULL) {
- warn("%s: malloc shdr", name);
- return (1);
- }
-
- if (fseeko(fp, foff + head->elf.e_shoff, SEEK_SET)) {
- warn("%s: fseeko", name);
- free(shdr);
- return (1);
- }
-
- 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);
- }
-
- 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 if (BAD_OBJECT(head->aout)) {
- if (warn_fmt)
- warnx("%s: bad format", name);
- return (1);
- } else {
- fix_header_order(&head->aout);
-
- text = head->aout.a_text;
- data = head->aout.a_data;
- bss = head->aout.a_bss;
- }
-
- if (first) {
- first = 0;
- (void)printf("text\tdata\tbss\tdec\thex\n");
- }
-
- total = text + data + bss;
- (void)printf("%lu\t%lu\t%lu\t%lu\t%lx", text, data, bss, total, total);
- if (count > 1)
- (void)printf("\t%s", name);
-
- total_text += text;
- total_data += data;
- total_bss += bss;
- total_total += total;
-
- (void)printf("\n");
- return (0);
-}
-
-void
-usage(void)
-{
- (void)fprintf(stderr, "usage: size [-tw] [file ...]\n");
- exit(1);
-}