|
|
1.1 root 1: static char ID[] = "@(#) ld00.c: 1.17 8/18/83";
2: #include "system.h"
3:
4: #include <stdio.h>
5:
6: #if TS || RT
7: #include <ar.h>
8: #else
9: #include <archive.h>
10: #endif
11:
12: #include "structs.h"
13: #include "extrns.h"
14: #include "list.h"
15: #include "ldfcn.h"
16: #include "sgs.h"
17: #include "sgsmacros.h"
18: #include "paths.h"
19: #include "y.tab.h"
20:
21: extern FILE *yyin; /* current lex input file */
22: extern char inline[]; /* current input line up to current token */
23: extern int yychar; /* current yacc lookahead token number */
24:
25: extern int in_y_exp; /*
26: * See explanation in ld.yac.
27: * We must initialize this var. to zero
28: * before parsing an ifile.
29: */
30:
31: #if FLEXNAMES
32: # define STRINCRE 2048
33: #else
34: # define STRINCRE 1024
35: #endif
36: #define MAXINFLS 16
37: #define MAXDLEN 64 /* maximum lib search directory length*/
38:
39: #ifndef LLIBDIR
40: #define LLIBDIR LIBDIR
41: #endif
42: #ifndef NDELDIRS
43: #define NDELDIRS 1
44: #endif
45:
46: extern char *realloc();
47:
48: static int nldirs = NDELDIRS; /* number of -L options used */
49: static char *libdirs[MAXLDIRS] = { /* directories searched for libraries */
50: LLIBDIR
51: #ifdef LLIBDIR1
52: ,LLIBDIR1
53: #endif
54: };
55:
56:
57: /*
58: * A stack is kept of input ifile discriptors so that
59: * ifiles may include other ifiles.
60: *
61: * NOTE: currently, this only works if the ifile name
62: * is the last statement in an ifile, because YACC does
63: * not return from a recursive call properly.
64: */
65: typedef struct instr INSTR;
66: struct instr {
67: FILE *infildes; /* file descriptor */
68: char *infilnm; /* ptr to file name */
69: int lastlnno; /* last line number read in the file */
70: };
71: char whichin = 0; /* index int instack */
72: INSTR instack[MAXINFLS+1]; /* stack of input ifiles */
73: /*eject*/
74: filespec(filename)
75: char *filename;
76: {
77:
78: /*
79: * This routine is called when there is an input directive to load a
80: * file. It checks the type of file, to distinguish between an ifile
81: * and an object file
82: */
83:
84: FILE *filedes;
85: #if PORTAR || PORT5AR
86: unsigned short firstword;
87: char atype[SARMAG];
88: #else
89: unsigned short firstword,
90: atype;
91: #endif
92:
93: #if DEBUG
94: if (dflag > 1)
95: fprintf(stderr, "filespec : %s\n", filename);
96: #endif
97:
98: if ((filedes = fopen(filename,"r")) == NULL) {
99: lderror(2,0,sname(curfilnm),"Can't open file %s for input", filename);
100: return;
101: }
102:
103: in_y_exp = 0;
104:
105: if (fread( (char *) &firstword, sizeof(firstword), 1, filedes) != 1)
106: lderror(2,0,NULL,"Can't read 1st word of file %s",filename);
107: #if PORTAR || PORT5AR
108: fseek(filedes,0L,0);
109: if (fread(atype,SARMAG,1,filedes) != 1)
110: atype[0] = '\0';
111: #else
112: if ( sizeof(firstword) != sizeof(ARMAG) )
113: if ( fread( (char *)&atype, sizeof(atype), 1, filedes) != 1)
114: atype = firstword;
115: #endif
116:
117: if (ISMAGIC(firstword)) {
118: bldldfil( savefn(filename), 0 );
119: fclose(filedes);
120: }
121: #if PORTAR || PORT5AR
122: else if (strncmp(atype,ARMAG,SARMAG) == 0) {
123: #else
124: else if ( (firstword == (unsigned short) ARMAG) ||
125: ((sizeof(firstword) != sizeof(ARMAG)) &&
126: (atype == (unsigned short) ARMAG)) ) {
127: #endif
128: bldldfil( savefn(filename), 1 );
129: fclose(filedes);
130: }
131: else if (BADMAGIC(firstword)) {
132: yyerror("file %s is of unknown type: magic number = %6.2x",
133: filename, firstword);
134: fclose(filedes);
135: }
136: else {
137: /*
138: * Assume that the file is an ifile
139: */
140: instack[whichin].infilnm = curfilnm;
141: instack[whichin].lastlnno = lineno;
142: instack[whichin].infildes = filedes;
143: curfilnm = savefn(filename);
144: lineno = 1;
145: if( ++whichin == MAXINFLS ) {
146: yyerror("ifile nesting limit exceeded with file %s", filename);
147: fclose(filedes);
148: curfilnm = instack[--whichin].infilnm;
149: lineno = instack[whichin].lastlnno++;
150: return;
151: }
152:
153: if (fseek(filedes, 0L, 0) != 0)
154: lderror(2,0,NULL,"Can't seek to the beginning of file %s",
155: filename);
156: yyin = filedes;
157:
158: #if DEBUG
159: if( dflag )
160: fprintf(stderr, "reading cmds from file %s (%.2o)\n",
161: filename, filedes);
162: #endif
163:
164: yyparse();
165: close(filedes);
166:
167: yyin = instack[--whichin].infildes;
168: curfilnm = instack[whichin].infilnm;
169: lineno = instack[whichin].lastlnno++;
170: yychar = -1;
171:
172: #if DEBUG
173: if( dflag )
174: fprintf(stderr, "returning input to fildes %s (%.2o)\n",
175: curfilnm, yyin);
176: #endif
177:
178: }
179: }
180: /*eject*/
181: bldldfil(fname, typflag)
182: char *fname;
183: int typflag;
184: {
185:
186: /*
187: * Build a LDFILE action item
188: */
189:
190: ACTITEM *p;
191:
192: p = (ACTITEM *) myalloc(sizeof(ACTITEM));
193:
194: p->ldlbry.aiinflnm = curfilnm;
195: p->ldlbry.aiinlnno = lineno;
196: p->ldlbry.aitype = typflag ? AILDLBRY : AILDFILE;
197: p->ldlbry.aifilnam = fname;
198:
199: listadd(l_AI, &ldfilist, p);
200: }
201:
202:
203:
204:
205: bldadscn(scname, fname, sp)
206: char *scname;
207: char *fname;
208: ACTITEM *sp; /* ptr to DFNSCN act_item */
209: {
210:
211: /*
212: * Build a ADDSCN action item
213: */
214:
215: ACTITEM *p;
216:
217: p = (ACTITEM *) myalloc(sizeof(ACTITEM));
218:
219: p->addscn.aitype = AIADDSCN;
220: p->addscn.aiinflnm = curfilnm;
221: p->addscn.aiinlnno = lineno;
222: copy(p->addscn.ainame, scname, sizeof(p->addscn.ainame));
223: p->addscn.aiscfile = fname;
224:
225: listadd(l_AI, &(sp->dfnscn.sectspec), p);
226: }
227:
228:
229:
230:
231: ACTITEM *
232: bldadfil(fname, sp)
233: char *fname;
234: ACTITEM *sp; /* ptr to DFNSCN act_item */
235: {
236:
237: /*
238: * Build a ADFILE action item
239: */
240:
241: ACTITEM *p;
242:
243: p = (ACTITEM *) myalloc(sizeof(ACTITEM));
244:
245: p->adfile.aitype = AIADFILE;
246: p->adfile.aiinflnm = curfilnm;
247: p->adfile.aiinlnno = lineno;
248: p->adfile.aifilnam = fname;
249:
250: listadd(l_AI, &(sp->dfnscn.sectspec), p);
251:
252: return (p);
253: }
254:
255:
256:
257:
258: bldexp(ep, lp)
259: ENODE *ep;
260: LISTOWN *lp;
261: {
262:
263: /*
264: * Build an EVEXPR action item
265: */
266:
267: ACTITEM *p;
268:
269: p = (ACTITEM *) myalloc(sizeof(ACTITEM));
270:
271: p->evexpr.aitype = AIEVEXPR;
272: p->evexpr.aiinlnno = lineno;
273: p->evexpr.aiinflnm = curfilnm;
274: p->evexpr.aiexptr = ep;
275:
276: listadd(l_AI, lp, p);
277: }
278:
279:
280:
281:
282: bldsym(sym, value, op)
283: char *sym;
284: long value;
285: int op;
286: {
287:
288: /*
289: * Build an DFNSYM action item
290: */
291:
292: ACTITEM *p;
293:
294: p = (ACTITEM *) myalloc(sizeof(ACTITEM));
295:
296: p->dfnsym.aitype = AIDFNSYM;
297: p->dfnsym.aiinlnno = lineno;
298: p->dfnsym.aiinflnm = curfilnm;
299: p->dfnsym.aisymbol = savefn(sym);
300: p->dfnsym.aideflag = op;
301: p->dfnsym.aidefval = value;
302:
303: listadd(l_AI, &symlist, p);
304: }
305: /*eject*/
306: pflags(flgname, ifile)
307: char *flgname; /* ptr to x, extracted from -x */
308: int ifile; /* set TRUE iff the flag comes from an ifile */
309: {
310:
311: /*
312: * Process flag specifications
313: *
314: * Note that flags can come from two sources:
315: * command line : everything is character strings
316: * ifile : parser has already converted tokens to binary
317: */
318:
319: register int type;
320:
321:
322: /*
323: * -a : make the output file "executable":
324: * 1. complain about unresolved references
325: * 2. define several "_xxxx" symbols
326: *
327: * -cn : increment the partial execution flag. 'n'
328: * defaults to 1:
329: * 0 : normal, complete ld execution
330: * 1 : execute parser of PASS 1 only
331: * 2 : execute PASS 1 only
332: * 3 : execute through allocation (up
333: * to output())
334: * 4 : complete ld execution, with
335: * /dev/null as the output
336: * file name
337: *
338: * -dn (-b for u3b): increment the internal ld debug flag. 'n'
339: * defaults to 1
340: *
341: * -e name : generate a UNIX a.out header in the optional
342: * header field of the output file, and
343: * set the "entry point" entry to the
344: * address of the symbol "name". This
345: * flag forces the flag -X
346: *
347: * -f 0xaabb : use the two-byte value aabb to:
348: * 1. fill "holes" between sections
349: * 2. fill uninitialized .bss sections
350: *
351: * -h nnn : make the optional header field nnn bytes in
352: * size. Zero fill any unused bytes of this
353: * header
354: *
355: * -i : ***** b16ld and x86ld only *****
356: * use two regions, to give separate I and
357: * D space (64 K each)
358: *
359: * -lx : search the library libx.a in directory
360: * libdirs[n] for any symbols which can
361: * satisfy outstanding unresolved references.
362: *
363: * -m : generate a memory map
364: *
365: * -o name : use "name" as the name of the output file.
366: * The default value is given by the
367: * constant A.OUT, defined in the include
368: * file paths.h
369: *
370: * -p[nnn] : generate a patch list. The size of the
371: * optional header is increased by the
372: * size of the patch list
373: * the output section size is set to nnn
374: * after allocation and patch list
375: * construction to save physical memory
376: *
377: * -r : keep relocation information in the output file
378: *
379: * -s : strip all relocation and symbol table
380: * information from the output file
381: *
382: * -t : ****** UNIX only ******
383: * do type checking
384:
385: * -tv : ***** b16ld/x86ld/n3bld only *****
386: * generate TV function linkage
387: *
388: * -x (only u3b) : do not preserve symbols in the output symbol
389: * table except static or external symbols
390: *
391: * -u name : add "name" to ld's symbol table, as an
392: * undefined symbol
393: *
394: * -z : ****** UNIX only ******
395: * leave memory around zero unconfigured ro catch
396: * null pointers
397: *
398: * -B nn : generate "padding" output sections of nn bytes
399: * of zero following any output section
400: * which is either:
401: * 1. of zero length
402: * 2. all of uninitialzed .bss
403: *
404: * -F : ****** UNIX only ******
405: * indicate in header file for paging, block
406: * for paging, memory configure for paging, etc.
407: *
408: * -H : change the type of all global symbol table
409: * entries to "static"
410: *
411: * -L<path> : provides alternate directories and orders
412: * search path for libraries (equivalent to
413: * -I flag for cpp includes). -L must precede
414: * -l to be effective.
415: *
416: * -M : ****** UNIX only *****
417: * output message if external variables are
418: * multiply defined
419: *
420: * -N : squash text and data together
421: *
422: * -S : "silent" mode: only fatal errors will be
423: * listed - not warnings or diagnostics
424: *
425: * -V : output current ld environment definition. '-V'
426: * flags are cumulative:
427: * 1 : describe the ld version
428: * 2 : describe the machine and os version
429: *
430: * -VS nn : put nn as version stamp in the optional header
431: *
432: * -X : generate, in the optional header field, a
433: * standard UNIX a.out header
434: * (except for u3b, where it means
435: * elimate compiler generated labels)
436: *
437: * -ild : generate an "extra" output section for each
438: * unallocated area of configured memory
439: *
440: */
441:
442: switch (flgname[0]) {
443: #if !UNIX || M32
444: case 'a':
445: aflag++;
446: break;
447: #endif
448: #if !ONEPROC
449: case 'c':
450: type = 1;
451: if( flgname[1] )
452: if( (type = stoi(&flgname[1])) == 0x8000 ) {
453: yyerror("-c flag does not specify a number: %s", &flgname[1]);
454: type = 1;
455: }
456: cflag += type;
457: break;
458: #endif
459: #if DEBUG
460: case 'd':
461: #if UNIX
462: lderror(0,0,NULL,"-d flag is not implemented");
463: break;
464: case 'b':
465: #endif
466: type = 1;
467: if( flgname[1] )
468: if( (type = stoi(&flgname[1])) == 0x8000 ) {
469: yyerror("-%c flag does not specify a number: %s", flgname[0],flgname[1]);
470: type = 1;
471: }
472: dflag += type;
473: break;
474: #endif
475: case 'e':
476: if( ifile )
477: if (yylex() != NAME)
478: yyerror("-e flag does not specify a legal symbol name: %s", inline);
479: else
480: #if FLEXNAMES
481: strcpy(epsymbol, yylval.sptr);
482: #else
483: copy(epsymbol, yylval.sptr, 8);
484: #endif
485: else {
486: #if FLEXNAMES
487: strcpy(epsymbol, *++argptr);
488: #else
489: copy(epsymbol, *++argptr, 8);
490: #endif
491: argcnt--;
492: }
493: Xflag++;
494: #if DEBUG
495: if (dflag)
496: fprintf(stderr, "a.out entry point symbol: %s\n",
497: epsymbol);
498: #endif
499: break;
500: case 'f':
501: if( ifile )
502: if (yylex() != LONGINT)
503: yyerror("-f flag does not specify a two-byte number: %s", inline);
504: else
505: globfill = (short) *yylval.lptr;
506: else {
507: if( (globfill = (short) stoi(*++argptr)) == (short) 0x8000 ) {
508: yyerror("-f flag does not specify a two-byte number: %s", *argptr);
509: globfill = 0;
510: }
511: argcnt--;
512: }
513: #if DEBUG
514: if (dflag)
515: fprintf(stderr, "global fill: %.2x\n",
516: globfill);
517: #endif
518: break;
519: #if !UNIX
520: case 'h':
521: if( ifile )
522: if (yylex() != LONGINT)
523: yyerror("-h flag does not specify a numeric value: %s", inline);
524: else
525: hflag = *yylval.lptr;
526: else {
527: if( (hflag = stoi(*++argptr)) == 0x8000 ) {
528: yyerror("-h flag does not specify a numeric value: %s", *argptr);
529: hflag = 0;
530: }
531: argcnt--;
532: }
533: if( hflag < 0 ) {
534: yyerror("invalid value on -h flag: %.2x", hflag);
535: hflag = 0;
536: }
537: #if DEBUG
538: if(dflag)
539: fprintf(stderr, "optional header size: %d\n",
540: hflag);
541: #endif
542: break;
543: #endif
544: case 'i':
545: #if IANDD
546: if (flgname [1] == '\0')
547: {
548: iflag++;
549: break;
550: }
551: #endif
552: #if ILDOPT
553: if (flgname [1] == 'l' && flgname [2] == 'd')
554: {
555: ildflag++;
556: break;
557: }
558:
559: yyerror("%s is an invalid flag",flgname);
560: #endif
561: break;
562: case 'l':
563: if( flgname[1] != '\0' ) {
564: library(flgname);
565: }
566: else {
567: specflags(flgname, argptr);
568: }
569: break;
570: case 'm':
571: mflag++;
572: break;
573: #if !UNIX
574: case 'p':
575: pflag = -1; /* use default patch size */
576: if( flgname[1] ) {
577: if( (pflag = stoi(&flgname[1])) == 0x8000 ) {
578: yyerror("-p flag does not specify a number: %s", &flgname[1]);
579: pflag = -1;
580: } else {
581: if (pflag <= 0) {
582: yyerror("-p flag size out of range: %s", &flgname[1]);
583: pflag = -1;
584: }
585: } /* else */
586: } /* if flgname */
587: break;
588: #endif
589: case 'o':
590: if( ifile ) {
591: type = yylex();
592: if( (type == FILENAME) || (type == NAME) )
593: copy(outfilnm, yylval.sptr, 128);
594: else
595: yyerror("-o flag does not specify a valid file name: %s", inline);
596: }
597: else {
598: copy(outfilnm, *++argptr, 128);
599: argcnt--;
600: }
601: if( outfilnm[127] != '\0' ) {
602: outfilnm[127] = '\0';
603: yyerror("-o file name too large (> 128 char); truncated to (%s)", outfilnm);
604: }
605: #if DEBUG
606: if(dflag)
607: fprintf(stderr, "output file name: %s\n",
608: outfilnm);
609: #endif
610: break;
611: case 'r':
612: rflag++;
613: break;
614: case 's':
615: sflag++;
616: break;
617: case 't':
618: #if TRVEC
619: if (flgname[1] == 'v') {
620: tvflag = 1;
621: magic = (unsigned short) TVMAGIC;
622: break;
623: }
624: #endif
625: #if COMMON
626: tflag++;
627: #endif
628: break;
629: case 'u':
630: if( ifile )
631: if( yylex() != NAME )
632: yyerror("-u flag does not specify a legal symbol name: %s", inline);
633: else
634: bldsym(yylval.sptr, 0L, 0);
635: else {
636: bldsym(*++argptr, 0L, 0);
637: argcnt--;
638: }
639: break;
640: #if PAGING
641: case 'z':
642: zflag++;
643: break;
644: #endif
645: #if !UNIX
646: case 'B':
647: if( ifile )
648: if (yylex() != LONGINT)
649: yyerror("-B flag does not specify a number: %s", inline);
650: else
651: Bflag = *yylval.lptr;
652: else {
653: if( (Bflag = stoi(*++argptr)) == 0x8000 ) {
654: yyerror("-B flag does not specify a number: %s", *argptr);
655: Bflag = 0;
656: }
657: argcnt--;
658: }
659: #if DEBUG
660: if (dflag)
661: fprintf(stderr, "pad-section size: %.2x\n",
662: Bflag);
663: #endif
664: break;
665: case 'H':
666: Hflag++;
667: break;
668: #endif
669: #if PAGING
670: case 'F':
671: Fflag++;
672: break;
673: #endif
674: #if COMMON
675: case 'M':
676: Mflag++;
677: break;
678: #endif
679: case 'N':
680: Nflag++;
681: break;
682: case 'L':
683: if ( nldirs >= MAXLDIRS )
684: yyerror("too many -L options, %d allowed", MAXLDIRS-1);
685: else if ( flgname[1] == NULL )
686: yyerror("no directory given with -L");
687: else if ( strlen(&flgname[1]) > MAXDLEN )
688: yyerror("-L path too long(%s)", &flgname[1]);
689: else {
690: libdirs[nldirs] = myalloc(size(&flgname[1]));
691: strcpy(libdirs[nldirs++], &flgname[1]);
692: }
693: break;
694: case 'S':
695: Sflag++;
696: break;
697: case 'V':
698: if (flgname[1] == 'S') {
699: if( ifile )
700: if (yylex() != LONGINT)
701: yyerror("-VS flag does not specify a numeric value: %s", inline);
702: else
703: VSflag = *yylval.lptr;
704: else {
705: if( (VSflag = stoi(*++argptr)) == 0x8000 ) {
706: yyerror("-VS flag does not specify a numeric value: %s", *argptr);
707: VSflag = 0;
708: }
709: argcnt--;
710: }
711: }
712: else {
713: Vflag++;
714: }
715: break;
716: #if !UNIX
717: case 'X':
718: Xflag++;
719: break;
720: #endif
721: default:
722: specflags(flgname, argptr);
723: }
724: }
725: /*eject*/
726: library(fname)
727: char *fname;
728: {
729:
730: /*
731: * For a library flag of the form "-lx", build a file name of the form
732: *
733: * "libdirs[n]/libx.a"
734: *
735: * where libdirs[0] is LIBDIR (defined in paths.h) and libdirs[n>0]
736: * are defined using the -L option. Then build a LDFILE action item.
737: */
738:
739: static char libname[MAXDLEN+16]; /* -lx file name */
740: int dndx;
741: char *p;
742: FILE *lfd;
743:
744: if ( *(++fname) == '\0' ) {
745: yyerror("the -l flag (specifying a default library) is not supported");
746: return;
747: }
748: else
749: p = fname;
750:
751: /*
752: * Loop thru libdir[NDELDIRS] thru libdir[nldirs-1]
753: */
754: for ( dndx = NDELDIRS; dndx < nldirs; dndx++) {
755: sprintf(libname, "%s%s%.8s%s", libdirs[dndx], "/lib", p, ".a");
756: if ( (lfd = fopen(libname,"r")) != NULL)
757: goto liblab;
758: }
759:
760: /*
761: * loop thru libdirs[0] thru libdirs[NDELDIRS-1]
762: */
763: for ( dndx = 0; dndx < NDELDIRS; dndx++) {
764: sprintf(libname, "%s%s%.8s%s", libdirs[dndx], "/lib", p, ".a");
765: if ( (lfd = fopen(libname,"r")) != NULL)
766: goto liblab;
767: }
768:
769: yyerror("can't find library lib%s.a", p);
770: return;
771:
772: liblab:
773: fclose(lfd);
774: bldldfil(savefn(libname), 1);
775: }
776: /*eject*/
777: char *
778: savefn(name)
779: char *name;
780: {
781:
782: /*
783: * Save the name of an ifile or input *.o or archive file
784: */
785:
786: char *strbeg;
787: int length;
788:
789: length = strlen(name) + 1;
790: if (strnext + length > strlimit)
791: {
792: #if ONEPROC
793: strbase = myalloc( STRINCRE );
794: strnext = strbase;
795: strlimit = strbase + STRINCRE;
796: #else
797: lderror( 0, 0, NULL, "too many strings, out of space" );
798: lderror( 2, 0, NULL, "%sld run is too large and complex", SGS );
799: #endif
800: }
801: strbeg = strnext;
802: strncpy( strbeg, name, length );
803: strnext += length;
804:
805: return( strbeg );
806: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.