1493 lines · 25.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* vl - mips linker */#define	EXTERN#include	"l.h"#include	<ar.h> #ifndef	DEFAULT#define	DEFAULT	'9'#endif char	*noname		= "<none>";char	symname[]	= SYMDEF;char	thechar		= 'v';char	*thestring 	= "mips";int little; char**	libdir;int	nlibdir	= 0;static	int	maxlibdir = 0; /* * -H0 -T0x40004C -D0x10000000 is abbrev unix		(boot image) * -H1 -T0x80020000 -R4	is bootp() format for 3k	(boot image) * -H2 -T16416 -R16384	is plan9 format * -H3 -T0x80020000 -R8	is bootp() format for 4k	(4k boot image) * -H4 -T0x400000 -R4	is sgi unix coff executable	(4k boot image) * -H5 -T0x4000A0 -R4	is sgi unix elf executable * -H6			is headerless * -H7			is 64-bit elf executable */ voidusage(void){	diag("usage: %s [-options] objects", argv0);	errorexit();} voidmain(int argc, char *argv[]){	int c;	char *a;	char name[LIBNAMELEN]; 	Binit(&bso, 1, OWRITE);	cout = -1;	listinit();	outfile = 0;	nerrors = 0;	curtext = P;	HEADTYPE = -1;	INITTEXT = -1;	INITTEXTP = -1;	INITDAT = -1;	INITRND = -1;	INITENTRY = 0; 	ARGBEGIN {	default:		c = ARGC();		if(c >= 0 && c < sizeof(debug))			debug[c]++;		break;	case 'o':		outfile = ARGF();		break;	case 'E':		a = ARGF();		if(a)			INITENTRY = a;		break;	case  'm':			/* for little-endian mips */		thechar = '0';		thestring = "spim";		little = 1;		break;	case 'T':		a = ARGF();		if(a)			INITTEXT = atolwhex(a);		break;	case 'P':		a = ARGF();		if(a)			INITTEXTP = atolwhex(a);		break;	case 'D':		a = ARGF();		if(a)			INITDAT = atolwhex(a);		break;	case 'R':		a = ARGF();		if(a)			INITRND = atolwhex(a);		break;	case 'H':		a = ARGF();		if(a)			HEADTYPE = atolwhex(a);		/* do something about setting INITTEXT */		break;	case 'L':		addlibpath(EARGF(usage()));		break;	} ARGEND 	USED(argc); 	if(*argv == 0)		usage();	if(!debug['9'] && !debug['U'] && !debug['B'])		debug[DEFAULT] = 1;	a = getenv("ccroot");	if(a != nil && *a != '\0') {		if(!fileexists(a)) {			diag("nonexistent $ccroot: %s", a);			errorexit();		}	}else		a = "";	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);	addlibpath(name);	if(HEADTYPE == -1) {		if(debug['U'])			HEADTYPE = 0;		if(debug['B'])			HEADTYPE = 1;		if(debug['9'])			HEADTYPE = 2;	}	switch(HEADTYPE) {	default:		diag("unknown -H option");		errorexit(); 	case 0:	/* unix simple */		HEADR = 20L+56L;		if(INITTEXT == -1)			INITTEXT = 0x40004CL;		if(INITDAT == -1)			INITDAT = 0x10000000L;		if(INITRND == -1)			INITRND = 0;		break;	case 1:	/* boot for 3k */		HEADR = 20L+60L;		if(INITTEXT == -1)			INITTEXT = 0x80020000L;		if(INITDAT == -1)			INITDAT = 0;		if(INITRND == -1)			INITRND = 4;		break;	case 2:	/* plan 9 */		HEADR = 32L;		if(INITDAT == -1)			INITDAT = 0;		if(INITRND == -1)			INITRND = 16*1024;		if(INITTEXT == -1)			INITTEXT = INITRND + HEADR;		break;	case 3:	/* boot for 4k */		HEADR = 20L+56L+3*40L;		if(INITTEXT == -1)			INITTEXT = 0x80020000L;		if(INITDAT == -1)			INITDAT = 0;		if(INITRND == -1)			INITRND = 8;		break;	case 4:	/* sgi unix coff executable */		HEADR = 20L+56L+3*40L;		if(INITTEXT == -1)			INITTEXT = 0x00400000L+HEADR;		if(INITDAT == -1)			INITDAT = 0x10000000;		if(INITRND == -1)			INITRND = 0;		break;	case 5:	/* sgi unix elf executable */		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);		if(INITTEXT == -1)			INITTEXT = 0x00400000L+HEADR;		if(INITDAT == -1)			INITDAT = 0x10000000;		if(INITRND == -1)			INITRND = 0;		break;	case 6:	/* headerless */		HEADR = 0;		if(INITTEXT == -1)			INITTEXT = 0x80000000L+HEADR;		if(INITDAT == -1)			INITDAT = 0;		if(INITRND == -1)			INITRND = 4096;		break;	case 7:	/* 64-bit elf executable */		HEADR = rnd(Ehdr64sz+3*Phdr64sz, 16);		if(INITTEXT == -1)			INITTEXT = 0x00400000L+HEADR;		if(INITDAT == -1)			INITDAT = 0x10000000;		if(INITRND == -1)			INITRND = 0;		break;	}	if (INITTEXTP == -1)		INITTEXTP = INITTEXT;	if(INITDAT != 0 && INITRND != 0)		print("warning: -D%#llux is ignored because of -R%#llux\n",			INITDAT, INITRND);	if(debug['v'])		Bprint(&bso, "HEADER = -H%d -T%#llux -D%#llux -R%#llux\n",			HEADTYPE, INITTEXT, INITDAT, INITRND);	Bflush(&bso);	zprg.as = AGOK;	zprg.reg = NREG;	zprg.from.name = D_NONE;	zprg.from.type = D_NONE;	zprg.from.reg = NREG;	zprg.to = zprg.from;	buildop();	histgen = 0;	textp = P;	datap = P;	pc = 0;	dtype = 4;	if(outfile == 0) {		static char name[20]; 		snprint(name, sizeof name, "%c.out", thechar);		outfile = name;	}	cout = create(outfile, 1, 0775);	if(cout < 0) {		diag("cannot create %s: %r", outfile);		errorexit();	}	nuxiinit(); 	version = 0;	cbp = buf.cbuf;	cbc = sizeof(buf.cbuf);	firstp = prg();	lastp = firstp; 	if(INITENTRY == 0) {		INITENTRY = "_main";		if(debug['p'])			INITENTRY = "_mainp";		if(!debug['l'])			lookup(INITENTRY, 0)->type = SXREF;	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))		lookup(INITENTRY, 0)->type = SXREF; 	while(*argv)		objfile(*argv++);	if(!debug['l'])		loadlib();	firstp = firstp->link;	if(firstp == P)		goto out;	patch();	if(debug['p'])		if(debug['1'])			doprof1();		else			doprof2();	dodata();	follow();	if(firstp == P)		goto out;	noops();	span();	asmb();	undef(); out:	if(debug['v']) {		Bprint(&bso, "%5.2f cpu time\n", cputime());		Bprint(&bso, "%ld memory used\n", thunk);		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));	}	Bflush(&bso);	errorexit();} voidaddlibpath(char *arg){	char **p; 	if(nlibdir >= maxlibdir) {		if(maxlibdir == 0)			maxlibdir = 8;		else			maxlibdir *= 2;		p = malloc(maxlibdir*sizeof(*p));		if(p == nil) {			diag("out of memory");			errorexit();		}		memmove(p, libdir, nlibdir*sizeof(*p));		free(libdir);		libdir = p;	}	libdir[nlibdir++] = strdup(arg);} char*findlib(char *file){	int i;	char name[LIBNAMELEN]; 	for(i = 0; i < nlibdir; i++) {		snprint(name, sizeof(name), "%s/%s", libdir[i], file);		if(fileexists(name))			return libdir[i];	}	return nil;} voidloadlib(void){	int i;	long h;	Sym *s; loop:	xrefresolv = 0;	for(i=0; i<libraryp; i++) {		if(debug['v'])			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);		objfile(library[i]);	}	if(xrefresolv)	for(h=0; h<nelem(hash); h++)	for(s = hash[h]; s != S; s = s->link)		if(s->type == SXREF)			goto loop;} voiderrorexit(void){ 	if(nerrors) {		if(cout >= 0)			remove(outfile);		exits("error");	}	exits(0);} voidobjfile(char *file){	long off, esym, cnt, l;	int f, work;	Sym *s;	char magbuf[SARMAG];	char name[100], pname[150];	struct ar_hdr arhdr;	char *e, *start, *stop; 	if(file[0] == '-' && file[1] == 'l') {		if(debug['9'])			sprint(name, "/%s/lib/lib", thestring);		else			sprint(name, "/usr/%clib/lib", thechar);		strcat(name, file+2);		strcat(name, ".a");		file = name;	}	if(debug['v'])		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);	Bflush(&bso);	f = open(file, 0);	if(f < 0) {		diag("cannot open file: %s", file);		errorexit();	}	l = read(f, magbuf, SARMAG);	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){		/* load it as a regular file */		l = seek(f, 0L, 2);		seek(f, 0L, 0);		ldobj(f, l, file);		close(f);		return;	} 	if(debug['v'])		Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);	l = read(f, &arhdr, SAR_HDR);	if(l != SAR_HDR) {		diag("%s: short read on archive file symbol header", file);		goto out;	}	if(strncmp(arhdr.name, symname, strlen(symname))) {		diag("%s: first entry not symbol header", file);		goto out;	} 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);	off = SARMAG + SAR_HDR; 	/*	 * just bang the whole symbol file into memory	 */	seek(f, off, 0);	cnt = esym - off;	start = malloc(cnt + 10);	cnt = read(f, start, cnt);	if(cnt <= 0){		close(f);		return;	}	stop = &start[cnt];	memset(stop, 0, 10); 	work = 1;	while(work){		if(debug['v'])			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);		Bflush(&bso);		work = 0;		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {			s = lookup(e+5, 0);			if(s->type != SXREF)				continue;			sprint(pname, "%s(%s)", file, s->name);			if(debug['v'])				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);			Bflush(&bso);			l = e[1] & 0xff;			l |= (e[2] & 0xff) << 8;			l |= (e[3] & 0xff) << 16;			l |= (e[4] & 0xff) << 24;			seek(f, l, 0);			/* need readn to read the dumps (at least) */			l = readn(f, &arhdr, SAR_HDR);			if(l != SAR_HDR)				goto bad;			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))				goto bad;			l = atolwhex(arhdr.size);			ldobj(f, l, pname);			if(s->type == SXREF) {				diag("%s: failed to load: %s", file, s->name);				errorexit();			}			work = 1;			xrefresolv = 1;		}	}	return; bad:	diag("%s: bad or out of date archive", file);out:	close(f);} intzaddr(uchar *p, Adr *a, Sym *h[]){	int i, c;	int l;	Sym *s;	Auto *u; 	c = p[2];	if(c < 0 || c > NSYM){		print("sym out of range: %d\n", c);		p[0] = ALAST+1;		return 0;	}	a->type = p[0];	a->reg = p[1];	a->sym = h[c];	a->name = p[3];	c = 4; 	if(a->reg < 0 || a->reg > NREG) {

Lines 1–500 of 1493.