|
|
1.1 root 1: /*
2: * The routines in this file make up
3: * a writer for the Coherent style l.out object
4: * file. During code assembly all the bits get
5: * written to a temporary file. At the very end the
6: * bits get copied back to the final object file.
7: * This uses the newest compiler base (the one
8: * that does "readonly" and has the segment names
9: * rearranged).
10: */
11: #ifdef vax
12: #include "INC$LIB:cc2.h"
13: #include "INC$LIB:canon.h"
14: #include "INC$LIB:lout.h"
15: #else
16: #include "cc2.h"
17: #include "canon.h"
18: #include "l.out.h"
19: #endif
20:
21: #define NTXT 256 /* Text buffer size */
22: #define NREL 256 /* Relocation buffer size */
23:
24: /*
25: * Scratch file.
26: */
27: #define TTYPE 07 /* Type */
28: #define TTYPE 07 /* Type */
29: #define TPCR 010 /* PC rel flag, ored in */
30: #define TSYM 020 /* Symbol based flag, ored in */
31: #define T8087 0340 /* 8087 flags */
32:
33: #define TEND 00 /* End marker */
34: #define TENTER 01 /* Enter new area */
35: #define TBYTE 02 /* Byte data */
36: #define TWORD 03 /* Word data */
37: #define TCODE 04 /* Code segment base */
38: #define TDATA 05 /* Data segment base */
39: #define TBASE 06 /* External segment base */
40:
41: #define TWT 0040 /* M:_WT */
42: #define TWST 0100 /* M:_WST */
43: #define TWES 0140 /* M:_WES */
44: #define TWCS 0200 /* M:_WCS */
45: #define TWSS 0240 /* M:_WSS */
46: #define TWDS 0300 /* M:_WDS */
47:
48: struct ldheader ldh; /* Header buffer */
49: long crseek; /* Current relocation seek address */
50: ADDRESS txtla; /* Load address */
51: char txt[NTXT]; /* Text buffer */
52: char rel[NREL]; /* Relocation buffer */
53: char *txtp; /* Text pointer */
54: char *relp; /* Relocation pointer */
55:
56: /*
57: * Convert a C compiler segment into
58: * an "l.out" segment. This is no longer a
59: * one to one mapping.
60: */
61: char segindex[] = {
62: L_SHRI, /* SCODE */
63: L_SHRI, /* SLINK */
64: L_SHRD, /* SPURE */
65: 0, /* SSTRN (Patched) */
66: L_PRVD, /* SDATA */
67: L_BSSD /* SBSS */
68: };
69:
70: /*
71: * Output a segment switch.
72: */
73: outseg(s)
74: {
75: bput(TENTER);
76: bput(s);
77: }
78:
79: /*
80: * Output an absolute byte.
81: */
82: outab(b)
83: {
84: bput(TBYTE);
85: bput(b);
86: ++dot;
87: }
88:
89: /*
90: * Output an absolute word.
91: */
92: outaw(w)
93: {
94: bput(TWORD);
95: iput(w);
96: dot += 2;
97: }
98:
99: /*
100: * Output a full byte.
101: */
102: outxb(sp, b, pcrf)
103: register SYM *sp;
104: {
105: register int opcode;
106:
107: opcode = TBYTE;
108: if (sp != NULL)
109: opcode |= TSYM;
110: if (pcrf)
111: opcode |= TPCR;
112: bput(opcode);
113: bput(b);
114: if (sp != NULL)
115: pput(sp);
116: ++dot;
117: }
118:
119: /*
120: * Output a full word.
121: */
122: outxw(sp, w, pcrf)
123: register SYM *sp;
124: {
125: register int opcode;
126:
127: opcode = TWORD;
128: if (sp != NULL)
129: opcode |= TSYM;
130: if (pcrf)
131: opcode |= TPCR;
132: bput(opcode);
133: iput(w);
134: if (sp != NULL)
135: pput(sp);
136: dot += 2;
137: }
138:
139: /*
140: * Output a 1 word object containing
141: * the base address of the current code
142: * segment.
143: */
144: outcb()
145: {
146: bput(TCODE);
147: dot += 2;
148: }
149:
150: /*
151: * Output a 1 word object containing
152: * the base address of the current data
153: * segment.
154: */
155: outdb()
156: {
157: bput(TDATA);
158: dot += 2;
159: }
160:
161: /*
162: * Output a 1 word object containing
163: * the base address of the external symbol
164: * pointed to by `sp'.
165: */
166: outsb(sp)
167: SYM *sp;
168: {
169: bput(TBASE);
170: pput(sp);
171: dot += 2;
172: }
173:
174: /*
175: * Copy a dlabel record from ifp to nowhere.
176: */
177: outdlab(i, n)
178: int i; /* Indentation */
179: register int n; /* Class initially */
180: {
181: /* Get line number */
182: iget();
183:
184: /* Get value */
185: if (n < DC_AUTO)
186: ;
187: else if (n < DC_MOS)
188: iget();
189: else {
190: bget(); /* Width */
191: bget(); /* Offset */
192: iget(); /* Value */
193: }
194:
195: /* Get name */
196: sget(id, NCSYMB);
197:
198: /* Get type */
199: for (;;) {
200: n = bget();
201: if (n < DC_SEX) {
202: if (n < DX_MEMBS)
203: iget();
204: if (n == DX_MEMBS) {
205: ++i;
206: n = iget();
207: for ( ; n > 0; n-=1) {
208: outdlab(i, bget());
209: }
210: --i;
211: break;
212: } else if (n == DX_NAME) {
213: iget();
214: sget(id, NCSYMB);
215: break;
216: } else if (n < DT_STRUCT)
217: break;
218: } else
219: cbotch("unrecognized type byte: %d", n);
220: }
221:
222: /* Done */
223: }
224:
225: /*
226: * Forget a debug line record.
227: */
228: outdlin(op)
229: {
230: }
231:
232: /*
233: * Forget a debug relocation record.
234: */
235: outdloc(n)
236: {
237: }
238:
239: /*
240: * Initialize the code writer.
241: */
242: outinit()
243: {
244: txtp = &txt[0];
245: relp = &rel[0];
246: }
247:
248: /*
249: * Finish up.
250: */
251: outdone()
252: {
253: if (notvariant(VASM))
254: bput(TEND);
255: }
256:
257: /*
258: * Copy back.
259: * Figure out the sizes and final values
260: * of everything. Copy the code from the scratch
261: * file back to the output file.
262: */
263: copycode()
264: {
265: register SYM *sp;
266: register SEG *segp;
267: register int op;
268: register int data;
269: register ADDRESS mseek;
270: register long dseek;
271: register int nd;
272: register int nr;
273: register int index;
274: register ADDRESS segsize;
275: register ADDRESS auxsize;
276: register ADDRESS reldot;
277: register int refnum;
278: register int i;
279: register int rop;
280: struct ldsym lds;
281:
282: /*
283: * Make sure that the "segindex"
284: * table is set up correctly for the string
285: * mapping, based on the ROM flags.
286: */
287: if (isvariant(VROM))
288: segindex[SSTRN] = L_SHRD;
289: else
290: segindex[SSTRN] = L_PRVD;
291: /*
292: * Sweep through the segment table and
293: * assign the memory and disc seek addresses to each
294: * entry. Two sections (SLINK and SSTRN) are done in
295: * a magic way, because they live in another segment.
296: */
297: mseek = 0;
298: index = 0;
299: dseek = sizeof(ldh);
300: for (segp=&seg[SCODE]; segp<=&seg[SBSS]; ++segp) {
301: if (segp!=&seg[SLINK] && segp!=&seg[SSTRN]) {
302: segp->s_mseek = mseek;
303: segsize = rup(segp->s_dot);
304: mseek += segsize;
305: if (segp != &seg[SBSS]) {
306: segp->s_dseek = dseek;
307: dseek += segsize;
308: }
309: if (segp == &seg[SCODE]) {
310: seg[SLINK].s_mseek = mseek;
311: auxsize = rup(seg[SLINK].s_dot);
312: mseek += auxsize;
313: seg[SLINK].s_dseek = dseek;
314: dseek += auxsize;
315: segsize += auxsize;
316: }
317: if (isvariant(VROM) && segp==&seg[SPURE]
318: || notvariant(VROM) && segp==&seg[SDATA]) {
319: seg[SSTRN].s_mseek = mseek;
320: auxsize = rup(seg[SSTRN].s_dot);
321: mseek += auxsize;
322: seg[SSTRN].s_dseek = dseek;
323: dseek += auxsize;
324: segsize += auxsize;
325: }
326: ldh.l_ssize[segindex[index]] = segsize;
327: }
328: ++index;
329: }
330: /*
331: * Seek to the start of the symbol table and
332: * write out all of the global symbols. All symbols get
333: * relocated to their final values here. Reference numbers
334: * are assigned to every symbol.
335: */
336: fseek(ofp, dseek, 0);
337: ldh.l_ssize[L_SYM] = 0;
338: refnum = 0;
339: for (i=0; i<NSHASH; ++i) {
340: sp = hash2[i];
341: while (sp != NULL) {
342: if ((sp->s_flag&S_DEF) != 0)
343: sp->s_value += seg[sp->s_seg].s_mseek;
344: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) {
345: sp->s_ref = refnum++;
346: ldscopy(lds.ls_id, sp->s_id);
347: lds.ls_type = L_REF;
348: if ((sp->s_flag&S_DEF) != 0)
349: lds.ls_type = segindex[sp->s_seg];
350: lds.ls_type |= L_GLOBAL;
351: lds.ls_addr = sp->s_value;
352: canint(lds.ls_type);
353: canvaddr(lds.ls_addr);
354: owrite((char *) &lds, sizeof(lds));
355: ldh.l_ssize[L_SYM] += sizeof(lds);
356: }
357: sp = sp->s_fp;
358: }
359: }
360: /*
361: * Copy out code.
362: */
363: crseek = ftell(ofp);
364: ldh.l_ssize[L_REL] = 0;
365: for (segp=&seg[SCODE]; segp<=&seg[SBSS]; ++segp)
366: segp->s_dot = 0;
367: dotseg = SCODE;
368: dot = 0;
369: while ((op = bget()) != TEND) {
370: if (op==TCODE || op==TDATA || op==TBASE)
371: cbotch("large item");
372: if ((op&T8087) != 0)
373: cbotch("8087 item");
374: if (op == TENTER) {
375: notenuf();
376: seg[dotseg].s_dot = dot;
377: dotseg = bget();
378: dot = seg[dotseg].s_dot;
379: continue;
380: }
381: if ((op&TTYPE) == TBYTE) {
382: nd = 1;
383: data = bget();
384: } else {
385: nd = 2;
386: data = iget();
387: }
388: if ((op&TPCR) != 0)
389: data -= dot+nd;
390: /*
391: * Absolute.
392: */
393: if ((op&(TSYM|TPCR)) == 0) {
394: enuf(nd, 0);
395: *txtp++ = data;
396: if (nd != 1)
397: *txtp++ = data>>8;
398: dot += nd;
399: continue;
400: }
401: /*
402: * Not symbol based.
403: * Must be absolute and PC rel.
404: */
405: reldot = dot + seg[dotseg].s_mseek;
406: if ((op&TSYM) == 0) {
407: enuf(nd, 3);
408: rop = LR_BYTE|L_ABS|LR_PCR;
409: *txtp++ = data;
410: if (nd != 1) {
411: rop = LR_WORD|L_ABS|LR_PCR;
412: *txtp++ = data>>8;
413: }
414: *relp++ = rop;
415: *relp++ = reldot;
416: *relp++ = reldot>>8;
417: dot += nd;
418: continue;
419: }
420: /*
421: * Symbol based.
422: * Might be PC rel.
423: */
424: nr = 5;
425: sp = pget();
426: if ((sp->s_flag&S_DEF) != 0) {
427: nr = 3;
428: data += sp->s_value;
429: }
430: enuf(nd, nr);
431: rop = LR_BYTE;
432: *txtp++ = data;
433: if (nd != 1) {
434: rop = LR_WORD;
435: *txtp++ = data>>8;
436: }
437: if ((op&TPCR) != 0)
438: rop |= LR_PCR;
439: if (nr == 3)
440: rop |= segindex[sp->s_seg];
441: else
442: rop |= L_SYM;
443: *relp++ = rop;
444: *relp++ = reldot;
445: *relp++ = reldot>>8;
446: if (nr == 5) {
447: *relp++ = sp->s_ref;
448: *relp++ = sp->s_ref>>8;
449: }
450: dot += nd;
451: }
452: /*
453: * Flush buffers.
454: * Write out the l.out header, since we
455: * now know the size of the relocation section.
456: */
457: notenuf();
458: ldh.l_magic = L_MAGIC;
459: canint(ldh.l_magic);
460: ldh.l_flag = 0;
461: canint(ldh.l_flag);
462: ldh.l_machine = M_8086;
463: canint(ldh.l_machine);
464: ldh.l_entry = 0;
465: canvaddr(ldh.l_entry);
466: for (i=L_SHRI; i<=L_REL; ++i)
467: cansize(ldh.l_ssize[i]);
468: fseek(ofp, (long)0, 0);
469: owrite((char *) &ldh, sizeof(ldh));
470: }
471:
472: /*
473: * Copy a NUL terminated name into
474: * a loader symbol. Pad the symbol out with
475: * 0 bytes.
476: */
477: ldscopy(p1, p2)
478: register char *p1;
479: register char *p2;
480: {
481: register int n;
482:
483: n = NCPLN;
484: while (*p2!=0 && n!=0) {
485: *p1++ = *p2++;
486: --n;
487: }
488: while (n != 0) {
489: *p1++ = 0;
490: --n;
491: }
492: }
493:
494: /*
495: * This routine checks to see if
496: * there is enough room in the text and relocation
497: * buffers to hold `nt' bytes of text and `nr' bytes of
498: * relocation.
499: */
500: enuf(nt, nr)
501: {
502: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL])
503: notenuf();
504: if (txtp == txt)
505: txtla = dot;
506: }
507:
508: /*
509: * Flush the text and relocation buffers. Look
510: * at the segment table to figure out the exact location
511: * of the data in the file, and compute the correct seek
512: * address in the image by adding the base address of
513: * the text record "txtla" to that base.
514: */
515: notenuf()
516: {
517: register int n;
518:
519: if ((n=txtp-txt) != 0) {
520: fseek(ofp, txtla+seg[dotseg].s_dseek, 0);
521: owrite(txt, n);
522: if ((n=relp-rel) != 0) {
523: fseek(ofp, crseek, 0);
524: owrite(rel, n);
525: crseek += n;
526: ldh.l_ssize[L_REL] += n;
527: relp = rel;
528: }
529: }
530: txtp = txt;
531: }
532:
533: /*
534: * Write a block of bytes to the output file,
535: * looking at the return status and checking for any
536: * write errors.
537: */
538: owrite(p, n)
539: char *p;
540: {
541: if (fwrite(p, sizeof(char), n, ofp) != n)
542: cfatal("output write error");
543: }
544:
545: /*
546: * Round up a size to the next
547: * even boundry.
548: */
549: rup(a)
550: {
551: return ((a+01)&~01);
552: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.