[BACK]Return to nm.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / nm

Annotation of src/usr.bin/nm/nm.c, Revision 1.51

1.51    ! mmcc        1: /*     $OpenBSD: nm.c,v 1.50 2015/11/13 15:22:44 deraadt Exp $ */
1.2       deraadt     2: /*     $NetBSD: nm.c,v 1.7 1996/01/14 23:04:03 pk Exp $        */
1.1       deraadt     3:
                      4: /*
                      5:  * Copyright (c) 1989, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Hans Huebner.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
1.18      millert    19:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.42      deraadt    36: #include <sys/types.h>
1.20      mickey     37: #include <sys/mman.h>
1.1       deraadt    38: #include <a.out.h>
1.20      mickey     39: #include <elf_abi.h>
1.1       deraadt    40: #include <ar.h>
                     41: #include <ranlib.h>
                     42: #include <unistd.h>
1.2       deraadt    43: #include <err.h>
1.23      millert    44: #include <errno.h>
1.1       deraadt    45: #include <ctype.h>
1.14      espie      46: #include <link.h>
1.37      miod       47:
1.1       deraadt    48: #include <stdio.h>
                     49: #include <stdlib.h>
                     50: #include <string.h>
1.20      mickey     51: #include <getopt.h>
1.47      miod       52: #include "util.h"
1.27      mickey     53: #include "elfuncs.h"
1.1       deraadt    54:
1.20      mickey     55: #define        SYMTABMAG       "/ "
                     56: #define        STRTABMAG       "//"
1.41      miod       57: #define        SYM64MAG        "/SYM64/         "
1.20      mickey     58:
                     59: union hdr {
1.27      mickey     60:        Elf32_Ehdr elf32;
                     61:        Elf64_Ehdr elf64;
1.20      mickey     62: };
1.27      mickey     63:
1.20      mickey     64: int armap;
                     65: int demangle;
                     66: int non_object_warning;
1.1       deraadt    67: int print_only_external_symbols;
                     68: int print_only_undefined_symbols;
                     69: int print_all_symbols;
                     70: int print_file_each_line;
1.20      mickey     71: int show_extensions;
                     72: int issize;
1.47      miod       73: char posix_fmtstr[6];
                     74: int posix_output;
                     75: char posix_radix = 'x';
1.23      millert    76: int usemmap = 1;
1.45      guenther   77: int dynamic_only;
1.20      mickey     78:
                     79: /* size vars */
                     80: unsigned long total_text, total_data, total_bss, total_total;
                     81: int non_object_warning, print_totals;
1.1       deraadt    82:
                     83: int rev;
1.16      millert    84: int fname(const void *, const void *);
                     85: int rname(const void *, const void *);
                     86: int value(const void *, const void *);
1.47      miod       87: char *otherstring(struct xnlist *);
1.36      deraadt    88: int (*sfunc)(const void *, const void *) = fname;
1.47      miod       89: char typeletter(struct xnlist *);
1.39      deraadt    90: int mmbr_name(struct ar_hdr *, char **, int, int *, FILE *);
                     91: int show_symtab(off_t, u_long, const char *, FILE *);
                     92: int show_symdef(off_t, u_long, const char *, FILE *);
1.8       espie      93:
1.1       deraadt    94: /* some macros for symbol type (nlist.n_type) handling */
                     95: #define        IS_EXTERNAL(x)          ((x) & N_EXT)
                     96: #define        SYMBOL_TYPE(x)          ((x) & (N_TYPE | N_STAB))
                     97:
1.16      millert    98: void    pipe2cppfilt(void);
                     99: void    usage(void);
1.47      miod      100: char   *symname(struct xnlist *);
1.20      mickey    101: int    process_file(int, const char *);
                    102: int    show_archive(int, const char *, FILE *);
                    103: int    show_file(int, int, const char *, FILE *fp, off_t, union hdr *);
1.47      miod      104: void   print_symbol(const char *, struct xnlist *);
1.20      mickey    105:
1.47      miod      106: #define        OPTSTRING_NM    "aABCDegnopPrst:uvw"
1.20      mickey    107: const struct option longopts_nm[] = {
                    108:        { "debug-syms",         no_argument,            0,      'a' },
                    109:        { "demangle",           no_argument,            0,      'C' },
1.45      guenther  110:        { "dynamic",            no_argument,            0,      'D' },
1.20      mickey    111:        { "extern-only",        no_argument,            0,      'g' },
                    112: /*     { "line-numbers",       no_argument,            0,      'l' }, */
                    113:        { "no-sort",            no_argument,            0,      'p' },
                    114:        { "numeric-sort",       no_argument,            0,      'n' },
                    115:        { "print-armap",        no_argument,            0,      's' },
                    116:        { "print-file-name",    no_argument,            0,      'o' },
                    117:        { "reverse-sort",       no_argument,            0,      'r' },
                    118: /*     { "size-sort",          no_argument,            &szval, 1 }, */
                    119:        { "undefined-only",     no_argument,            0,      'u' },
                    120:        { "help",               no_argument,            0,      '?' },
                    121:        { NULL }
                    122: };
