[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.37

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