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