diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2015-08-13 19:13:29 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2015-08-13 19:13:29 +0000 |
commit | 594f369c3083b9c5702508642f03f24299ca98de (patch) | |
tree | cd49e70d1620bac6b7199050caa7c64f0f77a4ba | |
parent | 661ac077c29d835753830294c6810b04625ad12f (diff) |
Grow -P (POSIX output) and -t (POSIX output radix) support. Several 3rd-party
software depend upon this.
Requested by feinerer@, ok millert@; manpage bits ok jmc@
-rw-r--r-- | usr.bin/nm/elf.c | 63 | ||||
-rw-r--r-- | usr.bin/nm/elfuncs.h | 10 | ||||
-rw-r--r-- | usr.bin/nm/nm.1 | 34 | ||||
-rw-r--r-- | usr.bin/nm/nm.c | 144 | ||||
-rw-r--r-- | usr.bin/nm/util.h | 7 |
5 files changed, 163 insertions, 95 deletions
diff --git a/usr.bin/nm/elf.c b/usr.bin/nm/elf.c index c44a6babbe5..7458af512ce 100644 --- a/usr.bin/nm/elf.c +++ b/usr.bin/nm/elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: elf.c,v 1.32 2015/06/23 15:16:34 semarie Exp $ */ +/* $OpenBSD: elf.c,v 1.33 2015/08/13 19:13:28 miod Exp $ */ /* * Copyright (c) 2003 Michael Shalayeff @@ -37,8 +37,8 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> -#include "elfuncs.h" #include "util.h" +#include "elfuncs.h" #if ELFSIZE == 32 #define swap_addr swap32 @@ -116,7 +116,7 @@ #endif int elf_shn2type(Elf_Ehdr *, u_int, const char *); -int elf2nlist(Elf_Sym *, Elf_Ehdr *, Elf_Shdr *, char *, struct nlist *); +int elf2nlist(Elf_Sym *, Elf_Ehdr *, Elf_Shdr *, char *, struct xnlist *); int elf_fix_header(Elf_Ehdr *eh) @@ -342,11 +342,12 @@ elf_shn2type(Elf_Ehdr *eh, u_int shn, const char *sn) } /* - * Devise nlist's type from Elf_Sym. + * Devise xnlist'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) +elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr, + struct xnlist *np) { u_char stt; const char *sn; @@ -372,60 +373,61 @@ elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr, struct nlist type = elf_shn2type(eh, sym->st_shndx, sn); if (type < 0) { if (sn == NULL) - np->n_other = '?'; + np->nl.n_other = '?'; else - np->n_type = stt == STT_NOTYPE? N_COMM : N_DATA; + np->nl.n_type = stt == STT_NOTYPE ? + N_COMM : N_DATA; } else { /* a hack for .rodata check (; */ if (type == N_SIZE) { - np->n_type = N_DATA; - np->n_other = 'r'; + np->nl.n_type = N_DATA; + np->nl.n_other = 'r'; } else - np->n_type = type; + np->nl.n_type = type; } if (ELF_ST_BIND(sym->st_info) == STB_WEAK) - np->n_other = 'W'; + np->nl.n_other = 'W'; break; case STT_FUNC: type = elf_shn2type(eh, sym->st_shndx, NULL); - np->n_type = type < 0? N_TEXT : type; + np->nl.n_type = type < 0? N_TEXT : type; if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { - np->n_other = 'W'; + np->nl.n_other = 'W'; } else if (sn != NULL && *sn != 0 && strcmp(sn, ELF_INIT) && strcmp(sn, ELF_TEXT) && strcmp(sn, ELF_FINI)) /* XXX GNU compat */ - np->n_other = '?'; + np->nl.n_other = '?'; break; case STT_SECTION: type = elf_shn2type(eh, sym->st_shndx, NULL); if (type < 0) - np->n_other = '?'; + np->nl.n_other = '?'; else - np->n_type = type; + np->nl.n_type = type; break; case STT_FILE: - np->n_type = N_FN | N_EXT; + np->nl.n_type = N_FN | N_EXT; break; case STT_PARISC_MILLI: if (eh->e_machine == EM_PARISC) - np->n_type = N_TEXT; + np->nl.n_type = N_TEXT; else - np->n_other = '?'; + np->nl.n_other = '?'; break; default: - np->n_other = '?'; + np->nl.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((unsigned char)np->n_other); + if (np->nl.n_type != N_UNDF && ELF_ST_BIND(sym->st_info) != STB_LOCAL) { + np->nl.n_type |= N_EXT; + if (np->nl.n_other) + np->nl.n_other = toupper((unsigned char)np->nl.n_other); } return (0); @@ -456,12 +458,12 @@ elf_size(Elf_Ehdr *head, Elf_Shdr *shdr, int elf_symloadx(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, - Elf_Shdr *shdr, char *shstr, long shstrsize, struct nlist **pnames, - struct nlist ***psnames, size_t *pstabsize, int *pnrawnames, + Elf_Shdr *shdr, char *shstr, long shstrsize, struct xnlist **pnames, + struct xnlist ***psnames, size_t *pstabsize, int *pnrawnames, const char *strtab, const char *symtab) { long symsize; - struct nlist *np; + struct xnlist *np; Elf_Sym sbuf; int i; @@ -532,8 +534,9 @@ elf_symloadx(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, continue; elf2nlist(&sbuf, eh, shdr, shstr, np); - np->n_value = sbuf.st_value; - np->n_un.n_strx = sbuf.st_name; + np->nl.n_value = sbuf.st_value; + np->nl.n_un.n_strx = sbuf.st_name; + np->n_size = sbuf.st_size; np++; } *pnrawnames = np - *pnames; @@ -544,7 +547,7 @@ elf_symloadx(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, int elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, - Elf_Shdr *shdr, struct nlist **pnames, struct nlist ***psnames, + Elf_Shdr *shdr, struct xnlist **pnames, struct xnlist ***psnames, size_t *pstabsize, int *pnrawnames) { long shstrsize; diff --git a/usr.bin/nm/elfuncs.h b/usr.bin/nm/elfuncs.h index 7121c75c75a..e1f1977c2f2 100644 --- a/usr.bin/nm/elfuncs.h +++ b/usr.bin/nm/elfuncs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: elfuncs.h,v 1.4 2015/06/23 15:02:58 semarie Exp $ */ +/* $OpenBSD: elfuncs.h,v 1.5 2015/08/13 19:13:28 miod Exp $ */ /* * Copyright (c) 2004 Michael Shalayeff @@ -36,10 +36,10 @@ 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_symloadx(const char *, FILE *, off_t, Elf32_Ehdr *, Elf32_Shdr *, - char *, long, struct nlist **, struct nlist ***, size_t *, int *, + char *, long, struct xnlist **, struct xnlist ***, size_t *, int *, const char *, const char *); int elf32_symload(const char *, FILE *, off_t, Elf32_Ehdr *, Elf32_Shdr *, - struct nlist **, struct nlist ***, size_t *, int *); + struct xnlist **, struct xnlist ***, size_t *, int *); int elf64_fix_header(Elf64_Ehdr *eh); Elf64_Shdr*elf64_load_shdrs(const char *, FILE *, off_t, Elf64_Ehdr *); @@ -49,7 +49,7 @@ 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_symloadx(const char *, FILE *, off_t, Elf64_Ehdr *, Elf64_Shdr *, - char *, long, struct nlist **, struct nlist ***, size_t *, int *, + char *, long, struct xnlist **, struct xnlist ***, size_t *, int *, const char *, const char *); int elf64_symload(const char *, FILE *, off_t, Elf64_Ehdr *, Elf64_Shdr *, - struct nlist **, struct nlist ***, size_t *, int *); + struct xnlist **, struct xnlist ***, size_t *, int *); diff --git a/usr.bin/nm/nm.1 b/usr.bin/nm/nm.1 index 0d75aa531e0..f3a0c04e7dd 100644 --- a/usr.bin/nm/nm.1 +++ b/usr.bin/nm/nm.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nm.1,v 1.27 2015/05/17 20:19:08 guenther Exp $ +.\" $OpenBSD: nm.1,v 1.28 2015/08/13 19:13:28 miod Exp $ .\" $NetBSD: nm.1,v 1.3 1995/08/31 23:41:58 jtc Exp $ .\" .\" Copyright (c) 1980, 1990, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)nm.1 8.1 (Berkeley) 6/6/93 .\" -.Dd $Mdocdate: May 17 2015 $ +.Dd $Mdocdate: August 13 2015 $ .Dt NM 1 .Os .Sh NAME @@ -38,7 +38,8 @@ .Nd display name list (symbol table) .Sh SYNOPSIS .Nm nm -.Op Fl aCDegnoprsuw +.Op Fl AaCDegnoPprsuw +.Op Fl t d|o|x .Op Ar .Sh DESCRIPTION The symbol table (name list) of each object in @@ -58,6 +59,8 @@ and displays its symbol table if it exists. .Pp The options are as follows: .Bl -tag -width Ds +.It Fl A +Display the full path or library name of object on every line. .It Fl a Display symbol table entries inserted for use by debuggers. .It Fl C @@ -73,13 +76,36 @@ Restrict display to external (global) symbols. .It Fl n Present results in numerical order. .It Fl o -Display full path or library name of object on every line. +Display the full path or library name of object on every line +.Pq this is similar to Fl A . +.It Fl P +Report information in POSIX format: full path or library name of object if +either +.Fl A +or +.Fl o +has been specified; symbol name; symbol type; +symbol value and size (unless the symbol is undefined). +The radix of symbol values and sizes defaults to decimal, and may be changed +with the +.Fl t +option. .It Fl p Do not sort at all. .It Fl r Reverse order sort. .It Fl s Show archive index. +.It Fl t Ar d|o|x +In POSIX format output, choose the numeric radix as follows: +.Bl -tag -width 3n -compact +.It d +Decimal. +.It o +Octal. +.It x +Hexadecimal. +.El .It Fl u Display undefined symbols only. .It Fl w diff --git a/usr.bin/nm/nm.c b/usr.bin/nm/nm.c index bb80d03dc01..bc02f50d758 100644 --- a/usr.bin/nm/nm.c +++ b/usr.bin/nm/nm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nm.c,v 1.46 2015/05/17 21:41:50 guenther Exp $ */ +/* $OpenBSD: nm.c,v 1.47 2015/08/13 19:13:28 miod Exp $ */ /* $NetBSD: nm.c,v 1.7 1996/01/14 23:04:03 pk Exp $ */ /* @@ -49,8 +49,8 @@ #include <stdlib.h> #include <string.h> #include <getopt.h> -#include "elfuncs.h" #include "util.h" +#include "elfuncs.h" #define SYMTABMAG "/ " #define STRTABMAG "//" @@ -70,6 +70,9 @@ int print_all_symbols; int print_file_each_line; int show_extensions; int issize; +char posix_fmtstr[6]; +int posix_output; +char posix_radix = 'x'; int usemmap = 1; int dynamic_only; @@ -81,9 +84,9 @@ int rev; int fname(const void *, const void *); int rname(const void *, const void *); int value(const void *, const void *); -char *otherstring(struct nlist *); +char *otherstring(struct xnlist *); int (*sfunc)(const void *, const void *) = fname; -char typeletter(struct nlist *); +char typeletter(struct xnlist *); int mmbr_name(struct ar_hdr *, char **, int, int *, FILE *); int show_symtab(off_t, u_long, const char *, FILE *); int show_symdef(off_t, u_long, const char *, FILE *); @@ -94,13 +97,13 @@ int show_symdef(off_t, u_long, const char *, FILE *); void pipe2cppfilt(void); void usage(void); -char *symname(struct nlist *); +char *symname(struct xnlist *); 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 *); +void print_symbol(const char *, struct xnlist *); -#define OPTSTRING_NM "aABCDegnoprsuvw" +#define OPTSTRING_NM "aABCDegnopPrst:uvw" const struct option longopts_nm[] = { { "debug-syms", no_argument, 0, 'a' }, { "demangle", no_argument, 0, 'C' }, @@ -171,6 +174,9 @@ main(int argc, char *argv[]) case 'p': sfunc = NULL; break; + case 'P': + posix_output = 1; + break; case 'r': rev = 1; break; @@ -186,14 +192,23 @@ main(int argc, char *argv[]) case 't': if (issize) { print_totals = 1; - break; + } else { + posix_radix = *optarg; + if (strlen(optarg) != 1 || + (posix_radix != 'd' && posix_radix != 'o' && + posix_radix != 'x')) + usage(); } + break; case '?': default: usage(); } } + if (posix_output) + (void)snprintf(posix_fmtstr, sizeof posix_fmtstr, "%%%c %%%c", + posix_radix, posix_radix); if (demangle) pipe2cppfilt(); argv += optind; @@ -468,6 +483,8 @@ show_archive(int count, const char *fname, FILE *fp) u_long mmbrlen, symtablen; baselen = strlen(fname) + 3; + if (posix_output) + baselen += 2; namelen = sizeof(ar_head.ar_name); if ((name = malloc(baselen + namelen)) == NULL) err(1, NULL); @@ -555,7 +572,9 @@ show_archive(int count, const char *fname, FILE *fp) * on each output line */ *name = '\0'; - if (count > 1) + if (posix_output) + snprintf(name, baselen - 1, "%s[", fname); + else if (count > 1) snprintf(name, baselen - 1, "%s:", fname); if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) { @@ -563,6 +582,9 @@ show_archive(int count, const char *fname, FILE *fp) break; } + if (posix_output) + strlcat(name, "]", baselen + namelen); + foff = ftello(fp); /* get and check current object's header */ @@ -605,7 +627,7 @@ 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, *names, **snames; + struct xnlist *np, *names, **snames; int i, nrawnames, nnames; size_t stabsize; @@ -693,14 +715,14 @@ show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union * * don't mess with zero offsets */ - if (np->n_un.n_strx) - np->n_un.n_name = stab + np->n_un.n_strx; + if (np->nl.n_un.n_strx) + np->nl.n_un.n_name = stab + np->nl.n_un.n_strx; else - np->n_un.n_name = ""; - if (print_only_external_symbols && !IS_EXTERNAL(np->n_type)) + np->nl.n_un.n_name = ""; + if (print_only_external_symbols && !IS_EXTERNAL(np->nl.n_type)) continue; if (print_only_undefined_symbols && - SYMBOL_TYPE(np->n_type) != N_UNDF) + SYMBOL_TYPE(np->nl.n_type) != N_UNDF) continue; snames[nnames++] = np; @@ -724,9 +746,9 @@ show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union } char * -symname(struct nlist *sym) +symname(struct xnlist *sym) { - return sym->n_un.n_name; + return sym->nl.n_un.n_name; } /* @@ -734,30 +756,42 @@ symname(struct nlist *sym) * show one symbol */ void -print_symbol(const char *name, struct nlist *sym) +print_symbol(const char *name, struct xnlist *sym) { - if (print_file_each_line) - (void)printf("%s:", name); - - /* - * handle undefined-only format especially (no space is - * left for symbol values, no type field is printed) - */ - if (!print_only_undefined_symbols) { - /* print symbol's value */ - if (SYMBOL_TYPE(sym->n_type) == N_UNDF) - (void)printf(" "); - else - (void)printf("%08lx", sym->n_value); - - /* print type information */ - if (show_extensions) - (void)printf(" %c ", typeletter(sym)); + if (print_file_each_line) { + if (posix_output) + (void)printf("%s: ", name); else - (void)printf(" %c ", typeletter(sym)); + (void)printf("%s:", name); } - (void)puts(symname(sym)); + if (posix_output) { + (void)printf("%s %c ", symname(sym), typeletter(sym)); + if (SYMBOL_TYPE(sym->nl.n_type) != N_UNDF) + (void)printf(posix_fmtstr, sym->nl.n_value, + sym->n_size); + (void)printf("\n"); + } else { + /* + * handle undefined-only format especially (no space is + * left for symbol values, no type field is printed) + */ + if (!print_only_undefined_symbols) { + /* print symbol's value */ + if (SYMBOL_TYPE(sym->nl.n_type) == N_UNDF) + (void)printf(" "); + else + (void)printf("%08lx", sym->nl.n_value); + + /* print type information */ + if (show_extensions) + (void)printf(" %c ", typeletter(sym)); + else + (void)printf(" %c ", typeletter(sym)); + } + + (void)puts(symname(sym)); + } } /* @@ -767,14 +801,14 @@ print_symbol(const char *name, struct nlist *sym) * external, lower case for internal symbols. */ char -typeletter(struct nlist *np) +typeletter(struct xnlist *np) { - int ext = IS_EXTERNAL(np->n_type); + int ext = IS_EXTERNAL(np->nl.n_type); - if (np->n_other) - return np->n_other; + if (np->nl.n_other) + return np->nl.n_other; - switch(SYMBOL_TYPE(np->n_type)) { + switch(SYMBOL_TYPE(np->nl.n_type)) { case N_ABS: return(ext? 'A' : 'a'); case N_BSS: @@ -802,39 +836,39 @@ typeletter(struct nlist *np) int fname(const void *a0, const void *b0) { - struct nlist * const *a = a0, * const *b = b0; + struct xnlist * const *a = a0, * const *b = b0; - return(strcmp((*a)->n_un.n_name, (*b)->n_un.n_name)); + return(strcmp((*a)->nl.n_un.n_name, (*b)->nl.n_un.n_name)); } int rname(const void *a0, const void *b0) { - struct nlist * const *a = a0, * const *b = b0; + struct xnlist * const *a = a0, * const *b = b0; - return(strcmp((*b)->n_un.n_name, (*a)->n_un.n_name)); + return(strcmp((*b)->nl.n_un.n_name, (*a)->nl.n_un.n_name)); } int value(const void *a0, const void *b0) { - struct nlist * const *a = a0, * const *b = b0; + struct xnlist * const *a = a0, * const *b = b0; - if (SYMBOL_TYPE((*a)->n_type) == N_UNDF) - if (SYMBOL_TYPE((*b)->n_type) == N_UNDF) + if (SYMBOL_TYPE((*a)->nl.n_type) == N_UNDF) + if (SYMBOL_TYPE((*b)->nl.n_type) == N_UNDF) return(0); else return(-1); - else if (SYMBOL_TYPE((*b)->n_type) == N_UNDF) + else if (SYMBOL_TYPE((*b)->nl.n_type) == N_UNDF) return(1); if (rev) { - if ((*a)->n_value == (*b)->n_value) + if ((*a)->nl.n_value == (*b)->nl.n_value) return(rname(a0, b0)); - return((*b)->n_value > (*a)->n_value ? 1 : -1); + return((*b)->nl.n_value > (*a)->nl.n_value ? 1 : -1); } else { - if ((*a)->n_value == (*b)->n_value) + if ((*a)->nl.n_value == (*b)->nl.n_value) return(fname(a0, b0)); - return((*a)->n_value > (*b)->n_value ? 1 : -1); + return((*a)->nl.n_value > (*b)->nl.n_value ? 1 : -1); } } @@ -875,7 +909,7 @@ usage(void) if (issize) fprintf(stderr, "usage: %s [-tw] [file ...]\n", __progname); else - fprintf(stderr, "usage: %s [-aCDegnoprsuw] [file ...]\n", + fprintf(stderr, "usage: %s [-AaCDegnoPprsuw] [-t d|o|x] [file ...]\n", __progname); exit(1); } diff --git a/usr.bin/nm/util.h b/usr.bin/nm/util.h index 622f2158972..f91fa432f23 100644 --- a/usr.bin/nm/util.h +++ b/usr.bin/nm/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.4 2015/06/23 15:16:34 semarie Exp $ */ +/* $OpenBSD: util.h,v 1.5 2015/08/13 19:13:28 miod Exp $ */ /* * Placed in the public domain by Todd C. Miller <Todd.Miller@courtesan.com> @@ -31,3 +31,8 @@ extern int usemmap; extern int dynamic_only; + +struct xnlist { + struct nlist nl; + unsigned long n_size; +}; |