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