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

1.26    ! mickey      1: /*     $OpenBSD: nm.c,v 1.25 2004/05/04 23:09:07 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:
                     36: #ifndef lint
1.20      mickey     37: static const char copyright[] =
1.1       deraadt    38: "@(#) Copyright (c) 1989, 1993\n\
                     39:        The Regents of the University of California.  All rights reserved.\n";
                     40: #endif /* not lint */
                     41:
                     42: #if 0
1.20      mickey     43: static const char sccsid[] = "@(#)nm.c 8.1 (Berkeley) 6/6/93";
1.1       deraadt    44: #endif
1.26    ! mickey     45: static const char rcsid[] = "$OpenBSD: nm.c,v 1.25 2004/05/04 23:09:07 deraadt Exp $";
1.1       deraadt    46:
1.5       deraadt    47: #include <sys/param.h>
1.20      mickey     48: #include <sys/mman.h>
1.1       deraadt    49: #include <a.out.h>
1.20      mickey     50: #include <elf_abi.h>
1.1       deraadt    51: #include <stab.h>
                     52: #include <ar.h>
                     53: #include <ranlib.h>
                     54: #include <unistd.h>
1.2       deraadt    55: #include <err.h>
1.23      millert    56: #include <errno.h>
1.1       deraadt    57: #include <ctype.h>
1.14      espie      58: #include <link.h>
1.20      mickey     59: #ifdef __ELF__
                     60: #include <link_aout.h>
                     61: #endif
1.1       deraadt    62: #include <stdio.h>
                     63: #include <stdlib.h>
                     64: #include <string.h>
1.20      mickey     65: #include <getopt.h>
1.8       espie      66: /* XXX get shared code to handle byte-order swaps */
                     67: #include "byte.c"
1.20      mickey     68: #include "elf.c"
1.7       niklas     69:
1.20      mickey     70: #ifdef MID_MACHINE_OVERRIDE
                     71: #undef MID_MACHINE
                     72: #define        MID_MACHINE     MID_MACHINE_OVERRIDE
                     73: #endif
1.1       deraadt    74:
1.20      mickey     75: #define        SYMTABMAG       "/ "
                     76: #define        STRTABMAG       "//"
                     77:
                     78: union hdr {
                     79:        struct exec aout;
                     80:        Elf_Ehdr elf;
                     81: };
                     82:
                     83: int armap;
                     84: int demangle;
                     85: int non_object_warning;
1.1       deraadt    86: int print_only_external_symbols;
                     87: int print_only_undefined_symbols;
                     88: int print_all_symbols;
                     89: int print_file_each_line;
1.20      mickey     90: int show_extensions;
                     91: int issize;
1.23      millert    92: int usemmap = 1;
1.20      mickey     93:
                     94: /* size vars */
                     95: unsigned long total_text, total_data, total_bss, total_total;
                     96: int non_object_warning, print_totals;
1.1       deraadt    97:
                     98: int rev;
1.16      millert    99: int fname(const void *, const void *);
                    100: int rname(const void *, const void *);
                    101: int value(const void *, const void *);
                    102: int (*sfunc)(const void *, const void *) = fname;
                    103: char *otherstring(struct nlist *);
                    104: char *typestring(unsigned int);
1.20      mickey    105: char typeletter(struct nlist *, int);
1.8       espie     106:
1.1       deraadt   107: /* some macros for symbol type (nlist.n_type) handling */
                    108: #define        IS_DEBUGGER_SYMBOL(x)   ((x) & N_STAB)
                    109: #define        IS_EXTERNAL(x)          ((x) & N_EXT)
                    110: #define        SYMBOL_TYPE(x)          ((x) & (N_TYPE | N_STAB))
                    111:
1.16      millert   112: void    pipe2cppfilt(void);
                    113: void    usage(void);
                    114: char   *symname(struct nlist *);
1.20      mickey    115: int    process_file(int, const char *);
                    116: int    show_archive(int, const char *, FILE *);
                    117: int    show_file(int, int, const char *, FILE *fp, off_t, union hdr *);
1.25      deraadt   118: void   print_symbol(const char *, struct nlist *, int);
1.20      mickey    119: int    elf_symload(const char *, FILE *, off_t, Elf_Ehdr *, Elf_Shdr *);
                    120:
                    121: #define        OPTSTRING_NM    "aABCegnoprsuvVw"
                    122: const struct option longopts_nm[] = {
                    123:        { "debug-syms",         no_argument,            0,      'a' },
                    124:        { "demangle",           no_argument,            0,      'C' },
                    125: /*     { "dynamic",            no_argument,            0,      'D' }, */
                    126:        { "extern-only",        no_argument,            0,      'g' },
                    127: /*     { "line-numbers",       no_argument,            0,      'l' }, */
                    128:        { "no-sort",            no_argument,            0,      'p' },
                    129:        { "numeric-sort",       no_argument,            0,      'n' },
                    130:        { "print-armap",        no_argument,            0,      's' },
                    131:        { "print-file-name",    no_argument,            0,      'o' },
                    132:        { "reverse-sort",       no_argument,            0,      'r' },
                    133: /*     { "size-sort",          no_argument,            &szval, 1 }, */
                    134:        { "undefined-only",     no_argument,            0,      'u' },
                    135:        { "version",            no_argument,            0,      'V' },
                    136:        { "help",               no_argument,            0,      '?' },
                    137:        { NULL }
                    138: };
1.10      espie     139:
1.1       deraadt   140: /*
                    141:  * main()
                    142:  *     parse command line, execute process_file() for each file
                    143:  *     specified on the command line.
                    144:  */
