xref: /csrg-svn/old/symorder/symorder.c (revision 21578)
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.1 (Berkeley) 05/31/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 	if (fread(strings, 1, symsize, f) != symsize) {
110 		fprintf(stderr, "symorder: Truncated strings ");
111 		perror(argv[2]);
112 		exit(1);
113 	}
114 
115 	newtab = (struct nlist *)malloc(n);
116 	if (newtab == (struct nlist *)0) {
117 		fprintf(stderr,
118 		    "symorder: Out of core, no space for new symtab\n");
119 		exit(1);
120 	}
121 	i = n / sizeof (struct nlist);
122 	reorder(symtab, newtab, i);
123 	free((char *)symtab);
124 	symtab = newtab;
125 
126 	newstrings = malloc(symsize);
127 	if (newstrings == (char *)0) {
128 		fprintf(stderr,
129 		    "symorder: Out of core, no space for newstrings\n");
130 		exit(1);
131 	}
132 	ns = newstrings;
133 	for (symp = symtab; --i >= 0; symp++) {
134 		if (symp->n_un.n_strx == 0)
135 			continue;
136 		symp->n_un.n_strx -= sizeof (int);
137 		if ((unsigned)symp->n_un.n_strx >= symsize) {
138 			fprintf(stderr,"symorder: Corrupted string pointers\n");
139 			exit(1);
140 		}
141 		strcpy(ns, &strings[symp->n_un.n_strx]);
142 		symp->n_un.n_strx = (ns - newstrings) + sizeof (int);
143 		ns = index(ns, 0) + 1;
144 		if (ns > &newstrings[symsize]) {
145 			fprintf(stderr, "symorder: Strings grew longer!\n");
146 			exit(1);
147 		}
148 	}
149 
150 	lseek(o, sa, 0);
151 	if (write(o, (char *)symtab, n) != n) {
152 		fprintf(stderr, "symorder: Write failed "); perror(argv[2]);
153 		exit(1);
154 	}
155 	if (write(o, (char *)&symsize, sizeof (int)) != sizeof (int)) {
156 		fprintf(stderr, "symorder: Write failed "); perror(argv[2]);
157 		exit(1);
158 	}
159 	if (write(o, newstrings, symsize) != symsize) {
160 		fprintf(stderr, "symorder: Write failed "); perror(argv[2]);
161 		exit(1);
162 	}
163 	if ((i = nsym - symfound) > 0) {
164 		fprintf(stderr, "symorder: %d symbol%s not found:\n",
165 		    i, i == 1 ? "" : "s");
166 		for (i = 0; i < nsym; i++) {
167 			if (order[i].n_value == 0)
168 				printf("%s\n", order[i].n_un.n_name);
169 		}
170 	}
171 	exit(0);
172 }
173 
174 reorder(st1, st2, n)
175 	register struct nlist *st1, *st2;
176 	register n;
177 {
178 	register struct nlist *stp = st2 + nsym;
179 	register i;
180 
181 	while (--n >= 0) {
182 		i = inlist(st1);
183 		if (i == -1)
184 			*stp++ = *st1++;
185 		else
186 			st2[i] = *st1++;
187 	}
188 }
189 
190 inlist(p)
191 	register struct nlist *p;
192 {
193 	register char *nam;
194 	register struct nlist *op;
195 
196 	if (p->n_type & N_STAB)
197 		return (-1);
198 	if (p->n_un.n_strx == 0)
199 		return (-1);
200 
201 	nam = &strings[p->n_un.n_strx - sizeof(int)];
202 	if (nam >= &strings[symsize]) {
203 		fprintf(stderr, "symorder: corrupt symtab\n");
204 		exit(1);
205 	}
206 
207 	for (op = &order[nsym]; --op >= order; ) {
208 		if (strcmp(op->n_un.n_name, nam) != 0)
209 			continue;
210 		if (op->n_value == 0) {
211 			op->n_value++;
212 			symfound++;
213 		}
214 		return (op - order);
215 	}
216 	return (-1);
217 }
218 
219 #define	NSAVETAB	4096
220 char	*savetab;
221 int	saveleft;
222 
223 char *
224 savestr(cp)
225 	register char *cp;
226 {
227 	register int len;
228 
229 	len = strlen(cp) + 1;
230 	if (len > saveleft) {
231 		saveleft = NSAVETAB;
232 		if (len > saveleft)
233 			saveleft = len;
234 		savetab = (char *)malloc(saveleft);
235 		if (savetab == 0) {
236 			fprintf(stderr,
237 			    "symorder: ran out of memory (savestr)\n");
238 			exit(1);
239 		}
240 	}
241 	strncpy(savetab, cp, len);
242 	cp = savetab;
243 	savetab += len;
244 	saveleft -= len;
245 	return (cp);
246 }
247