354 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			354 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 *
 | 
						|
 *          This product is part of the Amsterdam Compiler Kit.
 | 
						|
 *
 | 
						|
 * Permission to use, sell, duplicate or disclose this software must be
 | 
						|
 * obtained in writing. Requests for such permissions may be sent to
 | 
						|
 *
 | 
						|
 *      Dr. Andrew S. Tanenbaum
 | 
						|
 *      Wiskundig Seminarium
 | 
						|
 *      Vrije Universiteit
 | 
						|
 *      Postbox 7161
 | 
						|
 *      1007 MC Amsterdam
 | 
						|
 *      The Netherlands
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * 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"); }
 |