123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- /* $Id$ */
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- */
- /*
- * Convert ACK a.out file to VAX Berkeley Unix object format.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <out.h>
- #include <assert.h>
- #include <stdlib.h>
- long lseek();
- #define OMAGIC 0407 /* old-fashioned */
- #define NMAGIC 0410 /* text write protexted */
- #define ZMAGIC 0413 /* demand paging */
- struct bhdr {
- long magic;
- long tsize;
- long dsize;
- long bsize;
- long ssize;
- long entry;
- long rtsize;
- long rdsize;
- };
- struct machrelo {
- long address;
- long relodata;
- };
- #define setpcrel(X,f) (X |= (f<<7))
- #define setsymbolnum(X,n) (X = (X & 0377) | ((long)n << 8))
- #define setextern(X,f) (X |= (f << 4))
- #define setlength(X,l) (X = (X & ~0x60)|((long) l << 5))
- struct sym {
- long name;
- char type;
- char other;
- short desc;
- long value;
- };
- #define N_UNDF 0
- #define N_ABS 02
- #define N_TEXT 04
- #define N_DATA 06
- #define N_BSS 010
- #define N_EXT 01
- #define N_FN 0x1f
- /*
- * Header and section table of new format object file.
- */
- struct outhead outhead;
- struct outsect outsect[S_MAX];
- char *output_file;
- int outputfile_created;
- long magic;
- int rom_in_data;
- char *program ;
- char flag ;
- /* Output file definitions and such */
- struct bhdr bh;
- #define ENTRY 0x0
- #define TOT_HDRSIZE (sizeof(struct bhdr))
- #define TEXTSG 0
- #define ROMSG 1
- #define DATASG 2
- #define BSSSG 3
- #define LSECT BSSSG+1
- #define NSECT LSECT+1
- int output;
- int unresolved;
- int nflag;
- long textsize ;
- long datasize ;
- long bsssize;
- long align(a,b)
- long a,b;
- {
- a += b - 1;
- return a - a % b;
- }
- int
- follows(pa, pb)
- register struct outsect *pa, *pb;
- {
- /* return 1 if pa follows pb */
- return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
- }
- main(argc, argv)
- int argc;
- char *argv[];
- {
- register int nsect;
- program= argv[0] ;
- while ( argc>1 && argv[1][0]=='-' ) {
- flag=argv[1][1] ;
- if (flag == 'u') unresolved++;
- else if (flag == 'n') nflag = 1;
- argc-- ; argv++ ;
- }
- switch (argc) {
- case 3: if ((output = creat(argv[2], 0644)) < 0 ||
- (close(output), output = open(argv[2],2)) < 0)
- fatal("Can't write %s.\n", argv[2]);
- output_file = argv[2];
- outputfile_created = 1;
- if (! rd_open(argv[1]))
- fatal("Can't read %s.\n", argv[1]);
- break;
- default:fatal("Usage: %s [-u] [-n] <ACK object> <Vax object>.\n", program);
- }
- rd_ohead(&outhead);
- if (BADMAGIC(outhead))
- fatal("Not an ack object file.\n");
- if (outhead.oh_flags & HF_LINK) {
- if (! unresolved) {
- fprintf(stderr,"Warning: contains unresolved references.\n");
- }
- unresolved++;
- }
- else if (outhead.oh_nrelo > 0 && !unresolved)
- fprintf(stderr, "Warning: relocation information present.\n");
- if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
- fatal("Input file must have %d sections, not %ld\n",
- NSECT,outhead.oh_nsect) ;
- rd_sect(outsect, outhead.oh_nsect);
- /* A few checks */
- if ( outsect[BSSSG].os_flen != 0 )
- fatal("bss space contains initialized data\n") ;
- if ( !unresolved) {
- if (! follows(&outsect[BSSSG], &outsect[DATASG]))
- fatal("bss segment must follow data segment\n") ;
- if (! follows(&outsect[ROMSG],&outsect[TEXTSG]))
- fatal("rom segment must follow text\n") ;
- if (! follows(&outsect[DATASG], &outsect[ROMSG]))
- fatal("data segment must follow rom\n") ;
- }
- outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
- outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
- outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
- if ( outsect[ROMSG].os_lign == 0x400 ) {
- /* 410/413 file with ROMSG in data space */
- rom_in_data = 1;
- magic= NMAGIC ;
- textsize= outsect[TEXTSG].os_size;
- datasize= outsect[ROMSG].os_size + outsect[DATASG].os_size ;
- } else
- if ( outsect[DATASG].os_lign == 0x400 ) {
- /* 410/413 file with ROMSG in instruction space */
- rom_in_data = 0;
- magic= NMAGIC ;
- textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
- datasize= outsect[DATASG].os_size ;
- } else {
- /* Plain 407 file */
- rom_in_data = 0;
- magic= OMAGIC ;
- textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
- datasize = outsect[DATASG].os_size;
- }
- bsssize = outsect[BSSSG].os_size;
- if (nflag && magic != NMAGIC) {
- fatal("illegal alignments.\n");
- }
- if (magic == NMAGIC && ! nflag) {
- if (datasize & 0x3ff) {
- int diff = 0x400 - (datasize & 0x3ff);
- if (bsssize >= diff) bsssize -= diff;
- else bsssize = 0;
- outsect[DATASG].os_size += diff;
- datasize += diff;
- }
- magic = ZMAGIC;
- }
- if ( outhead.oh_nsect==NSECT ) {
- if (! follows(&outsect[LSECT],&outsect[BSSSG]))
- fatal("end segment must follow bss\n") ;
- if ( outsect[LSECT].os_size != 0 )
- fatal("end segment must be empty\n") ;
- }
- if (magic != OMAGIC && unresolved) {
- fatal("unresolved references with wrong magic number\n");
- }
- if (outsect[TEXTSG].os_base != ENTRY) {
- fatal("Illegal entry point.\n");
- }
- bh.magic = magic;
- bh.tsize = textsize;
- bh.bsize = bsssize;
- bh.dsize = datasize;
- bh.rtsize = 0;
- bh.rdsize = 0;
- bh.entry = ENTRY;
- /* Action at last */
- if (magic == ZMAGIC) {
- lseek(output,(long) 0x400, 0);
- }
- else lseek(output,(long) TOT_HDRSIZE,0);
- emits(&outsect[TEXTSG]) ;
- emits(&outsect[ROMSG]) ;
- emits(&outsect[DATASG]) ;
- if (unresolved) emit_relo();
- emit_symtab();
- bh.ssize = outhead.oh_nname * sizeof(struct sym);
- lseek(output,0L,0);
- cvlong(&(bh.magic));
- cvlong(&(bh.tsize));
- cvlong(&(bh.dsize));
- cvlong(&(bh.bsize));
- cvlong(&(bh.ssize));
- cvlong(&(bh.entry));
- cvlong(&(bh.rtsize));
- cvlong(&(bh.rdsize));
- writef(&bh, 1, (long) TOT_HDRSIZE);
- if ( outputfile_created && !unresolved ) chmod(argv[2],0755);
- exit(0);
- }
- writef(addr,sz,cnt)
- char *addr;
- long cnt;
- {
- cnt *= sz;
- while (cnt) {
- int i = cnt >= 0x4000 ? 0x4000 : cnt;
- cnt -= i;
- if (write(output, addr, i) < i) {
- fatal("write error\n");
- }
- addr += i;
- }
- }
- /*
- * Transfer the emitted byted from one file to another.
- */
- emits(section) struct outsect *section ; {
- char *p;
- long sz = section->os_flen;
- rd_outsect(section - outsect);
- while (sz) {
- unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
- if (!(p = malloc(i))) {
- fatal("No memory.\n");
- }
- rd_emit(p, i);
- if (write(output, p, i) < i) {
- fatal("write error.\n");
- }
- free(p);
- sz -= i;
- }
- sz = section->os_size - section->os_flen;
- if (sz) {
- if (!(p = calloc(0x4000, 1))) {
- fatal("No memory.\n");
- }
- while (sz) {
- unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
- if (write(output, p, i) < i) {
- fatal("write error.\n");
- }
- sz -= i;
- }
- free(p);
- }
- }
- struct outname *ACKnames;
- emit_relo()
- {
- struct outrelo *ACKrelo;
- struct machrelo *MACHtrelo,*MACHdrelo;
- register struct outrelo *ap;
- register struct machrelo *mtp, *mdp;
- unsigned int cnt = outhead.oh_nrelo;
- ACKrelo = (struct outrelo *) calloc(cnt, sizeof(struct outrelo));
- MACHtrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
- MACHdrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
- ACKnames = (struct outname *) calloc(outhead.oh_nname, sizeof(struct outname));
- if (!(ap = ACKrelo) || !(mtp = MACHtrelo) || !(mdp = MACHdrelo) ||
- !ACKnames) {
- fatal("No memory.\n");
- }
- rd_relo(ACKrelo, cnt);
- rd_name(ACKnames, outhead.oh_nname);
- while (cnt-- != 0) {
- register struct machrelo *mp;
- if (ap->or_sect - S_MIN <= ROMSG) mp = mtp++;
- else mp = mdp++;
- setlength(mp->relodata,(ap->or_type&RELSZ) >> 1);
- setpcrel(mp->relodata,(ap->or_type&RELPC != 0));
- mp->address = ap->or_addr;
- if (ap->or_sect == ROMSG+S_MIN) {
- mp->address += outsect[TEXTSG].os_size;
- }
- if (ap->or_nami < outhead.oh_nname) {
- if (ACKnames[ap->or_nami].on_type & S_EXT) {
- setsymbolnum(mp->relodata, ap->or_nami);
- setextern(mp->relodata,1);
- }
- else {
- patch(ap, &ACKnames[ap->or_nami], mp);
- }
- }
- else {
- setsymbolnum(mp->relodata, N_ABS);
- }
- cvlong(&(mp->address));
- cvlong(&(mp->relodata));
- ap++;
- }
- bh.rtsize = (char *) mtp - (char *) MACHtrelo;
- bh.rdsize = (char *) mdp - (char *) MACHdrelo;
- writef(MACHtrelo, 1, bh.rtsize);
- writef(MACHdrelo, 1, bh.rdsize);
- free(ACKrelo);
- free(MACHtrelo);
- free(MACHdrelo);
- }
- long
- get(sz)
- {
- char buf[10];
- long l = 0;
- register char *p = buf + sz;
- read(output,buf,sz);
- while (sz--) {
- l = (l << 8) | (*--p & 0377);
- }
- return l;
- }
- put(l,sz)
- long l;
- {
- char buf[10];
- register char *p = buf;
- *p++ = l;
- *p++ = l >> 8;
- *p++ = l >> 16;
- *p++ = l >> 24;
- p -= sz;
- if (write(output, p, sz) < sz) {
- fatal("write error.\n");
- }
- }
- patch(ap, an, mp)
- register struct outrelo *ap;
- register struct outname *an;
- register struct machrelo *mp;
- {
- int whichsect = (an->on_type & S_TYP) - S_MIN;
- long correction = 0;
- long where = TOT_HDRSIZE+ap->or_addr;
- long X;
- long here;
- int sz;
- if (!(an->on_type & S_SCT)) {
- fprintf(stderr,"funny on_type %x\n", an->on_type);
- }
- switch(whichsect) {
- case TEXTSG:
- setsymbolnum(mp->relodata,N_TEXT);
- return;
- case DATASG:
- correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size;
- setsymbolnum(mp->relodata,N_DATA);
- break;
- case ROMSG:
- correction = outsect[TEXTSG].os_size;
- setsymbolnum(mp->relodata,N_TEXT);
- break;
- case BSSSG:
- correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size+
- outsect[DATASG].os_size;
- setsymbolnum(mp->relodata,N_BSS);
- break;
- default:
- assert(0);
- }
- switch(ap->or_sect - S_MIN) {
- case DATASG:
- where += outsect[ROMSG].os_size;
- case ROMSG:
- where += outsect[TEXTSG].os_size;
- case TEXTSG:
- break;
- default:
- assert(0);
- }
- here = lseek(output, 0L, 1);
- lseek(output, where, 0);
- sz = ap->or_type & RELSZ;
- X = get(sz) + correction;
- lseek(output, where, 0);
- put(X,sz);
- lseek(output, here, 0);
- }
- cvlong(l)
- long *l;
- {
- long x = *l;
- char *p = (char *) l;
- *p++ = x;
- *p++ = x >> 8;
- *p++ = x >> 16;
- *p++ = x >> 24;
- }
- cvshort(s)
- short *s;
- {
- int x = *s;
- char *p = (char *) s;
- *p++ = x;
- *p = x >> 8;
- }
- int
- is_rest_local(A, i)
- register int i;
- register struct outname *A;
- {
- while (i--) {
- if (A->on_type & S_EXT) return 0;
- A++;
- }
- return 1;
- }
- emit_symtab()
- {
- register unsigned short i = outhead.oh_nname;
- register struct outname *A;
- struct sym *MACHnames;
- register struct sym *M;
- char *chars;
- long offX = OFF_CHAR(outhead) - 4;
- if (!(A = ACKnames)) {
- if (!(A = (struct outname *)
- calloc(i, sizeof(struct outname)))) {
- fatal("No memory.\n");
- }
- rd_name(A, outhead.oh_nname);
- }
- if (!(M = (struct sym *) calloc(i, sizeof(struct sym)))) {
- fatal("No memory.\n");
- }
- MACHnames = M;
- ACKnames = A;
- for (; i; i--, A++) {
- M->value = A->on_valu;
- M->desc = A->on_desc;
- if ((A->on_type & S_SCT) ||
- (A->on_type & S_ETC) == S_FIL) {
- static int rest_local;
- if (! unresolved || rest_local || (rest_local = is_rest_local(A, i))) {
- outhead.oh_nname--;
- continue;
- }
- }
- if (A->on_type & S_STB) {
- M->type = A->on_type >> 8;
- }
- else if (A->on_type & S_COM) {
- M->type = N_UNDF | N_EXT;
- }
- else switch(A->on_type & S_TYP) {
- case S_UND:
- switch(A->on_type & S_ETC) {
- default:
- M->type = N_UNDF;
- break;
- case S_MOD:
- M->type = N_FN;
- break;
- case S_LIN:
- M->type = N_ABS;
- break;
- }
- break;
- case S_ABS:
- M->type = N_ABS;
- break;
- case S_MIN + TEXTSG:
- M->type = N_TEXT;
- break;
- case S_MIN + ROMSG:
- if (unresolved) {
- M->value += outsect[TEXTSG].os_size;
- }
- M->type = (rom_in_data ? N_DATA : N_TEXT);
- break;
- case S_MIN + DATASG:
- if (unresolved) {
- M->value += outsect[TEXTSG].os_size +
- outsect[ROMSG].os_size;
- }
- M->type = N_DATA;
- break;
- case S_MIN + BSSSG:
- if (unresolved) {
- M->value += outsect[TEXTSG].os_size +
- outsect[ROMSG].os_size +
- outsect[DATASG].os_size;
- }
- M->type = N_BSS;
- break;
- case S_MIN + LSECT:
- M->type = N_BSS;
- break;
- default:
- fprintf(stderr,"warning: unknown s_type: %d\n",
- A->on_type & S_TYP);
- }
- if (A->on_type & S_EXT) M->type |= N_EXT;
- M->name = A->on_foff;
- M++;
- }
- M = MACHnames;
- for (i = outhead.oh_nname; i; i--, M++) {
- if (M->name) {
- M->name -= offX;
- }
- else M->name = outhead.oh_nchar + 3; /* pointer to nullbyte */
- cvlong(&(M->name));
- cvlong(&(M->value));
- cvshort(&(M->desc));
- }
- writef(MACHnames, sizeof(struct sym), (long) outhead.oh_nname);
- free(MACHnames);
- free(ACKnames);
- if ((unsigned) outhead.oh_nchar != outhead.oh_nchar ||
- !( chars = malloc((unsigned) outhead.oh_nchar))) {
- fatal("No memory\n.");
- }
- put(outhead.oh_nchar+4,4);
- rd_string(chars,outhead.oh_nchar);
- writef(chars, 1, outhead.oh_nchar);
- free(chars);
- }
- /* VARARGS1 */
- fatal(s, a1, a2)
- char *s;
- {
- fprintf(stderr,"%s: ",program) ;
- fprintf(stderr, s, a1, a2);
- if (outputfile_created)
- unlink(output_file);
- exit(-1);
- }
- rd_fatal() { fatal("read error.\n"); }
|