1.20      mickey    145: int
1.19      deraadt   146: main(int argc, char *argv[])
1.1       deraadt   147: {
1.20      mickey    148:        extern char *__progname;
1.1       deraadt   149:        extern int optind;
1.20      mickey    150:        const char *optstr;
                    151:        const struct option *lopts;
                    152:        int ch, eval;
                    153:
                    154:        optstr = OPTSTRING_NM;
                    155:        lopts = longopts_nm;
                    156:        if (!strcmp(__progname, "size")) {
                    157:                issize++;
                    158:                optstr = "tw";
                    159:                lopts = NULL;
                    160:        }
1.1       deraadt   161:
1.20      mickey    162:        while ((ch = getopt_long(argc, argv, optstr, lopts, NULL)) != -1) {
1.1       deraadt   163:                switch (ch) {
                    164:                case 'a':
                    165:                        print_all_symbols = 1;
                    166:                        break;
1.10      espie     167:                case 'B':
                    168:                        /* no-op, compat with gnu-nm */
                    169:                        break;
                    170:                case 'C':
                    171:                        demangle = 1;
                    172:                        break;
1.12      espie     173:                case 'e':
                    174:                        show_extensions = 1;
                    175:                        break;
1.1       deraadt   176:                case 'g':
                    177:                        print_only_external_symbols = 1;
                    178:                        break;
                    179:                case 'n':
1.20      mickey    180:                case 'v':
1.1       deraadt   181:                        sfunc = value;
                    182:                        break;
1.20      mickey    183:                case 'A':
1.1       deraadt   184:                case 'o':
                    185:                        print_file_each_line = 1;
                    186:                        break;
                    187:                case 'p':
                    188:                        sfunc = NULL;
                    189:                        break;
                    190:                case 'r':
                    191:                        rev = 1;
                    192:                        break;
1.20      mickey    193:                case 's':
                    194:                        armap = 1;
                    195:                        break;
1.1       deraadt   196:                case 'u':
                    197:                        print_only_undefined_symbols = 1;
                    198:                        break;
1.20      mickey    199:                case 'V':
                    200:                        fprintf(stderr, "%s\n", rcsid);
                    201:                        exit(0);
1.1       deraadt   202:                case 'w':
1.20      mickey    203:                        non_object_warning = 1;
1.1       deraadt   204:                        break;
1.20      mickey    205:                case 't':
                    206:                        if (issize) {
                    207:                                print_totals = 1;
                    208:                                break;
                    209:                        }
1.1       deraadt   210:                case '?':
                    211:                default:
                    212:                        usage();
                    213:                }
                    214:        }
1.10      espie     215:
                    216:        if (demangle)
                    217:                pipe2cppfilt();
1.1       deraadt   218:        argv += optind;
1.20      mickey    219:        argc -= optind;
1.1       deraadt   220:
                    221:        if (rev && sfunc == fname)
                    222:                sfunc = rname;
                    223:
1.20      mickey    224:        eval = 0;
                    225:        if (*argv)
1.1       deraadt   226:                do {
1.20      mickey    227:                        eval |= process_file(argc, *argv);
1.1       deraadt   228:                } while (*++argv);
1.20      mickey    229:        else
                    230:                eval |= process_file(1, "a.out");
                    231:
                    232:        if (issize && print_totals)
                    233:                printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
                    234:                    total_text, total_data, total_bss,
                    235:                    total_total, total_total);
                    236:        exit(eval);
1.1       deraadt   237: }
                    238:
                    239: /*
                    240:  * process_file()
                    241:  *     show symbols in the file given as an argument.  Accepts archive and
                    242:  *     object files as input.
                    243:  */
1.20      mickey    244: int
                    245: process_file(int count, const char *fname)
1.1       deraadt   246: {
1.20      mickey    247:        union hdr exec_head;
1.1       deraadt   248:        FILE *fp;
                    249:        int retval;
1.24      miod      250:        size_t bytes;
1.1       deraadt   251:        char magic[SARMAG];
1.25      deraadt   252:
1.1       deraadt   253:        if (!(fp = fopen(fname, "r"))) {
1.6       deraadt   254:                warn("cannot read %s", fname);
1.1       deraadt   255:                return(1);
                    256:        }
                    257:
1.20      mickey    258:        if (!issize && count > 1)
1.1       deraadt   259:                (void)printf("\n%s:\n", fname);
1.25      deraadt   260:
1.1       deraadt   261:        /*
                    262:         * first check whether this is an object file - read a object
                    263:         * header, and skip back to the beginning
                    264:         */
1.24      miod      265:        bzero(&exec_head, sizeof(exec_head));
                    266:        bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);
                    267:        if (bytes < sizeof(exec_head)) {
                    268:                if (bytes < sizeof(exec_head.aout) || IS_ELF(exec_head.elf)) {
                    269:                        warnx("%s: bad format", fname);
                    270:                        (void)fclose(fp);
                    271:                        return(1);
                    272:                }
1.1       deraadt   273:        }
                    274:        rewind(fp);
                    275:
                    276:        /* this could be an archive */
1.20      mickey    277:        if (!IS_ELF(exec_head.elf) && N_BADMAG(exec_head.aout)) {
1.1       deraadt   278:                if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
                    279:                    strncmp(magic, ARMAG, SARMAG)) {
1.2       deraadt   280:                        warnx("%s: not object file or archive", fname);
1.1       deraadt   281:                        (void)fclose(fp);
                    282:                        return(1);
                    283:                }
1.20      mickey    284:                retval = show_archive(count, fname, fp);
1.1       deraadt   285:        } else
1.20      mickey    286:                retval = show_file(count, 1, fname, fp, 0, &exec_head);
1.1       deraadt   287:        (void)fclose(fp);
                    288:        return(retval);
                    289: }
                    290:
