1 /* $Id: cv.c,v 1.4 1994/06/24 13:53:58 ceriel Exp $ */
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".
9 * Convert ACK a.out file to VAX Berkeley Unix object format.
18 #define OMAGIC 0407 /* old-fashioned */
19 #define NMAGIC 0410 /* text write protexted */
20 #define ZMAGIC 0413 /* demand paging */
37 #define setpcrel(X,f) (X |= (f<<7))
38 #define setsymbolnum(X,n) (X = (X & 0377) | ((long)n << 8))
39 #define setextern(X,f) (X |= (f << 4))
40 #define setlength(X,l) (X = (X & ~0x60)|((long) l << 5))
59 * Header and section table of new format object file.
61 struct outhead outhead;
62 struct outsect outsect[S_MAX];
65 int outputfile_created;
74 /* Output file definitions and such */
79 #define TOT_HDRSIZE (sizeof(struct bhdr))
107 register struct outsect *pa, *pb;
109 /* return 1 if pa follows pb */
111 return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
121 while ( argc>1 && argv[1][0]=='-' ) {
123 if (flag == 'u') unresolved++;
124 else if (flag == 'n') nflag = 1;
128 case 3: if ((output = creat(argv[2], 0644)) < 0 ||
129 (close(output), output = open(argv[2],2)) < 0)
130 fatal("Can't write %s.\n", argv[2]);
131 output_file = argv[2];
132 outputfile_created = 1;
133 if (! rd_open(argv[1]))
134 fatal("Can't read %s.\n", argv[1]);
136 default:fatal("Usage: %s [-u] [-n] <ACK object> <Vax object>.\n", program);
139 if (BADMAGIC(outhead))
140 fatal("Not an ack object file.\n");
141 if (outhead.oh_flags & HF_LINK) {
143 fprintf(stderr,"Warning: contains unresolved references.\n");
147 else if (outhead.oh_nrelo > 0 && !unresolved)
148 fprintf(stderr, "Warning: relocation information present.\n");
149 if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
150 fatal("Input file must have %d sections, not %ld\n",
151 NSECT,outhead.oh_nsect) ;
152 rd_sect(outsect, outhead.oh_nsect);
154 if ( outsect[BSSSG].os_flen != 0 )
155 fatal("bss space contains initialized data\n") ;
157 if (! follows(&outsect[BSSSG], &outsect[DATASG]))
158 fatal("bss segment must follow data segment\n") ;
159 if (! follows(&outsect[ROMSG],&outsect[TEXTSG]))
160 fatal("rom segment must follow text\n") ;
161 if (! follows(&outsect[DATASG], &outsect[ROMSG]))
162 fatal("data segment must follow rom\n") ;
164 outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
165 outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
166 outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
167 if ( outsect[ROMSG].os_lign == 0x400 ) {
168 /* 410/413 file with ROMSG in data space */
171 textsize= outsect[TEXTSG].os_size;
172 datasize= outsect[ROMSG].os_size + outsect[DATASG].os_size ;
174 if ( outsect[DATASG].os_lign == 0x400 ) {
175 /* 410/413 file with ROMSG in instruction space */
178 textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
179 datasize= outsect[DATASG].os_size ;
184 textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
185 datasize = outsect[DATASG].os_size;
187 bsssize = outsect[BSSSG].os_size;
188 if (nflag && magic != NMAGIC) {
189 fatal("illegal alignments.\n");
191 if (magic == NMAGIC && ! nflag) {
192 if (datasize & 0x3ff) {
193 int diff = 0x400 - (datasize & 0x3ff);
195 if (bsssize >= diff) bsssize -= diff;
197 outsect[DATASG].os_size += diff;
202 if ( outhead.oh_nsect==NSECT ) {
203 if (! follows(&outsect[LSECT],&outsect[BSSSG]))
204 fatal("end segment must follow bss\n") ;
205 if ( outsect[LSECT].os_size != 0 )
206 fatal("end segment must be empty\n") ;
209 if (magic != OMAGIC && unresolved) {
210 fatal("unresolved references with wrong magic number\n");
213 if (outsect[TEXTSG].os_base != ENTRY) {
214 fatal("Illegal entry point.\n");
226 if (magic == ZMAGIC) {
227 lseek(output,(long) 0x400, 0);
229 else lseek(output,(long) TOT_HDRSIZE,0);
230 emits(&outsect[TEXTSG]) ;
231 emits(&outsect[ROMSG]) ;
232 emits(&outsect[DATASG]) ;
233 if (unresolved) emit_relo();
235 bh.ssize = outhead.oh_nname * sizeof(struct sym);
243 cvlong(&(bh.rtsize));
244 cvlong(&(bh.rdsize));
245 writef(&bh, 1, (long) TOT_HDRSIZE);
246 if ( outputfile_created && !unresolved ) chmod(argv[2],0755);
257 int i = cnt >= 0x4000 ? 0x4000 : cnt;
260 if (write(output, addr, i) < i) {
261 fatal("write error\n");
268 * Transfer the emitted byted from one file to another.
270 emits(section) struct outsect *section ; {
272 char *calloc(), *malloc();
273 long sz = section->os_flen;
275 rd_outsect(section - outsect);
277 unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
278 if (!(p = malloc(i))) {
279 fatal("No memory.\n");
282 if (write(output, p, i) < i) {
283 fatal("write error.\n");
289 sz = section->os_size - section->os_flen;
291 if (!(p = calloc(0x4000, 1))) {
292 fatal("No memory.\n");
295 unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
296 if (write(output, p, i) < i) {
297 fatal("write error.\n");
305 struct outname *ACKnames;
309 struct outrelo *ACKrelo;
310 struct machrelo *MACHtrelo,*MACHdrelo;
311 register struct outrelo *ap;
312 register struct machrelo *mtp, *mdp;
313 unsigned int cnt = outhead.oh_nrelo;
315 ACKrelo = (struct outrelo *) calloc(cnt, sizeof(struct outrelo));
316 MACHtrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
317 MACHdrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
318 ACKnames = (struct outname *) calloc(outhead.oh_nname, sizeof(struct outname));
319 if (!(ap = ACKrelo) || !(mtp = MACHtrelo) || !(mdp = MACHdrelo) ||
321 fatal("No memory.\n");
323 rd_relo(ACKrelo, cnt);
324 rd_name(ACKnames, outhead.oh_nname);
326 register struct machrelo *mp;
328 if (ap->or_sect - S_MIN <= ROMSG) mp = mtp++;
330 setlength(mp->relodata,(ap->or_type&RELSZ) >> 1);
331 setpcrel(mp->relodata,(ap->or_type&RELPC != 0));
332 mp->address = ap->or_addr;
333 if (ap->or_sect == ROMSG+S_MIN) {
334 mp->address += outsect[TEXTSG].os_size;
336 if (ap->or_nami < outhead.oh_nname) {
337 if (ACKnames[ap->or_nami].on_type & S_EXT) {
338 setsymbolnum(mp->relodata, ap->or_nami);
339 setextern(mp->relodata,1);
342 patch(ap, &ACKnames[ap->or_nami], mp);
346 setsymbolnum(mp->relodata, N_ABS);
348 cvlong(&(mp->address));
349 cvlong(&(mp->relodata));
352 bh.rtsize = (char *) mtp - (char *) MACHtrelo;
353 bh.rdsize = (char *) mdp - (char *) MACHdrelo;
354 writef(MACHtrelo, 1, bh.rtsize);
355 writef(MACHdrelo, 1, bh.rdsize);
366 register char *p = buf + sz;
370 l = (l << 8) | (*--p & 0377);
379 register char *p = buf;
386 if (write(output, p, sz) < sz) {
387 fatal("write error.\n");
392 register struct outrelo *ap;
393 register struct outname *an;
394 register struct machrelo *mp;
396 int whichsect = (an->on_type & S_TYP) - S_MIN;
398 long where = TOT_HDRSIZE+ap->or_addr;
403 if (!(an->on_type & S_SCT)) {
404 fprintf(stderr,"funny on_type %x\n", an->on_type);
408 setsymbolnum(mp->relodata,N_TEXT);
411 correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size;
412 setsymbolnum(mp->relodata,N_DATA);
415 correction = outsect[TEXTSG].os_size;
416 setsymbolnum(mp->relodata,N_TEXT);
419 correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size+
420 outsect[DATASG].os_size;
421 setsymbolnum(mp->relodata,N_BSS);
427 switch(ap->or_sect - S_MIN) {
429 where += outsect[ROMSG].os_size;
431 where += outsect[TEXTSG].os_size;
437 here = lseek(output, 0L, 1);
438 lseek(output, where, 0);
439 sz = ap->or_type & RELSZ;
440 X = get(sz) + correction;
441 lseek(output, where, 0);
443 lseek(output, here, 0);
450 char *p = (char *) l;
462 char *p = (char *) s;
471 register struct outname *A;
474 if (A->on_type & S_EXT) return 0;
482 register unsigned short i = outhead.oh_nname;
483 register struct outname *A;
484 struct sym *MACHnames;
485 register struct sym *M;
486 extern char *malloc(), *calloc();
488 long offX = OFF_CHAR(outhead) - 4;
490 if (!(A = ACKnames)) {
491 if (!(A = (struct outname *)
492 calloc(i, sizeof(struct outname)))) {
493 fatal("No memory.\n");
495 rd_name(A, outhead.oh_nname);
497 if (!(M = (struct sym *) calloc(i, sizeof(struct sym)))) {
498 fatal("No memory.\n");
502 for (; i; i--, A++) {
503 M->value = A->on_valu;
504 M->desc = A->on_desc;
505 if ((A->on_type & S_SCT) ||
506 (A->on_type & S_ETC) == S_FIL) {
507 static int rest_local;
508 if (! unresolved || rest_local || (rest_local = is_rest_local(A, i))) {
513 if (A->on_type & S_STB) {
514 M->type = A->on_type >> 8;
516 else if (A->on_type & S_COM) {
517 M->type = N_UNDF | N_EXT;
519 else switch(A->on_type & S_TYP) {
521 switch(A->on_type & S_ETC) {
541 M->value += outsect[TEXTSG].os_size;
543 M->type = (rom_in_data ? N_DATA : N_TEXT);
547 M->value += outsect[TEXTSG].os_size +
548 outsect[ROMSG].os_size;
554 M->value += outsect[TEXTSG].os_size +
555 outsect[ROMSG].os_size +
556 outsect[DATASG].os_size;
564 fprintf(stderr,"warning: unknown s_type: %d\n",
567 if (A->on_type & S_EXT) M->type |= N_EXT;
568 M->name = A->on_foff;
572 for (i = outhead.oh_nname; i; i--, M++) {
576 else M->name = outhead.oh_nchar + 3; /* pointer to nullbyte */
581 writef(MACHnames, sizeof(struct sym), (long) outhead.oh_nname);
584 if ((unsigned) outhead.oh_nchar != outhead.oh_nchar ||
585 !( chars = malloc((unsigned) outhead.oh_nchar))) {
586 fatal("No memory\n.");
588 put(outhead.oh_nchar+4,4);
589 rd_string(chars,outhead.oh_nchar);
590 writef(chars, 1, outhead.oh_nchar);
598 fprintf(stderr,"%s: ",program) ;
599 fprintf(stderr, s, a1, a2);
600 if (outputfile_created)
605 rd_fatal() { fatal("read error.\n"); }