|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)rel.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "as.h"
10: #include <a.out.h>
11:
12: struct reloc{ struct relocation_info r; struct sym_bkt *rsymbol; };
13:
14: /* Handle output file processing for b.out files */
15:
16: FILE *tout; /* text portion of output file */
17: FILE *dout; /* data portion of output file */
18: FILE *d1out; /* data portion of output file */
19: FILE *d2out; /* data portion of output file */
20: FILE *rtout; /* text relocation commands */
21: FILE *rdout; /* data relocation commands */
22:
23: long rtsize; /* size of text relocation area */
24: long rdsize; /* size of data relocation area */
25:
26: char *rname = "/tmp/as68XXXXXXXX"; /* name of file for relocation commands */
27:
28: extern int ext_instruction_set; /* = 1 for the 68020 assembler */
29:
30: struct exec filhdr; /* header for a.out files, contains sizes */
31:
32: /* Initialize files for output and write out the header */
33: rel_header()
34: {
35: if ((tout = fopen(rel_name, "w")) == NULL ||
36: (dout = fopen(rel_name, "a")) == NULL ||
37: (d1out = fopen(rel_name, "a")) == NULL ||
38: (d2out = fopen(rel_name, "a")) == NULL)
39: sys_error("open on output file %s failed", rel_name);
40:
41: /* Concat(rname, Source_name, ".tmpr"); */
42: mktemp( rname );
43: if ((rtout = fopen(rname, "w")) == NULL
44: || (rdout = fopen(rname, "a")) == NULL)
45: sys_error("open on output file %s failed", rname);
46: filhdr.a_machtype = (ext_instruction_set ? M_68020 : M_68010);
47: filhdr.a_magic = OMAGIC;
48: filhdr.a_text = tsize;
49: filhdr.a_data = dsize+d1size+d2size;
50: filhdr.a_trsize = rtsize;
51: filhdr.a_drsize = rdsize;
52: filhdr.a_bss = bsize;
53: filhdr.a_entry = 0;
54:
55: fseek(tout, 0L, 0);
56: fwrite(&filhdr, sizeof(filhdr), 1, tout);
57:
58: fseek(tout, (long)(N_TXTOFF(filhdr)), 0); /* seek to start of text */
59: fseek(dout, (long)(N_TXTOFF(filhdr)+tsize), 0);
60: fseek(rdout, rtsize, 0);
61: fseek(d1out, (long)(N_TXTOFF(filhdr)+tsize+dsize), 0);
62: fseek(d2out, (long)(N_TXTOFF(filhdr)+tsize+dsize+d1size), 0);
63: rtsize = 0;
64: rdsize = 0;
65:
66: } /* end Rel_Header * /
67:
68: /*
69: * Fix_Rel - Fix up the object file
70: * For .b files, we have to
71: * 1) append the relocation segments
72: * 2) fix up the rtsize and rdsize in the header
73: * 3) delete the temporary file for relocation commands
74: */
75: fix_rel()
76: {
77: register FILE *fin, *fout;
78: long ortsize;
79: long i;
80: # define FUDGE( x ) ((x)/sizeof(struct reloc))*sizeof(struct relocation_info)
81:
82: ortsize = filhdr.a_trsize;
83: if (ortsize < rtsize ) sys_error("First pass relocation botch\n");
84: filhdr.a_trsize = FUDGE(rtsize);
85: if( rflag ){
86: filhdr.a_trsize += FUDGE(rdsize);
87: filhdr.a_drsize = 0;
88: filhdr.a_text += filhdr.a_data;
89: filhdr.a_data = 0;
90: } else
91: filhdr.a_drsize = FUDGE(rdsize);
92: fclose(rtout);
93: fclose(rdout);
94: if ((fin = fopen(rname, "r")) == NULL)
95: sys_error("cannot reopen relocation file %s", rname);
96:
97: fout = tout;
98:
99: /* first write text relocation commands */
100: fseek(fout, (long)(N_TXTOFF(filhdr)+filhdr.a_text+filhdr.a_data), 0);
101: redosyms();
102: dorseg(fin,fout,rtsize);
103:
104: /* seek to start of data segment relocation commands */
105: fseek(fin, ortsize, 0);
106: dorseg(fin,fout,rdsize);
107: /* Now put the full symbol table out there */
108: filhdr.a_syms = sym_write(fout);
109:
110: /* Now for the string table */
111: i = str_write(fout);
112: /* After the table is written, rewrite the length */
113: fseek(fout,N_STROFF(filhdr),0);
114: fwrite(&i,sizeof(long),1,fout);
115:
116: /* now re-write header */
117: fseek(fout, 0, 0);
118: fwrite(&filhdr, sizeof(filhdr), 1, fout);
119: fclose(fin);
120: unlink(rname);
121: # undef FUDGE
122: } /* Fix_Rel */
123:
124:
125: dorseg(fin,fout,size)
126: register size;
127: FILE *fin,*fout;
128: {
129: struct reloc new;
130: while(size) {
131: size -= sizeof(new);
132: fread(&new,sizeof(new),1,fin);
133: if (new.r.r_extern == 1){
134: new.r.r_symbolnum = new.rsymbol->final;
135: }
136: fwrite(&new.r ,sizeof(new.r ),1,fout);
137: } /* end while */
138: } /* end dorseg */
139:
140: /* rel_val - Puts value of operand into next bytes of Code
141: * updating Code_length. Put_Rel is called to handle possible relocation.
142: * If size=L a longword is stored, otherwise a word is stored
143: */
144: rel_val(opnd,size, pcrel)
145: register struct oper *opnd;
146: subop_t size;
147: {
148: register int i;
149: register struct sym_bkt *sp;
150: long val;
151: char *ccode; /* char version of this */
152: union /* floating point equivalence */
153: {
154: unsigned short words[6] ;
155: float f ;
156: double d ;
157: /* extended x ; bcdrecord p ; */
158: }
159: float_equivalence ;
160:
161: i = code_length>>1; /* get index into WCode */
162: if (sp = opnd->sym_o)
163: put_rel(opnd, size, dot + code_length, pcrel);
164: val = opnd->value_o;
165: /* /*
166: /* * if we're doing pc-relative relocation, we must bias this data
167: /* * by the negative of its own address. The linker, ld, will add in
168: /* * the absolute address, then subtract out this assembly's relocation
169: /* * constant, leaving us with the pc-relative value.
170: /* */
171: /* if (pcrel)
172: /* val -= dot + code_length;
173: */
174: switch(size) {
175: case SUBOP_D: /* Op code specifies double operand. */
176: switch(opnd->immed_o)
177: {
178: case T_FLOAT : /* Immediate operand was actually single. */
179: float_equivalence.d = (double) opnd->fval_o ;
180: break ;
181: case T_DOUBLE : /* Immediate operand was actually double. */
182: float_equivalence.d = (double) opnd->dval_o ;
183: break ;
184: default: /* Immediate operand was integer. */
185: float_equivalence.d = (double) opnd->value_o ;
186: break ;
187: }
188: wcode[i++] = float_equivalence.words[0] ;
189: wcode[i++] = float_equivalence.words[1] ;
190: wcode[i++] = float_equivalence.words[2] ;
191: wcode[i++] = float_equivalence.words[3] ;
192: code_length += 8 ;
193: break ;
194:
195: case SUBOP_S: /* Op code specifies single operand. */
196: switch(opnd->immed_o)
197: {
198: case T_FLOAT : /* Immediate operand was actually single. */
199: float_equivalence.f = (float) opnd->fval_o ;
200: break ;
201: case T_DOUBLE : /* Immediate operand was actually double. */
202: float_equivalence.f = (float) opnd->dval_o ;
203: break ;
204: default: /* Immediate operand was integer. */
205: float_equivalence.f = (float) opnd->value_o ;
206: break ;
207: }
208: wcode[i++] = float_equivalence.words[0] ;
209: wcode[i++] = float_equivalence.words[1] ;
210: code_length += 4 ;
211: break ;
212:
213: case SUBOP_L: wcode[i++] = val>>16;
214: code_length += 2;
215: val &= 0xFFFF;
216: /* fall through ... */
217: case SUBOP_W:
218: default:
219: if ((short)val > 32767 || (short)val < -32768)
220: PROG_ERROR( E_OFFSET );
221: wcode[i] = val;
222: code_length += 2;
223: break;
224: case SUBOP_B:
225: if ((char)val > 255 || (char)val < -256)
226: PROG_ERROR( E_OFFSET );
227: ccode = (char *)wcode;
228: ccode[code_length++] = val;
229: }
230: } /* end rel_val */
231:
232: /* Version of Put_Text which puts whole words, thus enforcing the mapping
233: * of bytes to words.
234: */
235:
236: #ifdef mc68000
237: put_words(code,nbytes)
238: char *code;
239: {
240: if (nbytes & 1) sys_error("Put_Words given odd nbytes=%d\n",nbytes);
241: put_text(code,nbytes);
242: }
243: #endif
244:
245: #ifndef mc68000
246: Put_Words(code,nbytes)
247: register char *code;
248: { register char *cc, ch;
249: register int i;
250: char tcode[100];
251:
252: cc = tcode;
253: for (i=0; i<nbytes; i++) tcode[i] = code[i];
254: i = nbytes>>1;
255: if (nbytes & 1) Sys_Error("Put_Words given odd nbytes=%d\n",nbytes);
256: while (i--) { ch = *cc; *cc = cc[1]; *++cc = ch; cc++; }
257: Put_Text(tcode,nbytes);
258: }
259: #endif
260:
261: /* Put_Text - Write out text to proper portion of file */
262:
263: put_text(code,length)
264: register char *code;
265: {
266: if (pass != 2) return;
267: switch(cur_csect_name){
268: case C_TEXT:
269: fwrite(code, length, 1, tout); break;
270: case C_DATA:
271: fwrite(code, length, 1, dout); break;
272: case C_DATA1:
273: fwrite(code, length, 1, d1out); break;
274: case C_DATA2:
275: fwrite(code, length, 1, d2out); break;
276: }
277: /* else ignore bss segment */
278: } /* end Put_Text */
279:
280:
281: /* set up relocation word for operand:
282: * opnd pointer to operand structure
283: * size 0 = byte, 1 = word, 2 = long/address
284: * offset offset into WCode & WReloc array
285: */
286:
287: put_rel(opnd, size, offset, pcrel)
288: struct oper *opnd;
289: subop_t size;
290: long offset;
291: {
292: struct reloc r;
293: int tz = (rflag)?0:tsize;
294: if (opnd->sym_o == 0) return; /* no relocation */
295: switch( cur_csect_name ){
296: case C_TEXT:
297: rtsize += rel_cmd(&r, opnd, size, offset, rtout, pcrel);
298: break;
299: case C_DATA:
300: rdsize += rel_cmd(&r, opnd, size, offset - tz, rdout, pcrel);
301: break;
302: case C_DATA1:
303: rdsize += rel_cmd(&r, opnd, size, offset - tz, rdout, pcrel);
304: break;
305: case C_DATA2:
306: rdsize += rel_cmd(&r, opnd, size, offset - tz, rdout, pcrel);
307: break;
308: }
309: /* else ignore bss segment */
310: } /* end Put_Rel */
311:
312:
313: /* rel_cmd - Generate a relocation command and output */
314:
315: rel_cmd(rp, opnd, size, offset, file, pcrel)
316: register struct reloc* rp;
317: struct oper *opnd;
318: subop_t size;
319: long offset;
320: FILE *file;
321: {
322: register struct sym_bkt *sp; /* pointer to symbol */
323: static char zed[ sizeof *rp ] = {0};
324:
325: sp = opnd->sym_o;
326: if (pass == 2) {
327: *rp = *(struct reloc *)zed; /* zero the whole structure */
328: /* rp->r.r_extern = 0; */
329: if (!(sp->attr_s & S_DEF) && (sp->attr_s & S_EXT)) {
330: rp->r.r_extern = 1;
331: rp->rsymbol = sp;
332: }
333: else switch( sp->csect_s ){
334: case C_TEXT:
335: rp->r.r_symbolnum = N_TEXT;
336: break;
337: default:
338: rp->r.r_symbolnum = (rflag)?N_TEXT:N_DATA;
339: break;
340: case C_BSS:
341: rp->r.r_symbolnum = N_BSS;
342: break;
343: case C_UNDEF:
344: prog_error(E_RELOCATE);
345: }
346: rp->r.r_address = offset;
347: rp->r.r_length = (size==SUBOP_L)?2:(size==SUBOP_B)?0:1;
348: rp->r.r_pcrel = pcrel;
349: fwrite(rp, sizeof *rp, 1, file);
350: }
351: return(sizeof *rp);
352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.