1.20      mickey    291: char *nametab;
                    292:
                    293: /*
                    294:  *
                    295:  *     given the archive member header -- produce member name
                    296:  */
                    297: int
                    298: mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)
                    299: {
                    300:        char *p = *name + strlen(*name);
                    301:        long i;
                    302:
                    303:        if (nametab && arh->ar_name[0] == '/') {
                    304:                int len;
                    305:
                    306:                i = atol(&arh->ar_name[1]);
                    307:                len = strlen(&nametab[i]);
                    308:                if (len > *namelen) {
                    309:                        p -= (long)*name;
                    310:                        if ((*name = realloc(*name, baselen+len)) == NULL)
                    311:                                err(1, NULL);
                    312:                        *namelen = len;
                    313:                        p += (long)*name;
                    314:                }
                    315:                strlcpy(p, &nametab[i], len);
                    316:                p += len;
                    317:        } else
                    318: #ifdef AR_EFMT1
                    319:        /*
                    320:         * BSD 4.4 extended AR format: #1/<namelen>, with name as the
                    321:         * first <namelen> bytes of the file
                    322:         */
                    323:        if ((arh->ar_name[0] == '#') &&
                    324:            (arh->ar_name[1] == '1') &&
1.25      deraadt   325:            (arh->ar_name[2] == '/') &&
1.20      mickey    326:            (isdigit(arh->ar_name[3]))) {
                    327:                int len = atoi(&arh->ar_name[3]);
                    328:
                    329:                if (len > *namelen) {
                    330:                        p -= (long)*name;
                    331:                        if ((*name = realloc(*name, baselen+len)) == NULL)
                    332:                                err(1, NULL);
                    333:                        *namelen = len;
                    334:                        p += (long)*name;
                    335:                }
                    336:                if (fread(p, len, 1, fp) != 1) {
                    337:                        warnx("%s: premature EOF", *name);
                    338:                        free(*name);
                    339:                        return(1);
                    340:                }
                    341:                p += len;
                    342:        } else
                    343: #endif
                    344:        for (i = 0; i < sizeof(arh->ar_name); ++i)
                    345:                if (arh->ar_name[i] && arh->ar_name[i] != ' ')
                    346:                        *p++ = arh->ar_name[i];
                    347:        *p = '\0';
                    348:        if (p[-1] == '/')
                    349:                *--p = '\0';
                    350:
                    351:        return (0);
                    352: }
                    353:
1.22      millert   354: #define        MMAP(ptr, len, prot, flags, fd, off)    do {            \
1.23      millert   355:        if ((ptr = mmap(NULL, len, prot, flags, fd, off)) == MAP_FAILED) { \
                    356:                usemmap = 0;                                            \
                    357:                if (errno != EINVAL)                                    \
                    358:                        warn("mmap");                                   \
                    359:                else if ((ptr = malloc(len)) == NULL) {                 \
1.22      millert   360:                        ptr = MAP_FAILED;                               \
                    361:                        warn("malloc");                                 \
                    362:                } else if (pread(fd, ptr, len, off) != len) {           \
                    363:                        free(ptr);                                      \
                    364:                        ptr = MAP_FAILED;                               \
                    365:                        warn("pread");                                  \
                    366:                }                                                       \
                    367:        }                                                               \
                    368: } while (0)
                    369:
                    370: #define MUNMAP(addr, len)      do {                                    \
1.23      millert   371:        if (usemmap)                                                    \
1.22      millert   372:                munmap(addr, len);                                      \
                    373:        else                                                            \
                    374:                free(addr);                                             \
                    375: } while (0)
                    376:
1.20      mickey    377: /*
                    378:  * show_symtab()
                    379:  *     show archive ranlib index (fs5)
                    380:  */
                    381: int
                    382: show_symtab(off_t off, u_long len, const char *name, FILE *fp)
                    383: {
                    384:        struct ar_hdr ar_head;
                    385:        int *symtab, *ps;
                    386:        char *strtab, *p;
                    387:        int num, rval = 0;
1.23      millert   388:        int namelen;
1.20      mickey    389:
1.22      millert   390:        MMAP(symtab, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);
                    391:        if (symtab == MAP_FAILED)
1.20      mickey    392:                return (1);
                    393:
                    394:        namelen = sizeof(ar_head.ar_name);
                    395:        if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) {
                    396:                warn("%s: malloc", name);
1.22      millert   397:                MUNMAP(symtab, len);
1.20      mickey    398:        }
                    399:
                    400:        printf("\nArchive index:\n");
                    401:        num = betoh32(*symtab);
                    402:        strtab = (char *)(symtab + num + 1);
                    403:        for (ps = symtab + 1; num--; ps++, strtab += strlen(strtab) + 1) {
                    404:                if (fseeko(fp, betoh32(*ps), SEEK_SET)) {
                    405:                        warn("%s: fseeko", name);
                    406:                        rval = 1;
                    407:                        break;
                    408:                }
                    409:
                    410:                if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
                    411:                    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
                    412:                        warnx("%s: member fseeko", name);
                    413:                        rval = 1;
                    414:                        break;
                    415:                }
                    416:
                    417:                *p = '\0';
                    418:                if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
                    419:                        rval = 1;
                    420:                        break;
                    421:                }
                    422:
                    423:                printf("%s in %s\n", strtab, p);
                    424:        }
                    425:
                    426:        free(p);
1.22      millert   427:        MUNMAP(symtab, len);
1.20      mickey    428:        return (rval);
                    429: }
                    430:
                    431: /*
                    432:  * show_symdef()
                    433:  *     show archive ranlib index (gob)
                    434:  */
                    435: int
                    436: show_symdef(off_t off, u_long len, const char *name, FILE *fp)
                    437: {
                    438:        struct ranlib *prn, *eprn;
                    439:        struct ar_hdr ar_head;
                    440:        void *symdef;
                    441:        char *strtab, *p;
                    442:        u_long size;
1.23      millert   443:        int namelen, rval = 0;
1.20      mickey    444:
1.22      millert   445:        MMAP(symdef, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);
                    446:        if (symdef == MAP_FAILED)
1.20      mickey    447:                return (1);
1.23      millert   448:        if (usemmap)
1.22      millert   449:                (void)madvise(symdef, len, MADV_SEQUENTIAL);
1.20      mickey    450:
                    451:        namelen = sizeof(ar_head.ar_name);
                    452:        if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) {
                    453:                warn("%s: malloc", name);
1.22      millert   454:                MUNMAP(symdef, len);
1.20      mickey    455:                return (1);
                    456:        }
                    457:
                    458:        size = *(u_long *)symdef;
                    459:        prn = symdef + sizeof(u_long);
                    460:        eprn = prn + size / sizeof(*prn);
                    461:        strtab = symdef + sizeof(u_long) + size + sizeof(u_long);
                    462:
                    463:        printf("\nArchive index:\n");
                    464:        for (; prn < eprn; prn++) {
                    465:                if (fseeko(fp, prn->ran_off, SEEK_SET)) {
                    466:                        warn("%s: fseeko", name);
                    467:                        rval = 1;
                    468:                        break;
                    469:                }
                    470:
                    471:                if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
                    472:                    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
                    473:                        warnx("%s: member fseeko", name);
                    474:                        rval = 1;
                    475:                        break;
                    476:                }
                    477:
                    478:                *p = '\0';
                    479:                if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
                    480:                        rval = 1;
                    481:                        break;
                    482:                }
                    483:
                    484:                printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p);
                    485:        }
                    486:
                    487:        free(p);
