|
|
1.1 root 1: /* ld/pass1.c */
2:
3: #include "data.h"
4:
5: /*
6: * Read input file
7: * If not archive, add it to module list
8: * If archive, add all modules that satisfy global references
9: * iterating until no more can be satisfied
10: * If it is not a ranlib, this must be done the hard way
11: */
12: int
13: rdfile( fname )
14: char * fname;
15: {
16: fsize_t offs, arhend;
17: arh_t arh;
18: struct stat arstat;
19: int magic, found;
20: FILE *ifp;
21:
22: if ( (ifp = fopen(fname, "r")) == NULL )
23: return (0);
24:
25: setbuf( ifp, pbuf1 );
26: fstat( fileno(ifp), &arstat );
27:
28: if ( fread( &magic, sizeof(magic), 1, ifp ) != 1 )
29: fatal( "can't read %s", fname );
30:
31: canint( magic );
32:
33: /*
34: * Not a library.
35: */
36: if ( magic != ARMAG ) {
37: rewind( ifp );
38: addmod( ifp, (fsize_t)0, fname, "" );
39: }
40:
41: /*
42: * Library header extracted.
43: */
44: else if ( fread( &arh, sizeof(arh), 1, ifp ) == 1 ) {
45:
46: cantime( arh.ar_date );
47: cansize( arh.ar_size );
48: arhend = sizeof(magic) + sizeof(arh) + arh.ar_size;
49:
50: /*
51: * Not random library.
52: */
53: if ( strncmp( arh.ar_name, HDRNAME, DIRSIZ ) != 0 ) {
54: arhend = sizeof(magic);
55: }
56:
57: /*
58: * Outdated random library.
59: */
60: else if ( arstat.st_mtime > arh.ar_date+SLOPTIME ) {
61: filemsg( fname, "outdated ranlib" );
62: }
63:
64: /*
65: * Perform exhaustive search of random libraries symbol table.
66: */
67: else {
68: FILE *xfp = fopen( fname, "r" );
69: ars_t ars;
70:
71: setbuf( xfp, pbuf2 );
72:
73: if ( watch )
74: filemsg( fname, "ranlib" );
75:
76: /*
77: * Scan random symbol table.
78: */
79: do {
80: found = 0;
81: fseek( xfp, offs=sizeof(magic)+sizeof(arh), 0);
82:
83: for ( ; offs < arhend; offs += sizeof(ars) ) {
84:
85: if (fread(&ars,sizeof(ars),1,xfp) != 1)
86: break;
87:
88: if ( symref( &ars ) == NULL )
89: continue;
90:
91: cansize( ars.ar_off );
92: fseek( ifp, ars.ar_off+=arhend, 0 );
93:
94: /*
95: * At end of random symbol table.
96: */
97: if (fread(&arh,sizeof(arh),1,ifp) != 1)
98: break;
99:
100: found |= addmod( ifp,
101: ars.ar_off += sizeof(arh),
102: fname, arh.ar_name );
103: }
104: } while ( nundef && found );
105:
106: fclose( xfp );
107: fclose( ifp );
108: return( 1 );
109: }
110:
111: /*
112: * Perform exhaustive search of sequential library.
113: */
114: do {
115: found = 0;
116: fseek( ifp, offs = arhend, 0 );
117:
118: while ( offs < arstat.st_size ) {
119:
120: /*
121: * At end of library.
122: */
123: if ( fread( &arh, sizeof(arh), 1, ifp ) != 1 )
124: break;
125:
126: cansize( arh.ar_size );
127: offs += sizeof(arh);
128: found |= modref(ifp, offs, fname, arh.ar_name);
129: fseek( ifp, offs += arh.ar_size, 0 );
130: }
131: } while ( nundef && found );
132: }
133:
134: fclose( ifp );
135: return( 1 );
136: }
137:
138: /*
139: * Check whether module satisfies any global references.
140: * If so, add the module to the list and return flag indicating success
141: */
142: int
143: modref( fp, offs, fname, mname )
144: FILE *fp;
145: fsize_t offs;
146: char *fname, mname[];
147: {
148: ldh_t ldh;
149: lds_t lds;
150: unsigned int nsym;
151: int i;
152:
153: /*
154: * Read module header.
155: */
156: if( fread( &ldh, sizeof(ldh), 1, fp ) != 1 ) {
157: modmsg( fname, mname, "can't read" );
158: return( 0 );
159: }
160:
161: canint( ldh.l_magic );
162:
163: if ( ldh.l_magic != L_MAGIC ) {
164: modmsg( fname, mname, "bad header" );
165: return( 0 );
166: }
167:
168: for ( i = 0; i < NLSEG; i++ )
169: cansize( ldh.l_ssize[i] );
170:
171: /*
172: * Prepare to read module's symbol table.
173: */
174: fseek( fp, symoff(&ldh), 1 );
175:
176: /*
177: * Scan module's symbol table.
178: */
179: for ( nsym = ldh.l_ssize[L_SYM] / sizeof(lds); nsym; nsym-- ) {
180:
181: /*
182: * Read module symbol table entry.
183: */
184: if ( fread( &lds, sizeof(lds), 1, fp ) != 1 ) {
185: modmsg( fname, mname, "bad symbol segment" );
186: return( 0 );
187: }
188:
189: canint( lds.ls_type );
190:
191: /*
192: * Add module if it contains a global referenced symbol.
193: */
194: if ( (lds.ls_type & L_GLOBAL)
195: && (lds.ls_type != (L_GLOBAL|L_REF))
196: && (symref(&lds) != NULL) ) {
197: fseek( fp, offs, 0 );
198: return( addmod( fp, offs, fname, mname ) );
199: }
200: }
201:
202: return( 0 );
203: }
204:
205: /*
206: * Allocate module descriptor and add to end of list.
207: */
208: int
209: addmod( fp, offs, fname, mname )
210: FILE *fp;
211: fsize_t offs;
212: char *fname, mname[];
213: {
214: mod_t *mp;
215: ldh_t ldh;
216: lds_t lds;
217: int i, segn;
218: unsigned int nsym;
219: sym_t *tmsym;
220:
221: if ( watch ) {
222: modmsg( fname, mname, "adding" );
223: }
224:
225: /*
226: * Read module header.
227: */
228: if ( fread( &ldh, sizeof(ldh), 1, fp ) != 1 ) {
229: modmsg( fname, mname, "can't read" );
230: return( 0 );
231: }
232:
233: canint( ldh.l_magic );
234: canint( ldh.l_flag );
235: canint( ldh.l_machine );
236:
237: for ( i = 0; i < NLSEG; i++ )
238: cansize( ldh.l_ssize[i] );
239:
240: if ( ldh.l_magic != L_MAGIC ) {
241: modmsg( fname, mname, "bad header" );
242: return( 0 );
243: }
244:
245: if ( ldh.l_flag & LF_SEP ) {
246: modmsg( fname, mname, "cannot load separated I/D" );
247: return( 0 );
248: }
249:
250: /*
251: * Machine type not defined yet.
252: */
253: if ( oldh.l_machine == 0 ) {
254:
255: /*
256: * Define machine type and byte ordering.
257: */
258: switch ( oldh.l_machine = ldh.l_machine ) {
259:
260: case M_PDP11:
261: case M_8086:
262: worder = LOHI;
263: break;
264:
265: case M_Z8002:
266: worder = HILO;
267: break;
268:
269: default:
270: modmsg( fname, mname, "can't load %s code (yet)",
271: mchname[ldh.l_machine] );
272: exit( 1 );
273: }
274: }
275:
276: /*
277: * Mismatch on machine type.
278: */
279: else if ( ldh.l_machine != oldh.l_machine ) {
280: modmsg( fname, mname, "inconsistent machine" );
281: return( 0 );
282: }
283:
284: /*
285: * Allocate descriptor, add to list, initialize
286: */
287: nsym = ldh.l_ssize[L_SYM] / sizeof(lds_t);
288:
289: if ( mdisk ) {
290: mp = mtemp;
291: nmod++;
292: fseek( mfp, (long) sizeof(mod_t), 1 );
293: }
294:
295: else {
296: if ( (mp=malloc(sizeof(mod_t)+nsym*sizeof(sym_t *))) == NULL )
297: fatal("out of space");
298:
299: if ( modhead == NULL )
300: modhead = mp;
301:
302: else
303: modtail->next = mp;
304:
305: modtail = mp;
306: mp->next = NULL;
307: }
308:
309: mp->fname = fname;
310:
311: for ( i = 0; i < DIRSIZ; i++ )
312: mp->mname[i] = mname[0] ? mname[i] : 0;
313:
314: for ( i = 0; i < NLSEG; i++ )
315: mp->seg[i].size = ldh.l_ssize[i];
316:
317: baseall( mp->seg, &ldh );
318: segoffs( mp->seg, offs );
319: mp->nsym = nsym;
320:
321: /*
322: * Prepare to read module symbol table.
323: */
324: fseek( fp, symoff(&ldh), 1 );
325:
326: /*
327: * Add symbols
328: */
329: for ( i = 0; i < nsym; i++ ) {
330:
331: /*
332: * Read entry from module symbol table.
333: */
334: if ( fread( &lds, sizeof(lds), 1, fp ) != 1 ) {
335: modmsg( fname, mname, "bad symbol segment" );
336: mp->nsym = i;
337: break;
338: } else {
339: canint( lds.ls_type );
340: canvaddr( lds.ls_addr );
341: segn = lds.ls_type & ~L_GLOBAL;
342:
343: /*
344: * Make symbols segment relative
345: */
346: if ( segn < L_SYM )
347: lds.ls_addr += oseg[segn].size
348: - mp->seg[segn].vbase;
349:
350: if ( mdisk ) {
351: tmsym = addsym( &lds, mp );
352:
353: if ( fwrite(&tmsym,sizeof(tmsym),1,mfp) != 1 )
354: badisk: fatal("disk error");
355: } else
356: mp->sym[i] = addsym( &lds, mp );
357: }
358: }
359:
360: for ( i = 0; i < NLSEG; i++ )
361: if ( i != L_SYM )
362: oseg[i].size += ldh.l_ssize[i];
363:
364: if ( mdisk ) {
365: if ( mxmsym < mp->nsym )
366: mxmsym = mp->nsym;
367:
368: fseek( mfp,(long)-(sizeof(mod_t))-(mp->nsym*sizeof(tmsym)),1 );
369:
370: if( fwrite( mtemp, sizeof(mod_t), 1, mfp ) != 1 )
371: goto badisk;
372:
373: fseek( mfp, (long) mp->nsym * sizeof(tmsym), 1 );
374: }
375:
376: return (1);
377: }
378:
379: /*
380: * Add symbol to symbol table
381: * If match, resolve references and definitions
382: * otherwise, create new symbol entry.
383: * Keep track of number of undefined symbols,
384: * amount of space required by commons,
385: * size of output symbol segment.
386: */
387: sym_t *
388: addsym( lsp, mp )
389: register lds_t *lsp;
390: mod_t *mp;
391: {
392: register sym_t *sp;
393: int h;
394:
395: h = hash( lsp->ls_id );
396:
397: /*
398: * Not a global symbol.
399: */
400: if ( !(lsp->ls_type & L_GLOBAL) ) {
401:
402: /*
403: * Discard if local symbol and required to.
404: */
405: if ( nolcl || noilcl && (lsp->ls_id[0] == 'L') )
406: return( NULL );
407: }
408:
409: /*
410: * Scan internal symbol table.
411: */
412: else for ( sp = symtable[h]; sp != NULL; sp = sp->next ) {
413:
414: if ((sp->s.ls_type & L_GLOBAL) && eq(sp->s.ls_id,lsp->ls_id)) {
415:
416: if ( lsp->ls_type != (L_GLOBAL|L_REF) ) {
417:
418: /*
419: * New def, old def
420: */
421: if ( sp->s.ls_type != (L_GLOBAL|L_REF) )
422: symredef( sp, mp );
423:
424: /*
425: * New def, old ref
426: * common compatible with def
427: */
428: else if ( (sp->s.ls_addr == 0)
429: || commdef(sp->mod, mp, lsp)) {
430: if ( sp->s.ls_addr == 0 )
431: nundef--;
432: sp->s.ls_type = lsp->ls_type;
433: sp->s.ls_addr = lsp->ls_addr;
434: sp->mod = mp;
435: }
436: }
437:
438: /*
439: * New ref, old def
440: */
441: else if ( sp->s.ls_type != (L_GLOBAL|L_REF) ) {
442: if ( lsp->ls_addr != 0 )
443: commdef( mp, sp->mod, &sp->s );
444: }
445:
446: /*
447: * New ref > old ref
448: */
449: else if ( sp->s.ls_addr < lsp->ls_addr ) {
450:
451: /*
452: * Ref becomes comm
453: */
454: if ( sp->s.ls_addr == 0 )
455: nundef--;
456:
457: commons += lsp->ls_addr - sp->s.ls_addr;
458: sp->s.ls_addr = lsp->ls_addr;
459: sp->mod = mp;
460: }
461:
462: return( sp );
463: }
464: }
465:
466: /*
467: * Symbol not found (or is local)
468: */
469: if ( (sp = newsym()) == NULL )
470: fatal("out of space - S");
471:
472: oseg[L_SYM].size += sizeof(lds_t);
473: sp->next = symtable[h];
474: symtable[h] = sp;
475: sp->s = *lsp; /* struct assign */
476: sp->mod = mp;
477:
478: /*
479: * Note reference to internal symbol 'etext', 'edata', or 'end'.
480: */
481: if ( eq( sp->s.ls_id, etext_id ) )
482: etext_s = sp;
483: else if ( eq( sp->s.ls_id, edata_id ) )
484: edata_s = sp;
485: else if ( eq( sp->s.ls_id, end_id ) )
486: end_s = sp;
487:
488: /*
489: * Note reference to global symbol.
490: */
491: else if ( sp->s.ls_type == (L_GLOBAL|L_REF) ) {
492: if ( sp->s.ls_addr == 0 )
493: nundef++;
494: else
495: commons += (uaddr_t)(sp->s.ls_addr);
496: }
497:
498: return( sp );
499: }
500:
501: /*
502: * Allocate a new sym_t from sym_t blocks to reduce malloc overhead.
503: */
504: sym_t *
505: newsym()
506: {
507: static sym_t *symb;
508: static int nsym;
509:
510: /*
511: * Symbol cluster exhaused.
512: */
513: if ( nsym == 0 ) {
514: /*
515: * Allocate new symbol cluster.
516: */
517: if ( (symb = malloc(64*sizeof(sym_t))) == NULL )
518: return (NULL);
519: nsym = 64;
520: }
521:
522: /*
523: * Allocate symbol table entry.
524: */
525: nsym -= 1;
526: return( symb++ );
527: }
528:
529: /*
530: * complain about redefined symbol
531: */
532: void
533: symredef( sp, mp )
534: sym_t *sp;
535: mod_t *mp;
536: {
537: /*
538: * Simple module.
539: */
540: if ( mp->mname[0] == '\0' )
541: spmsg( sp, "redefined in file %s", mp->fname );
542:
543: /*
544: * Library module.
545: */
546: else
547: spmsg( sp, "redefined in file %s: module %.*s",
548: mp->fname, DIRSIZ, mp->mname );
549: }
550:
551: /*
552: * Check if common compatible with symbol definition
553: */
554: int
555: commdef( cmp, dmp, lsp )
556: mod_t *cmp, *dmp;
557: lds_t *lsp;
558: {
559: int type = lsp->ls_type & ~L_GLOBAL;
560:
561: /*
562: * Compatible if not private code or shared data.
563: */
564: if ( (type != L_PRVI) && (type != L_SHRI) )
565: return (1);
566:
567: /*
568: * Incompatible simple module.
569: */
570: if ( dmp->mname[0] == 0 ) {
571: mpmsg( cmp, "common %.*s: conflicts with code in file %s",
572: NCPLN, lsp->ls_id, dmp->fname );
573: }
574:
575: /*
576: * Incompatible library module.
577: */
578: else {
579: mpmsg( cmp,
580: "common %.*s: conflicts with code in file %s: module %.*s",
581: NCPLN, lsp->ls_id, dmp->fname, DIRSIZ, dmp->mname );
582: }
583:
584: return (0);
585: }
586:
587: /*
588: * Add system symbols to symbol table
589: * Make definitions absolute
590: */
591: void
592: rdsystem( sysnam )
593: char * sysnam;
594: {
595: FILE *fp;
596: ldh_t ldh;
597: lds_t lds;
598: sym_t *sp;
599: int i;
600:
601: if ( (fp = fopen(sysnam, "r")) == NULL )
602: fatal("can't open %s", sysnam);
603:
604: /*
605: * Allow null input file
606: */
607: if ( fread( &ldh, sizeof(ldh), 1, fp ) != 1 )
608: return;
609:
610: canint( ldh.l_magic );
611:
612: /*
613: * Not a program.
614: */
615: if ( ldh.l_magic != L_MAGIC ) {
616: filemsg( sysnam, "bad header" );
617: return;
618: }
619:
620: canint( ldh.l_machine );
621:
622: /*
623: * Not the right machine.
624: */
625: if ( ldh.l_machine != oldh.l_machine ) {
626: filemsg( sysnam, "inconsistent machine" );
627: return;
628: }
629:
630: for ( i = 0; i < NLSEG; i++ )
631: cansize( ldh.l_ssize[i] );
632:
633: /*
634: * Prepare to read the system symbol table.
635: */
636: fseek( fp, symoff(&ldh), 1 );
637:
638: /*
639: * Read system symbol table, one entry at a time.
640: */
641: for ( i = ldh.l_ssize[L_SYM] / sizeof(lds); i; i-- ) {
642:
643: /*
644: * Couldn't read entry from system symbol table.
645: */
646: if ( fread( &lds, sizeof(lds), 1, fp ) != 1 ) {
647: filemsg( sysnam, "bad symbol segment" );
648: return;
649: }
650:
651: else {
652: canint( lds.ls_type );
653: canvaddr( lds.ls_addr );
654:
655: /*
656: * If system symbol is global and is referenced,
657: * update reference offset.
658: */
659: if ( (lds.ls_type & L_GLOBAL)
660: && (lds.ls_type != (L_GLOBAL|L_REF))
661: && ((sp = symref(&lds)) != NULL) ) {
662: sp->s.ls_type = L_GLOBAL | L_ABS;
663: sp->s.ls_addr = lds.ls_addr;
664: nundef--;
665: }
666: }
667: }
668: }
669:
670: /*
671: * Return reference to given symbol if any
672: */
673: sym_t *
674: symref( ldsp )
675: union {lds_t lds_f; ars_t ars_f;} *ldsp;
676: {
677: register sym_t *sp;
678:
679: /*
680: * Scan internal symbol table.
681: */
682: for ( sp=symtable[hash(ldsp->lds_f.ls_id)]; sp != NULL; sp=sp->next ) {
683:
684: /*
685: * Reference to given [global] symbol found.
686: */
687: if ( (sp->s.ls_type == (L_GLOBAL|L_REF))
688: && (eq(sp->s.ls_id, ldsp->lds_f.ls_id))
689: && (sp->s.ls_addr == 0) )
690: break;
691: }
692:
693: /*
694: * Return reference, or NULL.
695: */
696: return( sp );
697: }
698:
699: /*
700: * Compute hash index into symbol table by summing chars in name
701: * (mod table length)
702: */
703: int
704: hash( id )
705: char id[];
706: {
707: register char * s = &id[0];
708: register int h;
709: int i;
710:
711: /*
712: * Sum all characters in symbol name.
713: */
714: for ( h = i = 0; *s && (i < NCPLN); i++ )
715: h += *s++;
716:
717: /*
718: * Convert character sum to hash.
719: */
720: return( h % NHASH );
721: }
722:
723: /*
724: * Calculate file offset of symbol segment relative to end of header
725: */
726: fsize_t
727: symoff( ldhp )
728: register ldh_t *ldhp;
729: {
730: register fsize_t offs = 0;
731: register int i;
732:
733: /*
734: * Scan all segments up to [but not including] the symbol segment.
735: */
736: for ( i = 0; i < L_SYM; i++ ) {
737:
738: /*
739: * Uninitialized code/data do not occupy space in the file.
740: */
741: if ( (i == L_BSSI) || (i == L_BSSD) )
742: continue;
743:
744: /*
745: * Adjust offset by segment size.
746: */
747: else
748: offs += ldhp->l_ssize[i];
749: }
750:
751: /*
752: * Return offset of symbol segment.
753: */
754: return( offs );
755: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.