|
|
1.1 root 1: /*
2: * The routines in this file make up
3: * a writer for the Coherent reloc.h object
4: * file. During code assembly all the bits get
5: * written to a temporary file. At the very end the
6: * bits get copied back to the final object file.
7: * The symbol table is constructed as the code is read,
8: * each symbol is declared when defined. References are
9: * tacked onto the end of the file.
10: * Relocation instructions for debug and symbol table entries are
11: * also passed through the scratch file.
12: */
13: #ifdef vax
14: #include "INC$LIB:cc2.h"
15: #include "INC$LIB:canon.h"
16: #include "INC$LIB:reloc.h"
17: #include "INC$LIB:debug.h"
18: #else
19: #include "cc2.h"
20: #include <canon.h>
21: #include <reloc.h>
22: #include <debug.h>
23: #endif
24:
25: #if !TINY
26: #define dbrpt(x,y) _dbrpt(x,y)
27: #else
28: #define dbrpt(x,y) /* dbrpt(x,y) */
29: #endif
30: #define NTXT 512 /* Text buffer size */
31: #define NREL 256 /* Relocation buffer size */
32: /*
33: * Scratch file operators.
34: */
35: #define TTYPE 017 /* Type mask */
36: #define Tflag(x) (((x)>>4)&7) /* Get flag bits */
37: #define TEND 000 /* End marker */
38: #define TENTER 001 /* Enter new area */
39: #define TBYTE 002 /* Byte data */
40: #define TWORD 003 /* Word data */
41: #if 0
42: #define TTRIP 004 /* Triple byte data */
43: #define TLONG 005 /* Long data */
44: #endif
45: #define TDLAB 006 /* Debug item */
46: #define TDLOC 007 /* Debug location */
47: #define TCODE 010 /* Code segment base */
48: #define TDATA 011 /* Data segment base */
49: #define TBASE 012 /* External segment base */
50:
51: #define TPCR 020 /* PC rel flag, ored in */
52: #define TSYM 040 /* Symbol based flag, ored in */
53: #define locrup(x) (((x)+01)&~01) /* memory alignment */
54: objhdr_t objhdr = { /* object header */
55: REL_OBJ,
56: "i8086",
57: "C",
58: VERSMWC
59: };
60:
61: summseg_t summseg = { /* Summary segment */
62: SUMMARY,
63: sizeof (summseg.seg_off)
64: };
65:
66: extern char *calloc();
67: extern char *malloc();
68: extern char *strcpy();
69:
70: ADDRESS SCODE_len; /* Length of SCODE in bytes */
71: char txt[NTXT]; /* Text buffer */
72: char rel[NREL]; /* Relocation buffer */
73: char *txtp = txt; /* Text pointer */
74: char *relp = rel; /* Relocation pointer */
75: int refnum = 0; /* Symbol reference number */
76: static int level = 0; /* Debug brace level */
77: static int dline = 0; /* Most recent line number entry */
78:
79: /*
80: * This table converts a C compiler
81: * segment index into a relocatable object segment type.
82: */
83: char segindex[] = {
84: PURCODE, /* SCODE */
85: OWNCODE, /* SLINK */
86: PURDATA, /* SPURE */
87: STRINGS, /* SSTRN */
88: OWNDATA, /* SDATA */
89: BLDATA, /* SBSS */
90: -1, /* SANY */
91: -1, /* SSTACK */
92: -1, /* SALIEN */
93: DEBUG, /* SDBG */
94: SYMBOLS /* SSYM */
95: };
96:
97: /*
98: * Output a segment switch.
99: */
100: outseg(s)
101: {
102: bput(TENTER);
103: bput(s);
104: }
105:
106: /*
107: * Output an absolute byte.
108: */
109: outab(b)
110: {
111: bput(TBYTE);
112: bput(b);
113: dot += 1;
114: }
115:
116: /*
117: * Output an absolute word.
118: */
119: outaw(w)
120: {
121: bput(TWORD);
122: iput(w);
123: dot += 2;
124: }
125:
126:
127: #ifdef TLONG
128: /*
129: * Output an absolute long.
130: */
131: outal(l)
132: long l;
133: {
134: bput(TLONG);
135: lput(l);
136: dot += 4;
137: }
138: #endif
139:
140: /*
141: * Output a full byte.
142: */
143: outxb(sp, b, pcrf)
144: register SYM *sp;
145: {
146: register opcode;
147:
148: opcode = TBYTE;
149: if (sp != NULL)
150: opcode |= TSYM;
151: if (pcrf)
152: opcode |= TPCR;
153: bput(opcode);
154: bput(b);
155: if (sp != NULL)
156: pput(sp);
157: dot += 1;
158: }
159:
160: /*
161: * Output a full word.
162: */
163: outxw(sp, w, pcrf)
164: register SYM *sp;
165: {
166: register opcode;
167:
168: opcode = TWORD;
169: if (sp != NULL)
170: opcode |= TSYM;
171: if (pcrf)
172: opcode |= TPCR;
173: bput(opcode);
174: iput(w);
175: if (sp != NULL)
176: pput(sp);
177: dot += 2;
178: }
179:
180: #ifdef TLONG
181: /*
182: * Output a full long.
183: */
184: outxl(sp, l, pcrf)
185: register SYM *sp;
186: long l;
187: {
188: register opcode;
189:
190: opcode = TLONG;
191: if (sp != NULL)
192: opcode |= TSYM;
193: if (pcrf)
194: opcode |= TPCR;
195: bput(opcode);
196: lput(lR);
197: if (sp != NULL)
198: pput(sp);
199: dot += 4;
200: }
201: #endif
202:
203: /*
204: * Copy a dlabel record from ifp to ofp.
205: * Flag the symbol table entry if appropriate.
206: */
207: outdlab(l,class)
208: {
209: register int val;
210: register SYM *sp;
211: int n;
212:
213: if (l == 0)
214: bput(TDLAB);
215: bput(class);
216:
217: /* Get line number. */
218: iput(iget());
219:
220: /* Get value */
221: if (class < DC_AUTO)
222: ;
223: else if (class < DC_MOS)
224: iput(val = iget());
225: else {
226: bput(bget());
227: bput(bget());
228: iput(iget());
229: }
230:
231: /* Get name */
232: sget(id, NCSYMB);
233:
234: /* Check for symbol table entry */
235: if (class==DC_GDEF || class==DC_SEX || class==DC_GREF) {
236: sp = glookup(id, 0);
237: sp->s_flag |= S_PUT;
238: } else if (class==DC_SIN) {
239: sp = llookup(val, 0);
240: sp->s_flag |= S_PUT;
241: }
242:
243: /* Put name */
244: sput(id);
245:
246: /* Get type */
247: for (;;) {
248: switch (bput(bget())) {
249: case DT_NONE:
250: case DT_CHAR:
251: case DT_UCHAR:
252: case DT_SHORT:
253: case DT_USHORT:
254: case DT_INT:
255: case DT_UINT:
256: case DT_LONG:
257: case DT_ULONG:
258: case DT_FLOAT:
259: case DT_DOUBLE:
260: case DT_VOID:
261: iput(iget());
262: break;
263: case DT_STRUCT:
264: case DT_UNION:
265: case DT_ENUM:
266: case DD_PTR:
267: case DD_FUNC:
268: case DD_ARRAY:
269: iput(iget());
270: continue;
271: break;
272: case DX_MEMBS:
273: bput(n = iget());
274: for ( ; n > 0; n-=1) {
275: outdlab(1, bget());
276: }
277: break;
278: case DX_NAME:
279: iget();
280: sget(id, NCSYMB);
281: sput(id);
282: break;
283: default:
284: cbotch("outdlab: %d", n);
285: }
286: break;
287: }
288: }
289:
290: /*
291: * Output a debug line record.
292: */
293: outdlin(op)
294: {
295: bput(TDLAB);
296: bput(DC_LINE);
297: iput(line);
298: bput(op);
299: bput(0);
300: bput(DT_NONE);
301: iput(0);
302: }
303:
304: /*
305: * Output a debug relocation record.
306: */
307: outdloc(n)
308: {
309: bput(TDLOC);
310: iput(n);
311: }
312:
313: /*
314: * Abort illegal output.
315: * reloc.h doesn't handle 8087 or Large model.
316: */
317: outbad()
318: {
319: cbotch("bad temp file object");
320: }
321:
322: /*
323: * Output a 1 word object containing
324: * the base address of the current code
325: * segment.
326: */
327: outcb()
328: {
329: return (outbad());
330: bput(TCODE);
331: dot += 2;
332: }
333:
334: /*
335: * Output a 1 word object containing
336: * the base address of the current data
337: * segment.
338: */
339: outdb()
340: {
341: return (outbad());
342: bput(TDATA);
343: dot += 2;
344: }
345:
346: /*
347: * Output a 1 word object containing
348: * the base address of the external symbol
349: * pointed to by `sp'.
350: */
351: outsb(sp)
352: SYM *sp;
353: {
354: return (outbad());
355: bput(TBASE);
356: pput(sp);
357: dot += 2;
358: }
359:
360: /*
361: * Initialize the code writer.
362: * This routine is called before anything is written to the scratch file.
363: * A no op on coherent reloc.h format.
364: */
365: outinit()
366: {
367: }
368:
369: /*
370: * Finish off the code writer.
371: * This routine is called just before the scratch file is closed.
372: * Write either the "end" to the output file
373: * if generating assembler,
374: * or a "TEND" code to stop the
375: * "copycode" routine if writing binary.
376: */
377: outdone()
378: {
379: register SYM *sp;
380: register int i;
381:
382: if (isvariant(VASM)) {
383: return;
384: }
385:
386: /*
387: * Assign refnums to symbols.
388: * And make dlabel items for internally generated symbols.
389: */
390: for (refnum = i = 0; i < NSHASH; i++) {
391: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) {
392: if ((sp->s_flag&S_GBL) != 0
393: || (sp->s_flag&S_DEF) == 0) {
394: if ((sp->s_flag&S_LABNO) == 0)
395: sp->s_ref = refnum++;
396: if ((sp->s_flag&S_PUT) == 0) {
397: bput(TDLAB);
398: bput(DC_GREF);
399: iput(0);
400: sput(sp->s_id);
401: bput(DT_NONE);
402: iput(0);
403: }
404: }
405: }
406: }
407:
408: bput(TEND);
409: }
410:
411: /*
412: * Copy back.
413: * Figure out the sizes and final values
414: * of everything. Copy the code from the scratch
415: * file back to the output file.
416: */
417: copycode()
418: {
419: int op, nd, nr;
420: ADDRESS data;
421: long addr;
422: fsize_t size, symsize;
423: unsigned char reltype, segtype;
424:
425: SCODE_len = seg[SCODE].s_dot;
426:
427: /*
428: * Initialize output.
429: */
430: oheader(0);
431:
432: /*
433: * Copy out code.
434: */
435: dotseg = SCODE;
436: dot = 0;
437: while ((op=bget()) != TEND) {
438: switch (op & TTYPE) {
439:
440: case TENTER:
441: oenter(bget());
442: continue;
443:
444: case TBYTE:
445: nd = 1;
446: reltype = B_0;
447: data = bget();
448: break;
449:
450: case TWORD:
451: nd = 2;
452: reltype = B_01;
453: data = iget();
454: break;
455:
456: #ifdef TLONG
457: case TLONG:
458: nd = 4;
459: reltype = B_0123;
460: data = lget();
461: break;
462: #endif
463:
464: case TDLAB:
465: getdlab();
466: continue;
467:
468: case TDLOC:
469: getdloc();
470: continue;
471:
472: default:
473: cbotch("copycode: op=%d", op);
474:
475: }
476:
477: switch (Tflag(op)) {
478:
479: case 0: /* Absolute */
480: nr = 0;
481: break;
482:
483: case Tflag(TPCR|TSYM): /* Symbol based pc relative */
484: data -= dot+nd;
485: /* Fall through */
486:
487: case Tflag(TSYM): /* Symbol based */
488: {
489: register SYM *sp;
490:
491: sp = pget();
492: if ((sp->s_flag&S_DEF) != 0) {
493: nr = 6;
494: segtype = segindex[sp->s_seg];
495: data += sp->s_value;
496: } else {
497: nr = 10;
498: segtype = SYMBOLS;
499: addr = sp->s_ref;
500: }
501: if ((op&TPCR) != 0)
502: segtype |= PCREL;
503: break;
504: }
505:
506: case Tflag(TPCR): /* Absolute pc relative */
507: data -= dot+nd;
508: segtype = ABSLUTE|PCREL;
509: nr = 10;
510: addr = 0;
511: break;
512:
513: default:
514: cbotch("copycode: flags=%o", op);
515: }
516:
517: /*
518: * Write the current record.
519: */
520: enuf(nd, nr);
521: if (nr != 0) {
522: rbbuf(reltype);
523: rbbuf(segtype);
524: rlbuf((long) dot);
525: if (nr == 10)
526: rlbuf(addr);
527: }
528: do {
529: bbuf((int) data);
530: data >>= 8;
531: } while (--nd > 0);
532: }
533:
534: if (isvariant(VLINES))
535: outbrace('}');
536: if (notvariant(VLIB))
537: dump(); /* Dump the typedefs */
538:
539: /*
540: * Flush buffers.
541: */
542: notenuf();
543:
544: /*
545: * Write symbol table.
546: */
547: summseg.seg_off[SYMBOLS] = ftell(ofp);
548: segtype = SYMBOLS;
549: bput(segtype);
550: size = symsize;
551: cansize(size);
552: owrite(&size, sizeof(size));
553: addr = refnum;
554: canuaddr(addr);
555: owrite(&addr, sizeof(addr));
556: oglobals();
557: symsize = ftell(ofp) - summseg.seg_off[SYMBOLS] - sizeof(fsize_t) - 1;
558:
559: /*
560: * Put end marker.
561: */
562: segtype = LASTSEG;
563: bput(segtype);
564:
565: /*
566: * Now go back and patch the remaining holes.
567: */
568: fseek(ofp, (fsize_t)0, 0);
569: oheader(1);
570:
571: /*
572: * Symbol segment size and count.
573: */
574: fseek(ofp, summseg.seg_off[SYMBOLS]+1, 0);
575: size = symsize;
576: cansize(size);
577: owrite(&size, sizeof(size));
578: addr = refnum;
579: canuaddr(addr);
580: owrite(&addr, sizeof(addr));
581: }
582:
583: /*
584: * Switch segments.
585: */
586: oenter(newseg)
587: register int newseg;
588: {
589: notenuf();
590: if (dotseg != SSYM)
591: seg[dotseg].s_dot = dot;
592: dotseg = newseg;
593: if (dotseg != SSYM)
594: dot = seg[dotseg].s_dot;
595: else
596: dot = 0;
597: }
598:
599: /*
600: * This routine checks to see if
601: * there is enough room in the text and relocation
602: * buffers to hold `nt' bytes of text and `nr' bytes of
603: * relocation.
604: */
605: enuf(nt, nr)
606: {
607: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL])
608: notenuf();
609: }
610:
611: /*
612: * Flush buffers.
613: */
614: notenuf()
615: {
616: register n;
617: unsigned char segtype;
618: fsize_t size;
619:
620: if ((n=txtp-txt) != 0) {
621: if (dotseg != SSYM) {
622: segtype = segindex[dotseg];
623: bput(segtype);
624: size = n;
625: cansize(size);
626: owrite(&size, sizeof(size));
627: }
628: owrite(txt, n);
629: if ((n=relp-rel) != 0) {
630: segtype = RELOCN;
631: bput(segtype);
632: size = n;
633: cansize(size);
634: owrite(&size, sizeof(size));
635: owrite(rel, n);
636: relp = rel;
637: }
638: }
639: txtp = txt;
640: }
641:
642: /*
643: * Write a byte or long to text or relocation buffers
644: * in canonical ordering.
645: */
646: bbuf(b)
647: {
648: *txtp++ = b;
649: dot += 1;
650: }
651:
652: lbuf(l)
653: long l;
654: {
655: *txtp++ = l >> 16;
656: *txtp++ = l >> 24;
657: *txtp++ = l;
658: *txtp++ = l >> 8;
659: dot += 4;
660: }
661:
662: rbbuf(b)
663: {
664: *relp++ = b;
665: }
666:
667: rlbuf(l)
668: long l;
669: {
670: *relp++ = l >> 16;
671: *relp++ = l >> 24;
672: *relp++ = l;
673: *relp++ = l >> 8;
674: }
675:
676: /*
677: * Write a block of bytes to the output file.
678: */
679: owrite(p, n)
680: register char *p;
681: register int n;
682: {
683: while (--n >= 0)
684: bput(*p++);
685: }
686:
687: /*
688: * Write the header and summary segment.
689: * Summary is complete on second call only.
690: */
691: oheader(n)
692: {
693: fsize_t offs;
694: register int i;
695: register struct seg *segp;
696:
697: /*
698: * Write header.
699: */
700: owrite(&objhdr, sizeof(objhdr));
701:
702: /*
703: * Copy segment sizes into summary segment.
704: */
705: for (segp = &seg[i=0]; i < NSEG; segp++, i++) {
706: if (segindex[i] < 0 || i == SSYM) continue;
707: offs = segp->s_dot;
708: if (i != SDBG)
709: offs = locrup(offs);
710: if (n == 0 || i >= SDBG)
711: summseg.seg_off[segindex[i]] += offs;
712: segp->s_dot = 0;
713: }
714: /*
715: * Write summary segment.
716: */
717: bput(summseg.seg_type);
718: offs = summseg.seg_size;
719: cansize(offs);
720: owrite(&offs, sizeof(offs));
721: for (i=0; i<SUMMARY; i+=1) {
722: offs = summseg.seg_off[i];
723: cansize(offs);
724: owrite(&offs, sizeof(offs));
725: }
726: }
727:
728: /*
729: * Structure to contain debug items on this pass.
730: */
731: struct dbgt {
732: struct dbgt *d_dp; /* Link */
733: int d_ref; /* Index number */
734: unsigned char d_class; /* Storage class */
735: unsigned char d_flag; /* Flags */
736: unsigned char d_level; /* Bracket level */
737: unsigned char d_seg; /* Segment */
738: ADDRESS d_value; /* Offset in segment */
739: int d_size; /* Size of d_data */
740: char d_data[]; /* Name and type */
741: };
742: #define D_GBL 1
743: #define D_LCL 2
744: #define D_TAG 4
745: #define D_NAM 8
746: #define D_LAB 16
747: #define D_ENU 32
748:
749: struct dbgt *newdbgt();
750: struct dbgt *getdbgt();
751: struct dbgt *dbase;
752: struct dbgt *dnext;
753: char *getmembs();
754:
755: /*
756: * Read debug table item(s) into memory.
757: */
758: getdlab()
759: {
760: register struct dbgt *dp;
761: static int refnum = 0;
762:
763: dp = getdbgt();
764:
765: /* This should be done in cc0 */
766:
767: if (isvariant(VLIB)) {
768: switch (dp->d_class) {
769: case DC_TYPE:
770: case DC_STAG:
771: case DC_UTAG:
772: case DC_ETAG:
773: return;
774: }
775: }
776: if (dp->d_class == DC_LINE || dp->d_class == DC_LAB)
777: dp->d_ref = refnum;
778:
779: refnum += 1;
780: if (dbase == NULL)
781: dbase = dp;
782: if (dnext != NULL)
783: dnext->d_dp = dp;
784: dbrpt("enter", dp);
785: while (dp->d_dp != NULL) {
786: dp = dp->d_dp;
787: dbrpt("enter", dp);
788: }
789: dnext = dp;
790: if (dp->d_class == DC_FILE)
791: outbrace('{');
792: }
793:
794: /*
795: * Read a debug relocation item and patch current `dot'
796: * into the appropriate debug/symbol table item.
797: * If the debug item is '}' and level 2, then dump the batch of locals.
798: * If the debug item is '}' and level 1, then dump the type definitions.
799: */
800: getdloc()
801: {
802: register struct dbgt *dp;
803: register int ref;
804:
805: ref = iget();
806: for (dp = dbase; ; dp = dp->d_dp) {
807: if (dp == NULL)
808: cbotch("getdloc: %d", ref);
809: if ((dp->d_flag&D_GBL) != 0)
810: continue;
811: if (dp->d_ref == ref)
812: break;
813: }
814: dp->d_seg = segindex[dotseg];
815: dp->d_value = dot;
816:
817: dbrpt("reloc", dp);
818: if (dp->d_data[0] == '}' && dp->d_level <= 2) {
819: outbrace('}');
820: level--;
821: dump();
822: }
823: }
824:
825: /*
826: * Dump the locals and type definitions
827: */
828:
829: dump()
830: {
831: register struct dbgt *dp, **dpp;
832: int saveseg;
833:
834: if ((saveseg = dotseg) != SDBG)
835: oenter(SDBG);
836: dpp = &dbase;
837: dnext = NULL;
838: while ((dp = *dpp) != NULL) {
839: if ((dp->d_flag&D_LCL) != 0) {
840: dbrpt("write", dp);
841: osymbol(dp, -1);
842: dp->d_flag &= ~D_LCL;
843: }
844: if ((dp->d_flag&D_GBL) == 0) {
845: dbrpt("free", dp);
846: *dpp = dp->d_dp;
847: free(dp);
848: } else {
849: dbrpt("save", dp);
850: dnext = dp;
851: dpp = &dp->d_dp;
852: }
853: }
854: if (saveseg != SDBG)
855: oenter(saveseg);
856: }
857:
858: /*
859: * Write out global symbol definitions and references.
860: */
861: oglobals()
862: {
863: register struct dbgt *dp, *dp1;
864: extern int refnum;
865:
866: oenter(SSYM);
867: for (dp = dbase; dp != NULL; dp = dp1) {
868: dp1 = dp->d_dp;
869: dbrpt("write", dp);
870: if (dp->d_seg == TYPESYM || dp->d_seg == ABSLUTE)
871: osymbol(dp, refnum++);
872: else
873: osymbol(dp, dp->d_ref);
874: dbrpt("free", dp);
875: free(dp);
876: }
877: notenuf();
878: }
879:
880: /*
881: * Write out a symbol to the symbol or debug table.
882: * Debug table symbols have negative refnums,
883: * and may require relocation.
884: */
885: osymbol(dp, refnum)
886: register struct dbgt *dp;
887: {
888: register char *cp;
889: unsigned char segtype;
890: uaddr_t segaddr;
891: int nd, nr;
892:
893: /* Write scope/refnum or seg/value+relocation expression */
894: nd = 5 + dp->d_size;
895: nr = 0;
896: if (refnum >= 0) {
897: if (dp->d_seg == ABSLUTE) {
898: segtype = MDSCOPE;
899: nd += 5;
900: } else if (dp->d_seg != LASTSEG) {
901: segtype = LDSCOPE;
902: nd += 5;
903: } else
904: segtype = RFSCOPE;
905: segaddr = refnum;
906: } else {
907: segtype = dp->d_seg;
908: segaddr = dp->d_value;
909: if (segtype < SUMMARY
910: && segtype != TYPESYM
911: && segtype != ABSLUTE)
912: nr = 6;
913: }
914: enuf(nd, nr);
915: bbuf(segtype);
916: if (nr != 0) {
917: rbbuf(B_2301);
918: rbbuf(dp->d_seg);
919: rlbuf((long) dot);
920: }
921: lbuf(segaddr);
922:
923: /* Write name */
924: cp = dp->d_data;
925: nd = dp->d_size;
926: do {
927: bbuf(*cp);
928: nd -= 1;
929: } while (*cp++);
930:
931: /* Write seg/value expression */
932: if (refnum >= 0 && (segtype == MDSCOPE || segtype == LDSCOPE)) {
933: bbuf(dp->d_seg);
934: lbuf((long) dp->d_value);
935: }
936:
937: /* Type */
938: while (--nd >= 0)
939: bbuf(*cp++);
940: }
941:
942: /*
943: * Read in debug items translating into loader type syntax.
944: * Member definitions are fetched recursively.
945: * If a tag or type definition, the member definitions are appended to the
946: * node surrounded by "{" and "}" nodes.
947: * If not a tag definition, the member definitions are discarded.
948: * In either case, the member types are appended to the type of the
949: * parent node.
950: */
951: #define DSZ 512
952: struct dbgt *
953: getdbgt()
954: {
955: register int n;
956: register char *dptr;
957: struct dbgt d;
958: char data[DSZ];
959: int value, width, offs;
960: int typet, subt, membs;
961: char *sdp;
962:
963: d.d_dp = NULL;
964: d.d_ref = -1;
965: d.d_flag = D_LCL;
966: d.d_level = level;
967: d.d_seg = LASTSEG;
968: d.d_value = 0;
969: d.d_size = 0;
970: width = membs = 0;
971:
972: /*
973: * Loop to read entire record:
974: * class, optional value, name, type.
975: */
976: dptr = data;
977: for (typet = 0; ; typet += 1) {
978:
979: if (dptr >= data+DSZ) {
980: dbrpt("1", &d);
981: cbotch("getdbgt buffer");
982: }
983:
984: n = bget();
985: if (n < DX_MEMBS)
986: value = iget() * NBPBYTE;
987: else if (n < DC_SEX)
988: ;
989: else {
990: dline = iget();
991: if (n < DC_AUTO)
992: ;
993: else if (n < DC_MOS)
994: value = iget();
995: else {
996: width = bget();
997: offs = bget();
998: value = iget();
999: }
1000: }
1001: subt = 0;
1002:
1003: switch (n) {
1004:
1005: /*
1006: * Classes: fetch values and set flags.
1007: */
1008: case DC_SEX:
1009: d.d_flag |= D_NAM;
1010: goto setclass;
1011:
1012: case DC_GDEF:
1013: case DC_GREF:
1014: d.d_flag = D_GBL|D_NAM;
1015: goto setclass;
1016:
1017: case DC_ETAG:
1018: d.d_flag |= D_ENU;
1019: strcpy(dptr, "enum ");
1020: dptr += 5;
1021: goto tag;
1022: case DC_STAG:
1023: strcpy(dptr, "struct ");
1024: dptr += 7;
1025: goto tag;
1026: case DC_UTAG:
1027: strcpy(dptr, "union ");
1028: dptr += 6;
1029: case DC_TYPE:
1030: tag:
1031: d.d_flag = (level == 0) ? D_TAG|D_GBL : D_TAG|D_LCL;
1032: d.d_seg = TYPESYM;
1033: goto setclass;
1034:
1035: case DC_FILE:
1036: d.d_seg = PURCODE;
1037: goto setclass;
1038:
1039: case DC_AUTO:
1040: d.d_seg = L_STACK;
1041: d.d_value = value;
1042: goto setclass;
1043:
1044: case DC_SIN:
1045: d.d_flag |= D_LAB;
1046: goto setclass;
1047:
1048: case DC_REG:
1049: d.d_seg = L_REG;
1050: d.d_value = value;
1051: goto setclass;
1052:
1053: case DC_PREG:
1054: if (level == 0) {
1055: level++;
1056: outbrace('{');
1057: }
1058: d.d_seg = L_REG;
1059: d.d_value = value;
1060: goto setclass;
1061:
1062: case DC_MOE:
1063: d.d_seg = ABSLUTE;
1064: d.d_value = value;
1065: goto setclass;
1066:
1067: case DC_PAUTO:
1068: if (level == 0) {
1069: level++;
1070: outbrace('{');
1071: }
1072: d.d_seg = P_STACK;
1073: d.d_value = value;
1074: goto setclass;
1075:
1076: case DC_LAB:
1077: case DC_LINE:
1078: goto setclass;
1079:
1080: case DC_MOS:
1081: case DC_MOU:
1082: d.d_seg = FLD_OFF;
1083: d.d_value = value * NBPBYTE + offs;
1084: goto setclass;
1085:
1086: /*
1087: * Set the class field, read the name;
1088: * Lookup globals and statics.
1089: */
1090: setclass:
1091: d.d_class = n;
1092: while (*dptr++ = bget())
1093: ;
1094: if ((d.d_flag&(D_NAM|D_LAB)) != 0) {
1095: register SYM *sp;
1096:
1097: if ((d.d_flag&D_NAM) != 0)
1098: sp = glookup(data, 0);
1099: else
1100: sp = llookup(value, 0);
1101: if ((sp->s_flag&S_DEF) != 0) {
1102: d.d_seg = segindex[sp->s_seg];
1103: d.d_value = sp->s_value;
1104: #if COMMON
1105: } else if (sp->s_value != 0) {
1106: d.d_seg = BLDATA|Cb;
1107: d.d_value = sp->s_value;
1108: #endif
1109: }
1110: if ((d.d_flag&D_GBL) != 0)
1111: d.d_ref = sp->s_ref;
1112: }
1113: continue;
1114:
1115: /*
1116: * Types: write type and prepare for trailing data.
1117: * For files and lines, write a phony type.
1118: */
1119: case DT_NONE:
1120: if (d.d_class == DC_FILE) {
1121: register char *p;
1122:
1123: *dptr++ = STRINGt;
1124: p = "source file";
1125: while (*dptr++ = *p++)
1126: ;
1127: }
1128: if (d.d_class == DC_LINE) {
1129: *dptr++ = 6; /* Line */
1130: *dptr++ = dline;
1131: *dptr++ = dline >> 8;
1132: *dptr++ = 0; /* Column */
1133: *dptr++ = 0; /* Flag */
1134: *dptr++ = 0; /* Saved instruction */
1135: *dptr++ = 0;
1136: }
1137: break;
1138:
1139: case DT_CHAR:
1140: case DT_SHORT:
1141: case DT_INT:
1142: case DT_LONG:
1143: n = Integer;
1144: goto getwidth;
1145:
1146: case DT_UCHAR:
1147: case DT_USHORT:
1148: case DT_UINT:
1149: case DT_ULONG:
1150: n = Natural;
1151: goto getwidth;
1152:
1153: case DT_FLOAT:
1154: case DT_DOUBLE:
1155: n = Rational;
1156: goto settype;
1157:
1158: case DT_VOID:
1159: n = Void;
1160: goto settype;
1161:
1162: case DT_STRUCT:
1163: membs = n;
1164: n = Record;
1165: sdp = dptr;
1166: goto settype;
1167:
1168: case DT_UNION:
1169: membs = n;
1170: n = Union;
1171: sdp = dptr;
1172: goto settype;
1173:
1174: case DT_ENUM:
1175: d.d_flag |= D_ENU;
1176: membs = n;
1177: n = Natural;
1178: sdp = dptr;
1179: goto settype;
1180:
1181: getwidth:
1182: if (width)
1183: value = width;
1184:
1185: settype:
1186: *dptr++ = 1;
1187: *dptr++ = n;
1188: if (n != Void) {
1189: if (value == 0)
1190: *dptr++ = ANYt;
1191: else if (value <= 0377) {
1192: *dptr++ = 1;
1193: *dptr++ = value;
1194: } else {
1195: *dptr++ = 2;
1196: *dptr++ = value;
1197: *dptr++ = value >> 8;
1198: }
1199: }
1200: if (subt) {
1201: *dptr++ = TYPEt;
1202: continue;
1203: }
1204: if (membs) {
1205: --typet;
1206: continue;
1207: }
1208: break;
1209:
1210: /*
1211: * Dimensions: as for types, but flag for subtypes.
1212: */
1213: case DD_PTR:
1214: n = Pointer;
1215: ++subt;
1216: goto settype;
1217:
1218: case DD_FUNC:
1219: n = Proc;
1220: ++subt;
1221: goto settype;
1222:
1223: case DD_ARRAY:
1224: n = Array;
1225: ++subt;
1226: goto settype;
1227:
1228: /*
1229: * Trailing struct/union/enum data.
1230: */
1231: case DX_NAME:
1232: dptr = sdp;
1233: *dptr++ = STRINGt;
1234: switch (membs) {
1235: case DT_STRUCT:
1236: strcpy(dptr, "struct ");
1237: dptr += 7;
1238: break;
1239: case DT_UNION:
1240: strcpy(dptr, "union ");
1241: dptr += 6;
1242: break;
1243: case DT_ENUM:
1244: strcpy(dptr, "enum ");
1245: dptr += 5;
1246: }
1247: while (*dptr++ = bget())
1248: ;
1249: membs = 0;
1250: break;
1251:
1252: case DX_MEMBS:
1253: level += 1;
1254: dptr = getmembs(&d, data, dptr);
1255: level -= 1;
1256: membs = 0;
1257: break;
1258:
1259: default:
1260: cbotch("getdbgt: %d", n);
1261: }
1262: /*
1263: * Terminate types.
1264: */
1265: if (dptr + typet >= data + DSZ) {
1266: dbrpt("2", &d);
1267: cbotch("getdbgt buffer");
1268: }
1269: while (--typet >= 0)
1270: *dptr++ = 0;
1271: break;
1272: }
1273:
1274: /*
1275: * Check level change.
1276: */
1277: if (data[0] == '{') {
1278: if (level++ == 0) {
1279: d.d_level = level++;
1280: outbrace('{');
1281: }
1282: }
1283: else if (data[0] == '}')
1284: level -= 1;
1285:
1286: /*
1287: * Copy into dynamic storage.
1288: */
1289: d.d_size = dptr - data;
1290: return (newdbgt(&d, data));
1291: }
1292:
1293: /*
1294: * Read a list of members of a union/struct/enum.
1295: * If struct/union, append member types to caller's buffer.
1296: * If making a debug table:
1297: * If struct/union tag definition, bracket member definitions.
1298: * If enum tag, make member type into "enum tag".
1299: */
1300: char *
1301: getmembs(dp0, bb, bp)
1302: struct dbgt *dp0;
1303: char *bb;
1304: register char *bp;
1305: {
1306: int nmembs, n, istag, isenu, isgbl, isdbg;
1307: char *sbp;
1308: register struct dbgt *dp;
1309: struct dbgt **dpp;
1310: register char *p;
1311: static struct dbgt dbrace = {
1312: NULL, /* d_dp */
1313: -1, /* d_ref */
1314: DT_NONE, /* d_class */
1315: D_LCL, /* d_flag */
1316: 0, /* d_level */
1317: TYPESYM, /* d_seg */
1318: 0, /* d_value */
1319: 3 /* d_size */
1320: };
1321:
1322: dp = dp0;
1323: nmembs = bget();
1324: istag = (dp->d_flag&D_TAG) != 0;
1325: isenu = (dp->d_flag&D_ENU) != 0;
1326: isgbl = (dp->d_flag&D_GBL) != 0;
1327: isdbg = (isvariant(VDSYMB) && isvariant(VTYPES)) != 0;
1328: if (isenu) {
1329: sbp = bp;
1330: isenu = strlen(bb) + 1 + 1;
1331: }
1332: if ( ! isenu) {
1333: *bp++ = 1;
1334: *bp++ = nmembs;
1335: }
1336: dpp = &dp->d_dp;
1337: if (istag && isdbg && ! isenu) {
1338: dp = *dpp = newdbgt(&dbrace, "{\0\0");
1339: if (isgbl)
1340: dp->d_flag ^= D_GBL|D_LCL;
1341: dpp = &dp->d_dp;
1342: }
1343: while (--nmembs >= 0) {
1344: dp = *dpp = getdbgt();
1345: if (isgbl)
1346: dp->d_flag ^= D_GBL|D_LCL;
1347: n = dp->d_size;
1348: p = dp->d_data;
1349: if (isenu && istag && isdbg) {
1350: dp->d_size += isenu;
1351: dp = newdbgt(dp, dp->d_data);
1352: bp = dp->d_data;
1353: while (*bp++)
1354: ;
1355: *bp++ = STRINGt;
1356: p = bb;
1357: while (*bp++ = *p++)
1358: ;
1359: *bp++ = 0;
1360: free(*dpp);
1361: *dpp = dp;
1362: bp = sbp;
1363: }
1364: if ( ! isenu) {
1365: do {
1366: --n;
1367: } while (*p++);
1368: *bp++ = TYPEt;
1369: if (bp + n >= bb + DSZ) {
1370: dbrpt("3", dp);
1371: cbotch("getdbgt buffer");
1372: }
1373: do {
1374: *bp++ = *p++;
1375: } while (--n > 0);
1376: }
1377: if (istag && isdbg)
1378: dpp = &dp->d_dp;
1379: else
1380: free(*dpp);
1381: }
1382: if (istag && isdbg && ! isenu) {
1383: dp = *dpp = newdbgt(&dbrace, "}\0\0");
1384: if (isgbl)
1385: dp->d_flag ^= D_GBL|D_LCL;
1386: dpp = &dp->d_dp;
1387: }
1388: *dpp = NULL;
1389: return (bp);
1390: }
1391:
1392: /*
1393: * Output a debug brace
1394: */
1395: outbrace(c)
1396: char c;
1397: {
1398: struct dbgt *dp;
1399:
1400: if ((dp = (struct dbgt *)calloc(1, sizeof(struct dbgt) + 10)) == NULL)
1401: cnomem("outbrace");
1402: dp->d_class = DC_LINE;
1403: dp->d_flag = D_LCL;
1404: dp->d_seg = segindex[SCODE];
1405: dp->d_value = ( dotseg == SCODE ? dot : seg[SCODE].s_dot);
1406: dp->d_size = 10;
1407: dp->d_data[0] = c;
1408: *(dp->d_data + 2) = 6;
1409: *(dp->d_data + 3) = dline;
1410: *(dp->d_data + 4) = dline >> 8;
1411: if (dnext != NULL)
1412: dnext->d_dp = dp;
1413: dnext = dp;
1414: }
1415:
1416: struct dbgt *
1417: newdbgt(dp, cp)
1418: struct dbgt *dp;
1419: register char *cp;
1420: {
1421: register struct dbgt *ndp;
1422: register char *ncp;
1423: register int n;
1424:
1425: n = dp->d_size;
1426: if ((ndp = (struct dbgt *)malloc(sizeof(struct dbgt) + n)) == NULL)
1427: cnomem("newdbgt");
1428: *ndp = *dp;
1429: for (ncp = ndp->d_data; --n >= 0; *ncp++ = *cp++)
1430: ;
1431: return (ndp);
1432: }
1433:
1434: #if !TINY
1435: _dbrpt(p, dp)
1436: char *p;
1437: register struct dbgt *dp;
1438: {
1439: if (xflag > 5) {
1440: printf("%5s: %-10s %2x %2d %2x %2x %2x %04x %2x\n",
1441: p,
1442: dp->d_data,
1443: dp->d_class,
1444: dp->d_ref,
1445: dp->d_flag,
1446: dp->d_level,
1447: dp->d_seg,
1448: dp->d_value,
1449: dp->d_size
1450: );
1451: }
1452: }
1453:
1454: dbtyp(dp)
1455: struct dbgt *dp;
1456: {
1457: register int n;
1458: register char *p;
1459:
1460: if (xflag > 20) {
1461: n = dp->d_size;
1462: p = dp->d_data;
1463: do {
1464: --n;
1465: putchar(*p);
1466: } while (*p++);
1467: while (--n >= 0) {
1468: if (*p == STRINGt) {
1469: putchar(' ');
1470: putchar('"');
1471: ++p;
1472: do {
1473: --n;
1474: } while (putchar(*p++));
1475: putchar('"');
1476: continue;
1477: } else if (*p == TYPEt)
1478: printf(" TYPEt");
1479: else if (*p == ANYt)
1480: printf(" ANYt");
1481: else
1482: printf(" %o", *p&0377);
1483: ++p;
1484: }
1485: putchar('\n');
1486: }
1487: }
1488: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.