130855Sbostic /* 239109Sbostic * Copyright (c) 1989 The Regents of the University of California. 339109Sbostic * All rights reserved. 439109Sbostic * 539109Sbostic * This code is derived from software contributed to Berkeley by 639109Sbostic * Hans Huebner. 739109Sbostic * 839109Sbostic * Redistribution and use in source and binary forms are permitted 939109Sbostic * provided that the above copyright notice and this paragraph are 1039109Sbostic * duplicated in all such forms and that any documentation, 1139109Sbostic * advertising materials, and other materials related to such 1239109Sbostic * distribution and use acknowledge that the software was developed 1339109Sbostic * by the University of California, Berkeley. The name of the 1439109Sbostic * University may not be used to endorse or promote products derived 1539109Sbostic * from this software without specific prior written permission. 1639109Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1739109Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1839109Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1930855Sbostic */ 2030855Sbostic 2112672Ssam #ifndef lint 2239109Sbostic char copyright[] = 2339109Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 2439109Sbostic All rights reserved.\n"; 2539109Sbostic #endif /* not lint */ 2630855Sbostic 2739109Sbostic #ifndef lint 28*42452Sbostic static char sccsid[] = "@(#)nm.c 5.5 (Berkeley) 05/29/90"; 2939109Sbostic #endif /* not lint */ 3030855Sbostic 31619Sbill #include <sys/types.h> 32653Sbill #include <a.out.h> 33619Sbill #include <stab.h> 3439109Sbostic #include <ar.h> 3530855Sbostic #include <ranlib.h> 3639109Sbostic #include <unistd.h> 3739109Sbostic #include <errno.h> 3839109Sbostic #include <ctype.h> 3939109Sbostic #include <stdio.h> 40*42452Sbostic #include <stdlib.h> 4142034Sbostic #include <string.h> 42619Sbill 4340272Sbostic int ignore_bad_archive_entries = 1; 4440272Sbostic int print_only_external_symbols; 4540272Sbostic int print_only_undefined_symbols; 4640272Sbostic int print_all_symbols; 4740272Sbostic int print_file_each_line; 4840272Sbostic int cmp_value(), cmp_name(); 4940272Sbostic int (*sort_func)() = cmp_name; 5040272Sbostic 5139109Sbostic enum { FORWARD, BACKWARD } sort_direction = FORWARD; 5239109Sbostic int fcount; 5330855Sbostic 5439109Sbostic /* some macros for symbol type (nlist.n_type) handling */ 5539109Sbostic #define IS_DEBUGGER_SYMBOL(x) ((x) & N_STAB) 5639109Sbostic #define IS_EXTERNAL(x) ((x) & N_EXT) 5739109Sbostic #define SYMBOL_TYPE(x) ((x) & (N_TYPE | N_STAB)) 5830855Sbostic 5939109Sbostic /* 6039109Sbostic * main() 6139109Sbostic * parse command line, execute process_file() for each file 6239109Sbostic * specified on the command line. 6339109Sbostic */ 64619Sbill main(argc, argv) 6539109Sbostic int argc; 6639109Sbostic char **argv; 67619Sbill { 6839109Sbostic extern int optind; 6939109Sbostic int ch, errors; 70619Sbill 7139109Sbostic while ((ch = getopt(argc, argv, "agnopruw")) != EOF) { 7239109Sbostic switch (ch) { 7330855Sbostic case 'a': 7439109Sbostic print_all_symbols = 1; 7530855Sbostic break; 7630855Sbostic case 'g': 7739109Sbostic print_only_external_symbols = 1; 7830855Sbostic break; 79619Sbill case 'n': 8039109Sbostic sort_func = cmp_value; 8130855Sbostic break; 8230855Sbostic case 'o': 8339109Sbostic print_file_each_line = 1; 8430855Sbostic break; 8530855Sbostic case 'p': 8639109Sbostic sort_func = NULL; 8730855Sbostic break; 88619Sbill case 'r': 8939109Sbostic sort_direction = BACKWARD; 9030855Sbostic break; 9130855Sbostic case 'u': 9239109Sbostic print_only_undefined_symbols = 1; 9330855Sbostic break; 9439109Sbostic case 'w': 9539109Sbostic ignore_bad_archive_entries = 0; 9639109Sbostic break; 9730855Sbostic case '?': 98619Sbill default: 9939109Sbostic usage(); 100619Sbill } 10139109Sbostic } 10239109Sbostic fcount = argc - optind; 10330855Sbostic argv += optind; 10439109Sbostic 10539109Sbostic if (!fcount) 10639109Sbostic errors = process_file("a.out"); 10739109Sbostic else { 10839109Sbostic errors = 0; 10939109Sbostic do { 11039109Sbostic errors |= process_file(*argv); 11139109Sbostic } while (*++argv); 112619Sbill } 11339109Sbostic exit(errors); 114619Sbill } 115619Sbill 11639109Sbostic /* 11739109Sbostic * process_file() 11839109Sbostic * show symbols in the file given as an argument. Accepts archive and 11939109Sbostic * object files as input. 12039109Sbostic */ 12139109Sbostic process_file(fname) 12239109Sbostic char *fname; 123619Sbill { 12439109Sbostic struct exec exec_head; 12539109Sbostic FILE *fp; 12639109Sbostic int retval; 12739109Sbostic char magic[SARMAG]; 12839109Sbostic 12939109Sbostic if (!(fp = fopen(fname, "r"))) { 13039109Sbostic (void)fprintf(stderr, "nm: cannot read %s.\n", fname); 13139109Sbostic return(1); 13239109Sbostic } 133619Sbill 13439109Sbostic if (fcount > 1) 13539109Sbostic (void)printf("\n%s:\n", fname); 13639109Sbostic 13730855Sbostic /* 13839109Sbostic * first check whether this is an object file - read a object 13939109Sbostic * header, and skip back to the beginning 14030855Sbostic */ 141*42452Sbostic if (fread((char *)&exec_head, sizeof(exec_head), (size_t)1, fp) != 1) { 14239109Sbostic (void)fprintf(stderr, "nm: %s: bad format.\n", fname); 14339109Sbostic (void)fclose(fp); 14439109Sbostic return(1); 145619Sbill } 14639109Sbostic rewind(fp); 14739109Sbostic 14839109Sbostic /* this could be an archive */ 14939109Sbostic if (N_BADMAG(exec_head)) { 150*42452Sbostic if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 || 15139109Sbostic strncmp(magic, ARMAG, SARMAG)) { 15239109Sbostic (void)fprintf(stderr, 15339109Sbostic "nm: %s: not object file or archive.\n", fname); 15439109Sbostic (void)fclose(fp); 15539109Sbostic return(1); 15630855Sbostic } 15739109Sbostic retval = show_archive(fname, fp); 15839109Sbostic } else 15939109Sbostic retval = show_objfile(fname, fp); 16039109Sbostic (void)fclose(fp); 16139109Sbostic return(retval); 16239109Sbostic } 16339109Sbostic 16439109Sbostic /* 16539109Sbostic * show_archive() 16639109Sbostic * show symbols in the given archive file 16739109Sbostic */ 16839109Sbostic show_archive(fname, fp) 16939109Sbostic char *fname; 17039109Sbostic FILE *fp; 17139109Sbostic { 17239109Sbostic struct ar_hdr ar_head; 17339109Sbostic struct exec exec_head; 174*42452Sbostic int i, rval; 175*42452Sbostic long last_ar_off; 17639109Sbostic char *p, *name, *emalloc(); 17739109Sbostic long atol(); 17839109Sbostic 179*42452Sbostic name = emalloc(sizeof(ar_head.ar_name) + strlen(fname) + 3); 18039109Sbostic 18139109Sbostic rval = 0; 18239109Sbostic 18339109Sbostic /* while there are more entries in the archive */ 184*42452Sbostic while (fread((char *)&ar_head, sizeof(ar_head), (size_t)1, fp) == 1) { 18539109Sbostic /* bad archive entry - stop processing this archive */ 18639109Sbostic if (strncmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) { 18739109Sbostic (void)fprintf(stderr, 18839109Sbostic "nm: %s: bad format archive header", fname); 18939109Sbostic (void)free(name); 19039109Sbostic return(1); 19139109Sbostic } 19239109Sbostic 19330855Sbostic /* 19439143Sbostic * construct a name of the form "archive.a:obj.o:" for the 19539109Sbostic * current archive entry if the object name is to be printed 19639109Sbostic * on each output line 19730855Sbostic */ 198*42452Sbostic p = name; 199*42452Sbostic if (print_file_each_line) 200*42452Sbostic p += sprintf(p, "%s:", fname); 20139109Sbostic for (i = 0; i < sizeof(ar_head.ar_name); ++i) 20239109Sbostic if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ') 20339109Sbostic *p++ = ar_head.ar_name[i]; 20439109Sbostic *p++ = '\0'; 20530855Sbostic 20639109Sbostic /* remember start position of current archive object */ 20739109Sbostic last_ar_off = ftell(fp); 20830855Sbostic 20939109Sbostic /* get and check current object's header */ 210*42452Sbostic if (fread((char *)&exec_head, sizeof(exec_head), 211*42452Sbostic (size_t)1, fp) != 1) { 21239109Sbostic (void)fprintf(stderr, "nm: %s: premature EOF.\n", name); 21339109Sbostic (void)free(name); 21439109Sbostic return(1); 215619Sbill } 21639109Sbostic if (strcmp(name, RANLIBMAG)) 21739109Sbostic if (N_BADMAG(exec_head)) { 21839109Sbostic if (!ignore_bad_archive_entries) { 21939109Sbostic (void)fprintf(stderr, 22039109Sbostic "nm: %s: bad format.\n", name); 22139109Sbostic rval = 1; 22239109Sbostic } 22339109Sbostic } else { 22439109Sbostic (void)fseek(fp, (long)-sizeof(exec_head), 22539109Sbostic SEEK_CUR); 22639109Sbostic if (!print_file_each_line) 22739109Sbostic (void)printf("\n%s:\n", name); 22839109Sbostic rval |= show_objfile(name, fp); 22939109Sbostic } 23030855Sbostic 23139109Sbostic /* 232*42452Sbostic * skip to next archive object - it starts at the next 233*42452Sbostic * even byte boundary 23439109Sbostic */ 235*42452Sbostic #define even(x) (((x) + 1) & ~1) 236*42452Sbostic if (fseek(fp, last_ar_off + even(atol(ar_head.ar_size)), 23739109Sbostic SEEK_SET)) { 23839109Sbostic (void)fprintf(stderr, 23939109Sbostic "nm: %s: %s\n", fname, strerror(errno)); 24039109Sbostic (void)free(name); 24139109Sbostic return(1); 24230855Sbostic } 24339109Sbostic } 24439109Sbostic (void)free(name); 24539109Sbostic return(rval); 24639109Sbostic } 24730855Sbostic 24839109Sbostic /* 24939109Sbostic * show_objfile() 25039109Sbostic * show symbols from the object file pointed to by fp. The current 25139109Sbostic * file pointer for fp is expected to be at the beginning of an a.out 25239109Sbostic * header. 25339109Sbostic */ 25439109Sbostic show_objfile(objname, fp) 25539109Sbostic char *objname; 25639109Sbostic FILE *fp; 25739109Sbostic { 258*42452Sbostic register struct nlist *names, *np; 25939109Sbostic register int i, nnames, nrawnames; 26039109Sbostic struct exec head; 26139109Sbostic long stabsize; 26239109Sbostic char *stab, *emalloc(); 26339109Sbostic 26439109Sbostic /* read a.out header */ 265*42452Sbostic if (fread((char *)&head, sizeof(head), (size_t)1, fp) != 1) { 26639109Sbostic (void)fprintf(stderr, 26739109Sbostic "nm: %s: cannot read header.\n", objname); 26839109Sbostic return(1); 26939109Sbostic } 27039109Sbostic 27139109Sbostic /* 27239109Sbostic * skip back to the header - the N_-macros return values relative 27339109Sbostic * to the beginning of the a.out header 27439109Sbostic */ 27539109Sbostic if (fseek(fp, (long)-sizeof(head), SEEK_CUR)) { 27639109Sbostic (void)fprintf(stderr, 27739109Sbostic "nm: %s: %s\n", objname, strerror(errno)); 27839109Sbostic return(1); 27939109Sbostic } 28039109Sbostic 28139109Sbostic /* stop if this is no valid object file */ 28239109Sbostic if (N_BADMAG(head)) { 28339109Sbostic (void)fprintf(stderr, 28439109Sbostic "nm: %s: bad format.\n", objname); 28539109Sbostic return(1); 28639109Sbostic } 28739109Sbostic 28839109Sbostic /* stop if the object file contains no symbol table */ 28939109Sbostic if (!head.a_syms) { 29039109Sbostic (void)fprintf(stderr, 29139109Sbostic "nm: %s: no name list.\n", objname); 29239109Sbostic return(1); 29339109Sbostic } 29439109Sbostic 29539109Sbostic if (fseek(fp, (long)N_SYMOFF(head), SEEK_CUR)) { 29639109Sbostic (void)fprintf(stderr, 29739109Sbostic "nm: %s: %s\n", objname, strerror(errno)); 29839109Sbostic return(1); 29939109Sbostic } 30039109Sbostic 30139109Sbostic /* get memory for the symbol table */ 302*42452Sbostic names = (struct nlist *)emalloc((size_t)head.a_syms); 30339109Sbostic nrawnames = head.a_syms / sizeof(*names); 304*42452Sbostic if (fread((char *)names, (size_t)head.a_syms, (size_t)1, fp) != 1) { 30539109Sbostic (void)fprintf(stderr, 30639109Sbostic "nm: %s: cannot read symbol table.\n", objname); 30739109Sbostic (void)free((char *)names); 30839109Sbostic return(1); 30939109Sbostic } 31039109Sbostic 31139109Sbostic /* 31239109Sbostic * Following the symbol table comes the string table. The first 31339109Sbostic * 4-byte-integer gives the total size of the string table 31439109Sbostic * _including_ the size specification itself. 31539109Sbostic */ 316*42452Sbostic if (fread((char *)&stabsize, sizeof(stabsize), (size_t)1, fp) != 1) { 31739109Sbostic (void)fprintf(stderr, 31839109Sbostic "nm: %s: cannot read stab size.\n", objname); 31939109Sbostic (void)free((char *)names); 32039109Sbostic return(1); 32139109Sbostic } 322*42452Sbostic stab = emalloc((size_t)stabsize); 32339109Sbostic 32439109Sbostic /* 32539109Sbostic * read the string table offset by 4 - all indices into the string 32639109Sbostic * table include the size specification. 32739109Sbostic */ 32839143Sbostic stabsize -= 4; /* we already have the size */ 329*42452Sbostic if (fread(stab + 4, (size_t)stabsize, (size_t)1, fp) != 1) { 33039109Sbostic (void)fprintf(stderr, 33139109Sbostic "nm: %s: stab truncated..\n", objname); 33239109Sbostic (void)free((char *)names); 33339109Sbostic (void)free(stab); 33439109Sbostic return(1); 33539109Sbostic } 33639109Sbostic 33739109Sbostic /* 33839109Sbostic * fix up the symbol table and filter out unwanted entries 33939109Sbostic * 34039109Sbostic * common symbols are characterized by a n_type of N_UNDF and a 34139109Sbostic * non-zero n_value -- change n_type to N_COMM for all such 34239109Sbostic * symbols to make life easier later. 34339109Sbostic * 34439109Sbostic * filter out all entries which we don't want to print anyway 34539109Sbostic */ 346*42452Sbostic for (np = names, i = nnames = 0; i < nrawnames; np++, i++) { 347*42452Sbostic if (SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value) 348*42452Sbostic np->n_type = N_COMM | (np->n_type & N_EXT); 349*42452Sbostic if (!print_all_symbols && IS_DEBUGGER_SYMBOL(np->n_type)) 35030855Sbostic continue; 351*42452Sbostic if (print_only_external_symbols && !IS_EXTERNAL(np->n_type)) 352619Sbill continue; 35339109Sbostic if (print_only_undefined_symbols && 354*42452Sbostic SYMBOL_TYPE(np->n_type) != N_UNDF) 35539109Sbostic continue; 35630855Sbostic 35739109Sbostic /* 35839109Sbostic * make n_un.n_name a character pointer by adding the string 35939109Sbostic * table's base to n_un.n_strx 36039109Sbostic * 361*42452Sbostic * don't mess with zero offsets 36239109Sbostic */ 363*42452Sbostic if (np->n_un.n_strx) 364*42452Sbostic np->n_un.n_name = stab + np->n_un.n_strx; 36539109Sbostic else 366*42452Sbostic np->n_un.n_name = ""; 367*42452Sbostic names[nnames++] = *np; 36839109Sbostic } 36930855Sbostic 37039109Sbostic /* sort the symbol table if applicable */ 37139109Sbostic if (sort_func) 372*42452Sbostic qsort((char *)names, (size_t)nnames, sizeof(*names), sort_func); 37330855Sbostic 37439109Sbostic /* print out symbols */ 375*42452Sbostic for (np = names, i = 0; i < nnames; np++, i++) 376*42452Sbostic print_symbol(objname, np); 37730855Sbostic 37839109Sbostic (void)free((char *)names); 37939109Sbostic (void)free(stab); 38039109Sbostic return(0); 381619Sbill } 382619Sbill 38339109Sbostic /* 38439109Sbostic * print_symbol() 38539109Sbostic * show one symbol 38639109Sbostic */ 38739109Sbostic print_symbol(objname, sym) 38839109Sbostic char *objname; 389*42452Sbostic register struct nlist *sym; 390619Sbill { 39139109Sbostic char *typestring(), typeletter(); 392619Sbill 39339109Sbostic if (print_file_each_line) 394*42452Sbostic (void)printf("%s:", objname); 39539109Sbostic 39639109Sbostic /* 39739109Sbostic * handle undefined-only format seperately (no space is 39839109Sbostic * left for symbol values, no type field is printed) 39939109Sbostic */ 40039109Sbostic if (print_only_undefined_symbols) { 401*42452Sbostic (void)puts(sym->n_un.n_name); 40239109Sbostic return; 403619Sbill } 40439109Sbostic 40539109Sbostic /* print symbol's value */ 40639109Sbostic if (SYMBOL_TYPE(sym->n_type) == N_UNDF) 40739109Sbostic (void)printf(" "); 40839109Sbostic else 40939109Sbostic (void)printf("%08lx", sym->n_value); 41039109Sbostic 41139109Sbostic /* print type information */ 41239109Sbostic if (IS_DEBUGGER_SYMBOL(sym->n_type)) 41339109Sbostic (void)printf(" - %02x %04x %5s ", sym->n_other, 41439109Sbostic sym->n_desc&0xffff, typestring(sym->n_type)); 41539109Sbostic else 41639109Sbostic (void)printf(" %c ", typeletter(sym->n_type)); 41739109Sbostic 41839109Sbostic /* print the symbol's name */ 419*42452Sbostic (void)puts(sym->n_un.n_name); 420619Sbill } 421619Sbill 42239109Sbostic /* 42339109Sbostic * typestring() 42439109Sbostic * return the a description string for an STAB entry 42539109Sbostic */ 42639109Sbostic char * 42739109Sbostic typestring(type) 42839109Sbostic register u_char type; 429619Sbill { 43039109Sbostic switch(type) { 43139109Sbostic case N_BCOMM: 43239109Sbostic return("BCOMM"); 43339109Sbostic case N_ECOML: 43439109Sbostic return("ECOML"); 43539109Sbostic case N_ECOMM: 43639109Sbostic return("ECOMM"); 43739109Sbostic case N_ENTRY: 43839109Sbostic return("ENTRY"); 43939109Sbostic case N_FNAME: 44039109Sbostic return("FNAME"); 44139109Sbostic case N_FUN: 44239109Sbostic return("FUN"); 44339109Sbostic case N_GSYM: 44439109Sbostic return("GSYM"); 44539109Sbostic case N_LBRAC: 44639109Sbostic return("LBRAC"); 44739109Sbostic case N_LCSYM: 44839109Sbostic return("LCSYM"); 44939109Sbostic case N_LENG: 45039109Sbostic return("LENG"); 45139109Sbostic case N_LSYM: 45239109Sbostic return("LSYM"); 45339109Sbostic case N_PC: 45439109Sbostic return("PC"); 45539109Sbostic case N_PSYM: 45639109Sbostic return("PSYM"); 45739109Sbostic case N_RBRAC: 45839109Sbostic return("RBRAC"); 45939109Sbostic case N_RSYM: 46039109Sbostic return("RSYM"); 46139109Sbostic case N_SLINE: 46239109Sbostic return("SLINE"); 46339109Sbostic case N_SO: 46439109Sbostic return("SO"); 46539109Sbostic case N_SOL: 46639109Sbostic return("SOL"); 46739109Sbostic case N_SSYM: 46839109Sbostic return("SSYM"); 46939109Sbostic case N_STSYM: 47039109Sbostic return("STSYM"); 471619Sbill } 47239109Sbostic return("???"); 473619Sbill } 474619Sbill 47539109Sbostic /* 47639109Sbostic * typeletter() 47739109Sbostic * return a description letter for the given basic type code of an 47839109Sbostic * symbol table entry. The return value will be upper case for 47939109Sbostic * external, lower case for internal symbols. 48039109Sbostic */ 48139109Sbostic char 48239109Sbostic typeletter(type) 48339109Sbostic u_char type; 484619Sbill { 48539109Sbostic switch(SYMBOL_TYPE(type)) { 48639109Sbostic case N_ABS: 48739109Sbostic return(IS_EXTERNAL(type) ? 'A' : 'a'); 48839109Sbostic case N_BSS: 48939109Sbostic return(IS_EXTERNAL(type) ? 'B' : 'b'); 49039109Sbostic case N_COMM: 49139109Sbostic return(IS_EXTERNAL(type) ? 'C' : 'c'); 49239109Sbostic case N_DATA: 49339109Sbostic return(IS_EXTERNAL(type) ? 'D' : 'd'); 49439109Sbostic case N_FN: 49539109Sbostic return(IS_EXTERNAL(type) ? 'F' : 'f'); 49639109Sbostic case N_TEXT: 49739109Sbostic return(IS_EXTERNAL(type) ? 'T' : 't'); 49839109Sbostic case N_UNDF: 49939109Sbostic return(IS_EXTERNAL(type) ? 'U' : 'u'); 50039109Sbostic } 50139109Sbostic return('?'); 50239109Sbostic } 503619Sbill 50439109Sbostic /* 50539109Sbostic * cmp_name() 50639109Sbostic * compare two symbols by their names 50739109Sbostic */ 508*42452Sbostic cmp_name(a0, b0) 509*42452Sbostic void *a0, *b0; 51039109Sbostic { 511*42452Sbostic struct nlist *a = a0, *b = b0; 512*42452Sbostic 51339109Sbostic return(sort_direction == FORWARD ? 51439109Sbostic strcmp(a->n_un.n_name, b->n_un.n_name) : 51539109Sbostic strcmp(b->n_un.n_name, a->n_un.n_name)); 516619Sbill } 517619Sbill 51839109Sbostic /* 51939109Sbostic * cmp_value() 52039109Sbostic * compare two symbols by their values 52139109Sbostic */ 522*42452Sbostic cmp_value(a0, b0) 523*42452Sbostic void *a0, *b0; 52439109Sbostic { 525*42452Sbostic register struct nlist *a = a0, *b = b0; 526*42452Sbostic 52739109Sbostic if (SYMBOL_TYPE(a->n_type) == N_UNDF) 52839109Sbostic if (SYMBOL_TYPE(b->n_type) == N_UNDF) 52939109Sbostic return(0); 53039109Sbostic else 53139109Sbostic return(-1); 53239109Sbostic else if (SYMBOL_TYPE(b->n_type) == N_UNDF) 53339109Sbostic return(1); 53439109Sbostic if (a->n_value == b->n_value) 535*42452Sbostic return(cmp_name((void *)a, (void *)b)); 53639109Sbostic return(sort_direction == FORWARD ? a->n_value > b->n_value : 53739109Sbostic a->n_value < b->n_value); 53839109Sbostic } 539619Sbill 540619Sbill char * 54139109Sbostic emalloc(size) 542*42452Sbostic size_t size; 543619Sbill { 544*42452Sbostic char *p; 545619Sbill 54639109Sbostic /* NOSTRICT */ 54739109Sbostic if (!(p = malloc(size))) { 54839109Sbostic (void)fprintf(stderr, "nm: no more memory.\n"); 54939109Sbostic exit(1); 55039109Sbostic } 55139109Sbostic return(p); 552619Sbill } 55330855Sbostic 55439109Sbostic usage() 55530855Sbostic { 556*42452Sbostic (void)fprintf(stderr, "usage: nm [-agnopruw] [file ...]\n"); 55739109Sbostic exit(1); 55830855Sbostic } 559