]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/symorder/symorder.c
This commit was generated by cvs2svn to compensate for changes in r68325,
[FreeBSD/FreeBSD.git] / usr.bin / symorder / symorder.c
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 const 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 #if 0
42 static char sccsid[] = "@(#)symorder.c  5.8 (Berkeley) 4/1/91";
43 #endif
44 static const char rcsid[] =
45   "$FreeBSD$";
46 #endif /* not lint */
47
48 /*
49  * symorder - reorder symbol table
50  */
51
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <a.out.h>
55 #include <ctype.h>
56 #include <err.h>
57 #include <errno.h>
58 #include <fcntl.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63
64 #define SPACE           500
65
66 #define OKEXIT          0
67 #define NOTFOUNDEXIT    1
68 #define ERREXIT         2
69
70 char    *exclude[SPACE];
71 struct  nlist order[SPACE];
72
73 struct  exec exec;
74 struct  stat stb;
75 struct  nlist *newtab, *symtab;
76 off_t   sa;
77 int     nexclude, nsym, strtabsize, symfound, symkept, small, missing, clean;
78 char    *kfile, *newstrings, *strings, asym[BUFSIZ];
79
80 void badfmt __P((char *));
81 int excluded __P((struct nlist *));
82 int inlist __P((struct nlist *));
83 void reorder __P((struct nlist *, struct nlist *, int));
84 int savesymb __P((struct nlist *));
85 static void usage __P((void));
86
87 int
88 main(argc, argv)
89         int argc;
90         char **argv;
91 {
92         register struct nlist *p, *symp;
93         register FILE *f, *xfile;
94         register int i;
95         register char *start, *t, *xfilename;
96         int ch, n, o;
97
98         xfilename = NULL;
99         while ((ch = getopt(argc, argv, "cmtx:")) != -1)
100                 switch(ch) {
101                 case 'c':
102                         clean = 1;
103                         break;
104                 case 'm':
105                         missing = 1;
106                         break;
107                 case 't':
108                         small = 1;
109                         break;
110                 case 'x':
111                         if (xfilename != NULL)
112                                 usage();
113                         xfilename = optarg;
114                         break;
115                 case '?':
116                 default:
117                         usage();
118                 }
119         argc -= optind;
120         argv += optind;
121
122         if (argc != 2)
123                 usage();
124
125         if ((f = fopen(argv[0], "r")) == NULL)
126                 err(ERREXIT, "%s", argv[0]);
127
128         for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
129                 for (t = asym; isspace(*t); ++t);
130                 if (!*(start = t))
131                         continue;
132                 while (*++t);
133                 if (*--t == '\n')
134                         *t = '\0';
135                 p->n_un.n_name = strdup(start);
136                 ++p;
137                 if (++nsym >= sizeof order / sizeof order[0])
138                         break;
139         }
140         (void)fclose(f);
141
142         if (xfilename != NULL) {
143                 if ((xfile = fopen(xfilename, "r")) == NULL)
144                         err(ERREXIT, "%s", xfilename);
145                 for (; fgets(asym, sizeof(asym), xfile) != NULL;) {
146                         for (t = asym; isspace(*t); ++t);
147                         if (!*(start = t))
148                                 continue;
149                         while (*++t);
150                         if (*--t == '\n')
151                                 *t = '\0';
152                         exclude[nexclude] = strdup(start);
153                         if (++nexclude >= sizeof exclude / sizeof exclude[0])
154                                 break;
155                 }
156                 (void)fclose(xfile);
157         }
158
159         kfile = argv[1];
160         if ((f = fopen(kfile, "r")) == NULL)
161                 err(ERREXIT, "%s", kfile);
162         if ((o = open(kfile, O_WRONLY)) < 0)
163                 err(ERREXIT, "%s", kfile);
164
165         /* read exec header */
166         if ((fread(&exec, sizeof(exec), 1, f)) != 1)
167                 badfmt("no exec header");
168         if (N_BADMAG(exec))
169                 badfmt("bad magic number");
170         if (exec.a_syms == 0)
171                 badfmt("stripped");
172         (void)fstat(fileno(f), &stb);
173         if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
174                 badfmt("no string table");
175
176         /* seek to and read the symbol table */
177         sa = N_SYMOFF(exec);
178         (void)fseek(f, sa, SEEK_SET);
179         n = exec.a_syms;
180         if (!(symtab = (struct nlist *)malloc(n)))
181                 err(ERREXIT, NULL);
182         if (fread((void *)symtab, 1, n, f) != n)
183                 badfmt("corrupted symbol table");
184
185         /* read string table size and string table */
186         if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 ||
187             strtabsize <= 0)
188                 badfmt("corrupted string table");
189         strings = malloc(strtabsize);
190         if (strings == NULL)
191                 err(ERREXIT, NULL);
192         /*
193          * Subtract four from strtabsize since strtabsize includes itself,
194          * and we've already read it.
195          */
196         if (fread(strings, 1, strtabsize - sizeof(int), f) !=
197             strtabsize - sizeof(int))
198                 badfmt("corrupted string table");
199
200         i = n / sizeof(struct nlist);
201         if (!clean) {
202                 newtab = (struct nlist *)malloc(n);
203                 if (newtab == (struct nlist *)NULL)
204                         err(ERREXIT, NULL);
205                 memset(newtab, 0, n);
206
207                 reorder(symtab, newtab, i);
208                 free((void *)symtab);
209                 symtab = newtab;
210         } else {
211                 symkept = i;
212         }
213
214         newstrings = malloc(strtabsize);
215         if (newstrings == NULL)
216                 err(ERREXIT, NULL);
217         t = newstrings;
218         for (symp = symtab; --i >= 0; symp++) {
219                 if (symp->n_un.n_strx == 0)
220                         continue;
221                 if (inlist(symp) < 0) {
222                         if (small)
223                                 continue;
224                         if (clean && !savesymb(symp))
225                                 symp->n_type &= ~N_EXT;
226                 } else if (clean)
227                         symfound++;
228                 symp->n_un.n_strx -= sizeof(int);
229                 (void)strcpy(t, &strings[symp->n_un.n_strx]);
230                 symp->n_un.n_strx = (t - newstrings) + sizeof(int);
231                 t += strlen(t) + 1;
232         }
233
234         /* update shrunk sizes */
235         strtabsize = t - newstrings + sizeof(int);
236         n = symkept * sizeof(struct nlist);
237
238         /* fix exec sym size */
239         (void)lseek(o, (off_t)0, SEEK_SET);
240         exec.a_syms = n;
241         if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec))
242                 err(ERREXIT, "%s", kfile);
243
244         (void)lseek(o, sa, SEEK_SET);
245         if (write(o, (void *)symtab, n) != n)
246                 err(ERREXIT, "%s", kfile);
247         if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int))
248                 err(ERREXIT, "%s", kfile);
249         if (write(o, newstrings, strtabsize - sizeof(int)) !=
250             strtabsize - sizeof(int))
251                 err(ERREXIT, "%s", kfile);
252
253         ftruncate(o, lseek(o, (off_t)0, SEEK_CUR));
254
255         if ((i = nsym - symfound) > 0) {
256                 (void)printf("symorder: %d symbol%s not found:\n",
257                     i, i == 1 ? "" : "s");
258                 for (i = 0; i < nsym; i++)
259                         if (order[i].n_value == 0)
260                                 printf("%s\n", order[i].n_un.n_name);
261                 if (!missing)
262                         exit(NOTFOUNDEXIT);
263         }
264         exit(OKEXIT);
265 }
266
267 int
268 savesymb(s)
269         register struct nlist *s;
270 {
271         if ((s->n_type & N_EXT) != N_EXT)
272                 return 0;
273         switch (s->n_type & N_TYPE) {
274                 case N_TEXT:
275                 case N_DATA:    
276                         return 0;
277                 default:        
278                         return 1;
279         }
280 }
281
282 void
283 reorder(st1, st2, entries)
284         register struct nlist *st1, *st2;
285         int entries;
286 {
287         register struct nlist *p;
288         register int i, n;
289
290         for (p = st1, n = entries; --n >= 0; ++p)
291                 if (inlist(p) != -1)
292                         ++symfound;
293         for (p = st2 + symfound, n = entries; --n >= 0; ++st1) {
294                 if (excluded(st1))
295                         continue;
296                 i = inlist(st1);
297                 if (i == -1)
298                         *p++ = *st1;
299                 else
300                         st2[i] = *st1;
301                 ++symkept;
302         }
303 }
304
305 int
306 inlist(p)
307         register struct nlist *p;
308 {
309         register char *nam;
310         register struct nlist *op;
311
312         if (p->n_type & N_STAB || p->n_un.n_strx == 0)
313                 return (-1);
314         if (p->n_un.n_strx < sizeof(int) || p->n_un.n_strx >= strtabsize)
315                 badfmt("corrupted symbol table");
316         nam = &strings[p->n_un.n_strx - sizeof(int)];
317         for (op = &order[nsym]; --op >= order; ) {
318                 if (strcmp(op->n_un.n_name, nam) != 0)
319                         continue;
320                 op->n_value = 1;
321                 return (op - order);
322         }
323         return (-1);
324 }
325
326 int
327 excluded(p)
328         register struct nlist *p;
329 {
330         register char *nam;
331         register int x;
332
333         if (p->n_type & N_STAB || p->n_un.n_strx == 0)
334                 return (0);
335         if (p->n_un.n_strx < sizeof(int) || p->n_un.n_strx >= strtabsize)
336                 badfmt("corrupted symbol table");
337         nam = &strings[p->n_un.n_strx - sizeof(int)];
338         for (x = nexclude; --x >= 0; )
339                 if (strcmp(nam, exclude[x]) == 0)
340                         return (1);
341         return (0);
342 }
343
344 void
345 badfmt(why)
346         char *why;
347 {
348         errx(ERREXIT, "%s: %s: %s", kfile, why, strerror(EFTYPE));
349 }
350
351 static void
352 usage()
353 {
354         (void)fprintf(stderr,
355             "usage: symorder [-c] [-m] [-t] [-x excludelist] symlist file\n");
356         exit(ERREXIT);
357 }