Pristine Ack-5.5
[Ack-5.5.git] / mach / m68020 / cv / cv.c
1 /* $Id: cv.c,v 1.7 1994/06/24 13:06:07 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 /* This is a special cv.c program for testing purposes ;
7  * it converts to a stripped version of COFF
8  */
9
10 #include <stdio.h>
11
12 typedef struct filehdr {
13         unsigned short  f_magic;        /* magic number */
14         unsigned short  f_nscns;        /* number of sections */
15         long            f_timdat;       /* time & date stamp */
16         long            f_symptr;       /* file pointer to symtab */
17         long            f_nsyms;        /* number of symtab entries */
18         unsigned short  f_opthdr;       /* sizeof(optional hdr) */
19         unsigned short  f_flags;        /* flags */
20 } FILHDR;
21
22 typedef struct aouthdr {
23         short   magic;
24         short   vstamp; 
25         long    tsize;
26         long    dsize;
27         long    bsize;
28         long    entry;
29         long    text_start;
30         long    data_start;
31 } AOUTHDR;
32
33 typedef struct scnhdr {
34         char            s_name[8];
35         long            s_paddr;
36         long            s_vaddr;
37         long            s_size;
38         long            s_scnptr;
39         long            s_relptr;
40         long            s_lnnoptr;
41         unsigned short  s_nreloc;
42         unsigned short  s_nlnno;
43         long            s_flags;
44 } SCNHDR;
45
46 #define AOUTHSZ sizeof(AOUTHDR)
47 #define SCNHSZ  sizeof(SCNHDR)
48 #define FILHSZ  sizeof(FILHDR)
49
50 #include <out.h>
51
52 #define ASSERT(x) switch (2) { case 0: case (x): ; }
53
54 /*
55  * Header and section table of new format object file.
56  */
57 struct outhead  outhead;
58 struct outsect  outsect[S_MAX];
59
60 char    *output_file;
61 int     outputfile_created;
62
63 int rom_in_data;
64
65 char *program ;
66
67 char flag ;
68
69 #define readf(a, b, c)  fread((a), (b), (int)(c), input)
70 #define writef(a, b, c) fwrite((a), (b), (int)(c), output)
71
72 /* Output file definitions and such */
73
74 #define TS 0
75 #define DS 1
76 #define BS 2
77 #define NS 3
78
79 FILHDR  filh;
80 AOUTHDR aouth;
81 SCNHDR  scnh[NS];
82
83 #define ENTRY 0
84 #define MC68MAGIC 0520
85 #define MYFLAGS 01017
86
87 #define STYP_TEXT 0x20
88 #define STYP_DATA 0x40
89 #define STYP_BSS  0x80
90
91 #define _TEXT ".text"
92 #define _DATA ".data"
93 #define _BSS  ".bss"
94
95 #define TEXTSG  0
96 #define ROMSG   1
97 #define DATASG  2
98 #define BSSSG   3
99 #define LSECT   BSSSG+1
100 #define NSECT   LSECT+1
101
102
103 FILE            *input;
104 FILE            *output;
105
106 long align(a,b)
107         long a,b;
108 {
109         a += b - 1;
110         return a - a % b;
111 }
112
113 int
114 follows(pa, pb)
115         register struct outsect *pa, *pb;
116 {
117         /* return 1 if pa follows pb */
118
119         return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
120 }
121
122 main(argc, argv)
123         int     argc;
124         char    *argv[];
125 {
126         register int            nsect;
127         long                    magic ;
128         long                    textsize, datasize, bsssize;
129         extern long             ftell();
130         long                    filepos;
131         int                     scn;
132
133         ASSERT(sizeof(struct outhead) == SZ_HEAD);
134         ASSERT(sizeof(struct outsect) == SZ_SECT);
135
136         input = stdin; output = stdout;
137         program= argv[0] ;
138         if ( argc>1 && argv[1][0]=='-' ) {
139                 flag=argv[1][1] ;
140                 argc-- ; argv++ ;
141         }
142         switch (argc) {
143         case 1: break;
144         case 3: if ((output = fopen(argv[2], "w")) == (FILE *)0)
145                         fatal("Can't write %s.\n", argv[2]);
146                 output_file = argv[2];
147                 outputfile_created = 1;
148                 /* FALLTHROUGH */
149         case 2: if ((input = fopen(argv[1], "r")) == (FILE *)0)
150                         fatal("Can't read %s.\n", argv[1]);
151                 break;
152         default:fatal("Usage: %s <as object> <dl object>.\n", argv[0]);
153         }
154         if ( !rhead(input,&outhead) )
155                 fatal("Reading header failed.\n");
156         if (BADMAGIC(outhead))
157                 fatal("Not an ack object file.\n");
158         if (outhead.oh_nrelo > 0)
159                 fprintf(stderr, "Warning: relocation information present.\n");
160         if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
161                 fatal("Input file must have %d sections, not %ld\n",
162                         NSECT,outhead.oh_nsect) ;
163         for ( nsect=0 ; nsect<outhead.oh_nsect ; nsect++ )
164                 if ( !rsect(input,&outsect[nsect]) )
165                         fatal("Reading section table failed.\n");
166         /* A few checks */
167         if ( outsect[TEXTSG].os_base != ENTRY)
168                 fatal("text must start at %lx not at 0x%lx\n", ENTRY,
169                         outsect[TEXTSG].os_base) ;
170         if ( outsect[BSSSG].os_flen != 0 )
171                 printf("Warning: bss space contains initialized data\n") ;
172                         /* as actually writes zeroes in the bss segment */
173         if ( ! follows(&outsect[BSSSG], &outsect[DATASG]))
174                 fatal("bss segment must follow data segment\n") ;
175
176         /* 410 file with ROMSG in instruction space */
177         rom_in_data = 0;
178         magic= 0410 ;
179         textsize= (outsect[ROMSG].os_base - outsect[TEXTSG].os_base) 
180                         + outsect[ROMSG].os_size ;
181         datasize= outsect[BSSSG].os_base - outsect[DATASG].os_base ;
182         if ( ! follows(&outsect[ROMSG], &outsect[TEXTSG]))
183                 fatal("rom segment must follow text\n") ;
184
185         outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
186         outsect[DATASG].os_size = datasize;
187         bsssize = outsect[BSSSG].os_size;
188         if ( outhead.oh_nsect==NSECT ) {
189                 if ( ! follows(&outsect[LSECT], &outsect[BSSSG]))
190                         fatal("end segment must follow bss\n") ;
191                 if ( outsect[LSECT].os_size != 0 )
192                         fatal("end segment must be empty\n") ;
193         }
194
195         filh.f_magic    = MC68MAGIC;
196         filh.f_nscns    = 3;    /* three sections: .text, data, .bss */
197         filh.f_timdat   = (long) time(0); /* doesn't really matter */
198         filh.f_symptr   = 0L;   /* no symbol table */
199         filh.f_nsyms    = 0L;   /* ditto */
200         filh.f_opthdr   = AOUTHSZ;
201         filh.f_flags    = MYFLAGS;
202
203         aouth.magic     = magic;
204         aouth.vstamp    = 0;
205         aouth.tsize     = textsize;
206         aouth.dsize     = datasize;
207         aouth.bsize     = bsssize;
208         aouth.entry     = ENTRY;
209         aouth.text_start= ENTRY;
210         aouth.data_start= outsect[DATASG].os_base;
211
212         strcpy(scnh[TS].s_name, _TEXT);
213         strcpy(scnh[DS].s_name, _DATA);
214         strcpy(scnh[BS].s_name, _BSS);
215
216         scnh[TS].s_vaddr = (scnh[TS].s_paddr = aouth.text_start);
217         scnh[DS].s_vaddr = (scnh[DS].s_paddr = aouth.data_start);
218         scnh[BS].s_vaddr = (scnh[BS].s_paddr = aouth.data_start + datasize);
219
220         scnh[TS].s_size = textsize;
221         scnh[DS].s_size = datasize;
222         scnh[BS].s_size = bsssize;
223
224         scnh[TS].s_scnptr = FILHSZ + AOUTHSZ + 3 * SCNHSZ;
225         scnh[DS].s_scnptr = FILHSZ + AOUTHSZ + 3 * SCNHSZ + textsize;
226         scnh[BS].s_scnptr = 0L; /* always 0 for .bss section */
227
228         for (scn=TS; scn<=BS; scn++) {
229                 scnh[scn].s_relptr = 0L;        /* no relocation */
230                 scnh[scn].s_lnnoptr = 0L;       /* no line numbers */
231                 scnh[scn].s_nreloc = 0;         /* no relocation */
232                 scnh[scn].s_nlnno = 0;          /* no line numbers */
233         }
234
235         scnh[TS].s_flags = STYP_TEXT;
236         scnh[DS].s_flags = STYP_DATA;
237         scnh[BS].s_flags = STYP_BSS;
238
239         /* now write the new file headers */
240         ffwrite(&filh, FILHSZ, 1);
241         ffwrite(&aouth, AOUTHSZ, 1);
242         ffwrite(scnh, SCNHSZ, 3);       /* write all three section headers */
243
244         emits(&outsect[TEXTSG]) ;
245         emits(&outsect[ROMSG]) ;
246         emits(&outsect[DATASG]) ;
247
248         if ( outputfile_created ) chmod(argv[2],0755);
249         return 0;
250 }
251
252 ffwrite(ptr, size, nitems)
253 char *ptr;
254 {
255         writef(ptr, size, nitems);
256         if (ferror(output))
257                 fatal("output write error\n");
258 }
259
260 /*
261  * Transfer the emitted bytes from one file to another.
262  */
263 emits(section) struct outsect *section ; {
264         register long   n ;
265         register int    blk;
266         char            buffer[BUFSIZ];
267
268         n= section->os_flen ;
269         while (n > 0) {
270                 blk = n > BUFSIZ ? BUFSIZ : n;
271                 readf(buffer, 1, blk);
272                 writef(buffer, 1, blk);
273                 n -= blk;
274         }
275         if ((n=section->os_size - section->os_flen) > 0) {
276                 fseek(output, n-1, 1);
277                 writef("\0",1,1);
278         }
279 }
280
281
282 rhead(f,head) struct outhead *head ; FILE *f ; {
283         char buf[SZ_HEAD] ;
284         if ( fread(buf,SZ_HEAD,1,f)!=1 ) return 0 ;
285         iconvert(buf,(char *)head,SF_HEAD) ;
286         return 1 ;
287 }
288
289 rsect(f,sect) struct outsect *sect ; FILE *f ; {
290         char buf[SZ_SECT] ;
291         if ( fread(buf,SZ_SECT,1,f)!=1 ) return 0 ;
292         iconvert(buf,(char *)sect,SF_SECT) ;
293         return 1 ;
294 }
295
296
297 iconvert(buf,str,fmt) char *buf, *str, *fmt ; {
298         register char *nf, *ni, *no ;
299         int last, i ;
300         long value ;
301         ni=buf ; no=str ; nf=fmt ;
302         while ( last = *nf++ ) {
303                 last -= '0' ;
304                 if ( last<1 || last >9 ) fatal("illegal out.h format string\n");
305                 value=0 ;
306                 i=last ;
307                 while ( i-- ) {
308                         value = (value<<8) + (ni[i]&0xFF) ;
309                 }
310                 switch ( last ) {
311                 case 0 : break ;
312                 case 1 : *no= value ; break ;
313                 case 2 : *(unsigned short *)no = value ; break ;
314                 case 4 : *(long *)no = value ; break ;
315                 default :
316                          fatal("illegal out.h format string\n");
317                 }
318                 ni += last ; no += last ;
319         }
320 }
321
322
323 /* VARARGS1 */
324 fatal(s, a1, a2)
325         char    *s;
326 {
327         fprintf(stderr,"%s: ",program) ;
328         fprintf(stderr, s, a1, a2);
329         if (outputfile_created)
330                 unlink(output_file);
331         exit(-1);
332 }