Pristine Ack-5.5
[Ack-5.5.git] / mach / mantra / cv / Xcv.c
1 /* $Id: Xcv.c,v 1.4 1994/06/24 13:08:21 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  *
6  */
7
8 /*
9  * Convert Mantra object format to ACK object format
10  */
11 #include <stdio.h>
12 #include <out.h>
13
14 #define FMAGIC  0407
15 #define REG     06
16
17 #define RTEXT   00
18 #define RDATA   01
19 #define RBSS    02
20 #define REXT    03
21
22 #define RBYTE   00
23 #define RWORD   01
24 #define RLONG   02
25
26 struct bhdr {
27         long    fmagic;
28         long    tsize;
29         long    dsize;
30         long    bsize;
31         long    ssize;
32         long    rtsize;
33         long    rdsize;
34         long    entry;
35 };
36
37 struct reloc {
38         char x;
39 #define setseg(p,s)     (p->x = (p->x & ~03) | s)
40 #define setsiz(p,s)     (p->x = (p->x & ~014) | (s << 2))
41 #define setdis(p,s)     (p->x = (p->x & ~020) | (s << 4))
42 #define getseg(p)       (p->x&03)
43 #define getsiz(p)       ((p->x >> 2) & 03)
44 #define getdis(p)       ((p->x >> 4) & 01)
45         char     relpad2;
46         short rsymbol;
47         long rpos;
48 };
49
50 #define N_UNDF  0
51 #define N_ABS   01
52 #define N_TEXT  02
53 #define N_DATA  03
54 #define N_BSS   04
55 #define N_TYPE  037
56 #define N_REG   024
57 #define N_FN    037
58 #define N_EXT   040
59
60 #define ASSERT(x) switch (2) { case 0: case (x): ; }
61
62 /*
63  * Header and section table of new format object file.
64  */
65 struct outhead  outhead;
66 struct outsect  outsect[4];
67 #define TEXTSG 0
68 #define ROMSG 1
69 #define DATASG 2
70 #define BSSSG 3
71
72 char    *output_file;
73
74 char *program ;
75
76 char flag ;
77
78 #define readf(a, b, c)  fread((a), (b), (int)(c), input)
79
80 /* Output file definitions and such */
81
82 struct bhdr bh;
83
84 #define TOT_HDRSIZE     (sizeof(struct bhdr))
85
86 FILE            *input;
87
88 struct outrelo *orelo = 0;
89 struct outname *oname = 0;
90 char *strings = 0;
91 char *txt = 0;
92 char *data = 0;
93
94 main(argc, argv)
95         int     argc;
96         char    *argv[];
97 {
98         register struct outsect *p;
99         char *malloc();
100
101         input = stdin;
102         program= argv[0] ;
103         if ( argc>1 && argv[1][0]=='-' ) {
104                 flag=argv[1][1] ;
105                 argc-- ; argv++ ;
106         }
107         switch (argc) {
108         case 3: if (! wr_open(argv[2]))
109                         fatal("Can't write %s.\n", argv[2]);
110                 output_file = argv[2];
111                 if ((input = fopen(argv[1], "r")) == (FILE *)0)
112                         fatal("Can't read %s.\n", argv[1]);
113                 break;
114         default:fatal("Usage: %s <Mantra object> <ACK object>.\n", argv[0]);
115         }
116         if (! readf(&bh, sizeof(struct bhdr), 1)) rd_fatal();
117         if (bh.fmagic != FMAGIC) fatal("bad magic number\n");
118         outhead.oh_magic = O_MAGIC;
119         outhead.oh_stamp = 0;
120         outhead.oh_nsect = 4;
121         outhead.oh_nrelo = (bh.rtsize + bh.rdsize) / sizeof(struct reloc);
122         outhead.oh_flags = outhead.oh_nrelo ? HF_LINK : 0;
123         outhead.oh_nemit = bh.tsize + bh.dsize;
124         strings = malloc((unsigned) bh.ssize + 20);
125         orelo = (struct outrelo *)
126                         malloc(outhead.oh_nrelo * sizeof(struct outrelo));
127         oname = (struct outname *)
128                         malloc((unsigned) (bh.ssize / 6 + 3) * sizeof (struct outname));
129         txt = malloc(bh.tsize);
130         data = malloc(bh.dsize);
131         if (!strings || !orelo || !oname || !txt || !data) {
132                 fatal("No memory\n");
133         }
134         p = &outsect[TEXTSG];
135         p->os_base = 0; p->os_size = p->os_flen = bh.tsize;
136         p->os_foff = OFF_EMIT(outhead); p->os_lign = 1;
137         p = &outsect[ROMSG];
138         p->os_base = p->os_size = p->os_flen = 0;
139         p->os_foff = OFF_EMIT(outhead) + bh.tsize; p->os_lign = 1;
140         p = &outsect[DATASG];
141         p->os_base = 0; p->os_size = p->os_flen = bh.dsize;
142         p->os_foff = OFF_EMIT(outhead) + bh.tsize; p->os_lign = 1;
143         p = &outsect[BSSSG];
144         p->os_base = p->os_flen = 0; p->os_size = bh.bsize;
145         p->os_foff = OFF_EMIT(outhead)+bh.tsize+bh.dsize; p->os_lign = 1;
146
147         if (bh.tsize && ! readf(txt, 1, bh.tsize)) rd_fatal();
148         if (bh.dsize && ! readf(data, 1, bh.dsize)) rd_fatal();
149
150         symtab(oname, strings);
151         relo(orelo, txt, data);
152         wr_ohead(&outhead);
153         wr_sect(outsect, 4);
154         wr_outsect(TEXTSG);
155         wr_emit(txt, bh.tsize);
156         wr_outsect(DATASG);
157         wr_emit(data,bh.dsize);
158         wr_relo(orelo, outhead.oh_nrelo);
159         wr_name(oname, outhead.oh_nname);
160         wr_string(strings, outhead.oh_nchar);
161         wr_close();
162         return 0;
163 }
164
165 symtab(name, string)
166         struct outname *name;
167         char *string;
168 {
169         register struct outname *oname = name;
170         register char *strings = string;
171         register int c;
172         unsigned nnames = 3;
173         register long ssize = bh.ssize;
174         register char *b;
175
176         oname->on_valu = 0; oname->on_foff = 0; oname->on_desc = 0;
177         oname->on_type = (S_MIN+TEXTSG) | S_SCT;
178         b = ".text"; while (*strings++ = *b) b++;
179         oname++;
180         oname->on_valu = 0; oname->on_foff = strings - string; oname->on_desc = 0;
181         oname->on_type = (S_MIN+DATASG) | S_SCT;
182         b = ".data"; while (*strings++ = *b) b++;
183         oname++;
184         oname->on_valu = 0; oname->on_foff = strings - string; oname->on_desc = 0;
185         oname->on_type = (S_MIN+BSSSG) | S_SCT;
186         b = ".bss"; while (*strings++ = *b) b++;
187         oname++;
188         while (ssize > 0) {
189                 c = getc(input);
190                 getc(input);
191                 oname->on_valu = getw(input);
192                 ssize -= 6;
193                 switch(c & ~N_EXT) {
194                 case N_ABS:
195                         oname->on_type = S_ABS;
196                         break;
197                 case N_TEXT:
198                         oname->on_type = S_MIN + TEXTSG;
199                         break;
200                 case N_DATA:
201                         oname->on_type = S_MIN + DATASG;
202                         oname->on_valu -= bh.tsize;
203                         break;
204                 case N_BSS:
205                         oname->on_type = S_MIN + BSSSG;
206                         oname->on_valu -= bh.tsize + bh.dsize;
207                         break;
208                 case N_UNDF:
209                         if (! oname->on_valu) {
210                                 oname->on_type = S_UND;
211                                 break;
212                         }
213                         oname->on_type = (S_MIN + BSSSG) | S_COM;
214                         break;
215                 case REG:
216                 case N_REG:
217                 case N_FN:
218                         while (ssize > 0 && (getc(input) > 0))
219                                 ssize--;
220                         continue;
221                 default:
222                         fatal("Illegal type field %d in namelist\n", c);
223                 }
224                 if (c & N_EXT) oname->on_type |= S_EXT;
225                 oname->on_desc = 0;
226                 oname->on_foff = strings - string;
227                 nnames++;
228                 while (ssize > 0 && (c = getc(input)) > 0) {
229                         *strings++ = c;
230                         ssize--;
231                 }
232                 ssize--;
233                 *strings++ = c;
234                 oname++;
235         }
236         outhead.oh_nname = nnames;
237         outhead.oh_nchar = strings - string;
238         oname = name;
239         ssize = OFF_CHAR(outhead);
240         while (nnames--) {
241                 oname->on_foff += ssize;
242                 oname++;
243         }
244 }
245
246 long
247 get4(c)
248         register char *c;
249 {
250         register long l = (long) (*c++ & 0377) << 24;
251
252         l |= (long) (*c++ & 0377) << 16;
253         l |= (long) (*c++ & 0377) << 8;
254         l |= (long) (*c++ & 0377);
255         return l;
256 }
257
258 put4(l, c)
259         register char *c;
260         register long l;
261 {
262         *c++ = (l >> 24);
263         *c++ = (l >> 16);
264         *c++ = (l >> 8);
265         *c = l;
266 }
267
268 relo(orelo, txt, data)
269         struct outrelo *orelo;
270         char *txt, *data;
271 {
272         register struct outrelo *relo = orelo;
273         register relocnt = outhead.oh_nrelo;
274         struct reloc rel;
275         register struct reloc *relp = &rel;
276         int ndat = bh.rdsize / sizeof(struct reloc);    
277
278         while (relocnt-- > 0) {
279                 readf(relp, sizeof(struct reloc), 1);
280                 relo->or_sect = (relocnt >= ndat) ? S_MIN + TEXTSG :
281                                                      S_MIN + DATASG;
282                 relo->or_addr = relp->rpos;
283                 relo->or_nami = relp->rsymbol + 3;
284                 switch(getseg(relp)) {
285                 case RTEXT:
286                         relo->or_nami = 0;
287                         break;
288                 case RDATA:
289                         relo->or_nami = 1;
290                         break;
291                 case RBSS:
292                         relo->or_nami = 2;
293                         break;
294                 case REXT:
295                         break;
296                 default:
297                         fatal("Error 1 in relocation\n");
298                 }
299                 switch(getsiz(relp)) {
300                 case RBYTE:
301                         relo->or_type = RELO1|RELBR|RELWR;
302                         break;
303                 case RWORD:
304                         relo->or_type = RELO2|RELBR|RELWR;
305                         break;
306                 case RLONG: {
307                         register char *sct = (relocnt >= ndat ? txt : data) +
308                                                 relo->or_addr;
309                         long x;
310
311                         relo->or_type = RELO4|RELBR|RELWR;
312                         switch((oname + relo->or_nami)->on_type & S_TYP) {
313                         case (S_MIN+DATASG):
314                                 x = get4(sct) - bh.tsize;
315
316                                 put4(x, sct);
317                                 break;
318                         case (S_MIN+BSSSG):
319                                 if (! ((oname+relo->or_nami)->on_type & S_COM))
320                                         x = get4(sct) - (bh.tsize + bh.dsize);
321                                 put4(x, sct);
322                         }
323                         break;
324                         }
325                 default:
326                         fatal("Error 2 in relocation\n");
327                 }
328                 if (getdis(relp)) relo->or_type |= RELPC;
329                 relo++;
330         }
331 }
332
333 /* VARARGS1 */
334 fatal(s, a1, a2)
335         char    *s;
336 {
337         fprintf(stderr,"%s: ",program) ;
338         fprintf(stderr, s, a1, a2);
339         unlink(output_file);
340         exit(-1);
341 }
342
343 wr_fatal() { fatal("Write error\n"); }
344 rd_fatal() { fatal("Read error\n"); }