Annotation of src/usr.bin/gprof/aout.c, Revision 1.2
1.1 art 1: /*-
2: * Copyright (c) 1983, 1993
3: * The Regents of the University of California. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
1.2 ! millert 13: * 3. Neither the name of the University nor the names of its contributors
1.1 art 14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: #include <sys/types.h>
31: #include <a.out.h>
32:
33: #include "gprof.h"
34:
35: static void getstrtab(FILE *, const char *);
36: static void getsymtab(FILE *, const char *);
37: static void gettextspace(FILE *);
38: static bool funcsymbol(struct nlist *);
39:
40: static char *strtab; /* string table in core */
41: static long ssiz; /* size of the string table */
42: static struct exec xbuf; /* exec header of a.out */
43:
44: /* Things which get -E excluded by default. */
45: static char *excludes[] = { "mcount", "__mcleanup", NULL };
46:
47: /*
48: * Set up string and symbol tables from a.out.
49: * and optionally the text space.
50: * On return symbol table is sorted by value.
51: *
52: * Returns 0 on success, -1 on failure.
53: */
54: int
55: getnfile(const char *filename, char ***defaultEs)
56: {
57: FILE *nfile;
58:
59: nfile = fopen( filename ,"r");
60: if (nfile == NULL)
61: err(1, "fopen: %s", filename);
62:
63: fread(&xbuf, 1, sizeof(xbuf), nfile);
64: if (N_BADMAG(xbuf)) {
65: /* Bail out and let other binary formats try. */
66: fclose(nfile);
67: return (-1);
68: }
69: getstrtab(nfile, filename);
70: getsymtab(nfile, filename);
71: gettextspace(nfile);
72: fclose(nfile);
73: #ifdef DEBUG
74: if (debug & AOUTDEBUG) {
75: int j;
76:
77: for (j = 0; j < nname; j++) {
78: printf("[getnfile] 0X%08lx\t%s\n", nl[j].value,
79: nl[j].name);
80: }
81: }
82: #endif
83: *defaultEs = excludes;
84: return (0);
85: }
86:
87: static void
88: getstrtab(FILE *nfile, const char *filename)
89: {
90: fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0);
91: if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0)
92: errx(1, "%s: no string table (old format?)" , filename );
93: strtab = calloc(ssiz, 1);
94: if (strtab == NULL)
95: errx(1, "%s: no room for %d bytes of string table", filename,
96: ssiz);
97: if (fread(strtab + sizeof(ssiz), ssiz - sizeof(ssiz), 1, nfile) != 1)
98: errx(1, "%s: error reading string table", filename );
99: }
100:
101: /*
102: * Read in symbol table
103: */
104: static void
105: getsymtab(FILE *nfile, const char *filename)
106: {
107: struct nlist nbuf;
108: int askfor;
109: long i;
110:
111: /* pass1 - count symbols */
112: fseek(nfile, (long)N_SYMOFF(xbuf), 0);
113: nname = 0;
114: for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
115: fread(&nbuf, sizeof(nbuf), 1, nfile);
116: if (funcsymbol(&nbuf))
117: nname++;
118: }
119: if (nname == 0)
120: errx(1, "%s: no symbols", filename);
121:
122: askfor = nname + 1;
123: nl = calloc(askfor , sizeof(nltype));
124: if (nl == 0)
125: errx(1, "No room for %d bytes of symbol table",
126: askfor * sizeof(nltype));
127:
128: /* pass2 - read symbols */
129: fseek(nfile, (long)N_SYMOFF(xbuf), 0);
130: npe = nl;
131: nname = 0;
132: for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
133: fread(&nbuf, sizeof(nbuf), 1, nfile);
134: if (!funcsymbol(&nbuf)) {
135: #ifdef DEBUG
136: if (debug & AOUTDEBUG) {
137: printf("[getsymtab] rejecting: 0x%x %s\n",
138: nbuf.n_type, strtab + nbuf.n_un.n_strx);
139: }
140: #endif
141: continue;
142: }
143: npe->value = nbuf.n_value;
144: npe->name = strtab + nbuf.n_un.n_strx;
145: #ifdef DEBUG
146: if (debug & AOUTDEBUG) {
147: printf("[getsymtab] %d %s 0x%08lx\n",
148: nname, npe->name, npe->value);
149: }
150: #endif
151: npe++;
152: nname++;
153: }
154: npe->value = -1;
155: }
156:
157: /*
158: * read in the text space of an a.out file
159: */
160: static void
161: gettextspace(FILE *nfile)
162: {
163: if (cflag == 0)
164: return;
165: textspace = malloc(xbuf.a_text);
166: if (textspace == 0) {
167: warnx("ran out room for %d bytes of text space: can't do -c" ,
168: xbuf.a_text);
169: return;
170: }
171: (void)fseek(nfile, N_TXTOFF(xbuf), 0);
172: if (fread(textspace, 1, xbuf.a_text, nfile) != xbuf.a_text ) {
173: warnx("couldn't read text space: can't do -c");
174: free(textspace);
175: textspace = 0;
176: return;
177: }
178: }
179:
180: static bool
181: funcsymbol(struct nlist *nlistp)
182: {
183: char *name, c;
184:
185: /*
186: * must be a text symbol,
187: * and static text symbols don't qualify if aflag set.
188: */
189: if (!((nlistp->n_type == (N_TEXT|N_EXT))
190: || ((nlistp->n_type == N_TEXT) && (aflag == 0))))
191: return FALSE;
192:
193: /*
194: * name must start with an underscore if uflag is set.
195: * can't have any `funny' characters in name,
196: * where `funny' means `.' (.o file names)
197: * need to make an exception for sparc .mul & co.
198: * perhaps we should just drop this code entirely...
199: */
200: name = strtab + nlistp -> n_un.n_strx;
201: #ifdef sparc
202: if (nlistp -> n_value & 3)
203: return (FALSE);
204: if (*name == '.') {
205: char *p = name + 1;
206: if (*p == 'u')
207: p++;
208: if (strcmp(p, "mul") == 0 || strcmp(p, "div") == 0 ||
209: strcmp(p, "rem") == 0 )
210: return (TRUE);
211: }
212: #endif
213: while (c = *name++) {
214: if (c == '.') {
215: return (FALSE);
216: }
217: }
218:
219: return (TRUE);
220: }