/* $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 Mantra object format to ACK object format */ #include #include #define FMAGIC 0407 #define REG 06 #define RTEXT 00 #define RDATA 01 #define RBSS 02 #define REXT 03 #define RBYTE 00 #define RWORD 01 #define RLONG 02 struct bhdr { long fmagic; long tsize; long dsize; long bsize; long ssize; long rtsize; long rdsize; long entry; }; struct reloc { char x; #define setseg(p,s) (p->x = (p->x & ~03) | s) #define setsiz(p,s) (p->x = (p->x & ~014) | (s << 2)) #define setdis(p,s) (p->x = (p->x & ~020) | (s << 4)) #define getseg(p) (p->x&03) #define getsiz(p) ((p->x >> 2) & 03) #define getdis(p) ((p->x >> 4) & 01) char relpad2; short rsymbol; long rpos; }; #define N_UNDF 0 #define N_ABS 01 #define N_TEXT 02 #define N_DATA 03 #define N_BSS 04 #define N_TYPE 037 #define N_REG 024 #define N_FN 037 #define N_EXT 040 #define ASSERT(x) switch (2) { case 0: case (x): ; } /* * Header and section table of new format object file. */ struct outhead outhead; struct outsect outsect[4]; #define TEXTSG 0 #define ROMSG 1 #define DATASG 2 #define BSSSG 3 char *output_file; char *program ; char flag ; #define readf(a, b, c) fread((a), (b), (int)(c), input) /* Output file definitions and such */ struct bhdr bh; #define TOT_HDRSIZE (sizeof(struct bhdr)) FILE *input; struct outrelo *orelo = 0; struct outname *oname = 0; char *strings = 0; char *txt = 0; char *data = 0; main(argc, argv) int argc; char *argv[]; { register struct outsect *p; char *malloc(); input = stdin; program= argv[0] ; if ( argc>1 && argv[1][0]=='-' ) { flag=argv[1][1] ; argc-- ; argv++ ; } switch (argc) { case 3: if (! wr_open(argv[2])) fatal("Can't write %s.\n", argv[2]); output_file = argv[2]; if ((input = fopen(argv[1], "r")) == (FILE *)0) fatal("Can't read %s.\n", argv[1]); break; default:fatal("Usage: %s .\n", argv[0]); } if (! readf(&bh, sizeof(struct bhdr), 1)) rd_fatal(); if (bh.fmagic != FMAGIC) fatal("bad magic number\n"); outhead.oh_magic = O_MAGIC; outhead.oh_stamp = 0; outhead.oh_nsect = 4; outhead.oh_nrelo = (bh.rtsize + bh.rdsize) / sizeof(struct reloc); outhead.oh_flags = outhead.oh_nrelo ? HF_LINK : 0; outhead.oh_nemit = bh.tsize + bh.dsize; strings = malloc((unsigned) bh.ssize + 20); orelo = (struct outrelo *) malloc(outhead.oh_nrelo * sizeof(struct outrelo)); oname = (struct outname *) malloc((unsigned) (bh.ssize / 6 + 3) * sizeof (struct outname)); txt = malloc(bh.tsize); data = malloc(bh.dsize); if (!strings || !orelo || !oname || !txt || !data) { fatal("No memory\n"); } p = &outsect[TEXTSG]; p->os_base = 0; p->os_size = p->os_flen = bh.tsize; p->os_foff = OFF_EMIT(outhead); p->os_lign = 1; p = &outsect[ROMSG]; p->os_base = p->os_size = p->os_flen = 0; p->os_foff = OFF_EMIT(outhead) + bh.tsize; p->os_lign = 1; p = &outsect[DATASG]; p->os_base = 0; p->os_size = p->os_flen = bh.dsize; p->os_foff = OFF_EMIT(outhead) + bh.tsize; p->os_lign = 1; p = &outsect[BSSSG]; p->os_base = p->os_flen = 0; p->os_size = bh.bsize; p->os_foff = OFF_EMIT(outhead)+bh.tsize+bh.dsize; p->os_lign = 1; if (bh.tsize && ! readf(txt, 1, bh.tsize)) rd_fatal(); if (bh.dsize && ! readf(data, 1, bh.dsize)) rd_fatal(); symtab(oname, strings); relo(orelo, txt, data); wr_ohead(&outhead); wr_sect(outsect, 4); wr_outsect(TEXTSG); wr_emit(txt, bh.tsize); wr_outsect(DATASG); wr_emit(data,bh.dsize); wr_relo(orelo, outhead.oh_nrelo); wr_name(oname, outhead.oh_nname); wr_string(strings, outhead.oh_nchar); wr_close(); return 0; } symtab(name, string) struct outname *name; char *string; { register struct outname *oname = name; register char *strings = string; register int c; unsigned nnames = 3; register long ssize = bh.ssize; register char *b; oname->on_valu = 0; oname->on_foff = 0; oname->on_desc = 0; oname->on_type = (S_MIN+TEXTSG) | S_SCT; b = ".text"; while (*strings++ = *b) b++; oname++; oname->on_valu = 0; oname->on_foff = strings - string; oname->on_desc = 0; oname->on_type = (S_MIN+DATASG) | S_SCT; b = ".data"; while (*strings++ = *b) b++; oname++; oname->on_valu = 0; oname->on_foff = strings - string; oname->on_desc = 0; oname->on_type = (S_MIN+BSSSG) | S_SCT; b = ".bss"; while (*strings++ = *b) b++; oname++; while (ssize > 0) { c = getc(input); getc(input); oname->on_valu = getw(input); ssize -= 6; switch(c & ~N_EXT) { case N_ABS: oname->on_type = S_ABS; break; case N_TEXT: oname->on_type = S_MIN + TEXTSG; break; case N_DATA: oname->on_type = S_MIN + DATASG; oname->on_valu -= bh.tsize; break; case N_BSS: oname->on_type = S_MIN + BSSSG; oname->on_valu -= bh.tsize + bh.dsize; break; case N_UNDF: if (! oname->on_valu) { oname->on_type = S_UND; break; } oname->on_type = (S_MIN + BSSSG) | S_COM; break; case REG: case N_REG: case N_FN: while (ssize > 0 && (getc(input) > 0)) ssize--; continue; default: fatal("Illegal type field %d in namelist\n", c); } if (c & N_EXT) oname->on_type |= S_EXT; oname->on_desc = 0; oname->on_foff = strings - string; nnames++; while (ssize > 0 && (c = getc(input)) > 0) { *strings++ = c; ssize--; } ssize--; *strings++ = c; oname++; } outhead.oh_nname = nnames; outhead.oh_nchar = strings - string; oname = name; ssize = OFF_CHAR(outhead); while (nnames--) { oname->on_foff += ssize; oname++; } } long get4(c) register char *c; { register long l = (long) (*c++ & 0377) << 24; l |= (long) (*c++ & 0377) << 16; l |= (long) (*c++ & 0377) << 8; l |= (long) (*c++ & 0377); return l; } put4(l, c) register char *c; register long l; { *c++ = (l >> 24); *c++ = (l >> 16); *c++ = (l >> 8); *c = l; } relo(orelo, txt, data) struct outrelo *orelo; char *txt, *data; { register struct outrelo *relo = orelo; register relocnt = outhead.oh_nrelo; struct reloc rel; register struct reloc *relp = &rel; int ndat = bh.rdsize / sizeof(struct reloc); while (relocnt-- > 0) { readf(relp, sizeof(struct reloc), 1); relo->or_sect = (relocnt >= ndat) ? S_MIN + TEXTSG : S_MIN + DATASG; relo->or_addr = relp->rpos; relo->or_nami = relp->rsymbol + 3; switch(getseg(relp)) { case RTEXT: relo->or_nami = 0; break; case RDATA: relo->or_nami = 1; break; case RBSS: relo->or_nami = 2; break; case REXT: break; default: fatal("Error 1 in relocation\n"); } switch(getsiz(relp)) { case RBYTE: relo->or_type = RELO1|RELBR|RELWR; break; case RWORD: relo->or_type = RELO2|RELBR|RELWR; break; case RLONG: { register char *sct = (relocnt >= ndat ? txt : data) + relo->or_addr; long x; relo->or_type = RELO4|RELBR|RELWR; switch((oname + relo->or_nami)->on_type & S_TYP) { case (S_MIN+DATASG): x = get4(sct) - bh.tsize; put4(x, sct); break; case (S_MIN+BSSSG): if (! ((oname+relo->or_nami)->on_type & S_COM)) x = get4(sct) - (bh.tsize + bh.dsize); put4(x, sct); } break; } default: fatal("Error 2 in relocation\n"); } if (getdis(relp)) relo->or_type |= RELPC; relo++; } } /* VARARGS1 */ fatal(s, a1, a2) char *s; { fprintf(stderr,"%s: ",program) ; fprintf(stderr, s, a1, a2); unlink(output_file); exit(-1); } wr_fatal() { fatal("Write error\n"); } rd_fatal() { fatal("Read error\n"); }