1: /*
   2:  * mkovmake.c	by dennisf@ndcvx.cc.nd.edu  March 1990
   3:  *	makes an overlay makefile for specified object modules.
   4:  *  v1.1: adds -v option, and #defines for ovinit and module[].overlay.
   5:  *  v1.2: -o option renamed to -f, new -o and -l options for output name
   6:  *	and libraries.
   7:  *  v2: Overlay optimizer!  Many changes, practically different program.
   8:  *  v3: Modified to use new object file (strings table) format. 1/9/94 - sms.
   9:  */
  10: 
  11: #include <stdio.h>
  12: #include <strings.h>
  13: #include <ctype.h>
  14: #include <sys/param.h>
  15: #include <a.out.h>
  16: #include <sys/file.h>
  17: 
  18: #define MAXSYMLEN 32
  19: #define IN_BASE 0
  20: #define UNCOMMITTED -1
  21: #define isobj(name) name[0] && name[0] != '-' && rindex(name,'.') \
  22:     && !strcmp(rindex(name,'.'), ".o")
  23: #define isarc(name) name[0] && name[0] != '-' && rindex(name,'.') \
  24:     && !strcmp(rindex(name,'.'), ".a")
  25: 
  26: struct modstruct
  27: {
  28:     char *name;
  29:     unsigned text;
  30:     short overlay;
  31:     char **textnames;
  32:     char **undfnames;
  33: } *module;
  34: FILE *output;
  35: char *malloc(), *realloc(), *adlib(), *libs;
  36: int optimize, listnames;
  37: double metoo();
  38: 
  39: main(argc, argv)
  40: int argc;
  41: char **argv;
  42: {
  43:     register i, n;
  44:     int ovinit; /* initial ov number, IN_BASE or UNCOMMITTED */
  45:     int j;      /* redundant-module index */
  46:     int nobj;   /* number of modules, used for malloc()ing */
  47:     long ovtext;    /* total size of text of UNCOMMITTED modules */
  48:     int ov;     /* overlay number, used in for loop */
  49:     int max_ovs;    /* max number of ovs mkovmake can make */
  50:     int ovs_used;   /* number of ovs actually used */
  51:     int modsleftout;/* number of modules not assigned to an ov */
  52:     unsigned max_ovsize;    /* sizeof biggest overlay, multiple of 8k */
  53:     unsigned bigovmod;  /* sizeof biggest module not assigned to base */
  54:     unsigned ovspace;   /* space occupied in current ov */
  55:     unsigned basesize;  /* limit on base, if optimizing */
  56:     int mostroutines;   /* module with biggest global text routines
  57: 				   per kb text ratio, if optimizing base */
  58:     double baseopt;     /* the best such ratio so far */
  59:     int wannabe;    /* module that most wants to be on the overlay,
  60: 			   if optimizing */
  61:     double affinity;/* metoo(ov,wannabe) */
  62:     double affinn;  /* metoo(ov,n) */
  63:     int Zused;  /* -Z option specified somewhere used in -O2 */
  64:     long tmpl;
  65:     char *makename, *program;
  66:     char *arg, switchc;
  67: 
  68:     /* Usage */
  69:     if (argc == 1)
  70:     {
  71: usage:      fprintf(stderr,
  72:          "usage:  mkovmake [-On [basesize] [-n]] [-fmakefile] [-sovsize] [-vmax_ovs]\n");
  73:         fprintf(stderr, "\t\t[-oprogram] [-llibs ...] bases.o ... -Z ovmodules.o ...\n");
  74:         exit(1);
  75:     }
  76: 
  77:     /* Set defaults */
  78:     Zused = listnames = bigovmod = ovtext = nobj = optimize = 0;
  79:     output = stdout;
  80:     max_ovsize = basesize = UNCOMMITTED;
  81:     ovinit = IN_BASE;
  82:     max_ovs = NOVL;
  83:     program = "$(PROGRAM)";
  84:     libs = malloc(2);
  85:     libs[0] = 0;
  86:     /* First parsing: get options, count object modules */
  87:     for (i = 1; i < argc; ++i)
  88:     {
  89:         if (argv[i][0] != '-')
  90:         {
  91:             if (isobj(argv[i]))
  92:                 ++nobj;
  93:             else if (isarc(argv[i]))
  94:                 adlib(argv[i]);
  95:             else
  96:             {
  97:                 fprintf(stderr, "mkovmake:  %s: unknown file type.\n",
  98:                  argv[i]);
  99:                 exit(5);
 100:             }
 101:         }
 102:         else
 103:         {
 104:             switchc = argv[i][1];
 105:             arg = argv[i] + 2;
 106:             if (!arg[0])
 107:                 arg = argv[++i];
 108:             switch (switchc)
 109:             {
 110:             case 'O':
 111:                 optimize = 1; /* Use given BASE */
 112:                 if (arg[0] == '2')
 113:                 {
 114:                     optimize = 2; /* Determine BASE */
 115:                     if (isdigit(argv[i+1][0]))
 116:                     {
 117:                         basesize = atoi(argv[++i]);
 118:                         if (index(argv[i],'k')
 119:                          || index(argv[i],'K'))
 120:                             basesize *= 1024;
 121:                         if (basesize < 10)
 122:                             basesize *= 8192;
 123:                     }
 124:                 }
 125:                 else
 126:                     --i; /* no argument */
 127:                 break;
 128:             case 'n':
 129:                 ++listnames;
 130:                 --i; /* no argument */
 131:                 break;
 132:             case 'Z':
 133:                 if (optimize != 2 && !nobj)
 134:                     fprintf(stderr, "Nothing in the BASE?  Ok...\n");
 135:                 ++Zused;
 136:                 --i; /* no argument */
 137:                 break;
 138:             case 'f':
 139:                 makename = arg;
 140:                 if ((output = fopen(makename, "w")) == NULL)
 141:                 {
 142:                     fprintf(stderr,
 143:                     "%s: cannot open for output.\n", makename);
 144:                     exit(2);
 145:                 }
 146:                 break;
 147:             case 's':
 148:                 max_ovsize = atoi(arg);
 149:                 if (index(arg,'k') || index(arg,'K'))
 150:                     max_ovsize *= 1024;
 151:                 if (max_ovsize < 10)
 152:                     max_ovsize *= 8192;
 153:                 break;
 154:             case 'v':
 155:                 max_ovs = atoi(arg);
 156:                 if (max_ovs > NOVL)
 157:                 {
 158:                     fprintf(stderr,
 159:                      "mkovmake:  can only use %d overlays.\n",
 160:                      NOVL);
 161:                     max_ovs = NOVL;
 162:                 }
 163:                 break;
 164:             case 'o':
 165:                 program = arg;
 166:                 break;
 167:             case 'l':
 168:                 adlib("-l");
 169:                 adlib(arg);
 170:                 break;
 171:             default:
 172:                 goto usage;
 173:             }
 174:         }
 175:     }
 176:     if (!libs[0])
 177:     {
 178:         free(libs);
 179:         libs = "$(LIBS) ";
 180:     }
 181:     if (!Zused && optimize == 2)
 182:         ovinit = UNCOMMITTED;
 183: 
 184:     /* Second parsing: malloc for module[] array and load its members */
 185:     if (!(module = (struct modstruct *) malloc(sizeof(struct modstruct) * ++nobj)))
 186:     {
 187:         fprintf(stderr, "mkovmake:  not enough memory for module list.\n");
 188:         fprintf(stderr, "mkovmake:  can't use mkovmake!  Help!\n");
 189:         exit(6);
 190:     }
 191:     for (i = 1, n = 0; i < argc; ++i)
 192:     {
 193:         for (j = 1; j < i; ++j)
 194:             if (!strcmp(argv[i], argv[j]))
 195:                 break;
 196:         if (argv[i][0] == '-' && argv[i][1] == 'Z')
 197:             ovinit = UNCOMMITTED;
 198:         else if (j == i && isobj(argv[i]))
 199:         {
 200:             module[n].name = argv[i];
 201:             module[n].overlay = ovinit;
 202:             getnames(n);  /* gets sizeof text and name lists */
 203:             if (ovinit != IN_BASE)
 204:             {
 205:                 ovtext += module[n].text;
 206:                 if (module[n].text > bigovmod)
 207:                     bigovmod = module[n].text;
 208:             }
 209:             ++n;
 210:         }
 211:     }
 212:     module[n].name = "";
 213:     if (max_ovsize == UNCOMMITTED)
 214:     {
 215:         max_ovsize = (unsigned) (ovtext / (7680L * max_ovs) + 1) * 8192;
 216:         if (bigovmod > max_ovsize)
 217:             max_ovsize = (bigovmod / 8192 + 1) * 8192;
 218:         fprintf(output, "# Using %dk overlays.\n", max_ovsize/1024);
 219:     }
 220: 
 221:     /*
 222: 	 * Optimizer levels:
 223: 	 * 1: use given BASE, all other modules are UNCOMMITTED.
 224: 	 * 2: determine BASE, all modules are UNCOMMITTED.
 225: 	 * 3: programmer gets COMMITTED.
 226: 	 */
 227:     if (optimize == 2)
 228:     {
 229:         if (basesize == UNCOMMITTED)
 230:         {
 231:             /* is this a fudge or what?? */
 232:             tmpl = ((tmpl = 2048 + nlibs()*2048L + ovtext/5)
 233:              > 24576L) ? 24576L : tmpl;
 234:             basesize = (65536L - max_ovsize - tmpl);
 235:             fprintf(output, "# Using %u-byte base, without libraries.\n",
 236:              basesize);
 237:             /* If enough people are interested, I'll make a version
 238: 			   of this that adds up routines used within libraries */
 239:         }
 240:         n = -1;
 241:         while (module[++n].name[0])
 242:             if (module[n].overlay == IN_BASE)
 243:                 basesize -= module[n].text;
 244:         if (basesize < 0)
 245:         {
 246:             fprintf(stderr, "mkovmake:  specified modules don't fit in base.\n");
 247:             fprintf(stderr, "mkovmake:  specify fewer modules or larger base.\n");
 248:             exit(9);
 249:         }
 250:         do /* load the base */
 251:         {
 252:             baseopt = 0.;
 253:             n = -1;
 254:             while(module[++n].name[0])
 255:                 if (module[n].overlay != IN_BASE
 256:                  && module[n].text
 257:                  && module[n].text <= basesize
 258:                  && (double) (sizeof(module[n].textnames)-1)
 259:                  / module[n].text > baseopt)
 260:                 {
 261:                     mostroutines = n;
 262:                     baseopt = (double)
 263:                      (sizeof(module[n].textnames)-1)
 264:                      / module[n].text;
 265:                 }
 266:             if (baseopt)
 267:             {
 268:                 module[mostroutines].overlay = IN_BASE;
 269:                 basesize -= module[mostroutines].text;
 270:             }
 271:         } while(baseopt);
 272:     }
 273:     listmodules(IN_BASE);
 274: 
 275:     /*
 276: 	 * overlay packing:
 277: 	 * If not optimizing, just pack modules until no more can fit.
 278: 	 * Otherwise, add a module only if it's the one thats to be on
 279: 	 *	the ov the most, using metoo().
 280: 	 */
 281:     for (ov = 1; ov <= max_ovs; ++ov)
 282:     {
 283:         ovspace = 0;
 284: addmod:     n = -1;
 285:         while (module[++n].name[0])
 286:         {
 287:             if (module[n].overlay == UNCOMMITTED
 288:              && module[n].text + ovspace <= max_ovsize)
 289:             {
 290:                 module[n].overlay = ov;
 291:                 ovspace += module[n].text;
 292:                 /* optimizer needs one */
 293:                 if (optimize && module[n].text)
 294:                     break;
 295:             }
 296:         }
 297:         if (!ovspace) /* max_ovsize is too small for a module */
 298:             break;
 299:         if (optimize && module[n].name[0])
 300:         {
 301:             for (;;) /* only escape is the goto! yuck! */
 302:             {
 303:                 affinity = 0.;
 304:                 n = -1;
 305:                 while (module[++n].name[0])
 306:                 {
 307:                     if (module[n].overlay == UNCOMMITTED
 308:                      && module[n].text
 309:                      && module[n].text + ovspace <= max_ovsize
 310:                      && (affinn = metoo(ov,n)) > affinity)
 311:                     {
 312:                         wannabe = n;
 313:                         affinity = affinn;
 314:                     }
 315:                 }
 316:                 if (!affinity)
 317:                     goto addmod; /* will another mod fit? */
 318:                 module[wannabe].overlay = ov;
 319:                 ovspace += module[wannabe].text;
 320:             }
 321:         }
 322:         listmodules(ov);
 323:     }
 324:     ovs_used = ov;
 325: 
 326:     /* And what if they just don't all fit? */
 327:     n = modsleftout = 0;
 328:     while (module[n].name[0])
 329:         if (module[n++].overlay == UNCOMMITTED)
 330:             ++modsleftout;
 331:     if (modsleftout)
 332:     {
 333:         fprintf(stderr, "\nAfter %d overlay", ovs_used-1);
 334:         if (ovs_used != 2)  fprintf(stderr, "s");
 335:         fprintf(stderr, ", the following ");
 336:         if (modsleftout == 1)
 337:             fprintf(stderr, "module was\n");
 338:         else
 339:             fprintf(stderr, "%d modules were\n", modsleftout);
 340:         fprintf(stderr,
 341:          "left out of the BASE and OVerlay definitions:\n");
 342:         n = -1;
 343:         while (module[++n].name[0])
 344:             if (module[n].overlay == UNCOMMITTED)
 345:                 fprintf(stderr, "  %s\n", module[n].name);
 346:         fprintf(stderr,
 347:          "\nYou can 1) Use more or bigger overlays,\n");
 348:         fprintf(stderr, "  2) Use a smaller base, or\n");
 349:         fprintf(stderr, "  3) \"Go buy a VAX.\"\n");
 350:         fclose(output);
 351:         exit(3);
 352:     }
 353: 
 354:     fprintf(output,
 355:      "%s:\n\t/bin/ld -i -X -o %s /lib/crt0.o \\\n\t", program, program);
 356:     fprintf(output, "$(BASE) ");
 357:     for (ov = 1; ov < ovs_used; ++ov)
 358:     {
 359:         if (ov % 4 == 1)
 360:             fprintf(output, "\\\n\t");
 361:         fprintf(output, "-Z $(OV%d) ", ov);
 362:     }
 363:     fprintf(output, "\\\n\t-Y %s-lc\n", libs);
 364:     fclose(output);
 365:     free((char *) module);
 366:     free(libs);
 367:     exit(0);
 368: }
 369: 
 370: /*
 371:  * listmodules(ov)
 372:  *	lists modules in overlay ov (ov=0 is BASE), each line
 373:  *	preceded by a tab and not exceeding LISTWIDTH characters.
 374:  */
 375: 
 376: #define LISTWIDTH   60
 377: 
 378: listmodules(ov)
 379: int ov;
 380: {
 381:     int currentwidth = 0, n = -1, namelength;
 382:     unsigned listovspace = 0;
 383: 
 384:     if (ov == IN_BASE)
 385:         fprintf(output, "\nBASE=\t");
 386:     else
 387:         fprintf(output, "OV%d=\t", ov);
 388:     while (module[++n].name[0])
 389:     {
 390:         if (module[n].overlay == ov)
 391:         {
 392:             namelength = strlen(module[n].name);
 393:             if (currentwidth + namelength > LISTWIDTH)
 394:             {
 395:                 fprintf(output, "\\\n\t");
 396:                 currentwidth = 0;
 397:             }
 398:             currentwidth += (namelength + 1);
 399:             fprintf(output, "%s ", module[n].name);
 400:             listovspace += module[n].text;
 401:         }
 402:     }
 403:     fprintf(output, "\n# %u bytes.\n\n", listovspace);
 404: }
 405: 
 406: /*
 407:  * metoo()	returns how much a module wants to be on an overlay.
 408:  */
 409: double
 410: metoo(ov, mod)
 411: int ov, mod;
 412: {
 413:     int n, postnews;
 414: 
 415:     if (!module[mod].text)
 416:         return(0.);
 417:     postnews = 0;
 418:     n = -1;
 419:     while (module[++n].name[0])
 420:         if (module[n].overlay == ov)
 421:             postnews += ilikeu(n, mod) + ilikeu(mod, n);
 422:     return((double) postnews / module[mod].text);
 423: }
 424: 
 425: /*
 426:  * ilikeu()	returns how much one module likes another.
 427:  *	Just like life, it's not necessarily symmetrical.
 428:  */
 429: ilikeu(me, you)
 430: int me, you;
 431: {
 432:     int friendly;
 433:     char **ineed, **youhave;
 434: 
 435:     friendly = 0;  /* Who are you? */
 436:     ineed = module[me].undfnames;
 437:     youhave = module[you].textnames;
 438:     while(**ineed)
 439:     {
 440:         while(**youhave)
 441:         {
 442:             if (!strcmp(*ineed, *youhave++))
 443:             {
 444:                 ++friendly;
 445:                 break;
 446:             }
 447:         }
 448:         ++ineed;
 449:     }
 450:     return(friendly);
 451: }
 452: 
 453: /*
 454:  * adlib(s)	adds s onto libs.
 455:  */
 456: char *
 457: adlib(s)
 458: char *s;
 459: {
 460:     char *morelibs;
 461: 
 462:     if (!(morelibs = realloc(libs, strlen(libs)+strlen(s)+3)))
 463:     {
 464:         fprintf(stderr, "mkovmake:  not enough memory for library names.\n");
 465:         exit(7);
 466:     }
 467:     strcat(morelibs, s);
 468:     if (s[0] != '-')
 469:         strcat(morelibs, " ");
 470:     libs = morelibs;
 471:     return(morelibs);
 472: }
 473: 
 474: /*
 475:  * nlibs()	How many libs are there?
 476:  */
 477: nlibs()
 478: {
 479:     int i=0;
 480:     char *s;
 481:     s = libs;
 482:     while (*s)
 483:         if (*s++ == ' ')
 484:             ++i;
 485:     return(i);
 486: }
 487: 
 488: /*
 489:  * getnames(n)	opens object module n and gets size of text,
 490:  *	and name lists if using optimizer.
 491:  */
 492: getnames(n)
 493: int n;
 494: {
 495:     struct xexec exp;
 496:     struct nlist namentry;
 497:     FILE *obj, *strfp = NULL;
 498:     off_t stroff;
 499:     int nundf, ntext;
 500:     char name[MAXSYMLEN + 2];
 501: 
 502:     bzero(name, sizeof (name));
 503:     if ((obj = fopen(module[n].name,"r")) == NULL)
 504:     {
 505:         fprintf(stderr, "mkovmake:  cannot open %s.\n", module[n].name);
 506:         exit(8);
 507:     }
 508:     fread((char *)&exp, 1, sizeof(exp), obj);
 509:     module[n].text = exp.e.a_text;
 510:     if (!optimize)
 511:     {
 512:         fclose(obj);
 513:         return(0);
 514:     }
 515: 
 516:     fseek(obj, N_SYMOFF(exp), L_SET);
 517: 
 518:     ntext = nundf = 0;
 519:     while (fread((char *)&namentry, sizeof(namentry), 1, obj) == 1)
 520:     {
 521:         if (feof(obj) || ferror(obj))
 522:             break;
 523:         if (namentry.n_type & N_EXT)
 524:         {
 525:             switch (namentry.n_type&N_TYPE)
 526:             {
 527:             case N_UNDF:
 528:                 if (!namentry.n_value)
 529:                     ++nundf;
 530:                 break;
 531:             case N_TEXT:
 532:                 ++ntext;
 533:                 break;
 534:             }
 535:         }
 536:     }
 537:     module[n].textnames = (char **) malloc(++ntext * 2);
 538:     module[n].undfnames = (char **) malloc(++nundf * 2);
 539:     if (!module[n].textnames || !module[n].undfnames)
 540:     {
 541: nosyms:     fprintf(stderr, "mkovmake:  out of memory for symbols list.\n");
 542:         fprintf(stderr, "mkovmake:  can't optimize.\n");
 543:         optimize = 0;
 544:         fclose(obj);
 545:         if (strfp)
 546:             fclose(strfp);
 547:         return(1);
 548:     }
 549: 
 550:     strfp = fopen(module[n].name, "r");
 551:     ntext = nundf = 0;
 552:     fseek(obj, N_SYMOFF(exp), L_SET);
 553:     stroff = N_STROFF(exp);
 554:     while (fread((char *)&namentry, sizeof(namentry), 1, obj) == 1)
 555:     {
 556:         if (namentry.n_type & N_EXT)
 557:         {
 558:             switch (namentry.n_type&N_TYPE)
 559:             {
 560:             case N_UNDF:
 561:                 if (!namentry.n_value)
 562:                 {
 563:                     fseek(strfp,
 564:                         stroff + namentry.n_un.n_strx,
 565:                         L_SET);
 566:                     fread(name, sizeof (name), 1, strfp);
 567:                     if (!(module[n].undfnames[nundf]
 568:                         = strdup(name)))
 569:                         goto nosyms;
 570:                     nundf++;
 571:                     if (listnames)
 572:                         pname(n, name, 0);
 573:                 }
 574:                 break;
 575:             case N_TEXT:
 576:                 fseek(strfp, stroff + namentry.n_un.n_strx,
 577:                     L_SET);
 578:                 fread(name, sizeof (name), 1, strfp);
 579:                 if (!(module[n].textnames[ntext]= strdup(name)))
 580:                     goto nosyms;
 581:                 ntext++;
 582:                 if (listnames)
 583:                     pname(n,name,1);
 584:                 break;
 585:             }
 586:         }
 587:     }
 588:     module[n].undfnames[nundf] = "";
 589:     module[n].textnames[ntext] = "";
 590:     fclose(obj);
 591:     fclose(strfp);
 592:     return(0);
 593: }
 594: 
 595: /*
 596:  * pname(n,s,t)
 597:  *	prints global Text(t=1) and Undf(t=0) name s encountered in module n.
 598:  */
 599: pname(n,s,t)
 600: int n,t;
 601: char *s;
 602: {
 603:     if (t)
 604:         fprintf(stderr, "%s: T %s\n", module[n].name, s);
 605:     else
 606:         fprintf(stderr, "%s: U %s\n", module[n].name, s);
 607: }

Defined functions

adlib defined in line 456; used 4 times
getnames defined in line 492; used 1 times
ilikeu defined in line 429; used 2 times
  • in line 421(2)
listmodules defined in line 378; used 2 times
main defined in line 39; never used
metoo defined in line 409; used 2 times
nlibs defined in line 477; used 1 times
pname defined in line 599; used 2 times

Defined variables

libs defined in line 35; used 11 times
listnames defined in line 36; used 4 times
module defined in line 33; used 64 times
optimize defined in line 36; used 10 times

Defined struct's

modstruct defined in line 26; used 4 times
  • in line 185(4)

Defined macros

IN_BASE defined in line 19; used 7 times
LISTWIDTH defined in line 376; used 1 times
MAXSYMLEN defined in line 18; used 1 times
UNCOMMITTED defined in line 20; used 9 times
isarc defined in line 23; used 1 times
  • in line 93
isobj defined in line 21; used 2 times
Last modified: 1994-01-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5438
Valid CSS Valid XHTML 1.0 Strict