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