factor portable object+library bits out of 5l/6l/8l into ld

R=r
DELTA=3214  (904 added, 2260 deleted, 50 changed)
OCL=35425
CL=35427
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 47cb44f..7098b42 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -30,17 +30,15 @@
 
 #define	EXTERN
 #include	"l.h"
+#include	"../ld/lib.h"
 #include	"../ld/elf.h"
 #include	"../ld/macho.h"
 #include	<ar.h>
 
 char	*noname		= "<none>";
-char	symname[]	= SYMDEF;
 char	thechar		= '6';
 char*	thestring 	= "amd64";
 char*	paramspace	= "FP";
-char*	libdir[16];	// contains "." first, goroot last
-int	nlibdir		= 0;
 
 /*
  *	-H2 -T4136 -R4096		is plan9 64-bit format
@@ -85,7 +83,6 @@
 main(int argc, char *argv[])
 {
 	int i, c;
-	char *a;
 
 	Binit(&bso, 1, OWRITE);
 	cout = -1;
@@ -98,7 +95,6 @@
 	INITDAT = -1;
 	INITRND = -1;
 	INITENTRY = 0;
-	libdir[nlibdir++] = ".";	// look in dot first
 
 	ARGBEGIN {
 	default:
@@ -116,11 +112,7 @@
 		HEADTYPE = atolwhex(EARGF(usage()));
 		break;
 	case 'L':
-		if(nlibdir >= nelem(libdir)-1) {
-			print("too many -L's: %d\n", nlibdir);
-			usage();
-		}
-		libdir[nlibdir++] = EARGF(usage());
+		Lflag(EARGF(usage()));
 		break;
 	case 'T':
 		INITTEXT = atolwhex(EARGF(usage()));
@@ -147,12 +139,7 @@
 	if(*argv == 0)
 		usage();
 
-	mywhatsys();	// get goroot, goarch, goos
-	if(strcmp(goarch, thestring) != 0)
-		print("goarch is not known: %s\n", goarch);
-
-	// put goroot in the libdir list.
-	libdir[nlibdir++] = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
+	libinit();
 
 	if(HEADTYPE == -1) {
 		HEADTYPE = 2;
@@ -348,33 +335,18 @@
 	edatap = P;
 	pc = 0;
 	dtype = 4;
-	unlink(outfile);
-	cout = create(outfile, 1, 0775);
-	if(cout < 0) {
-		diag("cannot create %s", outfile);
-		errorexit();
-	}
 	version = 0;
 	cbp = buf.cbuf;
 	cbc = sizeof(buf.cbuf);
 	firstp = prg();
 	lastp = firstp;
 
-	if(INITENTRY == nil) {
-		INITENTRY = mal(strlen(goarch)+strlen(goos)+10);
-		sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
-	}
-	lookup(INITENTRY, 0)->type = SXREF;
-
 	while(*argv)
 		objfile(*argv++);
 
-	if(!debug['l']) {
+	if(!debug['l'])
 		loadlib();
-		a = mal(strlen(goroot)+strlen(goarch)+strlen(goos)+20);
-		sprint(a, "%s/pkg/%s_%s/runtime.a", goroot, goos, goarch);
-		objfile(a);
-	}
+
 	deadcode();
 
 	firstp = firstp->link;
@@ -419,7 +391,6 @@
 	if(debug['v']) {
 		Bprint(&bso, "%5.2f cpu time\n", cputime());
 		Bprint(&bso, "%ld symbols\n", nsymbol);
-		Bprint(&bso, "%ld memory used\n", thunk);
 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
 	}
@@ -429,160 +400,6 @@
 }
 
 void
-loadlib(void)
-{
-	int i;
-	int32 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;
-}
-
-void
-errorexit(void)
-{
-	if(nerrors) {
-		if(cout >= 0)
-			remove(outfile);
-		exits("error");
-	}
-	exits(0);
-}
-
-void
-objfile(char *file)
-{
-	int32 off, esym, cnt, l;
-	int work;
-	Biobuf *f;
-	Sym *s;
-	char magbuf[SARMAG];
-	char name[100], pname[150];
-	struct ar_hdr arhdr;
-	char *e, *start, *stop;
-
-	if(file[0] == '-' && file[1] == 'l') {	// TODO: fix this
-		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 = Bopen(file, 0);
-	if(f == nil) {
-		diag("cannot open file: %s", file);
-		errorexit();
-	}
-	l = Bread(f, magbuf, SARMAG);
-	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
-		/* load it as a regular file */
-		l = Bseek(f, 0L, 2);
-		Bseek(f, 0L, 0);
-		ldobj(f, l, file);
-		Bterm(f);
-		return;
-	}
-
-	l = Bread(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
-	 */
-	Bseek(f, off, 0);
-	cnt = esym - off;
-	start = mal(cnt + 10);
-	cnt = Bread(f, start, cnt);
-	if(cnt <= 0){
-		Bterm(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;
-			Bseek(f, l, 0);
-			l = Bread(f, &arhdr, SAR_HDR);
-			if(l != SAR_HDR)
-				goto bad;
-			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
-				goto bad;
-			l = SARNAME;
-			while(l > 0 && arhdr.name[l-1] == ' ')
-				l--;
-			sprint(pname, "%s(%.*s)", file, l, arhdr.name);
-			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:
-	Bterm(f);
-}
-
-int32
-Bget4(Biobuf *f)
-{
-	uchar p[4];
-
-	if(Bread(f, p, 4) != 4)
-		return 0;
-	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-void
 zaddr(Biobuf *f, Adr *a, Sym *h[])
 {
 	int t;
@@ -655,182 +472,6 @@
 }
 
 void
-addlib(char *src, char *obj)
-{
-	char name[1024], pname[1024], comp[256], *p;
-	int i, search;
-
-	if(histfrogp <= 0)
-		return;
-
-	search = 0;
-	if(histfrog[0]->name[1] == '/') {
-		sprint(name, "");
-		i = 1;
-	} else
-	if(histfrog[0]->name[1] == '.') {
-		sprint(name, ".");
-		i = 0;
-	} else {
-		sprint(name, "");
-		i = 0;
-		search = 1;
-	}
-
-	for(; i<histfrogp; i++) {
-		snprint(comp, sizeof comp, histfrog[i]->name+1);
-		for(;;) {
-			p = strstr(comp, "$O");
-			if(p == 0)
-				break;
-			memmove(p+1, p+2, strlen(p+2)+1);
-			p[0] = thechar;
-		}
-		for(;;) {
-			p = strstr(comp, "$M");
-			if(p == 0)
-				break;
-			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
-				diag("library component too long");
-				return;
-			}
-			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
-			memmove(p, thestring, strlen(thestring));
-		}
-		if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
-			diag("library component too long");
-			return;
-		}
-		strcat(name, "/");
-		strcat(name, comp);
-	}
-
-	if(search) {
-		// try dot, -L "libdir", and then goroot.
-		for(i=0; i<nlibdir; i++) {
-			snprint(pname, sizeof pname, "%s/%s", libdir[i], name);
-			if(access(pname, AEXIST) >= 0)
-				break;
-		}
-		strcpy(name, pname);
-	}
-	cleanname(name);
-	if(debug['v'])
-		Bprint(&bso, "%5.2f addlib: %s %s pulls in %s\n", cputime(), obj, src, name);
-
-	for(i=0; i<libraryp; i++)
-		if(strcmp(name, library[i]) == 0)
-			return;
-	if(libraryp == nelem(library)){
-		diag("too many autolibs; skipping %s", name);
-		return;
-	}
-
-	p = mal(strlen(name) + 1);
-	strcpy(p, name);
-	library[libraryp] = p;
-	p = mal(strlen(obj) + 1);
-	strcpy(p, obj);
-	libraryobj[libraryp] = p;
-	libraryp++;
-}
-
-void
-copyhistfrog(char *buf, int nbuf)
-{
-	char *p, *ep;
-	int i;
-
-	p = buf;
-	ep = buf + nbuf;
-	i = 0;
-	for(i=0; i<histfrogp; i++) {
-		p = seprint(p, ep, "%s", histfrog[i]->name+1);
-		if(i+1<histfrogp && (p == buf || p[-1] != '/'))
-			p = seprint(p, ep, "/");
-	}
-}
-
-void
-addhist(int32 line, int type)
-{
-	Auto *u;
-	Sym *s;
-	int i, j, k;
-
-	u = mal(sizeof(Auto));
-	s = mal(sizeof(Sym));
-	s->name = mal(2*(histfrogp+1) + 1);
-
-	u->asym = s;
-	u->type = type;
-	u->aoffset = line;
-	u->link = curhist;
-	curhist = u;
-
-	s->name[0] = 0;
-	j = 1;
-	for(i=0; i<histfrogp; i++) {
-		k = histfrog[i]->value;
-		s->name[j+0] = k>>8;
-		s->name[j+1] = k;
-		j += 2;
-	}
-	s->name[j] = 0;
-	s->name[j+1] = 0;
-}
-
-void
-histtoauto(void)
-{
-	Auto *l;
-
-	while(l = curhist) {
-		curhist = l->link;
-		l->link = curauto;
-		curauto = l;
-	}
-}
-
-void
-collapsefrog(Sym *s)
-{
-	int i;
-
-	/*
-	 * bad encoding of path components only allows
-	 * MAXHIST components. if there is an overflow,
-	 * first try to collapse xxx/..
-	 */
-	for(i=1; i<histfrogp; i++)
-		if(strcmp(histfrog[i]->name+1, "..") == 0) {
-			memmove(histfrog+i-1, histfrog+i+1,
-				(histfrogp-i-1)*sizeof(histfrog[0]));
-			histfrogp--;
-			goto out;
-		}
-
-	/*
-	 * next try to collapse .
-	 */
-	for(i=0; i<histfrogp; i++)
-		if(strcmp(histfrog[i]->name+1, ".") == 0) {
-			memmove(histfrog+i, histfrog+i+1,
-				(histfrogp-i-1)*sizeof(histfrog[0]));
-			goto out;
-		}
-
-	/*
-	 * last chance, just truncate from front
-	 */
-	memmove(histfrog+0, histfrog+1,
-		(histfrogp-1)*sizeof(histfrog[0]));
-
-out:
-	histfrog[histfrogp-1] = s;
-}
-
-void
 nopout(Prog *p)
 {
 	p->as = ANOP;
@@ -839,71 +480,22 @@
 }
 
 void
-ldobj(Biobuf *f, int64 len, char *pn)
+ldobj1(Biobuf *f, int64 len, char *pn)
 {
 	vlong ipc;
 	Prog *p, *t;
 	int v, o, r, skip, mode;
 	Sym *h[NSYM], *s, *di;
 	uint32 sig;
-	static int files;
-	static char **filen;
-	char **nfilen, *line, *name;
-	int ntext, n, c1, c2, c3;
+	char *name;
+	int ntext;
 	vlong eof;
-	vlong import0, import1;
 	char src[1024];
 
-	src[0] = '\0';
-	eof = Boffset(f) + len;
-
 	ntext = 0;
-
-	if((files&15) == 0){
-		nfilen = malloc((files+16)*sizeof(char*));
-		memmove(nfilen, filen, files*sizeof(char*));
-		free(filen);
-		filen = nfilen;
-	}
-	pn = strdup(pn);
-	filen[files++] = pn;
-
+	eof = Boffset(f) + len;
 	di = S;
-
-	/* check the header */
-	line = Brdline(f, '\n');
-	if(line == nil) {
-		if(Blinelen(f) > 0) {
-			diag("%s: malformed object file", pn);
-			return;
-		}
-		goto eof;
-	}
-	n = Blinelen(f) - 1;
-	if(n != strlen(thestring) || strncmp(line, thestring, n) != 0) {
-		if(line)
-			line[n] = '\0';
-		diag("file not %s [%s]\n", thestring, line);
-		return;
-	}
-
-	/* skip over exports and other info -- ends with \n!\n */
-	import0 = Boffset(f);
-	c1 = '\n';	// the last line ended in \n
-	c2 = Bgetc(f);
-	c3 = Bgetc(f);
-	while(c1 != '\n' || c2 != '!' || c3 != '\n') {
-		c1 = c2;
-		c2 = c3;
-		c3 = Bgetc(f);
-		if(c3 == Beof)
-			goto eof;
-	}
-	import1 = Boffset(f);
-
-	Bseek(f, import0, 0);
-	ldpkg(f, import1 - import0 - 2, pn);	// -2 for !\n
-	Bseek(f, import1, 0);
+	src[0] = 0;
 
 newloop:
 	memset(h, 0, sizeof(h));
@@ -953,9 +545,9 @@
 			if(s->sig != 0 && s->sig != sig)
 				diag("incompatible type signatures"
 					"%lux(%s) and %lux(%s) for %s",
-					s->sig, filen[s->file], sig, pn, s->name);
+					s->sig, s->file, sig, pn, s->name);
 			s->sig = sig;
-			s->file = files-1;
+			s->file = pn;
 		}
 
 		if(debug['W'])
