132434Sbostic /* 232434Sbostic * Copyright (c) 1982 Regents of the University of California 332434Sbostic */ 432434Sbostic #ifndef lint 532434Sbostic static char sccsid[] = "@(#)asmain.c 4.13 6/30/83"; 632434Sbostic #endif not lint 732434Sbostic 832434Sbostic #include <stdio.h> 932434Sbostic #include <ctype.h> 1032434Sbostic #include <signal.h> 1132434Sbostic 1232434Sbostic #include "as.h" 1332434Sbostic #include "assyms.h" 1432434Sbostic #include "asscan.h" 1532434Sbostic #include "asexpr.h" 1632434Sbostic 1732434Sbostic #define unix_lang_name "VAX/UNIX Assembler V6/30/83 4.13" 1832434Sbostic /* 1932434Sbostic * variables to manage reading the assembly source files 2032434Sbostic */ 2132434Sbostic char *dotsname; /*the current file name; managed by the parser*/ 2232434Sbostic int lineno; /*current line number; managed by the parser*/ 2332434Sbostic char **innames; /*names of the files being assembled*/ 2432434Sbostic int ninfiles; /*how many interesting files there are*/ 2532434Sbostic FILE *source; /*current source file (for listing) */ 2632434Sbostic char layout[400]; /*layout bytes */ 2732434Sbostic char *layoutpos = layout; /*layout position in listfile */ 2832434Sbostic int ind = 0; /*innames in-index: 0..minfiles */ 2932434Sbostic int endofsource = 0; 3032434Sbostic long sourcepos; 3132434Sbostic /* 3232434Sbostic * Flags settable from the argv process argument list 3332434Sbostic */ 3432434Sbostic int silent = 0; /*don't complain about any errors*/ 3532434Sbostic int savelabels = 0; /*write the labels to the a.out file*/ 3632434Sbostic int d124 = 4; /*default allocate 4 bytes for unknown pointers*/ 3732434Sbostic int anyerrs = 0; /*no errors yet*/ 3832434Sbostic int anywarnings=0; /*no warnings yet*/ 3932434Sbostic int orgwarn = 0; /*Bad origins*/ 4032434Sbostic int passno = 1; /* current pass*/ 4132434Sbostic int jxxxJUMP = 0; /* in jxxxes that branch too far, use jmp instead of brw */ 4232434Sbostic int readonlydata = 0; /* initialzed data -> text space */ 4332434Sbostic int liston = 0; /* don't produce listing */ 4432434Sbostic 4532434Sbostic 4632434Sbostic #ifdef DEBUG 4732434Sbostic int debug = 0; 4832434Sbostic int toktrace = 0; 4932434Sbostic #endif 5032434Sbostic 5132434Sbostic int useVM = 0; 5232434Sbostic 5332434Sbostic char *endcore; /*where to get more symbol space*/ 5432434Sbostic 5532434Sbostic /* 5632434Sbostic * Managers of the a.out file. 5732434Sbostic */ 5832434Sbostic struct exec hdr; 5932434Sbostic #define MAGIC 0407 6032434Sbostic u_long tsize; /* total text size */ 6132434Sbostic u_long dsize; /* total data size */ 6232434Sbostic u_long datbase; /* base of the data segment */ 6332434Sbostic u_long trsize; /* total text relocation size */ 6432434Sbostic u_long drsize; /* total data relocation size */ 6532434Sbostic 6632434Sbostic /* 6732434Sbostic * Information about the current segment is accumulated in 6832434Sbostic * usedot; the most important information stored is the 6932434Sbostic * accumulated size of each of the text and data segments 7032434Sbostic * 7132434Sbostic * dotp points to the correct usedot expression for the current segment 7232434Sbostic */ 7332434Sbostic struct exp usedot[NLOC+NLOC]; /* info about all segments */ 7432434Sbostic struct exp *dotp; /* data/text location pointer */ 7532434Sbostic /* 7632434Sbostic * The inter pass temporary token file is opened and closed by stdio, but 7732434Sbostic * is written to using direct read/write, as the temporary file 7832434Sbostic * is composed of buffers exactly BUFSIZ long. 7932434Sbostic */ 8032434Sbostic FILE *tokfile; /* interpass communication file */ 8132434Sbostic char tokfilename[TNAMESIZE]; 8232434Sbostic /* 8332434Sbostic * The string file is the string table 8432434Sbostic * cat'ed to the end of the built up a.out file 8532434Sbostic */ 8632434Sbostic FILE *strfile; /* interpass string file */ 8732434Sbostic char strfilename[TNAMESIZE]; 8832434Sbostic int strfilepos = 0; /* position within the string file */ 8932434Sbostic /* 9032434Sbostic * a.out is created during the second pass. 9132434Sbostic * It is opened by stdio, but is filled with the parallel 9232434Sbostic * block I/O library 9332434Sbostic */ 9432434Sbostic char *outfile = "a.out"; 9532434Sbostic FILE *a_out_file; 9632434Sbostic off_t a_out_off; /* cumulative offsets for segments */ 9732434Sbostic /* 9832434Sbostic * The logical files containing the assembled data for each of 9932434Sbostic * the text and data segments are 10032434Sbostic * managed by the parallel block I/O library. 10132434Sbostic * a.out is logically opened in many places at once to 10232434Sbostic * receive the assembled data from the various segments as 10332434Sbostic * it all trickles in, but is physically opened only once 10432434Sbostic * to minimize file overhead. 10532434Sbostic */ 10632434Sbostic BFILE *usefile[NLOC+NLOC]; /* text/data files */ 10732434Sbostic BFILE *txtfil; /* current text/data file */ 10832434Sbostic /* 10932434Sbostic * Relocation information is accumulated seperately for each 11032434Sbostic * segment. This is required by the old loader (from BTL), 11132434Sbostic * but not by the new loader (Bill Joy). 11232434Sbostic * 11332434Sbostic * However, the size of the relocation information can not be computed 11432434Sbostic * during or after the 1st pass because the ''absoluteness' of values 11532434Sbostic * is unknown until all locally declared symbols have been seen. 11632434Sbostic * Thus, the size of the relocation information is only 11732434Sbostic * known after the second pass is finished. 11832434Sbostic * This obviates the use of the block I/O 11932434Sbostic * library, which requires knowing the exact offsets in a.out. 12032434Sbostic * 12132434Sbostic * So, we save the relocation information internally (we don't 12232434Sbostic * go to internal files to minimize overhead). 12332434Sbostic * 12432434Sbostic * Empirically, we studied 259 files composing the system, 12532434Sbostic * two compilers and a compiler generator: (all of which have 12632434Sbostic * fairly large source files) 12732434Sbostic * 12832434Sbostic * Number of files = 259 12932434Sbostic * Number of non zero text reloc files: 233 13032434Sbostic * Number of non zero data reloc files: 53 13132434Sbostic * Average text relocation = 889 13232434Sbostic * Average data relocation = 346 13332434Sbostic * Number of files > BUFSIZ text relocation = 71 13432434Sbostic * Number of files > BUFSIZ data relocation = 6 13532434Sbostic * 13632434Sbostic * For compiled C code, there is usually one text segment and two 13732434Sbostic * data segments; we see that allocating our own buffers and 13832434Sbostic * doing our internal handling of relocation information will, 13932434Sbostic * on the average, not use more memory than taken up by the buffers 14032434Sbostic * allocated for doing file I/O in parallel to a number of file. 14132434Sbostic * 14232434Sbostic * If we are assembling with the -V option, we 14332434Sbostic * use the left over token buffers from the 2nd pass, 14432434Sbostic * otherwise, we create our own. 14532434Sbostic * 14632434Sbostic * When the 2nd pass is complete, closeoutrel flushes the token 14732434Sbostic * buffers out to a BFILE. 14832434Sbostic * 14932434Sbostic * The internals to relbufdesc are known only in assyms.c 15032434Sbostic * 15132434Sbostic * outrel constructs the relocation information. 15232434Sbostic * closeoutrel flushes the relocation information to relfil. 15332434Sbostic */ 15432434Sbostic struct relbufdesc *rusefile[NLOC+NLOC]; 15532434Sbostic struct relbufdesc *relfil; /* un concatnated relocation info */ 15632434Sbostic BFILE *relocfile; /* concatnated relocation info */ 15732434Sbostic /* 15832434Sbostic * Once the relocation information has been written, 15932434Sbostic * we can write out the symbol table using the Block I/O 16032434Sbostic * mechanisms, as we once again know the offsets into 16132434Sbostic * the a.out file. 16232434Sbostic * 16332434Sbostic * We use relfil to output the symbol table information. 16432434Sbostic */ 16532434Sbostic char *tmpdirprefix = "/tmp/"; 16632434Sbostic int delexit(); 16732434Sbostic 16832434Sbostic main(argc, argv) 16932434Sbostic int argc; 17032434Sbostic char **argv; 17132434Sbostic { 17232434Sbostic char *sbrk(); 17332434Sbostic 17432434Sbostic tokfilename[0] = 0; 17532434Sbostic strfilename[0] = 0; 17632434Sbostic endcore = sbrk(0); 17732434Sbostic 17832434Sbostic argprocess(argc, argv); /* process argument lists */ 17932434Sbostic if (anyerrs) exit(1); 18032434Sbostic 18132434Sbostic initialize(); 18232434Sbostic zeroorigins(); /* set origins to zero */ 18332434Sbostic zerolocals(); /* fix local label counters */ 18432434Sbostic 18532434Sbostic i_pass1(); /* open temp files, etc */ 18632434Sbostic pass1(); /* first pass through .s files */ 18732434Sbostic testlocals(); /* check for undefined locals */ 18832434Sbostic if (anyerrs) delexit(); 18932434Sbostic 19032434Sbostic pass1_5(); /* resolve jxxx */ 19132434Sbostic if (anyerrs) delexit(); 19232434Sbostic 19332434Sbostic open_a_out(); /* open a.out */ 19432434Sbostic roundsegments(); /* round segments to FW */ 19532434Sbostic build_hdr(); /* build initial header, and output */ 19632434Sbostic 19732434Sbostic i_pass2(); /* reopen temporary file, etc */ 19832434Sbostic pass2(); /* second pass through the virtual .s */ 19932434Sbostic if (anyerrs) delexit(); 20032434Sbostic 20132434Sbostic fillsegments(); /* fill segments with 0 to FW */ 20232434Sbostic reloc_syms(); /* dump relocation and symbol table */ 20332434Sbostic 20432434Sbostic delete(); /* remove tmp file */ 20532434Sbostic bflush(); /* close off block I/O view of a.out */ 20632434Sbostic fix_a_out(); /* add in text and data reloc counts */ 20732434Sbostic 20832434Sbostic if (anyerrs == 0 && orgwarn) 20932434Sbostic yyerror("Caution: absolute origins.\n"); 21032434Sbostic 21132434Sbostic exit(anyerrs != 0); 21232434Sbostic } 21332434Sbostic 21432434Sbostic argprocess(argc, argv) 21532434Sbostic int argc; 21632434Sbostic char *argv[]; 21732434Sbostic { 21832434Sbostic register char *cp; 21932434Sbostic 22032434Sbostic ninfiles = 0; 22132434Sbostic silent = 0; 22232434Sbostic #ifdef DEBUG 22332434Sbostic debug = 0; 22432434Sbostic #endif 22532434Sbostic innames = (char **)ClearCalloc(argc+1, sizeof (innames[0])); 22632434Sbostic dotsname = "<argv error>"; 22732434Sbostic while (argc > 1) { 22832434Sbostic if (argv[1][0] != '-') 22932434Sbostic innames[ninfiles++] = argv[1]; 23032434Sbostic else { 23132434Sbostic cp = argv[1] + 1; 23232434Sbostic /* 23332434Sbostic * We can throw away single minus signs, so 23432434Sbostic * that make scripts for the PDP 11 assembler work 23532434Sbostic * on this assembler too 23632434Sbostic */ 23732434Sbostic while (*cp){ 23832434Sbostic switch(*cp++){ 23932434Sbostic default: 24032434Sbostic yyerror("Unknown flag: %c", *--cp); 24132434Sbostic cp++; 24232434Sbostic break; 24332434Sbostic case 'v': 24432434Sbostic selfwhat(stdout); 24532434Sbostic exit(1); 24632434Sbostic case 'd': 24732434Sbostic d124 = *cp++ - '0'; 24832434Sbostic if ( (d124 != 1) && (d124 != 2) && 24932434Sbostic (d124 != 4)){ 25032434Sbostic yyerror("-d[124] only"); 25132434Sbostic exit(1); 25232434Sbostic } 25332434Sbostic break; 25432434Sbostic case 'P': 25532434Sbostic liston = 1; 25632434Sbostic listfile = stdout; 25732434Sbostic break; 25832434Sbostic case 'o': 25932434Sbostic if (argc < 3){ 26032434Sbostic yyerror("-o what???"); 26132434Sbostic exit(1); 26232434Sbostic } 26332434Sbostic outfile = argv[2]; 26432434Sbostic bumpone: 26532434Sbostic argc -= 2; 26632434Sbostic argv += 2; 26732434Sbostic goto nextarg; 26832434Sbostic 26932434Sbostic case 't': 27032434Sbostic if (argc < 3){ 27132434Sbostic yyerror("-t what???"); 27232434Sbostic exit(1); 27332434Sbostic } 27432434Sbostic tmpdirprefix = argv[2]; 27532434Sbostic goto bumpone; 27632434Sbostic 27732434Sbostic case 'V': 27832434Sbostic useVM = 1; 27932434Sbostic break; 28032434Sbostic case 'W': 28132434Sbostic silent = 1; 28232434Sbostic break; 28332434Sbostic case 'L': 28432434Sbostic savelabels = 1; 28532434Sbostic break; 28632434Sbostic case 'J': 28732434Sbostic jxxxJUMP = 1; 28832434Sbostic break; 28932434Sbostic #ifdef DEBUG 29032434Sbostic case 'D': 29132434Sbostic debug = 1; 29232434Sbostic break; 29332434Sbostic case 'T': 29432434Sbostic toktrace = 1; 29532434Sbostic break; 29632434Sbostic #endif 29732434Sbostic case 'R': 29832434Sbostic readonlydata = 1; 29932434Sbostic break; 30032434Sbostic } /*end of the switch*/ 30132434Sbostic } /*end of pulling out all arguments*/ 30232434Sbostic } /*end of a flag argument*/ 30332434Sbostic --argc; ++argv; 30432434Sbostic nextarg:; 30532434Sbostic } 30632434Sbostic /* innames[ninfiles] = 0; */ 30732434Sbostic } 30832434Sbostic /* 30932434Sbostic * poke through the data space and find all sccs identifiers. 31032434Sbostic * We assume: 31132434Sbostic * a) that extern char **environ; is the first thing in the bss 31232434Sbostic * segment (true, if one is using the new version of cmgt.crt0.c) 31332434Sbostic * b) that the sccsid's have not been put into text space. 31432434Sbostic */ 31532434Sbostic selfwhat(place) 31632434Sbostic FILE *place; 31732434Sbostic { 31832434Sbostic extern char **environ; 31932434Sbostic register char *ub; 32032434Sbostic register char *cp; 32132434Sbostic char *sbrk(); 32232434Sbostic 32332434Sbostic for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){ 32432434Sbostic if (cp[0] != '@') continue; 32532434Sbostic if (cp[1] != '(') continue; 32632434Sbostic if (cp[2] != '#') continue; 32732434Sbostic if (cp[3] != ')') continue; 32832434Sbostic fputc('\t', place); 32932434Sbostic for (cp += 4; cp < ub; cp++){ 33032434Sbostic if (*cp == 0) break; 33132434Sbostic if (*cp == '>') break; 33232434Sbostic if (*cp == '\n') break; 33332434Sbostic fputc(*cp, place); 33432434Sbostic } 33532434Sbostic fputc('\n', place); 33632434Sbostic } 33732434Sbostic } 33832434Sbostic 33932434Sbostic initialize() 34032434Sbostic { 34132434Sbostic if (signal(SIGINT, SIG_IGN) != SIG_IGN) 34232434Sbostic signal(SIGINT, delexit); 34332434Sbostic /* 34432434Sbostic * Install symbols in the table 34532434Sbostic */ 34632434Sbostic symtabinit(); 34732434Sbostic syminstall(); 34832434Sbostic /* 34932434Sbostic * Build the expression parser accelerator token sets 35032434Sbostic */ 35132434Sbostic buildtokensets(); 35232434Sbostic } 35332434Sbostic 35432434Sbostic zeroorigins() 35532434Sbostic { 35632434Sbostic register int locindex; 35732434Sbostic /* 35832434Sbostic * Mark usedot: the first NLOC slots are for named text segments, 35932434Sbostic * the next for named data segments. 36032434Sbostic */ 36132434Sbostic for (locindex = 0; locindex < NLOC; locindex++){ 36232434Sbostic usedot[locindex].e_xtype = XTEXT; 36332434Sbostic usedot[NLOC + locindex].e_xtype = XDATA; 36432434Sbostic usedot[locindex].e_xvalue = 0; 36532434Sbostic usedot[NLOC + locindex].e_xvalue = 0; 36632434Sbostic } 36732434Sbostic } 36832434Sbostic 36932434Sbostic zerolocals() 37032434Sbostic { 37132434Sbostic register int i; 37232434Sbostic 37332434Sbostic for (i = 0; i <= 9; i++) { 37432434Sbostic lgensym[i] = 1; 37532434Sbostic genref[i] = 0; 37632434Sbostic } 37732434Sbostic } 37832434Sbostic 37932434Sbostic i_pass1() 38032434Sbostic { 38132434Sbostic FILE *tempopen(); 38232434Sbostic if (useVM == 0) 38332434Sbostic tokfile = tempopen(tokfilename, "T"); 38432434Sbostic strfile = tempopen(strfilename, "S"); 38532434Sbostic /* 38632434Sbostic * write out the string length. 38732434Sbostic * This will be overwritten when the 38832434Sbostic * strings are tacked onto the growing a.out file 38932434Sbostic */ 39032434Sbostic strfilepos = sizeof(int); 39132434Sbostic fwrite(&strfilepos, sizeof(int), 1, strfile); 39232434Sbostic 39332434Sbostic inittokfile(); 39432434Sbostic initijxxx(); 39532434Sbostic } 39632434Sbostic 39732434Sbostic FILE *tempopen(tname, part) 39832434Sbostic char *tname; 39932434Sbostic char *part; 40032434Sbostic { 40132434Sbostic FILE *file; 402*32435Sbostic (void)sprintf(tname, "%s%sas%s%05d", 40332434Sbostic tmpdirprefix, 40432434Sbostic (tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : 0, 40532434Sbostic part, 40632434Sbostic getpid()); 40732434Sbostic file = fopen(tname, "w"); 40832434Sbostic if (file == NULL) { 40932434Sbostic yyerror("Bad pass 1 temporary file for writing %s", tname); 41032434Sbostic delexit(); 41132434Sbostic } 41232434Sbostic return(file); 41332434Sbostic } 41432434Sbostic 41532434Sbostic pass1() 41632434Sbostic { 41732434Sbostic register int i; 41832434Sbostic 41932434Sbostic passno = 1; 42032434Sbostic dotp = &usedot[0]; 42132434Sbostic txtfil = (BFILE *)0; 42232434Sbostic relfil = (struct relbufdesc *)0; 42332434Sbostic 42432434Sbostic if (ninfiles == 0){ /*take the input from stdin directly*/ 42532434Sbostic lineno = 1; 42632434Sbostic dotsname = "<stdin>"; 42732434Sbostic 42832434Sbostic yyparse(); 42932434Sbostic } else { /*we have the names tanked*/ 43032434Sbostic for (i = 0; i < ninfiles; i++){ 43132434Sbostic new_dot_s(innames[i]); 43232434Sbostic if (freopen(innames[i], "r", stdin) == NULL) { 43332434Sbostic yyerror( "Can't open source file %s\n", 43432434Sbostic innames[i]); 43532434Sbostic exit(2); 43632434Sbostic } 43732434Sbostic /* stdio is NOT used to read the input characters */ 43832434Sbostic /* we use read directly, into our own buffers */ 43932434Sbostic yyparse(); 44032434Sbostic } 44132434Sbostic } 44232434Sbostic 44332434Sbostic closetokfile(); /*kick out the last buffered intermediate text*/ 44432434Sbostic } 44532434Sbostic 44632434Sbostic testlocals() 44732434Sbostic { 44832434Sbostic register int i; 44932434Sbostic for (i = 0; i <= 9; i++) { 45032434Sbostic if (genref[i]) 45132434Sbostic yyerror("Reference to undefined local label %df", i); 45232434Sbostic lgensym[i] = 1; 45332434Sbostic genref[i] = 0; 45432434Sbostic } 45532434Sbostic } 45632434Sbostic 45732434Sbostic pass1_5() 45832434Sbostic { 45932434Sbostic sortsymtab(); 46032434Sbostic #ifdef DEBUG 46132434Sbostic if (debug) dumpsymtab(); 46232434Sbostic #endif 46332434Sbostic jxxxfix(); 46432434Sbostic #ifdef DEBUG 46532434Sbostic if (debug) dumpsymtab(); 46632434Sbostic #endif 46732434Sbostic } 46832434Sbostic 46932434Sbostic open_a_out() 47032434Sbostic { 47132434Sbostic /* 47232434Sbostic * Open up the a.out file now, and get set to build 47332434Sbostic * up offsets into it for all of the various text,data 47432434Sbostic * text relocation and data relocation segments. 47532434Sbostic */ 47632434Sbostic a_out_file = fopen(outfile, "w"); 47732434Sbostic if (a_out_file == NULL) { 47832434Sbostic yyerror("Cannot create %s", outfile); 47932434Sbostic delexit(); 48032434Sbostic } 48132434Sbostic biofd = a_out_file->_file; 48232434Sbostic a_out_off = 0; 48332434Sbostic } 48432434Sbostic 48532434Sbostic roundsegments() 48632434Sbostic { 48732434Sbostic register int locindex; 48832434Sbostic register long v; 48932434Sbostic /* 49032434Sbostic * round and assign text segment origins 49132434Sbostic * the exec header always goes in usefile[0] 49232434Sbostic */ 49332434Sbostic tsize = 0; 49432434Sbostic for (locindex=0; locindex<NLOC; locindex++) { 49532434Sbostic v = round(usedot[locindex].e_xvalue, FW); 49632434Sbostic usedot[locindex].e_xvalue = tsize; 49732434Sbostic if ((locindex == 0) || (v != 0) ){ 49832434Sbostic usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE)); 49932434Sbostic bopen(usefile[locindex], a_out_off); 50032434Sbostic if (locindex == 0) 50132434Sbostic a_out_off = sizeof (struct exec); 50232434Sbostic } else { 50332434Sbostic usefile[locindex] = (BFILE *)-1; 50432434Sbostic } 50532434Sbostic tsize += v; 50632434Sbostic a_out_off += v; 50732434Sbostic } 50832434Sbostic /* 50932434Sbostic * Round and assign data segment origins. 51032434Sbostic */ 51132434Sbostic datbase = round(tsize, FW); 51232434Sbostic for (locindex=0; locindex<NLOC; locindex++) { 51332434Sbostic v = round(usedot[NLOC+locindex].e_xvalue, FW); 51432434Sbostic usedot[NLOC+locindex].e_xvalue = datbase + dsize; 51532434Sbostic if (v != 0){ 51632434Sbostic usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE)); 51732434Sbostic bopen(usefile[NLOC + locindex], a_out_off); 51832434Sbostic } else { 51932434Sbostic usefile[NLOC + locindex] = (BFILE *)-1; 52032434Sbostic } 52132434Sbostic dsize += v; 52232434Sbostic a_out_off += v; 52332434Sbostic } 52432434Sbostic /* 52532434Sbostic * Assign final values to symbols 52632434Sbostic */ 52732434Sbostic hdr.a_bss = dsize; 52832434Sbostic freezesymtab(); /* this touches hdr.a_bss */ 52932434Sbostic stabfix(); 53032434Sbostic /* 53132434Sbostic * Set up the relocation information "files" to 53232434Sbostic * be zero; outrel takes care of the rest 53332434Sbostic */ 53432434Sbostic for (locindex = 0; locindex < NLOC + NLOC; locindex++){ 53532434Sbostic rusefile[locindex] = (struct relbufdesc *)0; 53632434Sbostic } 53732434Sbostic } 53832434Sbostic 53932434Sbostic build_hdr() 54032434Sbostic { 54132434Sbostic /* 54232434Sbostic * Except for the text and data relocation sizes, 54332434Sbostic * calculate the final values for the header 54432434Sbostic * 54532434Sbostic * Write out the initial copy; we to come 54632434Sbostic * back later and patch up a_trsize and a_drsize, 54732434Sbostic * and overwrite this first version of the header. 54832434Sbostic */ 54932434Sbostic hdr.a_magic = MAGIC; 55032434Sbostic hdr.a_text = tsize; 55132434Sbostic hdr.a_data = dsize; 55232434Sbostic hdr.a_bss -= dsize; 55332434Sbostic hdr.a_syms = sizesymtab(); /* Does not include string pool length */ 55432434Sbostic hdr.a_entry = 0; 55532434Sbostic hdr.a_trsize = 0; 55632434Sbostic hdr.a_drsize = 0; 55732434Sbostic 55832434Sbostic bwrite((char *)&hdr, sizeof(hdr), usefile[0]); 55932434Sbostic } 56032434Sbostic 56132434Sbostic i_pass2() 56232434Sbostic { 56332434Sbostic if (useVM == 0) { 56432434Sbostic fclose(tokfile); 56532434Sbostic tokfile = fopen(tokfilename, "r"); 56632434Sbostic if (tokfile==NULL) { 56732434Sbostic yyerror("Bad pass 2 temporary file for reading %s", tokfilename); 56832434Sbostic delexit(); 56932434Sbostic } 57032434Sbostic } 57132434Sbostic fclose(strfile); 57232434Sbostic strfile = fopen(strfilename, "r"); 57332434Sbostic } 57432434Sbostic 57532434Sbostic pass2() 57632434Sbostic { 57732434Sbostic #ifdef DEBUG 57832434Sbostic if (debug) 57932434Sbostic printf("\n\n\n\t\tPASS 2\n\n\n\n"); 58032434Sbostic #endif DEBUG 58132434Sbostic passno = 2; 58232434Sbostic lineno = 1; 58332434Sbostic if (liston && ninfiles != 0) 58432434Sbostic { 58532434Sbostic char ch; 58632434Sbostic source = fopen (innames[ind++], "r"); 587*32435Sbostic (void)sprintf (layoutpos, "%4ld 00000000 ", lineno); 58832434Sbostic layoutpos += LHEAD; 58932434Sbostic ch = getc (source); 59032434Sbostic if (ch == EOF) 59132434Sbostic { 59232434Sbostic if (ind == ninfiles) 59332434Sbostic endofsource = 1; 59432434Sbostic else 59532434Sbostic source = fopen (innames[ind++], "r"); 59632434Sbostic } 59732434Sbostic else 59832434Sbostic ungetc (ch, source); 59932434Sbostic } 60032434Sbostic else 60132434Sbostic endofsource = 1; 60232434Sbostic dotp = &usedot[0]; 60332434Sbostic txtfil = usefile[0]; /* already opened (always!) */ 60432434Sbostic relfil = 0; /* outrel takes care of the rest */ 60532434Sbostic initoutrel(); 60632434Sbostic 60732434Sbostic inittokfile(); 60832434Sbostic 60932434Sbostic yyparse(); 61032434Sbostic 61132434Sbostic closetokfile(); 61232434Sbostic } 61332434Sbostic 61432434Sbostic fillsegments() 61532434Sbostic { 61632434Sbostic int locindex; 61732434Sbostic /* 61832434Sbostic * Round text and data segments to FW by appending zeros 61932434Sbostic */ 62032434Sbostic for (locindex = 0; locindex < NLOC + NLOC; locindex++) { 62132434Sbostic if (usefile[locindex]) { 62232434Sbostic txtfil = usefile[locindex]; 62332434Sbostic dotp = &usedot[locindex]; 62432434Sbostic while (usedot[locindex].e_xvalue & FW) 62532434Sbostic outb(0); 62632434Sbostic } 62732434Sbostic } 62832434Sbostic } 62932434Sbostic 63032434Sbostic reloc_syms() 63132434Sbostic { 63232434Sbostic u_long closerelfil(); 63332434Sbostic /* 63432434Sbostic * Move the relocation information to a.out 63532434Sbostic * a_out_off is the offset so far: 63632434Sbostic * exec + text segments + data segments 63732434Sbostic */ 63832434Sbostic relocfile = (BFILE *)Calloc(1,sizeof(BFILE)); 63932434Sbostic bopen(relocfile, a_out_off); 64032434Sbostic a_out_off += closeoutrel(relocfile); 64132434Sbostic 64232434Sbostic hdr.a_trsize = trsize; 64332434Sbostic hdr.a_drsize = drsize; 64432434Sbostic if (readonlydata) { 64532434Sbostic hdr.a_text += hdr.a_data; 64632434Sbostic hdr.a_data = 0; 64732434Sbostic hdr.a_trsize += hdr.a_drsize; 64832434Sbostic hdr.a_drsize = 0; 64932434Sbostic } 65032434Sbostic /* 65132434Sbostic * Output the symbol table and the string pool 65232434Sbostic * 65332434Sbostic * We must first rewind the string pool file to its beginning, 65432434Sbostic * in case it was seek'ed into for fetching ascii and asciz 65532434Sbostic * strings. 65632434Sbostic */ 65732434Sbostic fseek(strfile, 0, 0); 65832434Sbostic symwrite(relocfile); 65932434Sbostic } 66032434Sbostic 66132434Sbostic fix_a_out() 66232434Sbostic { 66332434Sbostic if (lseek(a_out_file->_file, 0L, 0) < 0L) 66432434Sbostic yyerror("Reposition for header rewrite fails"); 66532434Sbostic if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0) 66632434Sbostic yyerror("Rewrite of header fails"); 66732434Sbostic } 66832434Sbostic 66932434Sbostic delexit() 67032434Sbostic { 67132434Sbostic delete(); 67232434Sbostic if (passno == 2){ 67332434Sbostic unlink(outfile); 67432434Sbostic } 67532434Sbostic exit(1); 67632434Sbostic } 67732434Sbostic 67832434Sbostic delete() 67932434Sbostic { 68032434Sbostic if (useVM == 0 || tokfilename[0]) 68132434Sbostic unlink(tokfilename); 68232434Sbostic if (strfilename[0]) 68332434Sbostic unlink(strfilename); 68432434Sbostic } 68532434Sbostic 68632434Sbostic sawabort() 68732434Sbostic { 68832434Sbostic char *fillinbuffer(); 68932434Sbostic while (fillinbuffer() != (char *)0) 69032434Sbostic continue; 69132434Sbostic delete(); 69232434Sbostic exit(1); /*although the previous pass will also exit non zero*/ 69332434Sbostic } 69432434Sbostic 69532434Sbostic panic(fmt, a1, a2, a3, a4) 69632434Sbostic char *fmt; 69732434Sbostic /*VARARGS 1*/ 69832434Sbostic { 69932434Sbostic yyerror("Assembler panic: bad internal data structure."); 70032434Sbostic yyerror(fmt, a1, a2, a3, a4); 70132434Sbostic delete(); 70232434Sbostic abort(); 70332434Sbostic } 704