1.22      millert   488:        MUNMAP(symdef, len);
1.20      mickey    489:        return (rval);
                    490: }
                    491:
1.1       deraadt   492: /*
                    493:  * show_archive()
                    494:  *     show symbols in the given archive file
                    495:  */
1.20      mickey    496: int
                    497: show_archive(int count, const char *fname, FILE *fp)
1.1       deraadt   498: {
                    499:        struct ar_hdr ar_head;
1.20      mickey    500:        union hdr exec_head;
1.1       deraadt   501:        int i, rval;
1.20      mickey    502:        off_t last_ar_off, foff, symtaboff;
                    503:        char *name;
1.1       deraadt   504:        int baselen, namelen;
1.20      mickey    505:        u_long mmbrlen, symtablen;
1.1       deraadt   506:
                    507:        baselen = strlen(fname) + 3;
                    508:        namelen = sizeof(ar_head.ar_name);
1.20      mickey    509:        if ((name = malloc(baselen + namelen)) == NULL)
                    510:                err(1, NULL);
1.1       deraadt   511:
                    512:        rval = 0;
1.20      mickey    513:        nametab = NULL;
                    514:        symtaboff = 0;
                    515:        symtablen = 0;
1.1       deraadt   516:
                    517:        /* while there are more entries in the archive */
1.20      mickey    518:        while (fread(&ar_head, sizeof(ar_head), 1, fp) == 1) {
1.1       deraadt   519:                /* bad archive entry - stop processing this archive */
1.20      mickey    520:                if (memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
1.2       deraadt   521:                        warnx("%s: bad format archive header", fname);
1.20      mickey    522:                        rval = 1;
                    523:                        break;
1.1       deraadt   524:                }
                    525:
                    526:                /* remember start position of current archive object */
1.20      mickey    527:                last_ar_off = ftello(fp);
                    528:                mmbrlen = atol(ar_head.ar_size);
1.1       deraadt   529:
1.20      mickey    530:                if (strncmp(ar_head.ar_name, RANLIBMAG,
                    531:                    sizeof(RANLIBMAG) - 1) == 0) {
                    532:                        if (!issize && armap &&
                    533:                            show_symdef(last_ar_off, mmbrlen, fname, fp)) {
                    534:                                rval = 1;
                    535:                                break;
                    536:                        }
1.1       deraadt   537:                        goto skip;
1.20      mickey    538:                } else if (strncmp(ar_head.ar_name, SYMTABMAG,
                    539:                    sizeof(SYMTABMAG) - 1) == 0) {
                    540:                        /* if nametab hasn't been seen yet -- doit later */
                    541:                        if (!nametab) {
                    542:                                symtablen = mmbrlen;
                    543:                                symtaboff = last_ar_off;
                    544:                                goto skip;
                    545:                        }
                    546:
                    547:                        /* load the Sys5 long names table */
                    548:                } else if (strncmp(ar_head.ar_name, STRTABMAG,
                    549:                    sizeof(STRTABMAG) - 1) == 0) {
                    550:                        char *p;
                    551:
                    552:                        if ((nametab = malloc(mmbrlen)) == NULL) {
                    553:                                warn("%s: nametab", fname);
                    554:                                rval = 1;
                    555:                                break;
                    556:                        }
                    557:
                    558:                        if (fread(nametab, mmbrlen, (size_t)1, fp) != 1) {
                    559:                                warnx("%s: premature EOF", fname);
                    560:                                rval = 1;
                    561:                                break;
                    562:                        }
                    563:
                    564:                        for (p = nametab, i = mmbrlen; i--; p++)
                    565:                                if (*p == '\n')
                    566:                                        *p = '\0';
                    567:
                    568:                        if (issize || !armap || !symtablen || !symtaboff)
                    569:                                goto skip;
                    570:                }
                    571:
                    572:                if (!issize && armap && symtablen && symtaboff) {
                    573:                        if (show_symtab(symtaboff, symtablen, fname, fp)) {
                    574:                                rval = 1;
                    575:                                break;
                    576:                        } else {
                    577:                                symtaboff = 0;
                    578:                                symtablen = 0;
                    579:                                goto skip;
                    580:                        }
                    581:                }
1.1       deraadt   582:
                    583:                /*
                    584:                 * construct a name of the form "archive.a:obj.o:" for the
                    585:                 * current archive entry if the object name is to be printed
                    586:                 * on each output line
                    587:                 */
1.20      mickey    588:                *name = '\0';
                    589:                if (count > 1)
                    590:                        snprintf(name, baselen - 1, "%s:", fname);
                    591:
                    592:                if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
                    593:                        rval = 1;
                    594:                        break;
1.17      deraadt   595:                }
1.20      mickey    596:
                    597:                foff = ftello(fp);
1.1       deraadt   598:
                    599:                /* get and check current object's header */
                    600:                if (fread((char *)&exec_head, sizeof(exec_head),
                    601:                    (size_t)1, fp) != 1) {
1.20      mickey    602:                        warnx("%s: premature EOF", fname);
                    603:                        rval = 1;
                    604:                        break;
1.1       deraadt   605:                }
                    606:
1.20      mickey    607:                rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);
1.1       deraadt   608:                /*
                    609:                 * skip to next archive object - it starts at the next
1.25      deraadt   610:                 * even byte boundary
1.1       deraadt   611:                 */
                    612: #define even(x) (((x) + 1) & ~1)
1.20      mickey    613: skip:          if (fseeko(fp, last_ar_off + even(mmbrlen), SEEK_SET)) {
1.2       deraadt   614:                        warn("%s", fname);
1.20      mickey    615:                        rval = 1;
                    616:                        break;
1.1       deraadt   617:                }
                    618:        }
1.20      mickey    619:        if (nametab) {
                    620:                free(nametab);
                    621:                nametab = NULL;
                    622:        }
                    623:        free(name);
1.1       deraadt   624:        return(rval);
                    625: }
                    626:
