|
|
1.1 ! root 1: /* ! 2: * coff format output handler. ! 3: */ ! 4: #include <asm.h> ! 5: #include <coff.h> ! 6: #include <utype.h> ! 7: #include <symtab.h> ! 8: ! 9: #define WHERE 0x40A09C ! 10: ! 11: #define trace(n) printf("Trace %d\n", n); ! 12: ! 13: #define CMOD 2 /* clump every 2 bytes */ ! 14: #define LIMIT 10 /* bytes of data per line */ ! 15: #define STARTP 31 /* start source at. Must be n * 8 -1 */ ! 16: #define DATABUF 512 /* size of data buffer */ ! 17: #define RELBUF 128 /* entries in relocation buffer */ ! 18: #define LINEBUF 128 /* entries in line number buffer */ ! 19: #define MANSEG 3 /* Segments that must go out */ ! 20: #define ROUNDR 3 /* used to round segments */ ! 21: ! 22: typedef struct seg seg; ! 23: struct seg { /* coff section header */ ! 24: char s_name[8]; /* section name */ ! 25: long s_paddr; /* physical address, aliased s_nlib */ ! 26: long s_vaddr; /* virtual address */ ! 27: long s_size; /* section size */ ! 28: long s_scnptr; /* file ptr to raw data for section */ ! 29: long s_relptr; /* file ptr to relocation */ ! 30: long s_lnnoptr; /* file ptr to line numbers */ ! 31: unsigned short s_nreloc; /* number of relocation entries */ ! 32: unsigned short s_nlnno; /* number of line number entries */ ! 33: long s_flags; /* flags */ ! 34: ! 35: /* Extra data connected with this to allow running this segment */ ! 36: long data_seekad; /* next data seek address */ ! 37: long relo_seekad; /* next relocation seek address */ ! 38: long line_seekad; /* next line seek address */ ! 39: long curadd; /* current address this segment */ ! 40: long hiadd; /* hi address this pass */ ! 41: short segSeq; /* Segment sequence no */ ! 42: ! 43: char *bp; /* data buffer pointer */ ! 44: RELOC *relBp; /* relocation buffer pointer */ ! 45: LINENO *lineBp; /* line number buffer pointer */ ! 46: char buf[DATABUF]; /* data buffer */ ! 47: RELOC relBuf[RELBUF]; /* relocation entry buffer */ ! 48: LINENO lineBuf[LINEBUF]; /* line number entry buffer */ ! 49: }; ! 50: ! 51: static long *tracker; /* for debugging */ ! 52: ! 53: static seg *segs, *segend; /* segment bases */ ! 54: static seg *cseg; /* current segment */ ! 55: ! 56: static unsigned short ct, pos, sects, symbs, usects; ! 57: static long datapos, relpos, linepos, sympos, debpos; ! 58: static long strOff = 4; ! 59: static long lastSeek; ! 60: static FILE *ofp; /* output file */ ! 61: ! 62: static int coffDefCt; /* count of .def in file */ ! 63: static int coffAuxCt; /* aux records to be written */ ! 64: static int coffEfcnCt; /* end of function records */ ! 65: static int txtAt; /* DEBUG_RECS from last pass */ ! 66: #define DEBUG_RECS (coffDefCt + coffAuxCt - coffEfcnCt) ! 67: #define USECTS (txtAt ? usects * 2 : usects) ! 68: static char defSw; /* in a .def statement */ ! 69: static char auxSw; ! 70: static char efcnSw; ! 71: ! 72: struct xsym { /* Symbol for debugging becomes SYMENT and maybe auxent */ ! 73: int symno; ! 74: int value; ! 75: short scnum; ! 76: short type; ! 77: char sclass; ! 78: char numaux; ! 79: AUXENT aux; /* aux record data */ ! 80: char *name; /* name if there is one */ ! 81: }; ! 82: ! 83: static struct xsym *syms; /* all the debug stuff */ ! 84: static struct xsym *symptr; /* currently build debug stuff */ ! 85: ! 86: union word { ! 87: unsigned char uc[2]; ! 88: unsigned short us; ! 89: }; ! 90: ! 91: union full { ! 92: unsigned char uc[4]; ! 93: unsigned long ul; ! 94: }; ! 95: ! 96: /* ! 97: * output spaces and tabs to a position, then output a character. ! 98: */ ! 99: static void ! 100: outTo(to, s) ! 101: { ! 102: int i; ! 103: ! 104: if(!pos) ! 105: sTitle(); ! 106: ! 107: for (to += (' ' == s); (i = ((pos | 7) + 1)) <= to; pos = i) ! 108: putchar('\t'); ! 109: ! 110: for (; pos < to; pos++) ! 111: putchar(' '); ! 112: ! 113: if (' ' != s) ! 114: putchar(s); ! 115: } ! 116: ! 117: /* ! 118: * Do titles. ! 119: */ ! 120: sTitle() ! 121: { ! 122: static short pageno; ! 123: ! 124: if(pswitch && (++linect > nlpp)) { ! 125: if(pageno) ! 126: printf("\n\n\n\n\n"); ! 127: printf( ! 128: "\n\nMark Williams 80386 Assembler\t%s\t%s\tPage %d\n\n", ! 129: dTime, title, ++pageno); ! 130: linect = 0; ! 131: } ! 132: } ! 133: ! 134: /* ! 135: * output source line ! 136: */ ! 137: outLine(p, s) ! 138: char *p, s; ! 139: { ! 140: register char c; ! 141: ! 142: if ((2 != pass) || ! 143: !lswitch || ! 144: (!mlistsw && (NULL != macExp)) || ! 145: (NULL == p)) ! 146: return; ! 147: ! 148: outTo(STARTP, s); ! 149: for (; (c = *p++) && ('\n' != c); pos++) { ! 150: if (lineSize <= pos) { ! 151: putchar('\n'); ! 152: pos = 0; ! 153: outTo(STARTP, '|'); ! 154: } ! 155: if ('\t' == c) ! 156: pos |= 7; ! 157: putchar(c); ! 158: } ! 159: putchar('\n'); ! 160: pos = ct = 0; ! 161: } ! 162: ! 163: /* ! 164: * Write to obj file. ! 165: */ ! 166: static void ! 167: owrite(buf, size) ! 168: char *buf; ! 169: { ! 170: if (1 != fwrite(buf, size, 1, ofp)) ! 171: fatal("Write error on object file"); /**/ ! 172: lastSeek += size; ! 173: } ! 174: ! 175: /* ! 176: * Seek then Write to obj file. ! 177: */ ! 178: xwrite(add, buf, size) ! 179: long add; ! 180: char *buf; ! 181: { ! 182: if (add != lastSeek) { ! 183: if (fseek(ofp, add, 0)) ! 184: fatal("Seek error on object file"); /**/ ! 185: lastSeek = add; ! 186: } ! 187: owrite(buf, size); ! 188: } ! 189: ! 190: /* ! 191: * Write actual data. ! 192: */ ! 193: outData(s) ! 194: register seg *s; ! 195: { ! 196: register size; ! 197: ! 198: if (size = s->bp - s->buf) { ! 199: if (s->s_flags != STYP_BSS) { ! 200: xwrite(s->data_seekad, s->buf, size); ! 201: s->data_seekad += size; ! 202: } ! 203: s->bp = s->buf; ! 204: } ! 205: } ! 206: ! 207: /* ! 208: * Write relocation records. ! 209: */ ! 210: outRel(s) ! 211: register seg *s; ! 212: { ! 213: register size; ! 214: ! 215: if (size = (char *)s->relBp - (char *)s->relBuf) { ! 216: xwrite(s->relo_seekad, (char *)s->relBuf, size); ! 217: s->relo_seekad += size; ! 218: } ! 219: s->relBp = s->relBuf; ! 220: } ! 221: ! 222: /* ! 223: * Write Line records. ! 224: */ ! 225: outLineRec(s) ! 226: register seg *s; ! 227: { ! 228: register size; ! 229: ! 230: if (size = (char *)s->lineBp - (char *)s->lineBuf) { ! 231: xwrite(s->line_seekad, (char *)s->lineBuf, size); ! 232: s->line_seekad += size; ! 233: } ! 234: s->lineBp = s->lineBuf; ! 235: } ! 236: ! 237: /* ! 238: * put object data byte to buffer. ! 239: */ ! 240: binout(b, s) ! 241: unsigned short b; ! 242: register seg *s; ! 243: { ! 244: if (s->bp == (s->buf + DATABUF)) ! 245: outData(s); ! 246: *s->bp++ = b; ! 247: } ! 248: ! 249: ! 250: /* ! 251: * Limit data on line. This allows cuts at logical points. ! 252: */ ! 253: static void ! 254: limiter(n) ! 255: { ! 256: if (lswitch && (ct + n) > LIMIT) { ! 257: putchar('\n'); ! 258: ct = 0; ! 259: } ! 260: } ! 261: ! 262: /* ! 263: * list data ! 264: */ ! 265: outlst(b) ! 266: unsigned short b; ! 267: { ! 268: if (dot.sg == 3) { /* BSS */ ! 269: static int statem = -1; /* only one err per line */ ! 270: ! 271: if (statement != statem) { ! 272: statem = statement; ! 273: ! 274: yyerror("Data defined in .bss"); ! 275: /* The \fB.bss\fR segment is uninitialized data. ! 276: * You cannot place actual values there. */ ! 277: } ! 278: } ! 279: binout(b, cseg); ! 280: ! 281: if (!lswitch) ! 282: return; ! 283: ! 284: if (!ct) { ! 285: sTitle(); ! 286: pos = 4; ! 287: printf("%04lX", dot.loc + segs[dot.sg - 1].s_vaddr); ! 288: } ! 289: ! 290: if (!(ct % CMOD)) { ! 291: pos++; ! 292: putchar(' '); ! 293: } ! 294: printf("%02X", b & 255); ! 295: pos += 2; ! 296: ct++; ! 297: } ! 298: ! 299: /* ! 300: * output unrelocated byte ! 301: */ ! 302: outab(b) ! 303: unsigned short b; ! 304: { ! 305: if (2 == pass) { ! 306: limiter(1); ! 307: outlst(b); ! 308: } ! 309: dot.loc++; /* update location ctr */ ! 310: } ! 311: ! 312: /* ! 313: * output unrelocated word. ! 314: */ ! 315: outaw(u) ! 316: unsigned short u; ! 317: { ! 318: if (2 == pass) { ! 319: union word w; ! 320: ! 321: w.us = u; ! 322: limiter(2); ! 323: outlst(w.uc[0]); ! 324: outlst(w.uc[1]); ! 325: } ! 326: dot.loc += 2; ! 327: } ! 328: ! 329: /* ! 330: * output unrelocated long. ! 331: */ ! 332: outal(ul) ! 333: long ul; ! 334: { ! 335: if (2 == pass) { ! 336: union full l; ! 337: ! 338: l.ul = ul; ! 339: limiter(4); ! 340: outlst(l.uc[0]); ! 341: outlst(l.uc[1]); ! 342: outlst(l.uc[2]); ! 343: outlst(l.uc[3]); ! 344: } ! 345: dot.loc += 4; ! 346: } ! 347: ! 348: /* ! 349: * output relocation. ! 350: */ ! 351: static long ! 352: relOut(oper, sw) ! 353: register expr *oper; ! 354: unsigned sw; ! 355: { ! 356: register RELOC *bp; ! 357: register sym *sp; ! 358: register long rv; ! 359: ! 360: rv = oper->exp; ! 361: if (NULL == (sp = oper->ref) || (sp->type & S_XSYM)) ! 362: return(rv); /* absolute addr */ ! 363: ! 364: bp = cseg->relBp++; ! 365: bp->r_type = sw; ! 366: bp->r_vaddr = dot.loc + cseg->s_vaddr; ! 367: ! 368: /* ! 369: * Only use symbol references when forced ! 370: * seems to be required by a bug in the ! 371: * ESIX linker. ! 372: */ ! 373: if (!(sp->flag & (S_EXREF|S_COMMON))) { ! 374: int seg = segs[sp->sg - 1].segSeq - 1; ! 375: ! 376: bp->r_symndx = txtAt ? (seg * 2) + txtAt : seg; ! 377: } ! 378: else { ! 379: bp->r_symndx = sp->num; ! 380: if (sp->flag & S_COMMON) ! 381: rv += sp->size; ! 382: rv -= sp->loc; ! 383: } ! 384: ! 385: if (bp == (cseg->relBuf + (RELBUF - 1))) ! 386: outRel(cseg); ! 387: ! 388: /* gimmic addr to make .data after .text */ ! 389: if ((sp->sg > 1) && !(sp->flag & S_COMMON)) ! 390: rv += segs[sp->sg - 1].s_vaddr; ! 391: ! 392: return(rv); ! 393: } ! 394: ! 395: /* ! 396: * output relocated byte ! 397: */ ! 398: outrb(oper, sw) ! 399: expr *oper; ! 400: int sw; /* 0 = Relative address, 1 = PC relative address */ ! 401: { ! 402: if (2 == pass) { ! 403: limiter(1); ! 404: if (sw) ! 405: outlst((unsigned short)(relOut(oper, R_PCRBYTE) - ! 406: (dot.loc + 1))); ! 407: else ! 408: outlst((unsigned short)relOut(oper, R_RELBYTE)); ! 409: } ! 410: else if (NULL != oper->ref) ! 411: cseg->s_nreloc++; ! 412: dot.loc++; ! 413: } ! 414: ! 415: /* ! 416: * output relocated word. ! 417: */ ! 418: outrw(oper, sw) ! 419: expr *oper; ! 420: int sw; /* 0 = Relative address, 1 = PC relative address */ ! 421: { ! 422: union word w; ! 423: ! 424: if (2 == pass) { ! 425: if (sw) ! 426: w.us = relOut(oper, R_PCRWORD) - (dot.loc + 2); ! 427: else ! 428: w.us = relOut(oper, R_DIR16); ! 429: ! 430: limiter(2); ! 431: outlst(w.uc[0]); ! 432: outlst(w.uc[1]); ! 433: } ! 434: else if (NULL != oper->ref) ! 435: cseg->s_nreloc++; ! 436: dot.loc += 2; ! 437: } ! 438: ! 439: /* ! 440: * output relocated long. ! 441: */ ! 442: outrl(oper, sw) ! 443: expr *oper; ! 444: int sw; /* 0 = Relative address, 1 = PC relative address */ ! 445: { ! 446: union full l; ! 447: ! 448: if (2 == pass) { ! 449: if (sw) ! 450: l.ul = relOut(oper, R_PCRLONG) - (dot.loc + 4); ! 451: else ! 452: l.ul = relOut(oper, R_DIR32); ! 453: ! 454: limiter(4); ! 455: outlst(l.uc[0]); ! 456: outlst(l.uc[1]); ! 457: outlst(l.uc[2]); ! 458: outlst(l.uc[3]); ! 459: } ! 460: else if (NULL != oper->ref) ! 461: cseg->s_nreloc++; ! 462: dot.loc += 4; ! 463: } ! 464: ! 465: /* ! 466: * Output symbol table string. ! 467: */ ! 468: outSymStr(sp) ! 469: register sym *sp; ! 470: { ! 471: register i; ! 472: register char *name; ! 473: ! 474: name = SYMNAME(sp); ! 475: if ((i = strlen(name)) > SYMNMLEN) ! 476: owrite(name, i + 1); ! 477: } ! 478: ! 479: static void showIt(sp) ! 480: sym *sp; ! 481: { ! 482: int i; ! 483: char *name; ! 484: ! 485: i = strlen(name = SYMNAME(sp)); ! 486: fprintf(stderr, "Trace %X, '%s' flag %d len %d num %d\n", ! 487: sp, name, sp->flag, i, sp->num); ! 488: } ! 489: ! 490: /* ! 491: * output symbol table entry. ! 492: */ ! 493: SYMENT * ! 494: outSym(sp) ! 495: register sym *sp; ! 496: { ! 497: static SYMENT s; ! 498: int i; ! 499: register char *name; ! 500: ! 501: clear(&s); ! 502: ! 503: i = strlen(name = SYMNAME(sp)); ! 504: ! 505: if (i > SYMNMLEN) { ! 506: s.n_zeroes = 0; ! 507: s.n_offset = strOff; ! 508: strOff += i + 1; ! 509: } ! 510: else ! 511: strncpy(s._n._n_name, name, SYMNMLEN); ! 512: ! 513: if (sp->sg < 0) ! 514: s.n_scnum = sp->sg; ! 515: else ! 516: s.n_scnum = segs[sp->sg - 1].segSeq; ! 517: s.n_value = sp->loc; ! 518: s.n_sclass = C_STAT; ! 519: ! 520: if (sp->flag & S_EXDEF) { ! 521: s.n_sclass = C_EXT; ! 522: if (sp->flag & S_COMMON) { /* common */ ! 523: s.n_value = (sp->size ? sp->size : 1); ! 524: s.n_scnum = 0; ! 525: } ! 526: } ! 527: if (sp->flag & S_EXREF) { ! 528: s.n_scnum = 0; ! 529: s.n_value = 0; ! 530: s.n_sclass = C_EXT; ! 531: } ! 532: ! 533: /* gimmic addr to make .data after .text */ ! 534: if (s.n_scnum > 1) ! 535: s.n_value += segs[sp->sg - 1].s_vaddr; ! 536: ! 537: owrite((char *)&s, sizeof(s)); ! 538: return (&s); ! 539: } ! 540: ! 541: /* ! 542: * Go from pass 0 to pass 1 or 2 ! 543: */ ! 544: newPass(fn) ! 545: char *fn; ! 546: { ! 547: register seg *s; ! 548: unsigned size; ! 549: long xaddr; ! 550: ! 551: if ((cseg->curadd = dot.loc) > cseg->hiadd) ! 552: cseg->hiadd = cseg->curadd; ! 553: cseg = segs; /* return to .text */ ! 554: defCt = macNo = dot.loc = 0; ! 555: if ((txtAt = DEBUG_RECS) && !pass) { ! 556: xpass = 1; /* force another pass */ ! 557: symptr = syms = alloc(coffDefCt * sizeof(*syms)); ! 558: } ! 559: longMode = pass = dot.sg = 1; ! 560: if (indPass()) { /* take an extra pass */ ! 561: usects = 0; ! 562: for (s = segs; s < segend; s++) { ! 563: if (s->hiadd || usects < MANSEG) ! 564: usects++; ! 565: s->segSeq = usects; ! 566: s->bp = s->buf; ! 567: s->relBp = s->relBuf; ! 568: s->lineBp = s->lineBuf; ! 569: s->s_nlnno = s->s_nreloc = s->hiadd = s->curadd = 0; ! 570: } ! 571: symGlob(txtAt + USECTS); /* fix symbol table */ ! 572: coffDefCt = coffAuxCt = coffEfcnCt = 0; ! 573: return; ! 574: } ! 575: ! 576: pass = 2; /* last pass */ ! 577: linect = nlpp; ! 578: usects = xaddr = datapos = relpos = linepos = 0; ! 579: ofp = xopen(fn, "wb"); ! 580: ! 581: for (s = segs; s < segend; s++) { ! 582: if (s->hiadd || usects < MANSEG) ! 583: usects++; ! 584: s->s_paddr = s->s_vaddr = xaddr; ! 585: s->hiadd += ROUNDR; /* Round up */ ! 586: s->hiadd &= ~ROUNDR; ! 587: xaddr += s->s_size = s->hiadd; ! 588: s->data_seekad = datapos; /* temp value */ ! 589: s->s_relptr = relpos; ! 590: s->s_lnnoptr = linepos; ! 591: if (s->s_flags != STYP_BSS) { ! 592: datapos += s->hiadd; ! 593: relpos += s->s_nreloc * RELSZ; ! 594: linepos += s->s_nlnno * LINESZ; ! 595: } ! 596: } ! 597: size = sizeof(FILEHDR) + (usects * sizeof(SCNHDR)); ! 598: debpos = size + datapos + relpos + linepos; ! 599: sympos = debpos + (txtAt * SYMESZ); ! 600: linepos = size + datapos + relpos; ! 601: relpos = size + datapos; ! 602: ! 603: if (fseek(ofp, lastSeek = sympos, 0)) ! 604: fatal("Seek error on object file"); /**/ ! 605: ! 606: usects = 0; ! 607: for (s = segs; s < segend; s++) { ! 608: SYMENT sym; ! 609: AUXENT aux; ! 610: ! 611: if (s->hiadd || usects < MANSEG) ! 612: usects++; ! 613: else ! 614: continue; ! 615: ! 616: /* write symbol records for segments */ ! 617: clear(&sym); ! 618: s->segSeq = usects; ! 619: sym.n_sclass = C_STAT; ! 620: sym.n_value = s->s_vaddr; ! 621: memcpy(sym._n._n_name, s->s_name, SYMNMLEN); ! 622: sym.n_scnum = usects; ! 623: sym.n_numaux = txtAt ? 1 : 0; ! 624: owrite((char *)&sym, sizeof(sym)); ! 625: ! 626: if (sym.n_numaux) { ! 627: aux.ae_scnlen = s->s_size; ! 628: aux.ae_nreloc = s->s_nreloc; ! 629: aux.ae_nlinno = s->s_nlnno; ! 630: owrite((char *)&aux, sizeof(aux)); ! 631: } ! 632: ! 633: if (s->hiadd && (s->s_flags != STYP_BSS)) ! 634: s->s_scnptr = s->data_seekad += size; ! 635: else ! 636: s->s_scnptr = s->data_seekad = 0; ! 637: ! 638: if (s->s_nreloc && (s->s_flags != STYP_BSS)) ! 639: s->relo_seekad = s->s_relptr += relpos; ! 640: else ! 641: s->relo_seekad = s->s_relptr = 0; ! 642: ! 643: if (s->s_nlnno && (s->s_flags != STYP_BSS)) ! 644: s->line_seekad = s->s_lnnoptr += linepos; ! 645: else ! 646: s->line_seekad = s->s_lnnoptr = 0; ! 647: s->hiadd = s->curadd = 0; ! 648: } ! 649: ! 650: sympos = ftell(ofp); /* continue the symbol table from here */ ! 651: ! 652: /* fix the symbol table setting numbers */ ! 653: symGlob(txtAt + USECTS); ! 654: coffDefCt = coffAuxCt = coffEfcnCt = 0; ! 655: } ! 656: ! 657: /* ! 658: * write record header then segment headers. ! 659: */ ! 660: static void ! 661: writeHeader() ! 662: { ! 663: register seg *s; ! 664: FILEHDR head; ! 665: int i; ! 666: long loadd; ! 667: ! 668: head.f_magic = C_386_MAGIC; ! 669: time(&head.f_timdat); ! 670: head.f_nsyms = symbs; ! 671: head.f_symptr = debpos; ! 672: head.f_opthdr = 0; ! 673: head.f_flags = 0; ! 674: head.f_nscns = usects; ! 675: ! 676: xwrite(0L, (char *)&head, sizeof(head)); ! 677: for (loadd = i = 0, s = segs; s < segend; s++) { ! 678: if (s->hiadd || i < MANSEG) { ! 679: i++; ! 680: owrite(s, sizeof(SCNHDR)); ! 681: } ! 682: } ! 683: } ! 684: ! 685: /* ! 686: * Finish any output. ! 687: */ ! 688: cleanUp() ! 689: { ! 690: int pad; ! 691: register seg *s; ! 692: ! 693: s = cseg; /* close out current seg */ ! 694: if(s->hiadd < (s->curadd = dot.loc)) ! 695: s->hiadd = s->curadd; ! 696: ! 697: if (coffDefCt) /* Write debug symbols */ ! 698: writeDebug(); ! 699: ! 700: fseek(ofp, sympos, 0); ! 701: ! 702: symDump(outSym, txtAt); /* write ordinary symbols */ ! 703: ! 704: symbs = (ftell(ofp) - debpos) / SYMESZ; /* figure sym ct from loc */ ! 705: ! 706: if (strOff > 4) { ! 707: owrite(&strOff, sizeof(strOff)); /* write length of tail */ ! 708: writeDebugLong(); /* dump symbols that are too long */ ! 709: symDump(outSymStr, txtAt); ! 710: } ! 711: ! 712: writeHeader(); /* now we know header data */ ! 713: ! 714: for (s = segs; s < segend; s++) { ! 715: if (s->s_flags == STYP_BSS) ! 716: continue; ! 717: ! 718: /* go to end of segment */ ! 719: if (s->curadd != s->hiadd) ! 720: doOrg(NULL, NULL); ! 721: ! 722: /* pad with nop or zero */ ! 723: pad = (s->s_flags == STYP_TEXT) ? NOP : 0; ! 724: for (; s->hiadd & ROUNDR; s->hiadd++) ! 725: binout(pad, s); ! 726: outData(s); ! 727: outRel(s); ! 728: outLineRec(s); ! 729: } ! 730: } ! 731: ! 732: /* ! 733: * org command ! 734: */ ! 735: doOrg(label, oper) ! 736: parm *label; ! 737: data *oper; ! 738: { ! 739: register seg *s; ! 740: long from, to; ! 741: char pad; ! 742: ! 743: buildlab(label); ! 744: ! 745: from = dot.loc; ! 746: s = cseg; ! 747: if (pass == 2) ! 748: outData(s); ! 749: s->curadd = dot.loc; /* first make segment current */ ! 750: if (dot.loc > s->hiadd) ! 751: s->hiadd = dot.loc; ! 752: ! 753: /* process org */ ! 754: switch ((NULL == oper) ? 'n' : oper->type) { ! 755: case 'n': ! 756: to = s->hiadd; /* org to hi spot in segment */ ! 757: break; ! 758: case 'd': ! 759: case 's': ! 760: yyerror("Org to invalid value"); ! 761: /* You may not \fB.org\fR to doubles or strings. */ ! 762: return (1); ! 763: case 'y': ! 764: if (oper->d.y->sg != dot.sg) { ! 765: yyerror("Org to wrong segment"); ! 766: /* You must \fB.org\fR to the current segment. */ ! 767: return (1); ! 768: } ! 769: to = oper->d.y->loc; ! 770: break; ! 771: case 'l': ! 772: to = oper->d.l; /* org where requested */ ! 773: } ! 774: ! 775: if ((pass != 2) || (s->s_flags == STYP_BSS)) { /* no disk work */ ! 776: s->curadd = dot.loc = to; /* make segment current again */ ! 777: if (to > s->hiadd) ! 778: s->hiadd = dot.loc; ! 779: return (0); ! 780: } ! 781: if (to <= s->hiadd) { /* no pad if we've been there */ ! 782: s->curadd = dot.loc = to; ! 783: s->data_seekad += to - from; ! 784: return (0); ! 785: } ! 786: from = s->curadd = dot.loc = s->hiadd; /* seek to the old end */ ! 787: s->data_seekad += s->hiadd - from; ! 788: ! 789: pad = (s->s_flags == STYP_TEXT) ? NOP : 0; /* pad out */ ! 790: for (;from < to; from++) ! 791: binout(pad, s); ! 792: s->curadd = dot.loc = to; /* make segment current again */ ! 793: if (to > s->hiadd) ! 794: s->hiadd = dot.loc; ! 795: return (0); ! 796: } ! 797: ! 798: /* ! 799: * Initialize segment information. ! 800: */ ! 801: segInit() ! 802: { ! 803: int i; ! 804: register seg *s; ! 805: ! 806: static char *segclass[] = { ! 807: ".text", ".data", ".bss" ! 808: }; ! 809: static long segflag[] = { ! 810: STYP_TEXT, STYP_DATA, STYP_BSS ! 811: }; ! 812: ! 813: cseg = segs = alloc(sizeof(*segs) * MANSEG); ! 814: segend = segs + MANSEG; ! 815: ! 816: for (i = 0, s = segs; s < segend; s++, i++) { ! 817: strncpy(s->s_name, segclass[i], SYMNMLEN); ! 818: s->s_flags = segflag[i]; ! 819: s->segSeq = ++sects; ! 820: s->bp = s->buf; ! 821: s->relBp = s->relBuf; ! 822: s->lineBp = s->lineBuf; ! 823: } ! 824: } ! 825: ! 826: /* ! 827: * .ident and .version set stuff in the comment section. ! 828: */ ! 829: cmnt(op, p) ! 830: opc *op; ! 831: parm *p; ! 832: { ! 833: } ! 834: ! 835: /* ! 836: * coff debugging statements. ! 837: */ ! 838: coffFile(s) ! 839: parm *s; ! 840: { ! 841: #ifdef NODEBUG ! 842: return; ! 843: #else ! 844: coffDefCt++; ! 845: coffAuxCt++; ! 846: if (2 == pass) { ! 847: symptr->sclass = C_FILE; ! 848: symptr->scnum = N_DEBUG; ! 849: symptr->numaux = 1; ! 850: if ('"' == s->str[0]) { ! 851: char *p; ! 852: ! 853: if (NULL != (p = strchr(s->str + 1, '"'))) ! 854: *p = 0; ! 855: strncpy(symptr->aux.ae_fname, s->str + 1, FILNMLEN); ! 856: } ! 857: else ! 858: strncpy(symptr->aux.ae_fname, s->str, FILNMLEN); ! 859: symptr->name = ".file"; ! 860: symptr++; ! 861: } ! 862: #endif ! 863: } ! 864: ! 865: coffDef(s) ! 866: parm *s; ! 867: { ! 868: #ifdef NODEBUG ! 869: return; ! 870: #else ! 871: if (pass) { /* initialize new symbol */ ! 872: if (defSw) ! 873: yywarn("missing .endef"); ! 874: symptr->scnum = N_ABS; ! 875: if (NULL != symptr->name) ! 876: free(symptr->name); ! 877: symptr->name = scpy(s->str, 0); ! 878: symptr->symno = DEBUG_RECS; ! 879: defSw = 1; ! 880: } ! 881: #endif ! 882: } ! 883: ! 884: coffEndef() ! 885: { ! 886: #ifdef NODEBUG ! 887: return; ! 888: #else ! 889: if ((1 == pass) && (symptr->scnum != N_DEBUG)) ! 890: symReNumber(symptr->name, DEBUG_RECS); ! 891: ! 892: if (2 == pass) { ! 893: register struct xsym *s; ! 894: ! 895: switch (symptr->sclass) { ! 896: case C_BLOCK: ! 897: if (strcmp(symptr->name, ".eb")) ! 898: break; ! 899: for (s = symptr - 1; s != syms; s--) ! 900: if (C_BLOCK == s->sclass && ! 901: !strcmp(s->name, ".bb") && ! 902: !s->aux.ae_endndx) { ! 903: s->aux.ae_endndx = DEBUG_RECS + 2; ! 904: break; ! 905: } ! 906: if (s == syms) ! 907: yywarn(".eb does not connect to .bb"); ! 908: /* A .eb statement does not connect to a ! 909: * .bb statement */ ! 910: break; ! 911: ! 912: case C_EFCN: /* end of function marker */ ! 913: for (s = symptr - 1; s != syms; s--) { ! 914: if (!strcmp(symptr->name, s->name)) { ! 915: short type; ! 916: ! 917: /* if this is a function at any level */ ! 918: for (type = s->type & ~N_BTMASK; ! 919: type && !ISFCN(type); ! 920: type >>= N_TSHIFT) ! 921: ; ! 922: ! 923: if (type) ! 924: break; ! 925: } ! 926: } ! 927: if (s == syms) ! 928: yywarn(".type -1 does not connect"); ! 929: /* A type of -1 C_EFCN does not connect to ! 930: * a .def of a function */ ! 931: else { ! 932: s->aux.ae_fsize = symptr->value - s->value; ! 933: s->aux.ae_endndx = DEBUG_RECS; ! 934: } ! 935: } ! 936: symptr->numaux = auxSw; ! 937: symptr++; ! 938: if (!defSw) ! 939: yywarn(".endef must follow .def"); /* */ ! 940: } ! 941: coffDefCt++; /* we need a spot to remember this */ ! 942: coffEfcnCt += efcnSw; /* C_EFCN don't write to table */ ! 943: if (!efcnSw) /* They don't have aux records */ ! 944: coffAuxCt += auxSw; ! 945: auxSw = defSw = efcnSw = 0; ! 946: #endif ! 947: } ! 948: ! 949: /* ! 950: * .type command ! 951: */ ! 952: coffType(n) ! 953: long n; ! 954: { ! 955: #ifdef NODEBUG ! 956: return; ! 957: #else ! 958: if (ISFCN(n)) { /* function build a line record */ ! 959: register LINENO *bp; ! 960: ! 961: auxSw = 1; ! 962: if (2 != pass) ! 963: cseg->s_nlnno++; ! 964: else { ! 965: bp = cseg->lineBp++; ! 966: bp->l_lnno = 0; ! 967: bp->l_addr.l_symndx = DEBUG_RECS; ! 968: ! 969: if (bp == (cseg->lineBuf + (LINEBUF - 1))) ! 970: outLineRec(cseg); ! 971: } ! 972: } ! 973: ! 974: if (2 == pass) { ! 975: if (!defSw) ! 976: yywarn(".type not in .endif"); ! 977: /* Debug command .type must be in .endif */ ! 978: symptr->type = n; ! 979: } ! 980: #endif ! 981: } ! 982: ! 983: coffVal(item) ! 984: data *item; ! 985: { ! 986: #ifdef NODEBUG ! 987: return; ! 988: #else ! 989: SYMENT *s; ! 990: ! 991: if (2 != pass) ! 992: return; ! 993: if (!defSw) ! 994: yywarn(".val must follow .def"); /* */ ! 995: ! 996: if ('y' == item->type) { ! 997: sym *sp = item->d.y; ! 998: ! 999: if (sp->flag & S_COMMON) { ! 1000: symReNumber(symptr->name, DEBUG_RECS); ! 1001: symptr->scnum = N_UNDEF; ! 1002: symptr->value = sp->size; ! 1003: } ! 1004: else { ! 1005: symptr->scnum = sp->sg; ! 1006: symptr->value = sp->loc; ! 1007: } ! 1008: } ! 1009: else ! 1010: symptr->value = item->d.l; ! 1011: #endif ! 1012: } ! 1013: ! 1014: coffScl(n) ! 1015: long n; ! 1016: { ! 1017: #ifdef NODEBUG ! 1018: return; ! 1019: #else ! 1020: if (C_EFCN == n) ! 1021: efcnSw = 1; ! 1022: if (!pass) ! 1023: return; ! 1024: if (!defSw) ! 1025: yywarn(".scl must follow .def"); /* */ ! 1026: if (ISTAG(n)) ! 1027: symptr->scnum = N_DEBUG; ! 1028: symptr->sclass = n; ! 1029: #endif ! 1030: } ! 1031: ! 1032: coffSize(n) ! 1033: long n; ! 1034: { ! 1035: #ifdef NODEBUG ! 1036: return; ! 1037: #else ! 1038: auxSw = 1; ! 1039: if (2 != pass) ! 1040: return; ! 1041: if (!defSw) ! 1042: yywarn(".size must follow .def"); /* */ ! 1043: symptr->aux.ae_size = n; ! 1044: #endif ! 1045: } ! 1046: ! 1047: coffDim(n, d) ! 1048: long n; ! 1049: int d; ! 1050: { ! 1051: #ifdef NODEBUG ! 1052: return; ! 1053: #else ! 1054: auxSw = 1; ! 1055: if (2 != pass) ! 1056: return; ! 1057: if (!defSw) { ! 1058: yywarn(".dim must follow .def"); /* */ ! 1059: return; ! 1060: } ! 1061: if (DIMNUM <= d) { ! 1062: yywarn(".dim statement too complex"); ! 1063: /* A .dim statement may contain no more than 4 dimensions. */ ! 1064: return; ! 1065: } ! 1066: symptr->aux.ae_dimen[d] = n; ! 1067: #endif ! 1068: } ! 1069: ! 1070: coffTag(p) ! 1071: parm *p; ! 1072: { ! 1073: #ifdef NODEBUG ! 1074: return; ! 1075: #else ! 1076: struct xsym *s; ! 1077: ! 1078: auxSw = 1; ! 1079: if (2 != pass) ! 1080: return; ! 1081: for (s = symptr - 1; s != syms; s--) { ! 1082: if (ISTAG(s->sclass) && !strcmp(p->str, s->name)) { ! 1083: if (C_EOS == symptr->sclass) ! 1084: s->aux.ae_endndx = symptr->symno + 2; ! 1085: symptr->aux.ae_tagndx = s->symno; ! 1086: break; ! 1087: } ! 1088: } ! 1089: if (s == syms) ! 1090: yywarn(".tag does not connect"); ! 1091: /* This tag fails to connect to an earlier unconnected .def ! 1092: * of the same name and a proper n_sclass. ! 1093: */ ! 1094: #endif ! 1095: } ! 1096: ! 1097: coffLn(n) ! 1098: long n; ! 1099: { ! 1100: #ifdef NODEBUG ! 1101: return; ! 1102: #else ! 1103: register LINENO *bp; ! 1104: ! 1105: if (2 != pass) ! 1106: cseg->s_nlnno++; ! 1107: else { ! 1108: bp = cseg->lineBp++; ! 1109: bp->l_lnno = n; ! 1110: bp->l_addr.l_paddr = dot.loc; ! 1111: ! 1112: if (bp == (cseg->lineBuf + (LINEBUF - 1))) ! 1113: outLineRec(cseg); ! 1114: } ! 1115: #endif ! 1116: } ! 1117: ! 1118: coffLine(n) ! 1119: long n; ! 1120: { ! 1121: #ifdef NODEBUG ! 1122: return; ! 1123: #else ! 1124: auxSw = 1; ! 1125: if (2 != pass) ! 1126: return; ! 1127: if (!defSw) ! 1128: yywarn(".line must follow .def"); /* */ ! 1129: symptr->aux.ae_lnno = n; ! 1130: #endif ! 1131: } ! 1132: ! 1133: /* ! 1134: * Write debug records. ! 1135: */ ! 1136: writeDebug() ! 1137: { ! 1138: register struct xsym *s, *ends; ! 1139: int ct = 0, act = 0; ! 1140: ! 1141: fseek(ofp, lastSeek = debpos, 0); ! 1142: for (ends = (s = syms) + coffDefCt; s != ends; s++) { ! 1143: int i; ! 1144: SYMENT sym; ! 1145: ! 1146: if (C_EFCN == s->sclass) ! 1147: continue; ! 1148: ! 1149: sym.n_sclass = s->sclass; ! 1150: sym.n_value = s->value; ! 1151: sym.n_scnum = s->scnum; ! 1152: sym.n_type = s->type; ! 1153: sym.n_numaux = s->numaux; ! 1154: ! 1155: if ((i = strlen(s->name)) > SYMNMLEN) { ! 1156: sym.n_offset = strOff; ! 1157: sym.n_zeroes = 0; ! 1158: strOff += i + 1; ! 1159: } ! 1160: else ! 1161: strncpy(sym.n_name, s->name, SYMNMLEN); ! 1162: ! 1163: ct++; ! 1164: owrite(&sym, SYMESZ); ! 1165: if (sym.n_numaux) { ! 1166: act++; ! 1167: owrite(&(s->aux), AUXESZ); ! 1168: } ! 1169: } ! 1170: ! 1171: } ! 1172: ! 1173: writeDebugLong() ! 1174: { ! 1175: register struct xsym *s, *ends; ! 1176: ! 1177: for (ends = (s = syms) + coffDefCt; s != ends; s++) { ! 1178: int i; ! 1179: ! 1180: if (C_EFCN == s->sclass) ! 1181: continue; ! 1182: ! 1183: if ((i = strlen(s->name)) > SYMNMLEN) ! 1184: owrite(s->name, i + 1); ! 1185: } ! 1186: } ! 1187: ! 1188: /* ! 1189: * .comm and .lcomm commands. ! 1190: * Improve later. ! 1191: */ ! 1192: comm(op, p, n) ! 1193: opc *op; ! 1194: parm *p; ! 1195: long n; ! 1196: { ! 1197: if (NULL == p) { ! 1198: yyerror(".comm must have tag"); ! 1199: /* The format of \fB.comm\fR is \fB.comm name, size\fR. */ ! 1200: return; ! 1201: } ! 1202: if (op->code == 2) { ! 1203: sym *s; ! 1204: ! 1205: s = symLookUp(p->str, S_LOCAL, 0L, op->code + 1); ! 1206: s->size = n; ! 1207: s->flag = S_EXDEF|S_COMMON; ! 1208: } ! 1209: } ! 1210: ! 1211: /* ! 1212: * segment command. ! 1213: */ ! 1214: void ! 1215: segment(op, p, n) ! 1216: opc *op; ! 1217: parm *p; ! 1218: long n; ! 1219: { ! 1220: register seg *s; ! 1221: sym *rv; ! 1222: static int previous = 0; ! 1223: int thisSg; ! 1224: ! 1225: /* Implement one level segment stack */ ! 1226: if (10000 != op->code) { ! 1227: thisSg = op->code; ! 1228: previous = dot.sg - 1; /* save where we were */ ! 1229: } ! 1230: else /* .previous pops the stack */ ! 1231: thisSg = previous; ! 1232: ! 1233: s = segs + thisSg; ! 1234: ! 1235: if (NULL == p) { /* segment change */ ! 1236: if ((cseg->curadd = dot.loc) > cseg->hiadd) ! 1237: cseg->hiadd = cseg->curadd; ! 1238: ! 1239: cseg = s; ! 1240: dot.loc = s->curadd; ! 1241: dot.sg = thisSg + 1; ! 1242: return; ! 1243: } ! 1244: ! 1245: /* set up data */ ! 1246: rv = symLookUp(p->str, S_LOCAL, s->curadd, thisSg + 1); ! 1247: rv->size = n; ! 1248: s->curadd += n; ! 1249: if (s->curadd > s->hiadd) ! 1250: s->hiadd = s->curadd; ! 1251: return; ! 1252: } ! 1253: ! 1254: /* ! 1255: * Switch to a section by name. ! 1256: * add it if required. ! 1257: */ ! 1258: void ! 1259: section(name) ! 1260: char *name; ! 1261: { ! 1262: int motion, i; ! 1263: char *oldsegs; ! 1264: register seg *s; ! 1265: static opc segOp = { 0, S_SEGMENT }; ! 1266: ! 1267: /* These are common segment names with their flags */ ! 1268: static char *segclass[] = { ! 1269: ".init", ".fini", ".rodata", ! 1270: ".comment", ".ctors", ".dtors" ! 1271: }; ! 1272: static long segflag[] = { ! 1273: STYP_TEXT, STYP_DATA, STYP_DATA, ! 1274: STYP_INFO, STYP_DATA, STYP_DATA ! 1275: }; ! 1276: ! 1277: /* Look for section in segment list */ ! 1278: for (segOp.code = 0; segOp.code < sects; segOp.code++) { ! 1279: if (!strncmp(name, segs[segOp.code].s_name, 8)) { ! 1280: segment(&segOp, NULL, 0L); ! 1281: return; ! 1282: } ! 1283: } ! 1284: ! 1285: /* realloc segment list with room for one more */ ! 1286: oldsegs = (char *)segs; ! 1287: if (NULL == (segs = realloc(segs, sizeof(*segs) * ++sects))) ! 1288: fatal("Out of memory"); /**/ ! 1289: ! 1290: /* adjust pointers to segment list */ ! 1291: motion = (char *)segs - oldsegs; ! 1292: #define adjust(ptr) ptr = (char *)(((char *)(ptr)) + motion) ! 1293: adjust(cseg); ! 1294: adjust(segend); ! 1295: for (s = segs; s < segend; s++) { ! 1296: adjust(s->bp); ! 1297: adjust(s->relBp); ! 1298: adjust(s->lineBp); ! 1299: } ! 1300: #undef adjust ! 1301: segend++; ! 1302: ! 1303: /* build new entry on segment list */ ! 1304: memset(s, '\0', sizeof(*s)); ! 1305: strncpy(s->s_name, name, SYMNMLEN); ! 1306: ! 1307: s->s_flags = STYP_TEXT; /* set default */ ! 1308: for (i = 0; i < 6; i++) { /* look at common names */ ! 1309: if (!strcmp(name, segclass[i])) { ! 1310: s->s_flags = segflag[i]; ! 1311: break; ! 1312: } ! 1313: } ! 1314: ! 1315: s->segSeq = sects - 1; ! 1316: s->bp = s->buf; ! 1317: s->relBp = s->relBuf; ! 1318: s->lineBp = s->lineBuf; ! 1319: ! 1320: segment(&segOp, NULL, 0L); /* switch to the new entry */ ! 1321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.