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