xref: /original-bsd/old/symorder/symorder.c (revision 5ab5bc28)
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 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)symorder.c	5.3 (Berkeley) 11/01/88";
26 #endif /* not lint */
27 
28 /*
29  * symorder - reorder symbol table
30  */
31 
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <a.out.h>
36 
37 #define SPACE 100
38 
39 struct	nlist order[SPACE];
40 
41 char	*savestr(), *index(), *malloc();
42 struct	exec exec;
43 off_t	sa;
44 struct	stat stb;
45 int	nsym = 0;
46 int	symfound = 0;
47 char	*strings;
48 char	*newstrings;
49 struct	nlist *symtab;
50 struct	nlist *newtab;
51 int	symsize;
52 char	asym[BUFSIZ];
53 
54 main(argc, argv)
55 	char **argv;
56 {
57 	register char *ns;
58 	register struct nlist *symp;
59 	register struct nlist *p;
60 	register FILE *f;
61 	register int i;
62 	int n, o;
63 
64 	if (argc != 3) {
65 		fprintf(stderr, "Usage: symorder orderlist file\n");
66 		exit(1);
67 	}
68 	if ((f = fopen(argv[1], "r")) == NULL) {
69 		perror(argv[1]);
70 		exit(1);
71 	}
72 	for (p = order; fgets(asym, sizeof asym, f) != NULL; p++, nsym++) {
73 		for (i = 0; asym[i] && asym[i] != '\n'; i++)
74 			continue;
75 		if (asym[i] == '\n')
76 			asym[i] = 0;
77 		p->n_un.n_name = savestr(asym);
78 	}
79 	fclose(f);
80 	if ((f = fopen(argv[2], "r")) == NULL)
81 		perror(argv[2]), exit(1);
82 	if ((o = open(argv[2], 1)) < 0)
83 		perror(argv[2]), exit(1);
84 	if ((fread(&exec, sizeof exec, 1, f)) != 1 || N_BADMAG(exec)) {
85 		fprintf(stderr, "symorder: %s: bad format\n", argv[2]);
86 		exit(1);
87 	}
88 	if (exec.a_syms == 0) {
89 		fprintf(stderr, "symorder: %s is stripped\n", argv[2]);
90 		exit(1);
91 	}
92 	fstat(fileno(f), &stb);
93 	if (stb.st_size < N_STROFF(exec)+sizeof(off_t)) {
94 		fprintf(stderr, "symorder: %s is in old format or truncated\n",
95 		    argv[2]);
96 		exit(1);
97 	}
98 	sa = N_SYMOFF(exec);
99 	fseek(f, sa, 0);
100 	n = exec.a_syms;
101 	symtab = (struct nlist *)malloc(n);
102 	if (symtab == (struct nlist *)0) {
103 		fprintf(stderr, "symorder: Out of core, no space for symtab\n");
104 		exit(1);
105 	}
106 	if (fread((char *)symtab, 1, n, f) != n) {
107 		fprintf(stderr, "symorder: Short file "); perror(argv[2]);
108 		exit(1);
109 	}
110 	if (fread((char *)&symsize, sizeof (int), 1, f) != 1 ||
111 	    symsize <= 0) {
112 		fprintf(stderr, "symorder: No strings "); perror(argv[2]);
113 		exit(1);
114 	}
115 	strings = malloc(symsize);
116 	if (strings == (char *)0) {
117 		fprintf(stderr,"symorder: Out of core, no space for strings\n");
118 		exit(1);
119 	}
120 	/*
121 	 * Need to subtract four from symsize here since
122 	 * symsize includes itself, and we've already read
123 	 * it.  (6/30/85 chris@maryland)
124 	 */
125 	if (fread(strings, 1, symsize - 4, f) != symsize - 4) {
126 		fprintf(stderr, "symorder: Truncated strings ");
127 		perror(argv[2]);
128 		exit(1);
129 	}
130 
131 	newtab = (struct nlist *)malloc(n);
132 	if (newtab == (struct nlist *)0) {
133 		fprintf(stderr,
134 		    "symorder: Out of core, no space for new symtab\n");
135 		exit(1);
136 	}
137 	i = n / sizeof (struct nlist);
138 	reorder(symtab, newtab, i);
139 	free((char *)symtab);
140 	symtab = newtab;
141 
142 	newstrings = malloc(symsize);
143 	if (newstrings == (char *)0) {
144 		fprintf(stderr,
145 		    "symorder: Out of core, no space for newstrings\n");
146 		exit(1);
147 	}
148 	ns = newstrings;
149 	for (symp = symtab; --i >= 0; symp++) {
150 		if (symp->n_un.n_strx == 0)
151 			continue;
152 		symp->n_un.n_strx -= sizeof (int);
153 		if ((unsigned)symp->n_un.n_strx >= symsize) {
154 			fprintf(stderr,"symorder: Corrupted string pointers\n");
155 			exit(1);
156 		}
157 		strcpy(ns, &strings[symp->n_un.n_strx]);
158 		symp->n_un.n_strx = (ns - newstrings) + sizeof (int);
159 		ns = index(ns, 0) + 1;
160 		if (ns > &newstrings[symsize]) {
161 			fprintf(stderr, "symorder: Strings grew longer!\n");
162 			exit(1);
163 		}
164 	}
165 
166 	lseek(o, sa, 0);
167 	if (write(o, (char *)symtab, n) != n) {
168 		fprintf(stderr, "symorder: Write failed "); perror(argv[2]);
169 		exit(1);
170 	}
171 	if (write(o, (char *)&symsize, sizeof (int)) != sizeof (int)) {
172 		fprintf(stderr, "symorder: Write failed "); perror(argv[2]);
173 		exit(1);
174 	}
175 	if (write(o, newstrings, symsize - 4) != symsize - 4) {
176 		fprintf(stderr, "symorder: Write failed "); perror(argv[2]);
177 		exit(1);
178 	}
179 	if ((i = nsym - symfound) > 0) {
180 		fprintf(stderr, "symorder: %d symbol%s not found:\n",
181 		    i, i == 1 ? "" : "s");
182 		for (i = 0; i < nsym; i++) {
183 			if (order[i].n_value == 0)
184 				printf("%s\n", order[i].n_un.n_name);
185 		}
186 	}
187 	exit(0);
188 }
189 
190 reorder(st1, st2, n)
191 	register struct nlist *st1, *st2;
192 	register n;
193 {
194 	register struct nlist *stp = st2 + nsym;
195 	register i;
196 
197 	while (--n >= 0) {
198 		i = inlist(st1);
199 		if (i == -1)
200 			*stp++ = *st1++;
201 		else
202 			st2[i] = *st1++;
203 	}
204 }
205 
206 inlist(p)
207 	register struct nlist *p;
208 {
209 	register char *nam;
210 	register struct nlist *op;
211 
212 	if (p->n_type & N_STAB)
213 		return (-1);
214 	if (p->n_un.n_strx == 0)
215 		return (-1);
216 
217 	nam = &strings[p->n_un.n_strx - sizeof(int)];
218 	if (nam >= &strings[symsize]) {
219 		fprintf(stderr, "symorder: corrupt symtab\n");
220 		exit(1);
221 	}
222 
223 	for (op = &order[nsym]; --op >= order; ) {
224 		if (strcmp(op->n_un.n_name, nam) != 0)
225 			continue;
226 		if (op->n_value == 0) {
227 			op->n_value++;
228 			symfound++;
229 		}
230 		return (op - order);
231 	}
232 	return (-1);
233 }
234 
235 #define	NSAVETAB	4096
236 char	*savetab;
237 int	saveleft;
238 
239 char *
240 savestr(cp)
241 	register char *cp;
242 {
243 	register int len;
244 
245 	len = strlen(cp) + 1;
246 	if (len > saveleft) {
247 		saveleft = NSAVETAB;
248 		if (len > saveleft)
249 			saveleft = len;
250 		savetab = (char *)malloc(saveleft);
251 		if (savetab == 0) {
252 			fprintf(stderr,
253 			    "symorder: ran out of memory (savestr)\n");
254 			exit(1);
255 		}
256 	}
257 	strncpy(savetab, cp, len);
258 	cp = savetab;
259 	savetab += len;
260 	saveleft -= len;
261 	return (cp);
262 }
263