|
|
1.1 root 1: /*
2: * This file writes writes Intel iAPX-86 OMF with csd debugging information.
3: * Based on outomf.c, but with MWC CSD-format debug info (as in outrel.c)
4: * instead of Intel format.
5: * The 'out...' routines write to a temporary file during code assembly.
6: * At the end of assembly, 'copycode' uses the 'put...' routines
7: * to write the object file.
8: * This is necessary: SEGDEF records must be written before
9: * LEDATA and FIXUPP records, but each SEGDEF includes the size
10: * of the segment in bytes.
11: * However, the size of the DEBUG segment is fixed up ex post facto.
12: */
13:
14: /*
15: * Reference: "8086 Relocatable Object Formats,"
16: * Intel 121748-001 (C) Intel 1981.
17: */
18:
19: #ifdef vax
20: #include "INC$LIB:cc2.h"
21: #include "INC$LIB:debug.h"
22: #else
23: #include "cc2.h"
24: #include "debug.h"
25: #endif
26:
27: #define NTXT 256 /* Text buffer size */
28: #define NREL 256 /* Relocation buffer size */
29:
30: #ifndef __LINE__
31: #define __LINE__ 0
32: #endif
33:
34: #if !TINY
35: #define dbrpt(x,y) _dbrpt(x,y)
36: #else
37: #define dbrpt(x,y) /* _dbrpt(x,y) */
38: #endif
39:
40: /*
41: * Scratch file opcodes.
42: * Flags are or'ed in to TBYTE and TWORD opcodes only.
43: */
44: #define TTYPE 0x07 /* Type */
45: #define TPCR 0x08 /* PC rel flag */
46: #define TSYM 0x10 /* Symbol based flag */
47:
48: #define TEND 0x00 /* End marker */
49: #define TENTER 0x01 /* Enter new area */
50: #define TBYTE 0x02 /* Byte data */
51: #define TWORD 0x03 /* Word data */
52: #define TCODE 0x04 /* Code segment base */
53: #define TDATA 0x05 /* Data segment base */
54: #define TBASE 0x06 /* External segment base */
55: #define TDLAB 0x07 /* Debug label */
56: #define TDLOC 0x08 /* Debug location */
57:
58: #if EMUFIXUPS
59: /*
60: * If EMUFIXUPS is defined at compile time, the generated output writer
61: * targets 8087 instructions with magic "M:..." fixups.
62: * The linker can then create objects which use either 8087 hardware
63: * or software floating point emulation; in the latter case, the
64: * linker changes the 8087 instructions into traps to the emulator.
65: */
66: #define T8087 0xE0 /* 8087 flags */
67: #define TWT 0x20 /* M:_WT */
68: #define TWST 0x40 /* M:_WST */
69: #define TWES 0x60 /* M:_WES */
70: #define TWCS 0x80 /* M:_WCS */
71: #define TWSS 0xA0 /* M:_WSS */
72: #define TWDS 0xC0 /* M:_WDS */
73: #endif
74:
75: /*
76: * OMF types.
77: */
78: #define THEADR 0x80 /* Translator module header */
79: #define COMENT 0x88 /* Comment */
80: #define MODEND 0x8A /* Module end */
81: #define EXTDEF 0x8C /* External definition (reference) */
82: #define TYPDEF 0x8E /* Type definition */
83: #define PUBDEF 0x90 /* Public definition (definition) */
84: #define LNAMES 0x96 /* List of names */
85: #define SEGDEF 0x98 /* Segment definition */
86: #define GRPDEF 0x9A /* Group definition */
87: #define FIXUPP 0x9C /* Fixups */
88: #define LEDATA 0xA0 /* Enumerated data */
89: #define LIDATA 0xA2 /* Iterated data */
90:
91: /*
92: * Some OMF fields and flags.
93: */
94: #define BYTE (0x01<<5) /* Byte alignment */
95: #define PARA (0x03<<5) /* Paragraph alignment */
96: #define BIG 0x02 /* 64k */
97: #define CCON (0x02<<2) /* C field, concatenate */
98: #define CMEM (0x01<<2) /* C field, memory */
99: #define CSTACK (0x05<<2) /* C field, stack */
100:
101: #define LOCAT 0x80 /* Locat flag bit */
102: #define M 0x40 /* M bit; 0=self rel, 1=seg rel */
103: #define LOBYTE (0x00<<2) /* Locat */
104: #define OFFSET (0x01<<2) /* Locat */
105: #define BASE (0x02<<2) /* Locat */
106: #define POINTER (0x03<<2) /* Locat */
107: #define HIBYTE (0x04<<2) /* Locat */
108:
109: #define SECWAY 0x04 /* Secondary way */
110: #define FD8087 0x36 /* FIXDAT for 8087 fixup */
111: #define FSI (0<<4) /* Frame segment index */
112: #define FGI (1<<4) /* Frame group index */
113: #define FEI (2<<4) /* Frame external index */
114: #define FFN (3<<4) /* Frame frame number */
115: #define FLSEG (4<<4) /* Frame of LSEG */
116: #define FTARGET (5<<4) /* Frame of TARGET object */
117: #define FNONE (6<<4) /* No frame */
118: #define TSI 0 /* Target: segment index */
119: #define TGI 1 /* Target: group index */
120: #define TEI 2 /* Target: external index */
121: #define TFN 3 /* Target: frame */
122: #define F 0x80 /* Frame thread used */
123: #define T 0x08 /* Target thread used */
124: #define FT0 0x00 /* 0 */
125: #define FT1 0x10 /* 1 */
126:
127: #define VCSD (isvariant(VTYPES)||isvariant(VDSYMB))
128:
129: /*
130: * Structure to contain debug items on this pass.
131: * Debug items are kept in a linked list rooted at 'dbase',
132: * with 'dnext' pointing at the most recent item.
133: */
134: struct dbgt {
135: struct dbgt *d_dp; /* Link */
136: int d_ref; /* Index number */
137: unsigned char d_class; /* Storage class */
138: unsigned char d_flag; /* Flags */
139: unsigned char d_level; /* Bracket level */
140: unsigned char d_seg; /* Reloc-style segment */
141: unsigned char d_cseg; /* C Segment */
142: ADDRESS d_value; /* Offset in segment */
143: int d_size; /* Size of d_data */
144: char d_data[]; /* Name and type */
145: };
146: /* Flag bits. */
147: #define D_GBL 1
148: #define D_LCL 2
149: #define D_TAG 4
150: #define D_NAM 8
151: #define D_LAB 16
152: #define D_ENU 32
153:
154: /*
155: * Globals for output writer.
156: */
157: static int checksum; /* For putrecord and putbyte */
158: static char txt[NTXT+5]; /* Text buffer */
159: static char rel[NREL]; /* Relocation buffer */
160: static ADDRESS code_size; /* Size of CODE */
161: static ADDRESS data_size; /* Size of DATA */
162: static ADDRESS const_size; /* Size of CONST */
163: static ADDRESS bss_size; /* Size of BSS */
164: static char *txtp = txt; /* Text pointer */
165: static char *relp = rel; /* Relocation pointer */
166: static struct dbgt *dbase; /* Root debug list item */
167: static struct dbgt *dnext; /* Last debug list item */
168: static int level = 0; /* Debug brace level */
169: static int dline = 0; /* Most recent line number entry */
170:
171: #if EMUFIXUPS
172: static int has8087; /* Has 8087 code flag */
173: static SYM *wsp[6]; /* Links to emulator symbols */
174: #endif
175:
176: #if VAXFMT
177: /*
178: * The Intel cross software packs the OMF
179: * data into 512 byte blocks as 510 byte variable length
180: * records, with the last record short.
181: */
182: #define NVDATA 510 /* Blocksize - 2 */
183: static char vaxbuf[NVDATA]; /* Buffer */
184: static char *vaxptr = vaxbuf; /* Pointer */
185: #endif
186:
187: /*
188: * Function declarations.
189: */
190: extern char *calloc();
191: extern long ftell();
192: extern struct dbgt *getdbgt();
193: extern char *getmembs();
194: extern char *malloc();
195: extern struct dbgt *newdbgt();
196: extern long putsegdef();
197: extern char *setindex();
198: extern char *setsymid();
199: extern char *strcpy();
200:
201: /*
202: * These tables are indexed by a compiler segment name (SCODE et al)
203: * to get an OMF segment index.
204: * These tables understand the way the SSTRN segment moves
205: * around when the ROM option is given, and
206: * are dependent on the order of the calls to putsegdef() in copycode().
207: */
208: static char lnonseg[] = {
209: 1, /* SCODE => module_CODE */
210: 1, /* SLINK => module_CODE */
211: 1, /* SPURE => module_CODE */
212: 2, /* SSTRN => module_DATA */
213: 2, /* SDATA => module_DATA */
214: 2 /* SBSS => module_DATA */
215: };
216:
217: static char lromseg[] = {
218: 1, /* SCODE => module_CODE */
219: 1, /* SLINK => module_CODE */
220: 1, /* SPURE => module_CODE */
221: 1, /* SSTRN => module_CODE */
222: 2, /* SDATA => module_DATA */
223: 2 /* SBSS => module_DATA */
224: };
225:
226: static char lramseg[] = {
227: 1, /* SCODE => module_CODE */
228: 1, /* SLINK => module_CODE */
229: 2, /* SPURE => module_DATA */
230: 2, /* SSTRN => module_DATA */
231: 2, /* SDATA => module_DATA */
232: 2 /* SBSS => module_DATA */
233: };
234:
235: static char snonseg[] = {
236: 1, /* SCODE => CODE */
237: 1, /* SLINK => CODE */
238: 2, /* SPURE => CONST */
239: 3, /* SSTRN => DATA */
240: 3, /* SDATA => DATA */
241: 3 /* SBSS => DATA */
242: };
243:
244: static char sromseg[] = {
245: 1, /* SCODE => CODE */
246: 1, /* SLINK => CODE */
247: 2, /* SPURE => CONST */
248: 2, /* SSTRN => CONST */
249: 3, /* SDATA => DATA */
250: 3 /* SDATA => DATA */
251: };
252:
253: static char sramseg[] = {
254: 1, /* SCODE => CODE */
255: 1, /* SLINK => CODE */
256: 3, /* SPURE => DATA */
257: 3, /* SSTRN => DATA */
258: 3, /* SDATA => DATA */
259: 3 /* SDATA => DATA */
260: };
261:
262: /*
263: * Same game, but for group index codes.
264: * This is used only in SMALL model.
265: */
266: static char grpindex[] = {
267: 1, /* SCODE => CGROUP */
268: 1, /* SLINK => CGROUP */
269: 2, /* SPURE => DGROUP */
270: 2, /* SSTRN => DGROUP */
271: 2, /* SDATA => DGROUP */
272: 2 /* SBSS => DGROUP */
273: };
274:
275: /*
276: * Some prefabricated OMF items.
277: * These are just blasted out via calls to putrecord().
278: */
279: static char lthred[] = { 0x40, 1, /* module_CODE */
280: 0x41, 2 }; /* module_DATA */
281: static char gdef1[] = { 7, 0xFF, 1 };
282: static char gdef2[] = { 8, 0xFF, 2, 0xFF, 3, 0xFF, 4, 0xFF, 5 };
283: static char sthred[] = { 0x00, 1, /* Code */
284: 0x01, 2, /* Const */
285: 0x02, 3, /* Data */
286: 0x44, 1, /* Frame -> CGROUP */
287: 0x45, 2 /* Frame -> DGROUP */
288: };
289: static char typdef[] = { 0, 0, 0x80 };
290: static char modend[] = { 0x00 };
291:
292: /*
293: ** First pass routines.
294: ** Output items to the temporary file.
295: */
296: /*
297: * Initialize the code writer.
298: */
299: outinit()
300: {
301: #if MONOLITHIC
302: #if EMUFIXUPS
303: register int i;
304:
305: has8087 = 0;
306: for (i=0; i<6; ++i)
307: wsp[i] = NULL;
308: #endif
309: txtp = &txt[0];
310: relp = &rel[0];
311: dbase = dnext = NULL;
312: #if VAXFMT
313: vaxptr = &vaxbuf[0];
314: #endif
315: #endif
316: }
317:
318: /*
319: * Output a segment switch.
320: */
321: outseg(s)
322: {
323: bput(TENTER);
324: bput(s);
325: }
326:
327: /*
328: * Output an absolute byte.
329: */
330: outab(b)
331: {
332: bput(TBYTE);
333: bput(b);
334: ++dot;
335: }
336:
337: /*
338: * Output an absolute word.
339: */
340: outaw(w)
341: {
342: bput(TWORD);
343: iput(w);
344: dot += 2;
345: }
346:
347: /*
348: * Output a full byte.
349: */
350: outxb(sp, b, pcrf)
351: register SYM *sp;
352: {
353: register opcode;
354:
355: opcode = TBYTE;
356: if (sp != NULL)
357: opcode |= TSYM;
358: if (pcrf)
359: opcode |= TPCR;
360: bput(opcode);
361: bput(b);
362: if (sp != NULL)
363: pput(sp);
364: ++dot;
365: }
366:
367: /*
368: * Output a full word.
369: */
370: outxw(sp, w, pcrf)
371: register SYM *sp;
372: {
373: register opcode;
374:
375: opcode = TWORD;
376: if (sp != NULL)
377: opcode |= TSYM;
378: if (pcrf)
379: opcode |= TPCR;
380: bput(opcode);
381: iput(w);
382: if (sp != NULL)
383: pput(sp);
384: dot += 2;
385: }
386:
387: #if EMUFIXUPS
388: /*
389: * Output a one byte opcode for the 8087.
390: */
391: outfb(b)
392: {
393: has8087 = 1;
394: bput(TBYTE|TWT);
395: bput(b);
396: ++dot;
397: }
398:
399: /*
400: * Output a two byte opcode for the 8087.
401: */
402: outfw(w, prefix)
403: {
404: has8087 = 1;
405: bput(TWORD|((prefix>>3)+TWST));
406: iput(w);
407: dot += 2;
408: }
409: #endif
410:
411: #if 0
412: /*
413: * Because the compiler now generates LARGE model code with links,
414: * the following routines are currently unused.
415: * They are retained for future reference.
416: */
417: /*
418: * Output a 1 word object containing
419: * the base address of the current code segment.
420: */
421: outcb()
422: {
423: bput(TCODE);
424: dot += 2;
425: }
426:
427: /*
428: * Output a 1 word object containing
429: * the base address of the current data segment.
430: */
431: outdb()
432: {
433: bput(TDATA);
434: dot += 2;
435: }
436: #endif
437:
438: /*
439: * Output a 1 word object containing
440: * the base address of the external symbol pointed to by 'sp'.
441: */
442: outsb(sp)
443: SYM *sp;
444: {
445: bput(TBASE);
446: pput(sp);
447: dot += 2;
448: }
449:
450: /*
451: * Copy a dlabel record from ifp to ofp.
452: * Flag the symbol table entry if appropriate.
453: * Recursive for DX_MEMBS member lists.
454: */
455: outdlab(l,class)
456: {
457: register int val;
458: register SYM *sp;
459: int n;
460:
461: if (l == 0)
462: bput(TDLAB);
463: bput(class);
464:
465: /* Get line number. */
466: iput(iget());
467:
468: /* Get value */
469: if (class < DC_AUTO)
470: ;
471: else if (class < DC_MOS)
472: iput(val = iget());
473: else {
474: bput(bget());
475: bput(bget());
476: iput(iget());
477: }
478:
479: /* Get name */
480: sget(id, NCSYMB);
481:
482: /* Check for symbol table entry */
483: if (class==DC_GDEF || class==DC_SEX || class==DC_GREF) {
484: sp = glookup(id, 0);
485: sp->s_flag |= S_PUT;
486: } else if (class==DC_SIN) {
487: sp = llookup(val, 0);
488: sp->s_flag |= S_PUT;
489: }
490:
491: /* Put name */
492: sput(id);
493:
494: /* Get type */
495: for (;;) {
496: switch (bput(bget())) {
497: case DT_NONE:
498: case DT_CHAR:
499: case DT_UCHAR:
500: case DT_SHORT:
501: case DT_USHORT:
502: case DT_INT:
503: case DT_UINT:
504: case DT_LONG:
505: case DT_ULONG:
506: case DT_FLOAT:
507: case DT_DOUBLE:
508: case DT_VOID:
509: iput(iget());
510: break;
511: case DT_STRUCT:
512: case DT_UNION:
513: case DT_ENUM:
514: case DD_PTR:
515: case DD_FUNC:
516: case DD_ARRAY:
517: iput(iget());
518: continue;
519: break;
520: case DX_MEMBS:
521: bput(n = iget());
522: for ( ; n > 0; n-=1) {
523: outdlab(1, bget());
524: }
525: break;
526: case DX_NAME:
527: iget();
528: sget(id, NCSYMB);
529: sput(id);
530: break;
531: default:
532: cbotch("outdlab: %d", n);
533: }
534: break;
535: }
536: }
537:
538: #if 0 /* This routine is apparently unused. */
539: /*
540: * Output a debug line record.
541: */
542: outdlin(op)
543: {
544: bput(TDLAB);
545: bput(DC_LINE);
546: iput(line);
547: bput(op);
548: bput(0);
549: bput(DT_NONE);
550: iput(0);
551: }
552: #endif
553:
554: /*
555: * Output a debug relocation record.
556: * This 'n' is an index into the list of debug records written.
557: */
558: outdloc(n)
559: {
560: bput(TDLOC);
561: iput(n);
562: }
563:
564: /*
565: * Finish up the code.
566: * Some old outrel.c code is retained below for reference.
567: */
568: outdone()
569: {
570: #if 0
571: register SYM *sp;
572: register int i;
573: #endif
574:
575: if (isvariant(VASM))
576: return;
577:
578: #if 0
579: /*
580: * Make dlabel items for internally generated symbols.
581: */
582: for (i = 0; i < NSHASH; i++) {
583: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) {
584: if (((sp->s_flag&S_GBL) != 0 || (sp->s_flag&S_DEF) == 0)
585: && ((sp->s_flag&S_PUT) == 0)) {
586: bput(TDLAB);
587: bput(DC_GREF);
588: iput(0);
589: sput(sp->s_id);
590: bput(DT_NONE);
591: iput(0);
592: }
593: }
594: }
595: #endif
596:
597: #if EMUFIXUPS
598: /*
599: * Put magic names into the symbol table
600: * if any 8087 code was generated.
601: */
602: if (has8087) {
603: wsp[0] = glookup("M:_WT", 0);
604: wsp[1] = glookup("M:_WST", 0);
605: wsp[2] = glookup("M:_WES", 0);
606: wsp[3] = glookup("M:_WCS", 0);
607: wsp[4] = glookup("M:_WSS", 0);
608: wsp[5] = glookup("M:_WDS", 0);
609: }
610: #endif
611: bput(TEND);
612: }
613:
614: /*
615: ** Second pass routines.
616: ** Read the temporary file and write the output.
617: */
618: /*
619: * Finish up.
620: * Figure out the sizes and final values of everything.
621: * Copy the code from the scratch file back to the output file.
622: */
623: copycode()
624: {
625: register int op;
626: register SYM *sp;
627: register int i;
628: register ADDRESS v;
629: int fixup;
630: int nd;
631: int nr;
632: int data;
633: char coment[30];
634: long debugdef;
635:
636: /*
637: * Assign base addresses to the compiler's logical segments, based on
638: * the compilation model and the settings of the VROM and VRAM flags.
639: */
640: seg[SCODE].s_mseek = 0;
641: v = rup(seg[SCODE].s_dot);
642: seg[SLINK].s_mseek = v;
643: v += rup(seg[SLINK].s_dot);
644: if ((isvariant(VSMALL)) || (isvariant(VRAM))) {
645: code_size = v;
646: v = 0;
647: }
648: seg[SPURE].s_mseek = v;
649: v += rup(seg[SPURE].s_dot);
650: if (notvariant(VROM) && notvariant(VRAM)) {
651: if (isvariant(VSMALL))
652: const_size = v;
653: else
654: code_size = v;
655: v = 0;
656: }
657: seg[SSTRN].s_mseek = v;
658: v += rup(seg[SSTRN].s_dot);
659: if (isvariant(VROM)) {
660: if (isvariant(VSMALL))
661: const_size = v;
662: else
663: code_size = v;
664: v = 0;
665: }
666: seg[SDATA].s_mseek = v;
667: v += rup(seg[SDATA].s_dot);
668: seg[SBSS].s_mseek = v;
669: bss_size = rup(seg[SBSS].s_dot);
670: data_size = v + bss_size;
671:
672: /*
673: * Put out the preamble.
674: */
675: puttheadr(); /* THEADR */
676: coment[0] = coment[1] = '\0';
677: sprintf(&coment[2], "%s %s %s %s",
678: #ifdef vax
679: "VAX",
680: #else
681: #ifdef UDI
682: "UDI",
683: #else
684: #ifdef MSDOS
685: "MS-DOS",
686: #else
687: "COHERENT",
688: #endif
689: #endif
690: #endif
691: "MWC86", VERSMWC,
692: (isvariant(VSMALL)) ? "SMALL" : "LARGE");
693: putrecord(COMENT, coment, strlen(&coment[2])+2); /* COMENT */
694: putlnames(); /* LNAMES */
695: if (isvariant(VLARGE)) {
696: putsegdef(PARA|CCON, code_size, 2, 4); /* [1] */
697: putsegdef(PARA|CCON, data_size, 3, 5); /* [2] */
698: if (VCSD)
699: debugdef = putsegdef(BYTE|CCON, 0, 7, 6); /* [3] */
700: } else {
701: putsegdef(BYTE|CCON, code_size, 2, 2); /* [1] */
702: putsegdef(BYTE|CCON, const_size, 4, 4); /* [2] */
703: putsegdef(BYTE|CCON, data_size, 3, 3); /* [3] */
704: putsegdef(PARA|CSTACK, 0, 5, 5); /* [4] */
705: putsegdef(PARA|CMEM, 0, 6, 6); /* [5] */
706: if (VCSD)
707: debugdef = putsegdef(BYTE|CCON, 0, 10, 9); /* [6] */
708: putrecord(GRPDEF, gdef1, sizeof(gdef1)); /* [1] */
709: putrecord(GRPDEF, gdef2, sizeof(gdef2)); /* [2] */
710: }
711: putrecord(TYPDEF, typdef, sizeof(typdef)); /* TYPDEF */
712: if (isvariant(VLARGE))
713: putrecord(FIXUPP, lthred, sizeof(lthred));
714: else
715: putrecord(FIXUPP, sthred, sizeof(sthred)); /* Threads */
716: putsymdef(); /* PUBDEF, EXTDEF */
717:
718: /*
719: * Copy out code.
720: */
721: for (i=0; i<NSEG; ++i)
722: seg[i].s_dot = seg[i].s_mseek;
723: dotseg = SCODE;
724: dot = seg[SCODE].s_dot;
725: while ((op = bget()) != TEND) {
726: switch (op) {
727:
728: case TENTER:
729: notenuf();
730: enter(bget());
731: continue;
732: case TDLAB:
733: getdlab();
734: continue;
735: case TDLOC:
736: getdloc();
737: continue;
738: #if 0
739: /* See comment on outcb()/outdb() above. */
740: case TCODE:
741: case TDATA:
742: if (isvariant(VSMALL))
743: cbotch("code:data");
744: enuf(2, 4);
745: fixup = txtp - (txt+3);
746: *txtp++ = 0;
747: *txtp++ = 0;
748: *relp++ = LOCAT|M|BASE|(fixup>>8);
749: *relp++ = fixup;
750: *relp++ = FTARGET|SECWAY|TSI;
751: *relp++ = (op==TCODE) ? 1 : 2;
752: dot += 2;
753: continue;
754: #endif
755: case TBASE:
756: if (isvariant(VSMALL))
757: cbotch("base");
758: sp = pget();
759: if ((sp->s_flag&S_DEF) != 0) {
760: enuf(2, 4);
761: fixup = txtp - (txt+3);
762: *txtp++ = 0;
763: *txtp++ = 0;
764: *relp++ = LOCAT|M|BASE|(fixup>>8);
765: *relp++ = fixup;
766: *relp++ = FTARGET|SECWAY|TSI;
767: *relp++ = getsegindex(sp->s_seg);
768: dot += 2;
769: continue;
770: }
771: nr = 4;
772: if (sp->s_ref >= 128)
773: ++nr;
774: enuf(2, nr);
775: fixup = txtp - (txt+3);
776: *txtp++ = 0;
777: *txtp++ = 0;
778: *relp++ = LOCAT|M|BASE|(fixup>>8);
779: *relp++ = fixup;
780: *relp++ = FTARGET|SECWAY|TEI;
781: relp = setindex(relp, sp->s_ref);
782: dot += 2;
783: continue;
784: }
785: if ((op&TTYPE) == TBYTE) {
786: nd = 1;
787: data = bget();
788: } else {
789: nd = 2;
790: data = iget();
791: }
792: #if EMUFIXUPS
793: /*
794: * 8087 opcodes.
795: * Apply magic relocation for the emulator.
796: */
797: if ((op&T8087) != 0) {
798: sp = wsp[((op&T8087)-TWT)>>5];
799: nr = 6;
800: if (sp->s_ref >= 128)
801: ++nr;
802: enuf(nd, nr);
803: fixup = txtp - (txt+3);
804: *txtp++ = data;
805: if (nd != 1) {
806: *txtp++ = data >> 8;
807: fixup |= OFFSET << 8; /* Locat */
808: }
809: fixup |= M << 8; /* Seg rel */
810: *relp++ = (fixup>>8) | LOCAT; /* Not thread */
811: *relp++ = fixup;
812: *relp++ = FD8087; /* Symbol based */
813: *relp++ = 0; /* Frame # */
814: *relp++ = 0;
815: relp = setindex(relp, sp->s_ref);
816: dot += nd;
817: continue;
818: }
819: #endif
820: /*
821: * Absolute.
822: */
823: if ((op&(TSYM|TPCR)) == 0) {
824: enuf(nd, 0);
825: *txtp++ = data;
826: if (nd != 1)
827: *txtp++ = data >> 8;
828: dot += nd;
829: continue;
830: }
831: /*
832: * Absolute PC rel.
833: */
834: if ((op&TSYM) == 0) {
835: enuf(nd, 6);
836: fixup = txtp - (txt+3);
837: *txtp++ = 0;
838: if (nd != 1) {
839: *txtp++ = 0;
840: fixup |= OFFSET << 8;
841: }
842: *relp++ = (fixup>>8) | LOCAT; /* Not thread */
843: *relp++ = fixup;
844: *relp++ = FTARGET|TFN; /* Absolute frame */
845: *relp++ = 0; /* Frame number */
846: *relp++ = data; /* Disp */
847: *relp++ = data >> 8;
848: dot += nd;
849: continue;
850: }
851: /*
852: * Symbol based.
853: * I would like to always do this
854: * in the primary way. However, LINK-86
855: * doesn't do 3 byte offsets, so I cannot
856: * do a negative one.
857: */
858: sp = pget();
859: if ((sp->s_flag&S_DEF) != 0) {
860: data += sp->s_value;
861: /* Absolute */
862: if ((op&TPCR)!=0 && sp->s_seg==dotseg) {
863: enuf(nd, 0);
864: data -= dot+nd;
865: *txtp++ = data;
866: if (nd != 1)
867: *txtp++ = data >> 8;
868: dot += nd;
869: continue;
870: }
871: /* Segment relative */
872: enuf(nd, 6);
873: fixup = txtp - (txt+3);
874: *txtp++ = 0;
875: if (nd != 1) {
876: *txtp++ = 0;
877: fixup |= OFFSET << 8; /* Loc */
878: }
879: if ((op&TPCR) == 0)
880: fixup |= M << 8; /* Seg rel */
881: *relp++ = (fixup>>8) | LOCAT; /* Not thread */
882: *relp++ = fixup;
883: fixup = F|FT0|TSI; /* F code, seg ind */
884: if (getsegindex(sp->s_seg) != 1)
885: fixup |= FT1; /* F data */
886: *relp++ = fixup;
887: *relp++ = getsegindex(sp->s_seg);
888: *relp++ = data; /* Disp */
889: *relp++ = data >> 8;
890: dot += nd;
891: continue;
892: }
893: /*
894: * Symbol relative.
895: */
896: nr = 4;
897: if (sp->s_ref >= 128) /* Two byte index */
898: ++nr;
899: enuf(nd, nr);
900: fixup = txtp - (txt+3);
901: *txtp++ = data;
902: if (nd != 1) {
903: *txtp++ = data >> 8;
904: fixup |= OFFSET << 8; /* Loc */
905: }
906: if ((op&TPCR) == 0)
907: fixup |= M << 8; /* Seg rel */
908: *relp++ = LOCAT|(fixup>>8); /* Not THREAD */
909: *relp++ = fixup;
910: *relp++ = FTARGET|SECWAY|TEI; /* Fix dat */
911: relp = setindex(relp, sp->s_ref);
912: dot += nd;
913: }
914: if (isvariant(VLINES))
915: outbrace('}');
916: if (notvariant(VLIB))
917: dump();
918: if (VCSD)
919: oglobals(); /* Dump globals */
920: enter(SDATA); /* flush */
921: /*
922: * If the size of the SBSS segment is nonzero,
923: * use an LIDATA item to get it zeroed when the program is run.
924: */
925: if (bss_size != 0) {
926: txtp = &txt[0];
927: *txtp++ = (isvariant(VSMALL)) ? 3 : 2; /* DATA */
928: *txtp++ = seg[SBSS].s_mseek; /* Offset */
929: *txtp++ = seg[SBSS].s_mseek >> 8;
930: *txtp++ = bss_size; /* Length of loop */
931: *txtp++ = bss_size >> 8;
932: *txtp++ = 0;
933: *txtp++ = 0;
934: *txtp++ = 1;
935: *txtp++ = 0;
936: putrecord(LIDATA, txt, 9); /* LIDATA */
937: }
938: putrecord(MODEND, modend, sizeof(modend)); /* MODEND */
939: #if VAXFMT
940: vaxflush();
941: #endif
942: if (VCSD) {
943: if (fseek(ofp, debugdef, 0) == -1)
944: cbotch("fixsegdef seek failed");
945: if (isvariant(VLARGE))
946: putsegdef(BYTE|CCON, seg[SDBG].s_dot, 7, 6);
947: else
948: putsegdef(BYTE|CCON, seg[SDBG].s_dot, 10, 9);
949: }
950: }
951:
952: /*
953: ** Header writing routines.
954: */
955: /*
956: * Put out a THEADR item.
957: * The name is just the module name that the compiler has been keeping.
958: * It must be mapped into upper case before writing it to the file.
959: */
960: puttheadr()
961: {
962: register char *p1, *p2;
963: register c;
964: char b[40];
965:
966: p1 = module;
967: p2 = &b[0];
968: *p2++ = strlen(p1);
969: while ((c = *p1++) != '\0') {
970: #if 0
971: if (c>='a' && c<='z')
972: c -= 'a'-'A';
973: #endif
974: *p2++ = c;
975: }
976: putrecord(THEADR, b, p2-b);
977: }
978:
979: /*
980: * Write the list of names record.
981: * For SMALL model, write the standard 'lnames' record:
982: * [1] ""
983: * [2] "CODE"
984: * [3] "DATA"
985: * [4] "CONST"
986: * [5] "STACK"
987: * [6] "MEMORY"
988: * [7] "CGROUP"
989: * [8] "DGROUP"
990: * [9] "DEBUG" (if -VCSD)
991: * [10] "module_DEBUG" (if -VCSD)
992: * For LARGE model, the names are:
993: * [1] ""
994: * [2] "module_CODE"
995: * [3] "module_DATA"
996: * [4] "CODE"
997: * [5] "DATA"
998: * [6] "DEBUG" (if -VCSD)
999: * [7] "module_DEBUG" (if -VCSD)
1000: */
1001: putlnames()
1002: {
1003: register char *p1;
1004: char *movelname();
1005: char b[1 + 1+40+5 + 1+40+5 + 1+4 + 1+4 + 1+5 + 1+40+6];
1006:
1007: p1 = &b[0];
1008: *p1++ = 0; /* "" */
1009: if (isvariant(VSMALL)) {
1010: p1 = movelname(p1, "CODE", 0);
1011: p1 = movelname(p1, "DATA", 0);
1012: p1 = movelname(p1, "CONST", 0);
1013: p1 = movelname(p1, "STACK", 0);
1014: p1 = movelname(p1, "MEMORY", 0);
1015: p1 = movelname(p1, "CGROUP", 0);
1016: p1 = movelname(p1, "DGROUP", 0);
1017: } else {
1018: p1 = movelname(p1, "CODE", 1);
1019: p1 = movelname(p1, "DATA", 1);
1020: p1 = movelname(p1, "CODE", 0);
1021: p1 = movelname(p1, "DATA", 0);
1022: }
1023: if (VCSD) {
1024: p1 = movelname(p1, "DEBUG", 0);
1025: p1 = movelname(p1, "DEBUG", 1);
1026: }
1027: putrecord(LNAMES, b, p1-b);
1028: }
1029:
1030: /*
1031: * If flag==0, move p2 to the supplied buffer p1.
1032: * If flag==1, move module_p2 to p1.
1033: * Used by putlnames().
1034: */
1035: char *
1036: movelname(p1, p2, flag)
1037: register char *p1;
1038: char *p2;
1039: {
1040: register char *p3;
1041: register c;
1042:
1043: p3 = module;
1044: if (flag) {
1045: *p1++ = strlen(p3) + 1 + strlen(p2); /* length of "module_p2" */
1046: while ((c = *p3++) != '\0') { /* copy module name */
1047: #if 0
1048: if (c>='a' && c<='z')
1049: c -= 'a'-'A';
1050: #endif
1051: *p1++ = c;
1052: }
1053: *p1++ = '_'; /* append '_' */
1054: } else
1055: *p1++ = strlen(p2);
1056: p3 = p2;
1057: while ((c = *p3++) != '\0') /* copy p2 */
1058: *p1++ = c;
1059: return (p1);
1060: }
1061:
1062: /*
1063: * This routine formats and outputs a SEGDEF item.
1064: * There is no checking for BIG segments (segments that are 64k in size).
1065: * The overlay index points to a null name.
1066: * Return the location of the first byte of the record.
1067: */
1068: long
1069: putsegdef(flag, size, segi, classi)
1070: {
1071: long l;
1072: register char *bp;
1073: char b[6];
1074:
1075: l = ftell(ofp);
1076: bp = &b[0];
1077: *bp++ = flag;
1078: *bp++ = size;
1079: *bp++ = size >> 8;
1080: *bp++ = segi;
1081: *bp++ = classi;
1082: *bp++ = 1;
1083: putrecord(SEGDEF, b, 6);
1084: return(l);
1085: }
1086:
1087: /*
1088: * Sweep through the symbol table:
1089: * 1) Make symbols LSEG relative.
1090: * 2) Assign reference numbers.
1091: * 3) Output EXTDEF or PUBDEF.
1092: */
1093: putsymdef()
1094: {
1095: register SYM *sp;
1096: register int refnum;
1097: register int i;
1098:
1099: refnum = 1;
1100: for (i=0; i<NSHASH; ++i) {
1101: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp ) {
1102: if ((sp->s_flag&S_DEF) != 0)
1103: sp->s_value += seg[sp->s_seg].s_mseek;
1104: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) {
1105: sp->s_ref = 0;
1106: if ((sp->s_flag&S_DEF) != 0) {
1107: putpubdef(sp);
1108: } else {
1109: sp->s_ref = refnum++;
1110: putextdef(sp);
1111: }
1112: }
1113: }
1114: }
1115: }
1116:
1117: /*
1118: * Put out a PUBDEF item for symbol 'sp'.
1119: * All defs are tagged with the group
1120: * so that a FTARGET,EI fixup can determine the correct frame.
1121: */
1122: putpubdef(sp)
1123: register SYM *sp;
1124: {
1125: register char *bp;
1126: char b[1+1+40+2+1];
1127:
1128: bp = &b[0];
1129: *bp++ = getgrpindex(sp->s_seg);
1130: *bp++ = getsegindex(sp->s_seg);
1131: bp = setsymid(bp, sp->s_id);
1132: *bp++ = sp->s_value;
1133: *bp++ = sp->s_value >> 8;
1134: *bp++ = 1;
1135: putrecord(PUBDEF, b, bp-b);
1136: }
1137:
1138: /*
1139: * Put out an EXTDEF item for symbol 'sp'.
1140: */
1141: putextdef(sp)
1142: register SYM *sp;
1143: {
1144: register char *bp;
1145: char b[40+2];
1146:
1147: bp = setsymid(b, sp->s_id);
1148: *bp++ = 1;
1149: putrecord(EXTDEF, b, bp-b);
1150: }
1151:
1152: /*
1153: * Translate compiler segment codes
1154: * to OMF segment index value, using tables.
1155: * The table is selected by the model and the
1156: * setting of the VROM and VRAM variants.
1157: */
1158: getsegindex(s)
1159: register int s;
1160: {
1161: if (s > SBSS) {
1162: if (s == SDBG)
1163: return(isvariant(VSMALL) ? 6 : 3);
1164: else
1165: cbotch("getsegindex, seg=%d", s);
1166: }
1167: if (isvariant(VSMALL))
1168: return( (isvariant(VRAM)) ? sramseg[s]
1169: : (notvariant(VROM)) ? snonseg[s]
1170: : sromseg[s]);
1171: else
1172: return( (isvariant(VRAM)) ? lramseg[s]
1173: : (notvariant(VROM)) ? lnonseg[s]
1174: : lromseg[s]);
1175: }
1176:
1177: /*
1178: * Like getsegindex(), but returns a reloc-type segment name for CSD.
1179: */
1180: segindex(s) register int s;
1181: {
1182: register int seg;
1183:
1184: seg = getsegindex(s); /* Map to output segment */
1185: if (isvariant(VSMALL)) {
1186: if (seg == 1)
1187: return(PURCODE);
1188: else if (seg == 2 || seg == 3)
1189: return(PURDATA);
1190: } else {
1191: if (seg == 1)
1192: return(PURCODE);
1193: else if (seg == 2)
1194: return(PURDATA);
1195: }
1196: cbotch("segindex, s=%x, seg=%x\n", s, seg);
1197: }
1198:
1199: /*
1200: * Translate compiler segment codes
1201: * to OMF group index value, using table and model.
1202: */
1203: getgrpindex(s)
1204: register int s;
1205: {
1206: return (isvariant(VSMALL) ? grpindex[s] : 0);
1207: }
1208:
1209: /*
1210: ** Debug information processors.
1211: */
1212: /*
1213: * Read debug table item(s) into memory.
1214: */
1215: getdlab()
1216: {
1217: register struct dbgt *dp;
1218: static int refnum = 0;
1219:
1220: dp = getdbgt();
1221:
1222: /* This should be done in cc0 */
1223:
1224: if (isvariant(VLIB)) {
1225: switch (dp->d_class) {
1226: case DC_TYPE:
1227: case DC_STAG:
1228: case DC_UTAG:
1229: case DC_ETAG:
1230: return;
1231: }
1232: }
1233: if (dp->d_class == DC_LINE || dp->d_class == DC_LAB)
1234: dp->d_ref = refnum;
1235:
1236: refnum += 1;
1237: if (dbase == NULL)
1238: dbase = dp;
1239: if (dnext != NULL)
1240: dnext->d_dp = dp;
1241: dbrpt("enter", dp);
1242: while (dp->d_dp != NULL) {
1243: dp = dp->d_dp;
1244: dbrpt("enter", dp);
1245: }
1246: dnext = dp;
1247: if (dp->d_class == DC_FILE)
1248: outbrace('{');
1249: }
1250:
1251: /*
1252: * Read in debug items translating into loader type syntax.
1253: * Member definitions are fetched recursively.
1254: * If a tag or type definition, the member definitions are appended to the
1255: * node surrounded by "{" and "}" nodes.
1256: * If not a tag definition, the member definitions are discarded.
1257: * In either case, the member types are appended to the type of the
1258: * parent node.
1259: */
1260: #define DSZ 512
1261: struct dbgt *
1262: getdbgt()
1263: {
1264: register int n;
1265: register char *dptr;
1266: struct dbgt d;
1267: char data[DSZ];
1268: int value, width, offs;
1269: int typet, subt, membs;
1270: char *sdp;
1271:
1272: d.d_dp = NULL;
1273: d.d_ref = -1;
1274: d.d_flag = D_LCL;
1275: d.d_level = level;
1276: d.d_seg = LASTSEG;
1277: d.d_cseg = 0;
1278: d.d_value = 0;
1279: d.d_size = 0;
1280: width = membs = 0;
1281:
1282: /*
1283: * Loop to read entire record:
1284: * class, optional value, name, type.
1285: */
1286: dptr = data;
1287: for (typet = 0; ; typet += 1) {
1288:
1289: if (dptr >= data+DSZ) {
1290: dbrpt("1", &d);
1291: cbotch("getdbgt buffer");
1292: }
1293:
1294: n = bget();
1295: if (n < DX_MEMBS)
1296: value = iget() * NBPBYTE;
1297: else if (n < DC_SEX)
1298: ;
1299: else {
1300: dline = iget();
1301: if (n < DC_AUTO)
1302: ;
1303: else if (n < DC_MOS)
1304: value = iget();
1305: else {
1306: width = bget();
1307: offs = bget();
1308: value = iget();
1309: }
1310: }
1311: subt = 0;
1312:
1313: switch (n) {
1314:
1315: /*
1316: * Classes: fetch values and set flags.
1317: */
1318: case DC_SEX:
1319: d.d_flag |= D_NAM;
1320: goto setclass;
1321:
1322: case DC_GDEF:
1323: case DC_GREF:
1324: d.d_flag = D_GBL|D_NAM;
1325: goto setclass;
1326:
1327: case DC_ETAG:
1328: d.d_flag |= D_ENU;
1329: strcpy(dptr, "enum ");
1330: dptr += 5;
1331: goto tag;
1332: case DC_STAG:
1333: strcpy(dptr, "struct ");
1334: dptr += 7;
1335: goto tag;
1336: case DC_UTAG:
1337: strcpy(dptr, "union ");
1338: dptr += 6;
1339: case DC_TYPE:
1340: tag:
1341: d.d_flag = (level == 0) ? D_TAG|D_GBL
1342: : D_TAG|D_LCL;
1343: d.d_seg = TYPESYM;
1344: goto setclass;
1345:
1346: case DC_FILE:
1347: d.d_seg = PURCODE;
1348: goto setclass;
1349:
1350: case DC_AUTO:
1351: d.d_seg = L_STACK;
1352: d.d_value = value;
1353: goto setclass;
1354:
1355: case DC_SIN:
1356: d.d_flag |= D_LAB;
1357: goto setclass;
1358:
1359: case DC_LAB:
1360: goto setclass;
1361:
1362: case DC_REG:
1363: d.d_seg = L_REG;
1364: d.d_value = value;
1365: goto setclass;
1366:
1367: case DC_PREG:
1368: if (level == 0) {
1369: level++;
1370: outbrace('{');
1371: }
1372: d.d_seg = L_REG;
1373: d.d_value = value;
1374: goto setclass;
1375:
1376: case DC_MOE:
1377: d.d_seg = ABSLUTE;
1378: d.d_value = value;
1379: goto setclass;
1380:
1381: case DC_PAUTO:
1382: if (level == 0) {
1383: level++;
1384: outbrace('{');
1385: }
1386: d.d_seg = P_STACK;
1387: d.d_value = value;
1388: goto setclass;
1389:
1390: case DC_LINE:
1391: goto setclass;
1392:
1393: case DC_MOS:
1394: case DC_MOU:
1395: d.d_seg = FLD_OFF;
1396: d.d_value = value * NBPBYTE + offs;
1397: goto setclass;
1398:
1399: /*
1400: * Set the class field, read the name;
1401: * Lookup globals and statics.
1402: */
1403: setclass:
1404: d.d_class = n;
1405: while (*dptr++ = bget())
1406: ;
1407: if ((d.d_flag&(D_NAM|D_LAB)) != 0) {
1408: register SYM *sp;
1409:
1410: if ((d.d_flag&D_NAM) != 0)
1411: sp = glookup(data, 0);
1412: else
1413: sp = llookup(value, 0);
1414: if ((sp->s_flag&S_DEF) != 0) {
1415: d.d_cseg = sp->s_seg;
1416: d.d_seg = segindex(sp->s_seg);
1417: d.d_value = sp->s_value;
1418: }
1419: #if COMMON
1420: else if (sp->s_value != 0) {
1421: d.d_seg = BLDATA|Cb;
1422: d.d_value = sp->s_value;
1423: }
1424: #endif
1425: if ((d.d_flag&D_GBL) != 0)
1426: d.d_ref = sp->s_ref;
1427: }
1428: continue;
1429:
1430: /*
1431: * Types: write type and prepare for trailing data.
1432: * For files and lines, write a phony type.
1433: */
1434: case DT_NONE:
1435: if (d.d_class == DC_FILE) {
1436: register char *p;
1437:
1438: *dptr++ = STRINGt;
1439: p = "source file";
1440: while (*dptr++ = *p++)
1441: ;
1442: }
1443: if (d.d_class == DC_LINE) {
1444: *dptr++ = 6; /* Line */
1445: *dptr++ = dline;
1446: *dptr++ = dline >> 8;
1447: *dptr++ = 0; /* Column */
1448: *dptr++ = 0; /* Flag */
1449: *dptr++ = 0; /* Saved instruction */
1450: *dptr++ = 0;
1451: }
1452: break;
1453:
1454: case DT_CHAR:
1455: case DT_SHORT:
1456: case DT_INT:
1457: case DT_LONG:
1458: n = Integer;
1459: goto getwidth;
1460:
1461: case DT_UCHAR:
1462: case DT_USHORT:
1463: case DT_UINT:
1464: case DT_ULONG:
1465: n = Natural;
1466: goto getwidth;
1467:
1468: case DT_FLOAT:
1469: case DT_DOUBLE:
1470: n = Rational;
1471: goto settype;
1472:
1473: case DT_VOID:
1474: n = Void;
1475: goto settype;
1476:
1477: case DT_STRUCT:
1478: membs = n;
1479: n = Record;
1480: sdp = dptr;
1481: goto settype;
1482:
1483: case DT_UNION:
1484: membs = n;
1485: n = Union;
1486: sdp = dptr;
1487: goto settype;
1488:
1489: case DT_ENUM:
1490: d.d_flag |= D_ENU;
1491: membs = n;
1492: n = Natural;
1493: sdp = dptr;
1494: goto settype;
1495:
1496: getwidth:
1497: if (width)
1498: value = width;
1499:
1500: settype:
1501: *dptr++ = 1;
1502: *dptr++ = n;
1503: if (n != Void) {
1504: if (value == 0)
1505: *dptr++ = ANYt;
1506: else if (value <= 0377) {
1507: *dptr++ = 1;
1508: *dptr++ = value;
1509: } else {
1510: *dptr++ = 2;
1511: *dptr++ = value;
1512: *dptr++ = value >> 8;
1513: }
1514: }
1515: if (subt) {
1516: *dptr++ = TYPEt;
1517: continue;
1518: }
1519: if (membs) {
1520: --typet;
1521: continue;
1522: }
1523: break;
1524:
1525: /*
1526: * Dimensions: as for types, but flag for subtypes.
1527: */
1528: case DD_PTR:
1529: n = Pointer;
1530: ++subt;
1531: goto settype;
1532:
1533: case DD_FUNC:
1534: n = Proc;
1535: ++subt;
1536: goto settype;
1537:
1538: case DD_ARRAY:
1539: n = Array;
1540: ++subt;
1541: goto settype;
1542:
1543: /*
1544: * Trailing struct/union/enum data.
1545: */
1546: case DX_NAME:
1547: dptr = sdp;
1548: *dptr++ = STRINGt;
1549: switch (membs) {
1550: case DT_STRUCT:
1551: strcpy(dptr, "struct ");
1552: dptr += 7;
1553: break;
1554: case DT_UNION:
1555: strcpy(dptr, "union ");
1556: dptr += 6;
1557: break;
1558: case DT_ENUM:
1559: strcpy(dptr, "enum ");
1560: dptr += 5;
1561: }
1562: while (*dptr++ = bget())
1563: ;
1564: membs = 0;
1565: break;
1566:
1567: case DX_MEMBS:
1568: level += 1;
1569: dptr = getmembs(&d, data, dptr);
1570: level -= 1;
1571: membs = 0;
1572: break;
1573:
1574: default:
1575: cbotch("getdbgt: %d", n);
1576: }
1577: /*
1578: * Terminate types.
1579: */
1580: if (dptr + typet >= data + DSZ) {
1581: dbrpt("2", &d);
1582: cbotch("getdbgt buffer");
1583: }
1584: while (--typet >= 0)
1585: *dptr++ = 0;
1586: break;
1587: }
1588:
1589: /*
1590: * Check level change.
1591: */
1592: if (data[0] == '{') {
1593: if (level++ == 0) {
1594: d.d_level = level++;
1595: outbrace('{');
1596: }
1597: }
1598: else if (data[0] == '}')
1599: level -= 1;
1600:
1601: /*
1602: * Copy into dynamic storage.
1603: */
1604: d.d_size = dptr - data;
1605: return (newdbgt(&d, data));
1606: }
1607:
1608: /*
1609: * Enter a new output segment.
1610: */
1611: enter(newseg)
1612: register int newseg;
1613: {
1614: if (dotseg == newseg)
1615: return; /* already in newseg */
1616: notenuf(); /* flush */
1617: seg[dotseg].s_dot = dot; /* save current dot */
1618: dotseg = newseg; /* reset dotseg */
1619: dot = seg[dotseg].s_dot; /* and dot */
1620: }
1621:
1622: /*
1623: * Read a debug relocation item and patch current 'dot'
1624: * into the appropriate debug/symbol table item.
1625: * If the debug item is '}' and level 2, then dump the batch of locals.
1626: * If the debug item is '}' and level 1, then dump the type definitions.
1627: */
1628: getdloc()
1629: {
1630: register struct dbgt *dp;
1631: register int ref;
1632:
1633: ref = iget();
1634: for (dp = dbase; ; dp = dp->d_dp) {
1635: if (dp == NULL)
1636: cbotch("getdloc: %d", ref);
1637: if ((dp->d_flag&D_GBL) != 0)
1638: continue;
1639: if (dp->d_ref == ref)
1640: break;
1641: }
1642: dp->d_cseg = dotseg;
1643: dp->d_seg = segindex(dotseg);
1644: dp->d_value = dot;
1645:
1646: dbrpt("reloc", dp);
1647: if (dp->d_data[0] == '}' && dp->d_level <= 2) {
1648: outbrace('}');
1649: level--;
1650: dump();
1651: }
1652: }
1653:
1654: /*
1655: * Dump the locals and type definitions.
1656: */
1657: dump()
1658: {
1659: register struct dbgt *dp, **dpp;
1660: int saveseg;
1661:
1662: saveseg = dotseg;
1663: enter(SDBG);
1664: dpp = &dbase;
1665: dnext = NULL;
1666: while ((dp = *dpp) != NULL) {
1667: if ((dp->d_flag&D_LCL) != 0) {
1668: dbrpt("write", dp);
1669: osymbol(dp, -1);
1670: dp->d_flag &= ~D_LCL;
1671: }
1672: if ((dp->d_flag&D_GBL) == 0) {
1673: dbrpt("free", dp);
1674: *dpp = dp->d_dp;
1675: free(dp);
1676: } else {
1677: dbrpt("save", dp);
1678: dnext = dp;
1679: dpp = &dp->d_dp;
1680: }
1681: }
1682: enter(saveseg);
1683: }
1684:
1685: /*
1686: * Write out global symbol definitions and references.
1687: */
1688: oglobals()
1689: {
1690: register struct dbgt *dp, *dp1;
1691:
1692: enter(SDBG);
1693: for (dp = dbase; dp != NULL; dp = dp1) {
1694: dp1 = dp->d_dp;
1695: dbrpt("write", dp);
1696: if (dp->d_seg == TYPESYM || dp->d_seg == ABSLUTE)
1697: osymbol(dp, 0);
1698: else
1699: osymbol(dp, dp->d_ref);
1700: dbrpt("free", dp);
1701: free(dp);
1702: }
1703: notenuf();
1704: }
1705:
1706: /*
1707: * Write out a symbol to the symbol or debug table.
1708: * TYPESYM and ABSLUTE symbols have refnum 0.
1709: * Debug table symbols have negative refnums and may require relocation.
1710: */
1711: osymbol(dp, refnum)
1712: register struct dbgt *dp;
1713: {
1714: register char *cp;
1715: unsigned char seg;
1716: int nd, nr, fixup, fixseg;
1717:
1718: /* Write scope/refnum or seg/value+relocation expression */
1719: seg = dp->d_seg;
1720: nd = 5 + dp->d_size;
1721: nr = 0;
1722: #if 0
1723: printf("osymbol(%s, %x) seg=%x cseg=%x nd=%x\n", dp->d_data, refnum, seg,
1724: dp->d_cseg, nd);
1725: #endif
1726: if (refnum >= 0) {
1727: if (seg == LASTSEG) {
1728: for (cp=dp->d_data; *cp++; )
1729: ; /* skip the name */
1730: seg = (*cp++ == 1 && *cp++ == Proc) ? PURCODE : PURDATA;
1731: fixseg = -1; /* external fixup */
1732: } else
1733: fixseg = getsegindex(dp->d_cseg);
1734: if (seg != TYPESYM && seg != ABSLUTE)
1735: nr = (isvariant(VLARGE)) ? 10 : 6;
1736: } else if (refnum < 0) {
1737: if (seg < SUMMARY && seg != TYPESYM && seg != ABSLUTE) {
1738: nr = (isvariant(VLARGE)) ? 10 : 6;
1739: fixseg = getsegindex(dp->d_cseg);
1740: }
1741: else
1742: fixseg = 1; /* CODE */
1743: }
1744: enuf(nd, nr);
1745: dot += nd; /* bump dot */
1746: *txtp++ = seg; /* reloc-style segment */
1747: if (fixseg == -1) { /* extern fixup */
1748: if (isvariant(VLARGE)) {
1749: fixup = txtp - (txt+3);
1750: *relp++ = LOCAT|M|BASE|(fixup>>8);
1751: *relp++ = fixup;
1752: *relp++ = FTARGET|SECWAY|TEI;
1753: relp = setindex(relp, refnum);
1754: }
1755: *txtp++ = 0;
1756: *txtp++ = 0;
1757: fixup = txtp - (txt+3);
1758: *relp++ = LOCAT|M|OFFSET|(fixup>>8);
1759: *relp++ = fixup;
1760: *relp++ = FTARGET|SECWAY|TEI;
1761: relp = setindex(relp, refnum);
1762: *txtp++ = 0;
1763: *txtp++ = 0;
1764: } else {
1765: if (nr != 0 && isvariant(VLARGE)) { /* segment fixup */
1766: fixup = txtp - (txt+3);
1767: *relp++ = LOCAT|M|BASE|(fixup>>8);
1768: *relp++ = fixup;
1769: *relp++ = FTARGET|SECWAY|TSI;
1770: *relp++ = fixseg;
1771: }
1772: *txtp++ = 0;
1773: *txtp++ = 0; /* segment text */
1774: if (nr != 0) { /* offset text and fixup */
1775: fixup = txtp - (txt+3);
1776: *relp++ = LOCAT|M|OFFSET|(fixup>>8);
1777: *relp++ = fixup;
1778: if (fixseg == 1)
1779: *relp++ = F|FT0|TSI; /* fixup F code, seg index */
1780: else
1781: *relp++ = F|FT1|TSI; /* fixup F data, seg index */
1782: *relp++ = fixseg;
1783: *relp++ = dp->d_value;
1784: *relp++ = dp->d_value >> 8;
1785: *txtp++ = 0;
1786: *txtp++ = 0;
1787: } else {
1788: *txtp++ = dp->d_value;
1789: *txtp++ = dp->d_value >> 8; /* nonrelocated offset */
1790: }
1791: }
1792:
1793: /* Write name */
1794: cp = dp->d_data;
1795: nd = dp->d_size;
1796: do {
1797: *txtp++ = *cp;
1798: --nd;
1799: } while (*cp++);
1800:
1801: /* Type */
1802: while (--nd >= 0)
1803: *txtp++ = *cp++; /* type */
1804: }
1805:
1806: /*
1807: * Read a list of members of a union/struct/enum.
1808: * If struct/union, append member types to caller's buffer.
1809: * If making a debug table:
1810: * If struct/union tag definition, bracket member definitions.
1811: * If enum tag, make member type into "enum tag".
1812: */
1813: char *
1814: getmembs(dp0, bb, bp)
1815: struct dbgt *dp0;
1816: char *bb;
1817: register char *bp;
1818: {
1819: int nmembs, n, istag, isenu, isgbl, isdbg;
1820: char *sbp;
1821: register struct dbgt *dp;
1822: struct dbgt **dpp;
1823: register char *p;
1824: static struct dbgt dbrace = {
1825: NULL, /* d_dp */
1826: -1, /* d_ref */
1827: DT_NONE, /* d_class */
1828: D_LCL, /* d_flag */
1829: 0, /* d_level */
1830: TYPESYM, /* d_seg */
1831: 0, /* d_cseg */
1832: 0, /* d_value */
1833: 3 /* d_size */
1834: };
1835:
1836: dp = dp0;
1837: nmembs = bget();
1838: istag = (dp->d_flag&D_TAG) != 0;
1839: isenu = (dp->d_flag&D_ENU) != 0;
1840: isgbl = (dp->d_flag&D_GBL) != 0;
1841: isdbg = VCSD;
1842: if (isenu) {
1843: sbp = bp;
1844: isenu = strlen(bb) + 1 + 1;
1845: }
1846: if ( ! isenu) {
1847: #if DO_STRUCT_TYPE
1848: /* Note that this blows up for nmembs > 255 anyway */
1849: *bp++ = 1;
1850: *bp++ = nmembs;
1851: #else
1852: *bp++ = 1;
1853: *bp++ = 1;
1854: *bp++ = ANYt;
1855: #endif
1856: dpp = &dp->d_dp;
1857: dp = *dpp = newdbgt(&dbrace, "{\0\0");
1858: if (isgbl)
1859: dp->d_flag ^= D_GBL|D_LCL;
1860: }
1861: dpp = &dp->d_dp;
1862: while (--nmembs >= 0) {
1863: /* Note that dp could be a tagless structure, ie a list */
1864: dp = *dpp = getdbgt();
1865: if (isgbl)
1866: dp->d_flag ^= D_GBL|D_LCL;
1867: n = dp->d_size;
1868: p = dp->d_data;
1869: if (isenu && istag && isdbg) {
1870: /* Enumerators eschew member lists */
1871: dp->d_size += isenu;
1872: dp = newdbgt(dp, dp->d_data);
1873: bp = dp->d_data;
1874: while (*bp++)
1875: ;
1876: *bp++ = STRINGt;
1877: p = bb;
1878: while (*bp++ = *p++)
1879: ;
1880: *bp++ = 0;
1881: free(*dpp);
1882: *dpp = dp;
1883: bp = sbp;
1884: }
1885: #if DO_STRUCT_TYPE
1886: if ( ! isenu) {
1887: do {
1888: --n;
1889: } while (*p++);
1890: *bp++ = TYPEt;
1891: if (bp + n >= bb + DSZ) {
1892: dbrpt("3", dp);
1893: cbotch("getdbgt buffer");
1894: }
1895: do {
1896: *bp++ = *p++;
1897: } while (--n > 0);
1898: }
1899: #endif
1900: if (istag && isdbg)
1901: dpp = &dp->d_dp;
1902: else
1903: free(*dpp);
1904: }
1905: if ( ! isenu) {
1906: dp = *dpp = newdbgt(&dbrace, "}\0\0");
1907: dpp = &dp->d_dp;
1908: if (isgbl)
1909: dp->d_flag ^= D_GBL|D_LCL;
1910: }
1911: *dpp = NULL;
1912: return (bp);
1913: }
1914:
1915: struct dbgt *
1916: newdbgt(dp, cp)
1917: struct dbgt *dp;
1918: register char *cp;
1919: {
1920: register struct dbgt *ndp;
1921: register char *ncp;
1922: register int n;
1923:
1924: n = dp->d_size;
1925: if ((ndp = (struct dbgt *)malloc(sizeof(struct dbgt) + n)) == NULL)
1926: cnomem("newdbgt");
1927: *ndp = *dp;
1928: for (ncp = ndp->d_data; --n >= 0; *ncp++ = *cp++)
1929: ;
1930: return (ndp);
1931: }
1932:
1933: /*
1934: * Output a debug brace.
1935: */
1936: outbrace(c)
1937: int c;
1938: {
1939: struct dbgt *dp;
1940:
1941: if ((dp = (struct dbgt *)calloc(1, sizeof(struct dbgt) + 10)) == NULL)
1942: cnomem("outbrace");
1943: dp->d_class = DC_LINE;
1944: dp->d_flag = D_LCL;
1945: dp->d_seg = segindex(SCODE);
1946: dp->d_value = ( dotseg == SCODE ? dot : seg[SCODE].s_dot);
1947: dp->d_size = 10;
1948: dp->d_data[0] = c;
1949: *(dp->d_data + 2) = 6;
1950: *(dp->d_data + 3) = dline;
1951: *(dp->d_data + 4) = dline >> 8;
1952: if (dnext != NULL)
1953: dnext->d_dp = dp;
1954: dnext = dp;
1955: }
1956:
1957: #if !TINY
1958: _dbrpt(p, dp)
1959: char *p;
1960: register struct dbgt *dp;
1961: {
1962: if (xflag > 5)
1963: printf("%5s: %-10s %2x %2d %2x %2x %2x %2x %04x %2x\n",
1964: p,
1965: dp->d_data,
1966: dp->d_class,
1967: dp->d_ref,
1968: dp->d_flag,
1969: dp->d_level,
1970: dp->d_seg,
1971: dp->d_cseg,
1972: dp->d_value,
1973: dp->d_size
1974: );
1975: }
1976:
1977: #endif
1978:
1979: /*
1980: ** Low level record formatting.
1981: */
1982: /*
1983: * Put OMF index i at cp and return updated cp.
1984: */
1985: char *
1986: setindex(cp, i)
1987: register char *cp;
1988: register unsigned i;
1989: {
1990: if (i >= 128)
1991: *cp++ = (i >> 8) | 0x80;
1992: *cp++ = i;
1993: return (cp);
1994: }
1995:
1996: /*
1997: * This routine takes the name pointed to by 'cp' and
1998: * moves it into an OMF record. The 'bp' argument
1999: * is the OMF buffer pointer. The updated value
2000: * of 'bp' is returned.
2001: */
2002: char *
2003: setsymid(bp, cp)
2004: register char *bp;
2005: register char *cp;
2006: {
2007: register c, n;
2008:
2009: if ((n=strlen(cp)) > 39) {
2010: cwarn("symbol \"%s\" truncated to 39 characters", cp);
2011: n = 39;
2012: }
2013: *bp++ = n;
2014: while (n--) {
2015: #if 0
2016: if ((c = *cp++)>='a' && c<='z')
2017: c -= 'a'-'A';
2018: *bp++ = c;
2019: #else
2020: *bp++ = *cp++;
2021: #endif
2022: }
2023: return (bp);
2024: }
2025:
2026: /*
2027: * Put a record.
2028: * The 'type' argument is the record type.
2029: * The body of the record starts at 'p' and is
2030: * 'n' bytes long. The checksum is added.
2031: */
2032: putrecord(type, p, n)
2033: register char *p;
2034: register n;
2035: {
2036: checksum = 0;
2037: putbyte(type);
2038: putbyte(n+1); /* +1 for the checksum */
2039: putbyte((n+1)>>8);
2040: while(n--)
2041: putbyte(*p++);
2042: putbyte(-checksum);
2043: }
2044:
2045: putbyte(b)
2046: register b;
2047: {
2048: #if VAXFMT
2049: if (vaxptr >= &vaxbuf[NVDATA]) {
2050: vaxflush();
2051: vaxptr = vaxbuf;
2052: }
2053: *vaxptr++ = b;
2054: #else
2055: bput(b);
2056: #endif
2057: checksum += b;
2058: }
2059:
2060: /*
2061: ** Output buffering.
2062: */
2063: /*
2064: * This routine checks to see if
2065: * there is enough room in the text and relocation
2066: * buffers to hold 'nt' bytes of text and 'nr' bytes of
2067: * relocation.
2068: */
2069: enuf(nt, nr)
2070: {
2071: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL])
2072: notenuf();
2073: if (txtp == txt) {
2074: *txtp++ = getsegindex(dotseg);
2075: *txtp++ = dot;
2076: *txtp++ = dot >> 8;
2077: }
2078: }
2079:
2080: /*
2081: * Flush the buffer.
2082: */
2083: notenuf()
2084: {
2085: register n;
2086:
2087: if ((n = txtp-txt) > 3) {
2088: putrecord(LEDATA, txt, n);
2089: if ((n = relp-rel) != 0) {
2090: putrecord(FIXUPP, rel, n);
2091: relp = rel;
2092: }
2093: }
2094: txtp = txt;
2095: }
2096:
2097: /*
2098: * Round up to the next word.
2099: */
2100: rup(a)
2101: ADDRESS a;
2102: {
2103: return ((a+01)&~01);
2104: }
2105:
2106: #if VAXFMT
2107: /*
2108: * Flush out a record on the VAX. The record is a standard,
2109: * RMS variable length record. This routine checks for no bytes
2110: * in the buffer, so it can be unconditionally called at the
2111: * end to flush the buffer out.
2112: * The record is padded out to NVDATA bytes with zeros. This
2113: * only happens on the last block; the data beyond the end
2114: * is zeroed.
2115: */
2116: vaxflush()
2117: {
2118: register int n;
2119:
2120: if ((n = vaxptr-vaxbuf) != 0) {
2121: if (fwrite(vaxbuf, n, 1, ofp) != 1
2122: || fflush(ofp) == EOF)
2123: cfatal("output write error");
2124: }
2125: }
2126: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.