1.20      mickey    627: struct nlist *names;
                    628: struct nlist **snames;
                    629: char *stab;
                    630: int nnames, nrawnames, stabsize;
                    631:
1.1       deraadt   632: /*
1.20      mickey    633:  * show_file()
1.1       deraadt   634:  *     show symbols from the object file pointed to by fp.  The current
                    635:  *     file pointer for fp is expected to be at the beginning of an a.out
                    636:  *     header.
                    637:  */
1.20      mickey    638: int
                    639: show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
1.1       deraadt   640: {
1.20      mickey    641:        u_long text, data, bss, total;
                    642:        struct nlist *np;
                    643:        Elf_Shdr *shdr;
                    644:        off_t staboff;
1.23      millert   645:        int i, aout;
1.20      mickey    646:
                    647:        aout = 0;
                    648:        if (IS_ELF(head->elf) &&
                    649:            head->elf.e_ident[EI_CLASS] == ELF_TARG_CLASS &&
                    650:            head->elf.e_ident[EI_VERSION] == ELF_TARG_VER) {
                    651:
                    652:                elf_fix_header(&head->elf);
                    653:
                    654:                if ((shdr = malloc(head->elf.e_shentsize *
                    655:                    head->elf.e_shnum)) == NULL) {
                    656:                        warn("%s: malloc shdr", name);
                    657:                        return (1);
                    658:                }
                    659:
                    660:                if (fseeko(fp, foff + head->elf.e_shoff, SEEK_SET)) {
                    661:                        warn("%s: fseeko", name);
                    662:                        free(shdr);
                    663:                        return (1);
                    664:                }
                    665:
                    666:                if (fread(shdr, head->elf.e_shentsize, head->elf.e_shnum,
                    667:                    fp) != head->elf.e_shnum) {
                    668:                        warnx("%s: premature EOF", name);
                    669:                        free(shdr);
                    670:                        return(1);
                    671:                }
                    672:
                    673:                elf_fix_shdrs(&head->elf, shdr);
                    674:
                    675:                if (issize) {
                    676:                        text = data = bss = 0;
                    677:                        for (i = 0; i < head->elf.e_shnum; i++) {
                    678:                                if (!(shdr[i].sh_flags & SHF_ALLOC))
                    679:                                        ;
                    680:                                else if (shdr[i].sh_flags & SHF_EXECINSTR ||
                    681:                                    !(shdr[i].sh_flags & SHF_WRITE))
                    682:                                        text += shdr[i].sh_size;
                    683:                                else if (shdr[i].sh_type == SHT_NOBITS)
                    684:                                        bss += shdr[i].sh_size;
                    685:                                else
                    686:                                        data += shdr[i].sh_size;
                    687:                        }
                    688:                        free(shdr);
                    689:                } else {
                    690:                        i = elf_symload(name, fp, foff, &head->elf, shdr);
                    691:                        free(shdr);
                    692:                        if (i)
                    693:                                return (i);
                    694:                }
                    695:
                    696:        } else if (BAD_OBJECT(head->aout)) {
                    697:                if (warn_fmt)
                    698:                        warnx("%s: bad format", name);
                    699:                return (1);
                    700:        } else do {
                    701:                aout++;
                    702:
                    703:                fix_header_order(&head->aout);
                    704:
                    705:                if (issize) {
                    706:                        text = head->aout.a_text;
                    707:                        data = head->aout.a_data;
                    708:                        bss = head->aout.a_bss;
                    709:                        break;
                    710:                }
                    711:
                    712:                /* stop if the object file contains no symbol table */
                    713:                if (!head->aout.a_syms) {
                    714:                        warnx("%s: no name list", name);
                    715:                        return(1);
                    716:                }
                    717:
                    718:                if (fseeko(fp, foff + N_SYMOFF(head->aout), SEEK_SET)) {
                    719:                        warn("%s", name);
                    720:                        return(1);
                    721:                }
                    722:
                    723:                /* get memory for the symbol table */
                    724:                if ((names = malloc(head->aout.a_syms)) == NULL) {
                    725:                        warn("%s: malloc names", name);
                    726:                        return (1);
                    727:                }
                    728:                nrawnames = head->aout.a_syms / sizeof(*names);
                    729:                if ((snames = malloc(nrawnames * sizeof(struct nlist *))) == NULL) {
                    730:                        warn("%s: malloc snames", name);
                    731:                        free(names);
                    732:                        return (1);
                    733:                }
1.1       deraadt   734:
1.20      mickey    735:                if (fread(names, head->aout.a_syms, 1, fp) != 1) {
                    736:                        warnx("%s: cannot read symbol table", name);
                    737:                        free(snames);
                    738:                        free(names);
                    739:                        return(1);
                    740:                }
                    741:                fix_nlists_order(names, nrawnames, N_GETMID(head->aout));
1.1       deraadt   742:
1.20      mickey    743:                staboff = ftello(fp);
                    744:                /*
                    745:                 * Following the symbol table comes the string table.
                    746:                 * The first 4-byte-integer gives the total size of the
                    747:                 * string table _including_ the size specification itself.
                    748:                 */
                    749:                if (fread(&stabsize, sizeof(stabsize), (size_t)1, fp) != 1) {
                    750:                        warnx("%s: cannot read stab size", name);
                    751:                        free(snames);
                    752:                        free(names);
                    753:                        return(1);
                    754:                }
1.26    ! mickey    755:                stabsize = fix_long_order(stabsize, N_GETMID(head->aout));
1.22      millert   756:                MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
                    757:                    fileno(fp), staboff);
                    758:                if (stab == MAP_FAILED) {
1.20      mickey    759:                        free(snames);
                    760:                        free(names);
                    761:                        return (1);
                    762:                }
1.1       deraadt   763:
1.20      mickey    764:                stabsize -= 4;          /* we already have the size */
                    765:        } while (0);
