|
|
1.1 root 1: /* ld/main.c */
2:
3: #include "data.h"
4:
5: extern char *mktemp();
6:
7: main( argc, argv )
8: int argc;
9: char *argv[];
10: {
11: flag_t dcomm = 0, /* define commons even if reloc out */
12: nosym = 0, /* do not output symbol table */
13: memld = 0, /* do in-memory load */
14: reloc = 0; /* output relocation info */
15: char *ofname = "l.out",
16: *entrys = NULL,
17: *mfn,
18: *lp;
19: seg_t *sgp;
20: sym_t *sp;
21: mod_t *mp;
22: FILE *ofp;
23: struct stat statbuf;
24: int i, segn;
25: unsigned int symno;
26: fsize_t daddr;
27: uaddr_t addr;
28: #if BREADBOX
29: int abort();
30: #endif
31:
32: setbuf( stdout, NULL );
33: setbuf( stderr, NULL );
34:
35: /*
36: * set separate code/data flag (required for 286 protected mode)
37: */
38: oldh.l_flag |= LF_SEP;
39:
40: nmod = mxmsym = mdisk = 0;
41:
42: if ( argc <= 1 )
43: usage( "no args" );
44:
45: /*
46: * Pass 1: Scan argument list.
47: */
48: for ( i = 1; i < argc; i++ ) {
49:
50: /*
51: * Not -option; attempt to read file
52: */
53: if ( *argv[i] != '-' ) {
54: if ( !rdfile(argv[i]) )
55: fatal( "can't open %s", argv[i] );
56: }
57:
58: /*
59: * Decode options
60: */
61: else switch ( argv[i][1] ) {
62:
63: default:
64: usage( "unknown option %s", argv[i] );
65: continue;
66:
67: case 'b':
68: /*
69: * -b: undocumented option
70: * big link stores module structs on disk
71: */
72: mdisk++;
73:
74: if ( (mfp = fopen(mfn=mktemp("/tmp/ldXXXXXX"),"wr") )
75: ==NULL) {
76: unlink( mfn );
77: fatal( "can't open temp file" );
78: }
79:
80: mtemp = malloc( sizeof(mod_t) );
81: continue;
82:
83: case 'd':
84: /*
85: * -d: Define commons (even if undefined symbols).
86: */
87: dcomm++;
88: continue;
89:
90: case 'e':
91: /*
92: * -e ent: Set entry point to given symbol/octal number.
93: */
94: if ( ++i >= argc )
95: usage( "Bad -e option" );
96:
97: else {
98: undef( argv[i] );
99: entrys = argv[i];
100: }
101: continue;
102:
103: case 'i':
104: continue;
105:
106: case 'k':
107: /*
108: * -k[sys]: Kernel process - use system symbol table.
109: */
110: oldh.l_flag |= LF_KER;
111:
112: if ( argv[i][2] != '\0' )
113: rdsystem( &argv[i][2] );
114: else
115: rdsystem( "/coherent" );
116: continue;
117:
118: case 'l':
119: /*
120: * -l<lib>: Use standard library <lib>.
121: */
122: lp = malloc( strlen(argv[i])+16 );
123: sprintf( lp, "/lib/lib%s.a", &argv[i][2] );
124:
125: if ( rdfile(lp) )
126: ;
127:
128: else {
129: sprintf( lp, "/usr/lib/lib%s.a", &argv[i][2] );
130: if ( rdfile(lp) )
131: ;
132: else
133: fatal( "can't open lib%s.a",
134: &argv[i][2]);
135: }
136: continue;
137:
138: case 'm':
139: /*
140: * -m: Perform in-memory load if possible.
141: */
142: memld++;
143: continue;
144:
145: case 'n':
146: /*
147: * -n: Bind output shared.
148: */
149: oldh.l_flag |= LF_SHR;
150: #ifdef IAPX86
151: /*
152: * Special case, no -n without -i on IBM PC
153: */
154: oldh.l_flag |= LF_SEP;
155: #endif
156: continue;
157:
158: case 'o':
159: /*
160: * -o file: Place output in named file (default l.out).
161: */
162: if ( ++i >= argc )
163: usage( "bad -o option" );
164: else
165: ofname = argv[i];
166: continue;
167:
168: case 'r':
169: /*
170: * -r: Retain relocation information.
171: */
172: reloc++;
173: #ifdef IAPX86
174: /*
175: * Special case, -r disables -i.
176: */
177: oldh.l_flag &= ~LF_SEP;
178: #endif
179: continue;
180:
181: case 's':
182: /*
183: * -s: Discard symbol table.
184: */
185: nosym++;
186: continue;
187:
188: case 'u':
189: /*
190: * -u sym: Undefine 'sym' (forcing library search).
191: */
192: if ( ++i >= argc )
193: usage( "bad -u option" );
194: else
195: undef( argv[i] );
196: continue;
197:
198: case 'w':
199: /*
200: * -w: Watch everything happen.
201: */
202: watch++;
203: message( "watch!" );
204: continue;
205:
206: case 'X':
207: /*
208: * -X: Discard C internal local symbols.
209: */
210: noilcl++;
211: continue;
212:
213: case 'x':
214: /*
215: * -x: Discard all local symbols.
216: */
217: nolcl++;
218: continue;
219:
220: case 'C':
221: /*
222: * -C: Bind output combined code/data.
223: * (otherwise it will be separate code/data as
224: * required in 286 protected mode)
225: */
226: oldh.l_flag &= ~LF_SEP;
227: continue;
228: }
229: }
230:
231: if ( oldh.l_machine == 0 )
232: fatal( "no input found" );
233:
234: /*
235: * all modules have been read
236: * resolve meanings of various flags
237: */
238:
239: /*
240: * Relocation or undefined symbols...
241: */
242: if ( reloc || nundef ) {
243:
244: /*
245: * Requires symbol table be retained
246: */
247: nosym = 0;
248:
249: if ( oldh.l_flag & LF_SEP ) {
250:
251: message("link failed, the following symbols are undefined:");
252:
253: for ( i = 0; i < NHASH; i++ ) {
254: for ( sp=symtable[i]; sp!=NULL; sp=sp->next ) {
255: if(sp->s.ls_type==(L_GLOBAL|L_REF)
256: && sp->s.ls_addr==0)
257: spmsg(sp,"");
258: }
259: }
260:
261: if ( nundef )
262: exit( 1 );
263: }
264: }
265:
266: /*
267: * No relocation, no undefined symbols
268: */
269: else {
270: /*
271: * Must define commons
272: */
273: dcomm++;
274:
275: /*
276: * Discarding reloc info
277: */
278: if ( oseg[L_REL].size != 0 ) {
279: oldh.l_flag |= LF_NRB; /* make note */
280: oseg[L_REL].size = 0;
281: }
282: }
283:
284: /*
285: * To define common symbols...
286: */
287: if ( dcomm )
288: oseg[L_BSSD].size += commons; /* we need this much room */
289:
290: /*
291: * Discard symbol table.
292: */
293: if ( nosym )
294: oseg[L_SYM].size = 0;
295:
296: if ( watch )
297: message( "# undefined=%d", nundef );
298:
299: /*
300: * Set segment bases
301: */
302: baseall( oseg, &oldh );
303:
304: #ifdef IAPX86
305: if ( oldh.l_machine == M_8086 ) {
306: if ( (oseg[L_SHRI].size +
307: oseg[L_PRVI].size +
308: oseg[L_BSSI].size) >= MAXSEG86 )
309: fatal("FATAL: code segment too large");
310:
311: if ( (oseg[L_SHRD].size +
312: oseg[L_PRVD].size +
313: oseg[L_BSSD].size) >= (MAXSEG86 - DEFSTACK) )
314: fatal("FATAL: data segment too large");
315:
316: if ( (oseg[L_SHRD].size +
317: oseg[L_PRVD].size +
318: oseg[L_BSSD].size) >= (MAXSEG86 - DEFSTACK - WARNSIZE) )
319: message(
320: "Warning: data segment may be too large to execute");
321: }
322: #endif
323:
324: /*
325: * Open output file
326: */
327: if ( ((ofp = fopen(ofname, "w")) == NULL)
328: && ((unlink(ofname) != 0) || ((ofp = fopen(ofname, "w")) == NULL)) )
329: fatal( "cannot create %s", ofname );
330:
331: stat( ofname, &statbuf );
332: chmod( ofname, statbuf.st_mode & ~(S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)));
333: setbuf( ofp, NULL );
334:
335: /*
336: * set disk offsets of segments
337: * if not bigger than a breadbox, build output file in memory;
338: * otherwise, open the file for each segment,
339: * to get independent buffering
340: */
341: daddr = segoffs( oseg, 0L );
342:
343: if ( watch )
344: message( "size: %ld", daddr );
345:
346: #if BREADBOX
347: if ( memld || (daddr < BREADBOX) )
348: outbuf = malloc( (int) daddr );
349: #endif
350: for ( i = 0; i < NLSEG; i++ ) {
351:
352: if ( (i == L_BSSI) || (i == L_BSSD) )
353: continue;
354:
355: sgp = &oseg[i];
356:
357: if ( sgp->size == 0 )
358: continue;
359:
360: #if BREADBOX
361: if ( outbuf != NULL ) {
362: if ( (outputf[i] = malloc(sizeof(FILE))) == NULL )
363: fatal("out of space");
364:
365: outputf[i]->_cc = sgp->size;
366: outputf[i]->_cp = &outbuf[sgp->daddr];
367: outputf[i]->_pt = &abort;
368: }
369: else
370: #endif
371: {
372: if ( (outputf[i] = fopen(ofname, "r+w")) == NULL )
373: fatal( "cannot open %s (seg %d)", ofname, i );
374:
375: fseek( outputf[i], sgp->daddr, 0 );
376:
377: if ( i == L_SHRI )
378: setbuf( outputf[i], pbuf1 );
379:
380: if ( i == L_PRVD )
381: setbuf( outputf[i], pbuf2 );
382: }
383: }
384:
385: /*
386: * Define internal symbols which have been referenced
387: */
388: if ( dcomm ) {
389: i = oldh.l_flag & LF_KER;
390: endbind( etext_s, L_PRVI, i );
391: endbind( edata_s, L_PRVD, i );
392: endbind( end_s, L_BSSD, i );
393: }
394:
395: /*
396: * Run through symbol table fixing everything up
397: */
398: symno = 0;
399: for ( i=0; i < NHASH; i++ ) {
400:
401: for ( sp = symtable[i]; sp != NULL; sp = sp->next ) {
402:
403: /*
404: * Make defined symbol relative to virtual 0
405: */
406: if ( (segn = sp->s.ls_type & ~L_GLOBAL) < L_SYM ) {
407: sp->s.ls_addr += oseg[segn].vbase;
408: }
409:
410: else if ( segn == L_SYM ) {
411: spmsg( sp, "references symbol segment" );
412: }
413:
414: /*
415: * Leave absolutes alone
416: */
417: else if ( sp->s.ls_type != (L_GLOBAL|L_REF) ) {
418: ;
419: }
420:
421: /*
422: * Undefined global
423: */
424: else if ( sp->s.ls_addr == 0 ) {
425: if ( ! reloc )
426: spmsg( sp, "undefined" );
427: }
428:
429: /*
430: * Define commons
431: */
432: else if ( dcomm ) {
433: addr = sp->s.ls_addr;
434: sp->s.ls_addr = oseg[L_BSSD].vbase
435: +oseg[L_BSSD].size
436: -commons;
437: commons -= addr;
438: sp->s.ls_type = L_GLOBAL | L_BSSD;
439: }
440:
441: /*
442: * Assign symbol number
443: */
444: sp->symno = symno++;
445:
446: /*
447: * Output to symbol segment
448: */
449: if ( ! nosym ) {
450: canint( sp->s.ls_type );
451: canvaddr( sp->s.ls_addr );
452: putstruc( &sp->s, sizeof(sp->s),
453: outputf[L_SYM], &oseg[L_SYM] );
454: canint( sp->s.ls_type );
455: canvaddr( sp->s.ls_addr );
456: }
457: }
458: }
459:
460: /*
461: * get entry point (cannot precede symbol table fixup)
462: */
463: oldh.l_entry = (entrys != NULL)
464: ? lentry(entrys)
465: : (oldh.l_flag & LF_KER) ? drvbase[oldh.l_machine] : 0;
466: /*
467: * Pass 2
468: */
469: if ( mdisk ) {
470:
471: free( mtemp );
472:
473: if ((mp=malloc(sizeof(mod_t)+ mxmsym*sizeof(sym_t *))) == NULL)
474: fatal("out of space - M");
475:
476: rewind( mfp );
477:
478: for ( i = 0; i < nmod; i++ ) {
479:
480: if ( fread( mp, sizeof(mod_t), 1 ,mfp ) != 1 )
481: baddisk: fatal( "disk error" );
482:
483: if ( fread( mp->sym, sizeof(sym_t *), mp->nsym, mfp )
484: != mp->nsym)
485: goto baddisk;
486:
487: loadmod( mp );
488: }
489:
490: unlink( mfn );
491: }
492:
493: else {
494: for ( mp = modhead; mp != NULL; mp = mp->next )
495: loadmod( mp );
496: }
497:
498: /*
499: * All over but the flushing
500: */
501: canint( oldh.l_magic );
502: canint( oldh.l_flag );
503: canint( oldh.l_machine );
504: canvaddr( oldh.l_entry );
505:
506: for ( i = 0; i < NLSEG; i++ ) {
507: oldh.l_ssize[i] = oseg[i].size;
508: cansize(oldh.l_ssize[i]);
509: }
510:
511: if ( outbuf == NULL )
512: fwrite(&oldh, sizeof(oldh), 1, ofp);
513:
514: else {
515: for ( i = 0; i < sizeof(oldh); i++ )
516: outbuf[i] = *((char *)&oldh + i);
517: fwrite( outbuf, 1, (int)daddr, ofp );
518: }
519:
520: /*
521: * Make executable if no undefined symbols, and common storage defined.
522: */
523: if ( (nundef == 0) || (dcomm != 0) ) {
524: chmod(ofname, statbuf.st_mode|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
525: return( 0 );
526: }
527:
528: /*
529: * Supposed to be left relocatable.
530: */
531: else if ( reloc )
532: return( 0 );
533:
534: /*
535: * Undefined symbols left.
536: */
537: else
538: return( nundef );
539: }
540:
541: /*
542: * Set virtual bases in array of segments
543: * according to flags in header.
544: */
545: void
546: baseall( sega, ldhp )
547: register seg_t sega[];
548: register ldh_t *ldhp;
549: {
550: register uaddr_t addr;
551:
552: addr = (ldhp->l_flag & LF_KER) ? drvbase[ldhp->l_machine] : 0;
553:
554: /*
555: * Shared code segment first.
556: */
557: addr = setbase( &sega[L_SHRI], ldhp, addr );
558:
559: /*
560: * Shared data segment next if shared but not separate.
561: */
562: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) == LF_SHR )
563: addr = setbase( &sega[L_SHRD], ldhp, addr );
564:
565: /*
566: * Round up to page boundary if shared.
567: */
568: if ( ldhp->l_flag & LF_SHR )
569: addr = newpage(ldhp, addr);
570:
571: /*
572: * Private code segment next.
573: */
574: addr = setbase( &sega[L_PRVI], ldhp, addr );
575:
576: /*
577: * Private data segment next if shared but not separate.
578: */
579: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) == LF_SHR )
580: addr = setbase( &sega[L_PRVD], ldhp, addr );
581:
582: /*
583: * Uninitialized code segment next.
584: */
585: addr = setbase( &sega[L_BSSI], ldhp, addr );
586:
587: /*
588: * Set data offset if separate code/data.
589: */
590: if ( ldhp->l_flag & LF_SEP )
591: addr = (ldhp->l_flag & LF_KER) ? drvbase[ldhp->l_machine] : 0;
592:
593: /*
594: * Shared data segment next if not shared.
595: */
596: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) != LF_SHR )
597: addr = setbase( &sega[L_SHRD], ldhp, addr );
598:
599: /*
600: * Round up to page boundary if shared and separate.
601: */
602: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) == (LF_SHR|LF_SEP) )
603: addr = newpage( ldhp, addr );
604:
605: /*
606: * Private data segment next unless shared and not separate.
607: */
608: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) != LF_SHR )
609: addr = setbase( &sega[L_PRVD], ldhp, addr );
610:
611: /*
612: * Uninitialized data segment next.
613: */
614: setbase( &sega[L_BSSD], ldhp, addr );
615: }
616:
617: /*
618: * Set virtual base in given segment and return next address
619: * Check for wraparound and driver space overflow
620: */
621: uaddr_t
622: setbase( segp, ldhp, addr )
623: register seg_t *segp;
624: register ldh_t *ldhp;
625: register uaddr_t addr;
626: {
627: segp->vbase = addr;
628: addr += segp->size;
629:
630: /*
631: * Address wrap-around.
632: */
633: if ( addr < segp->vbase ) {
634: fatal("address wraparound");
635: }
636:
637: /*
638: * User process.
639: */
640: else if ( ! (ldhp->l_flag & LF_KER) ) {
641: ;
642: }
643:
644: /*
645: * Invalid kernel process.
646: */
647: else if (addr > drvtop[ldhp->l_machine]) {
648: fatal("driver larger than %dKb",
649: (drvtop[ldhp->l_machine]
650: -drvbase[ldhp->l_machine])/1024);
651: }
652:
653: return (addr);
654: }
655:
656: /*
657: * Set segment disk offsets, given sizes
658: * return size of module
659: */
660: fsize_t
661: segoffs(sega, offs)
662: seg_t sega[];
663: register fsize_t offs;
664: {
665: register seg_t *sgp;
666:
667: offs += sizeof(ldh_t);
668:
669: for ( sgp = &sega[0]; sgp < &sega[NLSEG]; sgp++ ) {
670:
671: /*
672: * Uninitialized code/data do not affect module size.
673: */
674: if ( (sgp == &sega[L_BSSI]) || (sgp == &sega[L_BSSD]) )
675: continue;
676:
677: /*
678: * Record segment address.
679: * Calculate module size.
680: */
681: else {
682: sgp->daddr = offs;
683: offs += sgp->size;
684: }
685: }
686:
687: /*
688: * Return module size.
689: */
690: return (offs);
691: }
692:
693: /*
694: * Bump address to next hardware segment boundary
695: */
696: uaddr_t
697: newpage( ldhp, addr )
698: ldh_t *ldhp;
699: uaddr_t addr;
700: {
701: register uaddr_t inc = segsize[ldhp->l_machine]-1;
702:
703: return ((addr+inc)&~inc);
704: }
705:
706: /*
707: * Determine entry point; either octal address or symbol name.
708: */
709: uaddr_t
710: lentry(str)
711: char *str;
712: {
713: char id[NCPLN], *s = &id[0];
714: uaddr_t oaddr=0;
715: int notoct=0;
716: register sym_t *sp;
717:
718: /*
719: * Scan string.
720: */
721: for ( ; *str; str++ ) {
722:
723: if ( s < &id[NCPLN] )
724: *s++ = *str;
725:
726: /*
727: * Accumulate octal digits.
728: */
729: if ( ('0' <= *str) && (*str <= '7') )
730: oaddr = oaddr*8 + *str - '0';
731:
732: /*
733: * Not an octal digit.
734: */
735: else
736: ++notoct;
737: }
738:
739: /*
740: * Octal string: return numeric value.
741: */
742: if (!notoct)
743: return (oaddr);
744:
745: /*
746: * Extend string with nulls.
747: */
748: while ( s < &id[NCPLN] )
749: *s++ = 0;
750:
751: /*
752: * Search for string in symbol table.
753: */
754: for ( sp = symtable[hash(id)]; sp != NULL; sp = sp->next ) {
755: if ( (sp->s.ls_type & L_GLOBAL)
756: && (sp->s.ls_type != (L_GLOBAL|L_REF))
757: && eq(sp->s.ls_id, id) )
758: return( sp->s.ls_addr );
759: }
760:
761: /*
762: * Symbol not found.
763: */
764: message("entry point %.*s undefined", NCPLN, id);
765: return (0);
766: }
767:
768: /*
769: * Define referenced internal symbol (as end of given segment)
770: */
771: void
772: endbind( sp, sn, ldrv )
773: register sym_t *sp;
774: int sn, ldrv;
775: {
776: if ( sp == NULL ) {
777: return;
778: }
779:
780: else if ((sp->s.ls_type == (L_GLOBAL|L_REF)) && (sp->s.ls_addr == 0)) {
781: sp->s.ls_type = L_GLOBAL|sn;
782: sp->s.ls_addr = oseg[sn].size;
783: }
784:
785: else if ( ldrv ) {
786: return;
787: }
788:
789: else {
790: spmsg(sp, "redefines builtin");
791: }
792: }
793:
794: /*
795: * Add reference to symbol table
796: */
797: void
798: undef( s )
799: char * s;
800: {
801: lds_t lds;
802: int i;
803:
804: /*
805: * Copy reference, extending with NULL.
806: */
807: for ( i = 0; i < NCPLN; i++ ) {
808: lds.ls_id[i] = *s;
809: if ( *s != '\0' )
810: s++;
811: }
812:
813: /*
814: * Define symbol as global reference.
815: */
816: lds.ls_type = L_GLOBAL|L_REF;
817: lds.ls_addr = 0;
818:
819: /*
820: * Add [undefined] to symbol table.
821: */
822: addsym(&lds, NULL);
823: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.