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