drm/i915: Update to Linux 4.2
[dragonfly.git] / usr.bin / symorder / symorder.c
blobe5499c598af7b81f0d5611ddfd11c32c3b8f7548
1 /*
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#) Copyright (c) 1980 The Regents of the University of California. All rights reserved.
30 * @(#)symorder.c 5.8 (Berkeley) 4/1/91
31 * $FreeBSD: src/usr.bin/symorder/symorder.c,v 1.15 1999/08/28 01:05:57 peter Exp $
35 * symorder - reorder symbol table
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <a.out.h>
41 #include <ctype.h>
42 #include <err.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <netinet/in.h>
51 #define SPACE 500
53 #define OKEXIT 0
54 #define NOTFOUNDEXIT 1
55 #define ERREXIT 2
57 char *exclude[SPACE];
58 struct nlist order[SPACE];
60 struct exec exec;
61 struct stat stb;
62 struct nlist *newtab, *symtab;
63 off_t sa;
64 int nexclude, nsym, strtabsize, symfound, symkept, small, missing, clean;
65 char *kfile, *newstrings, *strings, asym[BUFSIZ];
67 void badfmt(char *);
68 int excluded(struct nlist *);
69 int inlist(struct nlist *);
70 void reorder(struct nlist *, struct nlist *, int);
71 int savesymb(struct nlist *);
72 static void usage(void);
74 int
75 main(int argc, char **argv)
77 struct nlist *p, *symp;
78 FILE *f, *xfile;
79 int i;
80 char *start, *t, *xfilename;
81 int ch, n, o;
83 xfilename = NULL;
84 while ((ch = getopt(argc, argv, "cmtx:")) != -1)
85 switch(ch) {
86 case 'c':
87 clean = 1;
88 break;
89 case 'm':
90 missing = 1;
91 break;
92 case 't':
93 small = 1;
94 break;
95 case 'x':
96 if (xfilename != NULL)
97 usage();
98 xfilename = optarg;
99 break;
100 case '?':
101 default:
102 usage();
104 argc -= optind;
105 argv += optind;
107 if (argc != 2)
108 usage();
110 if ((f = fopen(argv[0], "r")) == NULL)
111 err(ERREXIT, "%s", argv[0]);
113 for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
114 for (t = asym; isspace(*t); ++t);
115 if (!*(start = t))
116 continue;
117 while (*++t);
118 if (*--t == '\n')
119 *t = '\0';
120 p->n_un.n_name = strdup(start);
121 ++p;
122 if (++nsym >= sizeof order / sizeof order[0])
123 break;
125 (void)fclose(f);
127 if (xfilename != NULL) {
128 if ((xfile = fopen(xfilename, "r")) == NULL)
129 err(ERREXIT, "%s", xfilename);
130 for (; fgets(asym, sizeof(asym), xfile) != NULL;) {
131 for (t = asym; isspace(*t); ++t);
132 if (!*(start = t))
133 continue;
134 while (*++t);
135 if (*--t == '\n')
136 *t = '\0';
137 exclude[nexclude] = strdup(start);
138 if (++nexclude >= sizeof exclude / sizeof exclude[0])
139 break;
141 (void)fclose(xfile);
144 kfile = argv[1];
145 if ((f = fopen(kfile, "r")) == NULL)
146 err(ERREXIT, "%s", kfile);
147 if ((o = open(kfile, O_WRONLY)) < 0)
148 err(ERREXIT, "%s", kfile);
150 /* read exec header */
151 if ((fread(&exec, sizeof(exec), 1, f)) != 1)
152 badfmt("no exec header");
153 if (N_BADMAG(exec))
154 badfmt("bad magic number");
155 if (exec.a_syms == 0)
156 badfmt("stripped");
157 (void)fstat(fileno(f), &stb);
158 if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
159 badfmt("no string table");
161 /* seek to and read the symbol table */
162 sa = N_SYMOFF(exec);
163 (void)fseek(f, sa, SEEK_SET);
164 n = exec.a_syms;
165 if (!(symtab = (struct nlist *)malloc(n)))
166 err(ERREXIT, NULL);
167 if (fread((void *)symtab, 1, n, f) != n)
168 badfmt("corrupted symbol table");
170 /* read string table size and string table */
171 if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 ||
172 strtabsize <= 0)
173 badfmt("corrupted string table");
174 strings = malloc(strtabsize);
175 if (strings == NULL)
176 err(ERREXIT, NULL);
178 * Subtract four from strtabsize since strtabsize includes itself,
179 * and we've already read it.
181 if (fread(strings, 1, strtabsize - sizeof(int), f) !=
182 strtabsize - sizeof(int))
183 badfmt("corrupted string table");
185 i = n / sizeof(struct nlist);
186 if (!clean) {
187 newtab = (struct nlist *)malloc(n);
188 if (newtab == NULL)
189 err(ERREXIT, NULL);
190 memset(newtab, 0, n);
192 reorder(symtab, newtab, i);
193 free((void *)symtab);
194 symtab = newtab;
195 } else {
196 symkept = i;
199 newstrings = malloc(strtabsize);
200 if (newstrings == NULL)
201 err(ERREXIT, NULL);
202 t = newstrings;
203 for (symp = symtab; --i >= 0; symp++) {
204 if (symp->n_un.n_strx == 0)
205 continue;
206 if (inlist(symp) < 0) {
207 if (small)
208 continue;
209 if (clean && !savesymb(symp))
210 symp->n_type &= ~N_EXT;
211 } else if (clean)
212 symfound++;
213 symp->n_un.n_strx -= sizeof(int);
214 (void)strcpy(t, &strings[symp->n_un.n_strx]);
215 symp->n_un.n_strx = (t - newstrings) + sizeof(int);
216 t += strlen(t) + 1;
219 /* update shrunk sizes */
220 strtabsize = t - newstrings + sizeof(int);
221 n = symkept * sizeof(struct nlist);
223 /* fix exec sym size */
224 (void)lseek(o, (off_t)0, SEEK_SET);
225 exec.a_syms = n;
226 if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec))
227 err(ERREXIT, "%s", kfile);
229 (void)lseek(o, sa, SEEK_SET);
230 if (write(o, (void *)symtab, n) != n)
231 err(ERREXIT, "%s", kfile);
232 if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int))
233 err(ERREXIT, "%s", kfile);
234 if (write(o, newstrings, strtabsize - sizeof(int)) !=
235 strtabsize - sizeof(int))
236 err(ERREXIT, "%s", kfile);
238 ftruncate(o, lseek(o, (off_t)0, SEEK_CUR));
240 if ((i = nsym - symfound) > 0) {
241 (void)printf("symorder: %d symbol%s not found:\n",
242 i, i == 1 ? "" : "s");
243 for (i = 0; i < nsym; i++)
244 if (order[i].n_value == 0)
245 printf("%s\n", order[i].n_un.n_name);
246 if (!missing)
247 exit(NOTFOUNDEXIT);
249 exit(OKEXIT);
253 savesymb(struct nlist *s)
255 if ((s->n_type & N_EXT) != N_EXT)
256 return 0;
257 switch (s->n_type & N_TYPE) {
258 case N_TEXT:
259 case N_DATA:
260 return 0;
261 default:
262 return 1;
266 void
267 reorder(struct nlist *st1, struct nlist *st2, int entries)
269 struct nlist *p;
270 int i, n;
272 for (p = st1, n = entries; --n >= 0; ++p)
273 if (inlist(p) != -1)
274 ++symfound;
275 for (p = st2 + symfound, n = entries; --n >= 0; ++st1) {
276 if (excluded(st1))
277 continue;
278 i = inlist(st1);
279 if (i == -1)
280 *p++ = *st1;
281 else
282 st2[i] = *st1;
283 ++symkept;
288 inlist(struct nlist *p)
290 char *nam;
291 struct nlist *op;
293 if (p->n_type & N_STAB || p->n_un.n_strx == 0)
294 return (-1);
295 if (p->n_un.n_strx < sizeof(int) || p->n_un.n_strx >= strtabsize)
296 badfmt("corrupted symbol table");
297 nam = &strings[p->n_un.n_strx - sizeof(int)];
298 for (op = &order[nsym]; --op >= order; ) {
299 if (strcmp(op->n_un.n_name, nam) != 0)
300 continue;
301 op->n_value = 1;
302 return (op - order);
304 return (-1);
308 excluded(struct nlist *p)
310 char *nam;
311 int x;
313 if (p->n_type & N_STAB || p->n_un.n_strx == 0)
314 return (0);
315 if (p->n_un.n_strx < sizeof(int) || p->n_un.n_strx >= strtabsize)
316 badfmt("corrupted symbol table");
317 nam = &strings[p->n_un.n_strx - sizeof(int)];
318 for (x = nexclude; --x >= 0; )
319 if (strcmp(nam, exclude[x]) == 0)
320 return (1);
321 return (0);
324 void
325 badfmt(char *why)
327 errx(ERREXIT, "%s: %s: %s", kfile, why, strerror(EFTYPE));
330 static void
331 usage(void)
333 (void)fprintf(stderr,
334 "usage: symorder [-c] [-m] [-t] [-x excludelist] symlist file\n");
335 exit(ERREXIT);