Pristine Ack-5.5
[Ack-5.5.git] / mach / vax4 / cv / cv.c
1 /* $Id: cv.c,v 1.4 1994/06/24 13:53:58 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 ACK a.out file to VAX Berkeley Unix object format.
10  */
11
12 #include <stdio.h>
13 #include <out.h>
14 #include <assert.h>
15
16 long    lseek();
17
18 #define OMAGIC  0407    /* old-fashioned */
19 #define NMAGIC  0410    /* text write protexted */
20 #define ZMAGIC  0413    /* demand paging */
21
22 struct bhdr {
23         long    magic;
24         long    tsize;
25         long    dsize;
26         long    bsize;
27         long    ssize;
28         long    entry;
29         long    rtsize;
30         long    rdsize;
31 };
32
33 struct machrelo {
34         long    address;
35         long    relodata;
36 };
37 #define setpcrel(X,f)   (X |= (f<<7))
38 #define setsymbolnum(X,n)       (X = (X & 0377) | ((long)n << 8))
39 #define setextern(X,f)  (X |= (f << 4))
40 #define setlength(X,l)  (X = (X & ~0x60)|((long) l << 5))
41
42 struct sym {
43         long    name;
44         char    type;
45         char    other;
46         short   desc;
47         long    value;
48 };
49
50 #define N_UNDF  0
51 #define N_ABS   02
52 #define N_TEXT  04
53 #define N_DATA  06
54 #define N_BSS   010
55 #define N_EXT   01
56 #define N_FN    0x1f
57
58 /*
59  * Header and section table of new format object file.
60  */
61 struct outhead  outhead;
62 struct outsect  outsect[S_MAX];
63
64 char    *output_file;
65 int     outputfile_created;
66 long magic;
67
68 int rom_in_data;
69
70 char *program ;
71
72 char flag ;
73
74 /* Output file definitions and such */
75
76 struct bhdr bh;
77
78 #define ENTRY 0x0
79 #define TOT_HDRSIZE     (sizeof(struct bhdr))
80
81
82
83 #define TEXTSG  0
84 #define ROMSG   1
85 #define DATASG  2
86 #define BSSSG   3
87 #define LSECT   BSSSG+1
88 #define NSECT   LSECT+1
89
90 int             output;
91
92 int     unresolved;
93 int     nflag;
94 long    textsize ; 
95 long    datasize ;
96 long    bsssize;
97
98 long align(a,b)
99         long a,b;
100 {
101         a += b - 1;
102         return a - a % b;
103 }
104
105 int
106 follows(pa, pb)
107         register struct outsect *pa, *pb;
108 {
109         /* return 1 if pa follows pb */
110
111         return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
112 }
113
114 main(argc, argv)
115         int     argc;
116         char    *argv[];
117 {
118         register int            nsect;
119
120         program= argv[0] ;
121         while ( argc>1 && argv[1][0]=='-' ) {
122                 flag=argv[1][1] ;
123                 if (flag == 'u') unresolved++;
124                 else if (flag == 'n') nflag = 1;
125                 argc-- ; argv++ ;
126         }
127         switch (argc) {
128         case 3: if ((output = creat(argv[2], 0644)) < 0 ||
129                     (close(output), output = open(argv[2],2)) < 0)
130                         fatal("Can't write %s.\n", argv[2]);
131                 output_file = argv[2];
132                 outputfile_created = 1;
133                 if (! rd_open(argv[1]))
134                         fatal("Can't read %s.\n", argv[1]);
135                 break;
136         default:fatal("Usage: %s [-u] [-n] <ACK object> <Vax object>.\n", program);
137         }
138         rd_ohead(&outhead);
139         if (BADMAGIC(outhead))
140                 fatal("Not an ack object file.\n");
141         if (outhead.oh_flags & HF_LINK) {
142                 if (! unresolved) {
143                         fprintf(stderr,"Warning: contains unresolved references.\n");
144                 }
145                 unresolved++;
146         }
147         else if (outhead.oh_nrelo > 0 && !unresolved)
148                 fprintf(stderr, "Warning: relocation information present.\n");
149         if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
150                 fatal("Input file must have %d sections, not %ld\n",
151                         NSECT,outhead.oh_nsect) ;
152         rd_sect(outsect, outhead.oh_nsect);
153         /* A few checks */
154         if ( outsect[BSSSG].os_flen != 0 )
155                 fatal("bss space contains initialized data\n") ;
156         if ( !unresolved) {
157                 if (! follows(&outsect[BSSSG], &outsect[DATASG]))
158                         fatal("bss segment must follow data segment\n") ;
159                 if (! follows(&outsect[ROMSG],&outsect[TEXTSG]))
160                         fatal("rom segment must follow text\n") ;
161                 if (! follows(&outsect[DATASG], &outsect[ROMSG]))
162                         fatal("data segment must follow rom\n") ;
163         }
164         outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
165         outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
166         outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
167         if ( outsect[ROMSG].os_lign == 0x400 ) {
168                 /* 410/413 file with ROMSG in data space */
169                 rom_in_data = 1;
170                 magic= NMAGIC ;
171                 textsize= outsect[TEXTSG].os_size;
172                 datasize= outsect[ROMSG].os_size + outsect[DATASG].os_size ;
173         } else
174         if ( outsect[DATASG].os_lign == 0x400 ) {
175                 /* 410/413 file with ROMSG in instruction space */
176                 rom_in_data = 0;
177                 magic= NMAGIC ;
178                 textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
179                 datasize= outsect[DATASG].os_size ;
180         } else {
181                 /* Plain 407 file */
182                 rom_in_data = 0;
183                 magic= OMAGIC ;
184                 textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
185                 datasize = outsect[DATASG].os_size;
186         }
187         bsssize = outsect[BSSSG].os_size;
188         if (nflag && magic != NMAGIC) {
189                 fatal("illegal alignments.\n");
190         }
191         if (magic == NMAGIC && ! nflag) {
192                 if (datasize & 0x3ff) {
193                         int diff = 0x400 - (datasize & 0x3ff);
194
195                         if (bsssize >= diff) bsssize -= diff;
196                         else bsssize = 0;
197                         outsect[DATASG].os_size += diff;
198                         datasize += diff;
199                 }
200                 magic = ZMAGIC;
201         }
202         if ( outhead.oh_nsect==NSECT ) {
203                 if (! follows(&outsect[LSECT],&outsect[BSSSG]))
204                         fatal("end segment must follow bss\n") ;
205                 if ( outsect[LSECT].os_size != 0 )
206                         fatal("end segment must be empty\n") ;
207         }
208
209         if (magic != OMAGIC && unresolved) {
210                 fatal("unresolved references with wrong magic number\n");
211         }
212
213         if (outsect[TEXTSG].os_base != ENTRY) {
214                 fatal("Illegal entry point.\n");
215         }
216
217         bh.magic = magic;
218         bh.tsize = textsize;
219         bh.bsize = bsssize;
220         bh.dsize = datasize;
221         bh.rtsize = 0;
222         bh.rdsize = 0;
223         bh.entry = ENTRY;
224
225         /* Action at last */
226         if (magic == ZMAGIC)  {
227                 lseek(output,(long) 0x400, 0);
228         }
229         else    lseek(output,(long) TOT_HDRSIZE,0);
230         emits(&outsect[TEXTSG]) ;
231         emits(&outsect[ROMSG]) ;
232         emits(&outsect[DATASG]) ;
233         if (unresolved) emit_relo();
234         emit_symtab();
235         bh.ssize = outhead.oh_nname * sizeof(struct sym);
236         lseek(output,0L,0);
237         cvlong(&(bh.magic));
238         cvlong(&(bh.tsize));
239         cvlong(&(bh.dsize));
240         cvlong(&(bh.bsize));
241         cvlong(&(bh.ssize));
242         cvlong(&(bh.entry));
243         cvlong(&(bh.rtsize));
244         cvlong(&(bh.rdsize));
245         writef(&bh, 1, (long) TOT_HDRSIZE);
246         if ( outputfile_created  && !unresolved ) chmod(argv[2],0755);
247         exit(0);
248 }
249
250 writef(addr,sz,cnt)
251         char *addr;
252         long cnt;
253 {
254         cnt *= sz;
255
256         while (cnt) {
257                 int i = cnt >= 0x4000 ? 0x4000 : cnt;
258
259                 cnt -= i;
260                 if (write(output, addr, i) < i) {
261                         fatal("write error\n");
262                 }
263                 addr += i;
264         }
265 }
266
267 /*
268  * Transfer the emitted byted from one file to another.
269  */
270 emits(section) struct outsect *section ; {
271         char            *p;
272         char            *calloc(), *malloc();
273         long sz = section->os_flen;
274
275         rd_outsect(section - outsect);
276         while (sz) {
277                 unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
278                 if (!(p = malloc(i))) {
279                         fatal("No memory.\n");
280                 }
281                 rd_emit(p, i);
282                 if (write(output, p, i) < i) {
283                         fatal("write error.\n");
284                 }
285                 free(p);
286                 sz -= i;
287         }
288
289         sz = section->os_size - section->os_flen;
290         if (sz) {
291                 if (!(p = calloc(0x4000, 1))) {
292                         fatal("No memory.\n");
293                 }
294                 while (sz) {
295                         unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
296                         if (write(output, p, i) < i) {
297                                 fatal("write error.\n");
298                         }
299                         sz -= i;
300                 }
301                 free(p);
302         }
303 }
304
305 struct outname *ACKnames;
306
307 emit_relo()
308 {
309         struct outrelo *ACKrelo;
310         struct machrelo *MACHtrelo,*MACHdrelo;
311         register struct outrelo *ap;
312         register struct machrelo *mtp, *mdp;
313         unsigned int cnt = outhead.oh_nrelo;
314
315         ACKrelo = (struct outrelo *) calloc(cnt, sizeof(struct outrelo));
316         MACHtrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
317         MACHdrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
318         ACKnames = (struct outname *) calloc(outhead.oh_nname, sizeof(struct outname));
319         if (!(ap = ACKrelo) || !(mtp = MACHtrelo) || !(mdp = MACHdrelo) ||
320             !ACKnames) {
321                 fatal("No memory.\n");
322         }
323         rd_relo(ACKrelo, cnt);
324         rd_name(ACKnames, outhead.oh_nname);
325         while (cnt-- != 0) {
326                 register struct machrelo *mp;
327
328                 if (ap->or_sect - S_MIN <= ROMSG) mp = mtp++;
329                 else mp = mdp++;
330                 setlength(mp->relodata,(ap->or_type&RELSZ) >> 1);
331                 setpcrel(mp->relodata,(ap->or_type&RELPC != 0));
332                 mp->address = ap->or_addr;
333                 if (ap->or_sect == ROMSG+S_MIN) {
334                         mp->address += outsect[TEXTSG].os_size;
335                 }
336                 if (ap->or_nami < outhead.oh_nname) {
337                         if (ACKnames[ap->or_nami].on_type & S_EXT) {
338                                 setsymbolnum(mp->relodata, ap->or_nami);
339                                 setextern(mp->relodata,1);
340                         }
341                         else {
342                                 patch(ap, &ACKnames[ap->or_nami], mp);
343                         }
344                 }
345                 else {
346                         setsymbolnum(mp->relodata, N_ABS);
347                 }
348                 cvlong(&(mp->address));
349                 cvlong(&(mp->relodata));
350                 ap++;
351         }
352         bh.rtsize = (char *) mtp - (char *) MACHtrelo;
353         bh.rdsize = (char *) mdp - (char *) MACHdrelo;
354         writef(MACHtrelo, 1, bh.rtsize);
355         writef(MACHdrelo, 1, bh.rdsize);
356         free(ACKrelo);
357         free(MACHtrelo);
358         free(MACHdrelo);
359 }
360
361 long
362 get(sz)
363 {
364         char buf[10];
365         long l = 0;
366         register char *p = buf + sz;
367
368         read(output,buf,sz);
369         while (sz--) {
370                 l = (l << 8) | (*--p & 0377);
371         }
372         return l;
373 }
374
375 put(l,sz)
376         long l;
377 {
378         char buf[10];
379         register char *p = buf;
380
381         *p++ = l;
382         *p++ = l >> 8;
383         *p++ = l >> 16;
384         *p++ = l >> 24;
385         p -= sz;
386         if (write(output, p, sz) < sz) {
387                 fatal("write error.\n");
388         }
389 }
390
391 patch(ap, an, mp)
392         register struct outrelo *ap;
393         register struct outname *an;
394         register struct machrelo *mp;
395 {
396         int whichsect = (an->on_type & S_TYP) - S_MIN;
397         long correction = 0;
398         long where = TOT_HDRSIZE+ap->or_addr;
399         long X;
400         long here;
401         int sz;
402
403         if (!(an->on_type & S_SCT)) {
404                 fprintf(stderr,"funny on_type %x\n", an->on_type);
405         }
406         switch(whichsect) {
407         case TEXTSG:
408                 setsymbolnum(mp->relodata,N_TEXT);
409                 return;
410         case DATASG:
411                 correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size;
412                 setsymbolnum(mp->relodata,N_DATA);
413                 break;
414         case ROMSG:
415                 correction = outsect[TEXTSG].os_size;
416                 setsymbolnum(mp->relodata,N_TEXT);
417                 break;
418         case BSSSG:
419                 correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size+
420                                 outsect[DATASG].os_size;
421                 setsymbolnum(mp->relodata,N_BSS);
422                 break;
423         default:
424                 assert(0);
425         }
426
427         switch(ap->or_sect - S_MIN) {
428         case DATASG:
429                 where += outsect[ROMSG].os_size;
430         case ROMSG:
431                 where += outsect[TEXTSG].os_size;
432         case TEXTSG:
433                 break;
434         default:
435                 assert(0);
436         }
437         here = lseek(output, 0L, 1);
438         lseek(output, where, 0);
439         sz = ap->or_type & RELSZ;
440         X = get(sz) + correction;
441         lseek(output, where, 0);
442         put(X,sz);
443         lseek(output, here, 0);
444 }
445
446 cvlong(l)
447         long *l;
448 {
449         long x = *l;
450         char *p = (char *) l;
451
452         *p++ = x;
453         *p++ = x >> 8;
454         *p++ = x >> 16;
455         *p++ = x >> 24;
456 }
457
458 cvshort(s)
459         short *s;
460 {
461         int x = *s;
462         char *p = (char *) s;
463
464         *p++ = x;
465         *p = x >> 8;
466 }
467
468 int
469 is_rest_local(A, i)
470         register int i;
471         register struct outname *A;
472 {
473         while (i--) {
474                 if (A->on_type & S_EXT) return 0;
475                 A++;
476         }
477         return 1;
478 }
479
480 emit_symtab()
481 {
482         register unsigned short i = outhead.oh_nname;
483         register struct outname *A;
484         struct sym *MACHnames;
485         register struct sym *M;
486         extern char *malloc(), *calloc();
487         char *chars;
488         long offX = OFF_CHAR(outhead) - 4;
489
490         if (!(A = ACKnames)) {
491                 if (!(A = (struct outname *)
492                         calloc(i, sizeof(struct outname)))) {
493                         fatal("No memory.\n");
494                 }
495                 rd_name(A, outhead.oh_nname);
496         }
497         if (!(M = (struct sym *) calloc(i, sizeof(struct sym)))) {
498                 fatal("No memory.\n");
499         }
500         MACHnames = M;
501         ACKnames = A;
502         for (; i; i--, A++) {
503                 M->value = A->on_valu;
504                 M->desc = A->on_desc;
505                 if ((A->on_type & S_SCT) ||
506                     (A->on_type & S_ETC) == S_FIL) {
507                         static int rest_local;
508                         if (! unresolved || rest_local || (rest_local = is_rest_local(A, i))) {
509                                 outhead.oh_nname--;
510                                 continue;
511                         }
512                 }
513                 if (A->on_type & S_STB) {
514                         M->type = A->on_type >> 8;
515                 }
516                 else if (A->on_type & S_COM) {
517                         M->type = N_UNDF | N_EXT;
518                 }
519                 else switch(A->on_type & S_TYP) {
520                         case S_UND:
521                                 switch(A->on_type & S_ETC) {
522                                 default:
523                                         M->type = N_UNDF;
524                                         break;
525                                 case S_MOD:
526                                         M->type = N_FN;
527                                         break;
528                                 case S_LIN:
529                                         M->type = N_ABS;
530                                         break;
531                                 }
532                                 break;
533                         case S_ABS:
534                                 M->type = N_ABS;
535                                 break;
536                         case S_MIN + TEXTSG:
537                                 M->type = N_TEXT; 
538                                 break;
539                         case S_MIN + ROMSG:
540                                 if (unresolved) {
541                                         M->value += outsect[TEXTSG].os_size;
542                                 }
543                                 M->type = (rom_in_data ? N_DATA : N_TEXT);
544                                 break;
545                         case S_MIN + DATASG:
546                                 if (unresolved) {
547                                         M->value += outsect[TEXTSG].os_size +
548                                                     outsect[ROMSG].os_size;
549                                 }
550                                 M->type = N_DATA;
551                                 break;
552                         case S_MIN + BSSSG:
553                                 if (unresolved) {
554                                         M->value += outsect[TEXTSG].os_size +
555                                                     outsect[ROMSG].os_size +
556                                                     outsect[DATASG].os_size;
557                                 }
558                                 M->type = N_BSS;
559                                 break;
560                         case S_MIN + LSECT:
561                                 M->type = N_BSS;
562                                 break;
563                         default:
564                                 fprintf(stderr,"warning: unknown s_type: %d\n",
565                                         A->on_type & S_TYP);
566                 }
567                 if (A->on_type & S_EXT) M->type |= N_EXT;
568                 M->name = A->on_foff;
569                 M++;
570         }
571         M = MACHnames;
572         for (i = outhead.oh_nname; i; i--, M++) {
573                 if (M->name) {
574                         M->name -= offX;
575                 }
576                 else M->name = outhead.oh_nchar + 3;    /* pointer to nullbyte */
577                 cvlong(&(M->name));
578                 cvlong(&(M->value));
579                 cvshort(&(M->desc));
580         }
581         writef(MACHnames, sizeof(struct sym), (long) outhead.oh_nname);
582         free(MACHnames);
583         free(ACKnames);
584         if ((unsigned) outhead.oh_nchar != outhead.oh_nchar ||
585             !( chars = malloc((unsigned) outhead.oh_nchar))) {
586                 fatal("No memory\n.");
587         }
588         put(outhead.oh_nchar+4,4);
589         rd_string(chars,outhead.oh_nchar);
590         writef(chars, 1, outhead.oh_nchar);
591         free(chars);
592 }
593
594 /* VARARGS1 */
595 fatal(s, a1, a2)
596         char    *s;
597 {
598         fprintf(stderr,"%s: ",program) ;
599         fprintf(stderr, s, a1, a2);
600         if (outputfile_created)
601                 unlink(output_file);
602         exit(-1);
603 }
604
605 rd_fatal() { fatal("read error.\n"); }