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