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*42034Sbostic static char sccsid[] = "@(#)nm.c 5.4 (Berkeley) 05/15/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*42034Sbostic #include <string.h> 41619Sbill 4240272Sbostic extern int errno; 43619Sbill 4440272Sbostic int ignore_bad_archive_entries = 1; 4540272Sbostic int print_only_external_symbols; 4640272Sbostic int print_only_undefined_symbols; 4740272Sbostic int print_all_symbols; 4840272Sbostic int print_file_each_line; 4940272Sbostic int cmp_value(), cmp_name(); 5040272Sbostic int (*sort_func)() = cmp_name; 5140272Sbostic 5239109Sbostic enum { FORWARD, BACKWARD } sort_direction = FORWARD; 5339109Sbostic int fcount; 5430855Sbostic 5539109Sbostic /* some macros for symbol type (nlist.n_type) handling */ 5639109Sbostic #define IS_DEBUGGER_SYMBOL(x) ((x) & N_STAB) 5739109Sbostic #define IS_EXTERNAL(x) ((x) & N_EXT) 5839109Sbostic #define SYMBOL_TYPE(x) ((x) & (N_TYPE | N_STAB)) 5930855Sbostic 6039109Sbostic /* 6139109Sbostic * main() 6239109Sbostic * parse command line, execute process_file() for each file 6339109Sbostic * specified on the command line. 6439109Sbostic */ 65619Sbill main(argc, argv) 6639109Sbostic int argc; 6739109Sbostic char **argv; 68619Sbill { 6939109Sbostic extern int optind; 7039109Sbostic int ch, errors; 71619Sbill 7239109Sbostic while ((ch = getopt(argc, argv, "agnopruw")) != EOF) { 7339109Sbostic switch (ch) { 7430855Sbostic case 'a': 7539109Sbostic print_all_symbols = 1; 7630855Sbostic break; 7730855Sbostic case 'g': 7839109Sbostic print_only_external_symbols = 1; 7930855Sbostic break; 80619Sbill case 'n': 8139109Sbostic sort_func = cmp_value; 8230855Sbostic break; 8330855Sbostic case 'o': 8439109Sbostic print_file_each_line = 1; 8530855Sbostic break; 8630855Sbostic case 'p': 8739109Sbostic sort_func = NULL; 8830855Sbostic break; 89619Sbill case 'r': 9039109Sbostic sort_direction = BACKWARD; 9130855Sbostic break; 9230855Sbostic case 'u': 9339109Sbostic print_only_undefined_symbols = 1; 9430855Sbostic break; 9539109Sbostic case 'w': 9639109Sbostic ignore_bad_archive_entries = 0; 9739109Sbostic break; 9830855Sbostic case '?': 99619Sbill default: 10039109Sbostic usage(); 101619Sbill } 10239109Sbostic } 10339109Sbostic fcount = argc - optind; 10430855Sbostic argv += optind; 10539109Sbostic 10639109Sbostic if (!fcount) 10739109Sbostic errors = process_file("a.out"); 10839109Sbostic else { 10939109Sbostic errors = 0; 11039109Sbostic do { 11139109Sbostic errors |= process_file(*argv); 11239109Sbostic } while (*++argv); 113619Sbill } 11439109Sbostic exit(errors); 115619Sbill } 116619Sbill 11739109Sbostic /* 11839109Sbostic * process_file() 11939109Sbostic * show symbols in the file given as an argument. Accepts archive and 12039109Sbostic * object files as input. 12139109Sbostic */ 12239109Sbostic process_file(fname) 12339109Sbostic char *fname; 124619Sbill { 12539109Sbostic struct exec exec_head; 12639109Sbostic FILE *fp; 12739109Sbostic int retval; 12839109Sbostic char magic[SARMAG]; 12939109Sbostic 13039109Sbostic if (!(fp = fopen(fname, "r"))) { 13139109Sbostic (void)fprintf(stderr, "nm: cannot read %s.\n", fname); 13239109Sbostic return(1); 13339109Sbostic } 134619Sbill 13539109Sbostic if (fcount > 1) 13639109Sbostic (void)printf("\n%s:\n", fname); 13739109Sbostic 13830855Sbostic /* 13939109Sbostic * first check whether this is an object file - read a object 14039109Sbostic * header, and skip back to the beginning 14130855Sbostic */ 14239109Sbostic if (fread((char *)&exec_head, 1, sizeof(exec_head), fp) != 14339109Sbostic sizeof(exec_head)) { 14439109Sbostic (void)fprintf(stderr, "nm: %s: bad format.\n", fname); 14539109Sbostic (void)fclose(fp); 14639109Sbostic return(1); 147619Sbill } 14839109Sbostic rewind(fp); 14939109Sbostic 15039109Sbostic /* this could be an archive */ 15139109Sbostic if (N_BADMAG(exec_head)) { 15239109Sbostic if (fread(magic, 1, sizeof(magic), fp) != sizeof(magic) || 15339109Sbostic strncmp(magic, ARMAG, SARMAG)) { 15439109Sbostic (void)fprintf(stderr, 15539109Sbostic "nm: %s: not object file or archive.\n", fname); 15639109Sbostic (void)fclose(fp); 15739109Sbostic return(1); 15830855Sbostic } 15939109Sbostic retval = show_archive(fname, fp); 16039109Sbostic } else 16139109Sbostic retval = show_objfile(fname, fp); 16239109Sbostic (void)fclose(fp); 16339109Sbostic return(retval); 16439109Sbostic } 16539109Sbostic 16639109Sbostic /* 16739109Sbostic * show_archive() 16839109Sbostic * show symbols in the given archive file 16939109Sbostic */ 17039109Sbostic show_archive(fname, fp) 17139109Sbostic char *fname; 17239109Sbostic FILE *fp; 17339109Sbostic { 17439109Sbostic struct ar_hdr ar_head; 17539109Sbostic struct exec exec_head; 17639109Sbostic off_t esize; 17739109Sbostic int i, last_ar_off, rval; 17839109Sbostic char *p, *name, *emalloc(); 17939109Sbostic long atol(); 18039109Sbostic 18139109Sbostic name = emalloc((u_int)(sizeof(ar_head.ar_name) + strlen(fname) + 3)); 18239109Sbostic 18339109Sbostic rval = 0; 18439109Sbostic 18539109Sbostic /* while there are more entries in the archive */ 18639109Sbostic while (fread((char *)&ar_head, 1, sizeof(ar_head), fp) == 18739109Sbostic sizeof(ar_head)) { 18839109Sbostic /* bad archive entry - stop processing this archive */ 18939109Sbostic if (strncmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) { 19039109Sbostic (void)fprintf(stderr, 19139109Sbostic "nm: %s: bad format archive header", fname); 19239109Sbostic (void)free(name); 19339109Sbostic return(1); 19439109Sbostic } 19539109Sbostic 19630855Sbostic /* 19739143Sbostic * construct a name of the form "archive.a:obj.o:" for the 19839109Sbostic * current archive entry if the object name is to be printed 19939109Sbostic * on each output line 20030855Sbostic */ 20139109Sbostic if (print_file_each_line) { 20239143Sbostic (void)sprintf(name, "%s:", fname); 20339109Sbostic p = name + strlen(name); 20439109Sbostic } else 20539109Sbostic p = name; 20639109Sbostic for (i = 0; i < sizeof(ar_head.ar_name); ++i) 20739109Sbostic if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ') 20839109Sbostic *p++ = ar_head.ar_name[i]; 20939109Sbostic *p++ = '\0'; 21030855Sbostic 21139109Sbostic /* remember start position of current archive object */ 21239109Sbostic last_ar_off = ftell(fp); 21330855Sbostic 21439109Sbostic /* get and check current object's header */ 21539109Sbostic if (fread((char *)&exec_head, 1, sizeof(exec_head), fp) != 21639109Sbostic sizeof(exec_head)) { 21739109Sbostic (void)fprintf(stderr, "nm: %s: premature EOF.\n", name); 21839109Sbostic (void)free(name); 21939109Sbostic return(1); 220619Sbill } 22139109Sbostic if (strcmp(name, RANLIBMAG)) 22239109Sbostic if (N_BADMAG(exec_head)) { 22339109Sbostic if (!ignore_bad_archive_entries) { 22439109Sbostic (void)fprintf(stderr, 22539109Sbostic "nm: %s: bad format.\n", name); 22639109Sbostic rval = 1; 22739109Sbostic } 22839109Sbostic } else { 22939109Sbostic (void)fseek(fp, (long)-sizeof(exec_head), 23039109Sbostic SEEK_CUR); 23139109Sbostic if (!print_file_each_line) 23239109Sbostic (void)printf("\n%s:\n", name); 23339109Sbostic rval |= show_objfile(name, fp); 23439109Sbostic } 23539109Sbostic esize = atol(ar_head.ar_size); 23630855Sbostic 23739109Sbostic /* 23839109Sbostic * skip to next archive object - esize&1 is added to stay 23939109Sbostic * on even starting points relative to the start of the 24039109Sbostic * archive file 24139109Sbostic */ 24239109Sbostic if (fseek(fp, (long)(last_ar_off + esize + (esize&1)), 24339109Sbostic SEEK_SET)) { 24439109Sbostic (void)fprintf(stderr, 24539109Sbostic "nm: %s: %s\n", fname, strerror(errno)); 24639109Sbostic (void)free(name); 24739109Sbostic return(1); 24830855Sbostic } 24939109Sbostic } 25039109Sbostic (void)free(name); 25139109Sbostic return(rval); 25239109Sbostic } 25330855Sbostic 25439109Sbostic /* 25539109Sbostic * show_objfile() 25639109Sbostic * show symbols from the object file pointed to by fp. The current 25739109Sbostic * file pointer for fp is expected to be at the beginning of an a.out 25839109Sbostic * header. 25939109Sbostic */ 26039109Sbostic show_objfile(objname, fp) 26139109Sbostic char *objname; 26239109Sbostic FILE *fp; 26339109Sbostic { 26439109Sbostic register struct nlist *names; 26539109Sbostic register int i, nnames, nrawnames; 26639109Sbostic struct exec head; 26739109Sbostic long stabsize; 26839109Sbostic char *stab, *emalloc(); 26939109Sbostic 27039109Sbostic /* read a.out header */ 27139109Sbostic if (fread((char *)&head, sizeof(head), 1, fp) != 1) { 27239109Sbostic (void)fprintf(stderr, 27339109Sbostic "nm: %s: cannot read header.\n", objname); 27439109Sbostic return(1); 27539109Sbostic } 27639109Sbostic 27739109Sbostic /* 27839109Sbostic * skip back to the header - the N_-macros return values relative 27939109Sbostic * to the beginning of the a.out header 28039109Sbostic */ 28139109Sbostic if (fseek(fp, (long)-sizeof(head), SEEK_CUR)) { 28239109Sbostic (void)fprintf(stderr, 28339109Sbostic "nm: %s: %s\n", objname, strerror(errno)); 28439109Sbostic return(1); 28539109Sbostic } 28639109Sbostic 28739109Sbostic /* stop if this is no valid object file */ 28839109Sbostic if (N_BADMAG(head)) { 28939109Sbostic (void)fprintf(stderr, 29039109Sbostic "nm: %s: bad format.\n", objname); 29139109Sbostic return(1); 29239109Sbostic } 29339109Sbostic 29439109Sbostic /* stop if the object file contains no symbol table */ 29539109Sbostic if (!head.a_syms) { 29639109Sbostic (void)fprintf(stderr, 29739109Sbostic "nm: %s: no name list.\n", objname); 29839109Sbostic return(1); 29939109Sbostic } 30039109Sbostic 30139109Sbostic if (fseek(fp, (long)N_SYMOFF(head), SEEK_CUR)) { 30239109Sbostic (void)fprintf(stderr, 30339109Sbostic "nm: %s: %s\n", objname, strerror(errno)); 30439109Sbostic return(1); 30539109Sbostic } 30639109Sbostic 30739109Sbostic /* get memory for the symbol table */ 30839109Sbostic names = (struct nlist *)emalloc((u_int)head.a_syms); 30939109Sbostic nrawnames = head.a_syms / sizeof(*names); 31039109Sbostic if (fread((char *)names, 1, (int)head.a_syms, fp) != head.a_syms) { 31139109Sbostic (void)fprintf(stderr, 31239109Sbostic "nm: %s: cannot read symbol table.\n", objname); 31339109Sbostic (void)free((char *)names); 31439109Sbostic return(1); 31539109Sbostic } 31639109Sbostic 31739109Sbostic /* 31839109Sbostic * Following the symbol table comes the string table. The first 31939109Sbostic * 4-byte-integer gives the total size of the string table 32039109Sbostic * _including_ the size specification itself. 32139109Sbostic */ 32239109Sbostic if (fread((char *)&stabsize, sizeof(stabsize), 1, fp) != 1) { 32339109Sbostic (void)fprintf(stderr, 32439109Sbostic "nm: %s: cannot read stab size.\n", objname); 32539109Sbostic (void)free((char *)names); 32639109Sbostic return(1); 32739109Sbostic } 32839109Sbostic stab = emalloc((u_int)stabsize); 32939109Sbostic 33039109Sbostic /* 33139109Sbostic * read the string table offset by 4 - all indices into the string 33239109Sbostic * table include the size specification. 33339109Sbostic */ 33439143Sbostic stabsize -= 4; /* we already have the size */ 33539109Sbostic if (fread(stab + 4, 1, (int)stabsize, fp) != stabsize) { 33639109Sbostic (void)fprintf(stderr, 33739109Sbostic "nm: %s: stab truncated..\n", objname); 33839109Sbostic (void)free((char *)names); 33939109Sbostic (void)free(stab); 34039109Sbostic return(1); 34139109Sbostic } 34239109Sbostic 34339109Sbostic /* 34439109Sbostic * fix up the symbol table and filter out unwanted entries 34539109Sbostic * 34639109Sbostic * common symbols are characterized by a n_type of N_UNDF and a 34739109Sbostic * non-zero n_value -- change n_type to N_COMM for all such 34839109Sbostic * symbols to make life easier later. 34939109Sbostic * 35039109Sbostic * filter out all entries which we don't want to print anyway 35139109Sbostic */ 35239109Sbostic for (i = nnames = 0; i < nrawnames; ++i) { 35339109Sbostic if (SYMBOL_TYPE(names[i].n_type) == N_UNDF && names[i].n_value) 35439109Sbostic names[i].n_type = N_COMM | (names[i].n_type & N_EXT); 35539109Sbostic if (!print_all_symbols && IS_DEBUGGER_SYMBOL(names[i].n_type)) 35630855Sbostic continue; 35739109Sbostic if (print_only_external_symbols && 35839109Sbostic !IS_EXTERNAL(names[i].n_type)) 359619Sbill continue; 36039109Sbostic if (print_only_undefined_symbols && 36139109Sbostic (SYMBOL_TYPE(names[i].n_type) != N_UNDF)) 36239109Sbostic continue; 36330855Sbostic 36439109Sbostic /* 36539109Sbostic * make n_un.n_name a character pointer by adding the string 36639109Sbostic * table's base to n_un.n_strx 36739109Sbostic * 36839109Sbostic * don't mess with null offsets 36939109Sbostic */ 37039109Sbostic if (names[i].n_un.n_name) 37139109Sbostic names[i].n_un.n_name = stab + names[i].n_un.n_strx; 37239109Sbostic else 37339109Sbostic names[i].n_un.n_name = ""; 37439109Sbostic if (nnames != i) 37539109Sbostic names[nnames] = names[i]; 37639109Sbostic ++nnames; 37739109Sbostic } 37830855Sbostic 37939109Sbostic /* sort the symbol table if applicable */ 38039109Sbostic if (sort_func) 38139109Sbostic qsort((char *)names, (int)nnames, sizeof(*names), sort_func); 38230855Sbostic 38339109Sbostic /* print out symbols */ 38439109Sbostic for (i = 0; i < nnames; ++i) 38539109Sbostic print_symbol(objname, &names[i]); 38630855Sbostic 38739109Sbostic (void)free((char *)names); 38839109Sbostic (void)free(stab); 38939109Sbostic return(0); 390619Sbill } 391619Sbill 39239109Sbostic /* 39339109Sbostic * print_symbol() 39439109Sbostic * show one symbol 39539109Sbostic */ 39639109Sbostic print_symbol(objname, sym) 39739109Sbostic char *objname; 39839109Sbostic struct nlist *sym; 399619Sbill { 40039109Sbostic char *typestring(), typeletter(); 401619Sbill 40239109Sbostic if (print_file_each_line) 40339143Sbostic printf("%s:", objname); 40439109Sbostic 40539109Sbostic /* 40639109Sbostic * handle undefined-only format seperately (no space is 40739109Sbostic * left for symbol values, no type field is printed) 40839109Sbostic */ 40939109Sbostic if (print_only_undefined_symbols) { 41039109Sbostic printf("%s\n", sym->n_un.n_name); 41139109Sbostic return; 412619Sbill } 41339109Sbostic 41439109Sbostic /* print symbol's value */ 41539109Sbostic if (SYMBOL_TYPE(sym->n_type) == N_UNDF) 41639109Sbostic (void)printf(" "); 41739109Sbostic else 41839109Sbostic (void)printf("%08lx", sym->n_value); 41939109Sbostic 42039109Sbostic /* print type information */ 42139109Sbostic if (IS_DEBUGGER_SYMBOL(sym->n_type)) 42239109Sbostic (void)printf(" - %02x %04x %5s ", sym->n_other, 42339109Sbostic sym->n_desc&0xffff, typestring(sym->n_type)); 42439109Sbostic else 42539109Sbostic (void)printf(" %c ", typeletter(sym->n_type)); 42639109Sbostic 42739109Sbostic /* print the symbol's name */ 42839109Sbostic (void)printf("%s\n", sym->n_un.n_name ? sym->n_un.n_name : ""); 429619Sbill } 430619Sbill 43139109Sbostic /* 43239109Sbostic * typestring() 43339109Sbostic * return the a description string for an STAB entry 43439109Sbostic */ 43539109Sbostic char * 43639109Sbostic typestring(type) 43739109Sbostic register u_char type; 438619Sbill { 43939109Sbostic switch(type) { 44039109Sbostic case N_BCOMM: 44139109Sbostic return("BCOMM"); 44239109Sbostic case N_ECOML: 44339109Sbostic return("ECOML"); 44439109Sbostic case N_ECOMM: 44539109Sbostic return("ECOMM"); 44639109Sbostic case N_ENTRY: 44739109Sbostic return("ENTRY"); 44839109Sbostic case N_FNAME: 44939109Sbostic return("FNAME"); 45039109Sbostic case N_FUN: 45139109Sbostic return("FUN"); 45239109Sbostic case N_GSYM: 45339109Sbostic return("GSYM"); 45439109Sbostic case N_LBRAC: 45539109Sbostic return("LBRAC"); 45639109Sbostic case N_LCSYM: 45739109Sbostic return("LCSYM"); 45839109Sbostic case N_LENG: 45939109Sbostic return("LENG"); 46039109Sbostic case N_LSYM: 46139109Sbostic return("LSYM"); 46239109Sbostic case N_PC: 46339109Sbostic return("PC"); 46439109Sbostic case N_PSYM: 46539109Sbostic return("PSYM"); 46639109Sbostic case N_RBRAC: 46739109Sbostic return("RBRAC"); 46839109Sbostic case N_RSYM: 46939109Sbostic return("RSYM"); 47039109Sbostic case N_SLINE: 47139109Sbostic return("SLINE"); 47239109Sbostic case N_SO: 47339109Sbostic return("SO"); 47439109Sbostic case N_SOL: 47539109Sbostic return("SOL"); 47639109Sbostic case N_SSYM: 47739109Sbostic return("SSYM"); 47839109Sbostic case N_STSYM: 47939109Sbostic return("STSYM"); 480619Sbill } 48139109Sbostic return("???"); 482619Sbill } 483619Sbill 48439109Sbostic /* 48539109Sbostic * typeletter() 48639109Sbostic * return a description letter for the given basic type code of an 48739109Sbostic * symbol table entry. The return value will be upper case for 48839109Sbostic * external, lower case for internal symbols. 48939109Sbostic */ 49039109Sbostic char 49139109Sbostic typeletter(type) 49239109Sbostic u_char type; 493619Sbill { 49439109Sbostic switch(SYMBOL_TYPE(type)) { 49539109Sbostic case N_ABS: 49639109Sbostic return(IS_EXTERNAL(type) ? 'A' : 'a'); 49739109Sbostic case N_BSS: 49839109Sbostic return(IS_EXTERNAL(type) ? 'B' : 'b'); 49939109Sbostic case N_COMM: 50039109Sbostic return(IS_EXTERNAL(type) ? 'C' : 'c'); 50139109Sbostic case N_DATA: 50239109Sbostic return(IS_EXTERNAL(type) ? 'D' : 'd'); 50339109Sbostic case N_FN: 50439109Sbostic return(IS_EXTERNAL(type) ? 'F' : 'f'); 50539109Sbostic case N_TEXT: 50639109Sbostic return(IS_EXTERNAL(type) ? 'T' : 't'); 50739109Sbostic case N_UNDF: 50839109Sbostic return(IS_EXTERNAL(type) ? 'U' : 'u'); 50939109Sbostic } 51039109Sbostic return('?'); 51139109Sbostic } 512619Sbill 51339109Sbostic /* 51439109Sbostic * cmp_name() 51539109Sbostic * compare two symbols by their names 51639109Sbostic */ 51739109Sbostic cmp_name(a, b) 51839109Sbostic struct nlist *a, *b; 51939109Sbostic { 52039109Sbostic return(sort_direction == FORWARD ? 52139109Sbostic strcmp(a->n_un.n_name, b->n_un.n_name) : 52239109Sbostic strcmp(b->n_un.n_name, a->n_un.n_name)); 523619Sbill } 524619Sbill 52539109Sbostic /* 52639109Sbostic * cmp_value() 52739109Sbostic * compare two symbols by their values 52839109Sbostic */ 52939109Sbostic cmp_value(a, b) 53039109Sbostic struct nlist *a, *b; 53139109Sbostic { 53239109Sbostic if (SYMBOL_TYPE(a->n_type) == N_UNDF) 53339109Sbostic if (SYMBOL_TYPE(b->n_type) == N_UNDF) 53439109Sbostic return(0); 53539109Sbostic else 53639109Sbostic return(-1); 53739109Sbostic else if (SYMBOL_TYPE(b->n_type) == N_UNDF) 53839109Sbostic return(1); 53939109Sbostic if (a->n_value == b->n_value) 54039109Sbostic return(cmp_name(a, b)); 54139109Sbostic return(sort_direction == FORWARD ? a->n_value > b->n_value : 54239109Sbostic a->n_value < b->n_value); 54339109Sbostic } 544619Sbill 545619Sbill char * 54639109Sbostic emalloc(size) 54739109Sbostic u_int size; 548619Sbill { 54939109Sbostic char *p, *malloc(); 550619Sbill 55139109Sbostic /* NOSTRICT */ 55239109Sbostic if (!(p = malloc(size))) { 55339109Sbostic (void)fprintf(stderr, "nm: no more memory.\n"); 55439109Sbostic exit(1); 55539109Sbostic } 55639109Sbostic return(p); 557619Sbill } 55830855Sbostic 55939109Sbostic usage() 56030855Sbostic { 56139109Sbostic (void)fprintf(stderr, "usage: nm [-agnopruw] [file ...]"); 56239109Sbostic exit(1); 56330855Sbostic } 564