| 1 | char LD[] = "@(#)ld.c 1.10 78/12/07 15:34:58"; /* sccs ident */ |
| 2 | /* |
| 3 | * link editor for VAX |
| 4 | */ |
| 5 | |
| 6 | /* layout of a.out file: |
| 7 | * |
| 8 | * header of 8 words magic number 0410: |
| 9 | data starts at 1st (PAGSIZ) |
| 10 | boundary above text |
| 11 | magic number 0407: |
| 12 | data starts immediately after |
| 13 | text |
| 14 | * text size ) |
| 15 | * data size ) in bytes |
| 16 | * bss size ) |
| 17 | * symbol table size |
| 18 | * entry point |
| 19 | * size of text relocation info |
| 20 | * size of data relocation info |
| 21 | * |
| 22 | * 'segment' origin comments |
| 23 | * header: 0 |
| 24 | * text: 32 0 padded to multiple of 4 bytes |
| 25 | * data: 32+textsize 0 padded to multiple of 4 bytes |
| 26 | * text relocation: 32+textsize+datasize |
| 27 | * data relocation: 32+textsize+datasize+textrelocationsize |
| 28 | * symbol table: 32+textsize+datasize+textrelocationsize+datarelocationsize |
| 29 | * |
| 30 | */ |
| 31 | #include <signal.h> |
| 32 | #include <stdio.h> |
| 33 | #include <ar.h> |
| 34 | #include <a.out.h> |
| 35 | #include <pagsiz.h> |
| 36 | |
| 37 | struct {short hiword; short loword;}; /* stupid fp-11 */ |
| 38 | fixl(p) register long *p;{ |
| 39 | register short t; |
| 40 | t=p->hiword; p->hiword=p->loword; p->loword=t; |
| 41 | } |
| 42 | |
| 43 | writel(p,n,f) long *p; FILE *f; { |
| 44 | #ifdef vax |
| 45 | fwrite(p,sizeof(*p),n,f); |
| 46 | #else |
| 47 | while (n--) { |
| 48 | fwrite(&(*p).loword,2,1,f); |
| 49 | fwrite(&(*p).hiword,2,1,f); |
| 50 | p++; |
| 51 | } |
| 52 | #endif |
| 53 | } |
| 54 | |
| 55 | long htoi(p) register char *p; {/* hex to integer conversion */ |
| 56 | register long n = 0; |
| 57 | while (*p) { |
| 58 | n <<= 4; |
| 59 | if (*p<='9' && *p>='0') n += *p - '0'; |
| 60 | else if (*p<='f' && *p>='a') n += *p -'a' +10; |
| 61 | else if (*p<='F' && *p>='A') n += *p -'A' +10; |
| 62 | p++; |
| 63 | } |
| 64 | return(n); |
| 65 | } |
| 66 | |
| 67 | typedef char *STRING; |
| 68 | typedef int BOOL; |
| 69 | #define TRUE 1 |
| 70 | #define FALSE 0 |
| 71 | |
| 72 | #define OMAGIC 0407 |
| 73 | #define NMAGIC 0410 |
| 74 | |
| 75 | /* |
| 76 | * Symbol types |
| 77 | */ |
| 78 | #define UNDEF 0x0 |
| 79 | #define ABS 0x2 |
| 80 | #define TEXT 0x4 |
| 81 | #define DATA 0x6 |
| 82 | #define BSS 0x8 |
| 83 | #define DATAO 0xA |
| 84 | #define BSSO 0xC |
| 85 | #define TEXTO 0xE |
| 86 | #define ABSO 0x10 |
| 87 | |
| 88 | #define COMM 0x12 /* for internal use only */ |
| 89 | |
| 90 | #define EXTERN 0x1 |
| 91 | #define TYPE 0x1E |
| 92 | #define STABTYPS 0xE0 |
| 93 | /* |
| 94 | * address reference types |
| 95 | */ |
| 96 | #define PCREL 1 |
| 97 | #define LEN1 0 |
| 98 | #define LEN2 2 |
| 99 | #define LEN4 4 |
| 100 | |
| 101 | #define HW 01 |
| 102 | #define FW 03 |
| 103 | #define DW 07 |
| 104 | |
| 105 | |
| 106 | #define TYPMASK 0x1E |
| 107 | #define TYMASK (0x1E) |
| 108 | #define TMASK 0x1F |
| 109 | |
| 110 | #define RABS (ABS) |
| 111 | #define RTEXT TEXT |
| 112 | #define RDATA DATA |
| 113 | #define RBSS BSS |
| 114 | #define RDATAO DATAO |
| 115 | #define RBSSO BSSO |
| 116 | #define RTEXTO TEXTO |
| 117 | #define RABSO ABSO |
| 118 | #define REXT (01<<3) |
| 119 | #define ROFF (02<<3) |
| 120 | #define REFMASK 0x7 |
| 121 | |
| 122 | #define NOVLY 1 |
| 123 | #define RELFLG 01 |
| 124 | #define NROUT 256 |
| 125 | #define NSYM 1103 |
| 126 | #define NSYMPR 500 |
| 127 | |
| 128 | char premeof[] = "Premature EOF"; |
| 129 | |
| 130 | typedef struct { |
| 131 | long loc; |
| 132 | } LIBLIST; |
| 133 | |
| 134 | /* overlay management */ |
| 135 | int vindex; |
| 136 | typedef struct { |
| 137 | int argsav; |
| 138 | int symsav; |
| 139 | LIBLIST *libsav; |
| 140 | STRING vname; |
| 141 | long ctsav, cdsav, cbsav; |
| 142 | long offt, offd, offb, offtr, offdr, offs; |
| 143 | } OVERLAY; |
| 144 | OVERLAY vnodes[NOVLY]; |
| 145 | |
| 146 | /* input management */ |
| 147 | typedef struct { |
| 148 | short *fakeptr; |
| 149 | int bno; |
| 150 | int nibuf; |
| 151 | int nuser; |
| 152 | char buff[BSIZE]; |
| 153 | } PAGE; |
| 154 | |
| 155 | PAGE page[2]; |
| 156 | |
| 157 | struct { |
| 158 | short *fakeptr; |
| 159 | int bno; |
| 160 | int nibuf; |
| 161 | int nuser; |
| 162 | } fpage; |
| 163 | |
| 164 | typedef struct { |
| 165 | char *ptr; |
| 166 | int bno; |
| 167 | int nibuf; |
| 168 | long size; |
| 169 | long pos; |
| 170 | PAGE *pno; |
| 171 | } STREAM; |
| 172 | |
| 173 | STREAM text; |
| 174 | STREAM reloc; |
| 175 | |
| 176 | struct ar_hdr archdr; |
| 177 | |
| 178 | struct exec filhdr; |
| 179 | |
| 180 | /* one entry for each archive member referenced; |
| 181 | * set in first pass; needs restoring for overlays |
| 182 | */ |
| 183 | |
| 184 | LIBLIST liblist[NROUT]; |
| 185 | LIBLIST *libp = liblist; |
| 186 | |
| 187 | |
| 188 | /* symbol management */ |
| 189 | typedef struct { |
| 190 | char sname[8]; |
| 191 | char stype; |
| 192 | char spare; |
| 193 | short symhash; /* index of hash table entry pointing to this symbol */ |
| 194 | long svalue; |
| 195 | } SYMBOL; |
| 196 | |
| 197 | typedef struct { |
| 198 | int locindex; /* index to symbol in file */ |
| 199 | SYMBOL *locsymbol; /* ptr to symbol table */ |
| 200 | } LOCAL; |
| 201 | |
| 202 | SYMBOL cursym; /* current symbol */ |
| 203 | SYMBOL *symtab; /* actual symbols */ |
| 204 | SYMBOL *lastsym; /* last symbol entered */ |
| 205 | SYMBOL *nextsym; /* next available symbol table entry */ |
| 206 | int nsym; /* number of symbols allocated in symtab */ |
| 207 | SYMBOL *hshtab[NSYM+2]; /* hash table for symbols */ |
| 208 | LOCAL *local; |
| 209 | |
| 210 | /* internal symbols */ |
| 211 | SYMBOL *p_data; |
| 212 | SYMBOL *p_etext; |
| 213 | SYMBOL *p_edata; |
| 214 | SYMBOL *p_end; |
| 215 | SYMBOL *entrypt; |
| 216 | |
| 217 | int trace; |
| 218 | /* flags */ |
| 219 | int xflag; /* discard local symbols */ |
| 220 | int Xflag; /* discard locals starting with 'L' */ |
| 221 | int Sflag; /* discard all except locals and globals*/ |
| 222 | int rflag; /* preserve relocation bits, don't define common */ |
| 223 | int arflag; /* original copy of rflag */ |
| 224 | int sflag; /* discard all symbols */ |
| 225 | int nflag = 1; /* pure procedure */ |
| 226 | int dflag; /* define common even with rflag */ |
| 227 | int iflag; /* I/D space separated */ |
| 228 | BOOL vflag; /* overlays used */ |
| 229 | int zflag; |
| 230 | |
| 231 | int ofilfnd; |
| 232 | char *ofilename = "l.out"; |
| 233 | int infil; |
| 234 | char *filname; |
| 235 | |
| 236 | long textbase; |
| 237 | /* cumulative sizes set in pass 1 */ |
| 238 | long tsize; |
| 239 | long dsize; |
| 240 | long bsize; |
| 241 | long trsize; |
| 242 | long drsize; |
| 243 | long ssize; |
| 244 | |
| 245 | /* symbol relocation; both passes */ |
| 246 | long ctrel; |
| 247 | long cdrel; |
| 248 | long cbrel; |
| 249 | long ctorel; |
| 250 | long cdorel; |
| 251 | long cborel; |
| 252 | |
| 253 | int errlev; |
| 254 | int delarg = 4; |
| 255 | |
| 256 | |
| 257 | FILE *tout; |
| 258 | FILE *dout; |
| 259 | char *doutn = ""; |
| 260 | FILE *trout; |
| 261 | char *troutn = ""; |
| 262 | FILE *drout; |
| 263 | char *droutn = ""; |
| 264 | FILE *sout; |
| 265 | char *soutn = ""; |
| 266 | |
| 267 | char *mktemp(); |
| 268 | char get(); |
| 269 | char getb(); |
| 270 | short gets(); |
| 271 | long get3(); |
| 272 | long getl(); |
| 273 | SYMBOL **lookup(); |
| 274 | FILE *tcreat(); |
| 275 | long round(); |
| 276 | SYMBOL **slookup(); |
| 277 | SYMBOL *lookloc(); |
| 278 | |
| 279 | symwrite(sp,n,f) SYMBOL *sp; FILE *f; { |
| 280 | #ifdef vax |
| 281 | fwrite(sp,sizeof(*symtab),n,f); |
| 282 | #else |
| 283 | while (n--) { |
| 284 | fwrite(sp,sizeof(*symtab)-sizeof(sp->svalue),1,f); |
| 285 | writel(&(sp->svalue),1,f); sp++; |
| 286 | } |
| 287 | #endif |
| 288 | } |
| 289 | |
| 290 | delexit() |
| 291 | { |
| 292 | unlink("l.out"); |
| 293 | unlink(doutn); |
| 294 | unlink(troutn); |
| 295 | unlink(droutn); |
| 296 | unlink(soutn); |
| 297 | if (delarg==0) |
| 298 | chmod(ofilename, 0777 &~ umask(0)); |
| 299 | exit(delarg); |
| 300 | } |
| 301 | |
| 302 | main(argc, argv) |
| 303 | char **argv; |
| 304 | { |
| 305 | register int c, i; |
| 306 | int num; |
| 307 | register char *ap, **p; |
| 308 | BOOL found; |
| 309 | int vscan; |
| 310 | char save; |
| 311 | |
| 312 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) |
| 313 | signal(SIGINT, delexit); |
| 314 | if (argc == 1) |
| 315 | exit(4); |
| 316 | p = argv+1; |
| 317 | |
| 318 | nextsym=symtab=sbrk(0); nsym=0; |
| 319 | /* scan files once to find symdefs */ |
| 320 | for (c=1; c<argc; c++) { |
| 321 | if (trace) printf("%s:\n", *p); |
| 322 | filname = 0; |
| 323 | ap = *p++; |
| 324 | |
| 325 | if (*ap == '-') { |
| 326 | for (i=1; ap[i]; i++) { |
| 327 | switch (ap[i]) { |
| 328 | case 'o': |
| 329 | if (++c >= argc) |
| 330 | error(1, "Bad output file"); |
| 331 | ofilename = *p++; |
| 332 | ofilfnd++; |
| 333 | continue; |
| 334 | |
| 335 | case 'u': |
| 336 | case 'e': |
| 337 | if (++c >= argc) |
| 338 | error(1, "Bad 'use' or 'entry'"); |
| 339 | enter(slookup(*p++)); |
| 340 | if (ap[i]=='e') |
| 341 | entrypt = lastsym; |
| 342 | continue; |
| 343 | |
| 344 | case 'v': |
| 345 | if (++c >= argc) |
| 346 | error(1, "-v: arg missing"); |
| 347 | vflag=TRUE; |
| 348 | vscan = vindex; |
| 349 | found=FALSE; |
| 350 | while (--vscan>=0 && found==FALSE) |
| 351 | found = eq(vnodes[vscan].vname, *p); |
| 352 | if (found) { |
| 353 | endload(c, argv); |
| 354 | restore(vscan); |
| 355 | } else |
| 356 | record(c, *p); |
| 357 | p++; |
| 358 | continue; |
| 359 | |
| 360 | case 'D': |
| 361 | if (++c >= argc) |
| 362 | error(1, "-D: arg missing"); |
| 363 | num = htoi(*p++); |
| 364 | if (dsize>num) |
| 365 | error(1, "-D: too small"); |
| 366 | dsize = num; |
| 367 | continue; |
| 368 | |
| 369 | case 'T': |
| 370 | if (++c >= argc) |
| 371 | error(1, "-T: arg missing"); |
| 372 | if (tsize!=0) |
| 373 | error(1, "-T: too late, some text already loaded"); |
| 374 | textbase = htoi(*p++); |
| 375 | continue; |
| 376 | |
| 377 | case 'l': |
| 378 | save = ap[--i]; |
| 379 | ap[i]='-'; |
| 380 | load1arg(&ap[i]); |
| 381 | ap[i]=save; |
| 382 | break; |
| 383 | |
| 384 | case 'x': |
| 385 | xflag++; |
| 386 | continue; |
| 387 | |
| 388 | case 'X': |
| 389 | Xflag++; |
| 390 | continue; |
| 391 | |
| 392 | case 'S': |
| 393 | Sflag++; |
| 394 | continue; |
| 395 | |
| 396 | case 'r': |
| 397 | rflag++; |
| 398 | arflag++; |
| 399 | continue; |
| 400 | |
| 401 | case 's': |
| 402 | sflag++; |
| 403 | xflag++; |
| 404 | continue; |
| 405 | |
| 406 | case 'n': |
| 407 | nflag++; |
| 408 | continue; |
| 409 | |
| 410 | case 'N': |
| 411 | nflag = 0; |
| 412 | continue; |
| 413 | |
| 414 | case 'd': |
| 415 | dflag++; |
| 416 | continue; |
| 417 | |
| 418 | case 'i': |
| 419 | iflag++; |
| 420 | continue; |
| 421 | |
| 422 | case 't': |
| 423 | trace++; |
| 424 | continue; |
| 425 | |
| 426 | case 'z': |
| 427 | zflag++; |
| 428 | continue; |
| 429 | |
| 430 | default: |
| 431 | error(1, "bad flag"); |
| 432 | } /*endsw*/ |
| 433 | break; |
| 434 | } /*endfor*/ |
| 435 | } else |
| 436 | load1arg(ap); |
| 437 | } |
| 438 | endload(argc, argv); |
| 439 | exit(0); |
| 440 | } |
| 441 | |
| 442 | /* used after pass 1 */ |
| 443 | long torigin; |
| 444 | long dorigin; |
| 445 | long borigin; |
| 446 | long database; |
| 447 | |
| 448 | endload(argc, argv) |
| 449 | int argc; |
| 450 | char **argv; |
| 451 | { |
| 452 | register int c, i; |
| 453 | long dnum; |
| 454 | register char *ap, **p; |
| 455 | |
| 456 | brk(nextsym); |
| 457 | filname = 0; |
| 458 | middle(); |
| 459 | setupout(); |
| 460 | if (-1==(local=sbrk(NSYMPR*sizeof(*local)))) error(1,"Memory overflow"); |
| 461 | p = argv+1; |
| 462 | libp = liblist; |
| 463 | for (c=1; c<argc; c++) { |
| 464 | ap = *p++; |
| 465 | if (trace) printf("%s:\n", ap); |
| 466 | if (*ap == '-') { |
| 467 | for (i=1; ap[i]; i++) { |
| 468 | switch (ap[i]) { |
| 469 | case 'D': |
| 470 | for (dnum = htoi(*p); dorigin<dnum; dorigin++) putc(0, dout); |
| 471 | case 'T': |
| 472 | case 'u': |
| 473 | case 'e': |
| 474 | case 'o': |
| 475 | case 'v': |
| 476 | ++c; |
| 477 | ++p; |
| 478 | |
| 479 | default: |
| 480 | continue; |
| 481 | |
| 482 | case 'l': |
| 483 | ap[--i]='-'; |
| 484 | load2arg(&ap[i]); |
| 485 | break; |
| 486 | } /*endsw*/ |
| 487 | break; |
| 488 | } /*endfor*/ |
| 489 | } else |
| 490 | load2arg(ap); |
| 491 | } |
| 492 | finishout(); |
| 493 | } |
| 494 | |
| 495 | record(c, nam) |
| 496 | int c; |
| 497 | STRING nam; |
| 498 | { |
| 499 | register OVERLAY *v; |
| 500 | |
| 501 | v = &vnodes[vindex++]; |
| 502 | v->argsav = c; |
| 503 | v->symsav = nextsym-symtab; |
| 504 | v->libsav = libp; |
| 505 | v->vname = nam; |
| 506 | v->offt = tsize; |
| 507 | v->offd = dsize; |
| 508 | v->offb = bsize; |
| 509 | v->offtr = trsize; |
| 510 | v->offdr = drsize; |
| 511 | v->offs = ssize; |
| 512 | v->ctsav = ctrel; |
| 513 | v->cdsav = cdrel; |
| 514 | v->cbsav = cbrel; |
| 515 | } |
| 516 | |
| 517 | restore(vscan) |
| 518 | int vscan; |
| 519 | { |
| 520 | register OVERLAY *v; |
| 521 | register SYMBOL *saved,*sp; |
| 522 | |
| 523 | v = &vnodes[vscan]; |
| 524 | vindex = vscan+1; |
| 525 | libp = v->libsav; |
| 526 | ctrel = v->ctsav; |
| 527 | cdrel = v->cdsav; |
| 528 | cbrel = v->cbsav; |
| 529 | tsize = v->offt; |
| 530 | dsize = v->offd; |
| 531 | bsize = v->offb; |
| 532 | trsize = v->offtr; |
| 533 | drsize = v->offdr; |
| 534 | ssize = v->offs; |
| 535 | saved = symtab + v->symsav; |
| 536 | sp = nextsym; |
| 537 | while (sp>saved) |
| 538 | hshtab[(--sp)->symhash]=0; |
| 539 | nextsym = saved; |
| 540 | } |
| 541 | |
| 542 | /* scan file to find defined symbols */ |
| 543 | load1arg(cp) |
| 544 | register char *cp; |
| 545 | { |
| 546 | long loc; |
| 547 | |
| 548 | if (getfile(cp)==0) |
| 549 | load1(0, 0L); |
| 550 | else { |
| 551 | loc = sizeof(int); |
| 552 | for (;;) { |
| 553 | dseek(&text, loc, (long)sizeof(archdr)); |
| 554 | if (text.size <= 0) { |
| 555 | libp->loc = -1; |
| 556 | if( ++libp >= liblist + NROUT) |
| 557 | error(1,"liblist overflow"); |
| 558 | /* thanks to Dennis Wasley */ |
| 559 | return; |
| 560 | } |
| 561 | mget((short *)&archdr, sizeof archdr, &text); |
| 562 | if (load1(1, loc+sizeof(archdr))) { |
| 563 | libp->loc = loc; |
| 564 | libp++; |
| 565 | } |
| 566 | #ifndef vax |
| 567 | if (archdr.ar_size.loword==0) fixl(&archdr.ar_size); |
| 568 | #endif |
| 569 | loc += round(archdr.ar_size, 1) + sizeof(archdr); |
| 570 | } |
| 571 | } |
| 572 | close(infil); |
| 573 | } |
| 574 | |
| 575 | /* single file or archive member */ |
| 576 | load1(libflg, loc) |
| 577 | long loc; |
| 578 | { |
| 579 | register SYMBOL *sp; |
| 580 | SYMBOL *savnext; |
| 581 | int ndef, nlocal, type; |
| 582 | |
| 583 | readhdr(loc); |
| 584 | ctrel = tsize; |
| 585 | cdrel += dsize; |
| 586 | cbrel += bsize; |
| 587 | ndef = 0; |
| 588 | nlocal = sizeof(cursym); |
| 589 | savnext = nextsym; |
| 590 | /* if (filhdr.a_trsize+filhdr.a_drsize==0) { |
| 591 | /* error(0, "No relocation bits"); |
| 592 | /* return(0); |
| 593 | /* } |
| 594 | */ |
| 595 | loc += filhdr.a_text + filhdr.a_data + |
| 596 | filhdr.a_trsize + filhdr.a_drsize + sizeof(filhdr); |
| 597 | dseek(&text, loc, filhdr.a_syms); |
| 598 | while (text.size > 0) { |
| 599 | symget(&cursym, &text); |
| 600 | type = cursym.stype; |
| 601 | if ((type&EXTERN)==0) { |
| 602 | if (Xflag==0 || cursym.sname[0]!='L' || type & STABTYPS) |
| 603 | nlocal += sizeof cursym; |
| 604 | continue; |
| 605 | } |
| 606 | symreloc(); |
| 607 | if (enter(lookup())) |
| 608 | continue; |
| 609 | if ((sp = lastsym)->stype != EXTERN+UNDEF) |
| 610 | continue; |
| 611 | if (cursym.stype == EXTERN+UNDEF) { |
| 612 | if (cursym.svalue > sp->svalue) |
| 613 | sp->svalue = cursym.svalue; |
| 614 | continue; |
| 615 | } |
| 616 | if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT) |
| 617 | continue; |
| 618 | ndef++; |
| 619 | sp->stype = cursym.stype; |
| 620 | sp->svalue = cursym.svalue; |
| 621 | } |
| 622 | if (libflg==0 || ndef) { |
| 623 | tsize += filhdr.a_text; |
| 624 | dsize += round(filhdr.a_data, FW); |
| 625 | bsize += round(filhdr.a_bss, FW); |
| 626 | ssize += nlocal; |
| 627 | trsize += filhdr.a_trsize; |
| 628 | drsize += filhdr.a_drsize; |
| 629 | return(1); |
| 630 | } |
| 631 | /* |
| 632 | * No symbols defined by this library member. |
| 633 | * Rip out the hash table entries and reset the symbol table. |
| 634 | */ |
| 635 | while (nextsym>savnext) |
| 636 | hshtab[(--nextsym)->symhash]=0; |
| 637 | return(0); |
| 638 | } |
| 639 | |
| 640 | middle() |
| 641 | { |
| 642 | register SYMBOL *sp, *symp; |
| 643 | long csize, t, corigin, ocsize; |
| 644 | int nund, rnd; |
| 645 | char s; |
| 646 | |
| 647 | torigin = 0; |
| 648 | dorigin = 0; |
| 649 | borigin = 0; |
| 650 | |
| 651 | p_data = *slookup("_data"); |
| 652 | p_etext = *slookup("_etext"); |
| 653 | p_edata = *slookup("_edata"); |
| 654 | p_end = *slookup("_end"); |
| 655 | /* |
| 656 | * If there are any undefined symbols, save the relocation bits. |
| 657 | */ |
| 658 | symp = nextsym; |
| 659 | if (rflag==0) { |
| 660 | for (sp = symtab; sp<symp; sp++) |
| 661 | if (sp->stype==EXTERN+UNDEF && sp->svalue==0 |
| 662 | && sp!=p_end && sp!=p_edata && sp!=p_etext |
| 663 | && sp!=p_data) { |
| 664 | rflag++; |
| 665 | dflag = 0; |
| 666 | break; |
| 667 | } |
| 668 | } |
| 669 | if (rflag) |
| 670 | sflag = iflag = 0; |
| 671 | /* |
| 672 | * Assign common locations. |
| 673 | */ |
| 674 | csize = 0; |
| 675 | database = round(tsize+textbase, (nflag? PAGRND:FW)); |
| 676 | if (dflag || rflag==0) { |
| 677 | ldrsym(p_data, (long)0 , EXTERN+DATA); |
| 678 | ldrsym(p_etext, tsize, EXTERN+TEXT); |
| 679 | ldrsym(p_edata, dsize, EXTERN+DATA); |
| 680 | ldrsym(p_end, bsize, EXTERN+BSS); |
| 681 | for (sp = symtab; sp<symp; sp++) { |
| 682 | if ((s=sp->stype)==EXTERN+UNDEF && (t = sp->svalue)!=0) { |
| 683 | if (t>DW) |
| 684 | rnd = DW; |
| 685 | else if (t>FW) |
| 686 | rnd = FW; |
| 687 | else |
| 688 | rnd = HW; |
| 689 | csize = round(csize, rnd); |
| 690 | sp->svalue = csize; |
| 691 | sp->stype = EXTERN+COMM; |
| 692 | ocsize = csize; |
| 693 | csize += t; |
| 694 | } |
| 695 | if (((s&TMASK) == EXTERN+UNDEF) && (s & STABTYPS)) { |
| 696 | sp->svalue = ocsize; |
| 697 | sp->stype = (s & STABTYPS) | (EXTERN+COMM); |
| 698 | } |
| 699 | } |
| 700 | } |
| 701 | /* |
| 702 | * Now set symbols to their final value |
| 703 | */ |
| 704 | csize = round(csize, FW); |
| 705 | torigin = textbase; |
| 706 | dorigin = database; |
| 707 | corigin = dorigin + dsize; |
| 708 | borigin = corigin + csize; |
| 709 | /* |
| 710 | if (zflag) |
| 711 | borigin = round(borigin, PAGRND); |
| 712 | */ |
| 713 | cdorel = 0; |
| 714 | cborel = dsize+csize; |
| 715 | nund = 0; |
| 716 | for (sp = symtab; sp<symp; sp++) switch (sp->stype & TMASK) { |
| 717 | case EXTERN+UNDEF: |
| 718 | errlev |= 01; |
| 719 | if ((arflag==0 || dflag) && sp->svalue==0) { |
| 720 | if (nund==0) |
| 721 | printf("Undefined:\n"); |
| 722 | nund++; |
| 723 | printf("%.8s\n", sp->sname); |
| 724 | } |
| 725 | continue; |
| 726 | |
| 727 | case EXTERN+ABS: |
| 728 | default: |
| 729 | continue; |
| 730 | |
| 731 | case EXTERN+TEXT: |
| 732 | sp->svalue += torigin; |
| 733 | continue; |
| 734 | |
| 735 | case EXTERN+DATA: |
| 736 | sp->svalue += dorigin; |
| 737 | continue; |
| 738 | |
| 739 | case EXTERN+BSS: |
| 740 | sp->svalue += borigin; |
| 741 | continue; |
| 742 | |
| 743 | case EXTERN+COMM: |
| 744 | sp->stype = (sp->stype & STABTYPS) | (EXTERN+BSS); |
| 745 | sp->svalue += corigin; |
| 746 | continue; |
| 747 | } |
| 748 | if (sflag || xflag) |
| 749 | ssize = 0; |
| 750 | bsize += csize; |
| 751 | nsym = ssize / (sizeof cursym); |
| 752 | } |
| 753 | |
| 754 | ldrsym(asp, val, type) |
| 755 | long val; |
| 756 | SYMBOL *asp; |
| 757 | { |
| 758 | register SYMBOL *sp; |
| 759 | |
| 760 | if ((sp = asp) == 0) |
| 761 | return; |
| 762 | if (sp->stype != EXTERN+UNDEF || sp->svalue) { |
| 763 | printf("%.8s: ", sp->sname); |
| 764 | error(0, "Multiply defined (internal)"); |
| 765 | return; |
| 766 | } |
| 767 | sp->stype = type; |
| 768 | sp->svalue = val; |
| 769 | } |
| 770 | |
| 771 | extern char _sibuf[BUFSIZ]; /* the space is forced upon us; might as well use it */ |
| 772 | |
| 773 | setupout() |
| 774 | { |
| 775 | int bss; |
| 776 | tout = fopen(ofilename, "w"); |
| 777 | if (tout==NULL) |
| 778 | error(1, "cannot create output"); |
| 779 | setbuf(tout,_sibuf); |
| 780 | dout = tcreat(&doutn, "/tmp/ldaaXXXXX"); |
| 781 | if (sflag==0 || xflag==0) |
| 782 | sout = tcreat(&soutn, "/tmp/ldbaXXXXX"); |
| 783 | if (rflag) { |
| 784 | trout = tcreat(&troutn, "/tmp/ldcaXXXXX"); |
| 785 | drout = tcreat(&droutn, "/tmp/lddaXXXXX"); |
| 786 | } |
| 787 | filhdr.a_magic = nflag? NMAGIC:OMAGIC; |
| 788 | if (zflag) |
| 789 | filhdr.a_magic = nflag?0413:0412; |
| 790 | filhdr.a_text = nflag? tsize:round(tsize, FW); |
| 791 | if (zflag) |
| 792 | filhdr.a_text = round(tsize, PAGRND); |
| 793 | filhdr.a_data = dsize; |
| 794 | if (zflag) |
| 795 | filhdr.a_data = round(dsize, PAGRND); |
| 796 | bss = bsize - (filhdr.a_data - dsize); |
| 797 | if (bss < 0) |
| 798 | bss = 0; |
| 799 | filhdr.a_bss = bss; |
| 800 | filhdr.a_trsize = trsize; |
| 801 | filhdr.a_drsize = drsize; |
| 802 | filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*(nextsym-symtab)); |
| 803 | if (entrypt) { |
| 804 | if (entrypt->stype!=EXTERN+TEXT) |
| 805 | error(0, "Entry point not in text"); |
| 806 | else |
| 807 | filhdr.a_entry = entrypt->svalue; |
| 808 | } else |
| 809 | filhdr.a_entry=0; |
| 810 | filhdr.a_trsize = (rflag ? trsize:0); |
| 811 | filhdr.a_drsize = (rflag ? drsize:0); |
| 812 | writel(&filhdr,8,tout); |
| 813 | if (zflag) |
| 814 | fseek(tout, PAGSIZ, 0); |
| 815 | } |
| 816 | |
| 817 | FILE * |
| 818 | tcreat(namep, name) |
| 819 | char **namep, *name; |
| 820 | { |
| 821 | register FILE *fp; |
| 822 | register char *tnm; |
| 823 | |
| 824 | tnm = mktemp(name); |
| 825 | if ((fp = fopen(tnm, "w")) == NULL) |
| 826 | error(1, "Cannot create temp file"); |
| 827 | chmod(tnm, 0600); |
| 828 | *namep = tnm; |
| 829 | return(fp); |
| 830 | } |
| 831 | |
| 832 | load2arg(acp) |
| 833 | char *acp; |
| 834 | { |
| 835 | register char *cp; |
| 836 | register LIBLIST *lp; |
| 837 | |
| 838 | cp = acp; |
| 839 | if (getfile(cp) == 0) { |
| 840 | while (*cp) |
| 841 | cp++; |
| 842 | while (cp >= acp && *--cp != '/'); |
| 843 | mkfsym(++cp); |
| 844 | load2(0L); |
| 845 | } else { /* scan archive members referenced */ |
| 846 | for (lp = libp; lp->loc != -1; lp++) { |
| 847 | dseek(&text, lp->loc, (long)sizeof(archdr)); |
| 848 | mget((short *)&archdr, sizeof(archdr), &text); |
| 849 | mkfsym(archdr.ar_name); |
| 850 | load2(lp->loc + (long)sizeof(archdr)); |
| 851 | } |
| 852 | libp = ++lp; |
| 853 | } |
| 854 | close(infil); |
| 855 | } |
| 856 | |
| 857 | load2(loc) |
| 858 | long loc; |
| 859 | { |
| 860 | register SYMBOL *sp; |
| 861 | register LOCAL *lp; |
| 862 | register int symno; |
| 863 | int type; |
| 864 | |
| 865 | readhdr(loc); |
| 866 | ctrel = torigin; |
| 867 | cdrel += dorigin; |
| 868 | cbrel += borigin; |
| 869 | /* |
| 870 | * Reread the symbol table, recording the numbering |
| 871 | * of symbols for fixing external references. |
| 872 | */ |
| 873 | lp = local; |
| 874 | symno = -1; |
| 875 | loc += sizeof(filhdr); |
| 876 | dseek(&text, loc+filhdr.a_text+filhdr.a_data+ |
| 877 | filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms); |
| 878 | while (text.size > 0) { |
| 879 | symno++; |
| 880 | symget(&cursym, &text); |
| 881 | symreloc(); |
| 882 | type = cursym.stype; |
| 883 | if ((type&EXTERN) == 0) { |
| 884 | if (!sflag&&!xflag&& |
| 885 | (!Xflag||cursym.sname[0]!='L'||type&STABTYPS)) |
| 886 | symwrite(&cursym, 1, sout); |
| 887 | continue; |
| 888 | } |
| 889 | if ((sp = *lookup()) == 0) |
| 890 | error(1, "internal error: symbol not found"); |
| 891 | if (cursym.stype == EXTERN+UNDEF) { |
| 892 | if (lp >= local+NSYMPR) |
| 893 | error(1, "Local symbol overflow"); |
| 894 | lp->locindex = symno; |
| 895 | lp++->locsymbol = sp; |
| 896 | continue; |
| 897 | } |
| 898 | if(cursym.stype & STABTYPS) continue; |
| 899 | if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) { |
| 900 | printf("%.8s: ", cursym.sname); |
| 901 | error(0, "Multiply defined"); |
| 902 | } |
| 903 | } |
| 904 | dseek(&text, loc, filhdr.a_text); |
| 905 | dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize); |
| 906 | load2td(lp, ctrel, tout, trout); |
| 907 | dseek(&text, loc+filhdr.a_text, filhdr.a_data); |
| 908 | dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize, filhdr.a_drsize); |
| 909 | load2td(lp, cdrel, dout, drout); |
| 910 | while (filhdr.a_data&FW) { |
| 911 | putc(0, dout); filhdr.a_data++; |
| 912 | } |
| 913 | torigin += filhdr.a_text; |
| 914 | dorigin += filhdr.a_data; |
| 915 | borigin += filhdr.a_bss; |
| 916 | cdorel += filhdr.a_data; |
| 917 | cborel += filhdr.a_bss; |
| 918 | } |
| 919 | |
| 920 | load2td(lp, creloc, b1, b2) |
| 921 | LOCAL *lp; |
| 922 | long creloc; |
| 923 | FILE *b1, *b2; |
| 924 | { |
| 925 | register r1; |
| 926 | register char r2; |
| 927 | register long t; |
| 928 | register SYMBOL *sp; |
| 929 | long tw,u,l; |
| 930 | |
| 931 | for (;;) { |
| 932 | if (reloc.size==0) {while (text.size) putc(get(&text),b1); break;} |
| 933 | t=getl(&reloc); /* position of relocatable stuff */ |
| 934 | if (rflag) putl(t+creloc,b2); /* remember for subsequent link editing */ |
| 935 | while (text.pos<t) putc(get(&text),b1); /* advance to proper position */ |
| 936 | r1=get3(&reloc); /* kind of relocation */ |
| 937 | r2 = getb(&reloc); |
| 938 | switch (r2&06) {/* read raw datum according to its length */ |
| 939 | case LEN1: tw=get(&text); break; |
| 940 | case LEN2: tw=gets(&text); break; |
| 941 | case LEN4: tw=getl(&text); break; |
| 942 | } |
| 943 | if (r2&REXT) { |
| 944 | sp=lookloc(lp,r1); /* find the symbol */ |
| 945 | if (sp->stype==EXTERN+UNDEF) { /* still undefined */ |
| 946 | r2=(r2&(REFMASK+REXT+ROFF)); |
| 947 | r1 = nsym+(sp-symtab); /* new reloc */ |
| 948 | } |
| 949 | else { |
| 950 | if (sp->stype==EXTERN+DATA && r2&ROFF) { |
| 951 | r1=RDATAO; |
| 952 | r2&=REFMASK; |
| 953 | } |
| 954 | else if (sp->stype==EXTERN+BSS && r2&ROFF) { |
| 955 | r1=RBSSO; |
| 956 | r2&=REFMASK; |
| 957 | } |
| 958 | else if (sp->stype==EXTERN+ABS && r2&ROFF) { |
| 959 | r1=RABSO; |
| 960 | r2&=REFMASK; |
| 961 | } |
| 962 | else if (sp->stype==EXTERN+TEXT && r2&ROFF) { |
| 963 | r1=RTEXTO; |
| 964 | r2&=REFMASK; |
| 965 | } |
| 966 | else {if (r2&ROFF) {if (rflag) {error(0,"!-r; see JFR"); rflag=0;}} |
| 967 | else tw += database; |
| 968 | r1=sp->stype&TYPE; |
| 969 | r2&=REFMASK; |
| 970 | } |
| 971 | tw += sp->svalue - database; |
| 972 | } |
| 973 | } else switch (r1&TYMASK) { |
| 974 | case RTEXT: tw += ctrel; break; |
| 975 | case RTEXTO:tw += round(filhdr.a_text,PAGRND)+ctrel-database; break; |
| 976 | case RDATA: tw += cdrel; break; |
| 977 | case RDATAO:tw += cdorel; break; |
| 978 | case RBSS: tw += cbrel; break; |
| 979 | case RBSSO: tw += cborel-filhdr.a_data; break; |
| 980 | case RABSO: tw += round(filhdr.a_text,PAGRND)-database; break; |
| 981 | } |
| 982 | if (rflag) { /* remember for subsequent link editing */ |
| 983 | put3(r1,b2); |
| 984 | putb(r2,b2); |
| 985 | } |
| 986 | if (r2&PCREL) tw -= creloc; /* assembler already subtracted text.pos */ |
| 987 | switch (r2&06) {/* output relocated datum according to its length */ |
| 988 | case LEN1: l= -128; u=127; putc((char)tw,b1); break; |
| 989 | case LEN2: l= -32768; u=32767; puts((short)tw,b1); break; |
| 990 | case LEN4: l=0x80000000; u=0x7FFFFFFF; putl(tw,b1); break; |
| 991 | } |
| 992 | if (tw<l || u<tw) error(0,"Displacement overflow"); |
| 993 | } |
| 994 | } |
| 995 | |
| 996 | finishout() |
| 997 | { |
| 998 | |
| 999 | if (!nflag) |
| 1000 | while (tsize&FW) { |
| 1001 | putc(0, tout); tsize++; |
| 1002 | } |
| 1003 | if (zflag) { |
| 1004 | while (tsize&PAGRND) { |
| 1005 | putc(0, tout); tsize++; |
| 1006 | } |
| 1007 | while (dsize&PAGRND) { |
| 1008 | putc(0, dout); dsize++; |
| 1009 | } |
| 1010 | } |
| 1011 | fclose(dout); |
| 1012 | copy(doutn); |
| 1013 | if (rflag) { |
| 1014 | fclose(trout); |
| 1015 | copy(troutn); |
| 1016 | fclose(drout); |
| 1017 | copy(droutn); |
| 1018 | } |
| 1019 | if (sflag==0) { |
| 1020 | if (xflag==0) { |
| 1021 | fclose(sout); |
| 1022 | copy(soutn); |
| 1023 | } |
| 1024 | symwrite(symtab, nextsym-symtab, tout); |
| 1025 | } |
| 1026 | fclose(tout); |
| 1027 | if (!ofilfnd) { |
| 1028 | unlink("a.out"); |
| 1029 | link("l.out", "a.out"); |
| 1030 | ofilename = "a.out"; |
| 1031 | } |
| 1032 | delarg = errlev; |
| 1033 | delexit(); |
| 1034 | } |
| 1035 | |
| 1036 | copy(np) |
| 1037 | char *np; |
| 1038 | { |
| 1039 | register c; |
| 1040 | register FILE *fp; |
| 1041 | |
| 1042 | if ((fp = fopen(np, "r")) == NULL) |
| 1043 | error(1, "cannot recopy output"); |
| 1044 | while ((c = getc(fp)) != EOF) |
| 1045 | putc(c, tout); |
| 1046 | fclose(fp); |
| 1047 | } |
| 1048 | |
| 1049 | mkfsym(s) |
| 1050 | char *s; |
| 1051 | { |
| 1052 | |
| 1053 | if (sflag || xflag) |
| 1054 | return; |
| 1055 | cp8c(s, cursym.sname); |
| 1056 | cursym.stype = TEXT; |
| 1057 | cursym.svalue = torigin; |
| 1058 | symwrite(&cursym, 1, sout); |
| 1059 | } |
| 1060 | |
| 1061 | mget(loc, n, sp) |
| 1062 | register STREAM *sp; |
| 1063 | register char *loc; |
| 1064 | { |
| 1065 | register char *p; |
| 1066 | |
| 1067 | if ((sp->nibuf -= n) >= 0) { |
| 1068 | if ((sp->size -= n) > 0) { |
| 1069 | p = sp->ptr; |
| 1070 | sp->pos += n; |
| 1071 | do |
| 1072 | *loc++ = *p++; |
| 1073 | while (--n); |
| 1074 | sp->ptr = p; |
| 1075 | return; |
| 1076 | } else |
| 1077 | sp->size += n; |
| 1078 | } |
| 1079 | sp->nibuf += n; |
| 1080 | do { |
| 1081 | *loc++ = get(sp); |
| 1082 | } while (--n); |
| 1083 | } |
| 1084 | |
| 1085 | short |
| 1086 | gets(sp) STREAM *sp; { |
| 1087 | short t; mget(&t,2,sp); return(t); |
| 1088 | } |
| 1089 | |
| 1090 | char |
| 1091 | getb(sp) STREAM *sp; { |
| 1092 | char t; mget(&t,1,sp); return(t); |
| 1093 | } |
| 1094 | |
| 1095 | long |
| 1096 | get3(sp) STREAM *sp; { |
| 1097 | long t; t=0; mget(&t,3,sp); return(t); |
| 1098 | } |
| 1099 | |
| 1100 | long |
| 1101 | getl(sp) STREAM *sp; { |
| 1102 | long t; mget(&t,4,sp); |
| 1103 | #ifndef vax |
| 1104 | fixl(&t); |
| 1105 | #endif |
| 1106 | return(t); |
| 1107 | } |
| 1108 | |
| 1109 | symget(sp,f) SYMBOL *sp; STREAM *f; { |
| 1110 | mget(sp,sizeof(*sp),f); |
| 1111 | #ifndef vax |
| 1112 | fixl(&sp->svalue); |
| 1113 | #endif |
| 1114 | } |
| 1115 | |
| 1116 | dseek(sp, loc, s) |
| 1117 | register STREAM *sp; |
| 1118 | long loc, s; |
| 1119 | { |
| 1120 | register PAGE *p; |
| 1121 | register b, o; |
| 1122 | int n; |
| 1123 | |
| 1124 | b = loc>>BSHIFT; |
| 1125 | o = loc&BMASK; |
| 1126 | if (o&01) |
| 1127 | error(1, "loader error; odd offset"); |
| 1128 | --sp->pno->nuser; |
| 1129 | if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b) |
| 1130 | if (p->nuser==0 || (p = &page[0])->nuser==0) { |
| 1131 | if (page[0].nuser==0 && page[1].nuser==0) |
| 1132 | if (page[0].bno < page[1].bno) |
| 1133 | p = &page[0]; |
| 1134 | p->bno = b; |
| 1135 | lseek(infil, loc & ~(long)BMASK, 0); |
| 1136 | if ((n = read(infil, p->buff, sizeof(p->buff))) < 0) |
| 1137 | n = 0; |
| 1138 | p->nibuf = n; |
| 1139 | } else |
| 1140 | error(1, "No pages"); |
| 1141 | ++p->nuser; |
| 1142 | sp->bno = b; |
| 1143 | sp->pno = p; |
| 1144 | if (s != -1) {sp->size = s; sp->pos = 0;} |
| 1145 | sp->ptr = (short *)(p->buff + o); |
| 1146 | if ((sp->nibuf = p->nibuf-o) <= 0) |
| 1147 | sp->size = 0; |
| 1148 | } |
| 1149 | |
| 1150 | char |
| 1151 | get(asp) |
| 1152 | STREAM *asp; |
| 1153 | { |
| 1154 | register STREAM *sp; |
| 1155 | |
| 1156 | sp = asp; |
| 1157 | if ((sp->nibuf -= sizeof(char)) < 0) { |
| 1158 | dseek(sp, ((long)(sp->bno+1)<<BSHIFT), (long)-1); |
| 1159 | sp->nibuf -= sizeof(char); |
| 1160 | } |
| 1161 | if ((sp->size -= sizeof(char)) <= 0) { |
| 1162 | if (sp->size < 0) |
| 1163 | error(1, premeof); |
| 1164 | ++fpage.nuser; |
| 1165 | --sp->pno->nuser; |
| 1166 | sp->pno = &fpage; |
| 1167 | } |
| 1168 | sp->pos += sizeof(char); |
| 1169 | return(*sp->ptr++); |
| 1170 | } |
| 1171 | |
| 1172 | getfile(acp) |
| 1173 | STRING acp; |
| 1174 | { |
| 1175 | register STRING cp; |
| 1176 | register int c; |
| 1177 | int arcmag; |
| 1178 | |
| 1179 | cp = acp; |
| 1180 | infil = -1; |
| 1181 | archdr.ar_name[0] = '\0'; |
| 1182 | filname = cp; |
| 1183 | if (cp[0]=='-' && cp[1]=='l') { |
| 1184 | char *locfilname = "/usr/local/lib/libxxxxxxxxxxxxxxx"; |
| 1185 | if(cp[2] == '\0') |
| 1186 | cp = "-la"; |
| 1187 | filname = "/usr/lib/libxxxxxxxxxxxxxxx"; |
| 1188 | for(c=0; cp[c+2]; c++) { |
| 1189 | filname[c+12] = cp[c+2]; |
| 1190 | locfilname[c+18] = cp[c+2]; |
| 1191 | } |
| 1192 | filname[c+12] = locfilname[c+18] = '.'; |
| 1193 | filname[c+13] = locfilname[c+19] = 'a'; |
| 1194 | filname[c+14] = locfilname[c+20] = '\0'; |
| 1195 | if ((infil = open(filname+4, 0)) >= 0) { |
| 1196 | filname += 4; |
| 1197 | } else if ((infil = open(filname, 0)) < 0) { |
| 1198 | filname = locfilname; |
| 1199 | } |
| 1200 | } |
| 1201 | if (infil == -1 && (infil = open(filname, 0)) < 0) |
| 1202 | error(1, "cannot open"); |
| 1203 | page[0].bno = page[1].bno = -1; |
| 1204 | page[0].nuser = page[1].nuser = 0; |
| 1205 | text.pno = reloc.pno = &fpage; |
| 1206 | fpage.nuser = 2; |
| 1207 | dseek(&text, 0L, (long)sizeof(int)); |
| 1208 | if (text.size <= 0) |
| 1209 | error(1, premeof); |
| 1210 | mget(&arcmag, sizeof(arcmag), &text); |
| 1211 | return(arcmag==ARMAG); |
| 1212 | } |
| 1213 | |
| 1214 | SYMBOL **lookup() |
| 1215 | { |
| 1216 | int i; |
| 1217 | BOOL clash; |
| 1218 | register SYMBOL **hp; |
| 1219 | register char *cp, *cp1; |
| 1220 | |
| 1221 | i = 0; |
| 1222 | for (cp = cursym.sname; cp < &cursym.sname[8];) |
| 1223 | i = (i<<1) + *cp++; |
| 1224 | for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) { |
| 1225 | cp1 = (*hp)->sname; |
| 1226 | clash=FALSE; |
| 1227 | for (cp = cursym.sname; cp < &cursym.sname[8];) |
| 1228 | if (*cp++ != *cp1++) { |
| 1229 | clash=TRUE; |
| 1230 | break; |
| 1231 | } |
| 1232 | if (clash) { |
| 1233 | if (++hp >= &hshtab[NSYM+2]) |
| 1234 | hp = hshtab; |
| 1235 | } else |
| 1236 | break; |
| 1237 | } |
| 1238 | return(hp); |
| 1239 | } |
| 1240 | |
| 1241 | SYMBOL **slookup(s) |
| 1242 | char *s; |
| 1243 | { |
| 1244 | cp8c(s, cursym.sname); |
| 1245 | cursym.stype = EXTERN+UNDEF; |
| 1246 | cursym.svalue = 0; |
| 1247 | return(lookup()); |
| 1248 | } |
| 1249 | |
| 1250 | enter(hp) |
| 1251 | register SYMBOL **hp; |
| 1252 | { |
| 1253 | register SYMBOL *sp; |
| 1254 | |
| 1255 | if (*hp==0) { |
| 1256 | if ((nextsym-symtab)>=NSYM) |
| 1257 | error(1, "Symbol table overflow"); |
| 1258 | if ((nextsym-symtab)>=nsym) { |
| 1259 | if (-1==sbrk(NSYM/5 * sizeof(*symtab))) error(1,"Memory overflow"); |
| 1260 | nsym += NSYM/5; |
| 1261 | } |
| 1262 | *hp = lastsym = sp = nextsym++; |
| 1263 | cp8c(cursym.sname, sp->sname); |
| 1264 | sp->stype = cursym.stype; |
| 1265 | sp->symhash = hp-hshtab; |
| 1266 | sp->svalue = cursym.svalue; |
| 1267 | return(1); |
| 1268 | } else { |
| 1269 | lastsym = *hp; |
| 1270 | return(0); |
| 1271 | } |
| 1272 | } |
| 1273 | |
| 1274 | symreloc() |
| 1275 | { |
| 1276 | switch (cursym.stype & 017) { |
| 1277 | |
| 1278 | case TEXT: |
| 1279 | case EXTERN+TEXT: |
| 1280 | cursym.svalue += ctrel; |
| 1281 | return; |
| 1282 | |
| 1283 | case DATA: |
| 1284 | case EXTERN+DATA: |
| 1285 | cursym.svalue += cdrel; |
| 1286 | return; |
| 1287 | |
| 1288 | case BSS: |
| 1289 | case EXTERN+BSS: |
| 1290 | cursym.svalue += cbrel; |
| 1291 | return; |
| 1292 | |
| 1293 | case EXTERN+UNDEF: |
| 1294 | return; |
| 1295 | } |
| 1296 | if (cursym.stype&EXTERN) |
| 1297 | cursym.stype = EXTERN+ABS; |
| 1298 | } |
| 1299 | |
| 1300 | error(n, s) |
| 1301 | char *s; |
| 1302 | { |
| 1303 | if (errlev==0) |
| 1304 | printf("ld:"); |
| 1305 | if (filname) { |
| 1306 | printf("%s", filname); |
| 1307 | if (archdr.ar_name[0]) |
| 1308 | printf("(%.14s)", archdr.ar_name); |
| 1309 | printf(": "); |
| 1310 | } |
| 1311 | printf("%s\n", s); |
| 1312 | if (n) |
| 1313 | delexit(); |
| 1314 | errlev = 2; |
| 1315 | } |
| 1316 | |
| 1317 | SYMBOL * |
| 1318 | lookloc(lp, r) |
| 1319 | register LOCAL *lp; |
| 1320 | { |
| 1321 | register LOCAL *clp; |
| 1322 | register sn; |
| 1323 | |
| 1324 | sn = r; |
| 1325 | for (clp = local; clp<lp; clp++) |
| 1326 | if (clp->locindex == sn) |
| 1327 | return(clp->locsymbol); |
| 1328 | error(1, "Local symbol botch"); |
| 1329 | } |
| 1330 | |
| 1331 | readhdr(loc) |
| 1332 | long loc; |
| 1333 | { |
| 1334 | long *p; int i; |
| 1335 | dseek(&text, loc, (long)sizeof(filhdr)); |
| 1336 | mget((short *)&filhdr, sizeof(filhdr), &text); |
| 1337 | #ifndef vax |
| 1338 | for (p= &filhdr,i=8;--i>=0;) fixl(p++); |
| 1339 | #endif |
| 1340 | if (filhdr.a_magic!=A_MAGIC1 && filhdr.a_magic!=A_MAGIC2 && |
| 1341 | filhdr.a_magic!=A_MAGIC3 && filhdr.a_magic!=A_MAGIC4) |
| 1342 | error(1,"Bad magic number"); |
| 1343 | if (filhdr.a_text&01 || filhdr.a_data&01) { |
| 1344 | printf("tsize=%X dsize=%X\n",filhdr.a_text,filhdr.a_data); |
| 1345 | error(1, "Text/data size odd"); |
| 1346 | } |
| 1347 | filhdr.a_bss = round(filhdr.a_bss, FW); |
| 1348 | if (filhdr.a_magic == NMAGIC) { |
| 1349 | cdrel = -round(filhdr.a_text, PAGRND); |
| 1350 | cbrel = cdrel - filhdr.a_data; |
| 1351 | } else if (filhdr.a_magic == OMAGIC) { |
| 1352 | cdrel = -filhdr.a_text; |
| 1353 | cbrel = cdrel - filhdr.a_data; |
| 1354 | } else |
| 1355 | error(1, "Bad format"); |
| 1356 | } |
| 1357 | |
| 1358 | cp8c(from, to) |
| 1359 | char *from, *to; |
| 1360 | { |
| 1361 | register char *f, *t, *te; |
| 1362 | |
| 1363 | f = from; |
| 1364 | t = to; |
| 1365 | te = t+8; |
| 1366 | while ((*t++ = *f++) && t<te); |
| 1367 | while (t<te) |
| 1368 | *t++ = 0; |
| 1369 | } |
| 1370 | |
| 1371 | eq(s1, s2) |
| 1372 | STRING s1; |
| 1373 | STRING s2; |
| 1374 | { |
| 1375 | while (*s1==*s2++) |
| 1376 | if ((*s1++)==0) |
| 1377 | return(TRUE); |
| 1378 | return(FALSE); |
| 1379 | } |
| 1380 | |
| 1381 | long |
| 1382 | round(v, r) |
| 1383 | long v; |
| 1384 | unsigned r; |
| 1385 | { |
| 1386 | v += r; |
| 1387 | v &= ~(long)r; |
| 1388 | return(v); |
| 1389 | } |
| 1390 | |
| 1391 | puts(w, f) |
| 1392 | FILE *f; short w; { |
| 1393 | fwrite(&w,sizeof(short),1,f); |
| 1394 | } |
| 1395 | |
| 1396 | putb(w, f) |
| 1397 | FILE *f; char w; { |
| 1398 | fwrite(&w,sizeof(char),1,f); |
| 1399 | } |
| 1400 | |
| 1401 | put3(w, f) |
| 1402 | FILE *f; long w; { |
| 1403 | fwrite(&w,3,1,f); |
| 1404 | } |
| 1405 | |
| 1406 | putl(w, f) |
| 1407 | FILE *f; long w; { |
| 1408 | #ifndef vax |
| 1409 | fixl(&w); |
| 1410 | #endif |
| 1411 | fwrite(&w,sizeof(long),1,f); |
| 1412 | } |