1.10      espie     123:
1.1       deraadt   124: /*
                    125:  * main()
                    126:  *     parse command line, execute process_file() for each file
                    127:  *     specified on the command line.
                    128:  */
1.20      mickey    129: int
1.19      deraadt   130: main(int argc, char *argv[])
1.1       deraadt   131: {
1.20      mickey    132:        extern char *__progname;
1.1       deraadt   133:        extern int optind;
1.20      mickey    134:        const char *optstr;
                    135:        const struct option *lopts;
                    136:        int ch, eval;
                    137:
1.50      deraadt   138:        if (pledge("stdio rpath proc exec", NULL) == -1)
                    139:                err(1, "pledge");
                    140:
1.20      mickey    141:        optstr = OPTSTRING_NM;
                    142:        lopts = longopts_nm;
                    143:        if (!strcmp(__progname, "size")) {
1.50      deraadt   144:                if (pledge("stdio rpath", NULL) == -1)
                    145:                        err(1, "pledge");
                    146:
                    147:                issize = 1;
1.20      mickey    148:                optstr = "tw";
                    149:                lopts = NULL;
                    150:        }
1.1       deraadt   151:
1.20      mickey    152:        while ((ch = getopt_long(argc, argv, optstr, lopts, NULL)) != -1) {
1.1       deraadt   153:                switch (ch) {
                    154:                case 'a':
                    155:                        print_all_symbols = 1;
                    156:                        break;
1.10      espie     157:                case 'B':
                    158:                        /* no-op, compat with gnu-nm */
                    159:                        break;
                    160:                case 'C':
                    161:                        demangle = 1;
1.45      guenther  162:                        break;
                    163:                case 'D':
                    164:                        dynamic_only = 1;
1.10      espie     165:                        break;
1.12      espie     166:                case 'e':
                    167:                        show_extensions = 1;
                    168:                        break;
1.1       deraadt   169:                case 'g':
                    170:                        print_only_external_symbols = 1;
                    171:                        break;
                    172:                case 'n':
1.20      mickey    173:                case 'v':
1.1       deraadt   174:                        sfunc = value;
                    175:                        break;
1.20      mickey    176:                case 'A':
1.1       deraadt   177:                case 'o':
                    178:                        print_file_each_line = 1;
                    179:                        break;
                    180:                case 'p':
                    181:                        sfunc = NULL;
                    182:                        break;
1.47      miod      183:                case 'P':
                    184:                        posix_output = 1;
                    185:                        break;
1.1       deraadt   186:                case 'r':
                    187:                        rev = 1;
                    188:                        break;
1.20      mickey    189:                case 's':
                    190:                        armap = 1;
                    191:                        break;
1.1       deraadt   192:                case 'u':
                    193:                        print_only_undefined_symbols = 1;
                    194:                        break;
                    195:                case 'w':
1.20      mickey    196:                        non_object_warning = 1;
1.1       deraadt   197:                        break;
1.20      mickey    198:                case 't':
                    199:                        if (issize) {
                    200:                                print_totals = 1;
1.47      miod      201:                        } else {
                    202:                                posix_radix = *optarg;
                    203:                                if (strlen(optarg) != 1 ||
                    204:                                    (posix_radix != 'd' && posix_radix != 'o' &&
                    205:                                     posix_radix != 'x'))
                    206:                                        usage();
1.20      mickey    207:                        }
1.47      miod      208:                        break;
1.1       deraadt   209:                case '?':
                    210:                default:
                    211:                        usage();
                    212:                }
                    213:        }
1.10      espie     214:
1.47      miod      215:        if (posix_output)
                    216:                (void)snprintf(posix_fmtstr, sizeof posix_fmtstr, "%%%c %%%c",
                    217:                    posix_radix, posix_radix);
1.10      espie     218:        if (demangle)
                    219:                pipe2cppfilt();
1.48      deraadt   220:
1.49      deraadt   221:        if (pledge("stdio rpath", NULL) == -1)
                    222:                err(1, "pledge");
1.48      deraadt   223:
1.1       deraadt   224:        argv += optind;
1.20      mickey    225:        argc -= optind;
1.1       deraadt   226:
                    227:        if (rev && sfunc == fname)
                    228:                sfunc = rname;
                    229:
1.20      mickey    230:        eval = 0;
                    231:        if (*argv)
1.1       deraadt   232:                do {
1.20      mickey    233:                        eval |= process_file(argc, *argv);
1.1       deraadt   234:                } while (*++argv);
1.20      mickey    235:        else
                    236:                eval |= process_file(1, "a.out");
                    237:
                    238:        if (issize && print_totals)
                    239:                printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
                    240:                    total_text, total_data, total_bss,
                    241:                    total_total, total_total);
                    242:        exit(eval);