1.8       espie     766:
1.20      mickey    767:        if (issize) {
                    768:                static int first = 1;
1.1       deraadt   769:
1.20      mickey    770:                if (first) {
                    771:                        first = 0;
                    772:                        printf("text\tdata\tbss\tdec\thex\n");
                    773:                }
1.1       deraadt   774:
1.20      mickey    775:                total = text + data + bss;
                    776:                printf("%lu\t%lu\t%lu\t%lu\t%lx",
                    777:                    text, data, bss, total, total);
                    778:                if (count > 1)
                    779:                        (void)printf("\t%s", name);
                    780:
                    781:                total_text += text;
                    782:                total_data += data;
                    783:                total_bss += bss;
                    784:                total_total += total;
1.1       deraadt   785:
1.20      mickey    786:                printf("\n");
                    787:                return (0);
1.1       deraadt   788:        }
1.20      mickey    789:        /* else we are nm */
1.1       deraadt   790:
                    791:        /*
1.20      mickey    792:         * it seems that string table is sequential
                    793:         * relative to the symbol table order
1.1       deraadt   794:         */
1.23      millert   795:        if (sfunc == NULL && usemmap)
                    796:                (void)madvise(stab, stabsize, MADV_SEQUENTIAL);
1.1       deraadt   797:
                    798:        /*
                    799:         * fix up the symbol table and filter out unwanted entries
                    800:         *
                    801:         * common symbols are characterized by a n_type of N_UNDF and a
                    802:         * non-zero n_value -- change n_type to N_COMM for all such
                    803:         * symbols to make life easier later.
                    804:         *
                    805:         * filter out all entries which we don't want to print anyway
                    806:         */
                    807:        for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
1.13      espie     808:                /*
                    809:                 * make n_un.n_name a character pointer by adding the string
                    810:                 * table's base to n_un.n_strx
                    811:                 *
                    812:                 * don't mess with zero offsets
                    813:                 */
                    814:                if (np->n_un.n_strx)
                    815:                        np->n_un.n_name = stab + np->n_un.n_strx;
                    816:                else
                    817:                        np->n_un.n_name = "";
1.20      mickey    818:                if (aout && SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value)
1.1       deraadt   819:                        np->n_type = N_COMM | (np->n_type & N_EXT);
                    820:                if (!print_all_symbols && IS_DEBUGGER_SYMBOL(np->n_type))
                    821:                        continue;
                    822:                if (print_only_external_symbols && !IS_EXTERNAL(np->n_type))
                    823:                        continue;
                    824:                if (print_only_undefined_symbols &&
                    825:                    SYMBOL_TYPE(np->n_type) != N_UNDF)
                    826:                        continue;
                    827:
1.13      espie     828:                snames[nnames++] = np;
1.1       deraadt   829:        }
                    830:
                    831:        /* sort the symbol table if applicable */
                    832:        if (sfunc)
1.13      espie     833:                qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);
1.1       deraadt   834:
1.20      mickey    835:        if (count > 1)
                    836:                (void)printf("\n%s:\n", name);
                    837:
1.1       deraadt   838:        /* print out symbols */
1.13      espie     839:        for (i = 0; i < nnames; i++) {
                    840:                if (show_extensions && snames[i] != names &&
                    841:                    SYMBOL_TYPE((snames[i] -1)->n_type) == N_INDR)
                    842:                        continue;
1.20      mickey    843:                print_symbol(name, snames[i], aout);
1.13      espie     844:        }
1.1       deraadt   845:
1.20      mickey    846:        free(snames);
                    847:        free(names);
1.22      millert   848:        MUNMAP(stab, stabsize);
1.1       deraadt   849:        return(0);
                    850: }
                    851:
1.20      mickey    852: int
                    853: elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, Elf_Shdr *shdr)
                    854: {
1.21      mickey    855:        long symsize, shstrsize;
1.20      mickey    856:        struct nlist *np;
                    857:        Elf_Sym sbuf;
                    858:        char *shstr;
1.23      millert   859:        int i;
1.20      mickey    860:
                    861:        shstrsize = shdr[eh->e_shstrndx].sh_size;
                    862:        if ((shstr = malloc(shstrsize)) == NULL) {
                    863:                warn("%s: malloc shsrt", name);
                    864:                return (1);
                    865:        }
                    866:
                    867:        if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) {
                    868:                warn("%s: fseeko", name);
                    869:                free(shstr);
                    870:                return (1);
                    871:        }
                    872:
                    873:        if (fread(shstr, 1, shstrsize, fp) != shstrsize) {
                    874:                warnx("%s: premature EOF", name);
                    875:                free(shstr);
                    876:                return(1);
                    877:        }
                    878:
                    879:        stab = NULL;
                    880:        names = NULL; snames = NULL;
                    881:        for (i = 0; i < eh->e_shnum; i++) {
                    882:                if (!strcmp(shstr + shdr[i].sh_name, ELF_STRTAB)) {
                    883:                        stabsize = shdr[i].sh_size;
                    884:                        if (stabsize > SIZE_T_MAX) {
                    885:                                warnx("%s: corrupt file", name);
                    886:                                free(shstr);
                    887:                                return (1);
                    888:                        }
                    889:
1.22      millert   890:                        MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
                    891:                            fileno(fp), foff + shdr[i].sh_offset);
                    892:                        if (stab == MAP_FAILED) {
1.20      mickey    893:                                free(shstr);
                    894:                                return (1);
                    895:                        }
                    896:                }
                    897:        }
                    898:        for (i = 0; i < eh->e_shnum; i++) {
                    899:                if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) {
                    900:                        symsize = shdr[i].sh_size;
                    901:                        if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) {
                    902:                                warn("%s: fseeko", name);
                    903:                                if (stab)
1.22      millert   904:                                        MUNMAP(stab, stabsize);
1.20      mickey    905:                                free(shstr);
                    906:                                return (1);
                    907:                        }
                    908:
                    909:                        nrawnames = symsize / sizeof(sbuf);
                    910:                        if ((names = calloc(nrawnames, sizeof(*np))) == NULL) {
                    911:                                warn("%s: malloc names", name);
                    912:                                if (stab)
1.22      millert   913:                                        MUNMAP(stab, stabsize);
1.20      mickey    914:                                free(names);
                    915:                                free(shstr);
                    916:                                return (1);
                    917:                        }
                    918:                        if ((snames = malloc(nrawnames * sizeof(np))) == NULL) {
                    919:                                warn("%s: malloc snames", name);
                    920:                                if (stab)
1.22      millert   921:                                        MUNMAP(stab, stabsize);
1.20      mickey    922:                                free(shstr);
                    923:                                free(names);
                    924:                                free(snames);
                    925:                                return (1);
                    926:                        }
                    927:
                    928:                        for (np = names; symsize > 0; symsize -= sizeof(sbuf)) {
                    929:                                if (fread(&sbuf, 1, sizeof(sbuf),
                    930:                                    fp) != sizeof(sbuf)) {
                    931:                                        warn("%s: read symbol", name);
                    932:                                        if (stab)
1.22      millert   933:                                                MUNMAP(stab, stabsize);
1.20      mickey    934:                                        free(shstr);
                    935:                                        free(names);
                    936:                                        free(snames);
                    937:                                        return (1);
                    938:                                }
                    939:
                    940:                                elf_fix_sym(eh, &sbuf);
                    941:
                    942:                                if (!sbuf.st_name)
                    943:                                        continue;
                    944:
                    945:                                elf2nlist(&sbuf, eh, shdr, shstr, np);
                    946:                                np->n_value = sbuf.st_value;
                    947:                                np->n_un.n_strx = sbuf.st_name;
                    948:                                np++;
                    949:                        }
                    950:                        nrawnames = np - names;
                    951:                }
                    952:        }
                    953:
                    954:        free(shstr);
                    955:        if (stab == NULL) {
                    956:                warnx("%s: no name list", name);
                    957:                if (names)
                    958:                        free(names);
                    959:                if (snames)
                    960:                        free(snames);
                    961:                return (1);
                    962:        }
