xref: /csrg-svn/old/symorder/symorder.c (revision 47684)
1 /*
2  * Copyright (c) 1980 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)symorder.c	5.7 (Berkeley) 03/29/91";
16 #endif /* not lint */
17 
18 /*
19  * symorder - reorder symbol table
20  */
21 
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <a.out.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #define SPACE		500
33 
34 #define	OKEXIT		0
35 #define	NOTFOUNDEXIT	1
36 #define	ERREXIT		2
37 
38 struct	nlist order[SPACE];
39 
40 struct	exec exec;
41 struct	stat stb;
42 struct	nlist *newtab, *symtab;
43 off_t	sa;
44 int	nsym, strtabsize, symfound, small;
45 char	*kfile, *newstrings, *strings, asym[BUFSIZ];
46 
47 main(argc, argv)
48 	int argc;
49 	char **argv;
50 {
51 	register struct nlist *p, *symp;
52 	register FILE *f;
53 	register int i;
54 	register char *start, *t;
55 	int n, o;
56 
57 	if (argc != 3 && argc != 4) {
58 		(void)fprintf(stderr, "usage: symorder [-T] orderlist file\n");
59 		exit(ERREXIT);
60 	}
61 	if (argc == 4 && strcmp(argv[1],"-T") == 0) {
62 		argv++;
63 		small++;
64 	}
65 	if ((f = fopen(argv[1], "r")) == NULL)
66 		error(argv[1]);
67 
68 	for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
69 		for (t = asym; isspace(*t); ++t);
70 		if (!*(start = t))
71 			continue;
72 		while (*++t);
73 		if (*--t == '\n')
74 			*t = '\0';
75 		p->n_un.n_name = strdup(start);
76 		++p;
77 		++nsym;
78 	}
79 	(void)fclose(f);
80 
81 	kfile = argv[2];
82 	if ((f = fopen(kfile, "r")) == NULL)
83 		error(kfile);
84 	if ((o = open(kfile, O_WRONLY)) < 0)
85 		error(kfile);
86 
87 	/* read exec header */
88 	if ((fread(&exec, sizeof(exec), 1, f)) != 1)
89 		badfmt("no exec header");
90 	if (N_BADMAG(exec))
91 		badfmt("bad magic number");
92 	if (exec.a_syms == 0)
93 		badfmt("stripped");
94 	(void)fstat(fileno(f), &stb);
95 	if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
96 		badfmt("no string table");
97 
98 	/* seek to and read the symbol table */
99 	sa = N_SYMOFF(exec);
100 	(void)fseek(f, sa, SEEK_SET);
101 	n = exec.a_syms;
102 	if (!(symtab = (struct nlist *)malloc(n)))
103 		error((char *)NULL);
104 	if (fread((char *)symtab, 1, n, f) != n)
105 		badfmt("corrupted symbol table");
106 
107 	/* read string table size and string table */
108 	if (fread((char *)&strtabsize, sizeof(int), 1, f) != 1 ||
109 	    strtabsize <= 0)
110 		badfmt("corrupted string table");
111 	strings = malloc(strtabsize);
112 	if (strings == (char *)NULL)
113 		error((char *)NULL);
114 	/*
115 	 * Subtract four from strtabsize since strtabsize includes itself,
116 	 * and we've already read it.
117 	 */
118 	if (fread(strings, 1, strtabsize - sizeof(int), f) !=
119 	    strtabsize - sizeof(int))
120 		badfmt("corrupted string table");
121 
122 	newtab = (struct nlist *)malloc(n);
123 	if (newtab == (struct nlist *)NULL)
124 		error((char *)NULL);
125 
126 	i = n / sizeof(struct nlist);
127 	reorder(symtab, newtab, i);
128 	free((char *)symtab);
129 	symtab = newtab;
130 
131 	newstrings = malloc(strtabsize);
132 	if (newstrings == (char *)NULL)
133 		error((char *)NULL);
134 	t = newstrings;
135 	for (symp = symtab; --i >= 0; symp++) {
136 		if (symp->n_un.n_strx == 0)
137 			continue;
138 		if (small && inlist(symp) < 0) continue;
139 		symp->n_un.n_strx -= sizeof(int);
140 		(void)strcpy(t, &strings[symp->n_un.n_strx]);
141 		symp->n_un.n_strx = (t - newstrings) + sizeof(int);
142 		t += strlen(t) + 1;
143 	}
144 
145 	/* update shrunk sizes */
146 	if(small) {
147 		strtabsize = t - newstrings + sizeof(int);
148 		n = symfound * sizeof(struct nlist);
149 		/* fix exec sym size */
150 		(void)lseek(o, 0, SEEK_SET);
151 		exec.a_syms = n;
152 		if (write(o, (char *)&exec, sizeof(exec)) != sizeof(exec))
153 			error(kfile);
154 	}
155 
156 	(void)lseek(o, sa, SEEK_SET);
157 	if (write(o, (char *)symtab, n) != n)
158 		error(kfile);
159 	if (write(o, (char *)&strtabsize, sizeof(int)) != sizeof(int))
160 		error(kfile);
161 	if (write(o, newstrings, strtabsize - sizeof(int)) !=
162 	    strtabsize - sizeof(int))
163 		error(kfile);
164 
165 	if (small) ftruncate(o, lseek(o, 0, SEEK_CUR));
166 
167 	if ((i = nsym - symfound) > 0) {
168 		(void)printf("symorder: %d symbol%s not found:\n",
169 		    i, i == 1 ? "" : "s");
170 		for (i = 0; i < nsym; i++)
171 			if (order[i].n_value == 0)
172 				printf("%s\n", order[i].n_un.n_name);
173 		exit(NOTFOUNDEXIT);
174 	}
175 	exit(OKEXIT);
176 }
177 
178 reorder(st1, st2, entries)
179 	register struct nlist *st1, *st2;
180 	int entries;
181 {
182 	register struct nlist *p;
183 	register int i, n;
184 
185 	for (p = st1, n = entries; --n >= 0; ++p)
186 		if (inlist(p) != -1)
187 			++symfound;
188 	for (p = st2 + symfound, n = entries; --n >= 0; ++st1) {
189 		i = inlist(st1);
190 		if (i == -1)
191 			*p++ = *st1;
192 		else
193 			st2[i] = *st1;
194 	}
195 }
196 
197 inlist(p)
198 	register struct nlist *p;
199 {
200 	register char *nam;
201 	register struct nlist *op;
202 
203 	if (p->n_type & N_STAB)
204 		return (-1);
205 	if (p->n_un.n_strx == 0)
206 		return (-1);
207 
208 	if (p->n_un.n_strx >= strtabsize)
209 		badfmt("corrupted symbol table");
210 
211 	nam = &strings[p->n_un.n_strx - sizeof(int)];
212 	for (op = &order[nsym]; --op >= order; ) {
213 		if (strcmp(op->n_un.n_name, nam) != 0)
214 			continue;
215 		op->n_value = 1;
216 		return (op - order);
217 	}
218 	return (-1);
219 }
220 
221 badfmt(why)
222 	char *why;
223 {
224 	(void)fprintf(stderr,
225 	    "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE));
226 	exit(ERREXIT);
227 }
228 
229 error(n)
230 	char *n;
231 {
232 	int sverr;
233 
234 	sverr = errno;
235 	(void)fprintf(stderr, "symorder: ");
236 	if (n)
237 		(void)fprintf(stderr, "%s: ", n);
238 	(void)fprintf(stderr, "%s\n", strerror(sverr));
239 	exit(ERREXIT);
240 }
241