|
|
1.1 ! root 1: /* ! 2: * One pass Coff Loader. ! 3: * Acts as ld and drvld. Will be mkshrlb when the specs are done. ! 4: * ! 5: * By Charles Fiterman for Mark Williams 3/30/92. ! 6: */ ! 7: #include "ld.h" ! 8: #include <stdlib.h> ! 9: #include <signal.h> ! 10: #include <ctype.h> ! 11: #include <path.h> ! 12: ! 13: flag_t reloc, /* Combine input into a new .o not an executable */ ! 14: nosym, /* No symbol table out. */ ! 15: watch, /* Produce a trace */ ! 16: noilcl, /* Discard C local symbols beginning .L */ ! 17: nolcl, /* Discard all local symbols */ ! 18: qflag, /* No warn on commons of different length */ ! 19: Qflag, /* Absolute silence on everything */ ! 20: debflg, /* Create debug data */ ! 21: drvld, /* Called as drvld */ ! 22: fource = -1; /* halt on error */ ! 23: ! 24: int errCount; ! 25: int nundef; ! 26: mod_t *head, /* head of list of modules to load */ ! 27: *tail, /* tail or list of modules */ ! 28: *xhead, /* head of noload modules */ ! 29: *xtail; /* tail of noload modules */ ! 30: ren_t *rhead; /* rename list */ ! 31: ! 32: char *ofname = "a.out"; /* output file name */ ! 33: long comnb, comns, comnl; /* common lengths */ ! 34: char *entrys; /* entry string */ ! 35: sym_t *symtable[NHASH]; /* hashed symbol table */ ! 36: ! 37: unsigned short osegs = NLSEG; /* the number of output segments */ ! 38: unsigned short segMap[MAXSEG] = /* All segments map to the first four */ ! 39: { S_TEXT, S_DATA, S_BSSD, S_COMM }; ! 40: ! 41: FILEHDR fileh; ! 42: AOUTHDR aouth; ! 43: SCNHDR *secth; /* output segments */ ! 44: ! 45: static long str_length; ! 46: static int ofd; ! 47: static long *file_value = NULL, file_first; ! 48: char *argv0; ! 49: ! 50: /* ! 51: * Write or die. ! 52: */ ! 53: void ! 54: xwrite(loc, size) ! 55: char *loc; ! 56: unsigned int size; ! 57: { ! 58: if (size != write(ofd, loc, size)) ! 59: fatal("write error"); /**/ ! 60: } ! 61: ! 62: /* ! 63: * Init segment descriptors. ! 64: */ ! 65: void ! 66: initSegs() ! 67: { ! 68: secth = alloc(sizeof(*secth) * MAXSEG); ! 69: strcpy(secth[S_TEXT].s_name, _TEXT); ! 70: secth[S_TEXT].s_flags = STYP_TEXT; ! 71: strcpy(secth[S_DATA].s_name, _DATA); ! 72: secth[S_DATA].s_flags = STYP_DATA; ! 73: strcpy(secth[S_BSSD].s_name, _BSS); ! 74: secth[S_BSSD].s_flags = STYP_BSS; ! 75: strcpy(secth[S_COMM].s_name, _COMMENT); ! 76: secth[S_COMM].s_flags = STYP_INFO; ! 77: } ! 78: ! 79: /* ! 80: * Come here on interrupt. ! 81: */ ! 82: byebye() ! 83: { ! 84: driver_fail(&aouth); ! 85: exit(1); ! 86: } ! 87: ! 88: /* ! 89: * We are drvld not ld. Ask the system where to put the stuff. ! 90: */ ! 91: getsys() ! 92: { ! 93: register int i; ! 94: long bsz, daddr; ! 95: ! 96: time(&fileh.f_timdat); ! 97: fileh.f_nscns = osegs = NLSEG; ! 98: ! 99: daddr = sizeof(fileh) + (sizeof(* secth) * osegs) + ! 100: (fileh.f_opthdr = sizeof(aouth)); ! 101: ! 102: for (i = 0; i < S_BSSD; i++) { ! 103: secth[i].s_scnptr = daddr; ! 104: daddr += secth[i].s_size; ! 105: } ! 106: bsz = secth[S_BSSD].s_size; ! 107: aouth.tsize = secth[S_TEXT].s_size; ! 108: aouth.dsize = secth[S_DATA].s_size + bsz; ! 109: signal(SIGKILL, byebye); ! 110: if (!driver_alloc(&aouth)) ! 111: fatal("kernel interface failed"); ! 112: /* This will become more elaborite when the kernel is done */ ! 113: secth[S_TEXT].s_vaddr = secth[S_TEXT].s_paddr = aouth.text_start; ! 114: secth[S_DATA].s_vaddr = secth[S_DATA].s_paddr = aouth.data_start; ! 115: secth[S_BSSD].s_vaddr = secth[S_BSSD].s_paddr = aouth.data_start + bsz; ! 116: aouth.dsize -= aouth.bsize = bsz; ! 117: ! 118: if (!nosym) ! 119: fileh.f_symptr = daddr; ! 120: } ! 121: ! 122: /* ! 123: * Set virtual bases in array of segments. ! 124: */ ! 125: static ! 126: baseall() ! 127: { ! 128: register SCNHDR *sh; ! 129: int i; ! 130: unsigned long daddr, vaddr, size; ! 131: ! 132: time(&fileh.f_timdat); ! 133: ! 134: /* Add extra segments to real segments */ ! 135: for (i = NLSEG; i < osegs; i++) { ! 136: SCNHDR *oh; ! 137: ! 138: oh = secth + i; ! 139: sh = secth + segMap[i]; ! 140: ! 141: sh->s_size += oh->s_size; ! 142: sh->s_nreloc += oh->s_nreloc; ! 143: sh->s_nlnno += oh->s_nlnno; ! 144: } ! 145: ! 146: /* only output S_COMM if it has something */ ! 147: fileh.f_nscns = secth[S_COMM].s_size ? NLSEG : S_COMM; ! 148: ! 149: size = 0; ! 150: daddr = sizeof(fileh) + (sizeof(* secth) * fileh.f_nscns); ! 151: if (reloc) ! 152: vaddr = 0; ! 153: else { ! 154: daddr += fileh.f_opthdr = sizeof(aouth); ! 155: if (fileh.f_flags & F_KER) /* kernel */ ! 156: vaddr = KERBASE; ! 157: else /* executable */ ! 158: vaddr = daddr; ! 159: } ! 160: ! 161: /* set s_vaddr, s_paddr, s_size, and s_scnptr for all segments */ ! 162: for (i = 0; i < NLSEG; i++) { ! 163: sh = secth + i; ! 164: switch (i) { ! 165: case S_TEXT: ! 166: aouth.text_start = sh->s_vaddr = vaddr; ! 167: aouth.tsize = size = sh->s_size; ! 168: break; ! 169: ! 170: case S_DATA: /* data adjustment */ ! 171: if (!reloc) { ! 172: if (fileh.f_flags & F_KER) ! 173: vaddr = (vaddr + 0x0fff) & ~0x0fffL; ! 174: else ! 175: vaddr = (vaddr & 0x0fff) + DATABASE; ! 176: } ! 177: ! 178: aouth.data_start = sh->s_vaddr = vaddr; ! 179: aouth.dsize = size = sh->s_size; ! 180: break; ! 181: ! 182: case S_BSSD: ! 183: sh->s_paddr = sh->s_vaddr = vaddr; ! 184: vaddr += aouth.bsize = sh->s_size; ! 185: sh->s_scnptr = 0; ! 186: continue; ! 187: ! 188: default: ! 189: sh->s_vaddr = vaddr; ! 190: size = sh->s_size; ! 191: } ! 192: ! 193: sh->s_paddr = sh->s_vaddr; ! 194: sh->s_scnptr = daddr; ! 195: daddr += size; ! 196: vaddr += size; ! 197: } ! 198: ! 199: /* fix new segments to point to right places */ ! 200: for (i = 0; i < NLSEG; i++) { ! 201: int j; ! 202: long vaddr, daddr; ! 203: ! 204: sh = secth + i; ! 205: vaddr = sh->s_vaddr + sh->s_size; /* mark the end */ ! 206: daddr = sh->s_scnptr + sh->s_size; ! 207: ! 208: for (j = osegs; --j >= NLSEG;) { ! 209: SCNHDR *oh; ! 210: ! 211: if (segMap[j] != i) ! 212: continue; ! 213: ! 214: oh = secth + j; ! 215: oh->s_vaddr = vaddr -= oh->s_size; ! 216: oh->s_scnptr = daddr -= oh->s_size; ! 217: w_message("set extra %.8s at %x %x", ! 218: oh->s_name, vaddr, daddr); ! 219: } ! 220: } ! 221: ! 222: /* set relocations for all segments */ ! 223: for (i = 0; i < NLSEG; i++) { ! 224: sh = secth + i; ! 225: if (!reloc || (S_BSSD == i) || !sh->s_nreloc) { ! 226: sh->s_relptr = 0; ! 227: continue; ! 228: } ! 229: sh->s_relptr = daddr; ! 230: daddr += sh->s_nreloc * RELSZ; ! 231: } ! 232: ! 233: /* set line numbers for all segments */ ! 234: for (i = 0; i < NLSEG; i++) { ! 235: sh = secth + i; ! 236: if (!debflg || !sh->s_nlnno) { ! 237: sh->s_nlnno = sh->s_lnnoptr = 0; ! 238: continue; ! 239: } ! 240: sh->s_lnnoptr = daddr; ! 241: daddr += sh->s_nlnno * LINESZ; ! 242: } ! 243: ! 244: if (!nosym) ! 245: fileh.f_symptr = daddr; ! 246: } ! 247: ! 248: /* ! 249: * return entry point ! 250: */ ! 251: static long ! 252: lentry(str) ! 253: char *str; ! 254: { ! 255: if (NULL == str) /* not user specified */ ! 256: return(aouth.text_start); ! 257: ! 258: /* If an octal number use that */ ! 259: { ! 260: register unsigned char c, *s; ! 261: long oaddr = 0; ! 262: ! 263: /* Try to scan whole string as octal. */ ! 264: for (s = str; c = *s++;) { ! 265: if (('0' > c) || (c > '7')) ! 266: break; ! 267: oaddr = (oaddr * 8) + (c - '0'); ! 268: } ! 269: ! 270: if (!c) ! 271: return (oaddr); ! 272: } ! 273: ! 274: /* Search for string in symbol table. */ ! 275: { ! 276: register sym_t *sp; ! 277: char work[SYMNMLEN + 1]; ! 278: ! 279: for (sp = symtable[crc16(str) % NHASH]; ! 280: sp != NULL; ! 281: sp = sp->next) { ! 282: if ((sp->sym.n_sclass == C_EXT) && ! 283: !strcmp(symName(&(sp->sym), work), str)) { ! 284: if (sp->sym.n_scnum != (S_TEXT + 1)) ! 285: message("entry point '%s' not in .text"); ! 286: return(sp->sym.n_value); ! 287: } ! 288: } ! 289: ! 290: message("entry point '%s' undefined", str); /**/ ! 291: return (aouth.text_start); ! 292: } ! 293: } ! 294: ! 295: /* ! 296: * Define referenced special symbols. ! 297: */ ! 298: void ! 299: symBind(sn, ldrv, name, loc) ! 300: int sn, ldrv; ! 301: char *name; ! 302: long loc; ! 303: { ! 304: register SYMENT *sym; ! 305: register sym_t *sp; ! 306: char work[SYMNMLEN + 1]; ! 307: ! 308: for (sp = symtable[crc16(name) % NHASH]; sp != NULL; sp = sp->next) { ! 309: sym = &(sp->sym); ! 310: if ((sym->n_sclass != C_EXT) || ! 311: strcmp(symName(sym, work), name)) ! 312: continue; ! 313: ! 314: if (undefined(sym)) { ! 315: nundef--; ! 316: sym->n_scnum = sn + 1; ! 317: sym->n_value = loc; ! 318: sp->mod = NULL; /* not defined in any mod */ ! 319: return; ! 320: } ! 321: ! 322: if (ldrv) ! 323: return; ! 324: else ! 325: spwarn(sp, "redefines builtin symbol"); ! 326: /* Some symbols such as __end and __end_text ! 327: * are special to the linker. In general symbols ! 328: * beginning __ are reserved to implementors and ! 329: * should be avoided by users. ! 330: * Your definition has been used. */ ! 331: } ! 332: } ! 333: ! 334: /* ! 335: * Add reference to symbol table ! 336: */ ! 337: void ! 338: undef(s) ! 339: char *s; ! 340: { ! 341: SYMENT lds; ! 342: ! 343: memset(&lds, '\0', sizeof(lds)); ! 344: lds.n_offset = (long)s; /* point symbol at our stuff */ ! 345: lds.n_sclass = C_EXTDEF; /* mark undefined */ ! 346: addsym(&lds, NULL); /* connect to no module */ ! 347: } ! 348: ! 349: /* ! 350: * Show undefined symbols. ! 351: */ ! 352: void ! 353: showUndef(sp, sym) ! 354: register sym_t *sp; ! 355: register SYMENT *sym; ! 356: { ! 357: if (undefined(sym)) ! 358: spmsg(sp, ""); /* NODOC */ ! 359: } ! 360: ! 361: /* ! 362: * Pass all symbols through a function. ! 363: * In a really elaborite order. ! 364: */ ! 365: void ! 366: allSym(fun) ! 367: int (*fun)(); ! 368: { ! 369: register SYMENT *sym; ! 370: register sym_t *sp; ! 371: register mod_t *mp; ! 372: register i; ! 373: SYMENT *symEnd; ! 374: ! 375: if (reloc) { /* We are producing another .o */ ! 376: /* ! 377: * Do symbols connected to modules in module order. ! 378: * Only process a global symbol for it's owner. ! 379: */ ! 380: for (mp = head; mp != (mod_t *)NULL; mp = mp->next) { ! 381: sym = ((SYMENT *)(mp->f->f_symptr)); ! 382: symEnd = sym + mp->f->f_nsyms; ! 383: for (; sym < symEnd; sym += sym->n_numaux + 1) { ! 384: if (1 == sym->n_zeroes) { /* pointer to original */ ! 385: sp = (sym_t *)sym->n_offset; ! 386: if (sp->mod == mp) ! 387: (*fun)(sp, &(sp->sym), mp, sym); ! 388: } ! 389: else ! 390: (*fun)(NULL, sym, mp, sym); ! 391: } ! 392: } ! 393: } ! 394: else { ! 395: /* ! 396: * Producing an executable. ! 397: */ ! 398: for (mp = head; mp != (mod_t *)NULL; mp = mp->next) { ! 399: char showSym; ! 400: ! 401: sym = ((SYMENT *)(mp->f->f_symptr)); ! 402: symEnd = sym + mp->f->f_nsyms; ! 403: ! 404: /* ! 405: * If first entry is not C_FILE supress ! 406: * all non C_EXT entries for debug, they make ! 407: * Orignon barf. If not debug mode and the ! 408: * user wants a symbol table give him everything. ! 409: */ ! 410: showSym = !debflg || C_FILE == sym->n_sclass; ! 411: ! 412: for (; sym < symEnd; sym += sym->n_numaux + 1) { ! 413: if ((C_EXT == sym->n_sclass) && !sym->n_numaux) ! 414: continue; /* do later */ ! 415: ! 416: /* pointer to original */ ! 417: if (1 == sym->n_zeroes) { ! 418: sp = (sym_t *)sym->n_offset; ! 419: if (sp->mod == mp) ! 420: (*fun)(showSym ? sp : NULL, ! 421: &(sp->sym), mp, sym); ! 422: } ! 423: else ! 424: (*fun)(NULL, sym, mp, sym); ! 425: } ! 426: } ! 427: ! 428: /* All C_EXT entries go at the end. */ ! 429: for (mp = head; mp != (mod_t *)NULL; mp = mp->next) { ! 430: sym = ((SYMENT *)(mp->f->f_symptr)); ! 431: symEnd = sym + mp->f->f_nsyms; ! 432: for (; sym < symEnd; sym += sym->n_numaux + 1) { ! 433: if (!((C_EXT == sym->n_sclass) && ! 434: !sym->n_numaux)) ! 435: continue; ! 436: ! 437: /* pointer to original */ ! 438: if (1 == sym->n_zeroes) { ! 439: sp = (sym_t *)sym->n_offset; ! 440: if (sp->mod == mp) ! 441: (*fun)(sp, &(sp->sym), mp, sym); ! 442: } ! 443: else ! 444: (*fun)(NULL, sym, mp, sym); ! 445: } ! 446: } ! 447: } ! 448: ! 449: /* ! 450: * Do symbols not connected to a module. ! 451: * These are end symbols and symbols defined with -u option ! 452: */ ! 453: for (i = 0; i < NHASH; i++) ! 454: for (sp = symtable[i]; NULL != sp; sp = sp->next) ! 455: if (NULL == sp->mod) ! 456: (*fun)(sp, &(sp->sym), sp->mod, NULL); ! 457: } ! 458: ! 459: /* ! 460: * Fixup a symbol between passes. ! 461: */ ! 462: void ! 463: symFix(sp, sym, mp, auxp) ! 464: sym_t *sp; ! 465: register SYMENT *sym, *auxp; ! 466: mod_t *mp; ! 467: { ! 468: int segn, len; ! 469: ! 470: segn = sym->n_scnum; ! 471: if (debflg && NULL != auxp && C_FILE == sym->n_sclass) { ! 472: if (NULL != file_value) /* files point in a circle */ ! 473: *file_value = fileh.f_nsyms; ! 474: else ! 475: file_first = fileh.f_nsyms; ! 476: file_value = &(sym->n_value); ! 477: fileh.f_nsyms += sym->n_numaux + 1; ! 478: return; ! 479: } ! 480: if (!reloc && common(sym)) { ! 481: switch ((len = sym->n_value) & 3) { ! 482: case 2: /* 2 byte aligned */ ! 483: sym->n_value = comns; ! 484: comns += len; ! 485: break; ! 486: case 0: /* 4 byte aligned */ ! 487: sym->n_value = comnl; ! 488: comnl += len; ! 489: break; ! 490: default: /* unaligned */ ! 491: sym->n_value = comnb; ! 492: comnb += len; ! 493: } ! 494: sym->n_scnum = S_BSSD + 1; ! 495: } ! 496: else if (segn > 0) ! 497: /* ! 498: * Correct the value to the output sector header. ! 499: * If mp == NULL then segn this is a constructed symbol ! 500: * and segn is relative to the output sector headers. ! 501: * Otherwise it is relative to the input sector headers ! 502: * but the connection to the output sector headers was ! 503: * placed in s_paddr by pass1.c/object(). ! 504: */ ! 505: sym->n_value += secth[(NULL == mp) ? segn - 1 : ! 506: mp->s[segn - 1].s_paddr].s_vaddr; ! 507: ! 508: if (NULL != sp && !nosym) { ! 509: sp->symno = fileh.f_nsyms++; ! 510: if (debflg) ! 511: fileh.f_nsyms += sym->n_numaux; ! 512: } ! 513: } ! 514: ! 515: /* ! 516: * Do work between passes. ! 517: */ ! 518: void ! 519: betweenPass() ! 520: { ! 521: if (reloc) ! 522: fileh.f_flags |= F_AR32WR; ! 523: else { ! 524: fileh.f_flags |= F_RELFLG | F_EXEC | F_AR32WR; ! 525: comnb += (4 - ((comnb + comns) & 3)) & 3; ! 526: secth[S_BSSD].s_size += comnb + comns + comnl; ! 527: } ! 528: if (nosym) ! 529: fileh.f_flags |= F_LSYMS; ! 530: ! 531: if (!debflg) ! 532: fileh.f_flags |= F_LNNO; ! 533: ! 534: if (drvld) ! 535: getsys(); /* get segment base information from system */ ! 536: else ! 537: baseall(); /* compute segment base information */ ! 538: ! 539: if (!reloc) { ! 540: int i; ! 541: ! 542: /* define referenced end of segment symbols */ ! 543: for (i = 0; i < NLSEG; i++) { ! 544: char end_name[20], c, *p; ! 545: ! 546: sprintf(end_name, "__end%.8s", secth[i].s_name); ! 547: for (p = end_name; '\0' != (c = *p); p++) ! 548: if (!isalnum(c)) ! 549: *p = '_'; ! 550: ! 551: symBind(i, drvld, end_name, secth[i].s_size); ! 552: } ! 553: /* define absolute end symbol */ ! 554: symBind(S_BSSD, drvld, "__end", secth[S_BSSD].s_size); ! 555: ! 556: /* get starting addresses for 1, 2 and 4 alligned commons */ ! 557: comnb = secth[S_BSSD].s_vaddr + secth[S_BSSD].s_size - comnb; ! 558: comns = comnb - comns; ! 559: comnl = comns - comnl; ! 560: } ! 561: ! 562: if (nundef && !reloc) { ! 563: message("the following symbols are undefined"); ! 564: errCount--; ! 565: allSym(showUndef); ! 566: } ! 567: ! 568: switch (errCount & fource) { ! 569: case 0: ! 570: break; ! 571: case 1: ! 572: fatal("pass 1, 1 error"); /* NODOC */ ! 573: default: ! 574: fatal("pass 1, %d errors", errCount); ! 575: /* At the end of pass 1 there were \fIn\fB errors detected. ! 576: * The link stopped here. */ ! 577: } ! 578: ! 579: /* Run through symbol table doing fixups */ ! 580: fileh.f_nsyms = 0; ! 581: allSym(symFix); ! 582: ! 583: if (NULL != file_value) ! 584: *file_value = file_first; ! 585: ! 586: aouth.entry = lentry(entrys); ! 587: } ! 588: ! 589: /* ! 590: * output symbol table. ! 591: */ ! 592: static void ! 593: outputSym(s, sm, mp, auxp) ! 594: register sym_t *s; ! 595: register SYMENT *sm; ! 596: mod_t *mp; ! 597: SYMENT *auxp; ! 598: { ! 599: int i; ! 600: char *name, work[SYMNMLEN + 1]; ! 601: SCNHDR *scn; ! 602: SYMENT sym; ! 603: ! 604: if (NULL == (char *)s) ! 605: return; ! 606: ! 607: /* build writeable copy */ ! 608: memcpy(&sym, sm, sizeof(sym)); ! 609: name = symName(sm, work); ! 610: ! 611: if (SYMNMLEN < (i = strlen(name))) { ! 612: sym.n_offset = str_length; ! 613: str_length += i + 1; ! 614: } ! 615: else ! 616: memcpy(sym.n_name, name, SYMNMLEN); ! 617: ! 618: if (!debflg || NULL == auxp) ! 619: sym.n_numaux = 0; ! 620: ! 621: if ((sym.n_scnum > 0) && (NULL != mp)) ! 622: sym.n_scnum = segMap[mp->s[sym.n_scnum - 1].s_paddr] + 1; ! 623: ! 624: xwrite(&sym, SYMESZ); ! 625: ! 626: if (sym.n_numaux) { ! 627: int aux = 1; ! 628: int has_fcn = 0; ! 629: ! 630: switch(sym.n_sclass) { ! 631: case C_STRTAG: ! 632: case C_UNTAG: ! 633: case C_ENTAG: ! 634: case C_BLOCK: ! 635: has_fcn = 1; ! 636: break; ! 637: case C_STAT: ! 638: case C_FILE: ! 639: aux = sym.n_numaux + 1; /* dont scan for ixs */ ! 640: break; ! 641: default: ! 642: if (ISFCN(sym.n_type)) ! 643: has_fcn = 1; ! 644: } ! 645: ! 646: for (; aux <= sym.n_numaux; aux++) { ! 647: SYMENT *s1, *s2, *s3; ! 648: AUXENT *a = auxp + aux; ! 649: ! 650: /* ! 651: * Fix indices to new value. ! 652: */ ! 653: if (a->ae_tagndx) { ! 654: s1 = ((SYMENT *)(mp->f->f_symptr)) + ! 655: a->ae_tagndx; ! 656: s = (sym_t *)s1->n_offset; ! 657: a->ae_tagndx = s->symno; ! 658: } ! 659: /* ae_endndx points past an entry */ ! 660: if (has_fcn && a->ae_endndx) { ! 661: s2 = ((SYMENT *)(mp->f->f_symptr)); ! 662: /* find the entry it points past */ ! 663: for (s1 = s2 + a->ae_endndx; ! 664: (s3 = (s2 + s2->n_numaux + 1)) < s1; ! 665: s2 = s3) ! 666: ; ! 667: s = (sym_t *)s2->n_offset; ! 668: a->ae_endndx = s->symno + s2->n_numaux + 1; ! 669: } ! 670: } ! 671: xwrite(auxp + 1, SYMESZ * sym.n_numaux); ! 672: } ! 673: } ! 674: ! 675: /* ! 676: * output long symbols. ! 677: */ ! 678: static void ! 679: longSym(s, sm) ! 680: register sym_t *s; ! 681: register SYMENT *sm; ! 682: { ! 683: int i; ! 684: char *name, work[SYMNMLEN + 1]; ! 685: ! 686: if (NULL == s) ! 687: return; ! 688: ! 689: name = symName(sm, work); ! 690: if (SYMNMLEN < (i = strlen(name))) ! 691: xwrite(name, i + 1); ! 692: } ! 693: ! 694: ! 695: /* ! 696: * Scan this modules sections for a name match. ! 697: */ ! 698: SCNHDR * ! 699: findSeg(mp, segn) ! 700: register mod_t *mp; ! 701: { ! 702: int i; ! 703: register SCNHDR *orsp, *isgp; ! 704: ! 705: orsp = secth + segn; ! 706: for (i = 0; i < mp->f->f_nscns; i++) { ! 707: isgp = mp->s + i; ! 708: if (strncmp(isgp->s_name, orsp->s_name, 8)) ! 709: isgp = NULL; ! 710: else ! 711: break; ! 712: } ! 713: return isgp; ! 714: } ! 715: ! 716: /* ! 717: * Do relocations ! 718: */ ! 719: static void ! 720: relocations(mp, osegn, isegn) ! 721: mod_t * mp; ! 722: { ! 723: register RELOC *rel; ! 724: char *t; /* actual text */ ! 725: SCNHDR *isgp, *orsp; ! 726: unsigned i; ! 727: long size, told, fixr; ! 728: ! 729: if ((NULL == (isgp = findSeg(mp, isegn))) || !(size = isgp->s_size)) ! 730: return; ! 731: ! 732: orsp = secth + osegn; ! 733: fixr = isgp->s_vaddr - orsp->s_vaddr; ! 734: t = (char *)isgp->s_scnptr; ! 735: ! 736: if (watch) { ! 737: errCount--; ! 738: mpmsg(mp, "relocating seg#%.8s[%06lx]@%06lx to %06lx r %ld", ! 739: isgp->s_name, ! 740: size, ! 741: isgp->s_vaddr, ! 742: orsp->s_vaddr, ! 743: isgp->s_nreloc); /* NODOC */ ! 744: told = lseek(ofd, 0, 2); ! 745: } ! 746: ! 747: for (i = 0; i < isgp->s_nreloc; i++) { ! 748: char *ptr; ! 749: char *mtype; ! 750: sym_t *sp; ! 751: SYMENT *s, *sym; ! 752: long relf, w, at; ! 753: int undef; ! 754: char work[SYMNMLEN + 1], *name; ! 755: static char *pcrel = "pcrel"; ! 756: ! 757: /* get reloc record */ ! 758: rel = ((RELOC *)isgp->s_relptr) + i; ! 759: ! 760: w = rel->r_vaddr - isgp->s_vaddr; ! 761: if ((w < 0) || (w > size)) ! 762: corrupt(mp); ! 763: ptr = t + w; ! 764: ! 765: if ((rel->r_symndx < 0) || (rel->r_symndx > mp->f->f_nsyms)) ! 766: corrupt(mp); ! 767: ! 768: s = (SYMENT *)mp->f->f_symptr + rel->r_symndx; ! 769: if (1 == s->n_zeroes) { /* fixed elsewhere */ ! 770: sp = (sym_t *)s->n_offset; ! 771: sym = &(sp->sym); ! 772: } else { ! 773: sp = NULL; ! 774: sym = s; ! 775: } ! 776: relf = sym->n_value; ! 777: mtype = "rel"; ! 778: undef = undefined(sym); ! 779: ! 780: if (watch) { ! 781: at = told + w; ! 782: name = symName(sym, work); ! 783: } ! 784: /* ! 785: * This wierdness is to deal with a coff wierdness. ! 786: * The address of a common is incremented by the ! 787: * length of the common as seen in that module. ! 788: */ ! 789: if (common(s)) ! 790: relf -= s->n_value; ! 791: /* ! 792: * If the symbol is native to this module ! 793: * the reference already has this modules ! 794: * segment address. Subtract it. ! 795: */ ! 796: else if (!undef && ((NULL == sp) || (sp->mod == mp))) ! 797: relf -= mp->s[s->n_scnum - 1].s_vaddr; ! 798: ! 799: /* relocate what the pointer is aimed at and leave a record */ ! 800: #define relocate(type) *(type *)ptr = (w = *(type *)ptr) + relf ! 801: ! 802: if (reloc) { ! 803: rel->r_vaddr = w + orsp->s_vaddr; ! 804: rel->r_symndx = sp->symno; ! 805: ! 806: switch (rel->r_type) { ! 807: case R_PCRBYTE: ! 808: mtype = pcrel; ! 809: relf = fixr; ! 810: ! 811: case R_DIR8: ! 812: case R_RELBYTE: ! 813: relocate(char); ! 814: break; ! 815: ! 816: case R_PCRWORD: ! 817: mtype = pcrel; ! 818: relf = fixr; ! 819: ! 820: case R_DIR16: ! 821: case R_RELWORD: ! 822: relocate(short); ! 823: break; ! 824: ! 825: case R_PCRLONG: ! 826: mtype = pcrel; ! 827: relf = fixr; ! 828: ! 829: case R_DIR32: ! 830: case R_RELLONG: ! 831: relocate(long); ! 832: break; ! 833: ! 834: case R_NONREL: ! 835: mtype = "nonrel"; ! 836: w = *(long *)ptr; ! 837: relf = 0; ! 838: break; ! 839: ! 840: default: ! 841: mpmsg(mp, "unknown r_type %d in segment %.8s record %d", ! 842: rel->r_type, isgp->s_name, i); ! 843: /* Unknown type on COFF relocation record. */ ! 844: } ! 845: ! 846: if ((sym->n_scnum > 0) && (mtype != pcrel)) ! 847: rel->r_symndx = sym->n_scnum - 1; ! 848: ! 849: if (!undef && (sym->n_scnum < 0)) ! 850: rel->r_type = R_NONREL; ! 851: ! 852: w_message("%lx '%s'(%d %lx %lx) %lx = '%s'(%lx) + %lx", ! 853: at, ! 854: mtype, ! 855: rel->r_type, ! 856: rel->r_vaddr, ! 857: rel->r_symndx, ! 858: relf + w, ! 859: name, ! 860: sym->n_value, ! 861: w); ! 862: } ! 863: else { ! 864: switch (rel->r_type) { ! 865: case R_PCRBYTE: ! 866: mtype = pcrel; ! 867: relf -= orsp->s_vaddr; ! 868: case R_DIR8: ! 869: case R_RELBYTE: ! 870: relocate(char); ! 871: break; ! 872: case R_PCRWORD: ! 873: mtype = pcrel; ! 874: relf -= orsp->s_vaddr; ! 875: case R_RELWORD: ! 876: case R_DIR16: ! 877: relocate(short); ! 878: break; ! 879: case R_PCRLONG: ! 880: mtype = pcrel; ! 881: relf -= orsp->s_vaddr; ! 882: case R_RELLONG: ! 883: case R_DIR32: ! 884: relocate(long); ! 885: break; ! 886: case R_NONREL: ! 887: mtype = "nonrel"; ! 888: w = *(long *)ptr; ! 889: relf = 0; ! 890: break; ! 891: default: ! 892: mpmsg(mp, "unknown r_type %d in segment %.8s record %d", ! 893: rel->r_type, isgp->s_name, i); ! 894: /* NODOC */ ! 895: } ! 896: w_message("%lx '%s'(%d) %lx = '%s'(%lx) + %lx", ! 897: at, ! 898: mtype, ! 899: rel->r_type, ! 900: relf + w, ! 901: name, ! 902: sym->n_value, ! 903: w); ! 904: } ! 905: } ! 906: #undef relocate ! 907: ! 908: orsp->s_vaddr += size; ! 909: xwrite(t, (int)size); ! 910: } ! 911: ! 912: /* ! 913: * Write line records for a segment. ! 914: */ ! 915: writeLine(mp, segn) ! 916: mod_t *mp; ! 917: { ! 918: int j; ! 919: long fptr; ! 920: AUXENT *a; ! 921: SYMENT *sym; ! 922: LINENO *l; ! 923: SCNHDR *scn; ! 924: ! 925: if (NULL == (scn = findSeg(mp, segn)) || (!scn->s_nlnno)) ! 926: return; ! 927: ! 928: /* ! 929: * set up n_lnnoptr in symbol table to point ! 930: * to line records ! 931: */ ! 932: l = (LINENO *)scn->s_lnnoptr; ! 933: fptr = lseek(ofd, 0L, 1); /* where I am */ ! 934: for (j = 0; j < scn->s_nlnno; j++, l++) { ! 935: if (!l->l_lnno) { ! 936: sym = ((SYMENT *)(mp->f->f_symptr)) + ! 937: l->l_addr.l_symndx; ! 938: if (sym->n_numaux) { ! 939: a = (AUXENT *)sym + 1; ! 940: a->ae_lnnoptr = fptr; ! 941: if (1 == sym->n_zeroes) { ! 942: sym_t *sp; ! 943: sp = (sym_t *)sym->n_offset; ! 944: l->l_addr.l_symndx = sp->symno; ! 945: } ! 946: } ! 947: } ! 948: fptr += LINESZ; ! 949: } ! 950: xwrite(scn->s_lnnoptr, LINESZ * scn->s_nlnno); ! 951: } ! 952: ! 953: /* ! 954: * Output all data. ! 955: */ ! 956: outputAll() ! 957: { ! 958: register mod_t *mp; ! 959: register SCNHDR *scn; ! 960: int i, j; ! 961: struct stat statbuf; ! 962: ! 963: /* Open output file */ ! 964: ofd = qopen(ofname, 1); ! 965: ! 966: /* write header */ ! 967: xwrite(&fileh, sizeof(fileh)); ! 968: ! 969: if (!reloc) { /* if executable set bits and write opt header */ ! 970: stat(ofname, &statbuf); ! 971: chmod(ofname, ! 972: statbuf.st_mode | S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)); ! 973: ! 974: aouth.magic = Z_MAGIC; ! 975: xwrite(&aouth, sizeof(aouth)); ! 976: } ! 977: ! 978: /* write sector headers */ ! 979: xwrite(secth, sizeof(* secth) * fileh.f_nscns); ! 980: ! 981: /* write corrected text segments */ ! 982: for (i = 0; i < NLSEG; i++) { ! 983: if (i == S_BSSD) ! 984: continue; ! 985: for (j = 0; j < osegs; j++) { ! 986: if (segMap[j] == i) ! 987: for (mp = head; mp != NULL; mp = mp->next) ! 988: relocations(mp, i, j); ! 989: } ! 990: } ! 991: ! 992: /* write relocation if required */ ! 993: for (i = (reloc ? 0 : S_BSSD); i < S_BSSD; i++) { ! 994: for (j = 0; j < osegs; j++) { ! 995: if (segMap[j] != i) ! 996: continue; ! 997: ! 998: for (mp = head; mp != NULL; mp = mp->next) { ! 999: if ((NULL == (scn = findSeg(mp, j))) || ! 1000: !scn->s_nreloc) ! 1001: continue; ! 1002: xwrite(scn->s_relptr, ! 1003: RELSZ * (int)scn->s_nreloc); ! 1004: } ! 1005: } ! 1006: } ! 1007: ! 1008: /* write lines if required */ ! 1009: for (i = (debflg ? 0 : NLSEG); i < NLSEG; i++) { ! 1010: for (j = 0; j < osegs; j++) { ! 1011: if (segMap[j] != i) ! 1012: continue; ! 1013: ! 1014: for (mp = head; mp != NULL; mp = mp->next) ! 1015: writeLine(mp, j); ! 1016: } ! 1017: } ! 1018: ! 1019: if (!nosym) { ! 1020: str_length = 4; ! 1021: ! 1022: allSym(outputSym); ! 1023: if (4 != str_length) { ! 1024: xwrite(&str_length, sizeof(str_length)); ! 1025: allSym(longSym); ! 1026: } ! 1027: } ! 1028: ! 1029: close(ofd); ! 1030: } ! 1031: ! 1032: /* ! 1033: * Process arguements, and call other work. ! 1034: */ ! 1035: main(argc, argv) ! 1036: char *argv[]; ! 1037: { ! 1038: int c; ! 1039: char *specialList = NULL; ! 1040: char *argString = "?ge:finKl:L:o:A:O:rsu:wXxZ:qQ"; ! 1041: char *env; ! 1042: ! 1043: /* find program name */ ! 1044: if (NULL == (argv0 = strrchr(argv[0], '/'))) ! 1045: argv0 = argv[0]; ! 1046: else ! 1047: argv0++; ! 1048: ! 1049: env = getenv("LIBPATH"); ! 1050: /* ! 1051: * drvld is an alternative name for ld. ! 1052: * In this mode ld will load the kernel's symbol table, so ! 1053: * that the loadable driver can link directly to kernel services. ! 1054: * After pass1 we call driver_alloc() to tell the kernel the ! 1055: * sizes of the driver segments, the kernel replys with locations ! 1056: * for them. Then we output the driver to a tmp file and execl() ! 1057: */ ! 1058: if (!strcmp(argv0, "drvld")) { ! 1059: #if 0 ! 1060: ofname = tmpnam(NULL); ! 1061: #endif ! 1062: argString = "?ge:l:L:u:wdq"; ! 1063: fileh.f_flags |= F_KER; ! 1064: drvld = 1; ! 1065: /* read kernel for symbol table but don't load */ ! 1066: readFile(kernelName(), 0, NULL); ! 1067: _addargs("DRVLD", &argc, &argv); ! 1068: } ! 1069: else ! 1070: _addargs("LD", &argc, &argv); ! 1071: ! 1072: initSegs(); ! 1073: ! 1074: while (EOF != (c = getargs(argc, argv, argString))) { ! 1075: switch (c) { ! 1076: case 0: /* Not an option, read a file for load */ ! 1077: readFile(optarg, 1, NULL); ! 1078: continue; ! 1079: ! 1080: case 'A': /* Read a file as an archive regardless of name */ ! 1081: readFile(optarg, 1, ".a"); ! 1082: continue; ! 1083: ! 1084: case 'O': /* Read a file as an object regardless of name */ ! 1085: readFile(optarg, 1, ".o"); ! 1086: continue; ! 1087: ! 1088: case 'f': /* attempt link even if errors */ ! 1089: fource = 0; ! 1090: continue; ! 1091: ! 1092: case 'g': /* save extra segments and aux symbols */ ! 1093: debflg ^= 1; ! 1094: continue; ! 1095: ! 1096: case 'e': ! 1097: entrys = optarg; ! 1098: ! 1099: case 'Z': /* use and erase after */ ! 1100: case 'i': /* obselete options */ ! 1101: case 'n': ! 1102: continue; ! 1103: ! 1104: case 'K': /* recompile of Kernel */ ! 1105: fileh.f_flags |= F_KER; ! 1106: continue; ! 1107: ! 1108: case 'L': ! 1109: /* ! 1110: * Special filelist for lookup. ! 1111: */ ! 1112: { ! 1113: char *new; ! 1114: ! 1115: if (NULL == specialList) { ! 1116: new = alloc(strlen(optarg) + 2); ! 1117: sprintf(new, "%c%s", LISTSEP, optarg); ! 1118: } ! 1119: else { ! 1120: new = alloc( ! 1121: strlen(specialList)+strlen(optarg)+2); ! 1122: sprintf(new, "%s%c%s", ! 1123: specialList, LISTSEP, optarg); ! 1124: free(specialList); ! 1125: } ! 1126: specialList = new; ! 1127: continue; ! 1128: } ! 1129: ! 1130: case 'l': ! 1131: /* -l<lib>: use standard lib */ ! 1132: { ! 1133: char *xp, *lp; ! 1134: ! 1135: xp = alloc(strlen(optarg) + 6); ! 1136: sprintf(xp, "lib%s.a", optarg); ! 1137: lp = NULL; ! 1138: if (NULL != specialList) ! 1139: lp = path(specialList, xp, AREAD); ! 1140: if (NULL == lp && NULL != env) ! 1141: lp = path(env, xp, AREAD); ! 1142: if (NULL == lp) ! 1143: lp = path(DEFLIBPATH, xp, AREAD); ! 1144: if (NULL == lp) ! 1145: fatal("can't find '%s'", xp); ! 1146: /* Can't locate requested library. */ ! 1147: ! 1148: readFile(lp, 1, NULL); ! 1149: free(xp); ! 1150: continue; ! 1151: } ! 1152: ! 1153: case 'o': ! 1154: ofname = optarg; ! 1155: continue; ! 1156: ! 1157: case 'r': ! 1158: reloc ^= 1; /* retain relocation information */ ! 1159: continue; ! 1160: ! 1161: case 's': ! 1162: nosym ^= 1; ! 1163: continue; ! 1164: ! 1165: case 'u': ! 1166: undef(optarg); ! 1167: continue; ! 1168: ! 1169: case 'Q': ! 1170: Qflag = 1; ! 1171: ! 1172: case 'q': ! 1173: qflag = 1; ! 1174: continue; ! 1175: ! 1176: case 'w': ! 1177: watch ^= 1; ! 1178: continue; ! 1179: ! 1180: case 'X': ! 1181: noilcl ^= 1; ! 1182: continue; ! 1183: ! 1184: case 'x': ! 1185: nolcl ^= 1; ! 1186: continue; ! 1187: ! 1188: case '?': ! 1189: help(); /* non returning */ ! 1190: ! 1191: default: ! 1192: usage(); /* non returning */ ! 1193: } ! 1194: } ! 1195: if (nosym) ! 1196: nolcl = 1; ! 1197: ! 1198: if (reloc || debflg) ! 1199: nosym = nolcl = noilcl = 0; ! 1200: ! 1201: if (!fileh.f_magic) ! 1202: fatal("No work"); ! 1203: /* There were no object files loaded. */ ! 1204: ! 1205: betweenPass(); /* between passes */ ! 1206: outputAll(); /* output all data */ ! 1207: ! 1208: /* repass argument list to erase any -Z files */ ! 1209: for (optix = 1; EOF != (c = getargs(argc, argv, argString));) ! 1210: if ('Z' == c) ! 1211: unlink(optarg); ! 1212: ! 1213: #if 0 ! 1214: if (drvld) { ! 1215: execl(ofname, ofname, NULL); /* should never return */ ! 1216: fatal("Cannot execute loadable driver '%s'.", ofname); /**/ ! 1217: } ! 1218: #endif ! 1219: return (0); ! 1220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.