1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)nlist.c 5.6 (Berkeley) 03/02/90"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/types.h> 23 #include <sys/file.h> 24 #include <a.out.h> 25 #include <stdio.h> 26 #include <unistd.h> 27 28 typedef struct nlist NLIST; 29 #define _strx n_un.n_strx 30 #define _name n_un.n_name 31 #define ISVALID(p) (p->_name && p->_name[0]) 32 33 nlist(name, list) 34 char *name; 35 NLIST *list; 36 { 37 register NLIST *p, *s; 38 struct exec ebuf; 39 FILE *fstr, *fsym; 40 NLIST nbuf; 41 off_t strings_offset, symbol_offset, symbol_size, lseek(); 42 int entries, len, maxlen; 43 char sbuf[256]; 44 45 entries = -1; 46 47 if (!(fsym = fopen(name, "r"))) 48 return(-1); 49 if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 || 50 N_BADMAG(ebuf)) 51 goto done1; 52 53 symbol_offset = N_SYMOFF(ebuf); 54 symbol_size = ebuf.a_syms; 55 strings_offset = symbol_offset + symbol_size; 56 if (fseek(fsym, symbol_offset, SEEK_SET)) 57 goto done1; 58 59 if (!(fstr = fopen(name, "r"))) 60 goto done1; 61 62 /* 63 * clean out any left-over information for all valid entries. 64 * Type and value defined to be 0 if not found; historical 65 * versions cleared other and desc as well. Also figure out 66 * the largest string length so don't read any more of the 67 * string table than we have to. 68 */ 69 for (p = list, entries = maxlen = 0; ISVALID(p); ++p, ++entries) { 70 p->n_type = 0; 71 p->n_other = 0; 72 p->n_desc = 0; 73 p->n_value = 0; 74 if ((len = strlen(p->_name)) > maxlen) 75 maxlen = len; 76 } 77 if (++maxlen > sizeof(sbuf)) { /* for the NULL */ 78 (void)fprintf(stderr, "nlist: symbol too large.\n"); 79 entries = -1; 80 goto done2; 81 } 82 83 for (s = &nbuf; symbol_size; symbol_size -= sizeof(NLIST)) { 84 if (fread((char *)s, sizeof(NLIST), 1, fsym) != 1) 85 goto done2; 86 if (!s->_strx || s->n_type&N_STAB) 87 continue; 88 if (fseek(fstr, strings_offset + s->_strx, SEEK_SET)) 89 goto done2; 90 (void)fread(sbuf, sizeof(sbuf[0]), maxlen, fstr); 91 for (p = list; ISVALID(p); p++) 92 if (!strcmp(p->_name, sbuf)) { 93 p->n_value = s->n_value; 94 p->n_type = s->n_type; 95 p->n_desc = s->n_desc; 96 p->n_other = s->n_other; 97 if (!--entries) 98 goto done2; 99 } 100 } 101 done2: (void)fclose(fstr); 102 done1: (void)fclose(fsym); 103 return(entries); 104 } 105