1.1       deraadt   243: }
                    244:
                    245: /*
                    246:  * process_file()
                    247:  *     show symbols in the file given as an argument.  Accepts archive and
                    248:  *     object files as input.
                    249:  */
1.20      mickey    250: int
                    251: process_file(int count, const char *fname)
1.1       deraadt   252: {
1.20      mickey    253:        union hdr exec_head;
1.1       deraadt   254:        FILE *fp;
                    255:        int retval;
1.24      miod      256:        size_t bytes;
1.1       deraadt   257:        char magic[SARMAG];
1.25      deraadt   258:
1.1       deraadt   259:        if (!(fp = fopen(fname, "r"))) {
1.6       deraadt   260:                warn("cannot read %s", fname);
1.1       deraadt   261:                return(1);
                    262:        }
                    263:
1.20      mickey    264:        if (!issize && count > 1)
1.1       deraadt   265:                (void)printf("\n%s:\n", fname);
1.25      deraadt   266:
1.1       deraadt   267:        /*
                    268:         * first check whether this is an object file - read a object
                    269:         * header, and skip back to the beginning
                    270:         */
1.24      miod      271:        bzero(&exec_head, sizeof(exec_head));
                    272:        bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);
                    273:        if (bytes < sizeof(exec_head)) {
1.37      miod      274:                if (bytes < sizeof(exec_head.elf32) || IS_ELF(exec_head.elf32)) {
1.24      miod      275:                        warnx("%s: bad format", fname);
                    276:                        (void)fclose(fp);
                    277:                        return(1);
                    278:                }
1.1       deraadt   279:        }
                    280:        rewind(fp);
                    281:
                    282:        /* this could be an archive */
1.37      miod      283:        if (!IS_ELF(exec_head.elf32)) {
1.1       deraadt   284:                if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
                    285:                    strncmp(magic, ARMAG, SARMAG)) {
1.2       deraadt   286:                        warnx("%s: not object file or archive", fname);
1.1       deraadt   287:                        (void)fclose(fp);
                    288:                        return(1);
                    289:                }
1.20      mickey    290:                retval = show_archive(count, fname, fp);
1.1       deraadt   291:        } else
1.20      mickey    292:                retval = show_file(count, 1, fname, fp, 0, &exec_head);
1.1       deraadt   293:        (void)fclose(fp);
                    294:        return(retval);
                    295: }
                    296:
1.20      mickey    297: char *nametab;
                    298:
                    299: /*
                    300:  *
                    301:  *     given the archive member header -- produce member name
                    302:  */
                    303: int
                    304: mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)
                    305: {
                    306:        char *p = *name + strlen(*name);
                    307:        long i;
                    308:
                    309:        if (nametab && arh->ar_name[0] == '/') {
                    310:                int len;
                    311:
                    312:                i = atol(&arh->ar_name[1]);
                    313:                len = strlen(&nametab[i]);
                    314:                if (len > *namelen) {
                    315:                        p -= (long)*name;
                    316:                        if ((*name = realloc(*name, baselen+len)) == NULL)
                    317:                                err(1, NULL);
                    318:                        *namelen = len;
                    319:                        p += (long)*name;
                    320:                }
                    321:                strlcpy(p, &nametab[i], len);
                    322:                p += len;
                    323:        } else
                    324: #ifdef AR_EFMT1
                    325:        /*
                    326:         * BSD 4.4 extended AR format: #1/<namelen>, with name as the
                    327:         * first <namelen> bytes of the file
                    328:         */
                    329:        if ((arh->ar_name[0] == '#') &&
                    330:            (arh->ar_name[1] == '1') &&
1.25      deraadt   331:            (arh->ar_name[2] == '/') &&
1.40      deraadt   332:            (isdigit((unsigned char)arh->ar_name[3]))) {
1.20      mickey    333:                int len = atoi(&arh->ar_name[3]);
                    334:
                    335:                if (len > *namelen) {
                    336:                        p -= (long)*name;
                    337:                        if ((*name = realloc(*name, baselen+len)) == NULL)
                    338:                                err(1, NULL);
                    339:                        *namelen = len;
                    340:                        p += (long)*name;
                    341:                }
                    342:                if (fread(p, len, 1, fp) != 1) {
                    343:                        warnx("%s: premature EOF", *name);
                    344:                        free(*name);
                    345:                        return(1);
                    346:                }
                    347:                p += len;
                    348:        } else
                    349: #endif
                    350:        for (i = 0; i < sizeof(arh->ar_name); ++i)
                    351:                if (arh->ar_name[i] && arh->ar_name[i] != ' ')
                    352:                        *p++ = arh->ar_name[i];
                    353:        *p = '\0';
                    354:        if (p[-1] == '/')
                    355:                *--p = '\0';
                    356:
                    357:        return (0);
                    358: }
                    359:
                    360: /*
                    361:  * show_symtab()
                    362:  *     show archive ranlib index (fs5)
                    363:  */
                    364: int
                    365: show_symtab(off_t off, u_long len, const char *name, FILE *fp)
                    366: {
                    367:        struct ar_hdr ar_head;
                    368:        int *symtab, *ps;
                    369:        char *strtab, *p;
                    370:        int num, rval = 0;
1.23      millert   371:        int namelen;
1.33      jasper    372:        off_t restore;
                    373:
                    374:        restore = ftello(fp);
1.20      mickey    375:
1.22      millert   376:        MMAP(symtab, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);
                    377:        if (symtab == MAP_FAILED)
1.20      mickey    378:                return (1);
                    379:
                    380:        namelen = sizeof(ar_head.ar_name);
                    381:        if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) {
                    382:                warn("%s: malloc", name);
1.22      millert   383:                MUNMAP(symtab, len);
1.20      mickey    384:        }
                    385:
                    386:        printf("\nArchive index:\n");
                    387:        num = betoh32(*symtab);
                    388:        strtab = (char *)(symtab + num + 1);
                    389:        for (ps = symtab + 1; num--; ps++, strtab += strlen(strtab) + 1) {
                    390:                if (fseeko(fp, betoh32(*ps), SEEK_SET)) {
                    391:                        warn("%s: fseeko", name);
                    392:                        rval = 1;
                    393:                        break;
                    394:                }
                    395:
                    396:                if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
                    397:                    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
                    398:                        warnx("%s: member fseeko", name);
                    399:                        rval = 1;
                    400:                        break;
                    401:                }
                    402:
                    403:                *p = '\0';
                    404:                if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
                    405:                        rval = 1;
                    406:                        break;
                    407:                }
                    408:
                    409:                printf("%s in %s\n", strtab, p);
                    410:        }
                    411:
1.33      jasper    412:        fseeko(fp, restore, SEEK_SET);
                    413:
1.20      mickey    414:        free(p);
1.22      millert   415:        MUNMAP(symtab, len);
1.20      mickey    416:        return (rval);
                    417: }
                    418:
                    419: /*
                    420:  * show_symdef()
                    421:  *     show archive ranlib index (gob)
                    422:  */
                    423: int
                    424: show_symdef(off_t off, u_long len, const char *name, FILE *fp)
                    425: {
                    426:        struct ranlib *prn, *eprn;
                    427:        struct ar_hdr ar_head;
1.39      deraadt   428:        char *symdef;
1.20      mickey    429:        char *strtab, *p;
                    430:        u_long size;
1.23      millert   431:        int namelen, rval = 0;
1.20      mickey    432:
1.22      millert   433:        MMAP(symdef, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);
                    434:        if (symdef == MAP_FAILED)
1.20      mickey    435:                return (1);
1.23      millert   436:        if (usemmap)
1.22      millert   437:                (void)madvise(symdef, len, MADV_SEQUENTIAL);
1.20      mickey    438:
                    439:        namelen = sizeof(ar_head.ar_name);
                    440:        if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) {
                    441:                warn("%s: malloc", name);
1.22      millert   442:                MUNMAP(symdef, len);
1.20      mickey    443:                return (1);
                    444:        }
                    445:
                    446:        size = *(u_long *)symdef;
1.39      deraadt   447:        prn = (struct ranlib *)(symdef + sizeof(u_long));
1.20      mickey    448:        eprn = prn + size / sizeof(*prn);
                    449:        strtab = symdef + sizeof(u_long) + size + sizeof(u_long);
                    450:
                    451:        printf("\nArchive index:\n");
                    452:        for (; prn < eprn; prn++) {
                    453:                if (fseeko(fp, prn->ran_off, SEEK_SET)) {
                    454:                        warn("%s: fseeko", name);
                    455:                        rval = 1;
                    456:                        break;
                    457:                }
                    458:
                    459:                if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
                    460:                    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
                    461:                        warnx("%s: member fseeko", name);
                    462:                        rval = 1;
                    463:                        break;
                    464:                }
                    465:
                    466:                *p = '\0';
                    467:                if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
                    468:                        rval = 1;
                    469:                        break;
                    470:                }
                    471:
                    472:                printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p);
                    473:        }
                    474:
                    475:        free(p);
1.22      millert   476:        MUNMAP(symdef, len);
1.20      mickey    477:        return (rval);
                    478: }
                    479:
1.1       deraadt   480: /*
                    481:  * show_archive()
                    482:  *     show symbols in the given archive file
                    483:  */
1.20      mickey    484: int
                    485: show_archive(int count, const char *fname, FILE *fp)
