Pristine Ack-5.5
[Ack-5.5.git] / mach / vax4 / ce / output.c
1 #include <system.h>
2 #include <em.h>
3 #include <out.h>
4 #include "mach.h"
5 #include "back.h"
6
7 /*      Unportable code. Written for VAX, meant to be run on a VAX.
8 */
9 #ifndef vax
10 Read above comment ...
11 #endif
12
13 extern File *B_out_file;
14
15 #include <a.out.h>
16 #include <alloc.h>
17
18 static struct exec u_header;
19
20 static long ntext, ndata, nrelo, nchar;
21
22 long B_base_address[SEGBSS+1];
23
24 static int trsize=0, drsize=0;
25
26 static struct relocation_info *u_reloc;
27
28 static reduce_name_table(), putbuf(), put_stringtablesize();
29 static convert_name(), convert_reloc(), init_unixheader();
30
31 output_back()
32 {
33         register int i;
34         register struct nlist *u_name;
35         register struct outrelo *rp;
36
37         /*
38          * Convert relocation data structures. This also requires
39          * some re-ordering, as SUN .o format needs has text relocation
40          * structures in front of the data relocation structures, whereas in
41          * ACK they can be in any order.
42          */
43
44         nrelo = relo - reloc_info;
45         u_reloc = (struct relocation_info *)
46                         Malloc((unsigned)nrelo*sizeof(struct relocation_info));
47
48         rp = reloc_info;
49         for (i = nrelo; i > 0; i--, rp++) {
50                 if (  ( rp->or_sect-S_MIN) == SEGTXT &&
51                         convert_reloc( rp, u_reloc)) {
52                         trsize++;
53                         u_reloc++;
54                 }
55         }
56         rp = reloc_info;
57         for (i = nrelo; i > 0; i--, rp++) {
58                 if (  ( rp->or_sect-S_MIN) != SEGTXT &&
59                         convert_reloc( rp, u_reloc)) {
60                         u_reloc++;
61                         drsize++;
62                 }
63         }
64
65         nrelo = trsize + drsize;
66         u_reloc -= nrelo;
67
68         reduce_name_table();
69
70         init_unixheader();
71
72         putbuf( (char *) &u_header, sizeof(struct exec));
73         putbuf( (char *) text_area,  ntext);
74         putbuf( (char *) data_area, ndata);
75         putbuf((char *) u_reloc, sizeof(struct relocation_info)*nrelo);
76         free(u_reloc);
77         
78         u_name = (struct nlist *)
79                         Malloc((unsigned)nname * sizeof(struct nlist));
80
81         for (i = 0; i < nname ; i++) { /* The segment names can be omitted */
82                 convert_name( &symbol_table[i], u_name++);
83         }
84         u_name -= nname;
85         putbuf((char *) u_name, sizeof(struct nlist)*nname);
86         free(u_name);
87
88         /* print( "size string_area %d\n", nchar); */
89
90         put_stringtablesize( nchar + 4);
91         putbuf((char *) string_area, nchar);
92 }
93
94 static
95 reduce_name_table()
96 {
97         /*
98          * Reduce the name table size. This is done by first marking
99          * the name-table entries that are needed for relocation, then
100          * removing the entries that are compiler-generated and not
101          * needed for relocation, while remembering how many entries were
102          * removed at each point, and then updating the relocation info.
103          * After that, the string table is reduced.
104          */
105
106 #define S_NEEDED        S_MOD
107 #define removable(nm)   (!(nm->on_type & (S_NEEDED|S_STB)) && *(nm->on_foff+string_area) == GENLAB)
108
109         register int *diff_index =
110                 (int *) Malloc((unsigned)(nname + 1) * sizeof(int));
111         register int i;
112         register struct outname *np;
113         char *new_str;
114         register char *p, *q;
115         register struct relocation_info *rp;
116
117         *diff_index++ = 0;
118         rp = u_reloc;
119         for (i = nrelo; i > 0; i--, rp++) {
120                 if (rp->r_extern) {
121                         symbol_table[rp->r_symbolnum].on_type |= S_NEEDED;
122                 }
123         }
124
125         np = symbol_table;
126         for (i = 0; i < nname; i++, np++) {
127                 int old_diff_index = diff_index[i-1];
128
129                 if (removable(np)) {
130                         diff_index[i] = old_diff_index + 1;
131                 }
132                 else {
133                         diff_index[i] = old_diff_index;
134                 }
135                 if ((np->on_type & S_TYP) == S_CRS) {
136                         struct outname *n = &symbol_table[(int) np->on_valu];
137                         if (! (n->on_type & S_COM)) {
138                                 np->on_type &= ~S_TYP;
139                                 np->on_type |= (n->on_type & S_TYP);
140                                 np->on_valu = n->on_valu;
141                         }
142                 }
143         }
144
145         rp = u_reloc;
146         for (i = nrelo; i > 0; i--, rp++) {
147                 if (rp->r_extern) {
148                         symbol_table[rp->r_symbolnum].on_type &= ~S_NEEDED;
149                         rp->r_symbolnum -= diff_index[rp->r_symbolnum];
150                 }
151         }
152
153         for (i = 0, np = symbol_table; i < nname; i++, np++) {
154                 if ((np->on_type & S_TYP) == S_CRS) {
155                         np->on_valu -= diff_index[(int) np->on_valu];
156                 }
157                 if (diff_index[i] && diff_index[i] == diff_index[i-1]) {
158                         symbol_table[i - diff_index[i]] = *np;
159                 }
160         }
161
162         nname -= diff_index[nname - 1];
163         free((char *)(diff_index-1));
164
165         new_str = q = Malloc((unsigned)(string - string_area));
166         np = symbol_table;
167         for (i = nname; i > 0; i--, np++) {
168                 p = np->on_foff + string_area;
169                 np->on_foff = q - new_str;
170                 while (*q++ = *p) p++;
171         }
172         free(string_area);
173         string_area = new_str;
174         string = q;
175 }
176
177 static
178 init_unixheader()
179 {
180         ntext = text - text_area;
181         ndata = data - data_area;
182         nchar = string - string_area;
183
184         u_header.a_magic = OMAGIC;
185         u_header.a_text = ntext;
186         u_header.a_data = ndata;
187         u_header.a_bss = nbss;
188         u_header.a_syms = nname * sizeof(struct nlist);
189         u_header.a_entry = 0;
190         u_header.a_trsize = trsize * sizeof(struct relocation_info);
191         u_header.a_drsize = drsize * sizeof(struct relocation_info);
192         /* print( "header %o %d %d %d %d %d %d %d\n",
193                 u_header.a_magic, u_header.a_text, u_header.a_data,
194                 u_header.a_bss, u_header.a_syms, u_header.a_entry,
195                 u_header.a_trsize, u_header.a_drsize);
196          */
197 }
198
199 static
200 convert_reloc( a_relo, u_relo)
201 register struct outrelo *a_relo;
202 register struct relocation_info *u_relo;
203 {
204         int retval = 1;
205
206         u_relo->r_address = a_relo->or_addr;
207         u_relo->r_symbolnum = a_relo->or_nami;
208         u_relo->r_pcrel = (a_relo->or_type & RELPC) >> 3;
209         u_relo->r_length = 2;
210         if ( symbol_table[ a_relo->or_nami].on_valu == -1 ||
211              (symbol_table[ a_relo->or_nami].on_type & S_COM)) 
212                 u_relo->r_extern = 1;
213         else  
214                 u_relo->r_extern = 0;
215         if ( u_relo->r_extern == 0) {
216                 switch ( (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN) {
217                         case SEGTXT : u_relo->r_symbolnum = N_TEXT;
218                                       if (u_relo->r_pcrel &&
219                                           (a_relo->or_sect-S_MIN == SEGTXT))
220                                                 retval = 0;
221                                       break;
222                         case SEGCON : u_relo->r_symbolnum = N_DATA;
223                                       break;
224                         case SEGBSS : u_relo->r_symbolnum = N_BSS;
225                                       break;
226 /* Shut up; this can actually happen on erroneous input
227                         default : fprint( STDERR, 
228                                            "convert_relo(): bad segment %d\n",
229                             (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN);
230 */
231                 }
232         }
233         return retval;
234 }
235
236 #define         n_mptr          n_un.n_name
237 #define         n_str           n_un.n_strx
238
239 static
240 convert_name( a_name, u_name)
241 register struct outname *a_name;
242 register struct nlist *u_name;
243 {
244         /* print( "naam is %s\n", a_name->on_foff + string_area);   */
245
246         u_name->n_str = a_name->on_foff + 4;
247         if (a_name->on_type & S_STB) u_name->n_type = a_name->on_type >> 8;
248         else    u_name->n_type = 0;
249         if ((a_name->on_type & S_TYP) == S_CRS) {
250                 a_name->on_valu = 0;
251                 a_name->on_type = S_COM;
252         }
253         if (a_name->on_valu != -1 && (! (a_name->on_type & S_COM))) {
254                 switch((a_name->on_type & S_TYP) - S_MIN) {
255                 case SEGTXT:
256                         u_name->n_type |= N_TEXT;
257                         break;
258                 case SEGCON:
259                         u_name->n_type |= N_DATA;
260                         break;
261                 case SEGBSS:
262                         u_name->n_type |= N_BSS;
263                         break;
264 /* Shut up; this can actually happen on erroneous input
265                 default:
266                         fprint(STDERR, "convert_name(): bad section %d\n",
267                                 (a_name->on_type & S_TYP) - S_MIN);
268                         break;
269 */
270                 }
271         }
272         if ((a_name->on_type & S_TYP) == S_UND ||
273             (a_name->on_type & S_EXT)) u_name->n_type |= N_EXT;
274         u_name->n_other = '\0';
275         u_name->n_desc = a_name->on_desc;
276         if (a_name->on_type & S_COM) 
277                 u_name->n_value = a_name->on_valu;
278         else if ( a_name->on_valu != -1)
279                 u_name->n_value = a_name->on_valu + 
280                         B_base_address[( a_name->on_type & S_TYP) - S_MIN];
281         else 
282                  u_name->n_value = 0;
283 }
284
285 static
286 put_stringtablesize( n)
287 long n;
288 {
289         putbuf( (char *)&n, 4L);
290 }
291
292 static
293 putbuf(buf,n)
294 char *buf;
295 long n;
296 {
297         sys_write( B_out_file, buf, n);
298 }