ack/mach/mantra/cv/Xcv.c
1987-03-10 11:49:39 +00:00

345 lines
7.4 KiB
C

/* $Header$ */
/*
* (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 <stdio.h>
#include <out.h>
#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 <Mantra object> <ACK object>.\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"); }