1.1       deraadt   486: {
                    487:        struct ar_hdr ar_head;
1.20      mickey    488:        union hdr exec_head;
1.1       deraadt   489:        int i, rval;
1.20      mickey    490:        off_t last_ar_off, foff, symtaboff;
                    491:        char *name;
1.1       deraadt   492:        int baselen, namelen;
1.20      mickey    493:        u_long mmbrlen, symtablen;
1.1       deraadt   494:
                    495:        baselen = strlen(fname) + 3;
1.47      miod      496:        if (posix_output)
                    497:                baselen += 2;
1.1       deraadt   498:        namelen = sizeof(ar_head.ar_name);
1.20      mickey    499:        if ((name = malloc(baselen + namelen)) == NULL)
                    500:                err(1, NULL);
1.1       deraadt   501:
                    502:        rval = 0;
1.20      mickey    503:        nametab = NULL;
                    504:        symtaboff = 0;
                    505:        symtablen = 0;
1.1       deraadt   506:
                    507:        /* while there are more entries in the archive */
1.20      mickey    508:        while (fread(&ar_head, sizeof(ar_head), 1, fp) == 1) {
1.1       deraadt   509:                /* bad archive entry - stop processing this archive */
1.20      mickey    510:                if (memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
1.2       deraadt   511:                        warnx("%s: bad format archive header", fname);
1.20      mickey    512:                        rval = 1;
                    513:                        break;
1.1       deraadt   514:                }
                    515:
                    516:                /* remember start position of current archive object */
1.20      mickey    517:                last_ar_off = ftello(fp);
                    518:                mmbrlen = atol(ar_head.ar_size);
1.1       deraadt   519:
1.20      mickey    520:                if (strncmp(ar_head.ar_name, RANLIBMAG,
                    521:                    sizeof(RANLIBMAG) - 1) == 0) {
                    522:                        if (!issize && armap &&
                    523:                            show_symdef(last_ar_off, mmbrlen, fname, fp)) {
                    524:                                rval = 1;
                    525:                                break;
                    526:                        }
1.1       deraadt   527:                        goto skip;
1.20      mickey    528:                } else if (strncmp(ar_head.ar_name, SYMTABMAG,
                    529:                    sizeof(SYMTABMAG) - 1) == 0) {
                    530:                        /* if nametab hasn't been seen yet -- doit later */
                    531:                        if (!nametab) {
                    532:                                symtablen = mmbrlen;
                    533:                                symtaboff = last_ar_off;
                    534:                                goto skip;
                    535:                        }
                    536:
                    537:                        /* load the Sys5 long names table */
                    538:                } else if (strncmp(ar_head.ar_name, STRTABMAG,
                    539:                    sizeof(STRTABMAG) - 1) == 0) {
                    540:                        char *p;
                    541:
                    542:                        if ((nametab = malloc(mmbrlen)) == NULL) {
                    543:                                warn("%s: nametab", fname);
                    544:                                rval = 1;
                    545:                                break;
                    546:                        }
                    547:
                    548:                        if (fread(nametab, mmbrlen, (size_t)1, fp) != 1) {
                    549:                                warnx("%s: premature EOF", fname);
                    550:                                rval = 1;
                    551:                                break;
                    552:                        }
                    553:
                    554:                        for (p = nametab, i = mmbrlen; i--; p++)
                    555:                                if (*p == '\n')
                    556:                                        *p = '\0';
                    557:
                    558:                        if (issize || !armap || !symtablen || !symtaboff)
                    559:                                goto skip;
                    560:                }
1.41      miod      561: #ifdef __mips64
                    562:                else if (memcmp(ar_head.ar_name, SYM64MAG,
                    563:                    sizeof(ar_head.ar_name)) == 0) {
                    564:                        /* IRIX6-compatible archive map */
                    565:                        goto skip;
                    566:                }
                    567: #endif
1.20      mickey    568:
                    569:                if (!issize && armap && symtablen && symtaboff) {
                    570:                        if (show_symtab(symtaboff, symtablen, fname, fp)) {
                    571:                                rval = 1;
                    572:                                break;
                    573:                        } else {
                    574:                                symtaboff = 0;
                    575:                                symtablen = 0;
                    576:                        }
                    577:                }
1.1       deraadt   578:
                    579:                /*
                    580:                 * construct a name of the form "archive.a:obj.o:" for the
                    581:                 * current archive entry if the object name is to be printed
                    582:                 * on each output line
                    583:                 */
1.20      mickey    584:                *name = '\0';
1.47      miod      585:                if (posix_output)
                    586:                        snprintf(name, baselen - 1, "%s[", fname);
                    587:                else if (count > 1)
1.20      mickey    588:                        snprintf(name, baselen - 1, "%s:", fname);
                    589:
                    590:                if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
                    591:                        rval = 1;
                    592:                        break;
1.17      deraadt   593:                }
1.20      mickey    594:
1.47      miod      595:                if (posix_output)
                    596:                        strlcat(name, "]", baselen + namelen);
                    597:
1.20      mickey    598:                foff = ftello(fp);
1.1       deraadt   599:
                    600:                /* get and check current object's header */
                    601:                if (fread((char *)&exec_head, sizeof(exec_head),
                    602:                    (size_t)1, fp) != 1) {
1.20      mickey    603:                        warnx("%s: premature EOF", fname);
                    604:                        rval = 1;
                    605:                        break;
1.1       deraadt   606:                }
                    607:
1.20      mickey    608:                rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);
1.1       deraadt   609:                /*
                    610:                 * skip to next archive object - it starts at the next
1.25      deraadt   611:                 * even byte boundary
1.1       deraadt   612:                 */
                    613: #define even(x) (((x) + 1) & ~1)
