|
|
1.1 ! root 1: /* ! 2: * n2/i386/outcoff.c ! 3: * C compiler COFF output writer. ! 4: * The first pass writes to a temp file. ! 5: * After the first pass, the compiler knows the sizes of the internal segments. ! 6: * The compiler then maps the internal segments to the actual output segments. ! 7: * The second pass reads the temp file and writes the actual output bits. ! 8: * i386. ! 9: */ ! 10: ! 11: #include <stdio.h> ! 12: #include <time.h> ! 13: #include <string.h> ! 14: #include <coff.h> ! 15: #include "cc2.h" ! 16: ! 17: #define CC_ID "COHERENT i386 cc " /* .comment contains CC_ID VERSMWC */ ! 18: ! 19: #define NTXT 256 /* Text buffer size */ ! 20: #define NREL 256 /* Relocation buffer size */ ! 21: ! 22: #define RUP(n) (((n)+3)&(~3)) /* Round n up to dword boundary */ ! 23: ! 24: /* SYM flag tests. */ ! 25: #define is_bss(sp) ((sp)->s_seg==SBSS) ! 26: #define is_def(sp) (((sp)->s_flag&S_DEF)!=0) ! 27: #define is_global(sp) (((sp)->s_flag&S_GBL)!=0) ! 28: #define is_label(sp) (((sp)->s_flag&S_LABNO)!=0) ! 29: ! 30: /* Debugging output. */ ! 31: #if DEBUG ! 32: #define dbprintf(args) printf args ! 33: #else ! 34: #define dbprintf(args) ! 35: #endif ! 36: ! 37: /* ! 38: * COFF output. ! 39: * .text is section 1, .data is section 2, .bss is section 3. ! 40: * Section 4 is .comment, containing a translator ID and version number; ! 41: * this currently gets written only if debug. ! 42: * The structure of the COFF output file is presently as follows: ! 43: * file header ! 44: * [optional header: absent] ! 45: * section headers 1 through 3 [4 if debug] ! 46: * data for sections 1 through 3 [4 if debug] ! 47: * relocs for sections 1 through 3 ! 48: * line numbers for section 1 [absent if not debug] ! 49: * symbol table [seg names, then symbols] ! 50: * string table [absent if no long names] ! 51: */ ! 52: ! 53: /* ! 54: * The definitions below are indices for the header definitions in scn_hdr[]. ! 55: * If not debug, they are also the symbol indices for .text, .data, .bss. ! 56: * Add 1 to covert to COFF section number. ! 57: */ ! 58: #define C_TEXT_SEG 0 /* .text section index */ ! 59: #define C_DATA_SEG 1 /* .data section index */ ! 60: #define C_BSS_SEG 2 /* .bss section index */ ! 61: #define C_CMT_SEG 3 /* .comment section index */ ! 62: #define C_NSECS 4 /* Number of sections */ ! 63: ! 64: /* Symbol indices for .text, .data and .bss if debug. */ ! 65: /* Symbol 0 is .file with 1 aux entry, each section also has 1 aux entry. */ ! 66: #define C_TEXT_DB 2 ! 67: #define C_DATA_DB 4 ! 68: #define C_BSS_DB 6 ! 69: ! 70: /* ! 71: * Debug information. ! 72: * Each DBSYM represents one symbol entry or aux entry ! 73: * in the object symbol table. ! 74: * The DBSYM contains the proto entry itself, plus ! 75: * enough additional information for the second pass to correct the ! 76: * actual entry by adjusting long names and adding segment bases. ! 77: */ ! 78: typedef struct dbsym { ! 79: struct dbsym *db_next; /* Link, must be first */ ! 80: int db_ref; /* Index number */ ! 81: union { ! 82: SYMENT db_use; /* Symbol entry */ ! 83: AUXENT db_uae; /* Aux entry */ ! 84: } db_u; ! 85: unsigned short db_level; /* Lexical level */ ! 86: char db_seg; /* C segment */ ! 87: char db_flags; /* Flags */ ! 88: char db_name[]; /* NUL or name if > 8 */ ! 89: } DBSYM; ! 90: #define db_se db_u.db_use ! 91: #define db_ae db_u.db_uae ! 92: #define DB_AUX 0x01 /* AUXENT, not SYMENT */ ! 93: #define DB_LNAME 0x02 /* Name is in db_name */ ! 94: #define is_aux(dp) (((dp)->db_flags & DB_AUX) != 0) ! 95: #define is_lname(dp) (((dp)->db_flags & DB_LNAME) != 0) ! 96: ! 97: /* The output writer generates a LNNUM for each line number entry. */ ! 98: typedef struct lnnum { ! 99: struct lnnum *ln_next; /* Link */ ! 100: DBSYM *ln_dp; /* Symbol needing value */ ! 101: AUXENT *ln_ap; /* Function aux entry */ ! 102: unsigned short ln_lnnum; /* Line number, 0 for fn */ ! 103: unsigned short ln_val; /* Refnum or fn syminx */ ! 104: ADDRESS ln_addr; /* Address */ ! 105: char ln_flag; /* LN_FUNC or LN_LINE */ ! 106: } LNNUM; ! 107: #define LN_FUNC 0 ! 108: #define LN_LINE 1 ! 109: ! 110: /* Linked list of symbols, used for .bb and tag lists. */ ! 111: typedef struct symlist { ! 112: struct symlist *sl_next; /* Link */ ! 113: DBSYM *sl_dp; /* Symbol pointer */ ! 114: } SYMLIST; ! 115: ! 116: /* Tag patch list for forward tag references. */ ! 117: typedef struct tagfix { ! 118: struct tagfix *tf_next; /* Link */ ! 119: SYMLIST *tf_sp; /* DBSYMs to fix */ ! 120: char tf_name[]; /* Name */ ! 121: } TAGFIX; ! 122: ! 123: extern DBSYM *new_db(); ! 124: extern DBSYM *new_sym(); ! 125: extern AUXENT *new_aux(); ! 126: extern LNNUM *new_ln(); ! 127: ! 128: /* ! 129: * Scratch file. ! 130: */ ! 131: #define TTYPE 0x07 /* Type mask */ ! 132: #define TPCR 0x08 /* PC rel flag, or'ed in */ ! 133: #define TSYM 0x10 /* Symbol based flag, or'ed in */ ! 134: ! 135: #define TEND 0x00 /* End marker */ ! 136: #define TENTER 0x01 /* Enter new segment */ ! 137: #define TBYTE 0x02 /* Byte data */ ! 138: #define TWORD 0x03 /* Word data */ ! 139: #define TLONG 0x04 /* Dword data */ ! 140: ! 141: /* ! 142: * Output writer globals. ! 143: */ ! 144: SYMLIST *blockp; /* Open .bb block list */ ! 145: FILEHDR coff_hdr; /* Header buffer */ ! 146: DBSYM *db_list; /* Debug symbol list */ ! 147: DBSYM **db_lastp = &db_list; /* Last db_list pointer */ ! 148: int dot_sec; /* Current COFF section */ ! 149: DBSYM *fn_dp; /* Current fn entry */ ! 150: int level; /* Lexical level */ ! 151: LNNUM *ln_list; /* Line number list */ ! 152: LNNUM **ln_lastp = &ln_list; /* Last ln_list pointer */ ! 153: int refnum = -1; /* Debug item refnum */ ! 154: char rel[NREL]; /* Relocation buffer */ ! 155: ADDRESS reldot[C_NSECS]; /* Relocation offsets */ ! 156: char *relp; /* Relocation pointer */ ! 157: SCNHDR scn_hdr[C_NSECS] = { /* Section headers */ ! 158: { _TEXT, 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_TEXT }, ! 159: { _DATA, 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_DATA }, ! 160: { _BSS, 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_BSS }, ! 161: { _COMMENT, 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_INFO } ! 162: }; ! 163: long str_seek; /* Seek to string table */ ! 164: long str_size; /* Size of string table */ ! 165: char symindex[C_NSECS]; /* Section symbol indices */ ! 166: SYMLIST *tag_list; /* Defined tags */ ! 167: TAGFIX *tag_fix; /* Forward tag refs */ ! 168: char txt[NTXT]; /* Text buffer */ ! 169: ADDRESS txtdot; /* Text offset */ ! 170: char *txtp; /* Text pointer */ ! 171: ! 172: /* ! 173: * Map C compiler internal segment into a COFF output section. ! 174: * The SSTRN entry gets patched by outinit() if not -VPSTR. ! 175: */ ! 176: char sec_index[] = { ! 177: C_TEXT_SEG, /* SCODE */ ! 178: C_TEXT_SEG, /* SLINK */ ! 179: C_TEXT_SEG, /* SPURE */ ! 180: C_TEXT_SEG, /* possibly patched */ /* SSTRN */ ! 181: C_DATA_SEG, /* SDATA */ ! 182: C_BSS_SEG /* SBSS */ ! 183: }; ! 184: ! 185: /* ! 186: * Map C debug scalar types to COFF types. ! 187: * Indexed by type as defined in h/ops.h. ! 188: * COFF has no direct representation for "void" type, ! 189: * it uses <DT_FCN T_NULL> for a void function. ! 190: */ ! 191: char coff_type[] = { ! 192: T_NULL, /* DT_NONE */ ! 193: T_CHAR, /* DT_CHAR */ ! 194: T_UCHAR, /* DT_UCHAR */ ! 195: T_SHORT, /* DT_SHORT */ ! 196: T_USHORT, /* DT_USHORT */ ! 197: T_INT, /* DT_INT */ ! 198: T_UINT, /* DT_UINT */ ! 199: T_LONG, /* DT_LONG */ ! 200: T_ULONG, /* DT_ULONG */ ! 201: T_FLOAT, /* DT_FLOAT */ ! 202: T_DOUBLE, /* DT_DOUBLE */ ! 203: T_NULL, /* DT_VOID */ ! 204: T_STRUCT, /* DT_STRUCT */ ! 205: T_UNION, /* DT_UNION */ ! 206: T_ENUM, /* DT_ENUM */ ! 207: DT_PTR, /* DD_PTR */ ! 208: DT_FCN, /* DD_FUNC */ ! 209: DT_ARY /* DD_ARRAY */ ! 210: }; ! 211: ! 212: /* ! 213: * Map C debug storage class to COFF storage class. ! 214: * Indexed by class-DC_SEX, as defined in h/ops.h. ! 215: * DC_CALL is defined in ops.h but not used anywhere. ! 216: * DC_LINE items generate COFF line number items, ! 217: * they have no COFF storage class. ! 218: */ ! 219: char coff_class[] = { ! 220: C_STAT, /* DC_SEX */ ! 221: C_EXT, /* DC_GDEF */ ! 222: C_EXT, /* DC_GREF */ ! 223: C_TPDEF, /* DC_TYPE */ ! 224: C_STRTAG, /* DC_STAG */ ! 225: C_UNTAG, /* DC_UTAG */ ! 226: C_ENTAG, /* DC_ETAG */ ! 227: C_FILE, /* DC_FILE */ ! 228: C_NULL, /* DC_LINE */ ! 229: C_LABEL, /* DC_LAB */ ! 230: C_AUTO, /* DC_AUTO */ ! 231: C_ARG, /* DC_PAUTO */ ! 232: C_REG, /* DC_REG */ ! 233: C_REGPARM, /* DC_PREG */ ! 234: C_STAT, /* DC_SIN */ ! 235: C_MOE, /* DC_MOE */ ! 236: C_NULL, /* unused */ /* DC_CALL */ ! 237: C_MOS, /* DC_MOS */ ! 238: C_MOU /* DC_MOU */ ! 239: }; ! 240: ! 241: /* ! 242: * Map C debug storage class to COFF section number. ! 243: * Indexed by class-DC_SEX, as defined in h/ops.h. ! 244: * DC_CALL is defined in ops.h but not used anywhere. ! 245: * DC_LINE items generate COFF line number items, they have no COFF section. ! 246: */ ! 247: #define N_ANY 127 /* maps to .code, .text or .data using sec_index[] */ ! 248: char coff_sec[] = { ! 249: N_ANY, /* DC_SEX */ ! 250: N_ANY, /* DC_GDEF */ ! 251: N_UNDEF, /* DC_GREF */ ! 252: N_DEBUG, /* DC_TYPE */ ! 253: N_DEBUG, /* DC_STAG */ ! 254: N_DEBUG, /* DC_UTAG */ ! 255: N_DEBUG, /* DC_ETAG */ ! 256: N_DEBUG, /* DC_FILE */ ! 257: N_DEBUG, /* DC_LINE */ ! 258: N_ANY, /* DC_LAB */ ! 259: N_ABS, /* DC_AUTO */ ! 260: N_ABS, /* DC_PAUTO */ ! 261: N_ABS, /* DC_REG */ ! 262: N_ABS, /* DC_PREG */ ! 263: N_ANY, /* DC_SIN */ ! 264: N_ABS, /* DC_MOE */ ! 265: N_ANY, /* unused */ /* DC_CALL */ ! 266: N_ABS, /* DC_MOS */ ! 267: N_ABS /* DC_MOU */ ! 268: }; ! 269: ! 270: /* First pass routines. */ ! 271: /* ! 272: * Initialize the code writer. ! 273: */ ! 274: outinit() ! 275: { ! 276: #if MONOLITHIC ! 277: /* Reinitialize the coff_hdr. */ ! 278: memset(&coff_hdr, 0, sizeof coff_hdr); ! 279: dot_sec = 0; ! 280: memset(reldot, 0, sizeof reldot); ! 281: memset(scn_hdr, 0, sizeof scn_hdr); ! 282: strcpy(scn_hdr[C_TEXT_SEG].s_name, _TEXT); ! 283: scn_hdr[C_TEXT_SEG].s_flags = STYP_TEXT; ! 284: strcpy(scn_hdr[C_DATA_SEG].s_name, _DATA); ! 285: scn_hdr[C_DATA_SEG].s_flags = STYP_DATA; ! 286: strcpy(scn_hdr[C_BSS_SEG].s_name, _BSS); ! 287: scn_hdr[C_BSS_SEG].s_flags = STYP_BSS; ! 288: strcpy(scn_hdr[C_CMT_SEG].s_name, _COMMENT); ! 289: scn_hdr[C_CMT_SEG].s_flags = STYP_INFO; ! 290: ! 291: /* Reinitialize other globals. */ ! 292: level = 0; ! 293: db_lastp = &db_list; ! 294: ln_lastp = &ln_list; ! 295: refnum = -1; ! 296: tag_fix = tag_list = NULL; ! 297: #endif ! 298: if (notvariant(VPSTR)) ! 299: sec_index[SSTRN] = C_DATA_SEG; ! 300: } ! 301: ! 302: /* ! 303: * Output an absolute byte. ! 304: */ ! 305: outab(b) int b; ! 306: { ! 307: bput(TBYTE); ! 308: bput(b); ! 309: ++dot; ! 310: } ! 311: ! 312: /* ! 313: * Output an absolute word. ! 314: */ ! 315: outaw(w) int w; ! 316: { ! 317: bput(TWORD); ! 318: iput((ival_t)w); ! 319: dot += 2; ! 320: } ! 321: ! 322: /* ! 323: * Output an absolute dword. ! 324: */ ! 325: outal(i) ival_t i; ! 326: { ! 327: bput(TLONG); ! 328: iput(i); ! 329: dot += 4; ! 330: } ! 331: ! 332: /* ! 333: * Output a full byte. ! 334: */ ! 335: outxb(sp, b, pcrf) register SYM *sp; ADDRESS b; int pcrf; ! 336: { ! 337: register int opcode; ! 338: ! 339: opcode = TBYTE; ! 340: if (sp != NULL) { ! 341: opcode |= TSYM; ! 342: scn_hdr[dot_sec].s_nreloc++; ! 343: } ! 344: if (pcrf) ! 345: opcode |= TPCR; ! 346: bput(opcode); ! 347: bput(b); ! 348: if (sp != NULL) ! 349: pput(sp); ! 350: ++dot; ! 351: } ! 352: ! 353: /* ! 354: * Output a full word. ! 355: */ ! 356: outxw(sp, w, pcrf) register SYM *sp; ADDRESS w; int pcrf; ! 357: { ! 358: register int opcode; ! 359: ! 360: opcode = TWORD; ! 361: if (sp != NULL) { ! 362: opcode |= TSYM; ! 363: scn_hdr[dot_sec].s_nreloc++; ! 364: } ! 365: if (pcrf) ! 366: opcode |= TPCR; ! 367: bput(opcode); ! 368: iput((ival_t)w); ! 369: if (sp != NULL) ! 370: pput(sp); ! 371: dot += 2; ! 372: } ! 373: ! 374: /* ! 375: * Output a full dword. ! 376: */ ! 377: outxl(sp, i, pcrf) register SYM *sp; ADDRESS i; int pcrf; ! 378: { ! 379: register int opcode; ! 380: ! 381: opcode = TLONG; ! 382: if (sp != NULL) { ! 383: opcode |= TSYM; ! 384: scn_hdr[dot_sec].s_nreloc++; ! 385: } ! 386: if (pcrf) ! 387: opcode |= TPCR; ! 388: bput(opcode); ! 389: iput(i); ! 390: if (sp != NULL) ! 391: pput(sp); ! 392: dot += 4; ! 393: } ! 394: ! 395: /* ! 396: * Output a segment switch. ! 397: */ ! 398: outseg(s) register int s; ! 399: { ! 400: bput(TENTER); ! 401: bput(s); ! 402: dot_sec = sec_index[s]; ! 403: } ! 404: ! 405: /* ! 406: * Output n zero bytes. ! 407: * If flag is true, generate NOPs instead. ! 408: */ ! 409: outnzb(n, flag) register sizeof_t n; int flag; ! 410: { ! 411: register int i, val; ! 412: ! 413: val = (flag) ? 0x90 : 0; /* xchg %eax, %eax or 0 */ ! 414: for (i = 1; i <= n; ++i) { ! 415: bput(TBYTE); ! 416: bput(val); ! 417: } ! 418: dot += n; ! 419: } ! 420: ! 421: /* ! 422: * Process a dlabel record. ! 423: * Do the work on pass 1 so that the number of symbols in the table is known. ! 424: * 'i' is the level of indentation, 'class' is the initial storage class. ! 425: * A lot of grunge. ! 426: */ ! 427: outdlab(i, class) int i; register int class; ! 428: { ! 429: register int line, type, n; ! 430: int csec, ctype, cclass, tagn; ! 431: ival_t size, value, cvalue, array_size, last_size, sue_size; ! 432: int seg, width, derived, dims, suppress; ! 433: static int enumtype = DT_INT; ! 434: unsigned short dim[DIMNUM]; ! 435: SYM *sp; ! 436: DBSYM *dp, *tagdp; ! 437: AUXENT *ap, *endap, *arrayap; ! 438: ! 439: ++refnum; /* compiler db refnum */ ! 440: ! 441: /* Initialize locals. */ ! 442: seg = -1; ! 443: suppress = tagn = ctype = derived = dims = 0; ! 444: last_size = array_size = sue_size = (ival_t)0; ! 445: ap = endap = arrayap = tagdp = sp = NULL; ! 446: ! 447: /* ! 448: * Map C segment and storage class to COFF section and storage class. ! 449: * The COFF info may get adjusted later. ! 450: */ ! 451: if (class >= DC_SEX && class <= DC_MOU) { ! 452: csec = coff_sec[class - DC_SEX]; ! 453: cclass = coff_class[class - DC_SEX]; ! 454: if (cclass == C_NULL && class != DC_LINE) ! 455: cbotch("unrecognized class=%d", class); ! 456: } else ! 457: cbotch("unrecognized class=%d", class); ! 458: dbprintf(("outdlab(%d, %d)\t", i, class)); ! 459: dbprintf(("#%d\t", refnum)); ! 460: dbprintf(("cclass=%d\t", cclass)); ! 461: ! 462: /* Get line number. */ ! 463: line = iget(); ! 464: dbprintf(("line=%d\t", line)); ! 465: ! 466: /* Get value. */ ! 467: if (class < DC_AUTO) ! 468: value = 0; /* Name string only */ ! 469: else if (class < DC_MOS) ! 470: value = iget(); /* Value */ ! 471: else { /* DC_MOS or DC_MOU */ ! 472: width = bget(); /* Width */ ! 473: n = bget(); /* Offset */ ! 474: value = iget(); /* Value */ ! 475: if (width != 0) { ! 476: value = value * 8 + n; /* bitfield offset */ ! 477: cclass = C_FIELD; /* and class */ ! 478: } ! 479: } ! 480: cvalue = value; /* COFF value, may be modified below */ ! 481: if (class == DC_REG || class == DC_PREG) { ! 482: /* Map compiler register to machine register number. */ ! 483: switch(value) { ! 484: case EBX: cvalue = MEBX; break; ! 485: case EDI: cvalue = MEDI; break; ! 486: case ESI: cvalue = MESI; break; ! 487: default: cbotch("unexpected register %d", value); ! 488: } ! 489: } ! 490: ! 491: /* Get name. */ ! 492: sget(id, NCSYMB); ! 493: dbprintf(("id=%s\t", id)); ! 494: ! 495: if (class == DC_SEX || class == DC_GDEF || class == DC_GREF) { ! 496: ! 497: /* Check for global symbol table entry. */ ! 498: sp = glookup(id, 0); ! 499: if (sp == NULL) ! 500: cbotch("global %s not found", id); ! 501: seg = sp->s_seg; ! 502: /* Grab section and value; cvalue gets patched later for commons. */ ! 503: if (is_def(sp)) { ! 504: csec = sec_index[seg] + 1; ! 505: value = cvalue = sp->s_value; ! 506: } else { ! 507: /* ! 508: * Extern: seg != SANY changed to seg -1; ! 509: * common: seg SANY. ! 510: */ ! 511: csec = N_UNDEF; ! 512: if (seg != SANY) ! 513: seg = -1; ! 514: } ! 515: /* Suppress redefinitions of globals. */ ! 516: for (dp = db_list; dp != NULL; dp = dp->db_next) { ! 517: if (!is_aux(dp) ! 518: && dp->db_level == 0 ! 519: && db_strcmp(dp, id) == 0) { ! 520: ++suppress; ! 521: #if 0 ! 522: if (is_def(sp)) { ! 523: /* Symbol may be defined since previous ref. */ ! 524: dp->db_se.n_value = cvalue; ! 525: dp->db_se.n_scnum = csec; ! 526: } ! 527: #endif ! 528: break; ! 529: } ! 530: } ! 531: } else if (class == DC_SIN) { ! 532: /* Find location of static internal items. */ ! 533: sp = llookup(value, 0); ! 534: if (sp == NULL) ! 535: cbotch("local %d not found", value); ! 536: seg = sp->s_seg; ! 537: csec = sec_index[seg] + 1; ! 538: value = cvalue = sp->s_value; ! 539: } else if (class == DC_LAB) ! 540: csec = C_TEXT_SEG + 1; ! 541: ! 542: /* Get type. */ ! 543: for (;;) { ! 544: type = bget(); /* type */ ! 545: if (class == DC_MOE) ! 546: type = enumtype; /* fudge DT_NONE */ ! 547: dbprintf(("type=%d ", type)); ! 548: ! 549: if (type < DC_SEX) { ! 550: size = iget(); /* size */ ! 551: if (csec == N_UNDEF && seg != SANY) ! 552: cvalue = size; /* cvalue means size for commons */ ! 553: if (last_size != 0) { ! 554: /* Compute array dim from last/current size. */ ! 555: if (dims <= DIMNUM) ! 556: dim[dims-1] = (unsigned short)(last_size/size); ! 557: last_size = 0; ! 558: } ! 559: dbprintf(("size=%d\t", size)); ! 560: ! 561: /* Compute COFF type. */ ! 562: if (type <= DT_ENUM) ! 563: ctype |= coff_type[type]; /* basic COFF type */ ! 564: else if (type <= DD_ARRAY) { ! 565: /* Derived types DD_PTR, DD_FUNC, DD_ARRAY. */ ! 566: ctype |= (coff_type[type] << N_BTSHFT) << (derived++ * N_TSHIFT); ! 567: if (type == DD_ARRAY ! 568: && (csec != N_UNDEF || seg != SANY)) { ! 569: /* Reconstruct array dim from current/next size. */ ! 570: if (dims++ == 0) { ! 571: array_size = size; ! 572: for (n = 0; n < DIMNUM; n++) ! 573: dim[n] = 0; ! 574: } ! 575: last_size = size; ! 576: } ! 577: } ! 578: dbprintf(("ctype=%x\t", ctype)); ! 579: ! 580: if (type < DT_STRUCT) { ! 581: /* ! 582: * Simple types. ! 583: * An aux entry is needed for fields, functions, ! 584: * nested autos and arrays. ! 585: */ ! 586: if (class == DC_LINE || class == DC_LAB) { ! 587: dbprintf(("\n")); ! 588: db_line(line); ! 589: return; ! 590: } else if (class == DC_FILE) { ! 591: dbprintf(("\n")); ! 592: db_file(); ! 593: return; ! 594: } ! 595: if (suppress) ! 596: break; ! 597: if (csec == N_UNDEF && dims > 0) ! 598: cvalue = array_size; ! 599: dp = new_sym(id, cvalue, csec, ctype, cclass); ! 600: dp->db_seg = seg; ! 601: if (cclass == C_FIELD) { ! 602: /* Bitfield. */ ! 603: ap = new_aux(); ! 604: ap->ae_size = width; ! 605: } else if (ISFCN(ctype) && csec != N_UNDEF) { ! 606: /* Non-extern function. */ ! 607: ap = new_aux(); ! 608: db_func(dp); ! 609: } else if (cclass == C_AUTO && level > 1) { ! 610: /* Auto in nested block. */ ! 611: if (blockp == NULL) ! 612: cbotch("no blockp"); ! 613: ap = new_aux(); ! 614: ap->ae_lnno = blockp->sl_dp->db_ae.ae_lnno; ! 615: } ! 616: if (dims != 0) { ! 617: /* Array. */ ! 618: if (ap == NULL) ! 619: ap = new_aux(); ! 620: arrayap = ap; ! 621: arrayap->ae_size = array_size; ! 622: } ! 623: break; ! 624: } else if (type <= DT_ENUM) { ! 625: /* ! 626: * DT_STRUCT, DT_UNION, DT_ENUM types. ! 627: * An aux entry is always generated, although in ! 628: * rare cases (unresolved tags) it remains empty. ! 629: */ ! 630: sue_size = size; ! 631: if (suppress) ! 632: ap = &(dp->db_ae); ! 633: else { ! 634: if (csec == N_UNDEF && dims > 0) ! 635: cvalue = array_size; ! 636: dp = new_sym(id, cvalue, csec, ctype, cclass); ! 637: ap = new_aux(); ! 638: ap->ae_size = size; ! 639: } ! 640: tagn = dp->db_ref; /* tag index */ ! 641: tagdp = dp->db_next; /* tag aux dp */ ! 642: if (ISTAG(cclass)) { ! 643: /* Tag definition. */ ! 644: tag_def(dp); ! 645: endap = ap; ! 646: ap->ae_size = size; ! 647: if (cclass == C_ENTAG) ! 648: enumtype = (size == 1) ? DT_UCHAR : DT_INT; ! 649: } else if (ISFCN(ctype)) ! 650: db_func(dp); ! 651: if (dims != 0) { ! 652: arrayap = ap; ! 653: arrayap->ae_size = array_size; ! 654: } ! 655: continue; /* to process tag, member list */ ! 656: } else if (type == DX_MEMBS) { ! 657: /* Process member list recursively. */ ! 658: ++level; ! 659: for ( ; size > 0; --size) { ! 660: dbprintf(("\n")); ! 661: /* ! 662: * Leave refnum unchanged to keep ! 663: * it in sync with the outdloc() ! 664: * reference numbers, for local structs. ! 665: * It gets bumped in outdlab(). ! 666: */ ! 667: --refnum; ! 668: outdlab(i+1, bget()); /* overwrites id */ ! 669: } ! 670: --level; ! 671: dp = new_sym(".eos", sue_size, N_ABS, T_NULL, C_EOS); ! 672: ap = new_aux(); ! 673: ap->ae_size = sue_size; ! 674: ap->ae_tagndx = tagn; ! 675: break; ! 676: } else if (type == DX_NAME) { ! 677: /* Named type. */ ! 678: sget(id, NCSYMB); /* overwrites id */ ! 679: tag_ref(id, tagdp); ! 680: dbprintf(("tag=%s", id)); ! 681: break; ! 682: } ! 683: } else ! 684: cbotch("unrecognized type %d", type); ! 685: } ! 686: if (endap != NULL) ! 687: endap->ae_endndx = coff_hdr.f_nsyms; /* patch end index */ ! 688: if (arrayap != NULL) ! 689: for (n = 0; n < DIMNUM; n++) ! 690: arrayap->ae_dimen[n] = dim[n]; /* patch array dims */ ! 691: if (dims > DIMNUM) ! 692: cwarn("line %d: array type too complex, debug information lost", line); ! 693: if (derived > 6) ! 694: cwarn("line %d: type too complex, debug information lost", line); ! 695: dbprintf(("\n")); ! 696: } ! 697: ! 698: /* ! 699: * Handle function debug information. ! 700: * This generates the .bf when the function name is seen ! 701: * rather than when the '{' is seen, ! 702: * because the .bb symbol must precede the function parameter symbols. ! 703: * The function size and endindex are patched when the .ef gets generated. ! 704: */ ! 705: db_func(dp) register DBSYM *dp; ! 706: { ! 707: register LNNUM *lp; ! 708: ! 709: lp = new_ln(LN_FUNC); ! 710: lp->ln_val = dp->db_ref; ! 711: fn_dp = dp; ! 712: dp = new_sym(".bf", (ival_t)0, C_TEXT_SEG+1, T_NULL, C_FCN); ! 713: new_aux(); ! 714: } ! 715: ! 716: /* ! 717: * Process DC_LINE ('{', ';' and '}') and DC_LAB items. ! 718: * Each generates a line number entry, some generate additional symbol entries. ! 719: * The screwy line numbers for .bb/.eb are as in Unix, might be wrong. ! 720: */ ! 721: db_line(line) register int line; ! 722: { ! 723: static int fn_line; /* First lnnum of fn */ ! 724: register LNNUM *lp; ! 725: register DBSYM *dp; ! 726: register AUXENT *ap; ! 727: SYMLIST *bp; ! 728: char *name; ! 729: ! 730: dbprintf(("db_line(%d): %c\n", line, id[0])); ! 731: dp = NULL; ! 732: switch(id[0]) { ! 733: case '{': ! 734: /* .bf got generated by db_func(), patch its value and line. */ ! 735: if (level == 0) { ! 736: if (fn_dp == NULL) ! 737: cfatal("incomplete function debug information"); ! 738: dp = fn_dp->db_next->db_next; /* .bf entry */ ! 739: fn_line = dp->db_next->db_ae.ae_lnno = line; ! 740: } else { ! 741: /* Generate a .bb entry. */ ! 742: dp = new_sym(".bb", (ival_t)0, C_TEXT_SEG+1, T_NULL, C_BLOCK); ! 743: ap = new_aux(); ! 744: ap->ae_lnno = line - fn_line + 2; /* huh? */ ! 745: ! 746: /* Link the .bb onto the blockp list. */ ! 747: bp = (SYMLIST *)malloc(sizeof(SYMLIST)); ! 748: if (bp == NULL) ! 749: cnomem("db_line"); ! 750: bp->sl_next = blockp; ! 751: bp->sl_dp = dp->db_next; ! 752: blockp = bp; ! 753: } ! 754: level++; ! 755: break; ! 756: case ';': ! 757: /* Generate a line number entry only. */ ! 758: break; ! 759: case '}': ! 760: /* Generate a .ef or .eb entry. */ ! 761: level--; ! 762: name = (level == 0) ? ".ef" : ".eb"; ! 763: dp = new_sym(name, (ival_t)0, C_TEXT_SEG+1, T_NULL, ! 764: (level == 0) ? C_FCN : C_BLOCK); ! 765: ap = new_aux(); ! 766: ap->ae_lnno = (level==0) ? line - fn_line + 1 ! 767: : line - fn_line + 2; /* huh? */ ! 768: if (level == 0) { ! 769: /* End of function, patch its length and end. */ ! 770: ap = &(fn_dp->db_next->db_ae); ! 771: ap->ae_fsize = -(fn_dp->db_se.n_value); /* -start */ ! 772: ap->ae_endndx = coff_hdr.f_nsyms; ! 773: } else { ! 774: /* Close nested block, popping blockp entry. */ ! 775: if ((bp = blockp) == NULL) ! 776: cbotch("db_line"); ! 777: blockp = bp->sl_next; ! 778: bp->sl_dp->db_ae.ae_endndx = coff_hdr.f_nsyms; ! 779: free(bp); ! 780: } ! 781: break; ! 782: default: ! 783: /* Generate a label entry. */ ! 784: dp = new_sym(id, (ival_t)0, C_TEXT_SEG+1, ! 785: T_NULL, /* icc uses <DT_ARY T_INT>, dunno why */ ! 786: C_LABEL); ! 787: break; ! 788: } ! 789: ! 790: /* Generate a new line number item. */ ! 791: lp = new_ln(LN_LINE); ! 792: lp->ln_dp = dp; /* adjust value of DBSYM when addr is known */ ! 793: lp->ln_lnnum = line - fn_line + 1; ! 794: lp->ln_val = refnum; ! 795: if (id[0] == '}' && level == 0) ! 796: lp->ln_ap = ap; /* adjust fn size when addr is known */ ! 797: } ! 798: ! 799: /* ! 800: * Create symbol table entries for a DC_FILE. ! 801: */ ! 802: db_file() ! 803: { ! 804: register DBSYM *dp; ! 805: register AUXENT *ap; ! 806: register char *cp; ! 807: ! 808: if (refnum != 0) ! 809: cbotch("db_file"); /* DC_FILE must be first entry */ ! 810: dp = new_sym(".file", (ival_t)0, N_DEBUG, T_NULL, C_FILE); ! 811: ap = new_aux(); /* aux entry */ ! 812: if ((cp = strrchr(id, '/')) == NULL) /* ignore pathname if present */ ! 813: cp = id; ! 814: strncpy(ap->ae_fname, cp, FILNMLEN); ! 815: coff_hdr.f_nsyms += 2 * C_NSECS; /* section symbols with aux entries */ ! 816: } ! 817: ! 818: /* ! 819: * Allocate a new DBSYM item, initialize it to 0 and link it into the list. ! 820: * If name is non-NULL, initialize its name field. ! 821: */ ! 822: DBSYM * ! 823: new_db(name) register char *name; ! 824: { ! 825: register DBSYM *dp; ! 826: register int size, len; ! 827: ! 828: size = sizeof(*dp); ! 829: if (name != NULL && (len = strlen(name)) > 8) ! 830: size += len + 1; ! 831: dp = (DBSYM *)malloc(size); ! 832: if (dp == NULL) ! 833: cnomem("new_db"); ! 834: memset(dp, 0, size); ! 835: *db_lastp = dp; ! 836: db_lastp = &(dp->db_next); ! 837: if (name != NULL) { ! 838: if (len <= 8) ! 839: strncpy(dp->db_se.n_name, name, 8); ! 840: else { ! 841: strcpy(dp->db_name, name); ! 842: dp->db_flags = DB_LNAME; ! 843: } ! 844: } ! 845: dp->db_seg = -1; ! 846: dp->db_level = level; ! 847: dp->db_ref = coff_hdr.f_nsyms++; ! 848: return dp; ! 849: } ! 850: ! 851: /* ! 852: * Allocate a new DBSYM item and initialize it. ! 853: */ ! 854: DBSYM * ! 855: new_sym(name, value, sec, type, class) ! 856: char *name; ! 857: ival_t value; ! 858: int sec, type, class; ! 859: { ! 860: register DBSYM *dp; ! 861: register SYMENT *sp; ! 862: ! 863: dp = new_db(name); ! 864: dbprintf(("new_sym(%s) val=%ld sec=%d type=%d cl=%d @%x\n", name, value, sec,type, class, dp)); ! 865: sp = &(dp->db_se); ! 866: sp->n_value = value; ! 867: sp->n_scnum = sec; ! 868: sp->n_type = type; ! 869: sp->n_sclass = class; ! 870: sp->n_numaux = 0; ! 871: return dp; ! 872: } ! 873: ! 874: /* ! 875: * Allocate a new AUXENT and return a pointer to it. ! 876: */ ! 877: AUXENT * ! 878: new_aux() ! 879: { ! 880: register DBSYM *dp; ! 881: ! 882: ++(((DBSYM *)db_lastp)->db_se.n_numaux); /* bump aux entry count */ ! 883: dp = new_db(NULL); ! 884: dp->db_flags |= DB_AUX; ! 885: return &(dp->db_ae); ! 886: } ! 887: ! 888: /* ! 889: * Allocate a new LNNUM item, initialize it to 0 and link it into the list. ! 890: */ ! 891: LNNUM * ! 892: new_ln(flag) int flag; ! 893: { ! 894: register LNNUM *lp; ! 895: ! 896: lp = (LNNUM *)malloc(sizeof(*lp)); ! 897: if (lp == NULL) ! 898: cnomem("new_ln"); ! 899: memset(lp, 0, sizeof(*lp)); ! 900: *ln_lastp = lp; ! 901: ln_lastp = &(lp->ln_next); ! 902: ++scn_hdr[C_TEXT_SEG].s_nlnno; ! 903: lp->ln_flag = flag; ! 904: return lp; ! 905: } ! 906: ! 907: /* Tag handling. */ ! 908: /* ! 909: * Define a tag with symbol table entry dp. ! 910: * Previous forward references are left unresolved until tag_resolve(). ! 911: */ ! 912: tag_def(dp) DBSYM *dp; ! 913: { ! 914: register SYMLIST *sp; ! 915: ! 916: sp = (SYMLIST *)malloc(sizeof(*sp)); ! 917: if (sp == NULL) ! 918: cnomem("tag_def"); ! 919: sp->sl_next = tag_list; ! 920: sp->sl_dp = dp; ! 921: tag_list = sp; ! 922: } ! 923: ! 924: /* ! 925: * Look up a tag name in the list of defined tags. ! 926: * Return a nonnegative symbol reference number or -1 if not found. ! 927: */ ! 928: int ! 929: tag_lookup(name) register char *name; ! 930: { ! 931: register SYMLIST *sp; ! 932: ! 933: for (sp = tag_list; sp != NULL; sp = sp->sl_next) ! 934: if (db_strcmp(sp->sl_dp, name) == 0) ! 935: return sp->sl_dp->db_ref; ! 936: return -1; ! 937: } ! 938: ! 939: /* ! 940: * Reference a tag. ! 941: * If defined, store the symbol reference number in the aux entry at dp. ! 942: * If not, add an entry to the TAGFIX list so it gets fixed up later. ! 943: */ ! 944: tag_ref(name, dp) char *name; DBSYM *dp; ! 945: { ! 946: register SYMLIST *sp; ! 947: register TAGFIX *tp; ! 948: register int n; ! 949: ! 950: dbprintf(("tag_ref(%s, %d):\n", name, dp->db_ref)); ! 951: if (dp == NULL) ! 952: cbotch("NULL aux pointer in tag_ref"); ! 953: if ((n = tag_lookup(name)) != -1) { ! 954: /* The tag is defined already. */ ! 955: dp->db_ae.ae_tagndx = n; /* store index */ ! 956: return; ! 957: } ! 958: ! 959: /* ! 960: * The tag is not defined. ! 961: * Search for an existing tag_fix entry. ! 962: */ ! 963: for (tp = tag_fix; tp != NULL; tp = tp->tf_next) ! 964: if (strcmp(name, tp->tf_name) == 0) ! 965: break; ! 966: if (tp == NULL) { ! 967: /* Build a new TAGFIX entry on first forward reference. */ ! 968: tp = (TAGFIX *)malloc(sizeof(*tp) + strlen(name) + 1); ! 969: if (tp == NULL) ! 970: cnomem("tag_ref"); ! 971: tp->tf_next = tag_fix; ! 972: tp->tf_sp = NULL; ! 973: strcpy(tp->tf_name, name); ! 974: tag_fix = tp; ! 975: } ! 976: ! 977: /* Add dp to the list of fixes. */ ! 978: sp = (SYMLIST *)malloc(sizeof(*sp)); ! 979: if (sp == NULL) ! 980: cnomem("tag_ref"); ! 981: sp->sl_next = tp->tf_sp; ! 982: sp->sl_dp = dp; ! 983: tp->tf_sp = sp; ! 984: } ! 985: ! 986: /* ! 987: * Resolve forward tag references and free the tag lists. ! 988: * Forward references which remain unresolved could be handled in several ways, ! 989: * this just leaves the aux entry (rather than deleting it) and leaves its ! 990: * tag member index zeroed. ! 991: */ ! 992: tag_resolve() ! 993: { ! 994: register TAGFIX *tp; ! 995: register SYMLIST *sp; ! 996: int n; ! 997: SYMLIST *sp2; ! 998: ! 999: while ((tp = tag_fix) != NULL) { ! 1000: if ((n = tag_lookup(tp->tf_name)) != -1) { ! 1001: /* Tag is defined. */ ! 1002: for (sp = tp->tf_sp; sp != NULL; ) { ! 1003: sp->sl_dp->db_ae.ae_tagndx = n; ! 1004: sp2 = sp; ! 1005: sp = sp->sl_next; ! 1006: free(sp2); ! 1007: } ! 1008: } else { ! 1009: /* Tag is not defined. */ ! 1010: dbprintf(("tag %s: unresolved forward references\n", tp->tf_name)); ! 1011: for (sp = tp->tf_sp; sp != NULL; ) { ! 1012: /* Do nothing; there are alternatives... */ ! 1013: sp2 = sp; ! 1014: sp = sp->sl_next; ! 1015: free(sp2); ! 1016: } ! 1017: } ! 1018: tag_fix = tp->tf_next; ! 1019: free(tp); ! 1020: } ! 1021: ! 1022: /* Free the tag list. */ ! 1023: while (tag_list != NULL) { ! 1024: sp = tag_list; ! 1025: tag_list = sp->sl_next; ! 1026: free(sp); ! 1027: } ! 1028: } ! 1029: ! 1030: /* ! 1031: * Process a debug relocation record. ! 1032: * n is the debug item reference number. ! 1033: */ ! 1034: outdloc(n) register int n; ! 1035: { ! 1036: register LNNUM *lp; ! 1037: register DBSYM *dp; ! 1038: register AUXENT *ap; ! 1039: ! 1040: dbprintf(("outdloc(%d): dot=%d\n", n, dot)); ! 1041: ! 1042: /* Find matching refnum in line number list. */ ! 1043: for (lp = ln_list; lp != NULL; lp = lp->ln_next) { ! 1044: if (lp->ln_flag == LN_LINE && lp->ln_val == n) ! 1045: break; ! 1046: } ! 1047: if (lp == NULL) ! 1048: cbotch("outdloc refnum=%d", n); ! 1049: if (dotseg != SCODE) ! 1050: cbotch("outdloc seg=%d", seg); ! 1051: lp->ln_addr = dot; /* patch address */ ! 1052: if ((dp = lp->ln_dp) != NULL) ! 1053: dp->db_se.n_value = dot; /* patch symbol entry address */ ! 1054: ! 1055: /* ! 1056: * The function size patch below is wrong because the actual ! 1057: * function size includes the epilog. ! 1058: * The "dot + 2" adds in the "leave; ret" bytes, ! 1059: * but there may be from 0 to 3 additional "pop" bytes for EBX, ESI, EDI. ! 1060: */ ! 1061: if ((ap = lp->ln_ap) != NULL) ! 1062: ap->ae_fsize += dot + 2; /* patch function length */ ! 1063: } ! 1064: ! 1065: /* ! 1066: * Finish up. ! 1067: */ ! 1068: outdone() ! 1069: { ! 1070: if (notvariant(VASM)) ! 1071: bput(TEND); ! 1072: tag_resolve(); ! 1073: } ! 1074: ! 1075: /* Second pass. */ ! 1076: copycode() ! 1077: { ! 1078: register int op, i, flags; ! 1079: register SEG *segp; ! 1080: register SYM *sp; ! 1081: register long dseek; ! 1082: register ADDRESS mseek, segsize; ! 1083: int nsecs, nd, isbyte, isword, issym, ispcr; ! 1084: ival_t data; ! 1085: RELOC *rp; ! 1086: SCNHDR *shp; ! 1087: ! 1088: /* Assign symbol table indices for sections, different if debug. */ ! 1089: flags = 0; /* COFF header flags */ ! 1090: nsecs = C_NSECS; /* number of sections, including .comment */ ! 1091: if (refnum != -1) { ! 1092: symindex[C_TEXT_SEG] = C_TEXT_DB; ! 1093: symindex[C_DATA_SEG] = C_DATA_DB; ! 1094: symindex[C_BSS_SEG] = C_BSS_DB; ! 1095: } else { ! 1096: flags |= F_LSYMS; /* no local symbols */ ! 1097: symindex[C_TEXT_SEG] = C_TEXT_SEG; ! 1098: symindex[C_DATA_SEG] = C_DATA_SEG; ! 1099: symindex[C_BSS_SEG] = C_BSS_SEG; ! 1100: --nsecs; /* do not write .comment section */ ! 1101: } ! 1102: ! 1103: /* Assign segment base addresses. */ ! 1104: dot_sec = -1; ! 1105: dseek = sizeof(FILEHDR) + nsecs * sizeof(SCNHDR); ! 1106: mseek = 0; ! 1107: for (i = SCODE, segp = &seg[SCODE]; i <= SBSS; ++i, ++segp) { ! 1108: segsize = RUP(segp->s_dot); ! 1109: segp->s_dot = 0; ! 1110: if (sec_index[i] != dot_sec) { ! 1111: /* Begin new COFF section. */ ! 1112: dot_sec = sec_index[i]; ! 1113: dbprintf(("COFF section %d\n", dot_sec)); ! 1114: shp = &scn_hdr[dot_sec]; ! 1115: shp->s_paddr = shp->s_vaddr = mseek; ! 1116: if (i != C_BSS_SEG) ! 1117: shp->s_scnptr = dseek; ! 1118: } ! 1119: dbprintf(("segment %d: size=%d dseek=%ld mseek=%ld\n", i, segsize, dseek, mseek)); ! 1120: segp->s_dseek = dseek; /* set compiler seg disk seek */ ! 1121: segp->s_mseek = mseek; /* and memory seek */ ! 1122: scn_hdr[dot_sec].s_size += segsize; /* bump COFF seg size */ ! 1123: dseek += segsize; /* bump seek pointer */ ! 1124: mseek += segsize; /* bump memory seek */ ! 1125: } ! 1126: ! 1127: /* Write the .comment section: translator id and version number. */ ! 1128: if (refnum != -1) { ! 1129: shp = &scn_hdr[C_CMT_SEG]; ! 1130: segsize = RUP(strlen(CC_ID) + strlen(VERSMWC) + 1); ! 1131: shp->s_paddr = mseek; ! 1132: shp->s_vaddr = mseek; ! 1133: shp->s_size = segsize; ! 1134: shp->s_scnptr = dseek; ! 1135: oseek(dseek); ! 1136: owrite(CC_ID, sizeof(CC_ID) - 1); /* no NUL */ ! 1137: owrite(VERSMWC, sizeof(VERSMWC)); /* with NUL */ ! 1138: dseek += segsize; /* bump seek pointer */ ! 1139: mseek += segsize; /* bump memory seek */ ! 1140: } ! 1141: ! 1142: /* Fix reloc offsets. */ ! 1143: for (shp = &scn_hdr[C_TEXT_SEG]; shp < &scn_hdr[nsecs]; ++shp) { ! 1144: if (shp->s_nreloc != 0) { ! 1145: shp->s_relptr = dseek; ! 1146: dseek += shp->s_nreloc * sizeof(RELOC); ! 1147: } ! 1148: } ! 1149: ! 1150: /* Write line number information, .text section only. */ ! 1151: shp = &scn_hdr[C_TEXT_SEG]; ! 1152: if (shp->s_nlnno != 0) { ! 1153: shp->s_lnnoptr = dseek; ! 1154: oseek(dseek); ! 1155: write_lnnums(); ! 1156: dseek += scn_hdr[C_TEXT_SEG].s_nlnno * sizeof(LINENO); ! 1157: } else ! 1158: flags |= F_LNNO; /* no line numbers */ ! 1159: ! 1160: /* Write symbols. */ ! 1161: write_symbols(dseek); ! 1162: ! 1163: /* Copy out code. */ ! 1164: dotseg = SCODE; ! 1165: dot_sec = sec_index[dotseg]; ! 1166: txtdot = dot = 0; ! 1167: txtp = &txt[0]; ! 1168: relp = &rel[0]; ! 1169: while ((op = bget()) != TEND) { ! 1170: if (op == TENTER) { ! 1171: notenuf(); ! 1172: seg[dotseg].s_dot = dot; ! 1173: dotseg = bget(); ! 1174: dot_sec = sec_index[dotseg]; ! 1175: txtdot = dot = seg[dotseg].s_dot; ! 1176: continue; ! 1177: } ! 1178: enuf(4, sizeof(RELOC)); /* leave space for next op */ ! 1179: if (isbyte = ((op & TTYPE) == TBYTE)) { ! 1180: nd = 1; ! 1181: data = bget(); ! 1182: } else if (isword = ((op & TTYPE) == TWORD)) { ! 1183: nd = 2; ! 1184: data = iget(); ! 1185: } else if ((op & TTYPE) == TLONG) { ! 1186: nd = 4; ! 1187: data = iget(); ! 1188: } else ! 1189: cbotch("unrecognized op byte: %d", op); ! 1190: if (issym = ((op & TSYM) != 0)) { ! 1191: sp = pget(); ! 1192: if (is_def(sp) || is_label(sp) || is_bss(sp)) ! 1193: data += sp->s_value; ! 1194: } ! 1195: if (ispcr = ((op & TPCR) != 0)) ! 1196: data -= dot + nd; ! 1197: ! 1198: /* Write text. */ ! 1199: for (i = 1; i <= nd; i++) { ! 1200: *txtp++ = data; ! 1201: data >>= 8; ! 1202: } ! 1203: ! 1204: /* Write relocation item if required. */ ! 1205: if (issym || ispcr) { ! 1206: rp = (RELOC *)relp; ! 1207: rp->r_vaddr = dot + seg[dotseg].s_mseek; ! 1208: if (issym) { ! 1209: if (is_def(sp) || is_label(sp)) ! 1210: rp->r_symndx = symindex[sec_index[sp->s_seg]]; ! 1211: else ! 1212: rp->r_symndx = sp->s_ref; ! 1213: } else ! 1214: rp->r_symndx = symindex[dot_sec]; ! 1215: if (ispcr) ! 1216: rp->r_type = (isbyte) ? R_PCRBYTE ! 1217: : (isword) ? R_PCRWORD : R_PCRLONG; ! 1218: else ! 1219: rp->r_type = (isbyte) ? R_DIR8 ! 1220: : (isword) ? R_DIR16 : R_DIR32; ! 1221: relp += sizeof(RELOC); ! 1222: } ! 1223: dot += nd; ! 1224: } ! 1225: ! 1226: /* Flush buffers. */ ! 1227: notenuf(); ! 1228: ! 1229: /* Write COFF header. */ ! 1230: coff_hdr.f_magic = C_386_MAGIC; ! 1231: coff_hdr.f_nscns = nsecs; ! 1232: coff_hdr.f_timdat = time(NULL); ! 1233: coff_hdr.f_opthdr = 0; ! 1234: coff_hdr.f_flags = F_AR32WR | flags; ! 1235: oseek(0L); ! 1236: owrite((char *)&coff_hdr, sizeof(coff_hdr)); ! 1237: ! 1238: /* Write section headers. */ ! 1239: for (shp = &scn_hdr[C_TEXT_SEG]; shp < &scn_hdr[nsecs]; ++shp) ! 1240: owrite((char *)shp, sizeof(*shp)); ! 1241: } ! 1242: ! 1243: /* ! 1244: * Write the COFF symbol table. ! 1245: * Spill long symbol names to the strings section. ! 1246: * If debug, there is a DBSYM entry for each symbol table entry, ! 1247: * except that the section names and their aux entries are implicit. ! 1248: * If not debug, generate COFF symbol table from the compiler symbol table. ! 1249: */ ! 1250: write_symbols(dseek) register long dseek; ! 1251: { ! 1252: register int i; ! 1253: register SYM *sp; ! 1254: int db_flag, nsecs; ! 1255: SYMENT sym; ! 1256: AUXENT aux; ! 1257: SCNHDR *shp; ! 1258: ! 1259: db_flag = (refnum != -1); ! 1260: nsecs = C_NSECS; ! 1261: coff_hdr.f_symptr = dseek; /* symbol secton base */ ! 1262: oseek(dseek); /* seek to symbol section */ ! 1263: if (db_flag) { ! 1264: /* Write .file symbol and its aux entry. */ ! 1265: write_dbsym(); /* .file */ ! 1266: write_dbsym(); /* .file aux entry */ ! 1267: } else ! 1268: coff_hdr.f_nsyms = --nsecs; /* .text, .data, .bss symbols */ ! 1269: ! 1270: /* Set reference numbers and adjust offsets in symbol table. */ ! 1271: for (i = 0; i < NSHASH; ++i) { ! 1272: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) { ! 1273: /* Adjust symbol offsets for segment bases. */ ! 1274: if (is_def(sp) || is_label(sp)) ! 1275: sp->s_value += seg[sp->s_seg].s_mseek; ! 1276: /* Set reference numbers. */ ! 1277: if (is_global(sp) || (!is_label(sp) && !is_def(sp))) { ! 1278: if (db_flag) ! 1279: setrefnum(sp); ! 1280: else ! 1281: sp->s_ref = coff_hdr.f_nsyms++; ! 1282: } else if (isvariant(VXSTAT) && !is_global(sp) ! 1283: && !is_label(sp) && is_def(sp)) ! 1284: sp->s_ref = coff_hdr.f_nsyms++; ! 1285: } ! 1286: } ! 1287: ! 1288: /* Write section name symbols. */ ! 1289: for (i = C_TEXT_SEG, shp = &scn_hdr[i]; i < nsecs; ++i, ++shp) { ! 1290: memset(sym.n_name, 0, sizeof(sym.n_name)); ! 1291: strcpy(sym.n_name, shp->s_name); ! 1292: sym.n_value = shp->s_vaddr; ! 1293: sym.n_scnum = i + 1; ! 1294: sym.n_type = T_NULL; /* no type */ ! 1295: sym.n_sclass = C_STAT; ! 1296: sym.n_numaux = (db_flag) ? 1 : 0; /* aux entries */ ! 1297: owrite((char *)&sym, sizeof(sym)); ! 1298: if (db_flag) { ! 1299: /* Write aux entries for sections if debug. */ ! 1300: memset(&aux, 0, sizeof(aux)); ! 1301: aux.ae_scnlen = shp->s_size; ! 1302: aux.ae_nreloc = shp->s_nreloc; ! 1303: aux.ae_nlinno = shp->s_nlnno; ! 1304: owrite((char *)&aux, sizeof(aux)); ! 1305: } ! 1306: } ! 1307: ! 1308: /* Write remaining symbols. */ ! 1309: str_size = sizeof(long); /* initial string section size */ ! 1310: str_seek = dseek + coff_hdr.f_nsyms * sizeof(sym) + str_size; /* first string seek */ ! 1311: if (db_flag) { ! 1312: while (db_list != NULL) ! 1313: write_dbsym(); ! 1314: } else { ! 1315: /* Scan the C symbol table again and dump the appropriate symbols. */ ! 1316: for (i = 0; i < NSHASH; ++i) { ! 1317: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) { ! 1318: if (is_global(sp) || (!is_label(sp) && !is_def(sp))) ! 1319: write_sym(sp, C_EXT); ! 1320: else if (isvariant(VXSTAT) && !is_global(sp) ! 1321: && !is_label(sp) && is_def(sp)) ! 1322: write_sym(sp, C_STAT); ! 1323: } ! 1324: } ! 1325: } ! 1326: /* Write string table size if nonempty. */ ! 1327: if (str_size != sizeof(long)) ! 1328: owrite((char *)&str_size, sizeof(str_size)); ! 1329: } ! 1330: ! 1331: /* ! 1332: * Write a symbol. ! 1333: */ ! 1334: write_sym(sp, class) register SYM *sp; ! 1335: { ! 1336: register int len; ! 1337: SYMENT sym; ! 1338: ! 1339: len = strlen(sp->s_id); ! 1340: if (len <= SYMNMLEN) ! 1341: strncpy(sym.n_name, sp->s_id, SYMNMLEN); ! 1342: else { ! 1343: /* Spill long name to string table. */ ! 1344: write_string(&sym, sp->s_id); ! 1345: } ! 1346: sym.n_value = sp->s_value; ! 1347: if (is_def(sp)) ! 1348: sym.n_scnum = sec_index[sp->s_seg] + 1; ! 1349: else ! 1350: sym.n_scnum = N_UNDEF; ! 1351: sym.n_type = T_NULL; /* no type */ ! 1352: sym.n_sclass = class; ! 1353: sym.n_numaux = 0; /* no aux entries */ ! 1354: owrite((char *)&sym, sizeof(sym)); ! 1355: } ! 1356: ! 1357: /* ! 1358: * Write a long string name to the string section. ! 1359: */ ! 1360: write_string(sp, id) SYMENT *sp; register char *id; ! 1361: { ! 1362: register long seek; ! 1363: register int len; ! 1364: ! 1365: sp->n_zeroes = 0L; ! 1366: sp->n_offset = str_size; ! 1367: len = strlen(id) + 1; ! 1368: seek = ftell(ofp); ! 1369: oseek(str_seek); ! 1370: sput(id); ! 1371: str_seek += len; ! 1372: str_size += len; ! 1373: oseek(seek); ! 1374: } ! 1375: ! 1376: /* ! 1377: * Write the line number entries. ! 1378: */ ! 1379: write_lnnums() ! 1380: { ! 1381: register LNNUM *lp; ! 1382: LINENO lineno; ! 1383: ! 1384: while ((lp = ln_list) != NULL) { ! 1385: lineno.l_lnno = lp->ln_lnnum; ! 1386: if (lp->ln_flag == LN_FUNC) /* function index */ ! 1387: lineno.l_addr.l_symndx = lp->ln_val; ! 1388: else if (lp->ln_flag == LN_LINE) /* line physical address */ ! 1389: lineno.l_addr.l_paddr = lp->ln_addr; ! 1390: else ! 1391: cbotch("write_lnnums"); ! 1392: owrite(&lineno, sizeof lineno); ! 1393: ln_list = lp->ln_next; ! 1394: free(lp); ! 1395: } ! 1396: } ! 1397: ! 1398: /* ! 1399: * Write a single DBSYM item to the symbol table. ! 1400: * Free the item from the list. ! 1401: */ ! 1402: write_dbsym() ! 1403: { ! 1404: register DBSYM *dp; ! 1405: register SYMENT *sp; ! 1406: register int n; ! 1407: ! 1408: if ((dp = db_list) == NULL) ! 1409: cfatal("incomplete debug information"); ! 1410: sp = &(dp->db_se); ! 1411: ! 1412: /* Adjust .data and .bss locations by section base. */ ! 1413: n = sp->n_scnum - 1; ! 1414: if (dp->db_seg != -1) ! 1415: sp->n_value += seg[dp->db_seg].s_mseek; ! 1416: ! 1417: /* Spill long name to the string table. */ ! 1418: if (is_lname(dp)) ! 1419: write_string(sp, dp->db_name); ! 1420: ! 1421: /* Write the symbol entry. */ ! 1422: owrite(sp, sizeof *sp); ! 1423: ! 1424: /* Free the entry. */ ! 1425: db_list = dp->db_next; ! 1426: free(dp); ! 1427: } ! 1428: ! 1429: /* ! 1430: * Set reference number of symbol sp by searching the debug symbol list, ! 1431: * so that fixups targeting it get the right symbol number. ! 1432: * This is used only if debug. ! 1433: */ ! 1434: setrefnum(sp) register SYM *sp; ! 1435: { ! 1436: static int ignore = -1; ! 1437: register DBSYM *dp; ! 1438: register char *name; ! 1439: ! 1440: /* If the user specifies -VTPROF but not -g, ignore the debug info. */ ! 1441: if (ignore == -1) /* set it first time */ ! 1442: ignore = (isvariant(VTPROF) && notvariant(VLINES) ! 1443: && notvariant(VTYPES) && notvariant(VDSYMB)); ! 1444: if (ignore) ! 1445: return; ! 1446: ! 1447: name = sp->s_id; ! 1448: for (dp = db_list; dp != NULL; dp = dp->db_next) ! 1449: if (!is_aux(dp) /* SYMENT not AUXENT */ ! 1450: && dp->db_level == 0 /* global */ ! 1451: && db_strcmp(dp, name) == 0) /* matching name */ ! 1452: break; /* gotcha */ ! 1453: if (dp == NULL) { ! 1454: /* ! 1455: * Function calls generated by the compiler (e.g. "memcpy" ! 1456: * for structure assignment) may have no associated debug item, ! 1457: * so create an appropriate External entry as required. ! 1458: */ ! 1459: if (sp->s_seg != SANY) ! 1460: cfatal("incomplete debug information (%s)", sp->s_id); ! 1461: dp = new_sym(sp->s_id, sp->s_value, N_UNDEF, T_NULL, C_EXT); ! 1462: } ! 1463: sp->s_ref = dp->db_ref; ! 1464: } ! 1465: ! 1466: /* ! 1467: * Compare two names like strcmp() does, but the first arg is a DBSYM *. ! 1468: */ ! 1469: int ! 1470: db_strcmp(dp, s) register DBSYM *dp; register char *s; ! 1471: { ! 1472: register int status; ! 1473: ! 1474: if (is_lname(dp)) ! 1475: return strcmp(dp->db_name, s); /* compare long db name */ ! 1476: status = strncmp(dp->db_se.n_name, s, 8); /* compare short db name */ ! 1477: if (status != 0) ! 1478: return status; /* mismatch */ ! 1479: return (strlen(s) <= 8) ? status : 1; /* first 8 match */ ! 1480: } ! 1481: ! 1482: /* Buffering and output writing routines. */ ! 1483: /* ! 1484: * Make sure there is enough room in the text and relocation buffers ! 1485: * for nt bytes of text and nr bytes of relocation. ! 1486: */ ! 1487: enuf(nt, nr) int nt, nr; ! 1488: { ! 1489: if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) ! 1490: notenuf(); ! 1491: } ! 1492: ! 1493: /* ! 1494: * Flush the text and relocation buffers. ! 1495: * Look at the segment table to figure out the exact location ! 1496: * of the data in the file, and compute the correct seek ! 1497: * address in the image by adding the base address of ! 1498: * the text record "txtdot" to that base. ! 1499: */ ! 1500: notenuf() ! 1501: { ! 1502: register int n; ! 1503: ! 1504: if ((n = txtp-txt) != 0) { ! 1505: dbprintf(("notenuf: %d text bytes\n", n)); ! 1506: dbprintf(("seek to txtdot=%d + seg[%d].s_dseek=%ld\n", txtdot, dotseg, seg[dotseg].s_dseek)); ! 1507: oseek(txtdot + seg[dotseg].s_dseek); ! 1508: owrite(txt, n); ! 1509: if ((n = relp-rel) != 0) { ! 1510: dbprintf(("notenuf: %d reloc bytes\n", n)); ! 1511: dbprintf(("seek to reldot[%d]=%d + relptr=%ld\n", dot_sec, reldot[dot_sec], scn_hdr[dot_sec].s_relptr)); ! 1512: oseek(reldot[dot_sec] + scn_hdr[dot_sec].s_relptr); ! 1513: owrite(rel, n); ! 1514: reldot[dot_sec] += n; ! 1515: relp = rel; ! 1516: } ! 1517: } ! 1518: txtp = txt; ! 1519: txtdot = dot; ! 1520: } ! 1521: ! 1522: /* ! 1523: * Seek output file, checking for seek error. ! 1524: */ ! 1525: oseek(l) long l; ! 1526: { ! 1527: if (fseek(ofp, l, SEEK_SET) == -1L) ! 1528: cfatal("seek to %ld failed", l); ! 1529: } ! 1530: ! 1531: /* ! 1532: * Write a block of n bytes from p to the output file, ! 1533: * checking for write errors. ! 1534: */ ! 1535: owrite(p, n) char *p; register int n; ! 1536: { ! 1537: if (fwrite(p, sizeof(char), n, ofp) != n) ! 1538: cfatal("output write error"); ! 1539: } ! 1540: ! 1541: /* end of n2/i386/outcoff.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.