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