xref: /386bsd/usr/src/usr.bin/symorder/symorder.c (revision a2142627)
1 /*
2  * Copyright (c) 1980 The Regents of the University of California.
3  * 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.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
37  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 static char sccsid[] = "@(#)symorder.c	5.8 (Berkeley) 4/1/91";
42 #endif /* not lint */
43 
44 /*
45  * symorder - reorder symbol table
46  */
47 
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <errno.h>
52 #include <a.out.h>
53 #include <unistd.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 #define SPACE		500
59 
60 #define	OKEXIT		0
61 #define	NOTFOUNDEXIT	1
62 #define	ERREXIT		2
63 
64 struct	nlist order[SPACE];
65 
66 struct	exec exec;
67 struct	stat stb;
68 struct	nlist *newtab, *symtab;
69 off_t	sa;
70 int	nsym, strtabsize, symfound, small;
71 char	*kfile, *newstrings, *strings, asym[BUFSIZ];
72 
main(argc,argv)73 main(argc, argv)
74 	int argc;
75 	char **argv;
76 {
77 	extern char *optarg;
78 	extern int optind;
79 	register struct nlist *p, *symp;
80 	register FILE *f;
81 	register int i;
82 	register char *start, *t;
83 	int ch, n, o;
84 
85 	while ((ch = getopt(argc, argv, "t")) != EOF)
86 		switch(ch) {
87 		case 't':
88 			small = 1;
89 			break;
90 		case '?':
91 		default:
92 			usage();
93 		}
94 	argc -= optind;
95 	argv += optind;
96 
97 	if (argc != 2)
98 		usage();
99 
100 	if ((f = fopen(argv[0], "r")) == NULL)
101 		error(argv[0]);
102 
103 	for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
104 		for (t = asym; isspace(*t); ++t);
105 		if (!*(start = t))
106 			continue;
107 		while (*++t);
108 		if (*--t == '\n')
109 			*t = '\0';
110 		p->n_un.n_name = strdup(start);
111 		++p;
112 		++nsym;
113 	}
114 	(void)fclose(f);
115 
116 	kfile = argv[1];
117 	if ((f = fopen(kfile, "r")) == NULL)
118 		error(kfile);
119 	if ((o = open(kfile, O_WRONLY)) < 0)
120 		error(kfile);
121 
122 	/* read exec header */
123 	if ((fread(&exec, sizeof(exec), 1, f)) != 1)
124 		badfmt("no exec header");
125 	if (N_BADMAG(exec))
126 		badfmt("bad magic number");
127 	if (exec.a_syms == 0)
128 		badfmt("stripped");
129 	(void)fstat(fileno(f), &stb);
130 	if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
131 		badfmt("no string table");
132 
133 	/* seek to and read the symbol table */
134 	sa = N_SYMOFF(exec);
135 	(void)fseek(f, sa, SEEK_SET);
136 	n = exec.a_syms;
137 	if (!(symtab = (struct nlist *)malloc(n)))
138 		error(NULL);
139 	if (fread((void *)symtab, 1, n, f) != n)
140 		badfmt("corrupted symbol table");
141 
142 	/* read string table size and string table */
143 	if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 ||
144 	    strtabsize <= 0)
145 		badfmt("corrupted string table");
146 	strings = malloc(strtabsize);
147 	if (strings == NULL)
148 		error(NULL);
149 	/*
150 	 * Subtract four from strtabsize since strtabsize includes itself,
151 	 * and we've already read it.
152 	 */
153 	if (fread(strings, 1, strtabsize - sizeof(int), f) !=
154 	    strtabsize - sizeof(int))
155 		badfmt("corrupted string table");
156 
157 	newtab = (struct nlist *)malloc(n);
158 	if (newtab == (struct nlist *)NULL)
159 		error(NULL);
160 
161 	i = n / sizeof(struct nlist);
162 	reorder(symtab, newtab, i);
163 	free((void *)symtab);
164 	symtab = newtab;
165 
166 	newstrings = malloc(strtabsize);
167 	if (newstrings == NULL)
168 		error(NULL);
169 	t = newstrings;
170 	for (symp = symtab; --i >= 0; symp++) {
171 		if (symp->n_un.n_strx == 0)
172 			continue;
173 		if (small && inlist(symp) < 0) continue;
174 		symp->n_un.n_strx -= sizeof(int);
175 		(void)strcpy(t, &strings[symp->n_un.n_strx]);
176 		symp->n_un.n_strx = (t - newstrings) + sizeof(int);
177 		t += strlen(t) + 1;
178 	}
179 
180 	/* update shrunk sizes */
181 	if(small) {
182 		strtabsize = t - newstrings + sizeof(int);
183 		n = symfound * sizeof(struct nlist);
184 		/* fix exec sym size */
185 		(void)lseek(o, 0, SEEK_SET);
186 		exec.a_syms = n;
187 		if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec))
188 			error(kfile);
189 	}
190 
191 	(void)lseek(o, sa, SEEK_SET);
192 	if (write(o, (void *)symtab, n) != n)
193 		error(kfile);
194 	if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int))
195 		error(kfile);
196 	if (write(o, newstrings, strtabsize - sizeof(int)) !=
197 	    strtabsize - sizeof(int))
198 		error(kfile);
199 
200 	if (small) ftruncate(o, lseek(o, 0, SEEK_CUR));
201 
202 	if ((i = nsym - symfound) > 0) {
203 		(void)printf("symorder: %d symbol%s not found:\n",
204 		    i, i == 1 ? "" : "s");
205 		for (i = 0; i < nsym; i++)
206 			if (order[i].n_value == 0)
207 				printf("%s\n", order[i].n_un.n_name);
208 		exit(NOTFOUNDEXIT);
209 	}
210 	exit(OKEXIT);
211 }
212 
reorder(st1,st2,entries)213 reorder(st1, st2, entries)
214 	register struct nlist *st1, *st2;
215 	int entries;
216 {
217 	register struct nlist *p;
218 	register int i, n;
219 
220 	for (p = st1, n = entries; --n >= 0; ++p)
221 		if (inlist(p) != -1)
222 			++symfound;
223 	for (p = st2 + symfound, n = entries; --n >= 0; ++st1) {
224 		i = inlist(st1);
225 		if (i == -1)
226 			*p++ = *st1;
227 		else
228 			st2[i] = *st1;
229 	}
230 }
231 
inlist(p)232 inlist(p)
233 	register struct nlist *p;
234 {
235 	register char *nam;
236 	register struct nlist *op;
237 
238 	if (p->n_type & N_STAB)
239 		return (-1);
240 	if (p->n_un.n_strx == 0)
241 		return (-1);
242 
243 	if (p->n_un.n_strx >= strtabsize)
244 		badfmt("corrupted symbol table");
245 
246 	nam = &strings[p->n_un.n_strx - sizeof(int)];
247 	for (op = &order[nsym]; --op >= order; ) {
248 		if (strcmp(op->n_un.n_name, nam) != 0)
249 			continue;
250 		op->n_value = 1;
251 		return (op - order);
252 	}
253 	return (-1);
254 }
255 
badfmt(why)256 badfmt(why)
257 	char *why;
258 {
259 	(void)fprintf(stderr,
260 	    "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE));
261 	exit(ERREXIT);
262 }
263 
error(n)264 error(n)
265 	char *n;
266 {
267 	int sverr;
268 
269 	sverr = errno;
270 	(void)fprintf(stderr, "symorder: ");
271 	if (n)
272 		(void)fprintf(stderr, "%s: ", n);
273 	(void)fprintf(stderr, "%s\n", strerror(sverr));
274 	exit(ERREXIT);
275 }
276 
usage()277 usage()
278 {
279 	(void)fprintf(stderr, "usage: symorder [-t] symlist file\n");
280 	exit(ERREXIT);
281 }
282