Annotation of src/usr.bin/nm/nm.c, Revision 1.18
1.18 ! millert 1: /* $OpenBSD: nm.c,v 1.17 2003/04/05 17:15:06 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
37: static char copyright[] =
38: "@(#) Copyright (c) 1989, 1993\n\
39: The Regents of the University of California. All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: #if 0
44: static char sccsid[] = "@(#)nm.c 8.1 (Berkeley) 6/6/93";
45: #endif
1.18 ! millert 46: static char rcsid[] = "$OpenBSD: nm.c,v 1.17 2003/04/05 17:15:06 deraadt Exp $";
1.1 deraadt 47: #endif /* not lint */
48:
1.5 deraadt 49: #include <sys/param.h>
1.1 deraadt 50: #include <sys/types.h>
51: #include <a.out.h>
52: #include <stab.h>
53: #include <ar.h>
54: #include <ranlib.h>
55: #include <unistd.h>
1.2 deraadt 56: #include <err.h>
1.1 deraadt 57: #include <ctype.h>
1.14 espie 58: #include <link.h>
1.1 deraadt 59: #include <stdio.h>
60: #include <stdlib.h>
61: #include <string.h>
1.8 espie 62: /* XXX get shared code to handle byte-order swaps */
63: #include "byte.c"
1.7 niklas 64:
1.1 deraadt 65:
1.10 espie 66: int demangle = 0;
1.1 deraadt 67: int ignore_bad_archive_entries = 1;
68: int print_only_external_symbols;
69: int print_only_undefined_symbols;
70: int print_all_symbols;
71: int print_file_each_line;
1.12 espie 72: int show_extensions = 0;
1.1 deraadt 73: int fcount;
74:
75: int rev;
1.16 millert 76: int fname(const void *, const void *);
77: int rname(const void *, const void *);
78: int value(const void *, const void *);
79: int (*sfunc)(const void *, const void *) = fname;
80: char *otherstring(struct nlist *);
81: char *typestring(unsigned int);
82: char typeletter(unsigned int);
1.1 deraadt 83:
1.8 espie 84:
1.1 deraadt 85: /* some macros for symbol type (nlist.n_type) handling */
86: #define IS_DEBUGGER_SYMBOL(x) ((x) & N_STAB)
87: #define IS_EXTERNAL(x) ((x) & N_EXT)
88: #define SYMBOL_TYPE(x) ((x) & (N_TYPE | N_STAB))
89:
1.16 millert 90: void *emalloc(size_t);
91: void pipe2cppfilt(void);
92: void usage(void);
93: char *symname(struct nlist *);
94: void print_symbol(const char *, struct nlist *);
1.10 espie 95:
1.1 deraadt 96: /*
97: * main()
98: * parse command line, execute process_file() for each file
99: * specified on the command line.
100: */
101: main(argc, argv)
102: int argc;
103: char **argv;
104: {
105: extern int optind;
106: int ch, errors;
107:
1.12 espie 108: while ((ch = getopt(argc, argv, "aBCegnopruw")) != -1) {
1.1 deraadt 109: switch (ch) {
110: case 'a':
111: print_all_symbols = 1;
112: break;
1.10 espie 113: case 'B':
114: /* no-op, compat with gnu-nm */
115: break;
116: case 'C':
117: demangle = 1;
118: break;
1.12 espie 119: case 'e':
120: show_extensions = 1;
121: break;
1.1 deraadt 122: case 'g':
123: print_only_external_symbols = 1;
124: break;
125: case 'n':
126: sfunc = value;
127: break;
128: case 'o':
129: print_file_each_line = 1;
130: break;
131: case 'p':
132: sfunc = NULL;
133: break;
134: case 'r':
135: rev = 1;
136: break;
137: case 'u':
138: print_only_undefined_symbols = 1;
139: break;
140: case 'w':
141: ignore_bad_archive_entries = 0;
142: break;
143: case '?':
144: default:
145: usage();
146: }
147: }
1.10 espie 148:
149: if (demangle)
150: pipe2cppfilt();
1.1 deraadt 151: fcount = argc - optind;
152: argv += optind;
153:
154: if (rev && sfunc == fname)
155: sfunc = rname;
156:
157: if (!fcount)
158: errors = process_file("a.out");
159: else {
160: errors = 0;
161: do {
162: errors |= process_file(*argv);
163: } while (*++argv);
164: }
165: exit(errors);
166: }
167:
168: /*
169: * process_file()
170: * show symbols in the file given as an argument. Accepts archive and
171: * object files as input.
172: */
173: process_file(fname)
174: char *fname;
175: {
176: struct exec exec_head;
177: FILE *fp;
178: int retval;
179: char magic[SARMAG];
180:
181: if (!(fp = fopen(fname, "r"))) {
1.6 deraadt 182: warn("cannot read %s", fname);
1.1 deraadt 183: return(1);
184: }
185:
186: if (fcount > 1)
187: (void)printf("\n%s:\n", fname);
188:
189: /*
190: * first check whether this is an object file - read a object
191: * header, and skip back to the beginning
192: */
193: if (fread((char *)&exec_head, sizeof(exec_head), (size_t)1, fp) != 1) {
1.2 deraadt 194: warnx("%s: bad format", fname);
1.1 deraadt 195: (void)fclose(fp);
196: return(1);
197: }
198: rewind(fp);
199:
1.8 espie 200: if (BAD_OBJECT(exec_head)) {
1.1 deraadt 201: /* this could be an archive */
202: if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
203: strncmp(magic, ARMAG, SARMAG)) {
1.2 deraadt 204: warnx("%s: not object file or archive", fname);
1.1 deraadt 205: (void)fclose(fp);
206: return(1);
207: }
208: retval = show_archive(fname, fp);
209: } else
210: retval = show_objfile(fname, fp);
211: (void)fclose(fp);
212: return(retval);
213: }
214:
215: /*
216: * show_archive()
217: * show symbols in the given archive file
218: */
219: show_archive(fname, fp)
220: char *fname;
221: FILE *fp;
222: {
223: struct ar_hdr ar_head;
224: struct exec exec_head;
225: int i, rval;
226: long last_ar_off;
227: char *p, *name;
228: int baselen, namelen;
229:
230: baselen = strlen(fname) + 3;
231: namelen = sizeof(ar_head.ar_name);
232: name = emalloc(baselen + namelen);
233:
234: rval = 0;
235:
236: /* while there are more entries in the archive */
237: while (fread((char *)&ar_head, sizeof(ar_head), (size_t)1, fp) == 1) {
238: /* bad archive entry - stop processing this archive */
239: if (strncmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
1.2 deraadt 240: warnx("%s: bad format archive header", fname);
1.1 deraadt 241: (void)free(name);
242: return(1);
243: }
244:
245: /* remember start position of current archive object */
246: last_ar_off = ftell(fp);
247:
248: /* skip ranlib entries */
249: if (!strncmp(ar_head.ar_name, RANLIBMAG, sizeof(RANLIBMAG) - 1))
250: goto skip;
251:
252: /*
253: * construct a name of the form "archive.a:obj.o:" for the
254: * current archive entry if the object name is to be printed
255: * on each output line
256: */
257: p = name;
1.17 deraadt 258: if (print_file_each_line) {
259: snprintf(p, baselen, "%s:", fname);
260: p += strlen(p);
261: }
1.1 deraadt 262: #ifdef AR_EFMT1
263: /*
264: * BSD 4.4 extended AR format: #1/<namelen>, with name as the
265: * first <namelen> bytes of the file
266: */
267: if ( (ar_head.ar_name[0] == '#') &&
268: (ar_head.ar_name[1] == '1') &&
269: (ar_head.ar_name[2] == '/') &&
270: (isdigit(ar_head.ar_name[3]))) {
271:
272: int len = atoi(&ar_head.ar_name[3]);
273: if (len > namelen) {
274: p -= (long)name;
1.11 smart 275: if ((name = realloc(name, baselen+len)) == NULL)
276: err(1, NULL);
1.1 deraadt 277: namelen = len;
278: p += (long)name;
279: }
280: if (fread(p, len, 1, fp) != 1) {
1.2 deraadt 281: warnx("%s: premature EOF", name);
1.1 deraadt 282: (void)free(name);
283: return 1;
284: }
285: p += len;
286: } else
287: #endif
288: for (i = 0; i < sizeof(ar_head.ar_name); ++i)
289: if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ')
290: *p++ = ar_head.ar_name[i];
291: *p++ = '\0';
292:
293: /* get and check current object's header */
294: if (fread((char *)&exec_head, sizeof(exec_head),
295: (size_t)1, fp) != 1) {
1.2 deraadt 296: warnx("%s: premature EOF", name);
1.1 deraadt 297: (void)free(name);
298: return(1);
299: }
300:
1.8 espie 301: if (BAD_OBJECT(exec_head)) {
1.1 deraadt 302: if (!ignore_bad_archive_entries) {
1.2 deraadt 303: warnx("%s: bad format", name);
1.1 deraadt 304: rval = 1;
305: }
306: } else {
1.2 deraadt 307: (void)fseek(fp, (long)-sizeof(exec_head), SEEK_CUR);
1.1 deraadt 308: if (!print_file_each_line)
309: (void)printf("\n%s:\n", name);
310: rval |= show_objfile(name, fp);
311: }
312:
313: /*
314: * skip to next archive object - it starts at the next
315: * even byte boundary
316: */
317: #define even(x) (((x) + 1) & ~1)
318: skip: if (fseek(fp, last_ar_off + even(atol(ar_head.ar_size)),
319: SEEK_SET)) {
1.2 deraadt 320: warn("%s", fname);
1.1 deraadt 321: (void)free(name);
322: return(1);
323: }
324: }
325: (void)free(name);
326: return(rval);
327: }
328:
329: /*
330: * show_objfile()
331: * show symbols from the object file pointed to by fp. The current
332: * file pointer for fp is expected to be at the beginning of an a.out
333: * header.
334: */
335: show_objfile(objname, fp)
336: char *objname;
337: FILE *fp;
338: {
1.13 espie 339: struct nlist *names, *np;
340: struct nlist **snames;
1.15 mpech 341: int i, nnames, nrawnames;
1.1 deraadt 342: struct exec head;
343: long stabsize;
344: char *stab;
345:
346: /* read a.out header */
347: if (fread((char *)&head, sizeof(head), (size_t)1, fp) != 1) {
1.2 deraadt 348: warnx("%s: cannot read header", objname);
1.1 deraadt 349: return(1);
350: }
351:
352: /*
353: * skip back to the header - the N_-macros return values relative
354: * to the beginning of the a.out header
355: */
356: if (fseek(fp, (long)-sizeof(head), SEEK_CUR)) {
1.2 deraadt 357: warn("%s", objname);
1.1 deraadt 358: return(1);
359: }
360:
1.8 espie 361: /* stop if this is no valid object file, or a format we don't dare
362: * playing with
363: */
364: if (BAD_OBJECT(head)) {
1.2 deraadt 365: warnx("%s: bad format", objname);
1.1 deraadt 366: return(1);
367: }
368:
1.8 espie 369: fix_header_order(&head);
370:
1.1 deraadt 371: /* stop if the object file contains no symbol table */
372: if (!head.a_syms) {
1.2 deraadt 373: warnx("%s: no name list", objname);
1.1 deraadt 374: return(1);
375: }
376:
377: if (fseek(fp, (long)N_SYMOFF(head), SEEK_CUR)) {
1.2 deraadt 378: warn("%s", objname);
1.1 deraadt 379: return(1);
380: }
381:
382: /* get memory for the symbol table */
383: names = emalloc((size_t)head.a_syms);
384: nrawnames = head.a_syms / sizeof(*names);
1.13 espie 385: snames = emalloc(nrawnames*sizeof(struct nlist *));
1.1 deraadt 386: if (fread((char *)names, (size_t)head.a_syms, (size_t)1, fp) != 1) {
1.2 deraadt 387: warnx("%s: cannot read symbol table", objname);
1.1 deraadt 388: (void)free((char *)names);
389: return(1);
390: }
1.8 espie 391: fix_nlists_order(names, nrawnames, N_GETMID(head));
1.1 deraadt 392:
393: /*
394: * Following the symbol table comes the string table. The first
395: * 4-byte-integer gives the total size of the string table
396: * _including_ the size specification itself.
397: */
398: if (fread((char *)&stabsize, sizeof(stabsize), (size_t)1, fp) != 1) {
1.2 deraadt 399: warnx("%s: cannot read stab size", objname);
1.1 deraadt 400: (void)free((char *)names);
401: return(1);
402: }
1.8 espie 403: stabsize = fix_long_order(stabsize, N_GETMID(head));
1.1 deraadt 404: stab = emalloc((size_t)stabsize);
405:
406: /*
407: * read the string table offset by 4 - all indices into the string
408: * table include the size specification.
409: */
410: stabsize -= 4; /* we already have the size */
411: if (fread(stab + 4, (size_t)stabsize, (size_t)1, fp) != 1) {
1.2 deraadt 412: warnx("%s: stab truncated..", objname);
1.1 deraadt 413: (void)free((char *)names);
414: (void)free(stab);
415: return(1);
416: }
417:
418: /*
419: * fix up the symbol table and filter out unwanted entries
420: *
421: * common symbols are characterized by a n_type of N_UNDF and a
422: * non-zero n_value -- change n_type to N_COMM for all such
423: * symbols to make life easier later.
424: *
425: * filter out all entries which we don't want to print anyway
426: */
427: for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
1.13 espie 428: /*
429: * make n_un.n_name a character pointer by adding the string
430: * table's base to n_un.n_strx
431: *
432: * don't mess with zero offsets
433: */
434: if (np->n_un.n_strx)
435: np->n_un.n_name = stab + np->n_un.n_strx;
436: else
437: np->n_un.n_name = "";
1.1 deraadt 438: if (SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value)
439: np->n_type = N_COMM | (np->n_type & N_EXT);
440: if (!print_all_symbols && IS_DEBUGGER_SYMBOL(np->n_type))
441: continue;
442: if (print_only_external_symbols && !IS_EXTERNAL(np->n_type))
443: continue;
444: if (print_only_undefined_symbols &&
445: SYMBOL_TYPE(np->n_type) != N_UNDF)
446: continue;
447:
1.13 espie 448: snames[nnames++] = np;
1.1 deraadt 449: }
450:
451: /* sort the symbol table if applicable */
452: if (sfunc)
1.13 espie 453: qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);
1.1 deraadt 454:
455: /* print out symbols */
1.13 espie 456: for (i = 0; i < nnames; i++) {
457: if (show_extensions && snames[i] != names &&
458: SYMBOL_TYPE((snames[i] -1)->n_type) == N_INDR)
459: continue;
460: print_symbol(objname, snames[i]);
461: }
1.1 deraadt 462:
1.13 espie 463: (void)free(snames);
464: (void)free(names);
1.1 deraadt 465: (void)free(stab);
466: return(0);
467: }
468:
1.13 espie 469: char *
470: symname(sym)
471: struct nlist *sym;
472: {
473: if (demangle && sym->n_un.n_name[0] == '_')
474: return sym->n_un.n_name + 1;
475: else
476: return sym->n_un.n_name;
477: }
478:
1.1 deraadt 479: /*
480: * print_symbol()
481: * show one symbol
482: */
1.13 espie 483: void
1.1 deraadt 484: print_symbol(objname, sym)
1.13 espie 485: const char *objname;
486: struct nlist *sym;
1.1 deraadt 487: {
488: if (print_file_each_line)
489: (void)printf("%s:", objname);
490:
491: /*
1.10 espie 492: * handle undefined-only format especially (no space is
1.1 deraadt 493: * left for symbol values, no type field is printed)
494: */
1.10 espie 495: if (!print_only_undefined_symbols) {
496: /* print symbol's value */
1.13 espie 497: if (SYMBOL_TYPE(sym->n_type) == N_UNDF ||
498: (show_extensions && SYMBOL_TYPE(sym->n_type) == N_INDR &&
499: sym->n_value == 0))
1.10 espie 500: (void)printf(" ");
501: else
502: (void)printf("%08lx", sym->n_value);
503:
504: /* print type information */
505: if (IS_DEBUGGER_SYMBOL(sym->n_type))
506: (void)printf(" - %02x %04x %5s ", sym->n_other,
507: sym->n_desc&0xffff, typestring(sym->n_type));
1.12 espie 508: else if (show_extensions)
509: (void)printf(" %c%2s ", typeletter(sym->n_type),
1.14 espie 510: otherstring(sym));
1.10 espie 511: else
512: (void)printf(" %c ", typeletter(sym->n_type));
1.1 deraadt 513: }
514:
1.13 espie 515: if (SYMBOL_TYPE(sym->n_type) == N_INDR && show_extensions) {
516: printf("%s -> %s\n", symname(sym), symname(sym+1));
517: }
1.1 deraadt 518: else
1.13 espie 519: (void)puts(symname(sym));
1.12 espie 520: }
521:
522: char *
1.14 espie 523: otherstring(sym)
524: struct nlist *sym;
1.12 espie 525: {
526: static char buf[3];
527: char *result;
528:
529: result = buf;
530:
1.14 espie 531: if (N_BIND(sym) == BIND_WEAK)
1.12 espie 532: *result++ = 'w';
1.14 espie 533: if (N_AUX(sym) == AUX_OBJECT)
1.12 espie 534: *result++ = 'o';
1.14 espie 535: else if (N_AUX(sym) == AUX_FUNC)
1.12 espie 536: *result++ = 'f';
537: *result++ = 0;
538: return buf;
1.1 deraadt 539: }
540:
541: /*
542: * typestring()
543: * return the a description string for an STAB entry
544: */
545: char *
546: typestring(type)
1.14 espie 547: unsigned int type;
1.1 deraadt 548: {
549: switch(type) {
550: case N_BCOMM:
551: return("BCOMM");
552: case N_ECOML:
553: return("ECOML");
554: case N_ECOMM:
555: return("ECOMM");
556: case N_ENTRY:
557: return("ENTRY");
558: case N_FNAME:
559: return("FNAME");
560: case N_FUN:
561: return("FUN");
562: case N_GSYM:
563: return("GSYM");
564: case N_LBRAC:
565: return("LBRAC");
566: case N_LCSYM:
567: return("LCSYM");
568: case N_LENG:
569: return("LENG");
570: case N_LSYM:
571: return("LSYM");
572: case N_PC:
573: return("PC");
574: case N_PSYM:
575: return("PSYM");
576: case N_RBRAC:
577: return("RBRAC");
578: case N_RSYM:
579: return("RSYM");
580: case N_SLINE:
581: return("SLINE");
582: case N_SO:
583: return("SO");
584: case N_SOL:
585: return("SOL");
586: case N_SSYM:
587: return("SSYM");
588: case N_STSYM:
589: return("STSYM");
590: }
591: return("???");
592: }
593:
594: /*
595: * typeletter()
596: * return a description letter for the given basic type code of an
597: * symbol table entry. The return value will be upper case for
598: * external, lower case for internal symbols.
599: */
600: char
601: typeletter(type)
1.14 espie 602: unsigned int type;
1.1 deraadt 603: {
604: switch(SYMBOL_TYPE(type)) {
605: case N_ABS:
606: return(IS_EXTERNAL(type) ? 'A' : 'a');
607: case N_BSS:
608: return(IS_EXTERNAL(type) ? 'B' : 'b');
609: case N_COMM:
610: return(IS_EXTERNAL(type) ? 'C' : 'c');
611: case N_DATA:
612: return(IS_EXTERNAL(type) ? 'D' : 'd');
613: case N_FN:
614: /* NOTE: N_FN == N_WARNING,
615: * in this case, the N_EXT bit is to considered as
616: * part of the symbol's type itself.
617: */
618: return(IS_EXTERNAL(type) ? 'F' : 'W');
619: case N_TEXT:
620: return(IS_EXTERNAL(type) ? 'T' : 't');
621: case N_INDR:
622: return(IS_EXTERNAL(type) ? 'I' : 'i');
623: case N_SIZE:
624: return(IS_EXTERNAL(type) ? 'S' : 's');
625: case N_UNDF:
626: return(IS_EXTERNAL(type) ? 'U' : 'u');
627: }
628: return('?');
629: }
630:
1.13 espie 631: int
1.1 deraadt 632: fname(a0, b0)
1.13 espie 633: const void *a0, *b0;
1.1 deraadt 634: {
1.13 espie 635: struct nlist * const *a = a0, * const *b = b0;
1.1 deraadt 636:
1.13 espie 637: return(strcmp((*a)->n_un.n_name, (*b)->n_un.n_name));
1.1 deraadt 638: }
639:
1.13 espie 640: int
1.1 deraadt 641: rname(a0, b0)
1.13 espie 642: const void *a0, *b0;
1.1 deraadt 643: {
1.13 espie 644: struct nlist * const *a = a0, * const *b = b0;
1.1 deraadt 645:
1.13 espie 646: return(strcmp((*b)->n_un.n_name, (*a)->n_un.n_name));
1.1 deraadt 647: }
648:
1.13 espie 649: int
1.1 deraadt 650: value(a0, b0)
1.13 espie 651: const void *a0, *b0;
1.1 deraadt 652: {
1.13 espie 653: struct nlist * const *a = a0, * const *b = b0;
1.1 deraadt 654:
1.13 espie 655: if (SYMBOL_TYPE((*a)->n_type) == N_UNDF)
656: if (SYMBOL_TYPE((*b)->n_type) == N_UNDF)
1.1 deraadt 657: return(0);
658: else
659: return(-1);
1.13 espie 660: else if (SYMBOL_TYPE((*b)->n_type) == N_UNDF)
1.1 deraadt 661: return(1);
662: if (rev) {
1.13 espie 663: if ((*a)->n_value == (*b)->n_value)
1.1 deraadt 664: return(rname(a0, b0));
1.13 espie 665: return((*b)->n_value > (*a)->n_value ? 1 : -1);
1.1 deraadt 666: } else {
1.13 espie 667: if ((*a)->n_value == (*b)->n_value)
1.1 deraadt 668: return(fname(a0, b0));
1.13 espie 669: return((*a)->n_value > (*b)->n_value ? 1 : -1);
1.1 deraadt 670: }
671: }
672:
673: void *
674: emalloc(size)
675: size_t size;
676: {
677: char *p;
678:
679: /* NOSTRICT */
680: if (p = malloc(size))
681: return(p);
1.2 deraadt 682: err(1, NULL);
1.1 deraadt 683: }
684:
1.10 espie 685: #define CPPFILT "/usr/bin/c++filt"
686:
687: void
688: pipe2cppfilt()
689: {
690: int pip[2];
691: char *argv[2];
692:
693: argv[0] = "c++filt";
694: argv[1] = NULL;
695:
696: if (pipe(pip) == -1)
697: err(1, "pipe");
698: switch(fork()) {
699: case -1:
700: err(1, "fork");
701: default:
702: dup2(pip[0], 0);
703: close(pip[0]);
704: close(pip[1]);
705: execve(CPPFILT, argv, NULL);
706: err(1, "execve");
707: case 0:
708: dup2(pip[1], 1);
709: close(pip[1]);
710: close(pip[0]);
711: }
712: }
713:
1.11 smart 714: void
1.1 deraadt 715: usage()
716: {
1.10 espie 717: (void)fprintf(stderr, "usage: nm [-aCgnopruw] [file ...]\n");
1.1 deraadt 718: exit(1);
719: }