1.25      deraadt   963:
1.20      mickey    964:        return (0);
                    965: }
                    966:
1.13      espie     967: char *
1.19      deraadt   968: symname(struct nlist *sym)
1.13      espie     969: {
1.25      deraadt   970:        if (demangle && sym->n_un.n_name[0] == '_')
1.13      espie     971:                return sym->n_un.n_name + 1;
                    972:        else
                    973:                return sym->n_un.n_name;
                    974: }
                    975:
1.1       deraadt   976: /*
                    977:  * print_symbol()
                    978:  *     show one symbol
                    979:  */
1.13      espie     980: void
1.20      mickey    981: print_symbol(const char *name, struct nlist *sym, int aout)
1.1       deraadt   982: {
                    983:        if (print_file_each_line)
1.20      mickey    984:                (void)printf("%s:", name);
1.1       deraadt   985:
                    986:        /*
1.10      espie     987:         * handle undefined-only format especially (no space is
1.1       deraadt   988:         * left for symbol values, no type field is printed)
                    989:         */
1.10      espie     990:        if (!print_only_undefined_symbols) {
                    991:                /* print symbol's value */
1.25      deraadt   992:                if (SYMBOL_TYPE(sym->n_type) == N_UNDF ||
                    993:                    (show_extensions && SYMBOL_TYPE(sym->n_type) == N_INDR &&
                    994:                    sym->n_value == 0))
1.10      espie     995:                        (void)printf("        ");
                    996:                else
                    997:                        (void)printf("%08lx", sym->n_value);
                    998:
                    999:                /* print type information */
                   1000:                if (IS_DEBUGGER_SYMBOL(sym->n_type))
                   1001:                        (void)printf(" - %02x %04x %5s ", sym->n_other,
                   1002:                            sym->n_desc&0xffff, typestring(sym->n_type));
1.12      espie    1003:                else if (show_extensions)
1.20      mickey   1004:                        (void)printf(" %c%2s ", typeletter(sym, aout),
1.14      espie    1005:                            otherstring(sym));
1.10      espie    1006:                else
1.20      mickey   1007:                        (void)printf(" %c ", typeletter(sym, aout));
1.1       deraadt  1008:        }
                   1009:
1.13      espie    1010:        if (SYMBOL_TYPE(sym->n_type) == N_INDR && show_extensions) {
                   1011:                printf("%s -> %s\n", symname(sym), symname(sym+1));
                   1012:        }
1.1       deraadt  1013:        else
1.13      espie    1014:                (void)puts(symname(sym));
1.12      espie    1015: }
                   1016:
                   1017: char *
1.19      deraadt  1018: otherstring(struct nlist *sym)
1.12      espie    1019: {
                   1020:        static char buf[3];
                   1021:        char *result;
                   1022:
                   1023:        result = buf;
                   1024:
1.14      espie    1025:        if (N_BIND(sym) == BIND_WEAK)
1.12      espie    1026:                *result++ = 'w';
1.14      espie    1027:        if (N_AUX(sym) == AUX_OBJECT)
1.12      espie    1028:                *result++ = 'o';
1.14      espie    1029:        else if (N_AUX(sym) == AUX_FUNC)
1.12      espie    1030:                *result++ = 'f';
                   1031:        *result++ = 0;
                   1032:        return buf;
1.1       deraadt  1033: }
                   1034:
                   1035: /*
                   1036:  * typestring()
                   1037:  *     return the a description string for an STAB entry
                   1038:  */
                   1039: char *
1.19      deraadt  1040: typestring(unsigned int type)
1.1       deraadt  1041: {
                   1042:        switch(type) {
                   1043:        case N_BCOMM:
                   1044:                return("BCOMM");
                   1045:        case N_ECOML:
                   1046:                return("ECOML");
                   1047:        case N_ECOMM:
                   1048:                return("ECOMM");
                   1049:        case N_ENTRY:
                   1050:                return("ENTRY");
                   1051:        case N_FNAME:
                   1052:                return("FNAME");
                   1053:        case N_FUN:
                   1054:                return("FUN");
                   1055:        case N_GSYM:
                   1056:                return("GSYM");
                   1057:        case N_LBRAC:
                   1058:                return("LBRAC");
                   1059:        case N_LCSYM:
                   1060:                return("LCSYM");
                   1061:        case N_LENG:
                   1062:                return("LENG");
                   1063:        case N_LSYM:
                   1064:                return("LSYM");
                   1065:        case N_PC:
                   1066:                return("PC");
                   1067:        case N_PSYM:
                   1068:                return("PSYM");
                   1069:        case N_RBRAC:
                   1070:                return("RBRAC");
                   1071:        case N_RSYM:
                   1072:                return("RSYM");
                   1073:        case N_SLINE:
                   1074:                return("SLINE");
                   1075:        case N_SO:
                   1076:                return("SO");
                   1077:        case N_SOL:
                   1078:                return("SOL");
                   1079:        case N_SSYM:
                   1080:                return("SSYM");
                   1081:        case N_STSYM:
                   1082:                return("STSYM");
                   1083:        }
                   1084:        return("???");
                   1085: }
                   1086:
                   1087: /*
                   1088:  * typeletter()
                   1089:  *     return a description letter for the given basic type code of an
                   1090:  *     symbol table entry.  The return value will be upper case for
                   1091:  *     external, lower case for internal symbols.
                   1092:  */
                   1093: char
