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