1.20      mickey    614: skip:          if (fseeko(fp, last_ar_off + even(mmbrlen), SEEK_SET)) {
1.2       deraadt   615:                        warn("%s", fname);
1.20      mickey    616:                        rval = 1;
                    617:                        break;
1.1       deraadt   618:                }
                    619:        }
1.51    ! mmcc      620:        free(nametab);
        !           621:        nametab = NULL;
1.20      mickey    622:        free(name);
1.1       deraadt   623:        return(rval);
                    624: }
                    625:
1.20      mickey    626: char *stab;
                    627:
1.1       deraadt   628: /*
1.20      mickey    629:  * show_file()
1.1       deraadt   630:  *     show symbols from the object file pointed to by fp.  The current
1.29      espie     631:  *     file pointer for fp is expected to be at the beginning of an object
                    632:  *     file header.
1.1       deraadt   633:  */
1.20      mickey    634: int
                    635: show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
1.1       deraadt   636: {
1.20      mickey    637:        u_long text, data, bss, total;
1.47      miod      638:        struct xnlist *np, *names, **snames;
1.37      miod      639:        int i, nrawnames, nnames;
1.27      mickey    640:        size_t stabsize;
1.20      mickey    641:
1.27      mickey    642:        if (IS_ELF(head->elf32) &&
                    643:            head->elf32.e_ident[EI_CLASS] == ELFCLASS32 &&
                    644:            head->elf32.e_ident[EI_VERSION] == ELF_TARG_VER) {
                    645:                void *shdr;
1.20      mickey    646:
1.27      mickey    647:                if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
1.20      mickey    648:                        return (1);
                    649:
1.27      mickey    650:                i = issize?
                    651:                    elf32_size(&head->elf32, shdr, &text, &data, &bss) :
                    652:                    elf32_symload(name, fp, foff, &head->elf32, shdr,
                    653:                        &names, &snames, &stabsize, &nrawnames);
                    654:                free(shdr);
                    655:                if (i)
                    656:                        return (i);
                    657:
                    658:        } else if (IS_ELF(head->elf64) &&
                    659:            head->elf64.e_ident[EI_CLASS] == ELFCLASS64 &&
                    660:            head->elf64.e_ident[EI_VERSION] == ELF_TARG_VER) {
                    661:                void *shdr;
1.20      mickey    662:
1.27      mickey    663:                if (!(shdr = elf64_load_shdrs(name, fp, foff, &head->elf64)))
                    664:                        return (1);
1.20      mickey    665:
1.27      mickey    666:                i = issize?
                    667:                    elf64_size(&head->elf64, shdr, &text, &data, &bss) :
                    668:                    elf64_symload(name, fp, foff, &head->elf64, shdr,
                    669:                        &names, &snames, &stabsize, &nrawnames);
                    670:                free(shdr);
                    671:                if (i)
                    672:                        return (i);
1.37      miod      673:        } else {
1.36      deraadt   674:                if (warn_fmt)
                    675:                        warnx("%s: bad format", name);
                    676:                return (1);
1.37      miod      677:        }
1.8       espie     678:
1.20      mickey    679:        if (issize) {
                    680:                static int first = 1;
1.1       deraadt   681:
1.20      mickey    682:                if (first) {
                    683:                        first = 0;
                    684:                        printf("text\tdata\tbss\tdec\thex\n");
                    685:                }
1.1       deraadt   686:
1.20      mickey    687:                total = text + data + bss;
                    688:                printf("%lu\t%lu\t%lu\t%lu\t%lx",
                    689:                    text, data, bss, total, total);
                    690:                if (count > 1)
                    691:                        (void)printf("\t%s", name);
                    692:
                    693:                total_text += text;
                    694:                total_data += data;
                    695:                total_bss += bss;
                    696:                total_total += total;
1.1       deraadt   697:
1.20      mickey    698:                printf("\n");
                    699:                return (0);
1.1       deraadt   700:        }
1.20      mickey    701:        /* else we are nm */
1.1       deraadt   702:
                    703:        /*
1.20      mickey    704:         * it seems that string table is sequential
                    705:         * relative to the symbol table order
1.1       deraadt   706:         */
1.23      millert   707:        if (sfunc == NULL && usemmap)
                    708:                (void)madvise(stab, stabsize, MADV_SEQUENTIAL);
1.1       deraadt   709:
                    710:        /*
                    711:         * fix up the symbol table and filter out unwanted entries
                    712:         *
                    713:         * common symbols are characterized by a n_type of N_UNDF and a
                    714:         * non-zero n_value -- change n_type to N_COMM for all such
                    715:         * symbols to make life easier later.
                    716:         *
                    717:         * filter out all entries which we don't want to print anyway
                    718:         */
                    719:        for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
1.13      espie     720:                /*
                    721:                 * make n_un.n_name a character pointer by adding the string
                    722:                 * table's base to n_un.n_strx
                    723:                 *
                    724:                 * don't mess with zero offsets
                    725:                 */
1.47      miod      726:                if (np->nl.n_un.n_strx)
                    727:                        np->nl.n_un.n_name = stab + np->nl.n_un.n_strx;
1.13      espie     728:                else
1.47      miod      729:                        np->nl.n_un.n_name = "";
                    730:                if (print_only_external_symbols && !IS_EXTERNAL(np->nl.n_type))
1.1       deraadt   731:                        continue;
                    732:                if (print_only_undefined_symbols &&
1.47      miod      733:                    SYMBOL_TYPE(np->nl.n_type) != N_UNDF)
1.1       deraadt   734:                        continue;
                    735:
1.13      espie     736:                snames[nnames++] = np;
1.1       deraadt   737:        }
                    738:
                    739:        /* sort the symbol table if applicable */
                    740:        if (sfunc)