1.20      mickey   1094: typeletter(struct nlist *np, int aout)
1.1       deraadt  1095: {
1.20      mickey   1096:        int ext = IS_EXTERNAL(np->n_type);
                   1097:
                   1098:        if (!aout && !IS_DEBUGGER_SYMBOL(np->n_type) && np->n_other)
                   1099:                return np->n_other;
                   1100:
                   1101:        switch(SYMBOL_TYPE(np->n_type)) {
1.1       deraadt  1102:        case N_ABS:
1.20      mickey   1103:                return(ext? 'A' : 'a');
1.1       deraadt  1104:        case N_BSS:
1.20      mickey   1105:                return(ext? 'B' : 'b');
1.1       deraadt  1106:        case N_COMM:
1.20      mickey   1107:                return(ext? 'C' : 'c');
1.1       deraadt  1108:        case N_DATA:
1.20      mickey   1109:                return(ext? 'D' : 'd');
1.1       deraadt  1110:        case N_FN:
                   1111:                /* NOTE: N_FN == N_WARNING,
                   1112:                 * in this case, the N_EXT bit is to considered as
                   1113:                 * part of the symbol's type itself.
                   1114:                 */
1.20      mickey   1115:                return(ext? 'F' : 'W');
1.1       deraadt  1116:        case N_TEXT:
1.20      mickey   1117:                return(ext? 'T' : 't');
1.1       deraadt  1118:        case N_INDR:
1.20      mickey   1119:                return(ext? 'I' : 'i');
1.1       deraadt  1120:        case N_SIZE:
1.20      mickey   1121:                return(ext? 'S' : 's');
1.1       deraadt  1122:        case N_UNDF:
1.20      mickey   1123:                return(ext? 'U' : 'u');
1.1       deraadt  1124:        }
                   1125:        return('?');
                   1126: }
                   1127:
1.13      espie    1128: int
1.19      deraadt  1129: fname(const void *a0, const void *b0)
1.1       deraadt  1130: {
1.13      espie    1131:        struct nlist * const *a = a0, * const *b = b0;
1.1       deraadt  1132:
1.13      espie    1133:        return(strcmp((*a)->n_un.n_name, (*b)->n_un.n_name));
1.1       deraadt  1134: }
                   1135:
1.13      espie    1136: int
1.19      deraadt  1137: rname(const void *a0, const void *b0)
1.1       deraadt  1138: {
1.13      espie    1139:        struct nlist * const *a = a0, * const *b = b0;
1.1       deraadt  1140:
1.13      espie    1141:        return(strcmp((*b)->n_un.n_name, (*a)->n_un.n_name));
1.1       deraadt  1142: }
                   1143:
1.13      espie    1144: int
1.19      deraadt  1145: value(const void *a0, const void *b0)
1.1       deraadt  1146: {
1.13      espie    1147:        struct nlist * const *a = a0, * const *b = b0;
1.1       deraadt  1148:
1.13      espie    1149:        if (SYMBOL_TYPE((*a)->n_type) == N_UNDF)
                   1150:                if (SYMBOL_TYPE((*b)->n_type) == N_UNDF)
1.1       deraadt  1151:                        return(0);
                   1152:                else
                   1153:                        return(-1);
1.13      espie    1154:        else if (SYMBOL_TYPE((*b)->n_type) == N_UNDF)
1.1       deraadt  1155:                return(1);
                   1156:        if (rev) {
1.13      espie    1157:                if ((*a)->n_value == (*b)->n_value)
1.1       deraadt  1158:                        return(rname(a0, b0));
1.13      espie    1159:                return((*b)->n_value > (*a)->n_value ? 1 : -1);
1.1       deraadt  1160:        } else {
1.13      espie    1161:                if ((*a)->n_value == (*b)->n_value)
1.1       deraadt  1162:                        return(fname(a0, b0));
1.13      espie    1163:                return((*a)->n_value > (*b)->n_value ? 1 : -1);
1.1       deraadt  1164:        }
                   1165: }
                   1166:
1.10      espie    1167: #define CPPFILT        "/usr/bin/c++filt"
                   1168:
                   1169: void
1.19      deraadt  1170: pipe2cppfilt(void)
1.10      espie    1171: {
                   1172:        int pip[2];
                   1173:        char *argv[2];
                   1174:
                   1175:        argv[0] = "c++filt";
                   1176:        argv[1] = NULL;
                   1177:
                   1178:        if (pipe(pip) == -1)
                   1179:                err(1, "pipe");
                   1180:        switch(fork()) {
                   1181:        case -1:
                   1182:                err(1, "fork");
                   1183:        default:
                   1184:                dup2(pip[0], 0);
                   1185:                close(pip[0]);
                   1186:                close(pip[1]);
                   1187:                execve(CPPFILT, argv, NULL);
                   1188:                err(1, "execve");
                   1189:        case 0:
                   1190:                dup2(pip[1], 1);
                   1191:                close(pip[1]);
                   1192:                close(pip[0]);
                   1193:        }
                   1194: }
                   1195:
1.11      smart    1196: void
1.19      deraadt  1197: usage(void)
1.1       deraadt  1198: {
1.20      mickey   1199:        extern char *__progname;
                   1200:
                   1201:        if (issize)
                   1202:                fprintf(stderr, "usage: %s [-tw] [file ...]\n", __progname);
                   1203:        else
                   1204:                fprintf(stderr, "usage: %s [-aABCegnoprsuvVw] [file ...]\n",
                   1205:                    __progname);
1.1       deraadt  1206:        exit(1);
                   1207: }