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.8 (Berkeley) 04/01/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 extern char *optarg; 52 extern int optind; 53 register struct nlist *p, *symp; 54 register FILE *f; 55 register int i; 56 register char *start, *t; 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]); 76 77 for (p = order; fgets(asym, sizeof(asym), f) != NULL;) { 78 for (t = asym; isspace(*t); ++t); 79 if (!*(start = t)) 80 continue; 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 90 kfile = argv[1]; 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 */ 108 sa = N_SYMOFF(exec); 109 (void)fseek(f, sa, SEEK_SET); 110 n = exec.a_syms; 111 if (!(symtab = (struct nlist *)malloc(n))) 112 error(NULL); 113 if (fread((void *)symtab, 1, n, f) != n) 114 badfmt("corrupted symbol table"); 115 116 /* read string table size and string table */ 117 if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 || 118 strtabsize <= 0) 119 badfmt("corrupted string table"); 120 strings = malloc(strtabsize); 121 if (strings == NULL) 122 error(NULL); 123 /* 124 * Subtract four from strtabsize since strtabsize includes itself, 125 * and we've already read it. 126 */ 127 if (fread(strings, 1, strtabsize - sizeof(int), f) != 128 strtabsize - sizeof(int)) 129 badfmt("corrupted string table"); 130 131 newtab = (struct nlist *)malloc(n); 132 if (newtab == (struct nlist *)NULL) 133 error(NULL); 134 135 i = n / sizeof(struct nlist); 136 reorder(symtab, newtab, i); 137 free((void *)symtab); 138 symtab = newtab; 139 140 newstrings = malloc(strtabsize); 141 if (newstrings == NULL) 142 error(NULL); 143 t = newstrings; 144 for (symp = symtab; --i >= 0; symp++) { 145 if (symp->n_un.n_strx == 0) 146 continue; 147 if (small && inlist(symp) < 0) continue; 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 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; 161 if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec)) 162 error(kfile); 163 } 164 165 (void)lseek(o, sa, SEEK_SET); 166 if (write(o, (void *)symtab, n) != n) 167 error(kfile); 168 if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int)) 169 error(kfile); 170 if (write(o, newstrings, strtabsize - sizeof(int)) != 171 strtabsize - sizeof(int)) 172 error(kfile); 173 174 if (small) ftruncate(o, lseek(o, 0, SEEK_CUR)); 175 176 if ((i = nsym - symfound) > 0) { 177 (void)printf("symorder: %d symbol%s not found:\n", 178 i, i == 1 ? "" : "s"); 179 for (i = 0; i < nsym; i++) 180 if (order[i].n_value == 0) 181 printf("%s\n", order[i].n_un.n_name); 182 exit(NOTFOUNDEXIT); 183 } 184 exit(OKEXIT); 185 } 186 187 reorder(st1, st2, entries) 188 register struct nlist *st1, *st2; 189 int entries; 190 { 191 register struct nlist *p; 192 register int i, n; 193 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) { 198 i = inlist(st1); 199 if (i == -1) 200 *p++ = *st1; 201 else 202 st2[i] = *st1; 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 217 if (p->n_un.n_strx >= strtabsize) 218 badfmt("corrupted symbol table"); 219 220 nam = &strings[p->n_un.n_strx - sizeof(int)]; 221 for (op = &order[nsym]; --op >= order; ) { 222 if (strcmp(op->n_un.n_name, nam) != 0) 223 continue; 224 op->n_value = 1; 225 return (op - order); 226 } 227 return (-1); 228 } 229 230 badfmt(why) 231 char *why; 232 { 233 (void)fprintf(stderr, 234 "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE)); 235 exit(ERREXIT); 236 } 237 238 error(n) 239 char *n; 240 { 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)); 248 exit(ERREXIT); 249 } 250 251 usage() 252 { 253 (void)fprintf(stderr, "usage: symorder [-t] symlist file\n"); 254 exit(ERREXIT); 255 } 256