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