Commit | Line | Data |
---|---|---|
22e155fc | 1 | /* |
1c3a0cca KB |
2 | * Copyright (c) 1980 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
6ecf3d85 | 5 | * %sccs.include.redist.c% |
22e155fc DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
1c3a0cca | 10 | "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ |
22e155fc | 11 | All rights reserved.\n"; |
1c3a0cca | 12 | #endif /* not lint */ |
22e155fc | 13 | |
34aa0635 | 14 | #ifndef lint |
801207e8 | 15 | static char sccsid[] = "@(#)symorder.c 5.8 (Berkeley) %G%"; |
1c3a0cca | 16 | #endif /* not lint */ |
45991748 | 17 | |
faa0bd68 BJ |
18 | /* |
19 | * symorder - reorder symbol table | |
20 | */ | |
45991748 | 21 | |
faa0bd68 | 22 | #include <sys/types.h> |
840fc587 | 23 | #include <sys/stat.h> |
a5ba81e5 KB |
24 | #include <fcntl.h> |
25 | #include <errno.h> | |
13257757 | 26 | #include <a.out.h> |
a5ba81e5 KB |
27 | #include <unistd.h> |
28 | #include <stdio.h> | |
29 | #include <stdlib.h> | |
30 | #include <string.h> | |
faa0bd68 | 31 | |
679879db KB |
32 | #define SPACE 500 |
33 | ||
34 | #define OKEXIT 0 | |
35 | #define NOTFOUNDEXIT 1 | |
36 | #define ERREXIT 2 | |
faa0bd68 BJ |
37 | |
38 | struct nlist order[SPACE]; | |
39 | ||
faa0bd68 | 40 | struct exec exec; |
faa0bd68 | 41 | struct stat stb; |
a5ba81e5 KB |
42 | struct nlist *newtab, *symtab; |
43 | off_t sa; | |
fb0f330e | 44 | int nsym, strtabsize, symfound, small; |
a5ba81e5 | 45 | char *kfile, *newstrings, *strings, asym[BUFSIZ]; |
faa0bd68 BJ |
46 | |
47 | main(argc, argv) | |
a5ba81e5 | 48 | int argc; |
faa0bd68 BJ |
49 | char **argv; |
50 | { | |
801207e8 KB |
51 | extern char *optarg; |
52 | extern int optind; | |
a5ba81e5 | 53 | register struct nlist *p, *symp; |
faa0bd68 | 54 | register FILE *f; |
45991748 | 55 | register int i; |
a5ba81e5 | 56 | register char *start, *t; |
801207e8 KB |
57 | int ch, n, o; |
58 | ||
59 | while ((ch = getopt(argc, argv, "t")) != EOF) | |
60 | switch(ch) { | |
61 | case 't': | |
62 | small = 1; | |
63 | break; | |
64 | case '?': | |
65 | default: | |
66 | usage(); | |
67 | } | |
68 | argc -= optind; | |
69 | argv += optind; | |
70 | ||
71 | if (argc != 2) | |
72 | usage(); | |
73 | ||
74 | if ((f = fopen(argv[0], "r")) == NULL) | |
75 | error(argv[0]); | |
a5ba81e5 KB |
76 | |
77 | for (p = order; fgets(asym, sizeof(asym), f) != NULL;) { | |
78 | for (t = asym; isspace(*t); ++t); | |
79 | if (!*(start = t)) | |
faa0bd68 | 80 | continue; |
a5ba81e5 KB |
81 | while (*++t); |
82 | if (*--t == '\n') | |
83 | *t = '\0'; | |
84 | p->n_un.n_name = strdup(start); | |
85 | ++p; | |
86 | ++nsym; | |
87 | } | |
88 | (void)fclose(f); | |
89 | ||
801207e8 | 90 | kfile = argv[1]; |
a5ba81e5 KB |
91 | if ((f = fopen(kfile, "r")) == NULL) |
92 | error(kfile); | |
93 | if ((o = open(kfile, O_WRONLY)) < 0) | |
94 | error(kfile); | |
95 | ||
96 | /* read exec header */ | |
97 | if ((fread(&exec, sizeof(exec), 1, f)) != 1) | |
98 | badfmt("no exec header"); | |
99 | if (N_BADMAG(exec)) | |
100 | badfmt("bad magic number"); | |
101 | if (exec.a_syms == 0) | |
102 | badfmt("stripped"); | |
103 | (void)fstat(fileno(f), &stb); | |
104 | if (stb.st_size < N_STROFF(exec) + sizeof(off_t)) | |
105 | badfmt("no string table"); | |
106 | ||
107 | /* seek to and read the symbol table */ | |
faa0bd68 | 108 | sa = N_SYMOFF(exec); |
a5ba81e5 | 109 | (void)fseek(f, sa, SEEK_SET); |
faa0bd68 | 110 | n = exec.a_syms; |
a5ba81e5 | 111 | if (!(symtab = (struct nlist *)malloc(n))) |
801207e8 KB |
112 | error(NULL); |
113 | if (fread((void *)symtab, 1, n, f) != n) | |
a5ba81e5 KB |
114 | badfmt("corrupted symbol table"); |
115 | ||
116 | /* read string table size and string table */ | |
801207e8 | 117 | if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 || |
a5ba81e5 KB |
118 | strtabsize <= 0) |
119 | badfmt("corrupted string table"); | |
120 | strings = malloc(strtabsize); | |
801207e8 KB |
121 | if (strings == NULL) |
122 | error(NULL); | |
48e0aad0 | 123 | /* |
a5ba81e5 KB |
124 | * Subtract four from strtabsize since strtabsize includes itself, |
125 | * and we've already read it. | |
48e0aad0 | 126 | */ |
a5ba81e5 KB |
127 | if (fread(strings, 1, strtabsize - sizeof(int), f) != |
128 | strtabsize - sizeof(int)) | |
129 | badfmt("corrupted string table"); | |
45991748 RC |
130 | |
131 | newtab = (struct nlist *)malloc(n); | |
a5ba81e5 | 132 | if (newtab == (struct nlist *)NULL) |
801207e8 | 133 | error(NULL); |
a5ba81e5 KB |
134 | |
135 | i = n / sizeof(struct nlist); | |
45991748 | 136 | reorder(symtab, newtab, i); |
801207e8 | 137 | free((void *)symtab); |
45991748 RC |
138 | symtab = newtab; |
139 | ||
a5ba81e5 | 140 | newstrings = malloc(strtabsize); |
801207e8 KB |
141 | if (newstrings == NULL) |
142 | error(NULL); | |
a5ba81e5 | 143 | t = newstrings; |
45991748 RC |
144 | for (symp = symtab; --i >= 0; symp++) { |
145 | if (symp->n_un.n_strx == 0) | |
146 | continue; | |
fb0f330e | 147 | if (small && inlist(symp) < 0) continue; |
a5ba81e5 KB |
148 | symp->n_un.n_strx -= sizeof(int); |
149 | (void)strcpy(t, &strings[symp->n_un.n_strx]); | |
150 | symp->n_un.n_strx = (t - newstrings) + sizeof(int); | |
151 | t += strlen(t) + 1; | |
152 | } | |
153 | ||
fb0f330e WN |
154 | /* update shrunk sizes */ |
155 | if(small) { | |
156 | strtabsize = t - newstrings + sizeof(int); | |
157 | n = symfound * sizeof(struct nlist); | |
158 | /* fix exec sym size */ | |
159 | (void)lseek(o, 0, SEEK_SET); | |
160 | exec.a_syms = n; | |
801207e8 | 161 | if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec)) |
fb0f330e WN |
162 | error(kfile); |
163 | } | |
164 | ||
a5ba81e5 | 165 | (void)lseek(o, sa, SEEK_SET); |
801207e8 | 166 | if (write(o, (void *)symtab, n) != n) |
a5ba81e5 | 167 | error(kfile); |
801207e8 | 168 | if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int)) |
a5ba81e5 KB |
169 | error(kfile); |
170 | if (write(o, newstrings, strtabsize - sizeof(int)) != | |
171 | strtabsize - sizeof(int)) | |
172 | error(kfile); | |
fb0f330e WN |
173 | |
174 | if (small) ftruncate(o, lseek(o, 0, SEEK_CUR)); | |
175 | ||
45991748 | 176 | if ((i = nsym - symfound) > 0) { |
a5ba81e5 | 177 | (void)printf("symorder: %d symbol%s not found:\n", |
45991748 | 178 | i, i == 1 ? "" : "s"); |
a5ba81e5 | 179 | for (i = 0; i < nsym; i++) |
faa0bd68 BJ |
180 | if (order[i].n_value == 0) |
181 | printf("%s\n", order[i].n_un.n_name); | |
679879db | 182 | exit(NOTFOUNDEXIT); |
faa0bd68 | 183 | } |
679879db | 184 | exit(OKEXIT); |
45991748 RC |
185 | } |
186 | ||
a5ba81e5 | 187 | reorder(st1, st2, entries) |
45991748 | 188 | register struct nlist *st1, *st2; |
a5ba81e5 | 189 | int entries; |
45991748 | 190 | { |
a5ba81e5 KB |
191 | register struct nlist *p; |
192 | register int i, n; | |
45991748 | 193 | |
a5ba81e5 KB |
194 | for (p = st1, n = entries; --n >= 0; ++p) |
195 | if (inlist(p) != -1) | |
196 | ++symfound; | |
197 | for (p = st2 + symfound, n = entries; --n >= 0; ++st1) { | |
45991748 RC |
198 | i = inlist(st1); |
199 | if (i == -1) | |
a5ba81e5 | 200 | *p++ = *st1; |
45991748 | 201 | else |
a5ba81e5 | 202 | st2[i] = *st1; |
45991748 RC |
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 | ||
a5ba81e5 KB |
217 | if (p->n_un.n_strx >= strtabsize) |
218 | badfmt("corrupted symbol table"); | |
45991748 | 219 | |
a5ba81e5 | 220 | nam = &strings[p->n_un.n_strx - sizeof(int)]; |
45991748 RC |
221 | for (op = &order[nsym]; --op >= order; ) { |
222 | if (strcmp(op->n_un.n_name, nam) != 0) | |
223 | continue; | |
a5ba81e5 | 224 | op->n_value = 1; |
45991748 RC |
225 | return (op - order); |
226 | } | |
227 | return (-1); | |
faa0bd68 BJ |
228 | } |
229 | ||
a5ba81e5 KB |
230 | badfmt(why) |
231 | char *why; | |
232 | { | |
233 | (void)fprintf(stderr, | |
234 | "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE)); | |
679879db | 235 | exit(ERREXIT); |
a5ba81e5 | 236 | } |
faa0bd68 | 237 | |
a5ba81e5 KB |
238 | error(n) |
239 | char *n; | |
faa0bd68 | 240 | { |
a5ba81e5 KB |
241 | int sverr; |
242 | ||
243 | sverr = errno; | |
244 | (void)fprintf(stderr, "symorder: "); | |
245 | if (n) | |
246 | (void)fprintf(stderr, "%s: ", n); | |
247 | (void)fprintf(stderr, "%s\n", strerror(sverr)); | |
679879db | 248 | exit(ERREXIT); |
faa0bd68 | 249 | } |
801207e8 KB |
250 | |
251 | usage() | |
252 | { | |
253 | (void)fprintf(stderr, "usage: symorder [-t] symlist file\n"); | |
254 | exit(ERREXIT); | |
255 | } |