|
|
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.