1.13      espie     741:                qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);
1.1       deraadt   742:
1.20      mickey    743:        if (count > 1)
                    744:                (void)printf("\n%s:\n", name);
                    745:
1.1       deraadt   746:        /* print out symbols */
1.44      guenther  747:        for (i = 0; i < nnames; i++)
1.37      miod      748:                print_symbol(name, snames[i]);
1.1       deraadt   749:
1.20      mickey    750:        free(snames);
                    751:        free(names);
1.22      millert   752:        MUNMAP(stab, stabsize);
1.1       deraadt   753:        return(0);
1.20      mickey    754: }
                    755:
1.13      espie     756: char *
1.47      miod      757: symname(struct xnlist *sym)
1.13      espie     758: {
1.47      miod      759:        return sym->nl.n_un.n_name;
1.13      espie     760: }
                    761:
1.1       deraadt   762: /*
                    763:  * print_symbol()
                    764:  *     show one symbol
                    765:  */
1.13      espie     766: void
1.47      miod      767: print_symbol(const char *name, struct xnlist *sym)
1.1       deraadt   768: {
1.47      miod      769:        if (print_file_each_line) {
                    770:                if (posix_output)
                    771:                        (void)printf("%s: ", name);
                    772:                else
                    773:                        (void)printf("%s:", name);
                    774:        }
1.1       deraadt   775:
1.47      miod      776:        if (posix_output) {
                    777:                (void)printf("%s %c ", symname(sym), typeletter(sym));
                    778:                if (SYMBOL_TYPE(sym->nl.n_type) != N_UNDF)
                    779:                        (void)printf(posix_fmtstr, sym->nl.n_value,
                    780:                            sym->n_size);
                    781:                (void)printf("\n");
                    782:        } else {
                    783:                /*
                    784:                 * handle undefined-only format especially (no space is
                    785:                 * left for symbol values, no type field is printed)
                    786:                 */
                    787:                if (!print_only_undefined_symbols) {
                    788:                        /* print symbol's value */
                    789:                        if (SYMBOL_TYPE(sym->nl.n_type) == N_UNDF)
                    790:                                (void)printf("        ");
                    791:                        else
                    792:                                (void)printf("%08lx", sym->nl.n_value);
                    793:
                    794:                        /* print type information */
                    795:                        if (show_extensions)
                    796:                                (void)printf(" %c   ", typeletter(sym));
                    797:                        else
                    798:                                (void)printf(" %c ", typeletter(sym));
                    799:                }
1.10      espie     800:
1.47      miod      801:                (void)puts(symname(sym));
1.1       deraadt   802:        }
                    803: }
                    804:
                    805: /*
                    806:  * typeletter()
                    807:  *     return a description letter for the given basic type code of an
                    808:  *     symbol table entry.  The return value will be upper case for
                    809:  *     external, lower case for internal symbols.
                    810:  */
                    811: char
