|
|
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.