1*615Sbill static char sccsid[] = "@(#)ld.c 3.1 08/15/80"; 2*615Sbill /* 3*615Sbill * VAX VM/UNIX ld - string table version 4*615Sbill */ 5*615Sbill 6*615Sbill #include <sys/types.h> 7*615Sbill #include <signal.h> 8*615Sbill #include <stdio.h> 9*615Sbill #include <ctype.h> 10*615Sbill #include <newar.h> 11*615Sbill #include <newa.out.h> 12*615Sbill #include <ranlib.h> 13*615Sbill #include <stat.h> 14*615Sbill #include <pagsiz.h> 15*615Sbill 16*615Sbill /* 17*615Sbill * Basic strategy: 18*615Sbill * 19*615Sbill * The loader takes a number of files and libraries as arguments. 20*615Sbill * A first pass examines each file in turn. Normal files are 21*615Sbill * unconditionally loaded, and the (external) symbols they define and require 22*615Sbill * are noted in the symbol table. Libraries are searched, and the 23*615Sbill * library members which define needed symbols are remembered 24*615Sbill * in a special data structure so they can be selected on the second 25*615Sbill * pass. Symbols defined and required by library members are also 26*615Sbill * recorded. 27*615Sbill * 28*615Sbill * After the first pass, the loader knows the size of the basic text 29*615Sbill * data, and bss segments from the sum of the sizes of the modules which 30*615Sbill * were required. It has computed, for each ``common'' symbol, the 31*615Sbill * maximum size of any reference to it, and these symbols are then assigned 32*615Sbill * storage locations after their sizes are appropriately rounded. 33*615Sbill * The loader now knows all sizes for the eventual output file, and 34*615Sbill * can determine the final locations of external symbols before it 35*615Sbill * begins a second pass. 36*615Sbill * 37*615Sbill * On the second pass each normal file and required library member 38*615Sbill * is processed again. The symbol table for each such file is 39*615Sbill * reread and relevant parts of it are placed in the output. The offsets 40*615Sbill * in the local symbol table for externally defined symbols are recorded 41*615Sbill * since relocation information refers to symbols in this way. 42*615Sbill * Armed with all necessary information, the text and data segments 43*615Sbill * are relocated and the result is placed in the output file, which 44*615Sbill * is pasted together, ``in place'', by writing to it in several 45*615Sbill * different places concurrently. 46*615Sbill */ 47*615Sbill 48*615Sbill /* 49*615Sbill * Internal data structures 50*615Sbill * 51*615Sbill * All internal data structures are segmented and dynamically extended. 52*615Sbill * The basic structures hold 1103 (NSYM) symbols, ~~200 (NROUT) 53*615Sbill * referenced library members, and 100 (NSYMPR) private (local) symbols 54*615Sbill * per object module. For large programs and/or modules, these structures 55*615Sbill * expand to be up to 40 (NSEG) times as large as this as necessary. 56*615Sbill */ 57*615Sbill #define NSEG 40 /* Number of segments, each data structure */ 58*615Sbill #define NSYM 1103 /* Number of symbols per segment */ 59*615Sbill #define NROUT 250 /* Number of library references per segment */ 60*615Sbill #define NSYMPR 100 /* Number of private symbols per segment */ 61*615Sbill 62*615Sbill /* 63*615Sbill * Structure describing each symbol table segment. 64*615Sbill * Each segment has its own hash table. We record the first 65*615Sbill * address in and first address beyond both the symbol and hash 66*615Sbill * tables, for use in the routine symx and the lookup routine respectively. 67*615Sbill * The symfree routine also understands this structure well as it used 68*615Sbill * to back out symbols from modules we decide that we don't need in pass 1. 69*615Sbill * 70*615Sbill * Csymseg points to the current symbol table segment; 71*615Sbill * csymseg->sy_first[csymseg->sy_used] is the next symbol slot to be allocated, 72*615Sbill * (unless csymseg->sy_used == NSYM in which case we will allocate another 73*615Sbill * symbol table segment first.) 74*615Sbill */ 75*615Sbill struct symseg { 76*615Sbill struct nlist *sy_first; /* base of this alloc'ed segment */ 77*615Sbill struct nlist *sy_last; /* end of this segment, for n_strx */ 78*615Sbill int sy_used; /* symbols used in this seg */ 79*615Sbill struct nlist **sy_hfirst; /* base of hash table, this seg */ 80*615Sbill struct nlist **sy_hlast; /* end of hash table, this seg */ 81*615Sbill } symseg[NSEG], *csymseg; 82*615Sbill 83*615Sbill /* 84*615Sbill * The lookup routine uses quadratic rehash. Since a quadratic rehash 85*615Sbill * only probes 1/2 of the buckets in the table, and since the hash 86*615Sbill * table is segmented the same way the symbol table is, we make the 87*615Sbill * hash table have twice as many buckets as there are symbol table slots 88*615Sbill * in the segment. This guarantees that the quadratic rehash will never 89*615Sbill * fail to find an empty bucket if the segment is not full and the 90*615Sbill * symbol is not there. 91*615Sbill */ 92*615Sbill #define HSIZE (NSYM*2) 93*615Sbill 94*615Sbill /* 95*615Sbill * Xsym converts symbol table indices (ala x) into symbol table pointers. 96*615Sbill * Symx (harder, but never used in loops) inverts pointers into the symbol 97*615Sbill * table into indices using the symseg[] structure. 98*615Sbill */ 99*615Sbill #define xsym(x) (symseg[(x)/NSYM].sy_first+((x)%NSYM)) 100*615Sbill /* symx() is a function, defined below */ 101*615Sbill 102*615Sbill struct nlist cursym; /* current symbol */ 103*615Sbill struct nlist *lastsym; /* last symbol entered */ 104*615Sbill struct nlist *nextsym; /* next available symbol table entry */ 105*615Sbill struct nlist *addsym; /* first sym defined during incr load */ 106*615Sbill int nsym; /* pass2: number of local symbols in a.out */ 107*615Sbill /* nsym + symx(nextsym) is the symbol table size during pass2 */ 108*615Sbill 109*615Sbill struct nlist **lookup(), **slookup(); 110*615Sbill struct nlist *p_data, *p_etext, *p_edata, *p_end, *entrypt; 111*615Sbill 112*615Sbill /* 113*615Sbill * Definitions of segmentation for library member table. 114*615Sbill * For each library we encounter on pass 1 we record pointers to all 115*615Sbill * members which we will load on pass 2. These are recorded as offsets 116*615Sbill * into the archive in the library member table. Libraries are 117*615Sbill * separated in the table by the special offset value -1. 118*615Sbill */ 119*615Sbill off_t li_init[NROUT]; 120*615Sbill struct libseg { 121*615Sbill off_t *li_first; 122*615Sbill int li_used; 123*615Sbill int li_used2; 124*615Sbill } libseg[NSEG] = { 125*615Sbill li_init, 0, 0, 126*615Sbill }, *clibseg = libseg; 127*615Sbill 128*615Sbill /* 129*615Sbill * In processing each module on pass 2 we must relocate references 130*615Sbill * relative to external symbols. These references are recorded 131*615Sbill * in the relocation information as relative to local symbol numbers 132*615Sbill * assigned to the external symbols when the module was created. 133*615Sbill * Thus before relocating the module in pass 2 we create a table 134*615Sbill * which maps these internal numbers to symbol table entries. 135*615Sbill * A hash table is constructed, based on the local symbol table indices, 136*615Sbill * for quick lookup of these symbols. 137*615Sbill * 138*615Sbill * COULD JUST KEEP WHOLE SYMBOL TABLE AROUND. 139*615Sbill */ 140*615Sbill #define LHSIZ 31 141*615Sbill struct local { 142*615Sbill int l_index; /* index to symbol in file */ 143*615Sbill struct nlist *l_symbol; /* ptr to symbol table */ 144*615Sbill struct local *l_link; /* hash link */ 145*615Sbill } *lochash[LHSIZ], lhinit[NSYMPR]; 146*615Sbill struct locseg { 147*615Sbill struct local *lo_first; 148*615Sbill int lo_used; 149*615Sbill } locseg[NSEG] = { 150*615Sbill lhinit, 0 151*615Sbill }, *clocseg; 152*615Sbill 153*615Sbill /* 154*615Sbill * Libraries are typically built with a table of contents, 155*615Sbill * which is the first member of a library with special file 156*615Sbill * name __.SYMDEF and contains a list of symbol names 157*615Sbill * and with each symbol the offset of the library member which defines 158*615Sbill * it. The loader uses this table to quickly tell which library members 159*615Sbill * are (potentially) useful. The alternative, examining the symbol 160*615Sbill * table of each library member, is painfully slow for large archives. 161*615Sbill * 162*615Sbill * See <ranlib.h> for the definition of the ranlib structure and an 163*615Sbill * explanation of the __.SYMDEF file format. 164*615Sbill */ 165*615Sbill int tnum; /* number of symbols in table of contents */ 166*615Sbill int ssiz; /* size of string table for table of contents */ 167*615Sbill struct ranlib *tab; /* the table of contents (dynamically allocated) */ 168*615Sbill char *tabstr; /* string table for table of contents */ 169*615Sbill 170*615Sbill /* 171*615Sbill * We open each input file or library only once, but in pass2 we 172*615Sbill * (historically) read from such a file at 2 different places at the 173*615Sbill * same time. These structures are remnants from those days, 174*615Sbill * and now serve only to catch ``Premature EOF''... soon to be gone... 175*615Sbill */ 176*615Sbill typedef struct { 177*615Sbill short *fakeptr; 178*615Sbill int bno; 179*615Sbill int nibuf; 180*615Sbill int nuser; 181*615Sbill char buff[BSIZE]; 182*615Sbill } PAGE; 183*615Sbill 184*615Sbill PAGE page[2]; 185*615Sbill 186*615Sbill struct { 187*615Sbill short *fakeptr; 188*615Sbill int bno; 189*615Sbill int nibuf; 190*615Sbill int nuser; 191*615Sbill } fpage; 192*615Sbill 193*615Sbill typedef struct { 194*615Sbill char *ptr; 195*615Sbill int bno; 196*615Sbill int nibuf; 197*615Sbill long size; 198*615Sbill long pos; 199*615Sbill PAGE *pno; 200*615Sbill } STREAM; 201*615Sbill 202*615Sbill STREAM text; 203*615Sbill STREAM reloc; 204*615Sbill 205*615Sbill /* 206*615Sbill * Header from the a.out and the archive it is from (if any). 207*615Sbill */ 208*615Sbill struct exec filhdr; 209*615Sbill struct ar_hdr archdr; 210*615Sbill #define OARMAG 0177545 211*615Sbill 212*615Sbill /* 213*615Sbill * Options. 214*615Sbill */ 215*615Sbill int trace; 216*615Sbill int xflag; /* discard local symbols */ 217*615Sbill int Xflag; /* discard locals starting with 'L' */ 218*615Sbill int Sflag; /* discard all except locals and globals*/ 219*615Sbill int rflag; /* preserve relocation bits, don't define common */ 220*615Sbill int arflag; /* original copy of rflag */ 221*615Sbill int sflag; /* discard all symbols */ 222*615Sbill int nflag; /* pure procedure */ 223*615Sbill int dflag; /* define common even with rflag */ 224*615Sbill int zflag = 1; /* demand paged */ 225*615Sbill long hsize; /* size of hole at beginning of data to be squashed */ 226*615Sbill int Aflag; /* doing incremental load */ 227*615Sbill int funding; /* reading fundamental file for incremental load */ 228*615Sbill 229*615Sbill /* 230*615Sbill * These are the cumulative sizes, set in pass 1, which 231*615Sbill * appear in the a.out header when the loader is finished. 232*615Sbill */ 233*615Sbill off_t tsize, dsize, bsize, trsize, drsize, ssize; 234*615Sbill 235*615Sbill /* 236*615Sbill * Symbol relocation: c?rel is a scale factor which is 237*615Sbill * added to an old relocation to convert it to new units; 238*615Sbill * i.e. it is the difference between segment origins. 239*615Sbill */ 240*615Sbill long ctrel, cdrel, cbrel; 241*615Sbill 242*615Sbill /* 243*615Sbill * Textbase is the starting text address, 0 unless given by -H. 244*615Sbill * Database is the base of all data, computed before and used during pass2. 245*615Sbill * The base addresses for the loaded text, data and bss from the 246*615Sbill * current module during pass2 are given by torigin, dorigin and borigin. 247*615Sbill */ 248*615Sbill long textbase, database; 249*615Sbill long torigin, dorigin, borigin; 250*615Sbill 251*615Sbill /* 252*615Sbill * Errlev is nonzero when errors have occured. 253*615Sbill * Delarg is an implicit argument to the routine delexit 254*615Sbill * which is called on error. We do ``delarg = errlev'' before normal 255*615Sbill * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the 256*615Sbill * result file executable. 257*615Sbill */ 258*615Sbill int errlev; 259*615Sbill int delarg = 4; 260*615Sbill 261*615Sbill /* 262*615Sbill * The biobuf structure and associated routines are used to write 263*615Sbill * into one file at several places concurrently. Calling bopen 264*615Sbill * with a biobuf structure sets it up to write ``biofd'' starting 265*615Sbill * at the specified offset. You can then use ``bwrite'' and/or ``bputc'' 266*615Sbill * to stuff characters in the stream, much like ``fwrite'' and ``fputc''. 267*615Sbill * Calling bflush drains all the buffers and MUST be done before exit. 268*615Sbill */ 269*615Sbill struct biobuf { 270*615Sbill short b_nleft; /* Number free spaces left in b_buf */ 271*615Sbill /* Initialize to be less than BUFSIZ initially, to boundary align in file */ 272*615Sbill char *b_ptr; /* Next place to stuff characters */ 273*615Sbill char b_buf[BUFSIZ]; /* The buffer itself */ 274*615Sbill off_t b_off; /* Current file offset */ 275*615Sbill struct biobuf *b_link; /* Link in chain for bflush() */ 276*615Sbill } *biobufs; 277*615Sbill #define bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \ 278*615Sbill : bflushc(b, c)) 279*615Sbill int biofd; 280*615Sbill off_t boffset; 281*615Sbill struct biobuf *tout, *dout, *trout, *drout, *sout, *strout; 282*615Sbill 283*615Sbill /* 284*615Sbill * Offset is the current offset in the string file. 285*615Sbill * Its initial value reflects the fact that we will 286*615Sbill * eventually stuff the size of the string table at the 287*615Sbill * beginning of the string table (i.e. offset itself!). 288*615Sbill */ 289*615Sbill off_t offset = sizeof (off_t); 290*615Sbill 291*615Sbill int ofilfnd; /* -o given; otherwise move l.out to a.out */ 292*615Sbill char *ofilename = "l.out"; 293*615Sbill int infil; /* current input file descriptor */ 294*615Sbill char *filname; /* and its name */ 295*615Sbill 296*615Sbill /* 297*615Sbill * Base of the string table of the current module (pass1 and pass2). 298*615Sbill */ 299*615Sbill char *curstr; 300*615Sbill 301*615Sbill char get(); 302*615Sbill int delexit(); 303*615Sbill char *savestr(); 304*615Sbill 305*615Sbill main(argc, argv) 306*615Sbill char **argv; 307*615Sbill { 308*615Sbill register int c, i; 309*615Sbill int num; 310*615Sbill register char *ap, **p; 311*615Sbill char save; 312*615Sbill 313*615Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 314*615Sbill signal(SIGINT, delexit); 315*615Sbill if (argc == 1) 316*615Sbill exit(4); 317*615Sbill p = argv+1; 318*615Sbill 319*615Sbill /* scan files once to find symdefs */ 320*615Sbill for (c=1; c<argc; c++) { 321*615Sbill if (trace) 322*615Sbill printf("%s:\n", *p); 323*615Sbill filname = 0; 324*615Sbill ap = *p++; 325*615Sbill if (*ap != '-') { 326*615Sbill load1arg(ap); 327*615Sbill continue; 328*615Sbill } 329*615Sbill for (i=1; ap[i]; i++) switch (ap[i]) { 330*615Sbill 331*615Sbill case 'o': 332*615Sbill if (++c >= argc) 333*615Sbill error(1, "-o where?"); 334*615Sbill ofilename = *p++; 335*615Sbill ofilfnd++; 336*615Sbill continue; 337*615Sbill case 'u': 338*615Sbill case 'e': 339*615Sbill if (++c >= argc) 340*615Sbill error(1, "-u or -c: arg missing"); 341*615Sbill enter(slookup(*p++)); 342*615Sbill if (ap[i]=='e') 343*615Sbill entrypt = lastsym; 344*615Sbill continue; 345*615Sbill case 'H': 346*615Sbill if (++c >= argc) 347*615Sbill error(1, "-H: arg missing"); 348*615Sbill if (tsize!=0) 349*615Sbill error(1, "-H: too late, some text already loaded"); 350*615Sbill hsize = atoi(*p++); 351*615Sbill continue; 352*615Sbill case 'A': 353*615Sbill if (++c >= argc) 354*615Sbill error(1, "-A: arg missing"); 355*615Sbill if (Aflag) 356*615Sbill error(1, "-A: only one base file allowed"); 357*615Sbill Aflag = 1; 358*615Sbill nflag = 0; 359*615Sbill funding = 1; 360*615Sbill load1arg(*p++); 361*615Sbill trsize = drsize = tsize = dsize = bsize = 0; 362*615Sbill ctrel = cdrel = cbrel = 0; 363*615Sbill funding = 0; 364*615Sbill addsym = nextsym; 365*615Sbill continue; 366*615Sbill case 'D': 367*615Sbill if (++c >= argc) 368*615Sbill error(1, "-D: arg missing"); 369*615Sbill num = htoi(*p++); 370*615Sbill if (dsize > num) 371*615Sbill error(1, "-D: too small"); 372*615Sbill dsize = num; 373*615Sbill continue; 374*615Sbill case 'T': 375*615Sbill if (++c >= argc) 376*615Sbill error(1, "-T: arg missing"); 377*615Sbill if (tsize!=0) 378*615Sbill error(1, "-T: too late, some text already loaded"); 379*615Sbill textbase = htoi(*p++); 380*615Sbill continue; 381*615Sbill case 'l': 382*615Sbill save = ap[--i]; 383*615Sbill ap[i]='-'; 384*615Sbill load1arg(&ap[i]); 385*615Sbill ap[i]=save; 386*615Sbill goto next; 387*615Sbill case 'x': 388*615Sbill xflag++; 389*615Sbill continue; 390*615Sbill case 'X': 391*615Sbill Xflag++; 392*615Sbill continue; 393*615Sbill case 'S': 394*615Sbill Sflag++; 395*615Sbill continue; 396*615Sbill case 'r': 397*615Sbill rflag++; 398*615Sbill arflag++; 399*615Sbill zflag = 0; 400*615Sbill nflag = 1; 401*615Sbill continue; 402*615Sbill case 's': 403*615Sbill sflag++; 404*615Sbill xflag++; 405*615Sbill continue; 406*615Sbill case 'n': 407*615Sbill nflag++; 408*615Sbill zflag = 0; 409*615Sbill continue; 410*615Sbill case 'N': 411*615Sbill nflag = 0; 412*615Sbill zflag = 0; 413*615Sbill continue; 414*615Sbill case 'd': 415*615Sbill dflag++; 416*615Sbill continue; 417*615Sbill case 'i': 418*615Sbill printf("ld: -i ignored\n"); 419*615Sbill continue; 420*615Sbill case 't': 421*615Sbill trace++; 422*615Sbill continue; 423*615Sbill case 'z': 424*615Sbill zflag++; 425*615Sbill nflag = 0; 426*615Sbill continue; 427*615Sbill default: 428*615Sbill filname = savestr("-x"); /* kludge */ 429*615Sbill filname[1] = ap[i]; /* kludge */ 430*615Sbill archdr.ar_name[0] = 0; /* kludge */ 431*615Sbill error(1, "bad flag"); 432*615Sbill } 433*615Sbill next: 434*615Sbill ; 435*615Sbill } 436*615Sbill endload(argc, argv); 437*615Sbill exit(0); 438*615Sbill } 439*615Sbill 440*615Sbill /* 441*615Sbill * Convert a ascii string which is a hex number. 442*615Sbill * Used by -T and -D options. 443*615Sbill */ 444*615Sbill htoi(p) 445*615Sbill register char *p; 446*615Sbill { 447*615Sbill register int c, n; 448*615Sbill 449*615Sbill n = 0; 450*615Sbill while (c = *p++) { 451*615Sbill n <<= 4; 452*615Sbill if (isdigit(c)) 453*615Sbill n += c - '0'; 454*615Sbill else if (c >= 'a' && c <= 'f') 455*615Sbill n += 10 + (c - 'a'); 456*615Sbill else if (c >= 'A' && c <= 'F') 457*615Sbill n += 10 + (c - 'A'); 458*615Sbill else 459*615Sbill error(1, "badly formed hex number"); 460*615Sbill } 461*615Sbill return (n); 462*615Sbill } 463*615Sbill 464*615Sbill delexit() 465*615Sbill { 466*615Sbill 467*615Sbill bflush(); 468*615Sbill unlink("l.out"); 469*615Sbill if (delarg==0 && Aflag==0) 470*615Sbill chmod(ofilename, 0777 &~ umask(0)); 471*615Sbill exit (delarg); 472*615Sbill } 473*615Sbill 474*615Sbill endload(argc, argv) 475*615Sbill int argc; 476*615Sbill char **argv; 477*615Sbill { 478*615Sbill register int c, i; 479*615Sbill long dnum; 480*615Sbill register char *ap, **p; 481*615Sbill 482*615Sbill clibseg = libseg; 483*615Sbill filname = 0; 484*615Sbill middle(); 485*615Sbill setupout(); 486*615Sbill p = argv+1; 487*615Sbill for (c=1; c<argc; c++) { 488*615Sbill ap = *p++; 489*615Sbill if (trace) 490*615Sbill printf("%s:\n", ap); 491*615Sbill if (*ap != '-') { 492*615Sbill load2arg(ap); 493*615Sbill continue; 494*615Sbill } 495*615Sbill for (i=1; ap[i]; i++) switch (ap[i]) { 496*615Sbill 497*615Sbill case 'D': 498*615Sbill dnum = htoi(*p); 499*615Sbill if (dorigin < dnum) 500*615Sbill while (dorigin < dnum) 501*615Sbill bputc(0, dout), dorigin++; 502*615Sbill /* fall into ... */ 503*615Sbill case 'T': 504*615Sbill case 'u': 505*615Sbill case 'e': 506*615Sbill case 'o': 507*615Sbill case 'H': 508*615Sbill ++c; 509*615Sbill ++p; 510*615Sbill /* fall into ... */ 511*615Sbill default: 512*615Sbill continue; 513*615Sbill case 'A': 514*615Sbill funding = 1; 515*615Sbill load2arg(*p++); 516*615Sbill funding = 0; 517*615Sbill c++; 518*615Sbill continue; 519*615Sbill case 'l': 520*615Sbill ap[--i]='-'; 521*615Sbill load2arg(&ap[i]); 522*615Sbill goto next; 523*615Sbill } 524*615Sbill next: 525*615Sbill ; 526*615Sbill } 527*615Sbill finishout(); 528*615Sbill } 529*615Sbill 530*615Sbill /* 531*615Sbill * Scan file to find defined symbols. 532*615Sbill */ 533*615Sbill load1arg(cp) 534*615Sbill register char *cp; 535*615Sbill { 536*615Sbill register struct ranlib *tp; 537*615Sbill off_t nloc; 538*615Sbill 539*615Sbill switch (getfile(cp)) { 540*615Sbill 541*615Sbill /* 542*615Sbill * Plain file. 543*615Sbill */ 544*615Sbill case 0: 545*615Sbill load1(0, 0L); 546*615Sbill break; 547*615Sbill 548*615Sbill /* 549*615Sbill * Archive without table of contents. 550*615Sbill * (Slowly) process each member. 551*615Sbill */ 552*615Sbill case 1: 553*615Sbill error(-1, "warning: archive has no table of contents"); 554*615Sbill nloc = SARMAG; 555*615Sbill while (step(nloc)) 556*615Sbill nloc += sizeof(archdr) + 557*615Sbill round(atol(archdr.ar_size), sizeof (short)); 558*615Sbill break; 559*615Sbill 560*615Sbill /* 561*615Sbill * Archive with table of contents. 562*615Sbill * Read the table of contents and its associated string table. 563*615Sbill * Pass through the library resolving symbols until nothing changes 564*615Sbill * for an entire pass (i.e. you can get away with backward references 565*615Sbill * when there is a table of contents!) 566*615Sbill */ 567*615Sbill case 2: 568*615Sbill nloc = SARMAG + sizeof (archdr); 569*615Sbill dseek(&text, nloc, sizeof (tnum)); 570*615Sbill mget((char *)&tnum, sizeof (tnum), &text); 571*615Sbill nloc += sizeof (tnum); 572*615Sbill tab = (struct ranlib *)malloc(tnum); 573*615Sbill if (tab == 0) 574*615Sbill error(1, "ran out of memory (toc)"); 575*615Sbill dseek(&text, nloc, tnum); 576*615Sbill mget((char *)tab, tnum, &text); 577*615Sbill nloc += tnum; 578*615Sbill tnum /= sizeof (struct ranlib); 579*615Sbill dseek(&text, nloc, sizeof (ssiz)); 580*615Sbill mget((char *)&ssiz, sizeof (ssiz), &text); 581*615Sbill nloc += sizeof (ssiz); 582*615Sbill tabstr = (char *)malloc(ssiz); 583*615Sbill if (tabstr == 0) 584*615Sbill error(1, "ran out of memory (tocstr)"); 585*615Sbill dseek(&text, nloc, ssiz); 586*615Sbill mget((char *)tabstr, ssiz, &text); 587*615Sbill for (tp = &tab[tnum]; --tp >= tab;) { 588*615Sbill if (tp->ran_un.ran_strx < 0 || 589*615Sbill tp->ran_un.ran_strx >= ssiz) 590*615Sbill error(1, "mangled archive table of contents"); 591*615Sbill tp->ran_un.ran_name = tabstr + tp->ran_un.ran_strx; 592*615Sbill } 593*615Sbill while (ldrand()) 594*615Sbill continue; 595*615Sbill cfree((char *)tab); 596*615Sbill cfree(tabstr); 597*615Sbill nextlibp(-1); 598*615Sbill break; 599*615Sbill 600*615Sbill /* 601*615Sbill * Table of contents is out of date, so search 602*615Sbill * as a normal library (but skip the __.SYMDEF file). 603*615Sbill */ 604*615Sbill case 3: 605*615Sbill error(-1, "warning: table of contents is out of date"); 606*615Sbill nloc = SARMAG; 607*615Sbill do 608*615Sbill nloc += sizeof(archdr) + 609*615Sbill round(atol(archdr.ar_size), sizeof(short)); 610*615Sbill while (step(nloc)); 611*615Sbill break; 612*615Sbill } 613*615Sbill close(infil); 614*615Sbill } 615*615Sbill 616*615Sbill /* 617*615Sbill * Advance to the next archive member, which 618*615Sbill * is at offset nloc in the archive. If the member 619*615Sbill * is useful, record its location in the liblist structure 620*615Sbill * for use in pass2. Mark the end of the archive in libilst with a -1. 621*615Sbill */ 622*615Sbill step(nloc) 623*615Sbill off_t nloc; 624*615Sbill { 625*615Sbill 626*615Sbill dseek(&text, nloc, (long) sizeof archdr); 627*615Sbill if (text.size <= 0) { 628*615Sbill nextlibp(-1); 629*615Sbill return (0); 630*615Sbill } 631*615Sbill getarhdr(); 632*615Sbill if (load1(1, nloc + (sizeof archdr))) 633*615Sbill nextlibp(nloc); 634*615Sbill return (1); 635*615Sbill } 636*615Sbill 637*615Sbill /* 638*615Sbill * Record the location of a useful archive member. 639*615Sbill * Recording -1 marks the end of files from an archive. 640*615Sbill * The liblist data structure is dynamically extended here. 641*615Sbill */ 642*615Sbill nextlibp(val) 643*615Sbill off_t val; 644*615Sbill { 645*615Sbill 646*615Sbill if (clibseg->li_used == NROUT) { 647*615Sbill if (++clibseg == &libseg[NSEG]) 648*615Sbill error(1, "too many files loaded from libraries"); 649*615Sbill clibseg->li_first = (off_t *)malloc(NROUT * sizeof (off_t)); 650*615Sbill if (clibseg->li_first == 0) 651*615Sbill error(1, "ran out of memory (nextlibp)"); 652*615Sbill } 653*615Sbill clibseg->li_first[clibseg->li_used++] = val; 654*615Sbill } 655*615Sbill 656*615Sbill /* 657*615Sbill * One pass over an archive with a table of contents. 658*615Sbill * Remember the number of symbols currently defined, 659*615Sbill * then call step on members which look promising (i.e. 660*615Sbill * that define a symbol which is currently externally undefined). 661*615Sbill * Indicate to our caller whether this process netted any more symbols. 662*615Sbill */ 663*615Sbill ldrand() 664*615Sbill { 665*615Sbill register struct nlist *sp, **hp; 666*615Sbill register struct ranlib *tp, *tplast; 667*615Sbill off_t loc; 668*615Sbill int nsymt = symx(nextsym); 669*615Sbill 670*615Sbill tplast = &tab[tnum-1]; 671*615Sbill for (tp = tab; tp <= tplast; tp++) { 672*615Sbill if ((hp = slookup(tp->ran_un.ran_name)) == 0) 673*615Sbill continue; 674*615Sbill sp = *hp; 675*615Sbill if (sp->n_type != N_EXT+N_UNDF) 676*615Sbill continue; 677*615Sbill step(tp->ran_off); 678*615Sbill loc = tp->ran_off; 679*615Sbill while (tp < tplast && (tp+1)->ran_off == loc) 680*615Sbill tp++; 681*615Sbill } 682*615Sbill return (symx(nextsym) != nsymt); 683*615Sbill } 684*615Sbill 685*615Sbill /* 686*615Sbill * Examine a single file or archive member on pass 1. 687*615Sbill */ 688*615Sbill load1(libflg, loc) 689*615Sbill off_t loc; 690*615Sbill { 691*615Sbill register struct nlist *sp; 692*615Sbill struct nlist *savnext; 693*615Sbill int ndef, nlocal, type, size, nsymt; 694*615Sbill register int i; 695*615Sbill off_t maxoff; 696*615Sbill struct stat stb; 697*615Sbill 698*615Sbill readhdr(loc); 699*615Sbill if (filhdr.a_syms == 0) { 700*615Sbill if (filhdr.a_text+filhdr.a_data == 0) 701*615Sbill return (0); 702*615Sbill error(1, "no namelist"); 703*615Sbill } 704*615Sbill if (libflg) 705*615Sbill maxoff = atol(archdr.ar_size); 706*615Sbill else { 707*615Sbill fstat(infil, &stb); 708*615Sbill maxoff = stb.st_size; 709*615Sbill } 710*615Sbill if (N_STROFF(filhdr) + sizeof (off_t) >= maxoff) 711*615Sbill error(1, "too small (old format .o?)"); 712*615Sbill ctrel = tsize; cdrel += dsize; cbrel += bsize; 713*615Sbill ndef = 0; 714*615Sbill nlocal = sizeof(cursym); 715*615Sbill savnext = nextsym; 716*615Sbill loc += N_SYMOFF(filhdr); 717*615Sbill dseek(&text, loc, filhdr.a_syms); 718*615Sbill dseek(&reloc, loc + filhdr.a_syms, sizeof(off_t)); 719*615Sbill mget(&size, sizeof (size), &reloc); 720*615Sbill dseek(&reloc, loc + filhdr.a_syms+sizeof (off_t), size-sizeof (off_t)); 721*615Sbill curstr = (char *)malloc(size); 722*615Sbill if (curstr == NULL) 723*615Sbill error(1, "no space for string table"); 724*615Sbill mget(curstr+sizeof(off_t), size-sizeof(off_t), &reloc); 725*615Sbill while (text.size > 0) { 726*615Sbill mget((char *)&cursym, sizeof(struct nlist), &text); 727*615Sbill if (cursym.n_un.n_strx) { 728*615Sbill if (cursym.n_un.n_strx<sizeof(size) || 729*615Sbill cursym.n_un.n_strx>=size) 730*615Sbill error(1, "bad string table index (pass 1)"); 731*615Sbill cursym.n_un.n_name = curstr + cursym.n_un.n_strx; 732*615Sbill } 733*615Sbill type = cursym.n_type; 734*615Sbill if ((type&N_EXT)==0) { 735*615Sbill if (Xflag==0 || cursym.n_un.n_name[0]!='L' || 736*615Sbill type & N_STAB) 737*615Sbill nlocal += sizeof cursym; 738*615Sbill continue; 739*615Sbill } 740*615Sbill symreloc(); 741*615Sbill if (enter(lookup())) 742*615Sbill continue; 743*615Sbill if ((sp = lastsym)->n_type != N_EXT+N_UNDF) 744*615Sbill continue; 745*615Sbill if (cursym.n_type == N_EXT+N_UNDF) { 746*615Sbill if (cursym.n_value > sp->n_value) 747*615Sbill sp->n_value = cursym.n_value; 748*615Sbill continue; 749*615Sbill } 750*615Sbill if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT) 751*615Sbill continue; 752*615Sbill ndef++; 753*615Sbill sp->n_type = cursym.n_type; 754*615Sbill sp->n_value = cursym.n_value; 755*615Sbill } 756*615Sbill if (libflg==0 || ndef) { 757*615Sbill tsize += filhdr.a_text; 758*615Sbill dsize += round(filhdr.a_data, sizeof (long)); 759*615Sbill bsize += round(filhdr.a_bss, sizeof (long)); 760*615Sbill ssize += nlocal; 761*615Sbill trsize += filhdr.a_trsize; 762*615Sbill drsize += filhdr.a_drsize; 763*615Sbill if (funding) 764*615Sbill textbase = (*slookup("_end"))->n_value; 765*615Sbill nsymt = symx(nextsym); 766*615Sbill for (i = symx(savnext); i < nsymt; i++) { 767*615Sbill sp = xsym(i); 768*615Sbill sp->n_un.n_name = savestr(sp->n_un.n_name); 769*615Sbill } 770*615Sbill free(curstr); 771*615Sbill return (1); 772*615Sbill } 773*615Sbill /* 774*615Sbill * No symbols defined by this library member. 775*615Sbill * Rip out the hash table entries and reset the symbol table. 776*615Sbill */ 777*615Sbill symfree(savnext); 778*615Sbill free(curstr); 779*615Sbill return(0); 780*615Sbill } 781*615Sbill 782*615Sbill middle() 783*615Sbill { 784*615Sbill register struct nlist *sp; 785*615Sbill long csize, t, corigin, ocsize; 786*615Sbill int nund, rnd; 787*615Sbill char s; 788*615Sbill register int i; 789*615Sbill int nsymt; 790*615Sbill 791*615Sbill torigin = 0; 792*615Sbill dorigin = 0; 793*615Sbill borigin = 0; 794*615Sbill 795*615Sbill p_data = *slookup("_data"); 796*615Sbill p_etext = *slookup("_etext"); 797*615Sbill p_edata = *slookup("_edata"); 798*615Sbill p_end = *slookup("_end"); 799*615Sbill /* 800*615Sbill * If there are any undefined symbols, save the relocation bits. 801*615Sbill */ 802*615Sbill nsymt = symx(nextsym); 803*615Sbill if (rflag==0) { 804*615Sbill for (i = 0; i < nsymt; i++) { 805*615Sbill sp = xsym(i); 806*615Sbill if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 && 807*615Sbill sp!=p_end && sp!=p_edata && 808*615Sbill sp!=p_etext && sp!=p_data) { 809*615Sbill rflag++; 810*615Sbill dflag = 0; 811*615Sbill break; 812*615Sbill } 813*615Sbill } 814*615Sbill } 815*615Sbill if (rflag) 816*615Sbill sflag = zflag = 0; 817*615Sbill /* 818*615Sbill * Assign common locations. 819*615Sbill */ 820*615Sbill csize = 0; 821*615Sbill if (!Aflag) 822*615Sbill addsym = symseg[0].sy_first; 823*615Sbill database = round(tsize+textbase, 824*615Sbill (nflag||zflag? PAGSIZ : sizeof (long))); 825*615Sbill database += hsize; 826*615Sbill if (dflag || rflag==0) { 827*615Sbill ldrsym(p_data, (long)0 , N_EXT+N_DATA); 828*615Sbill ldrsym(p_etext, tsize, N_EXT+N_TEXT); 829*615Sbill ldrsym(p_edata, dsize, N_EXT+N_DATA); 830*615Sbill ldrsym(p_end, bsize, N_EXT+N_BSS); 831*615Sbill for (i = symx(addsym); i < nsymt; i++) { 832*615Sbill sp = xsym(i); 833*615Sbill if ((s=sp->n_type)==N_EXT+N_UNDF && 834*615Sbill (t = sp->n_value)!=0) { 835*615Sbill if (t >= sizeof (double)) 836*615Sbill rnd = sizeof (double); 837*615Sbill else if (t >= sizeof (long)) 838*615Sbill rnd = sizeof (long); 839*615Sbill else 840*615Sbill rnd = sizeof (short); 841*615Sbill csize = round(csize, rnd); 842*615Sbill sp->n_value = csize; 843*615Sbill sp->n_type = N_EXT+N_COMM; 844*615Sbill ocsize = csize; 845*615Sbill csize += t; 846*615Sbill } 847*615Sbill if (s&N_EXT && (s&N_TYPE)==N_UNDF && s&N_STAB) { 848*615Sbill sp->n_value = ocsize; 849*615Sbill sp->n_type = (s&N_STAB) | (N_EXT+N_COMM); 850*615Sbill } 851*615Sbill } 852*615Sbill } 853*615Sbill /* 854*615Sbill * Now set symbols to their final value 855*615Sbill */ 856*615Sbill csize = round(csize, sizeof (long)); 857*615Sbill torigin = textbase; 858*615Sbill dorigin = database; 859*615Sbill corigin = dorigin + dsize; 860*615Sbill borigin = corigin + csize; 861*615Sbill nund = 0; 862*615Sbill nsymt = symx(nextsym); 863*615Sbill for (i = symx(addsym); i<nsymt; i++) { 864*615Sbill sp = xsym(i); 865*615Sbill switch (sp->n_type & (N_TYPE+N_EXT)) { 866*615Sbill 867*615Sbill case N_EXT+N_UNDF: 868*615Sbill errlev |= 01; 869*615Sbill if ((arflag==0 || dflag) && sp->n_value==0) { 870*615Sbill if (nund==0) 871*615Sbill printf("Undefined:\n"); 872*615Sbill nund++; 873*615Sbill printf("%s\n", sp->n_un.n_name); 874*615Sbill } 875*615Sbill continue; 876*615Sbill case N_EXT+N_ABS: 877*615Sbill default: 878*615Sbill continue; 879*615Sbill case N_EXT+N_TEXT: 880*615Sbill sp->n_value += torigin; 881*615Sbill continue; 882*615Sbill case N_EXT+N_DATA: 883*615Sbill sp->n_value += dorigin; 884*615Sbill continue; 885*615Sbill case N_EXT+N_BSS: 886*615Sbill sp->n_value += borigin; 887*615Sbill continue; 888*615Sbill case N_EXT+N_COMM: 889*615Sbill sp->n_type = (sp->n_type & N_STAB) | (N_EXT+N_BSS); 890*615Sbill sp->n_value += corigin; 891*615Sbill continue; 892*615Sbill } 893*615Sbill } 894*615Sbill if (sflag || xflag) 895*615Sbill ssize = 0; 896*615Sbill bsize += csize; 897*615Sbill nsym = ssize / (sizeof cursym); 898*615Sbill if (Aflag) { 899*615Sbill fixspec(p_data,dorigin); 900*615Sbill fixspec(p_etext,torigin); 901*615Sbill fixspec(p_edata,dorigin); 902*615Sbill fixspec(p_end,borigin); 903*615Sbill } 904*615Sbill } 905*615Sbill 906*615Sbill fixspec(sym,offset) 907*615Sbill struct nlist *sym; 908*615Sbill long offset; 909*615Sbill { 910*615Sbill 911*615Sbill if(symx(sym) < symx(addsym) && sym!=0) 912*615Sbill sym->n_value += offset; 913*615Sbill } 914*615Sbill 915*615Sbill ldrsym(sp, val, type) 916*615Sbill register struct nlist *sp; 917*615Sbill long val; 918*615Sbill { 919*615Sbill 920*615Sbill if (sp == 0) 921*615Sbill return; 922*615Sbill if ((sp->n_type != N_EXT+N_UNDF || sp->n_value) && !Aflag) { 923*615Sbill printf("%s: ", sp->n_un.n_name); 924*615Sbill error(0, "user attempt to redfine loader-defined symbol"); 925*615Sbill return; 926*615Sbill } 927*615Sbill sp->n_type = type; 928*615Sbill sp->n_value = val; 929*615Sbill } 930*615Sbill 931*615Sbill off_t wroff; 932*615Sbill struct biobuf toutb; 933*615Sbill 934*615Sbill setupout() 935*615Sbill { 936*615Sbill int bss; 937*615Sbill 938*615Sbill biofd = creat(ofilename, 0666); 939*615Sbill if (biofd < 0) 940*615Sbill error(1, "cannot create output"); 941*615Sbill tout = &toutb; 942*615Sbill bopen(tout, 0); 943*615Sbill filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC); 944*615Sbill filhdr.a_text = nflag ? tsize : 945*615Sbill round(tsize, zflag ? PAGSIZ : sizeof (long)); 946*615Sbill filhdr.a_data = zflag ? round(dsize, PAGSIZ) : dsize; 947*615Sbill bss = bsize - (filhdr.a_data - dsize); 948*615Sbill if (bss < 0) 949*615Sbill bss = 0; 950*615Sbill filhdr.a_bss = bss; 951*615Sbill filhdr.a_trsize = trsize; 952*615Sbill filhdr.a_drsize = drsize; 953*615Sbill filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*symx(nextsym)); 954*615Sbill if (entrypt) { 955*615Sbill if (entrypt->n_type!=N_EXT+N_TEXT) 956*615Sbill error(0, "entry point not in text"); 957*615Sbill else 958*615Sbill filhdr.a_entry = entrypt->n_value; 959*615Sbill } else 960*615Sbill filhdr.a_entry = 0; 961*615Sbill filhdr.a_trsize = (rflag ? trsize:0); 962*615Sbill filhdr.a_drsize = (rflag ? drsize:0); 963*615Sbill bwrite((char *)&filhdr, sizeof (filhdr), tout); 964*615Sbill if (zflag) { 965*615Sbill bflush1(tout); 966*615Sbill biobufs = 0; 967*615Sbill bopen(tout, PAGSIZ); 968*615Sbill } 969*615Sbill wroff = N_TXTOFF(filhdr) + filhdr.a_text; 970*615Sbill outb(&dout, filhdr.a_data); 971*615Sbill if (rflag) { 972*615Sbill outb(&trout, filhdr.a_trsize); 973*615Sbill outb(&drout, filhdr.a_drsize); 974*615Sbill } 975*615Sbill if (sflag==0 || xflag==0) { 976*615Sbill outb(&sout, filhdr.a_syms); 977*615Sbill wroff += sizeof (offset); 978*615Sbill outb(&strout, 0); 979*615Sbill } 980*615Sbill } 981*615Sbill 982*615Sbill outb(bp, inc) 983*615Sbill register struct biobuf **bp; 984*615Sbill { 985*615Sbill 986*615Sbill *bp = (struct biobuf *)malloc(sizeof (struct biobuf)); 987*615Sbill if (*bp == 0) 988*615Sbill error(1, "ran out of memory (outb)"); 989*615Sbill bopen(*bp, wroff); 990*615Sbill wroff += inc; 991*615Sbill } 992*615Sbill 993*615Sbill load2arg(acp) 994*615Sbill char *acp; 995*615Sbill { 996*615Sbill register char *cp; 997*615Sbill off_t loc; 998*615Sbill 999*615Sbill cp = acp; 1000*615Sbill if (getfile(cp) == 0) { 1001*615Sbill while (*cp) 1002*615Sbill cp++; 1003*615Sbill while (cp >= acp && *--cp != '/'); 1004*615Sbill mkfsym(++cp); 1005*615Sbill load2(0L); 1006*615Sbill } else { /* scan archive members referenced */ 1007*615Sbill for (;;) { 1008*615Sbill if (clibseg->li_used2 == clibseg->li_used) { 1009*615Sbill if (clibseg->li_used < NROUT) 1010*615Sbill error(1, "libseg botch"); 1011*615Sbill clibseg++; 1012*615Sbill } 1013*615Sbill loc = clibseg->li_first[clibseg->li_used2++]; 1014*615Sbill if (loc == -1) 1015*615Sbill break; 1016*615Sbill dseek(&text, loc, (long)sizeof(archdr)); 1017*615Sbill getarhdr(); 1018*615Sbill mkfsym(archdr.ar_name); 1019*615Sbill load2(loc + (long)sizeof(archdr)); 1020*615Sbill } 1021*615Sbill } 1022*615Sbill close(infil); 1023*615Sbill } 1024*615Sbill 1025*615Sbill load2(loc) 1026*615Sbill long loc; 1027*615Sbill { 1028*615Sbill int size; 1029*615Sbill register struct nlist *sp; 1030*615Sbill register struct local *lp; 1031*615Sbill register int symno, i; 1032*615Sbill int type; 1033*615Sbill 1034*615Sbill readhdr(loc); 1035*615Sbill if(!funding) { 1036*615Sbill ctrel = torigin; 1037*615Sbill cdrel += dorigin; 1038*615Sbill cbrel += borigin; 1039*615Sbill } 1040*615Sbill /* 1041*615Sbill * Reread the symbol table, recording the numbering 1042*615Sbill * of symbols for fixing external references. 1043*615Sbill */ 1044*615Sbill for (i = 0; i < LHSIZ; i++) 1045*615Sbill lochash[i] = 0; 1046*615Sbill clocseg = locseg; 1047*615Sbill clocseg->lo_used = 0; 1048*615Sbill symno = -1; 1049*615Sbill loc += N_TXTOFF(filhdr); 1050*615Sbill dseek(&text, loc+filhdr.a_text+filhdr.a_data+ 1051*615Sbill filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t)); 1052*615Sbill mget(&size, sizeof(size), &text); 1053*615Sbill dseek(&text, loc+filhdr.a_text+filhdr.a_data+ 1054*615Sbill filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t), 1055*615Sbill size - sizeof(off_t)); 1056*615Sbill curstr = (char *)malloc(size); 1057*615Sbill if (curstr == NULL) 1058*615Sbill error(1, "out of space reading string table (pass 2)"); 1059*615Sbill mget(curstr+sizeof(off_t), size-sizeof(off_t), &text); 1060*615Sbill dseek(&text, loc+filhdr.a_text+filhdr.a_data+ 1061*615Sbill filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms); 1062*615Sbill while (text.size > 0) { 1063*615Sbill symno++; 1064*615Sbill mget((char *)&cursym, sizeof(struct nlist), &text); 1065*615Sbill if (cursym.n_un.n_strx) { 1066*615Sbill if (cursym.n_un.n_strx<sizeof(size) || 1067*615Sbill cursym.n_un.n_strx>=size) 1068*615Sbill error(1, "bad string table index (pass 2)"); 1069*615Sbill cursym.n_un.n_name = curstr + cursym.n_un.n_strx; 1070*615Sbill } 1071*615Sbill /* inline expansion of symreloc() */ 1072*615Sbill switch (cursym.n_type & 017) { 1073*615Sbill 1074*615Sbill case N_TEXT: 1075*615Sbill case N_EXT+N_TEXT: 1076*615Sbill cursym.n_value += ctrel; 1077*615Sbill break; 1078*615Sbill case N_DATA: 1079*615Sbill case N_EXT+N_DATA: 1080*615Sbill cursym.n_value += cdrel; 1081*615Sbill break; 1082*615Sbill case N_BSS: 1083*615Sbill case N_EXT+N_BSS: 1084*615Sbill cursym.n_value += cbrel; 1085*615Sbill break; 1086*615Sbill case N_EXT+N_UNDF: 1087*615Sbill break; 1088*615Sbill default: 1089*615Sbill if (cursym.n_type&N_EXT) 1090*615Sbill cursym.n_type = N_EXT+N_ABS; 1091*615Sbill } 1092*615Sbill /* end inline expansion of symreloc() */ 1093*615Sbill type = cursym.n_type; 1094*615Sbill if ((type&N_EXT) == 0) { 1095*615Sbill if (!sflag&&!xflag&& 1096*615Sbill (!Xflag||cursym.n_un.n_name[0]!='L'||type&N_STAB)) 1097*615Sbill symwrite(&cursym, sout); 1098*615Sbill continue; 1099*615Sbill } 1100*615Sbill if (funding) 1101*615Sbill continue; 1102*615Sbill if ((sp = *lookup()) == 0) 1103*615Sbill error(1, "internal error: symbol not found"); 1104*615Sbill if (cursym.n_type == N_EXT+N_UNDF) { 1105*615Sbill if (clocseg->lo_used == NSYMPR) { 1106*615Sbill if (++clocseg == &locseg[NSEG]) 1107*615Sbill error(1, "local symbol overflow"); 1108*615Sbill clocseg->lo_used = 0; 1109*615Sbill } 1110*615Sbill if (clocseg->lo_first == 0) { 1111*615Sbill clocseg->lo_first = (struct local *) 1112*615Sbill malloc(NSYMPR * sizeof (struct local)); 1113*615Sbill if (clocseg->lo_first == 0) 1114*615Sbill error(1, "out of memory (clocseg)"); 1115*615Sbill } 1116*615Sbill lp = &clocseg->lo_first[clocseg->lo_used++]; 1117*615Sbill lp->l_index = symno; 1118*615Sbill lp->l_symbol = sp; 1119*615Sbill lp->l_link = lochash[symno % LHSIZ]; 1120*615Sbill lochash[symno % LHSIZ] = lp; 1121*615Sbill continue; 1122*615Sbill } 1123*615Sbill if (cursym.n_type & N_STAB) 1124*615Sbill continue; 1125*615Sbill if (cursym.n_type!=sp->n_type || cursym.n_value!=sp->n_value) { 1126*615Sbill printf("%s: ", cursym.n_un.n_name); 1127*615Sbill error(0, "multiply defined"); 1128*615Sbill } 1129*615Sbill } 1130*615Sbill if (funding) 1131*615Sbill return; 1132*615Sbill dseek(&text, loc, filhdr.a_text); 1133*615Sbill dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize); 1134*615Sbill load2td(ctrel, tout, trout); 1135*615Sbill dseek(&text, loc+filhdr.a_text, filhdr.a_data); 1136*615Sbill dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize, 1137*615Sbill filhdr.a_drsize); 1138*615Sbill load2td(cdrel, dout, drout); 1139*615Sbill while (filhdr.a_data & (sizeof(long)-1)) { 1140*615Sbill bputc(0, dout); 1141*615Sbill filhdr.a_data++; 1142*615Sbill } 1143*615Sbill torigin += filhdr.a_text; 1144*615Sbill dorigin += filhdr.a_data; 1145*615Sbill borigin += filhdr.a_bss; 1146*615Sbill free(curstr); 1147*615Sbill } 1148*615Sbill 1149*615Sbill load2td(creloc, b1, b2) 1150*615Sbill long creloc; 1151*615Sbill struct biobuf *b1, *b2; 1152*615Sbill { 1153*615Sbill register struct nlist *sp; 1154*615Sbill register struct local *lp; 1155*615Sbill long tw; 1156*615Sbill register struct relocation_info *rp, *rpend; 1157*615Sbill long address; 1158*615Sbill struct relocation_info *relp; 1159*615Sbill char *codep; 1160*615Sbill register char *cp; 1161*615Sbill int relsz, codesz; 1162*615Sbill 1163*615Sbill relsz = reloc.size; 1164*615Sbill relp = (struct relocation_info *)malloc(relsz); 1165*615Sbill codesz = text.size; 1166*615Sbill codep = (char *)malloc(codesz); 1167*615Sbill if (relp == 0 || codep == 0) 1168*615Sbill error(1, "out of memory (load2td)"); 1169*615Sbill mget((char *)relp, relsz, &reloc); 1170*615Sbill rpend = &relp[relsz / sizeof (struct relocation_info)]; 1171*615Sbill mget(codep, codesz, &text); 1172*615Sbill for (rp = relp; rp < rpend; rp++) { 1173*615Sbill if (rflag) 1174*615Sbill address = rp->r_address + creloc; 1175*615Sbill cp = codep + rp->r_address; 1176*615Sbill switch (rp->r_length) { 1177*615Sbill 1178*615Sbill case 0: /* byte */ 1179*615Sbill tw = *cp; 1180*615Sbill break; 1181*615Sbill 1182*615Sbill case 1: /* word */ 1183*615Sbill tw = *(short *)cp; 1184*615Sbill break; 1185*615Sbill 1186*615Sbill case 2: /* long */ 1187*615Sbill tw = *(long *)cp; 1188*615Sbill break; 1189*615Sbill 1190*615Sbill default: 1191*615Sbill error(1, "load2td botch: bad length"); 1192*615Sbill } 1193*615Sbill if (rp->r_extern) { 1194*615Sbill lp = lochash[rp->r_symbolnum % LHSIZ]; 1195*615Sbill while (lp->l_index != rp->r_symbolnum) { 1196*615Sbill lp = lp->l_link; 1197*615Sbill if (lp == 0) 1198*615Sbill error(1, "local symbol botch"); 1199*615Sbill } 1200*615Sbill sp = lp->l_symbol; 1201*615Sbill if (sp->n_type == N_EXT+N_UNDF) 1202*615Sbill rp->r_symbolnum = nsym+symx(sp); 1203*615Sbill else { 1204*615Sbill rp->r_symbolnum = sp->n_type & N_TYPE; 1205*615Sbill tw += sp->n_value; 1206*615Sbill rp->r_extern = 0; 1207*615Sbill } 1208*615Sbill } else switch (rp->r_symbolnum & N_TYPE) { 1209*615Sbill 1210*615Sbill case N_TEXT: 1211*615Sbill tw += ctrel; 1212*615Sbill break; 1213*615Sbill case N_DATA: 1214*615Sbill tw += cdrel; 1215*615Sbill break; 1216*615Sbill case N_BSS: 1217*615Sbill tw += cbrel; 1218*615Sbill break; 1219*615Sbill case N_ABS: 1220*615Sbill break; 1221*615Sbill default: 1222*615Sbill error(1, "relocation format botch (symbol type))"); 1223*615Sbill } 1224*615Sbill if (rp->r_pcrel) 1225*615Sbill /* assembler already subtracted text.pos */ 1226*615Sbill tw -= creloc; 1227*615Sbill switch (rp->r_length) { 1228*615Sbill 1229*615Sbill case 0: /* byte */ 1230*615Sbill if (tw < -128 || tw > 127) 1231*615Sbill error(0, "byte displacement overflow"); 1232*615Sbill *cp = tw; 1233*615Sbill break; 1234*615Sbill case 1: /* word */ 1235*615Sbill if (tw < -32768 || tw > 32767) 1236*615Sbill error(0, "word displacement overflow"); 1237*615Sbill *(short *)cp = tw; 1238*615Sbill break; 1239*615Sbill case 2: /* long */ 1240*615Sbill *(long *)cp = tw; 1241*615Sbill break; 1242*615Sbill } 1243*615Sbill if (rflag) 1244*615Sbill rp->r_address = address; 1245*615Sbill } 1246*615Sbill bwrite(codep, codesz, b1); 1247*615Sbill if (rflag) 1248*615Sbill bwrite(relp, relsz, b2); 1249*615Sbill cfree((char *)relp); 1250*615Sbill cfree(codep); 1251*615Sbill } 1252*615Sbill 1253*615Sbill finishout() 1254*615Sbill { 1255*615Sbill register int i; 1256*615Sbill int nsymt; 1257*615Sbill 1258*615Sbill if (sflag==0) { 1259*615Sbill nsymt = symx(nextsym); 1260*615Sbill for (i = 0; i < nsymt; i++) 1261*615Sbill symwrite(xsym(i), sout); 1262*615Sbill bwrite(&offset, sizeof offset, sout); 1263*615Sbill } 1264*615Sbill if (!ofilfnd) { 1265*615Sbill unlink("a.out"); 1266*615Sbill link("l.out", "a.out"); 1267*615Sbill ofilename = "a.out"; 1268*615Sbill } 1269*615Sbill delarg = errlev; 1270*615Sbill delexit(); 1271*615Sbill } 1272*615Sbill 1273*615Sbill mkfsym(s) 1274*615Sbill char *s; 1275*615Sbill { 1276*615Sbill 1277*615Sbill if (sflag || xflag) 1278*615Sbill return; 1279*615Sbill cursym.n_un.n_name = s; 1280*615Sbill cursym.n_type = N_TEXT; 1281*615Sbill cursym.n_value = torigin; 1282*615Sbill symwrite(&cursym, sout); 1283*615Sbill } 1284*615Sbill 1285*615Sbill getarhdr() 1286*615Sbill { 1287*615Sbill register char *cp; 1288*615Sbill 1289*615Sbill mget((char *)&archdr, sizeof archdr, &text); 1290*615Sbill for (cp=archdr.ar_name; cp<&archdr.ar_name[sizeof(archdr.ar_name)];) 1291*615Sbill if (*cp++ == ' ') { 1292*615Sbill cp[-1] = 0; 1293*615Sbill return; 1294*615Sbill } 1295*615Sbill } 1296*615Sbill 1297*615Sbill mget(loc, n, sp) 1298*615Sbill register STREAM *sp; 1299*615Sbill register char *loc; 1300*615Sbill { 1301*615Sbill register char *p; 1302*615Sbill register int take; 1303*615Sbill 1304*615Sbill top: 1305*615Sbill if (n == 0) 1306*615Sbill return; 1307*615Sbill if (sp->size && sp->nibuf) { 1308*615Sbill p = sp->ptr; 1309*615Sbill take = sp->size; 1310*615Sbill if (take > sp->nibuf) 1311*615Sbill take = sp->nibuf; 1312*615Sbill if (take > n) 1313*615Sbill take = n; 1314*615Sbill n -= take; 1315*615Sbill sp->size -= take; 1316*615Sbill sp->nibuf -= take; 1317*615Sbill sp->pos += take; 1318*615Sbill do 1319*615Sbill *loc++ = *p++; 1320*615Sbill while (--take > 0); 1321*615Sbill sp->ptr = p; 1322*615Sbill goto top; 1323*615Sbill } 1324*615Sbill if (n > BUFSIZ) { 1325*615Sbill take = n - n % BSIZE; 1326*615Sbill lseek(infil, (sp->bno+1)*BSIZE, 0); 1327*615Sbill if (take > sp->size || read(infil, loc, take) != take) 1328*615Sbill error(1, "premature EOF"); 1329*615Sbill loc += take; 1330*615Sbill n -= take; 1331*615Sbill sp->size -= take; 1332*615Sbill sp->pos += take; 1333*615Sbill dseek(sp, (sp->bno+1+take/BSIZE)*BSIZE, -1); 1334*615Sbill goto top; 1335*615Sbill } 1336*615Sbill *loc++ = get(sp); 1337*615Sbill --n; 1338*615Sbill goto top; 1339*615Sbill } 1340*615Sbill 1341*615Sbill symwrite(sp, bp) 1342*615Sbill struct nlist *sp; 1343*615Sbill struct biobuf *bp; 1344*615Sbill { 1345*615Sbill register int len; 1346*615Sbill register char *str; 1347*615Sbill 1348*615Sbill str = sp->n_un.n_name; 1349*615Sbill if (str) { 1350*615Sbill sp->n_un.n_strx = offset; 1351*615Sbill len = strlen(str) + 1; 1352*615Sbill bwrite(str, len, strout); 1353*615Sbill offset += len; 1354*615Sbill } 1355*615Sbill bwrite(sp, sizeof (*sp), bp); 1356*615Sbill sp->n_un.n_name = str; 1357*615Sbill } 1358*615Sbill 1359*615Sbill dseek(sp, loc, s) 1360*615Sbill register STREAM *sp; 1361*615Sbill long loc, s; 1362*615Sbill { 1363*615Sbill register PAGE *p; 1364*615Sbill register b, o; 1365*615Sbill int n; 1366*615Sbill 1367*615Sbill b = loc>>BSHIFT; 1368*615Sbill o = loc&BMASK; 1369*615Sbill if (o&01) 1370*615Sbill error(1, "loader error; odd offset"); 1371*615Sbill --sp->pno->nuser; 1372*615Sbill if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b) 1373*615Sbill if (p->nuser==0 || (p = &page[0])->nuser==0) { 1374*615Sbill if (page[0].nuser==0 && page[1].nuser==0) 1375*615Sbill if (page[0].bno < page[1].bno) 1376*615Sbill p = &page[0]; 1377*615Sbill p->bno = b; 1378*615Sbill lseek(infil, loc & ~(long)BMASK, 0); 1379*615Sbill if ((n = read(infil, p->buff, sizeof(p->buff))) < 0) 1380*615Sbill n = 0; 1381*615Sbill p->nibuf = n; 1382*615Sbill } else 1383*615Sbill error(1, "botch: no pages"); 1384*615Sbill ++p->nuser; 1385*615Sbill sp->bno = b; 1386*615Sbill sp->pno = p; 1387*615Sbill if (s != -1) {sp->size = s; sp->pos = 0;} 1388*615Sbill sp->ptr = (char *)(p->buff + o); 1389*615Sbill if ((sp->nibuf = p->nibuf-o) <= 0) 1390*615Sbill sp->size = 0; 1391*615Sbill } 1392*615Sbill 1393*615Sbill char 1394*615Sbill get(asp) 1395*615Sbill STREAM *asp; 1396*615Sbill { 1397*615Sbill register STREAM *sp; 1398*615Sbill 1399*615Sbill sp = asp; 1400*615Sbill if ((sp->nibuf -= sizeof(char)) < 0) { 1401*615Sbill dseek(sp, ((long)(sp->bno+1)<<BSHIFT), (long)-1); 1402*615Sbill sp->nibuf -= sizeof(char); 1403*615Sbill } 1404*615Sbill if ((sp->size -= sizeof(char)) <= 0) { 1405*615Sbill if (sp->size < 0) 1406*615Sbill error(1, "premature EOF"); 1407*615Sbill ++fpage.nuser; 1408*615Sbill --sp->pno->nuser; 1409*615Sbill sp->pno = (PAGE *) &fpage; 1410*615Sbill } 1411*615Sbill sp->pos += sizeof(char); 1412*615Sbill return(*sp->ptr++); 1413*615Sbill } 1414*615Sbill 1415*615Sbill getfile(acp) 1416*615Sbill char *acp; 1417*615Sbill { 1418*615Sbill register char *cp; 1419*615Sbill register int c; 1420*615Sbill char arcmag[SARMAG+1]; 1421*615Sbill struct stat stb; 1422*615Sbill 1423*615Sbill cp = acp; 1424*615Sbill infil = -1; 1425*615Sbill archdr.ar_name[0] = '\0'; 1426*615Sbill filname = cp; 1427*615Sbill if (cp[0]=='-' && cp[1]=='l') { 1428*615Sbill char *locfilname = "/usr/local/new/libxxxxxxxxxxxxxxx"; 1429*615Sbill if(cp[2] == '\0') 1430*615Sbill cp = "-la"; 1431*615Sbill filname = "/usr/new/libxxxxxxxxxxxxxxx"; 1432*615Sbill for(c=0; cp[c+2]; c++) { 1433*615Sbill filname[c+12] = cp[c+2]; 1434*615Sbill locfilname[c+18] = cp[c+2]; 1435*615Sbill } 1436*615Sbill filname[c+12] = locfilname[c+18] = '.'; 1437*615Sbill filname[c+13] = locfilname[c+19] = 'a'; 1438*615Sbill filname[c+14] = locfilname[c+20] = '\0'; 1439*615Sbill if ((infil = open(filname+4, 0)) >= 0) { 1440*615Sbill filname += 4; 1441*615Sbill } else if ((infil = open(filname, 0)) < 0) { 1442*615Sbill filname = locfilname; 1443*615Sbill } 1444*615Sbill } 1445*615Sbill if (infil == -1 && (infil = open(filname, 0)) < 0) 1446*615Sbill error(1, "cannot open"); 1447*615Sbill page[0].bno = page[1].bno = -1; 1448*615Sbill page[0].nuser = page[1].nuser = 0; 1449*615Sbill text.pno = reloc.pno = (PAGE *) &fpage; 1450*615Sbill fpage.nuser = 2; 1451*615Sbill dseek(&text, 0L, SARMAG); 1452*615Sbill if (text.size <= 0) 1453*615Sbill error(1, "premature EOF"); 1454*615Sbill mget((char *)arcmag, SARMAG, &text); 1455*615Sbill arcmag[SARMAG] = 0; 1456*615Sbill if (strcmp(arcmag, ARMAG)) 1457*615Sbill return (0); 1458*615Sbill dseek(&text, SARMAG, sizeof archdr); 1459*615Sbill if(text.size <= 0) 1460*615Sbill return (1); 1461*615Sbill getarhdr(); 1462*615Sbill if (strncmp(archdr.ar_name, "__.SYMDEF", sizeof(archdr.ar_name)) != 0) 1463*615Sbill return (1); 1464*615Sbill fstat(infil, &stb); 1465*615Sbill return (stb.st_mtime > atol(archdr.ar_date) ? 3 : 2); 1466*615Sbill } 1467*615Sbill 1468*615Sbill struct nlist ** 1469*615Sbill lookup() 1470*615Sbill { 1471*615Sbill register int sh; 1472*615Sbill register struct nlist **hp; 1473*615Sbill register char *cp, *cp1; 1474*615Sbill register struct symseg *gp; 1475*615Sbill register int i; 1476*615Sbill 1477*615Sbill sh = 0; 1478*615Sbill for (cp = cursym.n_un.n_name; *cp;) 1479*615Sbill sh = (sh<<1) + *cp++; 1480*615Sbill sh = (sh & 0x7fffffff) % HSIZE; 1481*615Sbill for (gp = symseg; gp < &symseg[NSEG]; gp++) { 1482*615Sbill if (gp->sy_first == 0) { 1483*615Sbill gp->sy_first = (struct nlist *) 1484*615Sbill calloc(NSYM, sizeof (struct nlist)); 1485*615Sbill gp->sy_hfirst = (struct nlist **) 1486*615Sbill calloc(HSIZE, sizeof (struct nlist *)); 1487*615Sbill if (gp->sy_first == 0 || gp->sy_hfirst == 0) 1488*615Sbill error(1, "ran out of space for symbol table"); 1489*615Sbill gp->sy_last = gp->sy_first + NSYM; 1490*615Sbill gp->sy_hlast = gp->sy_hfirst + HSIZE; 1491*615Sbill } 1492*615Sbill if (gp > csymseg) 1493*615Sbill csymseg = gp; 1494*615Sbill hp = gp->sy_hfirst + sh; 1495*615Sbill i = 1; 1496*615Sbill do { 1497*615Sbill if (*hp == 0) { 1498*615Sbill if (gp->sy_used == NSYM) 1499*615Sbill break; 1500*615Sbill return (hp); 1501*615Sbill } 1502*615Sbill cp1 = (*hp)->n_un.n_name; 1503*615Sbill for (cp = cursym.n_un.n_name; *cp == *cp1++;) 1504*615Sbill if (*cp++ == 0) 1505*615Sbill return (hp); 1506*615Sbill hp += i; 1507*615Sbill i += 2; 1508*615Sbill if (hp >= gp->sy_hlast) 1509*615Sbill hp -= HSIZE; 1510*615Sbill } while (i < HSIZE); 1511*615Sbill if (i > HSIZE) 1512*615Sbill error(1, "hash table botch"); 1513*615Sbill } 1514*615Sbill error(1, "symbol table overflow"); 1515*615Sbill /*NOTREACHED*/ 1516*615Sbill } 1517*615Sbill 1518*615Sbill symfree(saved) 1519*615Sbill struct nlist *saved; 1520*615Sbill { 1521*615Sbill register struct symseg *gp; 1522*615Sbill register struct nlist *sp; 1523*615Sbill 1524*615Sbill for (gp = csymseg; gp >= symseg; gp--, csymseg--) { 1525*615Sbill sp = gp->sy_first + gp->sy_used; 1526*615Sbill if (sp == saved) { 1527*615Sbill nextsym = sp; 1528*615Sbill return; 1529*615Sbill } 1530*615Sbill for (sp--; sp >= gp->sy_first; sp--) { 1531*615Sbill gp->sy_hfirst[sp->n_hash] = 0; 1532*615Sbill gp->sy_used--; 1533*615Sbill if (sp == saved) { 1534*615Sbill nextsym = sp; 1535*615Sbill return; 1536*615Sbill } 1537*615Sbill } 1538*615Sbill } 1539*615Sbill if (saved == 0) 1540*615Sbill return; 1541*615Sbill error(1, "symfree botch"); 1542*615Sbill } 1543*615Sbill 1544*615Sbill struct nlist ** 1545*615Sbill slookup(s) 1546*615Sbill char *s; 1547*615Sbill { 1548*615Sbill 1549*615Sbill cursym.n_un.n_name = s; 1550*615Sbill cursym.n_type = N_EXT+N_UNDF; 1551*615Sbill cursym.n_value = 0; 1552*615Sbill return (lookup()); 1553*615Sbill } 1554*615Sbill 1555*615Sbill enter(hp) 1556*615Sbill register struct nlist **hp; 1557*615Sbill { 1558*615Sbill register struct nlist *sp; 1559*615Sbill 1560*615Sbill if (*hp==0) { 1561*615Sbill if (hp < csymseg->sy_hfirst || hp >= csymseg->sy_hlast) 1562*615Sbill error(1, "enter botch"); 1563*615Sbill *hp = lastsym = sp = csymseg->sy_first + csymseg->sy_used; 1564*615Sbill csymseg->sy_used++; 1565*615Sbill sp->n_un.n_name = cursym.n_un.n_name; 1566*615Sbill sp->n_type = cursym.n_type; 1567*615Sbill sp->n_hash = hp - csymseg->sy_hfirst; 1568*615Sbill sp->n_value = cursym.n_value; 1569*615Sbill nextsym = lastsym + 1; 1570*615Sbill return(1); 1571*615Sbill } else { 1572*615Sbill lastsym = *hp; 1573*615Sbill return(0); 1574*615Sbill } 1575*615Sbill } 1576*615Sbill 1577*615Sbill symx(sp) 1578*615Sbill struct nlist *sp; 1579*615Sbill { 1580*615Sbill register struct symseg *gp; 1581*615Sbill 1582*615Sbill if (sp == 0) 1583*615Sbill return (0); 1584*615Sbill for (gp = csymseg; gp >= symseg; gp--) 1585*615Sbill /* <= is sloppy so nextsym will always work */ 1586*615Sbill if (sp >= gp->sy_first && sp <= gp->sy_last) 1587*615Sbill return ((gp - symseg) * NSYM + sp - gp->sy_first); 1588*615Sbill error(1, "symx botch"); 1589*615Sbill /*NOTREACHED*/ 1590*615Sbill } 1591*615Sbill 1592*615Sbill symreloc() 1593*615Sbill { 1594*615Sbill if(funding) return; 1595*615Sbill switch (cursym.n_type & 017) { 1596*615Sbill 1597*615Sbill case N_TEXT: 1598*615Sbill case N_EXT+N_TEXT: 1599*615Sbill cursym.n_value += ctrel; 1600*615Sbill return; 1601*615Sbill 1602*615Sbill case N_DATA: 1603*615Sbill case N_EXT+N_DATA: 1604*615Sbill cursym.n_value += cdrel; 1605*615Sbill return; 1606*615Sbill 1607*615Sbill case N_BSS: 1608*615Sbill case N_EXT+N_BSS: 1609*615Sbill cursym.n_value += cbrel; 1610*615Sbill return; 1611*615Sbill 1612*615Sbill case N_EXT+N_UNDF: 1613*615Sbill return; 1614*615Sbill 1615*615Sbill default: 1616*615Sbill if (cursym.n_type&N_EXT) 1617*615Sbill cursym.n_type = N_EXT+N_ABS; 1618*615Sbill return; 1619*615Sbill } 1620*615Sbill } 1621*615Sbill 1622*615Sbill error(n, s) 1623*615Sbill char *s; 1624*615Sbill { 1625*615Sbill if (errlev==0) 1626*615Sbill printf("ld:"); 1627*615Sbill if (filname) { 1628*615Sbill printf("%s", filname); 1629*615Sbill if (n != -1 && archdr.ar_name[0]) 1630*615Sbill printf("(%s)", archdr.ar_name); 1631*615Sbill printf(": "); 1632*615Sbill } 1633*615Sbill printf("%s\n", s); 1634*615Sbill if (n == -1) 1635*615Sbill return; 1636*615Sbill if (n) 1637*615Sbill delexit(); 1638*615Sbill errlev = 2; 1639*615Sbill } 1640*615Sbill 1641*615Sbill readhdr(loc) 1642*615Sbill off_t loc; 1643*615Sbill { 1644*615Sbill 1645*615Sbill dseek(&text, loc, (long)sizeof(filhdr)); 1646*615Sbill mget((short *)&filhdr, sizeof(filhdr), &text); 1647*615Sbill if (N_BADMAG(filhdr)) { 1648*615Sbill if (filhdr.a_magic == OARMAG) 1649*615Sbill error(1, "old archive"); 1650*615Sbill error(1, "bad magic number"); 1651*615Sbill } 1652*615Sbill if (filhdr.a_text&01 || filhdr.a_data&01) 1653*615Sbill error(1, "text/data size odd"); 1654*615Sbill if (filhdr.a_magic == NMAGIC || filhdr.a_magic == ZMAGIC) { 1655*615Sbill cdrel = -round(filhdr.a_text, PAGSIZ); 1656*615Sbill cbrel = cdrel - filhdr.a_data; 1657*615Sbill } else if (filhdr.a_magic == OMAGIC) { 1658*615Sbill cdrel = -filhdr.a_text; 1659*615Sbill cbrel = cdrel - filhdr.a_data; 1660*615Sbill } else 1661*615Sbill error(1, "bad format"); 1662*615Sbill } 1663*615Sbill 1664*615Sbill round(v, r) 1665*615Sbill int v; 1666*615Sbill u_long r; 1667*615Sbill { 1668*615Sbill 1669*615Sbill r--; 1670*615Sbill v += r; 1671*615Sbill v &= ~(long)r; 1672*615Sbill return(v); 1673*615Sbill } 1674*615Sbill 1675*615Sbill #define NSAVETAB 8192 1676*615Sbill char *savetab; 1677*615Sbill int saveleft; 1678*615Sbill 1679*615Sbill char * 1680*615Sbill savestr(cp) 1681*615Sbill register char *cp; 1682*615Sbill { 1683*615Sbill register int len; 1684*615Sbill 1685*615Sbill len = strlen(cp) + 1; 1686*615Sbill if (len > saveleft) { 1687*615Sbill saveleft = NSAVETAB; 1688*615Sbill if (len > saveleft) 1689*615Sbill saveleft = len; 1690*615Sbill savetab = (char *)malloc(saveleft); 1691*615Sbill if (savetab == 0) 1692*615Sbill error(1, "ran out of memory (savestr)"); 1693*615Sbill } 1694*615Sbill strncpy(savetab, cp, len); 1695*615Sbill cp = savetab; 1696*615Sbill savetab += len; 1697*615Sbill saveleft -= len; 1698*615Sbill return (cp); 1699*615Sbill } 1700*615Sbill 1701*615Sbill bopen(bp, off) 1702*615Sbill struct biobuf *bp; 1703*615Sbill { 1704*615Sbill 1705*615Sbill bp->b_ptr = bp->b_buf; 1706*615Sbill bp->b_nleft = BUFSIZ - off % BUFSIZ; 1707*615Sbill bp->b_off = off; 1708*615Sbill bp->b_link = biobufs; 1709*615Sbill biobufs = bp; 1710*615Sbill } 1711*615Sbill 1712*615Sbill int bwrerror; 1713*615Sbill 1714*615Sbill bwrite(p, cnt, bp) 1715*615Sbill register char *p; 1716*615Sbill register int cnt; 1717*615Sbill register struct biobuf *bp; 1718*615Sbill { 1719*615Sbill register int put; 1720*615Sbill register char *to; 1721*615Sbill 1722*615Sbill top: 1723*615Sbill if (cnt == 0) 1724*615Sbill return; 1725*615Sbill if (bp->b_nleft) { 1726*615Sbill put = bp->b_nleft; 1727*615Sbill if (put > cnt) 1728*615Sbill put = cnt; 1729*615Sbill bp->b_nleft -= put; 1730*615Sbill to = bp->b_ptr; 1731*615Sbill asm("movc3 r8,(r11),(r7)"); 1732*615Sbill bp->b_ptr += put; 1733*615Sbill p += put; 1734*615Sbill cnt -= put; 1735*615Sbill goto top; 1736*615Sbill } 1737*615Sbill if (cnt >= BUFSIZ) { 1738*615Sbill if (bp->b_ptr != bp->b_buf) 1739*615Sbill bflush1(bp); 1740*615Sbill put = cnt - cnt % BUFSIZ; 1741*615Sbill if (boffset != bp->b_off) 1742*615Sbill lseek(biofd, bp->b_off, 0); 1743*615Sbill if (write(biofd, p, put) != put) { 1744*615Sbill bwrerror = 1; 1745*615Sbill error(1, "output write error"); 1746*615Sbill } 1747*615Sbill bp->b_off += put; 1748*615Sbill boffset = bp->b_off; 1749*615Sbill p += put; 1750*615Sbill cnt -= put; 1751*615Sbill goto top; 1752*615Sbill } 1753*615Sbill bflush1(bp); 1754*615Sbill goto top; 1755*615Sbill } 1756*615Sbill 1757*615Sbill bflush() 1758*615Sbill { 1759*615Sbill register struct biobuf *bp; 1760*615Sbill 1761*615Sbill if (bwrerror) 1762*615Sbill return; 1763*615Sbill for (bp = biobufs; bp; bp = bp->b_link) 1764*615Sbill bflush1(bp); 1765*615Sbill } 1766*615Sbill 1767*615Sbill bflush1(bp) 1768*615Sbill register struct biobuf *bp; 1769*615Sbill { 1770*615Sbill register int cnt = bp->b_ptr - bp->b_buf; 1771*615Sbill 1772*615Sbill if (cnt == 0) 1773*615Sbill return; 1774*615Sbill if (boffset != bp->b_off) 1775*615Sbill lseek(biofd, bp->b_off, 0); 1776*615Sbill if (write(biofd, bp->b_buf, cnt) != cnt) { 1777*615Sbill bwrerror = 1; 1778*615Sbill error(1, "output write error"); 1779*615Sbill } 1780*615Sbill bp->b_off += cnt; 1781*615Sbill boffset = bp->b_off; 1782*615Sbill bp->b_ptr = bp->b_buf; 1783*615Sbill bp->b_nleft = BUFSIZ; 1784*615Sbill } 1785*615Sbill 1786*615Sbill bflushc(bp, c) 1787*615Sbill register struct biobuf *bp; 1788*615Sbill { 1789*615Sbill 1790*615Sbill bflush1(bp); 1791*615Sbill bputc(c, bp); 1792*615Sbill } 1793