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