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