1.47      miod      812: typeletter(struct xnlist *np)
1.1       deraadt   813: {
1.47      miod      814:        int ext = IS_EXTERNAL(np->nl.n_type);
1.20      mickey    815:
1.47      miod      816:        if (np->nl.n_other)
                    817:                return np->nl.n_other;
1.20      mickey    818:
1.47      miod      819:        switch(SYMBOL_TYPE(np->nl.n_type)) {
1.1       deraadt   820:        case N_ABS:
1.20      mickey    821:                return(ext? 'A' : 'a');
1.1       deraadt   822:        case N_BSS:
1.20      mickey    823:                return(ext? 'B' : 'b');
1.1       deraadt   824:        case N_COMM:
1.20      mickey    825:                return(ext? 'C' : 'c');
1.1       deraadt   826:        case N_DATA:
1.20      mickey    827:                return(ext? 'D' : 'd');
1.1       deraadt   828:        case N_FN:
                    829:                /* NOTE: N_FN == N_WARNING,
                    830:                 * in this case, the N_EXT bit is to considered as
                    831:                 * part of the symbol's type itself.
                    832:                 */
1.20      mickey    833:                return(ext? 'F' : 'W');
1.1       deraadt   834:        case N_TEXT:
1.20      mickey    835:                return(ext? 'T' : 't');
1.1       deraadt   836:        case N_SIZE:
1.20      mickey    837:                return(ext? 'S' : 's');
1.1       deraadt   838:        case N_UNDF:
1.20      mickey    839:                return(ext? 'U' : 'u');
1.1       deraadt   840:        }
                    841:        return('?');
                    842: }
                    843:
1.13      espie     844: int
1.19      deraadt   845: fname(const void *a0, const void *b0)
1.1       deraadt   846: {
1.47      miod      847:        struct xnlist * const *a = a0, * const *b = b0;
1.1       deraadt   848:
1.47      miod      849:        return(strcmp((*a)->nl.n_un.n_name, (*b)->nl.n_un.n_name));
1.1       deraadt   850: }
                    851:
1.13      espie     852: int
1.19      deraadt   853: rname(const void *a0, const void *b0)
1.1       deraadt   854: {
1.47      miod      855:        struct xnlist * const *a = a0, * const *b = b0;
1.1       deraadt   856:
1.47      miod      857:        return(strcmp((*b)->nl.n_un.n_name, (*a)->nl.n_un.n_name));
1.1       deraadt   858: }
                    859:
1.13      espie     860: int
1.19      deraadt   861: value(const void *a0, const void *b0)
1.1       deraadt   862: {
1.47      miod      863:        struct xnlist * const *a = a0, * const *b = b0;
1.1       deraadt   864:
1.47      miod      865:        if (SYMBOL_TYPE((*a)->nl.n_type) == N_UNDF)
                    866:                if (SYMBOL_TYPE((*b)->nl.n_type) == N_UNDF)
1.1       deraadt   867:                        return(0);
                    868:                else
                    869:                        return(-1);
1.47      miod      870:        else if (SYMBOL_TYPE((*b)->nl.n_type) == N_UNDF)
1.1       deraadt   871:                return(1);
                    872:        if (rev) {
1.47      miod      873:                if ((*a)->nl.n_value == (*b)->nl.n_value)
1.1       deraadt   874:                        return(rname(a0, b0));
1.47      miod      875:                return((*b)->nl.n_value > (*a)->nl.n_value ? 1 : -1);
1.1       deraadt   876:        } else {
1.47      miod      877:                if ((*a)->nl.n_value == (*b)->nl.n_value)
1.1       deraadt   878:                        return(fname(a0, b0));
1.47      miod      879:                return((*a)->nl.n_value > (*b)->nl.n_value ? 1 : -1);
1.1       deraadt   880:        }
                    881: }
                    882:
1.10      espie     883: #define CPPFILT        "/usr/bin/c++filt"
                    884:
                    885: void
1.19      deraadt   886: pipe2cppfilt(void)
1.10      espie     887: {
                    888:        int pip[2];
                    889:        char *argv[2];
                    890:
                    891:        argv[0] = "c++filt";
                    892:        argv[1] = NULL;
                    893:
                    894:        if (pipe(pip) == -1)
                    895:                err(1, "pipe");
                    896:        switch(fork()) {
                    897:        case -1:
                    898:                err(1, "fork");
                    899:        default:
                    900:                dup2(pip[0], 0);
                    901:                close(pip[0]);
                    902:                close(pip[1]);
                    903:                execve(CPPFILT, argv, NULL);
                    904:                err(1, "execve");
                    905:        case 0:
                    906:                dup2(pip[1], 1);
                    907:                close(pip[1]);
                    908:                close(pip[0]);
                    909:        }
                    910: }
                    911:
1.11      smart     912: void
1.19      deraadt   913: usage(void)
1.1       deraadt   914: {
1.20      mickey    915:        extern char *__progname;
                    916:
                    917:        if (issize)
                    918:                fprintf(stderr, "usage: %s [-tw] [file ...]\n", __progname);
                    919:        else
1.47      miod      920:                fprintf(stderr, "usage: %s [-AaCDegnoPprsuw] [-t d|o|x] [file ...]\n",
1.20      mickey    921:                    __progname);
1.1       deraadt   922:        exit(1);
                    923: }