1: /*
   2:  *	Program Name:   symorder.c
   3:  *	Date: January 21, 1994
   4:  *	Author: S.M. Schultz
   5:  *
   6:  *	-----------------   Modification History   ---------------
   7:  *      Version Date            Reason For Modification
   8:  *      1.0     21Jan94         1. Initial release into the public domain.
   9: */
  10: 
  11: /*
  12:  * This program reorders the symbol table of an executable.  This is
  13:  * done by moving symbols found in the second file argument (one symbol
  14:  * per line) to the front of the symbol table.
  15:  *
  16:  * NOTE: This program needs to hold the string table in memory.
  17:  * For the kernel which has not been 'strcompact'd this is about 21kb.
  18:  * It is highly recommended that 'strcompact' be run first - that program
  19:  * removes redundant strings, significantly reducing the amount of memory
  20:  * needed.  Running 'symcompact' will reduce the run time needed by
  21:  * this program by eliminating redundant non-overlaid text symbols.
  22: */
  23: 
  24: #include <stdio.h>
  25: #include <a.out.h>
  26: #include <ctype.h>
  27: #include <signal.h>
  28: #include <string.h>
  29: #include <sysexits.h>
  30: #include <sys/file.h>
  31: 
  32: #define NUMSYMS 125
  33:     char    *order[NUMSYMS];
  34:     int nsorted;
  35:     char    *Pgm;
  36:     void    cleanup();
  37: static  char    sym1tmp[20], sym2tmp[20], strtmp[20];
  38: static  char    *strtab, *oldname;
  39: 
  40: main(argc, argv)
  41:     int argc;
  42:     char    **argv;
  43:     {
  44:     FILE    *fp, *fp2, *sym1fp, *sym2fp, *strfp;
  45:     int cnt, nsyms, len, c;
  46:     char    fbuf1[BUFSIZ], fbuf2[BUFSIZ];
  47:     off_t   symoff, stroff, ltmp;
  48:     long    strsiz;
  49:     struct  nlist   sym;
  50:     struct  xexec   xhdr;
  51: 
  52:     Pgm = argv[0];
  53: 
  54:     signal(SIGQUIT, cleanup);
  55:     signal(SIGINT, cleanup);
  56:     signal(SIGHUP, cleanup);
  57: 
  58:     if  (argc != 3)
  59:         {
  60:         fprintf(stderr, "usage %s: symlist file\n", Pgm);
  61:         exit(EX_USAGE);
  62:         }
  63:     fp = fopen(argv[2], "r+");
  64:     if  (!fp)
  65:         {
  66:         fprintf(stderr, "%s: can't open '%s' for update\n", Pgm,
  67:             argv[2]);
  68:         exit(EX_NOINPUT);
  69:         }
  70:     setbuf(fp, fbuf1);
  71:     cnt = fread(&xhdr, 1, sizeof (xhdr), fp);
  72:     if  (cnt < sizeof (xhdr.e))
  73:         {
  74:         fprintf(stderr, "%s: Premature EOF reading header\n", Pgm);
  75:         exit(EX_DATAERR);
  76:         }
  77:     if  (N_BADMAG(xhdr.e))
  78:         {
  79:         fprintf(stderr, "%s: Bad magic number\n", Pgm);
  80:         exit(EX_DATAERR);
  81:         }
  82:     nsyms = xhdr.e.a_syms / sizeof (struct nlist);
  83:     if  (!nsyms)
  84:         {
  85:         fprintf(stderr, "%s: '%s' stripped\n", Pgm);
  86:         exit(EX_OK);
  87:         }
  88:     stroff = N_STROFF(xhdr);
  89:     symoff = N_SYMOFF(xhdr);
  90: /*
  91:  * Seek to the string table size longword and read it.  Then attempt to
  92:  * malloc memory to hold the string table.  First make a sanity check on
  93:  * the size.
  94: */
  95:     fseek(fp, stroff, L_SET);
  96:     fread(&strsiz, sizeof (long), 1, fp);
  97:     if  (strsiz > 48 * 1024L)
  98:         {
  99:         fprintf(stderr, "%s: string table > 48kb\n", Pgm);
 100:         exit(EX_DATAERR);
 101:         }
 102:     strtab = (char *)malloc((int)strsiz);
 103:     if  (!strtab)
 104:         {
 105:         fprintf(stderr, "%s: no memory for strings\n", Pgm);
 106:         exit(EX_OSERR);
 107:         }
 108: /*
 109:  * Now read the string table into memory.  Reduce the size read because
 110:  * we've already retrieved the string table size longword.  Adjust the
 111:  * address used so that we don't have to adjust each symbol table entry's
 112:  * string offset.
 113: */
 114:     cnt = fread(strtab + sizeof (long), 1, (int)strsiz - sizeof (long), fp);
 115:     if  (cnt != (int)strsiz - sizeof (long))
 116:         {
 117:         fprintf(stderr, "%s: Premature EOF reading strings\n", Pgm);
 118:         exit(EX_DATAERR);
 119:         }
 120: /*
 121:  * Now open the file containing the list of symbols to
 122:  * relocate to the front of the symbol table.
 123: */
 124:     fp2 = fopen(argv[1], "r");
 125:     if  (!fp2)
 126:         {
 127:         fprintf(stderr, "%s: Can not open '%s'\n", Pgm, argv[1]);
 128:         exit(EX_NOINPUT);
 129:         }
 130:     getsyms(fp2);
 131: 
 132: /*
 133:  * Create the temporary files which will hold the new symbol table and the
 134:  * new string table.  One temp file receives symbols _in_ the list,
 135:  * another file receives all other symbols, and the last file receives the
 136:  * new string table.
 137: */
 138:     strcpy(sym1tmp, "/tmp/sym1XXXXXX");
 139:     mktemp(sym1tmp);
 140:     strcpy(sym2tmp, "/tmp/sym2XXXXXX");
 141:     mktemp(sym2tmp);
 142:     strcpy(strtmp, "/tmp/strXXXXXX");
 143:     mktemp(strtmp);
 144:     sym1fp = fopen(sym1tmp, "w+");
 145:     sym2fp = fopen(sym2tmp, "w+");
 146:     strfp = fopen(strtmp, "w+");
 147:     if  (!sym1fp || !sym2fp || !strfp)
 148:         {
 149:         fprintf(stderr, "%s: Can't create %s, %s or %s\n", sym1tmp,
 150:             sym2tmp, strtmp);
 151:         exit(EX_CANTCREAT);
 152:         }
 153:     setbuf(sym1fp, fbuf2);
 154: /*
 155:  * Now position the executable to the start of the symbol table.  For each
 156:  * symbol scan the list for a match on the symbol name.  If the
 157:  * name matches write the symbol table entry to one tmp file, else write it
 158:  * to the second symbol tmp file.
 159:  *
 160:  * NOTE: Since the symbol table is being rearranged the usefulness of
 161:  * "local" symbols, especially 'register' symbols, is greatly diminished
 162:  * Not that they are terribly useful in any event - especially the register
 163:  * symbols, 'adb' claims to do something with them but doesn't.  In any
 164:  * event this suite of programs is targeted at the kernel and the register
 165:  * local symbols are of no use.  For this reason 'register' symbols are
 166:  * removed - this has the side effect of even further reducing the symbol
 167:  * and string tables that must be processed by 'nm', 'ps', 'adb' and so on.
 168:  * This removal probably should have been done earlier - in 'strcompact' or
 169:  * 'symcompact' and it may be in the future, but for now just do it here.
 170: */
 171:     fseek(fp, symoff, L_SET);
 172:     while   (nsyms--)
 173:         {
 174:         fread(&sym, sizeof (sym), 1, fp);
 175:         if  (sym.n_type == N_REG)
 176:             continue;
 177:         if  (inlist(&sym))
 178:             fwrite(&sym, sizeof (sym), 1, sym1fp);
 179:         else
 180:             fwrite(&sym, sizeof (sym), 1, sym2fp);
 181:         }
 182: 
 183: /*
 184:  * Position the executable file to where the symbol table starts.  Truncate
 185:  * the file to the current position to remove the old symbols and strings.  Then
 186:  * write the symbol table entries which are to appear at the front, followed
 187:  * by the remainder of the symbols.  As each symbol is processed adjust the
 188:  * string table offset and write the string to the strings tmp file.
 189:  *
 190:  * It was either re-scan the tmp files with the symbols again to retrieve
 191:  * the string offsets or simply write the strings to yet another tmp file.
 192:  * The latter was chosen.
 193: */
 194:     fseek(fp, symoff, L_SET);
 195:     ftruncate(fileno(fp), ftell(fp));
 196:     ltmp = sizeof (long);
 197:     rewind(sym1fp);
 198:     rewind(sym2fp);
 199:     nsyms = 0;
 200:     while   (fread(&sym, sizeof (sym), 1, sym1fp) == 1)
 201:         {
 202:         if  (ferror(sym1fp) || feof(sym1fp))
 203:             break;
 204:         oldname = strtab + (int)sym.n_un.n_strx;
 205:         sym.n_un.n_strx = ltmp;
 206:         len = strlen(oldname) + 1;
 207:         ltmp += len;
 208:         fwrite(&sym, sizeof (sym), 1, fp);
 209:         fwrite(oldname, len, 1, strfp);
 210:         nsyms++;
 211:         }
 212:     fclose(sym1fp);
 213:     while   (fread(&sym, sizeof (sym), 1, sym2fp) == 1)
 214:         {
 215:         if  (ferror(sym2fp) || feof(sym2fp))
 216:             break;
 217:         oldname = strtab + (int)sym.n_un.n_strx;
 218:         sym.n_un.n_strx = ltmp;
 219:         len = strlen(oldname) + 1;
 220:         ltmp += len;
 221:         fwrite(&sym, sizeof (sym), 1, fp);
 222:         fwrite(oldname, len, 1, strfp);
 223:         nsyms++;
 224:         }
 225:     fclose(sym2fp);
 226: /*
 227:  * Next write the symbol table size longword followed by the
 228:  * string table itself.
 229: */
 230:     fwrite(&ltmp, sizeof (long), 1, fp);
 231:     rewind(strfp);
 232:     while   ((c = getc(strfp)) != EOF)
 233:         putc(c, fp);
 234:     fclose(strfp);
 235: /*
 236:  * And last (but not least) we need to update the a.out header with
 237:  * the correct size of the symbol table.
 238: */
 239:     rewind(fp);
 240:     xhdr.e.a_syms = nsyms * sizeof (struct nlist);
 241:     fwrite(&xhdr.e, sizeof (xhdr.e), 1, fp);
 242:     fclose(fp);
 243:     free(strtab);
 244:     cleanup();
 245:     }
 246: 
 247: inlist(sp)
 248:     register struct nlist *sp;
 249:     {
 250:     register int i;
 251: 
 252:     for (i = 0; i < nsorted; i++)
 253:         {
 254:         if  (strcmp(strtab + (int)sp->n_un.n_strx, order[i]) == 0)
 255:             return(1);
 256:         }
 257:     return(0);
 258:     }
 259: 
 260: getsyms(fp)
 261:     FILE    *fp;
 262:     {
 263:     char    asym[128], *start;
 264:     register char *t, **p;
 265: 
 266:     for (p = order; fgets(asym, sizeof(asym), fp) != NULL;)
 267:         {
 268:         if  (nsorted >= NUMSYMS)
 269:             {
 270:             fprintf(stderr, "%s: only doing %d symbols\n",
 271:                 Pgm, NUMSYMS);
 272:             break;
 273:             }
 274:         for (t = asym; isspace(*t); ++t)
 275:             ;
 276:         if  (!*(start = t))
 277:             continue;
 278:         while   (*++t)
 279:             ;
 280:         if  (*--t == '\n')
 281:             *t = '\0';
 282:         *p++ = strdup(start);
 283:         ++nsorted;
 284:         }
 285:     fclose(fp);
 286:     }
 287: 
 288: void
 289: cleanup()
 290:     {
 291:     if  (strtmp[0])
 292:         unlink(strtmp);
 293:     if  (sym1tmp[0])
 294:         unlink(sym1tmp);
 295:     if  (sym2tmp[0])
 296:         unlink(sym2tmp);
 297:     exit(EX_OK);
 298:     }

Defined functions

cleanup defined in line 288; used 5 times
getsyms defined in line 260; used 1 times
inlist defined in line 247; used 1 times
main defined in line 40; never used

Defined variables

Pgm defined in line 35; used 11 times
nsorted defined in line 34; used 3 times
oldname defined in line 38; used 6 times
order defined in line 33; used 2 times
strtab defined in line 38; used 7 times
strtmp defined in line 37; used 6 times
sym1tmp defined in line 37; used 6 times
sym2tmp defined in line 37; used 6 times

Defined macros

NUMSYMS defined in line 32; used 3 times
Last modified: 1994-01-23
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3462
Valid CSS Valid XHTML 1.0 Strict