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