|
|
1.1 ! root 1: /* Copyright (c) 1980 Regents of the University of California */ ! 2: static char sccsid[] = "@(#)asmain.c 4.8 8/20/80"; ! 3: #include <stdio.h> ! 4: #include <ctype.h> ! 5: #include <signal.h> ! 6: ! 7: #include "as.h" ! 8: #include "assyms.h" ! 9: #include "asexpr.h" ! 10: #include "asscan.h" ! 11: ! 12: #ifdef UNIX ! 13: #define unix_lang_name "VAX/UNIX Assembler V8/20/80 4.8" ! 14: #endif ! 15: ! 16: #ifdef VMS ! 17: #define vms_lang_name "VAX/VMS C Assembler V1.00" ! 18: #endif VMS ! 19: ! 20: /* ! 21: * variables to manage reading the assembly source files ! 22: */ ! 23: char *dotsname; /*the current file name; managed by the parser*/ ! 24: int lineno; /*current line number; managed by the parser*/ ! 25: char **innames; /*names of the files being assembled*/ ! 26: int ninfiles; /*how many interesting files there are*/ ! 27: /* ! 28: * Flags settable from the argv process argument list ! 29: */ ! 30: int silent = 0; /*don't complain about any errors*/ ! 31: int savelabels = 0; /*write the labels to the a.out file*/ ! 32: int d124 = 4; /*default allocate 4 bytes for unknown pointers*/ ! 33: int anyerrs = 0; /*no errors yet*/ ! 34: int orgwarn = 0; /*Bad origins*/ ! 35: int passno = 1; /* current pass*/ ! 36: int jxxxJUMP = 0; /* in jxxxes that branch too far, use jmp instead of brw */ ! 37: int readonlydata = 0; /* initialzed data -> text space */ ! 38: ! 39: #ifdef DEBUG ! 40: int debug = 0; ! 41: int toktrace = 0; ! 42: #endif ! 43: ! 44: int useVM = /*put the temp file in virtual memory*/ ! 45: #ifdef VMS ! 46: 1; /*VMS has virtual memory (duh)*/ ! 47: #endif VMS ! 48: #ifdef UNIX ! 49: 0; ! 50: #endif ! 51: ! 52: char *endcore; /*where to get more symbol space*/ ! 53: ! 54: /* ! 55: * Managers of the a.out file. ! 56: */ ! 57: struct exec hdr; ! 58: #define MAGIC 0407 ! 59: u_long tsize; /* total text size */ ! 60: u_long dsize; /* total data size */ ! 61: u_long datbase; /* base of the data segment */ ! 62: u_long trsize; /* total text relocation size */ ! 63: u_long drsize; /* total data relocation size */ ! 64: ! 65: /* ! 66: * Information about the current segment is accumulated in ! 67: * usedot; the most important information stored is the ! 68: * accumulated size of each of the text and data segments ! 69: * ! 70: * dotp points to the correct usedot expression for the current segment ! 71: */ ! 72: struct exp usedot[NLOC+NLOC]; /* info about all segments */ ! 73: struct exp *dotp; /* data/text location pointer */ ! 74: /* ! 75: * The inter pass temporary file is opened and closed by stdio, but ! 76: * is written to using direct read/write, as the temporary file ! 77: * is composed of buffers exactly BUFSIZ long. ! 78: */ ! 79: FILE *tmpfil; /* interpass communication file */ ! 80: /* ! 81: * a.out is created during the second pass. ! 82: * It is opened by stdio, but is filled with the parallel ! 83: * block I/O library ! 84: */ ! 85: char *outfile = "a.out"; ! 86: FILE *a_out_file; ! 87: off_t a_out_off; /* cumulative offsets for segments */ ! 88: /* ! 89: * The logical files containing the assembled data for each of ! 90: * the text and data segments are ! 91: * managed by the parallel block I/O library. ! 92: * a.out is logically opened in many places at once to ! 93: * receive the assembled data from the various segments as ! 94: * it all trickles in, but is physically opened only once ! 95: * to minimize file overhead. ! 96: */ ! 97: BFILE *usefile[NLOC+NLOC]; /* text/data files */ ! 98: BFILE *txtfil; /* current text/data file */ ! 99: /* ! 100: * Relocation information is accumulated seperately for each ! 101: * segment. This is required by the old loader (from BTL), ! 102: * but not by the new loader (Bill Joy). ! 103: * ! 104: * However, the size of the relocation information can not be computed ! 105: * during or after the 1st pass because the ''absoluteness' of values ! 106: * is unknown until all locally declared symbols have been seen. ! 107: * Thus, the size of the relocation information is only ! 108: * known after the second pass is finished. ! 109: * This obviates the use of the block I/O ! 110: * library, which requires knowing the exact offsets in a.out. ! 111: * ! 112: * So, we save the relocation information internally (we don't ! 113: * go to internal files to minimize overhead). ! 114: * ! 115: * Empirically, we studied 259 files composing the system, ! 116: * two compilers and a compiler generator: (all of which have ! 117: * fairly large source files) ! 118: * ! 119: * Number of files = 259 ! 120: * Number of non zero text reloc files: 233 ! 121: * Number of non zero data reloc files: 53 ! 122: * Average text relocation = 889 ! 123: * Average data relocation = 346 ! 124: * Number of files > BUFSIZ text relocation = 71 ! 125: * Number of files > BUFSIZ data relocation = 6 ! 126: * ! 127: * For compiled C code, there is usually one text segment and two ! 128: * data segments; we see that allocating our own buffers and ! 129: * doing our internal handling of relocation information will, ! 130: * on the average, not use more memory than taken up by the buffers ! 131: * allocated for doing file I/O in parallel to a number of file. ! 132: * ! 133: * If we are assembling with the -V option, we ! 134: * use the left over token buffers from the 2nd pass, ! 135: * otherwise, we create our own. ! 136: * ! 137: * When the 2nd pass is complete, closeoutrel flushes the token ! 138: * buffers out to a BFILE. ! 139: * ! 140: * The internals to relbufdesc are known only in assyms.c ! 141: * ! 142: * outrel constructs the relocation information. ! 143: * closeoutrel flushes the relocation information to relfil. ! 144: */ ! 145: struct relbufdesc *rusefile[NLOC+NLOC]; ! 146: struct relbufdesc *relfil; /* un concatnated relocation info */ ! 147: BFILE *relocfile; /* concatnated relocation info */ ! 148: /* ! 149: * Once the relocation information has been written, ! 150: * we can write out the symbol table using the Block I/O ! 151: * mechanisms, as we once again know the offsets into ! 152: * the a.out file. ! 153: * ! 154: * We use relfil to output the symbol table information. ! 155: */ ! 156: ! 157: char *tmpdirprefix = ! 158: #ifdef UNIX ! 159: "/tmp/"; ! 160: #else VMS ! 161: "/usr/tmp/"; ! 162: #endif ! 163: ! 164: #define TMP_SUFFIX "asXXXXXX" ! 165: char tmpn1[TNAMESIZE]; ! 166: ! 167: int delexit(); ! 168: ! 169: main(argc, argv) ! 170: int argc; ! 171: char **argv; ! 172: { ! 173: ! 174: tmpn1[0] = 0; ! 175: endcore = (char *)sbrk(0); ! 176: ! 177: argprocess(argc, argv); /* process argument lists */ ! 178: if (anyerrs) exit(1); ! 179: ! 180: initialize(); ! 181: zeroorigins(); /* set origins to zero */ ! 182: zerolocals(); /* fix local label counters */ ! 183: ! 184: i_pass1(); /* open temp files, etc */ ! 185: pass1(); /* first pass through .s files */ ! 186: testlocals(); /* check for undefined locals */ ! 187: if (anyerrs) delexit(); ! 188: ! 189: pass1_5(); /* resolve jxxx */ ! 190: if (anyerrs) delexit(); ! 191: ! 192: open_a_out(); /* open a.out */ ! 193: roundsegments(); /* round segments to FW */ ! 194: build_hdr(); /* build initial header, and output */ ! 195: ! 196: i_pass2(); /* reopen temporary file, etc */ ! 197: pass2(); /* second pass through the virtual .s */ ! 198: if (anyerrs) delexit(); ! 199: ! 200: fillsegments(); /* fill segments with 0 to FW */ ! 201: reloc_syms(); /* dump relocation and symbol table */ ! 202: ! 203: delete(); /* remove tmp file */ ! 204: bflush(); /* close off block I/O view of a.out */ ! 205: fix_a_out(); /* add in text and data reloc counts */ ! 206: ! 207: if (anyerrs == 0 && orgwarn) ! 208: yyerror("Caution: absolute origins.\n"); ! 209: exit(anyerrs != 0); ! 210: } /*end of UNIX main*/ ! 211: ! 212: argprocess(argc, argv) ! 213: int argc; ! 214: char *argv[]; ! 215: { ! 216: register char *cp; ! 217: ! 218: ninfiles = 0; ! 219: silent = 0; ! 220: #ifdef DEBUG ! 221: debug = 0; ! 222: #endif ! 223: innames = (char **)ClearCalloc(argc+1, sizeof (innames[0])); ! 224: dotsname = "<argv error>"; ! 225: while (argc > 1) { ! 226: if (argv[1][0] != '-') ! 227: innames[ninfiles++] = argv[1]; ! 228: else { ! 229: cp = argv[1] + 1; ! 230: /* ! 231: * We can throw away single minus signs, so ! 232: * that make scripts for the PDP 11 assembler work ! 233: * on this assembler too ! 234: */ ! 235: while (*cp){ ! 236: switch(*cp++){ ! 237: default: ! 238: yyerror("Unknown flag: %c", *--cp); ! 239: cp++; ! 240: break; ! 241: case 'd': ! 242: d124 = *cp++ - '0'; ! 243: if ( (d124 != 1) && (d124 != 2) && ! 244: (d124 != 4)){ ! 245: yyerror("-d[124] only"); ! 246: exit(1); ! 247: } ! 248: break; ! 249: case 'o': ! 250: if (argc < 3){ ! 251: yyerror("-o what???"); ! 252: exit(1); ! 253: } ! 254: outfile = argv[2]; ! 255: bumpone: ! 256: argc -= 2; ! 257: argv += 2; ! 258: goto nextarg; ! 259: ! 260: case 't': ! 261: if (argc < 3){ ! 262: yyerror("-t what???"); ! 263: exit(1); ! 264: } ! 265: tmpdirprefix = argv[2]; ! 266: goto bumpone; ! 267: ! 268: case 'V': ! 269: useVM = 1; ! 270: break; ! 271: case 'W': ! 272: silent = 1; ! 273: break; ! 274: case 'L': ! 275: savelabels = 1; ! 276: break; ! 277: case 'J': ! 278: jxxxJUMP = 1; ! 279: break; ! 280: #ifdef DEBUG ! 281: case 'D': ! 282: debug = 1; ! 283: break; ! 284: case 'T': ! 285: toktrace = 1; ! 286: break; ! 287: #endif ! 288: case 'R': ! 289: readonlydata = 1; ! 290: break; ! 291: } /*end of the switch*/ ! 292: } /*end of pulling out all arguments*/ ! 293: } /*end of a flag argument*/ ! 294: --argc; ++argv; ! 295: nextarg:; ! 296: } ! 297: /* innames[ninfiles] = 0; */ ! 298: } ! 299: ! 300: initialize() ! 301: { ! 302: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 303: signal(SIGINT, delexit); ! 304: /* ! 305: * Install symbols in the table ! 306: */ ! 307: symtabinit(); ! 308: syminstall(); ! 309: /* ! 310: * Build the expression parser accelerator token sets ! 311: */ ! 312: buildtokensets(); ! 313: } ! 314: ! 315: zeroorigins() ! 316: { ! 317: register int locindex; ! 318: /* ! 319: * Mark usedot: the first NLOC slots are for named text segments, ! 320: * the next for named data segments. ! 321: */ ! 322: for (locindex = 0; locindex < NLOC; locindex++){ ! 323: usedot[locindex].e_xtype = XTEXT; ! 324: usedot[NLOC + locindex].e_xtype = XDATA; ! 325: usedot[locindex].e_xvalue = 0; ! 326: usedot[NLOC + locindex].e_xvalue = 0; ! 327: usedot[locindex].e_yvalue = 0; ! 328: usedot[NLOC + locindex].e_yvalue = 0; ! 329: } ! 330: } ! 331: ! 332: zerolocals() ! 333: { ! 334: register int i; ! 335: ! 336: for (i = 0; i <= 9; i++) { ! 337: lgensym[i] = 1; ! 338: genref[i] = 0; ! 339: } ! 340: } ! 341: ! 342: i_pass1() ! 343: { ! 344: if (useVM == 0){ ! 345: strcat(tmpn1, tmpdirprefix); ! 346: if (tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ! 347: strcat(tmpn1, "/"); ! 348: strcat(tmpn1, TMP_SUFFIX); ! 349: mktemp(tmpn1); ! 350: tmpfil = fopen(tmpn1, "w"); ! 351: if (tmpfil==NULL) { ! 352: yyerror("Bad pass 1 temporary file for writing %s", tmpn1); ! 353: delexit(); ! 354: } ! 355: } ! 356: ! 357: inittmpfile(); ! 358: initijxxx(); ! 359: } ! 360: ! 361: pass1() ! 362: { ! 363: register int i; ! 364: ! 365: passno = 1; ! 366: dotp = &usedot[0]; ! 367: txtfil = (BFILE *)0; ! 368: relfil = (struct relbufdesc *)0; ! 369: ! 370: if (ninfiles == 0){ /*take the input from stdin directly*/ ! 371: lineno = 1; ! 372: dotsname = "<stdin>"; ! 373: ! 374: yyparse(); ! 375: } else { /*we have the names tanked*/ ! 376: for (i = 0; i < ninfiles; i++){ ! 377: new_dot_s(innames[i]); ! 378: if (freopen(innames[i], "r", stdin) == NULL) { ! 379: yyerror( "Can't open source file %s\n", ! 380: innames[i]); ! 381: exit(2); ! 382: } ! 383: /* stdio is NOT used to read the input characters */ ! 384: /* we use read directly, into our own buffers */ ! 385: yyparse(); ! 386: } ! 387: } ! 388: ! 389: closetmpfile(); /*kick out the last buffered intermediate text*/ ! 390: } ! 391: ! 392: testlocals() ! 393: { ! 394: register int i; ! 395: for (i = 0; i <= 9; i++) { ! 396: if (genref[i]) ! 397: yyerror("Reference to undefined local label %df", i); ! 398: lgensym[i] = 1; ! 399: genref[i] = 0; ! 400: } ! 401: } ! 402: ! 403: pass1_5() ! 404: { ! 405: sortsymtab(); ! 406: #ifdef DEBUG ! 407: if (debug) dumpsymtab(); ! 408: #endif ! 409: jxxxfix(); ! 410: #ifdef DEBUG ! 411: if (debug) dumpsymtab(); ! 412: #endif ! 413: } ! 414: ! 415: open_a_out() ! 416: { ! 417: /* ! 418: * Open up the a.out file now, and get set to build ! 419: * up offsets into it for all of the various text,data ! 420: * text relocation and data relocation segments. ! 421: */ ! 422: a_out_file = fopen(outfile, "w"); ! 423: if (a_out_file == NULL) { ! 424: yyerror("Cannot create %s", outfile); ! 425: delexit(); ! 426: } ! 427: biofd = a_out_file->_file; ! 428: a_out_off = 0; ! 429: } ! 430: ! 431: roundsegments() ! 432: { ! 433: register int locindex; ! 434: register long v; ! 435: /* ! 436: * round and assign text segment origins ! 437: * the exec header always goes in usefile[0] ! 438: */ ! 439: tsize = 0; ! 440: for (locindex=0; locindex<NLOC; locindex++) { ! 441: v = round(usedot[locindex].e_xvalue, FW); ! 442: usedot[locindex].e_xvalue = tsize; ! 443: if ((locindex == 0) || (v != 0) ){ ! 444: usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE)); ! 445: bopen(usefile[locindex], a_out_off); ! 446: if (locindex == 0) ! 447: a_out_off = sizeof (struct exec); ! 448: } else { ! 449: usefile[locindex] = (BFILE *)-1; ! 450: } ! 451: tsize += v; ! 452: a_out_off += v; ! 453: } ! 454: /* ! 455: * Round and assign data segment origins. ! 456: */ ! 457: datbase = round(tsize, FW); ! 458: for (locindex=0; locindex<NLOC; locindex++) { ! 459: v = round(usedot[NLOC+locindex].e_xvalue, FW); ! 460: usedot[NLOC+locindex].e_xvalue = datbase + dsize; ! 461: if (v != 0){ ! 462: usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE)); ! 463: bopen(usefile[NLOC + locindex], a_out_off); ! 464: } else { ! 465: usefile[NLOC + locindex] = (BFILE *)-1; ! 466: } ! 467: dsize += v; ! 468: a_out_off += v; ! 469: } ! 470: /* ! 471: * Assign final values to symbols ! 472: */ ! 473: hdr.a_bss = dsize; ! 474: freezesymtab(); /* this touches hdr.a_bss */ ! 475: stabfix(); ! 476: /* ! 477: * Set up the relocation information "files" to ! 478: * be zero; outrel takes care of the rest ! 479: */ ! 480: for (locindex = 0; locindex < NLOC + NLOC; locindex++){ ! 481: rusefile[locindex] = (struct relbufdesc *)0; ! 482: } ! 483: } ! 484: ! 485: build_hdr() ! 486: { ! 487: /* ! 488: * Except for the text and data relocation sizes, ! 489: * calculate the final values for the header ! 490: * ! 491: * Write out the initial copy; we to come ! 492: * back later and patch up a_trsize and a_drsize, ! 493: * and overwrite this first version of the header. ! 494: */ ! 495: hdr.a_magic = MAGIC; ! 496: hdr.a_text = tsize; ! 497: hdr.a_data = dsize; ! 498: hdr.a_bss -= dsize; ! 499: hdr.a_syms = sizesymtab(); /* Does not include string pool length */ ! 500: hdr.a_entry = 0; ! 501: hdr.a_trsize = 0; ! 502: hdr.a_drsize = 0; ! 503: ! 504: bwrite((char *)&hdr, sizeof(hdr), usefile[0]); ! 505: } ! 506: ! 507: i_pass2() ! 508: { ! 509: if (useVM == 0) { ! 510: fclose(tmpfil); ! 511: tmpfil = fopen(tmpn1, "r"); ! 512: if (tmpfil==NULL) { ! 513: yyerror("Bad pass 2 temporary file for reading %s", tmpn1); ! 514: delexit(); ! 515: } ! 516: } ! 517: } ! 518: ! 519: pass2() ! 520: { ! 521: #ifdef DEBUG ! 522: if (debug) ! 523: printf("\n\n\n\t\tPASS 2\n\n\n\n"); ! 524: #endif DEBUG ! 525: passno = 2; ! 526: lineno = 1; ! 527: dotp = &usedot[0]; ! 528: txtfil = usefile[0]; /* already opened (always!) */ ! 529: relfil = 0; /* outrel takes care of the rest */ ! 530: initoutrel(); ! 531: ! 532: inittmpfile(); ! 533: ! 534: yyparse(); ! 535: ! 536: closetmpfile(); ! 537: } ! 538: ! 539: fillsegments() ! 540: { ! 541: int locindex; ! 542: /* ! 543: * Round text and data segments to FW by appending zeros ! 544: */ ! 545: for (locindex = 0; locindex < NLOC + NLOC; locindex++) { ! 546: if (usefile[locindex]) { ! 547: txtfil = usefile[locindex]; ! 548: dotp = &usedot[locindex]; ! 549: while (usedot[locindex].e_xvalue & FW) ! 550: outb(0); ! 551: } ! 552: } ! 553: } ! 554: ! 555: reloc_syms() ! 556: { ! 557: u_long closerelfil(); ! 558: /* ! 559: * Move the relocation information to a.out ! 560: * a_out_off is the offset so far: ! 561: * exec + text segments + data segments ! 562: */ ! 563: relocfile = (BFILE *)Calloc(1,sizeof(BFILE)); ! 564: bopen(relocfile, a_out_off); ! 565: a_out_off += closeoutrel(relocfile); ! 566: ! 567: hdr.a_trsize = trsize; ! 568: hdr.a_drsize = drsize; ! 569: if (readonlydata) { ! 570: hdr.a_text += hdr.a_data; ! 571: hdr.a_data = 0; ! 572: hdr.a_trsize += hdr.a_drsize; ! 573: hdr.a_drsize = 0; ! 574: } ! 575: /* ! 576: * Output the symbol table ! 577: * and if FLEXNAMES is set, the string pool ! 578: */ ! 579: symwrite(relocfile); ! 580: } ! 581: ! 582: fix_a_out() ! 583: { ! 584: if (lseek(a_out_file->_file, 0L, 0) < 0) ! 585: yyerror("Reposition for header rewrite fails"); ! 586: if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0) ! 587: yyerror("Rewrite of header fails"); ! 588: } ! 589: ! 590: delexit() ! 591: { ! 592: delete(); ! 593: if (passno == 2){ ! 594: unlink(outfile); ! 595: } ! 596: exit(1); ! 597: } ! 598: ! 599: delete() ! 600: { ! 601: if (useVM == 0 || tmpn1[0]) ! 602: unlink(tmpn1); ! 603: } ! 604: ! 605: sawabort() ! 606: { ! 607: char *fillinbuffer(); ! 608: while (fillinbuffer() != (char *)0) ! 609: continue; ! 610: delete(); ! 611: exit(1); /*although the previous pass will also exit non zero*/ ! 612: } ! 613: ! 614: panic(fmt, a1, a2, a3, a4) ! 615: char *fmt; ! 616: /*VARARGS 1*/ ! 617: { ! 618: yyerror("Assembler panic: bad internal data structure."); ! 619: yyerror(fmt, a1, a2, a3, a4); ! 620: delete(); ! 621: abort(); ! 622: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.