1: /*
   2:  *	Program Name:   strcompact.c
   3:  *	Date: February 12, 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:  *	2.0	12Feb94		2. Rewrite.  Use new utility program 'symdump'
  10:  *				   and a multi-key sort to not only create
  11:  *				   shared symbol strings but remove identical
  12:  *				   symbols (identical absolute local symbols
  13:  *				   are quite common).  Execution speed was
  14:  *				   speed up by about a factor of 4.
  15: */
  16: 
  17: /*
  18:  * This program compacts the string table of an executable image by
  19:  * preserving only a single string definition of a symbol and updating
  20:  * the symbol table string offsets.  Multiple symbols having the same
  21:  * string are very common - local symbols in a function often have the
  22:  * same name ('int error' inside a function for example).  This program
  23:  * reduced the string table size of the kernel at least 25%!
  24:  *
  25:  * In addition, local symbols with the same value (frame offset within
  26:  * a function) are very common.  By retaining only a single '~error=2'
  27:  * for example the symbol table is reduced even further (about 500 symbols
  28:  * are removed from a typical kernel).
  29: */
  30: 
  31: #include <stdio.h>
  32: #include <a.out.h>
  33: #include <signal.h>
  34: #include <string.h>
  35: #include <sysexits.h>
  36: #include <sys/file.h>
  37: 
  38:     char    *Pgm;
  39:     char    *Sort = "/usr/bin/sort";
  40:     char    *Symdump = "/usr/ucb/symdump";
  41: static  char    strfn[32], symfn[32];
  42: 
  43: main(argc, argv)
  44:     int argc;
  45:     char    **argv;
  46:     {
  47:     struct  nlist   sym;
  48:     char    buf1[128], symname[64], savedname[64];
  49:     struct  xexec   xhdr;
  50:     int nsyms, len;
  51:     FILE    *symfp, *strfp, *sortfp;
  52: register FILE   *fpin;
  53:     long    stroff;
  54:     unsigned short  type, value, ovly;
  55:     void    cleanup();
  56: 
  57:     Pgm = argv[0];
  58:     signal(SIGQUIT, cleanup);
  59:     signal(SIGINT, cleanup);
  60:     signal(SIGHUP, cleanup);
  61: 
  62:     if  (argc != 2)
  63:         {
  64:         fprintf(stderr, "%s: missing filename argument\n", Pgm);
  65:         exit(EX_USAGE);
  66:         }
  67:     fpin = fopen(argv[1], "r+");
  68:     if  (!fpin)
  69:         {
  70:         fprintf(stderr, "%s: can not open '%s' for update\n",
  71:             Pgm, argv[1]);
  72:         exit(EX_NOINPUT);
  73:         }
  74:     if  (fread(&xhdr, 1, sizeof (xhdr), fpin) < sizeof (xhdr.e))
  75:         {
  76:         fprintf(stderr, "%s: premature EOF\n", Pgm);
  77:         exit(EX_DATAERR);
  78:         }
  79:     if  (N_BADMAG(xhdr.e))
  80:         {
  81:         fprintf(stderr, "%s: Bad magic number\n", Pgm);
  82:         exit(EX_DATAERR);
  83:         }
  84:     nsyms = xhdr.e.a_syms / sizeof (struct nlist);
  85:     if  (!nsyms)
  86:         {
  87:         fprintf(stderr, "%s: '%s' stripped\n", Pgm, argv[1]);
  88:         exit(EX_OK);
  89:         }
  90: 
  91:     strcpy(strfn, "/tmp/strXXXXXX");
  92:     mktemp(strfn);
  93:     strcpy(symfn, "/tmp/symXXXXXX");
  94:     mktemp(symfn);
  95: 
  96:     sprintf(buf1, "%s %s | %s +0 -1 +1n -2 +2n -3 +3n -4 -u", Symdump,
  97:         argv[1], Sort);
  98:     sortfp = popen(buf1, "r");
  99:     if  (!sortfp)
 100:         {
 101:         fprintf(stderr, "%s: symdump | sort failed\n", Pgm);
 102:         exit(EX_SOFTWARE);
 103:         }
 104:     symfp = fopen(symfn, "w+");
 105:     strfp = fopen(strfn, "w+");
 106:     if  (!symfp || !strfp)
 107:         {
 108:         fprintf(stderr, "%s: can't create %s or %s\n", symfn, strfn);
 109:         exit(EX_CANTCREAT);
 110:         }
 111: 
 112:     stroff = sizeof (long);
 113:     len = 0;
 114:     nsyms = 0;
 115:     while   (fscanf(sortfp, "%s %u %u %u\n", symname, &type, &ovly,
 116:             &value) == 4)
 117:         {
 118:         if  (strcmp(symname, savedname))
 119:             {
 120:             stroff += len;
 121:             len = strlen(symname) + 1;
 122:             fwrite(symname, len, 1, strfp);
 123:             strcpy(savedname, symname);
 124:             }
 125:         sym.n_un.n_strx = stroff;
 126:         sym.n_type = type;
 127:         sym.n_ovly = ovly;
 128:         sym.n_value = value;
 129:         fwrite(&sym, sizeof (sym), 1, symfp);
 130:         nsyms++;
 131:         }
 132:     stroff += len;
 133: 
 134:     pclose(sortfp);
 135:     rewind(symfp);
 136:     rewind(strfp);
 137: 
 138:     if  (nsyms == 0)
 139:         {
 140:         fprintf(stderr, "%s: No symbols - %s not modified\n", argv[1]);
 141:         cleanup();
 142:         }
 143: 
 144:     fseek(fpin, N_SYMOFF(xhdr), L_SET);
 145: 
 146: /*
 147:  * Now append the new symbol table.  Then write the string table length
 148:  * followed by the string table.  Finally truncate the file to the new
 149:  * length, reflecting the smaller string table.
 150: */
 151:     copyfile(symfp, fpin);
 152:     fwrite(&stroff, sizeof (long), 1, fpin);
 153:     copyfile(strfp, fpin);
 154:     ftruncate(fileno(fpin), ftell(fpin));
 155: 
 156: /*
 157:  * Update the header with the correct symbol table size.
 158: */
 159:     rewind(fpin);
 160:     xhdr.e.a_syms = nsyms * sizeof (sym);
 161:     fwrite(&xhdr, sizeof (xhdr.e), 1, fpin);
 162: 
 163:     fclose(fpin);
 164:     fclose(symfp);
 165:     fclose(strfp);
 166:     cleanup();
 167:     }
 168: 
 169: copyfile(in, out)
 170:     register FILE *in, *out;
 171:     {
 172:     register int c;
 173: 
 174:     while   ((c = getc(in)) != EOF)
 175:         putc(c, out);
 176:     }
 177: 
 178: fatal(str)
 179:     char    *str;
 180:     {
 181: 
 182:     if  (strfn[0])
 183:         unlink(strfn);
 184:     if  (symfn[0])
 185:         unlink(symfn);
 186:     if  (!str)
 187:         exit(EX_OK);
 188:     fprintf(stderr, "%s: %s\n", str);
 189:     exit(EX_SOFTWARE);
 190:     }
 191: 
 192: void
 193: cleanup()
 194:     {
 195:     fatal((char *)NULL);
 196:     }

Defined functions

cleanup defined in line 192; used 6 times
copyfile defined in line 169; used 2 times
fatal defined in line 178; used 1 times
main defined in line 43; never used

Defined variables

Pgm defined in line 38; used 7 times
Sort defined in line 39; used 1 times
  • in line 97
Symdump defined in line 40; used 1 times
  • in line 96
strfn defined in line 41; used 6 times
symfn defined in line 41; used 6 times
Last modified: 1994-02-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3066
Valid CSS Valid XHTML 1.0 Strict