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

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