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 are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)symorder.c 5.3 (Berkeley) 11/01/88"; 26 #endif /* not lint */ 27 28 /* 29 * symorder - reorder symbol table 30 */ 31 32 #include <stdio.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <a.out.h> 36 37 #define SPACE 100 38 39 struct nlist order[SPACE]; 40 41 char *savestr(), *index(), *malloc(); 42 struct exec exec; 43 off_t sa; 44 struct stat stb; 45 int nsym = 0; 46 int symfound = 0; 47 char *strings; 48 char *newstrings; 49 struct nlist *symtab; 50 struct nlist *newtab; 51 int symsize; 52 char asym[BUFSIZ]; 53 54 main(argc, argv) 55 char **argv; 56 { 57 register char *ns; 58 register struct nlist *symp; 59 register struct nlist *p; 60 register FILE *f; 61 register int i; 62 int n, o; 63 64 if (argc != 3) { 65 fprintf(stderr, "Usage: symorder orderlist file\n"); 66 exit(1); 67 } 68 if ((f = fopen(argv[1], "r")) == NULL) { 69 perror(argv[1]); 70 exit(1); 71 } 72 for (p = order; fgets(asym, sizeof asym, f) != NULL; p++, nsym++) { 73 for (i = 0; asym[i] && asym[i] != '\n'; i++) 74 continue; 75 if (asym[i] == '\n') 76 asym[i] = 0; 77 p->n_un.n_name = savestr(asym); 78 } 79 fclose(f); 80 if ((f = fopen(argv[2], "r")) == NULL) 81 perror(argv[2]), exit(1); 82 if ((o = open(argv[2], 1)) < 0) 83 perror(argv[2]), exit(1); 84 if ((fread(&exec, sizeof exec, 1, f)) != 1 || N_BADMAG(exec)) { 85 fprintf(stderr, "symorder: %s: bad format\n", argv[2]); 86 exit(1); 87 } 88 if (exec.a_syms == 0) { 89 fprintf(stderr, "symorder: %s is stripped\n", argv[2]); 90 exit(1); 91 } 92 fstat(fileno(f), &stb); 93 if (stb.st_size < N_STROFF(exec)+sizeof(off_t)) { 94 fprintf(stderr, "symorder: %s is in old format or truncated\n", 95 argv[2]); 96 exit(1); 97 } 98 sa = N_SYMOFF(exec); 99 fseek(f, sa, 0); 100 n = exec.a_syms; 101 symtab = (struct nlist *)malloc(n); 102 if (symtab == (struct nlist *)0) { 103 fprintf(stderr, "symorder: Out of core, no space for symtab\n"); 104 exit(1); 105 } 106 if (fread((char *)symtab, 1, n, f) != n) { 107 fprintf(stderr, "symorder: Short file "); perror(argv[2]); 108 exit(1); 109 } 110 if (fread((char *)&symsize, sizeof (int), 1, f) != 1 || 111 symsize <= 0) { 112 fprintf(stderr, "symorder: No strings "); perror(argv[2]); 113 exit(1); 114 } 115 strings = malloc(symsize); 116 if (strings == (char *)0) { 117 fprintf(stderr,"symorder: Out of core, no space for strings\n"); 118 exit(1); 119 } 120 /* 121 * Need to subtract four from symsize here since 122 * symsize includes itself, and we've already read 123 * it. (6/30/85 chris@maryland) 124 */ 125 if (fread(strings, 1, symsize - 4, f) != symsize - 4) { 126 fprintf(stderr, "symorder: Truncated strings "); 127 perror(argv[2]); 128 exit(1); 129 } 130 131 newtab = (struct nlist *)malloc(n); 132 if (newtab == (struct nlist *)0) { 133 fprintf(stderr, 134 "symorder: Out of core, no space for new symtab\n"); 135 exit(1); 136 } 137 i = n / sizeof (struct nlist); 138 reorder(symtab, newtab, i); 139 free((char *)symtab); 140 symtab = newtab; 141 142 newstrings = malloc(symsize); 143 if (newstrings == (char *)0) { 144 fprintf(stderr, 145 "symorder: Out of core, no space for newstrings\n"); 146 exit(1); 147 } 148 ns = newstrings; 149 for (symp = symtab; --i >= 0; symp++) { 150 if (symp->n_un.n_strx == 0) 151 continue; 152 symp->n_un.n_strx -= sizeof (int); 153 if ((unsigned)symp->n_un.n_strx >= symsize) { 154 fprintf(stderr,"symorder: Corrupted string pointers\n"); 155 exit(1); 156 } 157 strcpy(ns, &strings[symp->n_un.n_strx]); 158 symp->n_un.n_strx = (ns - newstrings) + sizeof (int); 159 ns = index(ns, 0) + 1; 160 if (ns > &newstrings[symsize]) { 161 fprintf(stderr, "symorder: Strings grew longer!\n"); 162 exit(1); 163 } 164 } 165 166 lseek(o, sa, 0); 167 if (write(o, (char *)symtab, n) != n) { 168 fprintf(stderr, "symorder: Write failed "); perror(argv[2]); 169 exit(1); 170 } 171 if (write(o, (char *)&symsize, sizeof (int)) != sizeof (int)) { 172 fprintf(stderr, "symorder: Write failed "); perror(argv[2]); 173 exit(1); 174 } 175 if (write(o, newstrings, symsize - 4) != symsize - 4) { 176 fprintf(stderr, "symorder: Write failed "); perror(argv[2]); 177 exit(1); 178 } 179 if ((i = nsym - symfound) > 0) { 180 fprintf(stderr, "symorder: %d symbol%s not found:\n", 181 i, i == 1 ? "" : "s"); 182 for (i = 0; i < nsym; i++) { 183 if (order[i].n_value == 0) 184 printf("%s\n", order[i].n_un.n_name); 185 } 186 } 187 exit(0); 188 } 189 190 reorder(st1, st2, n) 191 register struct nlist *st1, *st2; 192 register n; 193 { 194 register struct nlist *stp = st2 + nsym; 195 register i; 196 197 while (--n >= 0) { 198 i = inlist(st1); 199 if (i == -1) 200 *stp++ = *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 nam = &strings[p->n_un.n_strx - sizeof(int)]; 218 if (nam >= &strings[symsize]) { 219 fprintf(stderr, "symorder: corrupt symtab\n"); 220 exit(1); 221 } 222 223 for (op = &order[nsym]; --op >= order; ) { 224 if (strcmp(op->n_un.n_name, nam) != 0) 225 continue; 226 if (op->n_value == 0) { 227 op->n_value++; 228 symfound++; 229 } 230 return (op - order); 231 } 232 return (-1); 233 } 234 235 #define NSAVETAB 4096 236 char *savetab; 237 int saveleft; 238 239 char * 240 savestr(cp) 241 register char *cp; 242 { 243 register int len; 244 245 len = strlen(cp) + 1; 246 if (len > saveleft) { 247 saveleft = NSAVETAB; 248 if (len > saveleft) 249 saveleft = len; 250 savetab = (char *)malloc(saveleft); 251 if (savetab == 0) { 252 fprintf(stderr, 253 "symorder: ran out of memory (savestr)\n"); 254 exit(1); 255 } 256 } 257 strncpy(savetab, cp, len); 258 cp = savetab; 259 savetab += len; 260 saveleft -= len; 261 return (cp); 262 } 263