Pristine Ack-5.5
[Ack-5.5.git] / mach / xenix3 / cv / cv.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  *
5  */
6
7 /*
8  * This program converts ack.out format to XENIX 3.0 x.out format.
9  * It uses ~em/modules/lib/libobject.a.
10  */
11
12 #include <stdio.h>
13
14 struct xexec {
15         unsigned short  x_magic;
16 #define XMAGIC  01006
17         unsigned short  x_ext;          /* 054 */
18         long            x_text;
19         long            x_data;
20         long            x_bss;
21         long            x_syms;
22         long            x_reloc;        /* 0 */
23         long            x_entry;        /* 0 */
24         char            x_cpu;
25 #define XBSWAP  0x80
26 #define XWSWAP  0x40
27 #define X8086   0x04
28 #define X286    0x09
29         char            x_relsym;       /* 0144, not used */
30         unsigned short  x_renv;
31 #define XV3             0x8000          /* after Xenix version 2.3 */
32 #define XVERS           0xc000          /* version mask */
33 #define XSEG            0x0800          /* segment table present */
34 #define XFS             0x0008          /* fixed stack */
35 #define XPURE           0x0004          /* pure text */
36 #define XSEP            0x0002          /* separate I & D */
37 #define XEXEC           0x0001          /* executable */
38 };
39
40 struct xext {
41         long            xe_trsize, xe_drsize, xe_tbase, xe_dbase; /* 0 */
42         long            xe_stksize;
43         long            xe_segpos;      /* 0140 ??? */
44         long            xe_segsize;     /* 2 or 3 segments */
45                                         /* one for name table, one for text+data
46                                            or one for text + one for data(-i)
47                                         */
48         long            xe_mdtpos, xe_mdtsize; /* 0 */
49         char            xe_mdttype;     /* 0 */
50         char            xe_pagesize;    /* 0 */
51         char            xe_ostype;      /* 1 */
52         char            xe_osvers;      /* 1 */
53         unsigned short  xe_eseg;        /* 077 ??? */
54         unsigned short  xe_sres;        /* 0 */
55 };
56
57 struct xseg {
58         unsigned short  xs_type;
59 #define XTEXT   1
60 #define XDATA   2
61 #define XTSYMS  3
62         unsigned short  xs_attr;
63 #define XAMEM   0x8000
64 #define X_ABSS  0x0004
65 #define X_APURE 0x0010
66         unsigned short  xs_seg;         /* 077 for text, 0107 for data, 0 for sym */
67         unsigned short  xs_sres;        /* 0 */
68         long            xs_filpos;
69         long            xs_psize;
70         long            xs_vsize;
71         long            xs_rbase;       /* 0 */
72         long            xs_lres;        /* 0 */
73         long            xs_lres2;       /* 0 */
74 };
75
76 #include <out.h>
77
78 #ifndef NORCSID
79 static char rcs_id[] = "$Id: cv.c,v 1.7 1994/06/24 13:54:16 ceriel Exp $" ;
80 #endif
81
82 #define ENTRY 0x0L      /* entry point */
83
84 /*
85  * Header and section table of new format object file.
86  */
87 struct outhead  outhead;
88 struct outsect  outsect[S_MAX];
89
90 struct xexec exec;
91 struct xext  ext;
92 struct xseg  seg[3];
93
94 char    *output_file;
95 int     outputfile_created;
96 int     output;
97
98 char *program ;
99
100 int sep_id;
101
102 extern long lseek();
103 #define TEXTSG  0
104 #define ROMSG   1
105 #define DATASG  2
106 #define BSSSG   3
107 #define LSECT   BSSSG+1
108 #define NSECT   LSECT+1
109
110 long    emit_symtab();
111
112 long align(a,b)
113         long a,b;
114 {
115         a += b - 1;
116         return a - a % b;
117 }
118
119 int
120 follows(pa, pb)
121         register struct outsect *pa, *pb;
122 {
123         /* return 1 if pa follows pb */
124
125         return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
126 }
127
128 main(argc, argv)
129         int     argc;
130         char    *argv[];
131 {
132         long                    stacksize = 0x1000;
133
134         output = 1;
135         program= argv[0] ;
136         if ( argc>1 && argv[1][0]=='-' ) {
137                 if (argv[1][1] == 'F') {
138                         register char *p = &argv[1][2];
139
140                         stacksize = 0;
141                         while (*p) {
142                                 stacksize <<= 4;
143                                 if (*p >= '0' && *p <= '9') 
144                                         stacksize += *p - '0';
145                                 else if (*p >= 'a' && *p <= 'f')
146                                         stacksize += 10 + *p - 'a';
147                                 else if (*p >= 'A' && *p <= 'F')
148                                         stacksize += 10 + *p - 'A';
149                                 else fatal("Illegal -F option\n");
150                                 p++;
151                         }
152                 }
153                 argc-- ; argv++ ;
154         }
155         switch (argc) {
156         case 1: rd_fdopen(0);
157                 break;
158         case 3: if ((output = creat(argv[2], 0644)) < 0) {
159                         fatal("Can't write %s.\n", argv[2]);
160                 }
161                 output_file = argv[2];
162                 outputfile_created = 1;
163                 /* FALLTHROUGH */
164         case 2:
165                 if (! rd_open(argv[1]))
166                         fatal("Can't read %s.\n", argv[1]);
167                 break;
168         default:fatal("Usage: %s <ACK object> <Xenix object>.\n", argv[0]);
169         }
170         rd_ohead(&outhead);
171         if (BADMAGIC(outhead))
172                 fatal("Not an ack object file.\n");
173         if (outhead.oh_flags & HF_LINK)
174                 fatal("Contains unresolved references.\n");
175         if (outhead.oh_nrelo > 0)
176                 fprintf(stderr, "Warning: relocation information present.\n");
177         if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
178                 fatal("Input file must have %d sections, not %ld\n",
179                         NSECT,outhead.oh_nsect) ;
180         rd_sect(outsect, outhead.oh_nsect);
181         /* A few checks */
182         if ( outsect[TEXTSG].os_base != ENTRY)
183                 fatal("text must start at 0x%lx not at 0x%lx\n", ENTRY,
184                         outsect[TEXTSG].os_base) ;
185         if ( outsect[BSSSG].os_flen != 0 )
186                 fatal("bss space contains initialized data\n") ;
187         if (! follows(&outsect[BSSSG], &outsect[DATASG]))
188                 fatal("bss segment must follow data segment\n") ;
189         if (! follows(&outsect[DATASG], &outsect[ROMSG]))
190                 fatal("bss segment must follow data segment\n") ;
191
192         outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
193         outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
194         exec.x_magic = XMAGIC;
195         exec.x_ext = 054;
196         exec.x_data = outsect[ROMSG].os_size + outsect[DATASG].os_size;
197         exec.x_bss = outsect[BSSSG].os_size;
198         exec.x_entry = outsect[TEXTSG].os_base;
199         exec.x_cpu = XWSWAP | X286;
200         exec.x_relsym = 0144;
201         exec.x_renv = XV3 | XSEG | XFS | XEXEC;
202         if ( outsect[ROMSG].os_base == 0x0 ) {
203                 /* Separate I/D */
204                 outsect[TEXTSG].os_size = align(outsect[TEXTSG].os_size, 2L);
205                 sep_id = 1;
206                 exec.x_renv |= XPURE | XSEP;
207         } else {
208                 if (! follows(&outsect[ROMSG], &outsect[TEXTSG]))
209                         fatal("bss segment must follow data segment\n") ;
210                 outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
211         }
212         exec.x_text = outsect[TEXTSG].os_size;
213         if ( outhead.oh_nsect==NSECT ) {
214                 if (! follows(&outsect[LSECT], &outsect[BSSSG]))
215                         fatal("bss segment must follow data segment\n") ;
216                 if ( outsect[LSECT].os_size != 0 )
217                         fatal("end segment must be empty\n") ;
218         }
219         ext.xe_stksize = stacksize;
220         /* Not too big, because "brk" and "sbrk"-allocated memory resides
221            above the stack!
222         */
223         ext.xe_segpos = 0140;
224         ext.xe_segsize = (2 + sep_id) * 040;
225         ext.xe_ostype = 1;
226         ext.xe_osvers = 1;
227         ext.xe_eseg = 077;
228         seg[0].xs_type = XDATA;
229         seg[0].xs_attr = XAMEM | X_ABSS;
230         seg[0].xs_seg = 0107;
231         seg[1].xs_type = XTSYMS;
232         seg[1].xs_attr = 1;     /* ??? */
233         seg[1].xs_filpos = 0140 + ext.xe_segsize + outsect[TEXTSG].os_size +
234                            outsect[DATASG].os_size + outsect[ROMSG].os_size;
235         if (sep_id) {
236                 seg[2] = seg[1];
237                 seg[1] = seg[0];
238                 seg[0].xs_type = XTEXT;
239                 seg[0].xs_attr = XAMEM | X_APURE;
240                 seg[0].xs_seg = 077;
241                 seg[0].xs_filpos = 0300;
242                 seg[0].xs_psize = seg[0].xs_vsize = outsect[TEXTSG].os_size;
243                 seg[1].xs_filpos = seg[0].xs_filpos + seg[0].xs_psize;
244                 seg[1].xs_psize = outsect[ROMSG].os_size + outsect[DATASG].os_size;
245                 seg[1].xs_vsize = seg[1].xs_psize + outsect[BSSSG].os_size;
246         }
247         else {
248                 seg[0].xs_filpos = 0240L;
249                 seg[0].xs_psize = outsect[TEXTSG].os_size +
250                                   outsect[ROMSG].os_size +
251                                   outsect[DATASG].os_size;
252                 seg[0].xs_vsize = seg[0].xs_psize + outsect[BSSSG].os_size;
253         }
254         lseek(output, seg[0].xs_filpos + outsect[TEXTSG].os_size +
255                         outsect[DATASG].os_size + outsect[ROMSG].os_size, 0);
256         if (! (exec.x_syms = seg[1+sep_id].xs_psize = emit_symtab())) {
257                 /* not enough memory to produce symbol table, do without */
258                 fprintf(stderr, "%s: warning: no symbol table produced\n", 
259                         program);
260                 ext.xe_segsize -= 040;
261                 seg[1+sep_id].xs_type = 0;
262                 seg[0].xs_filpos -= 040;
263                 seg[1].xs_filpos -= 040;
264         }
265         lseek(output, seg[0].xs_filpos, 0);
266
267         emits(&outsect[TEXTSG]) ;
268         emits(&outsect[ROMSG]) ;
269         emits(&outsect[DATASG]) ;
270
271         lseek(output, 0L, 0);
272         header();
273
274         if ( outputfile_created ) chmod(argv[2],0755);
275         exit(0);
276 }
277
278 #define shortcvt(val, p) (*p++ = val, *p++ = val >> 8)
279 #define longcvt(val, p)  (*p++ = val, *p++ = val >> 8, *p++ = val >> 16, *p++ = val >> 24)
280
281 char buf[0300];
282
283 header()
284 {
285         register char *p = buf;
286         register int i;
287
288         shortcvt(exec.x_magic, p);
289         shortcvt(exec.x_ext, p);
290         longcvt(exec.x_text, p);
291         longcvt(exec.x_data, p);
292         longcvt(exec.x_bss, p);
293         longcvt(exec.x_syms, p);
294         longcvt(exec.x_reloc, p);
295         longcvt(exec.x_entry, p);
296         *p++ = exec.x_cpu;
297         *p++ = exec.x_relsym;
298         shortcvt(exec.x_renv, p);
299
300         longcvt(ext.xe_trsize, p);
301         longcvt(ext.xe_drsize, p);
302         longcvt(ext.xe_tbase, p);
303         longcvt(ext.xe_dbase, p);
304         longcvt(ext.xe_stksize, p);
305         longcvt(ext.xe_segpos, p);
306         longcvt(ext.xe_segsize, p);
307         longcvt(ext.xe_mdtpos, p);
308         longcvt(ext.xe_mdtsize, p);
309         *p++ = ext.xe_mdttype;
310         *p++ = ext.xe_pagesize;
311         *p++ = ext.xe_ostype;
312         *p++ = ext.xe_osvers;
313         shortcvt(ext.xe_eseg, p);
314         shortcvt(ext.xe_sres, p);
315
316         p = &buf[0140];
317         for (i = 0; i <= 2 && seg[i].xs_type != 0; i++) {
318                 shortcvt(seg[i].xs_type, p);
319                 shortcvt(seg[i].xs_attr, p);
320                 shortcvt(seg[i].xs_seg, p);
321                 shortcvt(seg[i].xs_sres, p);
322                 longcvt(seg[i].xs_filpos, p);
323                 longcvt(seg[i].xs_psize, p);
324                 longcvt(seg[i].xs_vsize, p);
325                 longcvt(seg[i].xs_rbase, p);
326                 longcvt(seg[i].xs_lres, p);
327                 longcvt(seg[i].xs_lres2, p);
328         }
329
330         write(output, buf, 0140 + i * 040);
331 }
332
333 /*
334  * Transfer the emitted byted from one file to another.
335  */
336 emits(section) struct outsect *section ; {
337         register long   n ;
338         register int    blk;
339         char            buffer[BUFSIZ];
340
341         n= section->os_flen ;
342         rd_outsect(section - outsect);
343         while (n > 0) {
344                 blk = n > BUFSIZ ? BUFSIZ : n;
345                 rd_emit(buffer, (long) blk);
346                 write(output, buffer, blk);
347                 n -= blk;
348         }
349         if ((n = section->os_size - section->os_flen) > 0) {
350                 for (blk = BUFSIZ - 1; blk >= 0; blk--) {
351                         buffer[blk] = 0;
352                 }
353                 while (n > 0) {
354                         blk = n > BUFSIZ ? BUFSIZ : n;
355                         write(output, buffer, blk);
356                         n -= blk;
357                 }
358         }
359 }
360
361 long
362 emit_symtab()
363 {
364         register unsigned short i;
365         struct xnm {
366                 unsigned short s_type, s_seg;
367                 long    s_value;
368         } xnm;
369         char *chars, *xname;
370         struct outname *names;
371         register char *xptr;
372         extern char *malloc();
373         long off = OFF_CHAR(outhead);
374         register char *p;
375
376         chars = malloc((unsigned)(outhead.oh_nchar));
377         if (! chars) return 0;
378         names = (struct outname *)
379                 malloc(outhead.oh_nname * sizeof(struct outname));
380         if (! names) {
381                 free(chars);
382                 return 0;
383         }
384         xptr = malloc((unsigned)(outhead.oh_nchar) + 9 * outhead.oh_nname);
385         if (! xptr) {
386                 free(chars);
387                 free((char *) names);
388                 return 0;
389         }
390         xname = xptr;
391         rd_name(names, outhead.oh_nname);
392         rd_string(chars,outhead.oh_nchar);
393         for (i = 0; i < outhead.oh_nname; i++) {
394                 xnm.s_seg = 077;
395                 switch(names[i].on_type & S_ETC) {
396                 case S_FIL:
397                 case S_MOD:
398                         xnm.s_type = 0x1f;
399                         break;
400                 case S_SCT:
401                         xnm.s_type = 0x8;
402                         if ((names[i].on_type & S_TYP) != S_MIN+TEXTSG) {
403                                 xnm.s_seg = 0107;
404                         }
405                         break;
406                 default:
407                         switch(names[i].on_type & S_TYP) {
408                         case S_UND:
409                                 xnm.s_type = 0;
410                                 break;
411                         case S_ABS:
412                                 xnm.s_type = 1;
413                                 xnm.s_seg = 0107;
414                                 break;
415                         case S_MIN + TEXTSG:
416                                 xnm.s_type = 2;
417                                 break;
418                         case S_MIN + ROMSG:
419                         case S_MIN + DATASG:
420                                 xnm.s_type = 3;
421                                 xnm.s_seg = 0107;
422                                 break;
423                         case S_MIN + BSSSG:
424                         case S_MIN + LSECT:
425                                 xnm.s_type = 4;
426                                 xnm.s_seg = 0107;
427                                 break;
428                         default:
429                                 fprintf(stderr,"warning: unknown s_type: %d\n",
430                                         (int)(names[i].on_type) & S_TYP);
431                         }
432                 }
433                 if (names[i].on_type & S_EXT) xnm.s_type |= 0x20;
434                 xnm.s_value = names[i].on_valu;
435                 if (names[i].on_foff == 0) {
436                 }
437                 else {
438                         long l = names[i].on_foff - off;
439                         if (l < 0 || l >= outhead.oh_nchar) {
440                                 fatal("bad on_off: %ld\n",l);
441                         }
442                         p = &chars[l];
443                         shortcvt(xnm.s_type, xptr);
444                         shortcvt(xnm.s_seg, xptr);
445                         longcvt(xnm.s_value, xptr);
446                         do {
447                                 *xptr++ = *p;
448                         } while (*p++);
449                 }
450         }
451         write(output, xname, xptr - xname);
452         free(xname);
453         free((char *) names);
454         free(chars);
455         return xptr - xname;
456 }
457
458 /* VARARGS1 */
459 fatal(s, a1, a2)
460         char    *s;
461 {
462         fprintf(stderr,"%s: ",program) ;
463         fprintf(stderr, s, a1, a2);
464         if (outputfile_created)
465                 unlink(output_file);
466         exit(1);
467 }
468
469 rd_fatal()
470 {
471         fatal("read error\n");
472 }