@@ -1256,43 +848,6 @@
 	diag("truncated object file: %s", pn);
 }
 
-Sym*
-lookup(char *symb, int v)
-{
-	Sym *s;
-	char *p;
-	int32 h;
-	int l, c;
-
-	h = v;
-	for(p=symb; c = *p; p++)
-		h = h+h+h + c;
-	l = (p - symb) + 1;
-	if(h < 0)
-		h = ~h;
-	h %= NHASH;
-	for(s = hash[h]; s != S; s = s->link)
-		if(s->version == v)
-		if(memcmp(s->name, symb, l) == 0)
-			return s;
-
-	s = mal(sizeof(*s));
-	if(debug['v'] > 1)
-		Bprint(&bso, "lookup %s\n", symb);
-
-	s->name = mal(l + 1);
-	memmove(s->name, symb, l);
-
-	s->link = hash[h];
-	s->type = 0;
-	s->version = v;
-	s->value = 0;
-	s->sig = 0;
-	hash[h] = s;
-	nsymbol++;
-	return s;
-}
-
 Prog*
 prg(void)
 {
@@ -1477,189 +1032,3 @@
 	}
 }
 
-void
-nuxiinit(void)
-{
-	int i, c;
-
-	for(i=0; i<4; i++) {
-		c = find1(0x04030201L, i+1);
-		if(i < 2)
-			inuxi2[i] = c;
-		if(i < 1)
-			inuxi1[i] = c;
-		inuxi4[i] = c;
-		inuxi8[i] = c;
-		inuxi8[i+4] = c+4;
-		fnuxi4[i] = c;
-		fnuxi8[i] = c;
-		fnuxi8[i+4] = c+4;
-	}
-	if(debug['v']) {
-		Bprint(&bso, "inuxi = ");
-		for(i=0; i<1; i++)
-			Bprint(&bso, "%d", inuxi1[i]);
-		Bprint(&bso, " ");
-		for(i=0; i<2; i++)
-			Bprint(&bso, "%d", inuxi2[i]);
-		Bprint(&bso, " ");
-		for(i=0; i<4; i++)
-			Bprint(&bso, "%d", inuxi4[i]);
-		Bprint(&bso, " ");
-		for(i=0; i<8; i++)
-			Bprint(&bso, "%d", inuxi8[i]);
-		Bprint(&bso, "\nfnuxi = ");
-		for(i=0; i<4; i++)
-			Bprint(&bso, "%d", fnuxi4[i]);
-		Bprint(&bso, " ");
-		for(i=0; i<8; i++)
-			Bprint(&bso, "%d", fnuxi8[i]);
-		Bprint(&bso, "\n");
-	}
-	Bflush(&bso);
-}
-
-int
-find1(int32 l, int c)
-{
-	char *p;
-	int i;
-
-	p = (char*)&l;
-	for(i=0; i<4; i++)
-		if(*p++ == c)
-			return i;
-	return 0;
-}
-
-int
-find2(int32 l, int c)
-{
-	short *p;
-	int i;
-
-	p = (short*)&l;
-	for(i=0; i<4; i+=2) {
-		if(((*p >> 8) & 0xff) == c)
-			return i;
-		if((*p++ & 0xff) == c)
-			return i+1;
-	}
-	return 0;
-}
-
-int32
-ieeedtof(Ieee *e)
-{
-	int exp;
-	int32 v;
-
-	if(e->h == 0)
-		return 0;
-	exp = (e->h>>20) & ((1L<<11)-1L);
-	exp -= (1L<<10) - 2L;
-	v = (e->h & 0xfffffL) << 3;
-	v |= (e->l >> 29) & 0x7L;
-	if((e->l >> 28) & 1) {
-		v++;
-		if(v & 0x800000L) {
-			v = (v & 0x7fffffL) >> 1;
-			exp++;
-		}
-	}
-	if(exp <= -126 || exp >= 130)
-		diag("double fp to single fp overflow");
-	v |= ((exp + 126) & 0xffL) << 23;
-	v |= e->h & 0x80000000L;
-	return v;
-}
-
-double
-ieeedtod(Ieee *ieeep)
-{
-	Ieee e;
-	double fr;
-	int exp;
-
-	if(ieeep->h & (1L<<31)) {
-		e.h = ieeep->h & ~(1L<<31);
-		e.l = ieeep->l;
-		return -ieeedtod(&e);
-	}
-	if(ieeep->l == 0 && ieeep->h == 0)
-		return 0;
-	fr = ieeep->l & ((1L<<16)-1L);
-	fr /= 1L<<16;
-	fr += (ieeep->l>>16) & ((1L<<16)-1L);
-	fr /= 1L<<16;
-	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
-	fr /= 1L<<21;
-	exp = (ieeep->h>>20) & ((1L<<11)-1L);
-	exp -= (1L<<10) - 2L;
-	return ldexp(fr, exp);
-}
-
-void
-undefsym(Sym *s)
-{
-	int n;
-
-	n = imports;
-	if(s->value != 0)
-		diag("value != 0 on SXREF");
-	if(n >= 1<<Rindex)
-		diag("import index %d out of range", n);
-	s->value = n<<Roffset;
-	s->type = SUNDEF;
-	imports++;
-}
-
-void
-zerosig(char *sp)
-{
-	Sym *s;
-
-	s = lookup(sp, 0);
-	s->sig = 0;
-}
-
-void
-readundefs(char *f, int t)
-{
-	int i, n;
-	Sym *s;
-	Biobuf *b;
-	char *l, buf[256], *fields[64];
-
-	if(f == nil)
-		return;
-	b = Bopen(f, OREAD);
-	if(b == nil){
-		diag("could not open %s: %r", f);
-		errorexit();
-	}
-	while((l = Brdline(b, '\n')) != nil){
-		n = Blinelen(b);
-		if(n >= sizeof(buf)){
-			diag("%s: line too long", f);
-			errorexit();
-		}
-		memmove(buf, l, n);
-		buf[n-1] = '\0';
-		n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
-		if(n == nelem(fields)){
-			diag("%s: bad format", f);
-			errorexit();
-		}
-		for(i = 0; i < n; i++){
-			s = lookup(fields[i], 0);
-			s->type = SXREF;
-			s->subtype = t;
-			if(t == SIMPORT)
-				nimports++;
-			else
-				nexports++;
-		}
-	}
-	Bterm(b);
-}