Pristine Ack-5.5
[Ack-5.5.git] / mach / m68k2 / 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 #include <stdio.h>
8 #include "out.h"
9
10 #ifndef NORCSID
11 static char rcs_id[] = "$Id: cv.c,v 2.6 1994/06/24 13:03:23 ceriel Exp $" ;
12 #endif
13
14 /* BUG:
15    There is a problem with Bleasdale 'nm' and the namelist produced
16    by this program.
17    nm always acts as if there were no name list, while adb
18    understands a.out's with namelists without any complaint.
19    The cause is unclear. All sizes in the header and file are correct.
20    Setting the symbol table size to a size smaller than actually
21    present in the a.out causes 'adb' to produce error messages
22    about name list problems, but nm suddenly prints the namelist,
23    INCLUDING the entrie outside the size indicated in the a.out header.
24 */
25 #define ASSERT(x) switch (2) { case 0: case (x): ; }
26
27 /*
28  * Header and section table of new format object file.
29  */
30 struct outhead  outhead;
31 struct outsect  outsect[S_MAX];
32 char            *stringarea ;
33
34 char    *ofile;
35 int     ofile_created;
36
37 char *program ;
38
39 char flag ;
40
41 #define readf(a, b, c)  fread((a), (b), (int)(c), input)
42 #define writef(a, b, c) fwrite((a), (b), (int)(c), output)
43
44 /* Output file definitions and such */
45
46 #define HDR_LENGTH      32
47
48 char hdr[HDR_LENGTH] ;
49
50 #define TEXT    0
51 #define ROM     1
52 #define DATA    2
53 #define BSS     3
54 #define LSECT   BSS+1
55 #define NSECT   LSECT+1
56
57
58 #define N_EXT   040
59 #define N_UNDEF 00
60 #define N_ABS   01
61 #define N_TEXT  02
62 #define N_DATA  03
63 #define N_BSS   04
64 #define N_FN    037
65
66 FILE            *input;
67 FILE            *output;
68
69 long align(a,b)
70         long a,b;
71 {
72         a += b - 1;
73         return a - a % b;
74 }
75  
76 int
77 follows(pa, pb)
78         register struct outsect *pa, *pb;
79 {
80         /* return 1 if pa follows pb */
81  
82         return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
83 }
84
85 main(argc, argv)
86         int     argc;
87         char    *argv[];
88 {
89         register int            nsect;
90         long                    magic ;
91         long                    textsize ;
92         long                    datasize ;
93
94         ASSERT(sizeof(struct outhead) == SZ_HEAD);
95         ASSERT(sizeof(struct outsect) == SZ_SECT);
96
97         input = stdin; output = stdout;
98         program= argv[0] ;
99         if ( argc>1 && argv[1][0]=='-' ) {
100                 flag=argv[1][1] ;
101                 argc-- ; argv++ ;
102         }
103         switch (argc) {
104         case 1: break;
105         case 3: if ((output = fopen(argv[2], "w")) == (FILE *)0)
106                         fatal("Can't write %s.\n", argv[2]);
107                 ofile = argv[2];
108                 ofile_created = 1;
109                 /* FALLTHROUGH */
110         case 2: if ((input = fopen(argv[1], "r")) == (FILE *)0)
111                         fatal("Can't read %s.\n", argv[1]);
112                 break;
113         default:fatal("Usage: %s <as object> <dl object>.\n", argv[0]);
114         }
115         if ( !rhead(input,&outhead) )
116                 fatal("Reading header failed.\n");
117         if (BADMAGIC(outhead))
118                 fatal("Not an ack object file.\n");
119         if (outhead.oh_nrelo > 0)
120                 fprintf(stderr, "Warning: relocation information present.\n");
121         if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
122                 fatal("Input file must have %d sections, not %ld\n",
123                         NSECT,outhead.oh_nsect) ;
124         for ( nsect=0 ; nsect<outhead.oh_nsect ; nsect++ )
125                 if ( !rsect(input,&outsect[nsect]) )
126                         fatal("Reading section table failed.\n");
127         /* A few checks */
128         if ( outsect[TEXT].os_base != 0x20000 )
129                 fatal("text must start at 0x20000 not at 0x%lx\n",
130                         outsect[TEXT].os_base) ;
131         if ( outsect[BSS].os_flen != 0 )
132                 fatal("bss space contains initialized data\n") ;
133         if ( ! follows(&outsect[BSS], &outsect[DATA]))
134                 fatal("bss segment must follow data segment\n") ;
135         if ( outsect[ROM].os_lign == 0x8000 ) {
136                 /* 410 file with ROM in data space */
137                 if ( ! follows(&outsect[DATA], &outsect[ROM]))
138                         fatal("data segment must follow rom\n") ;
139                 magic= 0410 ;
140                 textsize= outsect[TEXT].os_size ;
141                 datasize= outsect[BSS].os_base - outsect[ROM].os_base ;
142                 outsect[ROM].os_size = outsect[DATA].os_base - outsect[ROM].os_base;
143                 outsect[DATA].os_size = outsect[BSS].os_base - outsect[DATA].os_base;
144         } else
145         if ( outsect[DATA].os_lign == 0x8000 ) {
146                 /* 410 file with ROM in instruction space */
147                 if ( ! follows(& outsect[ROM], &outsect[TEXT].os_base))
148                         fatal("rom segment must follow text\n") ;
149                 magic= 0410 ;
150                 outsect[TEXT].os_size = outsect[ROM].os_base - outsect[TEXT].os_base;
151                 textsize= outsect[TEXT].os_size + outsect[ROM].os_size ;
152                 datasize= outsect[BSS].os_base - outsect[DATA].os_base ;
153                 outsect[DATA].os_size = datasize;
154         } else {
155                 /* Plain 407 file */
156                 if ( ! follows(& outsect[ROM], &outsect[TEXT]))
157                         fatal("rom segment must follow text\n") ;
158                 if ( ! follows(& outsect[DATA], &outsect[ROM]))
159                         fatal("data segment must follow rom\n") ;
160                 magic= 0407 ;
161                 outsect[TEXT].os_size = textsize
162                         = outsect[ROM].os_base - outsect[TEXT].os_base;
163                 outsect[ROM].os_size = outsect[DATA].os_base - outsect[ROM].os_base;
164                 outsect[DATA].os_size = outsect[BSS].os_base - outsect[DATA].os_base;
165                 datasize= outsect[ROM].os_size + outsect[DATA].os_size ;
166         }
167         if ( outhead.oh_nsect==NSECT ) {
168                 if (! follows(&outsect[LSECT], &outsect[BSS]))
169                         fatal("end segment must follow bss\n") ;
170                 if ( outsect[LSECT].os_size != 0 )
171                         fatal("end segment must be empty\n") ;
172         }
173
174         /* Action at last */
175         fseek(output,(long)sizeof(hdr),0);
176         emits(&outsect[TEXT]) ;
177         emits(&outsect[ROM]) ;
178         emits(&outsect[DATA]) ;
179         names() ;
180         set4(hdr,0,magic) ;
181         set4(hdr,4,textsize) ;
182         set4(hdr,8,datasize) ;
183         set4(hdr,12,outsect[BSS].os_size) ;
184         set4(hdr,28,0x20000L) ; /* Entry point */
185         fseek(output,0L,0);
186         fwrite(hdr,sizeof(hdr),1,output);
187         if ( ferror(output) ) {
188                 fatal("output write error\n") ;
189         }
190         if ( ofile_created ) chmod(argv[2],0755);
191         return 0;
192 }
193
194 /*
195  * Transfer the emitted byted from one file to another.
196  * and zero fill the uninitialized space
197  */
198 emits(section) struct outsect *section ; {
199         register long   n ;
200         register int    blk;
201         char            buffer[BUFSIZ];
202
203         n= section->os_flen ;
204         while (n > 0) {
205                 blk = n > BUFSIZ ? BUFSIZ : n;
206                 readf(buffer, 1, blk);
207                 writef(buffer, 1, blk);
208                 n -= blk;
209         }
210         if ( section->os_flen!=section->os_size ) {
211                 for ( n=BUFSIZ-1 ; n ; n-- ) buffer[n]=0 ;
212                 n= section->os_size - section->os_flen ;
213                 while (n > 0) {
214                         blk = n > BUFSIZ ? BUFSIZ : n;
215                         writef(buffer, 1, blk);
216                         n -= blk;
217                 }
218         }
219 }
220
221 /*
222  * Copy the name table, except the last outhead.oh_nsect.
223  * These are assumed to be section names.
224  *
225  */
226 names()
227 {
228         register unsigned       n = outhead.oh_nname - outhead.oh_nsect;
229         int             type = 0 ;
230         struct outname  outname ;
231         char            buffer[100] ;
232         char            *s1, *s2 ;
233         long            length, fullength ;
234
235         fseek(input,OFF_CHAR(outhead),0) ;
236         chars() ;
237         if ( !stringarea ) return ;
238         fseek(input,OFF_NAME(outhead),0) ;
239         fullength=0 ; buffer[1]=0 ;
240         while (n--) {
241                 rname(input,&outname) ;
242                 if (outname.on_foff == 0)
243                         continue ;
244                 if (outname.on_type & S_ETC ) {
245                         switch (outname.on_type & S_ETC ) {
246                         /* ???
247                         case S_FIL :
248                                 type |= N_FN ;
249                         */
250                         case S_COM :
251                                 break ;
252                         default :
253                                 continue ;
254                         } 
255                 }
256                 set4(buffer,2,outname.on_valu ) ;
257                 switch (outname.on_type & S_TYP) {
258                 case S_UND:
259                         type = N_UNDEF;
260                         break;
261                 case S_ABS:
262                         type = N_ABS;
263                         break;
264                 case S_MIN + TEXT:
265                         type = N_TEXT;
266                         break;
267                 case S_MIN + DATA:
268                         type = N_DATA;
269                         break;
270                 case S_MIN + BSS:
271                 case S_MIN + LSECT:
272                         type = N_BSS;
273                         break ;
274                 }
275
276                 if (outname.on_type & S_EXT)
277                         type |= N_EXT;
278                 buffer[0]= type ;
279                 s1=buffer+6 ; s2= stringarea+outname.on_foff-OFF_CHAR(outhead);
280                 length= 6 ;
281                 while ( (++length<sizeof buffer) && (*s1++ = *s2++) ) ;
282                 buffer[sizeof buffer - 1]= 0 ; /* make sure of zero byte */
283                 writef(buffer, length, 1);
284                 fullength += length ;
285         }
286         /*
287          * The last outhead.oh_nsect names are discarded.
288          */
289         fseek(input, (long)(SZ_NAME * outhead.oh_nsect), 1);
290         set4(hdr,16,fullength) ;
291 }
292
293 /*
294  * Grab the string area preceded by the long that indicates its size.
295  *
296  */
297 chars()
298 {
299         register long   n = outhead.oh_nchar;
300         register int    blk;
301         char            *curr ;
302         extern char     *malloc() ;
303
304         if ( n==0 ) return ;
305         if ( (unsigned)n != n ) fatal("string table too large\n") ;
306         stringarea= malloc((unsigned)n) ;
307         if ( !stringarea ) fatal("string table too large\n") ;
308
309         curr= stringarea ;
310         while (n > 0) {
311                 blk = n > BUFSIZ ? BUFSIZ : n;
312                 readf(curr, 1, blk);
313                 curr += blk ;
314                 n -= blk;
315         }
316 }
317 rhead(f,head) struct outhead *head ; FILE *f ; {
318         char buf[SZ_HEAD] ;
319         if ( fread(buf,SZ_HEAD,1,f)!=1 ) return 0 ;
320         iconvert(buf,(char *)head,SF_HEAD) ;
321         return 1 ;
322 }
323
324 rsect(f,sect) struct outsect *sect ; FILE *f ; {
325         char buf[SZ_SECT] ;
326         if ( fread(buf,SZ_SECT,1,f)!=1 ) return 0 ;
327         iconvert(buf,(char *)sect,SF_SECT) ;
328         return 1 ;
329 }
330
331 rrelo(f,relo) struct outrelo *relo ; FILE *f ; {
332         char buf[SZ_RELO] ;
333         if ( fread(buf,SZ_RELO,1,f)!=1 ) return 0 ;
334         iconvert(buf,(char *)relo,SF_RELO) ;
335         return 1 ;
336 }
337
338 rname(f,name) struct outname *name ; FILE *f ; {
339         char buf[SZ_NAME] ;
340         if ( fread(buf,SZ_NAME,1,f)!=1 ) return 0 ;
341         iconvert(buf,(char *)name,SF_NAME) ;
342         return 1 ;
343 }
344
345 iconvert(buf,str,fmt) char *buf, *str, *fmt ; {
346         register char *nf, *ni, *no ;
347         int last, i ;
348         long value ;
349         ni=buf ; no=str ; nf=fmt ;
350         while ( last = *nf++ ) {
351                 last -= '0' ;
352                 if ( last<1 || last >9 ) fatal("illegal out.h format string\n");
353                 value=0 ;
354                 i=last ;
355                 while ( i-- ) {
356                         value = (value<<8) + (ni[i]&0xFF) ;
357                 }
358                 switch ( last ) {
359                 case 0 : break ;
360                 case 1 : *no= value ; break ;
361                 case 2 : *(unsigned short *)no = value ; break ;
362                 case 4 : *(long *)no = value ; break ;
363                 default :
364                          fatal("illegal out.h format string\n");
365                 }
366                 ni += last ; no += last ;
367         }
368 }
369
370 set2(buf,off,val) char *buf ; int val ; {
371         buf[off+0]      = val>>8 ;
372         buf[off+1]      = val ;
373 }
374
375 set4(buf,off,val) char *buf ; long val ; {
376         buf[off]        = val>>24 ;
377         buf[off+1]      = val>>16 ;
378         buf[off+2]      = val>>8 ;
379         buf[off+3]      = val ;
380 }
381
382 /* VARARGS1 */
383 fatal(s, a1, a2)
384         char    *s;
385 {
386         fprintf(stderr,"%s: ",program) ;
387         fprintf(stderr, s, a1, a2);
388         if (ofile_created)
389                 unlink(ofile);
390         exit(-1);
391 }