Pristine Ack-5.5
[Ack-5.5.git] / mach / mantra / cv / cv.c
1 /* $Id: cv.c,v 1.5 1994/06/24 13:08:25 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 #include <stdio.h>
9 #include <out.h>
10
11 #define FMAGIC  0407
12 #define NMAGIC  0410
13
14 struct bhdr {
15         long    fmagic;
16         long    tsize;
17         long    dsize;
18         long    bsize;
19         long    ssize;
20         long    rtsize;
21         long    rdsize;
22         long    entry;
23 };
24
25 struct sym {
26         char    stype;
27         char    sympad;
28         long    svalue;
29 };
30
31 #define N_UNDF  0
32 #define N_ABS   01
33 #define N_TEXT  02
34 #define N_DATA  03
35 #define N_BSS   04
36 #define N_EXT   040
37
38 #define ASSERT(x) switch (2) { case 0: case (x): ; }
39
40 /*
41  * Header and section table of new format object file.
42  */
43 struct outhead  outhead;
44 struct outsect  outsect[S_MAX];
45
46 char    *output_file;
47 int     outputfile_created;
48
49 int rom_in_data;
50
51 char *program ;
52
53 char flag ;
54
55 #define writef(a, b, c) fwrite((a), (b), (int)(c), output)
56
57 /* Output file definitions and such */
58
59 struct bhdr bh;
60
61 #define ENTRY 0x80000
62 #define TOT_HDRSIZE     (sizeof(struct bhdr))
63
64
65
66 #define TEXTSG  0
67 #define ROMSG   1
68 #define DATASG  2
69 #define BSSSG   3
70 #define LSECT   BSSSG+1
71 #define NSECT   LSECT+1
72
73 FILE            *output;
74
75 long align(a,b)
76         long a,b;
77 {
78         a += b - 1;
79         return a - a % b;
80 }
81  
82 int
83 follows(pa, pb)
84         register struct outsect *pa, *pb;
85 {
86         /* return 1 if pa follows pb */
87  
88         return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
89 }
90
91 main(argc, argv)
92         int     argc;
93         char    *argv[];
94 {
95         register int            nsect;
96         long                    magic ;
97         long                    textsize ;
98         long                    datasize ;
99         long                    bsssize;
100         long                    symstart;
101         extern long             ftell();
102
103         output = stdout;
104         program= argv[0] ;
105         if ( argc>1 && argv[1][0]=='-' ) {
106                 flag=argv[1][1] ;
107                 argc-- ; argv++ ;
108         }
109         switch (argc) {
110         case 3: if ((output = fopen(argv[2], "w")) == (FILE *)0)
111                         fatal("Can't write %s.\n", argv[2]);
112                 output_file = argv[2];
113                 outputfile_created = 1;
114                 if (! rd_open(argv[1]))
115                         fatal("Can't read %s.\n", argv[1]);
116                 break;
117         default:fatal("Usage: %s <ACK object> <Mantra object>.\n", argv[0]);
118         }
119         rd_ohead(&outhead);
120         if (BADMAGIC(outhead))
121                 fatal("Not an ack object file.\n");
122         if (outhead.oh_flags & HF_LINK)
123                 fatal("Contains unresolved references.\n");
124         if (outhead.oh_nrelo > 0)
125                 fprintf(stderr, "Warning: relocation information present.\n");
126         if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
127                 fatal("Input file must have %d sections, not %ld\n",
128                         NSECT,outhead.oh_nsect) ;
129         rd_sect(outsect, outhead.oh_nsect);
130         /* A few checks */
131         if ( outsect[TEXTSG].os_base != ENTRY)
132                 fatal("text must start at %d not at 0x%lx\n", ENTRY,
133                         outsect[TEXTSG].os_base) ;
134         if ( outsect[BSSSG].os_flen != 0 )
135                 fatal("bss space contains initialized data\n") ;
136         if ( ! follows(&outsect[BSSSG], &outsect[DATASG]))
137                 fatal("bss segment must follow data segment\n") ;
138         if ( outsect[ROMSG].os_lign == 0x8000 ) {
139                 /* 410 file with ROMSG in data space */
140                 if ( ! follows(&outsect[DATASG], &outsect[ROMSG]))
141                         fatal("data segment must follow rom\n") ;
142                 rom_in_data = 1;
143                 magic= NMAGIC ;
144                 textsize= outsect[TEXTSG].os_size ;
145                 datasize= outsect[BSSSG].os_base - outsect[ROMSG].os_base ;
146                 outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
147                 outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
148         } else
149         if ( outsect[DATASG].os_lign == 0x8000 ) {
150                 /* 410 file with ROMSG in instruction space */
151                 if ( ! follows(&outsect[ROMSG], &outsect[TEXTSG]))
152                         fatal("rom segment must follow text\n") ;
153                 rom_in_data = 0;
154                 magic= NMAGIC ;
155                 outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
156                 textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
157                 outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
158                 datasize= outsect[DATASG].os_size ;
159         } else {
160                 /* Plain 407 file */
161                 if ( ! follows(&outsect[ROMSG], &outsect[TEXTSG]))
162                         fatal("rom segment must follow text\n") ;
163                 if ( ! follows(&outsect[DATASG], &outsect[ROMSG]))
164                         fatal("data segment must follow rom\n") ;
165                 rom_in_data = 1;
166                 magic= FMAGIC ;
167                 outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
168                 outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
169                 outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
170                 textsize= outsect[TEXTSG].os_size ;
171                 datasize= outsect[ROMSG].os_size + outsect[DATASG].os_size ;
172         }
173         bsssize = outsect[BSSSG].os_size;
174         if ( outhead.oh_nsect==NSECT ) {
175                 if ( ! follows(&outsect[LSECT], &outsect[BSSSG]))
176                         fatal("end segment must follow bss\n") ;
177                 if ( outsect[LSECT].os_size != 0 )
178                         fatal("end segment must be empty\n") ;
179         }
180
181         bh.fmagic = magic;
182
183         bh.tsize = textsize;
184         bh.bsize = bsssize;
185         bh.dsize = datasize;
186         bh.entry = ENTRY;
187
188         /* Action at last */
189         fseek(output,(long) TOT_HDRSIZE,0);
190         emits(&outsect[TEXTSG]) ;
191         emits(&outsect[ROMSG]) ;
192         emits(&outsect[DATASG]) ;
193         symstart = ftell(output);
194         emit_symtab();
195         bh.ssize = ftell(output) - symstart;
196         fseek(output,0L,0);
197         write_header(&bh);
198         if ( ferror(output) ) {
199                 fatal("output write error\n") ;
200         }
201         if ( outputfile_created ) chmod(argv[2],0755);
202         return 0;
203 }
204
205 /*
206  * Transfer the emitted byted from one file to another.
207  */
208 emits(section) struct outsect *section ; {
209         char            *p;
210         char            *calloc();
211
212         rd_outsect(section - outsect);
213         if (!(p = calloc(section->os_size, 1))) {
214                 fatal("No memory.\n");
215         }
216         rd_emit(p, section->os_flen);
217         writef(p, 1, section->os_size);
218         free(p);
219 }
220
221 emit_symtab()
222 {
223         struct outname *ACK_names;
224         register unsigned short i;
225         register struct outname *A;
226         register char x;
227         register char *p;
228         extern char *malloc(), *calloc();
229         long l;
230         long off = OFF_CHAR(outhead);
231         char *chars;
232
233         if ((unsigned) outhead.oh_nchar != outhead.oh_nchar ||
234             !( chars = malloc((unsigned) outhead.oh_nchar))) {
235                 fatal("No memory\n.");
236         }
237         rd_string(chars,outhead.oh_nchar);
238         if ((unsigned) outhead.oh_nname != outhead.oh_nname ||
239             !(A = (struct outname *)
240                         calloc(outhead.oh_nname, sizeof(struct outname)))) {
241                 fatal("No memory.\n");
242         }
243         ACK_names = A;
244         rd_name(ACK_names, outhead.oh_nname);
245         for (i = 0; i < outhead.oh_nname; i++, A++) {
246                 if ((A->on_type & S_TYP) >= S_MIN + LSECT ||
247                     A->on_foff == 0) continue;
248                 switch(A->on_type & S_TYP) {
249                         case S_UND:
250                                 x = N_UNDF;
251                                 break;
252                         case S_ABS:
253                                 x = N_ABS;
254                                 break;
255                         case S_MIN + TEXTSG:
256                                 x = N_TEXT; 
257                                 break;
258                         case S_MIN + ROMSG:
259                                 x = (rom_in_data ? N_DATA : N_TEXT);
260                                 break;
261                         case S_MIN + DATASG:
262                                 x = N_DATA;
263                                 break;
264                         case S_MIN + BSSSG:
265                                 x = N_BSS;
266                                 break;
267                         default:
268                                 fprintf(stderr,"warning: unknown s_type: %d\n",
269                                         A->on_type & S_TYP);
270                 }
271                 if (A->on_type & S_EXT) x |= N_EXT;
272                 putc(x,output);
273                 putc(0,output);
274                 write_long(A->on_valu);
275                 l = A->on_foff - off;
276                 if (l < 0 || l >= outhead.oh_nchar) {
277                         fatal("bad on_off: %ld\n",l);
278                 }
279                 p = &chars[l];
280                 while (x = *p++) {
281                         putc(x,output);
282                 }
283                 putc('\0',output);
284         }
285 }
286
287 write_long(l)
288         register long l;
289 {
290         /*      write long "l" in 68000 order
291         */
292
293         putc((int) (l >> 24), output);
294         putc((int) (l >> 16), output);
295         putc((int) (l >> 8), output);
296         putc((int) l, output);
297 }
298
299 write_header(h)
300         register struct bhdr *h;
301 {
302         write_long(h->fmagic);
303         write_long(h->tsize);
304         write_long(h->dsize);
305         write_long(h->bsize);
306         write_long(h->ssize);
307         write_long(h->rtsize);
308         write_long(h->rdsize);
309         write_long(h->entry);
310 }
311
312 /* VARARGS1 */
313 fatal(s, a1, a2)
314         char    *s;
315 {
316         fprintf(stderr,"%s: ",program) ;
317         fprintf(stderr, s, a1, a2);
318         if (outputfile_created)
319                 unlink(output_file);
320         exit(-1);
321 }
322
323 rd_fatal() { fatal("read error.\n"); }