xref: /plan9/sys/src/cmd/5l/obj.c (revision aaee222289330fcec0b5b011953f18cc626114b4)
1 #define	EXTERN
2 #include	"l.h"
3 #include	<ar.h>
4 
5 #ifndef	DEFAULT
6 #define	DEFAULT	'9'
7 #endif
8 
9 char	*noname		= "<none>";
10 char	symname[]	= SYMDEF;
11 char	thechar		= '5';
12 char	*thestring 	= "arm";
13 
14 char**	libdir;
15 int	nlibdir	= 0;
16 static	int	maxlibdir = 0;
17 
18 /*
19  *	-H0				no header
20  *	-H1 -T0x10005000 -R4		is aif for risc os
21  *	-H2 -T4128 -R4096		is plan9 format
22  *	-H3 -T0xF0000020 -R4		is NetBSD format
23  *	-H4				is IXP1200 (raw)
24  *	-H5 -T0xC0008010 -R1024		is ipaq
25  *	-H6 -R4096			no header with segments padded to pages
26  *	-H7				is elf
27  */
28 
29 void
usage(void)30 usage(void)
31 {
32 	diag("usage: %s [-options] objects", argv0);
33 	errorexit();
34 }
35 
36 static int
isobjfile(char * f)37 isobjfile(char *f)
38 {
39 	int n, v;
40 	Biobuf *b;
41 	char buf1[5], buf2[SARMAG];
42 
43 	b = Bopen(f, OREAD);
44 	if(b == nil)
45 		return 0;
46 	n = Bread(b, buf1, 5);
47 	if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
48 		v = 1;	/* good enough for our purposes */
49 	else{
50 		Bseek(b, 0, 0);
51 		n = Bread(b, buf2, SARMAG);
52 		v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
53 	}
54 	Bterm(b);
55 	return v;
56 }
57 
58 void
main(int argc,char * argv[])59 main(int argc, char *argv[])
60 {
61 	int c;
62 	char *a;
63 	char name[LIBNAMELEN];
64 
65 	Binit(&bso, 1, OWRITE);
66 	cout = -1;
67 	listinit();
68 	outfile = 0;
69 	nerrors = 0;
70 	curtext = P;
71 	HEADTYPE = -1;
72 	INITTEXT = -1;
73 	INITTEXTP = -1;
74 	INITDAT = -1;
75 	INITRND = -1;
76 	INITENTRY = 0;
77 
78 	ARGBEGIN {
79 	default:
80 		c = ARGC();
81 		if(c >= 0 && c < sizeof(debug))
82 			debug[c]++;
83 		break;
84 	case 'o':
85 		outfile = ARGF();
86 		break;
87 	case 'E':
88 		a = ARGF();
89 		if(a)
90 			INITENTRY = a;
91 		break;
92 	case 'L':
93 		addlibpath(EARGF(usage()));
94 		break;
95 	case 'T':
96 		a = ARGF();
97 		if(a)
98 			INITTEXT = atolwhex(a);
99 		break;
100 	case 'P':
101 		a = ARGF();
102 		if(a)
103 			INITTEXTP = atolwhex(a);
104 		break;
105 	case 'D':
106 		a = ARGF();
107 		if(a)
108 			INITDAT = atolwhex(a);
109 		break;
110 	case 'R':
111 		a = ARGF();
112 		if(a)
113 			INITRND = atolwhex(a);
114 		break;
115 	case 'H':
116 		a = ARGF();
117 		if(a)
118 			HEADTYPE = atolwhex(a);
119 		/* do something about setting INITTEXT */
120 		break;
121 	case 'x':	/* produce export table */
122 		doexp = 1;
123 		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
124 			readundefs(ARGF(), SEXPORT);
125 		break;
126 	case 'u':	/* produce dynamically loadable module */
127 		dlm = 1;
128 		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
129 			readundefs(ARGF(), SIMPORT);
130 		break;
131 	} ARGEND
132 
133 	USED(argc);
134 
135 	if(*argv == 0)
136 		usage();
137 	if(!debug['9'] && !debug['U'] && !debug['B'])
138 		debug[DEFAULT] = 1;
139 	a = getenv("ccroot");
140 	if(a != nil && *a != '\0') {
141 		if(!fileexists(a)) {
142 			diag("nonexistent $ccroot: %s", a);
143 			errorexit();
144 		}
145 	}else
146 		a = "";
147 	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
148 	addlibpath(name);
149 	if(HEADTYPE == -1) {
150 		if(debug['U'])
151 			HEADTYPE = 0;
152 		if(debug['B'])
153 			HEADTYPE = 1;
154 		if(debug['9'])
155 			HEADTYPE = 2;
156 	}
157 	switch(HEADTYPE) {
158 	default:
159 		diag("unknown -H option");
160 		errorexit();
161 	case 0:	/* no header */
162 	case 6:	/* no header, padded segments */
163 		HEADR = 0L;
164 		if(INITTEXT == -1)
165 			INITTEXT = 0;
166 		if(INITDAT == -1)
167 			INITDAT = 0;
168 		if(INITRND == -1)
169 			INITRND = 4;
170 		break;
171 	case 1:	/* aif for risc os */
172 		HEADR = 128L;
173 		if(INITTEXT == -1)
174 			INITTEXT = 0x10005000 + HEADR;
175 		if(INITDAT == -1)
176 			INITDAT = 0;
177 		if(INITRND == -1)
178 			INITRND = 4;
179 		break;
180 	case 2:	/* plan 9 */
181 		HEADR = 32L;
182 		if(INITTEXT == -1)
183 			INITTEXT = 4128;
184 		if(INITDAT == -1)
185 			INITDAT = 0;
186 		if(INITRND == -1)
187 			INITRND = 4096;
188 		break;
189 	case 3:	/* boot for NetBSD */
190 		HEADR = 32L;
191 		if(INITTEXT == -1)
192 			INITTEXT = 0xF0000020L;
193 		if(INITDAT == -1)
194 			INITDAT = 0;
195 		if(INITRND == -1)
196 			INITRND = 4096;
197 		break;
198 	case 4: /* boot for IXP1200 */
199 		HEADR = 0L;
200 		if(INITTEXT == -1)
201 			INITTEXT = 0x0;
202 		if(INITDAT == -1)
203 			INITDAT = 0;
204 		if(INITRND == -1)
205 			INITRND = 4;
206 		break;
207 	case 5: /* boot for ipaq */
208 		HEADR = 16L;
209 		if(INITTEXT == -1)
210 			INITTEXT = 0xC0008010;
211 		if(INITDAT == -1)
212 			INITDAT = 0;
213 		if(INITRND == -1)
214 			INITRND = 1024;
215 		break;
216 	case 7:	/* elf executable */
217 		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
218 		if(INITTEXT == -1)
219 			INITTEXT = 4096+HEADR;
220 		if(INITDAT == -1)
221 			INITDAT = 0;
222 		if(INITRND == -1)
223 			INITRND = 4;
224 		break;
225 	}
226 	if (INITTEXTP == -1)
227 		INITTEXTP = INITTEXT;
228 	if(INITDAT != 0 && INITRND != 0)
229 		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
230 			INITDAT, INITRND);
231 	if(debug['v'])
232 		Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
233 			HEADTYPE, INITTEXT, INITDAT, INITRND);
234 	Bflush(&bso);
235 	zprg.as = AGOK;
236 	zprg.scond = 14;
237 	zprg.reg = NREG;
238 	zprg.from.name = D_NONE;
239 	zprg.from.type = D_NONE;
240 	zprg.from.reg = NREG;
241 	zprg.to = zprg.from;
242 	buildop();
243 	histgen = 0;
244 	textp = P;
245 	datap = P;
246 	pc = 0;
247 	dtype = 4;
248 	if(outfile == 0)
249 		outfile = "5.out";
250 	cout = create(outfile, 1, 0775);
251 	if(cout < 0) {
252 		diag("cannot create %s: %r", outfile);
253 		errorexit();
254 	}
255 	nuxiinit();
256 
257 	version = 0;
258 	cbp = buf.cbuf;
259 	cbc = sizeof(buf.cbuf);
260 	firstp = prg();
261 	lastp = firstp;
262 
263 	if(INITENTRY == 0) {
264 		INITENTRY = "_main";
265 		if(debug['p'])
266 			INITENTRY = "_mainp";
267 		if(!debug['l'])
268 			lookup(INITENTRY, 0)->type = SXREF;
269 	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
270 		lookup(INITENTRY, 0)->type = SXREF;
271 
272 	while(*argv)
273 		objfile(*argv++);
274 	if(!debug['l'])
275 		loadlib();
276 	firstp = firstp->link;
277 	if(firstp == P)
278 		goto out;
279 	if(doexp || dlm){
280 		EXPTAB = "_exporttab";
281 		zerosig(EXPTAB);
282 		zerosig("etext");
283 		zerosig("edata");
284 		zerosig("end");
285 		if(dlm){
286 			initdiv();
287 			import();
288 			HEADTYPE = 2;
289 			INITTEXT = INITDAT = 0;
290 			INITRND = 8;
291 			INITENTRY = EXPTAB;
292 		}
293 		else
294 			divsig();
295 		export();
296 	}
297 	patch();
298 	if(debug['p'])
299 		if(debug['1'])
300 			doprof1();
301 		else
302 			doprof2();
303 	dodata();
304 	follow();
305 	if(firstp == P)
306 		goto out;
307 	noops();
308 	span();
309 	asmb();
310 	undef();
311 
312 out:
313 	if(debug['v']) {
314 		Bprint(&bso, "%5.2f cpu time\n", cputime());
315 		Bprint(&bso, "%ld memory used\n", thunk);
316 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
317 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
318 	}
319 	Bflush(&bso);
320 	errorexit();
321 }
322 
323 void
addlibpath(char * arg)324 addlibpath(char *arg)
325 {
326 	char **p;
327 
328 	if(nlibdir >= maxlibdir) {
329 		if(maxlibdir == 0)
330 			maxlibdir = 8;
331 		else
332 			maxlibdir *= 2;
333 		p = malloc(maxlibdir*sizeof(*p));
334 		if(p == nil) {
335 			diag("out of memory");
336 			errorexit();
337 		}
338 		memmove(p, libdir, nlibdir*sizeof(*p));
339 		free(libdir);
340 		libdir = p;
341 	}
342 	libdir[nlibdir++] = strdup(arg);
343 }
344 
345 char*
findlib(char * file)346 findlib(char *file)
347 {
348 	int i;
349 	char name[LIBNAMELEN];
350 
351 	for(i = 0; i < nlibdir; i++) {
352 		snprint(name, sizeof(name), "%s/%s", libdir[i], file);
353 		if(fileexists(name))
354 			return libdir[i];
355 	}
356 	return nil;
357 }
358 
359 void
loadlib(void)360 loadlib(void)
361 {
362 	int i;
363 	long h;
364 	Sym *s;
365 
366 loop:
367 	xrefresolv = 0;
368 	for(i=0; i<libraryp; i++) {
369 		if(debug['v'])
370 			Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
371 		objfile(library[i]);
372 	}
373 	if(xrefresolv)
374 	for(h=0; h<nelem(hash); h++)
375 	for(s = hash[h]; s != S; s = s->link)
376 		if(s->type == SXREF)
377 			goto loop;
378 }
379 
380 void
errorexit(void)381 errorexit(void)
382 {
383 
384 	if(nerrors) {
385 		if(cout >= 0)
386 			remove(outfile);
387 		exits("error");
388 	}
389 	exits(0);
390 }
391 
392 void
objfile(char * file)393 objfile(char *file)
394 {
395 	long off, esym, cnt, l;
396 	int f, work;
397 	Sym *s;
398 	char magbuf[SARMAG];
399 	char name[LIBNAMELEN], pname[LIBNAMELEN];
400 	struct ar_hdr arhdr;
401 	char *e, *start, *stop;
402 
403 	if(debug['v'])
404 		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
405 	Bflush(&bso);
406 	if(file[0] == '-' && file[1] == 'l') {
407 		snprint(pname, sizeof(pname), "lib%s.a", file+2);
408 		e = findlib(pname);
409 		if(e == nil) {
410 			diag("cannot find library: %s", file);
411 			errorexit();
412 		}
413 		snprint(name, sizeof(name), "%s/%s", e, pname);
414 		file = name;
415 	}
416 	f = open(file, 0);
417 	if(f < 0) {
418 		diag("cannot open %s: %r", file);
419 		errorexit();
420 	}
421 	l = read(f, magbuf, SARMAG);
422 	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
423 		/* load it as a regular file */
424 		l = seek(f, 0L, 2);
425 		seek(f, 0L, 0);
426 		ldobj(f, l, file);
427 		close(f);
428 		return;
429 	}
430 
431 	if(debug['v'])
432 		Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
433 	l = read(f, &arhdr, SAR_HDR);
434 	if(l != SAR_HDR) {
435 		diag("%s: short read on archive file symbol header", file);
436 		goto out;
437 	}
438 	if(strncmp(arhdr.name, symname, strlen(symname))) {
439 		diag("%s: first entry not symbol header", file);
440 		goto out;
441 	}
442 
443 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
444 	off = SARMAG + SAR_HDR;
445 
446 	/*
447 	 * just bang the whole symbol file into memory
448 	 */
449 	seek(f, off, 0);
450 	cnt = esym - off;
451 	start = malloc(cnt + 10);
452 	cnt = read(f, start, cnt);
453 	if(cnt <= 0){
454 		close(f);
455 		return;
456 	}
457 	stop = &start[cnt];
458 	memset(stop, 0, 10);
459 
460 	work = 1;
461 	while(work){
462 		if(debug['v'])
463 			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
464 		Bflush(&bso);
465 		work = 0;
466 		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
467 			s = lookup(e+5, 0);
468 			if(s->type != SXREF)
469 				continue;
470 			sprint(pname, "%s(%s)", file, s->name);
471 			if(debug['v'])
472 				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
473 			Bflush(&bso);
474 			l = e[1] & 0xff;
475 			l |= (e[2] & 0xff) << 8;
476 			l |= (e[3] & 0xff) << 16;
477 			l |= (e[4] & 0xff) << 24;
478 			seek(f, l, 0);
479 			/* need readn to read the dumps (at least) */
480 			l = readn(f, &arhdr, SAR_HDR);
481 			if(l != SAR_HDR)
482 				goto bad;
483 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
484 				goto bad;
485 			l = atolwhex(arhdr.size);
486 			ldobj(f, l, pname);
487 			if(s->type == SXREF) {
488 				diag("%s: failed to load: %s", file, s->name);
489 				errorexit();
490 			}
491 			work = 1;
492 			xrefresolv = 1;
493 		}
494 	}
495 	return;
496 
497 bad:
498 	diag("%s: bad or out of date archive", file);
499 out:
500 	close(f);
501 }
502 
503 int
zaddr(uchar * p,Adr * a,Sym * h[])504 zaddr(uchar *p, Adr *a, Sym *h[])
505 {
506 	int i, c;
507 	int l;
508 	Sym *s;
509 	Auto *u;
510 
511 	c = p[2];
512 	if(c < 0 || c > NSYM){
513 		print("sym out of range: %d\n", c);
514 		p[0] = ALAST+1;
515 		return 0;
516 	}
517 	a->type = p[0];
518 	a->reg = p[1];
519 	a->sym = h[c];
520 	a->name = p[3];
521 	c = 4;
522 
523 	if(a->reg < 0 || a->reg > NREG) {
524 		print("register out of range %d\n", a->reg);
525 		p[0] = ALAST+1;
526 		return 0;	/*  force real diagnostic */
527 	}
528 
529 	switch(a->type) {
530 	default:
531 		print("unknown type %d\n", a->type);
532 		p[0] = ALAST+1;
533 		return 0;	/*  force real diagnostic */
534 
535 	case D_NONE:
536 	case D_REG:
537 	case D_FREG:
538 	case D_PSR:
539 	case D_FPCR:
540 		break;
541 
542 	case D_REGREG:
543 		a->offset = p[4];
544 		c++;
545 		break;
546 
547 	case D_BRANCH:
548 	case D_OREG:
549 	case D_CONST:
550 	case D_OCONST:
551 	case D_SHIFT:
552 		a->offset = p[4] | (p[5]<<8) |
553 			(p[6]<<16) | (p[7]<<24);
554 		c += 4;
555 		break;
556 
557 	case D_SCONST:
558 		while(nhunk < NSNAME)
559 			gethunk();
560 		a->sval = (char*)hunk;
561 		nhunk -= NSNAME;
562 		hunk += NSNAME;
563 
564 		memmove(a->sval, p+4, NSNAME);
565 		c += NSNAME;
566 		break;
567 
568 	case D_FCONST:
569 		while(nhunk < sizeof(Ieee))
570 			gethunk();
571 		a->ieee = (Ieee*)hunk;
572 		nhunk -= NSNAME;
573 		hunk += NSNAME;
574 
575 		a->ieee->l = p[4] | (p[5]<<8) |
576 			(p[6]<<16) | (p[7]<<24);
577 		a->ieee->h = p[8] | (p[9]<<8) |
578 			(p[10]<<16) | (p[11]<<24);
579 		c += 8;
580 		break;
581 	}
582 	s = a->sym;
583 	if(s == S)
584 		return c;
585 	i = a->name;
586 	if(i != D_AUTO && i != D_PARAM)
587 		return c;
588 
589 	l = a->offset;
590 	for(u=curauto; u; u=u->link)
591 		if(u->asym == s)
592 		if(u->type == i) {
593 			if(u->aoffset > l)
594 				u->aoffset = l;
595 			return c;
596 		}
597 
598 	while(nhunk < sizeof(Auto))
599 		gethunk();
600 	u = (Auto*)hunk;
601 	nhunk -= sizeof(Auto);
602 	hunk += sizeof(Auto);
603 
604 	u->link = curauto;
605 	curauto = u;
606 	u->asym = s;
607 	u->aoffset = l;
608 	u->type = i;
609 	return c;
610 }
611 
612 void
addlib(char * obj)613 addlib(char *obj)
614 {
615 	char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
616 	int i, search;
617 
618 	if(histfrogp <= 0)
619 		return;
620 
621 	name = fn1;
622 	search = 0;
623 	if(histfrog[0]->name[1] == '/') {
624 		sprint(name, "");
625 		i = 1;
626 	} else if(histfrog[0]->name[1] == '.') {
627 		sprint(name, ".");
628 		i = 0;
629 	} else {
630 		sprint(name, "");
631 		i = 0;
632 		search = 1;
633 	}
634 
635 	for(; i<histfrogp; i++) {
636 		snprint(comp, sizeof comp, histfrog[i]->name+1);
637 		for(;;) {
638 			p = strstr(comp, "$O");
639 			if(p == 0)
640 				break;
641 			memmove(p+1, p+2, strlen(p+2)+1);
642 			p[0] = thechar;
643 		}
644 		for(;;) {
645 			p = strstr(comp, "$M");
646 			if(p == 0)
647 				break;
648 			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
649 				diag("library component too long");
650 				return;
651 			}
652 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
653 			memmove(p, thestring, strlen(thestring));
654 		}
655 		if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
656 			diag("library component too long");
657 			return;
658 		}
659 		if(i > 0 || !search)
660 			strcat(fn1, "/");
661 		strcat(fn1, comp);
662 	}
663 
664 	cleanname(name);
665 
666 	if(search){
667 		p = findlib(name);
668 		if(p != nil){
669 			snprint(fn2, sizeof(fn2), "%s/%s", p, name);
670 			name = fn2;
671 		}
672 	}
673 
674 	for(i=0; i<libraryp; i++)
675 		if(strcmp(name, library[i]) == 0)
676 			return;
677 	if(libraryp == nelem(library)){
678 		diag("too many autolibs; skipping %s", name);
679 		return;
680 	}
681 
682 	p = malloc(strlen(name) + 1);
683 	strcpy(p, name);
684 	library[libraryp] = p;
685 	p = malloc(strlen(obj) + 1);
686 	strcpy(p, obj);
687 	libraryobj[libraryp] = p;
688 	libraryp++;
689 }
690 
691 void
addhist(long line,int type)692 addhist(long line, int type)
693 {
694 	Auto *u;
695 	Sym *s;
696 	int i, j, k;
697 
698 	u = malloc(sizeof(Auto));
699 	s = malloc(sizeof(Sym));
700 	s->name = malloc(2*(histfrogp+1) + 1);
701 
702 	u->asym = s;
703 	u->type = type;
704 	u->aoffset = line;
705 	u->link = curhist;
706 	curhist = u;
707 
708 	j = 1;
709 	for(i=0; i<histfrogp; i++) {
710 		k = histfrog[i]->value;
711 		s->name[j+0] = k>>8;
712 		s->name[j+1] = k;
713 		j += 2;
714 	}
715 }
716 
717 void
histtoauto(void)718 histtoauto(void)
719 {
720 	Auto *l;
721 
722 	while(l = curhist) {
723 		curhist = l->link;
724 		l->link = curauto;
725 		curauto = l;
726 	}
727 }
728 
729 void
collapsefrog(Sym * s)730 collapsefrog(Sym *s)
731 {
732 	int i;
733 
734 	/*
735 	 * bad encoding of path components only allows
736 	 * MAXHIST components. if there is an overflow,
737 	 * first try to collapse xxx/..
738 	 */
739 	for(i=1; i<histfrogp; i++)
740 		if(strcmp(histfrog[i]->name+1, "..") == 0) {
741 			memmove(histfrog+i-1, histfrog+i+1,
742 				(histfrogp-i-1)*sizeof(histfrog[0]));
743 			histfrogp--;
744 			goto out;
745 		}
746 
747 	/*
748 	 * next try to collapse .
749 	 */
750 	for(i=0; i<histfrogp; i++)
751 		if(strcmp(histfrog[i]->name+1, ".") == 0) {
752 			memmove(histfrog+i, histfrog+i+1,
753 				(histfrogp-i-1)*sizeof(histfrog[0]));
754 			goto out;
755 		}
756 
757 	/*
758 	 * last chance, just truncate from front
759 	 */
760 	memmove(histfrog+0, histfrog+1,
761 		(histfrogp-1)*sizeof(histfrog[0]));
762 
763 out:
764 	histfrog[histfrogp-1] = s;
765 }
766 
767 void
nopout(Prog * p)768 nopout(Prog *p)
769 {
770 	p->as = ANOP;
771 	p->from.type = D_NONE;
772 	p->to.type = D_NONE;
773 }
774 
775 uchar*
readsome(int f,uchar * buf,uchar * good,uchar * stop,int max)776 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
777 {
778 	int n;
779 
780 	n = stop - good;
781 	memmove(buf, good, stop - good);
782 	stop = buf + n;
783 	n = MAXIO - n;
784 	if(n > max)
785 		n = max;
786 	n = read(f, stop, n);
787 	if(n <= 0)
788 		return 0;
789 	return stop + n;
790 }
791 
792 void
ldobj(int f,long c,char * pn)793 ldobj(int f, long c, char *pn)
794 {
795 	long ipc;
796 	Prog *p, *t;
797 	uchar *bloc, *bsize, *stop;
798 	Sym *h[NSYM], *s, *di;
799 	int v, o, r, skip;
800 	ulong sig;
801 	static int files;
802 	static char **filen;
803 	char **nfilen;
804 
805 	if((files&15) == 0){
806 		nfilen = malloc((files+16)*sizeof(char*));
807 		memmove(nfilen, filen, files*sizeof(char*));
808 		free(filen);
809 		filen = nfilen;
810 	}
811 	filen[files++] = strdup(pn);
812 
813 	bsize = buf.xbuf;
814 	bloc = buf.xbuf;
815 	di = S;
816 
817 newloop:
818 	memset(h, 0, sizeof(h));
819 	version++;
820 	histfrogp = 0;
821 	ipc = pc;
822 	skip = 0;
823 
824 loop:
825 	if(c <= 0)
826 		goto eof;
827 	r = bsize - bloc;
828 	if(r < 100 && r < c) {		/* enough for largest prog */
829 		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
830 		if(bsize == 0)
831 			goto eof;
832 		bloc = buf.xbuf;
833 		goto loop;
834 	}
835 	o = bloc[0];		/* as */
836 	if(o <= AXXX || o >= ALAST) {
837 		diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
838 		print("	probably not a .5 file\n");
839 		errorexit();
840 	}
841 	if(o == ANAME || o == ASIGNAME) {
842 		sig = 0;
843 		if(o == ASIGNAME){
844 			sig = bloc[1] | (bloc[2]<<8) | (bloc[3]<<16) | (bloc[4]<<24);
845 			bloc += 4;
846 			c -= 4;
847 		}
848 		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
849 		if(stop == 0){
850 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
851 			if(bsize == 0)
852 				goto eof;
853 			bloc = buf.xbuf;
854 			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
855 			if(stop == 0){
856 				fprint(2, "%s: name too long\n", pn);
857 				errorexit();
858 			}
859 		}
860 		v = bloc[1];	/* type */
861 		o = bloc[2];	/* sym */
862 		bloc += 3;
863 		c -= 3;
864 
865 		r = 0;
866 		if(v == D_STATIC)
867 			r = version;
868 		s = lookup((char*)bloc, r);
869 		c -= &stop[1] - bloc;
870 		bloc = stop + 1;
871 
872 		if(sig != 0){
873 			if(s->sig != 0 && s->sig != sig)
874 				diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
875 			s->sig = sig;
876 			s->file = files-1;
877 		}
878 
879 		if(debug['W'])
880 			print("	ANAME	%s\n", s->name);
881 		h[o] = s;
882 		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
883 			s->type = SXREF;
884 		if(v == D_FILE) {
885 			if(s->type != SFILE) {
886 				histgen++;
887 				s->type = SFILE;
888 				s->value = histgen;
889 			}
890 			if(histfrogp < MAXHIST) {
891 				histfrog[histfrogp] = s;
892 				histfrogp++;
893 			} else
894 				collapsefrog(s);
895 		}
896 		goto loop;
897 	}
898 
899 	if(nhunk < sizeof(Prog))
900 		gethunk();
901 	p = (Prog*)hunk;
902 	nhunk -= sizeof(Prog);
903 	hunk += sizeof(Prog);
904 
905 	p->as = o;
906 	p->scond = bloc[1];
907 	p->reg = bloc[2];
908 	p->line = bloc[3] | (bloc[4]<<8) | (bloc[5]<<16) | (bloc[6]<<24);
909 
910 	r = zaddr(bloc+7, &p->from, h) + 7;
911 	r += zaddr(bloc+r, &p->to, h);
912 	bloc += r;
913 	c -= r;
914 
915 	if(p->reg > NREG)
916 		diag("register out of range %d", p->reg);
917 
918 	p->link = P;
919 	p->cond = P;
920 
921 	if(debug['W'])
922 		print("%P\n", p);
923 
924 	switch(o) {
925 	case AHISTORY:
926 		if(p->to.offset == -1) {
927 			addlib(pn);
928 			histfrogp = 0;
929 			goto loop;
930 		}
931 		addhist(p->line, D_FILE);		/* 'z' */
932 		if(p->to.offset)
933 			addhist(p->to.offset, D_FILE1);	/* 'Z' */
934 		histfrogp = 0;
935 		goto loop;
936 
937 	case AEND:
938 		histtoauto();
939 		if(curtext != P)
940 			curtext->to.autom = curauto;
941 		curauto = 0;
942 		curtext = P;
943 		if(c)
944 			goto newloop;
945 		return;
946 
947 	case AGLOBL:
948 		s = p->from.sym;
949 		if(s == S) {
950 			diag("GLOBL must have a name\n%P", p);
951 			errorexit();
952 		}
953 		if(s->type == 0 || s->type == SXREF) {
954 			s->type = SBSS;
955 			s->value = 0;
956 		}
957 		if(s->type != SBSS) {
958 			diag("redefinition: %s\n%P", s->name, p);
959 			s->type = SBSS;
960 			s->value = 0;
961 		}
962 		if(p->to.offset > s->value)
963 			s->value = p->to.offset;
964 		break;
965 
966 	case ADYNT:
967 		if(p->to.sym == S) {
968 			diag("DYNT without a sym\n%P", p);
969 			break;
970 		}
971 		di = p->to.sym;
972 		p->reg = 4;
973 		if(di->type == SXREF) {
974 			if(debug['z'])
975 				Bprint(&bso, "%P set to %d\n", p, dtype);
976 			di->type = SCONST;
977 			di->value = dtype;
978 			dtype += 4;
979 		}
980 		if(p->from.sym == S)
981 			break;
982 
983 		p->from.offset = di->value;
984 		p->from.sym->type = SDATA;
985 		if(curtext == P) {
986 			diag("DYNT not in text: %P", p);
987 			break;
988 		}
989 		p->to.sym = curtext->from.sym;
990 		p->to.type = D_CONST;
991 		p->link = datap;
992 		datap = p;
993 		break;
994 
995 	case AINIT:
996 		if(p->from.sym == S) {
997 			diag("INIT without a sym\n%P", p);
998 			break;
999 		}
1000 		if(di == S) {
1001 			diag("INIT without previous DYNT\n%P", p);
1002 			break;
1003 		}
1004 		p->from.offset = di->value;
1005 		p->from.sym->type = SDATA;
1006 		p->link = datap;
1007 		datap = p;
1008 		break;
1009 
1010 	case ADATA:
1011 		if(p->from.sym == S) {
1012 			diag("DATA without a sym\n%P", p);
1013 			break;
1014 		}
1015 		p->link = datap;
1016 		datap = p;
1017 		break;
1018 
1019 	case AGOK:
1020 		diag("unknown opcode\n%P", p);
1021 		p->pc = pc;
1022 		pc++;
1023 		break;
1024 
1025 	case ATEXT:
1026 		if(curtext != P) {
1027 			histtoauto();
1028 			curtext->to.autom = curauto;
1029 			curauto = 0;
1030 		}
1031 		skip = 0;
1032 		curtext = p;
1033 		autosize = (p->to.offset+3L) & ~3L;
1034 		p->to.offset = autosize;
1035 		autosize += 4;
1036 		s = p->from.sym;
1037 		if(s == S) {
1038 			diag("TEXT must have a name\n%P", p);
1039 			errorexit();
1040 		}
1041 		if(s->type != 0 && s->type != SXREF) {
1042 			if(p->reg & DUPOK) {
1043 				skip = 1;
1044 				goto casedef;
1045 			}
1046 			diag("redefinition: %s\n%P", s->name, p);
1047 		}
1048 		s->type = STEXT;
1049 		s->value = pc;
1050 		lastp->link = p;
1051 		lastp = p;
1052 		p->pc = pc;
1053 		pc++;
1054 		if(textp == P) {
1055 			textp = p;
1056 			etextp = p;
1057 			goto loop;
1058 		}
1059 		etextp->cond = p;
1060 		etextp = p;
1061 		break;
1062 
1063 	case ASUB:
1064 		if(p->from.type == D_CONST)
1065 		if(p->from.name == D_NONE)
1066 		if(p->from.offset < 0) {
1067 			p->from.offset = -p->from.offset;
1068 			p->as = AADD;
1069 		}
1070 		goto casedef;
1071 
1072 	case AADD:
1073 		if(p->from.type == D_CONST)
1074 		if(p->from.name == D_NONE)
1075 		if(p->from.offset < 0) {
1076 			p->from.offset = -p->from.offset;
1077 			p->as = ASUB;
1078 		}
1079 		goto casedef;
1080 
1081 	case AMOVDF:
1082 		if(!vfp || p->from.type != D_FCONST)
1083 			goto casedef;
1084 		p->as = AMOVF;
1085 		/* fall through */
1086 	case AMOVF:
1087 		if(skip)
1088 			goto casedef;
1089 
1090 		if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) {
1091 			/* size sb 9 max */
1092 			sprint(literal, "$%lux", ieeedtof(p->from.ieee));
1093 			s = lookup(literal, 0);
1094 			if(s->type == 0) {
1095 				s->type = SBSS;
1096 				s->value = 4;
1097 				t = prg();
1098 				t->as = ADATA;
1099 				t->line = p->line;
1100 				t->from.type = D_OREG;
1101 				t->from.sym = s;
1102 				t->from.name = D_EXTERN;
1103 				t->reg = 4;
1104 				t->to = p->from;
1105 				t->link = datap;
1106 				datap = t;
1107 			}
1108 			p->from.type = D_OREG;
1109 			p->from.sym = s;
1110 			p->from.name = D_EXTERN;
1111 			p->from.offset = 0;
1112 		}
1113 		goto casedef;
1114 
1115 	case AMOVD:
1116 		if(skip)
1117 			goto casedef;
1118 
1119 		if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) {
1120 			/* size sb 18 max */
1121 			sprint(literal, "$%lux.%lux",
1122 				p->from.ieee->l, p->from.ieee->h);
1123 			s = lookup(literal, 0);
1124 			if(s->type == 0) {
1125 				s->type = SBSS;
1126 				s->value = 8;
1127 				t = prg();
1128 				t->as = ADATA;
1129 				t->line = p->line;
1130 				t->from.type = D_OREG;
1131 				t->from.sym = s;
1132 				t->from.name = D_EXTERN;
1133 				t->reg = 8;
1134 				t->to = p->from;
1135 				t->link = datap;
1136 				datap = t;
1137 			}
1138 			p->from.type = D_OREG;
1139 			p->from.sym = s;
1140 			p->from.name = D_EXTERN;
1141 			p->from.offset = 0;
1142 		}
1143 		goto casedef;
1144 
1145 	default:
1146 	casedef:
1147 		if(skip)
1148 			nopout(p);
1149 
1150 		if(p->to.type == D_BRANCH)
1151 			p->to.offset += ipc;
1152 		lastp->link = p;
1153 		lastp = p;
1154 		p->pc = pc;
1155 		pc++;
1156 		break;
1157 	}
1158 	goto loop;
1159 
1160 eof:
1161 	diag("truncated object file: %s", pn);
1162 }
1163 
1164 Sym*
lookup(char * symb,int v)1165 lookup(char *symb, int v)
1166 {
1167 	Sym *s;
1168 	char *p;
1169 	long h;
1170 	int c, l;
1171 
1172 	h = v;
1173 	for(p=symb; c = *p; p++)
1174 		h = h+h+h + c;
1175 	l = (p - symb) + 1;
1176 	h &= 0xffffff;
1177 	h %= NHASH;
1178 	for(s = hash[h]; s != S; s = s->link)
1179 		if(s->version == v)
1180 		if(memcmp(s->name, symb, l) == 0)
1181 			return s;
1182 
1183 	while(nhunk < sizeof(Sym))
1184 		gethunk();
1185 	s = (Sym*)hunk;
1186 	nhunk -= sizeof(Sym);
1187 	hunk += sizeof(Sym);
1188 
1189 	s->name = malloc(l);
1190 	memmove(s->name, symb, l);
1191 
1192 	s->link = hash[h];
1193 	s->type = 0;
1194 	s->version = v;
1195 	s->value = 0;
1196 	s->sig = 0;
1197 	hash[h] = s;
1198 	return s;
1199 }
1200 
1201 Prog*
prg(void)1202 prg(void)
1203 {
1204 	Prog *p;
1205 
1206 	while(nhunk < sizeof(Prog))
1207 		gethunk();
1208 	p = (Prog*)hunk;
1209 	nhunk -= sizeof(Prog);
1210 	hunk += sizeof(Prog);
1211 
1212 	*p = zprg;
1213 	return p;
1214 }
1215 
1216 void
gethunk(void)1217 gethunk(void)
1218 {
1219 	char *h;
1220 	long nh;
1221 
1222 	nh = NHUNK;
1223 	if(thunk >= 5L*NHUNK) {
1224 		nh = 5L*NHUNK;
1225 		if(thunk >= 25L*NHUNK)
1226 			nh = 25L*NHUNK;
1227 	}
1228 	h = mysbrk(nh);
1229 	if(h == (char*)-1) {
1230 		diag("out of memory");
1231 		errorexit();
1232 	}
1233 	hunk = h;
1234 	nhunk = nh;
1235 	thunk += nh;
1236 }
1237 
1238 void
doprof1(void)1239 doprof1(void)
1240 {
1241 	Sym *s;
1242 	long n;
1243 	Prog *p, *q;
1244 
1245 	if(debug['v'])
1246 		Bprint(&bso, "%5.2f profile 1\n", cputime());
1247 	Bflush(&bso);
1248 	s = lookup("__mcount", 0);
1249 	n = 1;
1250 	for(p = firstp->link; p != P; p = p->link) {
1251 		if(p->as == ATEXT) {
1252 			q = prg();
1253 			q->line = p->line;
1254 			q->link = datap;
1255 			datap = q;
1256 			q->as = ADATA;
1257 			q->from.type = D_OREG;
1258 			q->from.name = D_EXTERN;
1259 			q->from.offset = n*4;
1260 			q->from.sym = s;
1261 			q->reg = 4;
1262 			q->to = p->from;
1263 			q->to.type = D_CONST;
1264 
1265 			q = prg();
1266 			q->line = p->line;
1267 			q->pc = p->pc;
1268 			q->link = p->link;
1269 			p->link = q;
1270 			p = q;
1271 			p->as = AMOVW;
1272 			p->from.type = D_OREG;
1273 			p->from.name = D_EXTERN;
1274 			p->from.sym = s;
1275 			p->from.offset = n*4 + 4;
1276 			p->to.type = D_REG;
1277 			p->to.reg = REGTMP;
1278 
1279 			q = prg();
1280 			q->line = p->line;
1281 			q->pc = p->pc;
1282 			q->link = p->link;
1283 			p->link = q;
1284 			p = q;
1285 			p->as = AADD;
1286 			p->from.type = D_CONST;
1287 			p->from.offset = 1;
1288 			p->to.type = D_REG;
1289 			p->to.reg = REGTMP;
1290 
1291 			q = prg();
1292 			q->line = p->line;
1293 			q->pc = p->pc;
1294 			q->link = p->link;
1295 			p->link = q;
1296 			p = q;
1297 			p->as = AMOVW;
1298 			p->from.type = D_REG;
1299 			p->from.reg = REGTMP;
1300 			p->to.type = D_OREG;
1301 			p->to.name = D_EXTERN;
1302 			p->to.sym = s;
1303 			p->to.offset = n*4 + 4;
1304 
1305 			n += 2;
1306 			continue;
1307 		}
1308 	}
1309 	q = prg();
1310 	q->line = 0;
1311 	q->link = datap;
1312 	datap = q;
1313 
1314 	q->as = ADATA;
1315 	q->from.type = D_OREG;
1316 	q->from.name = D_EXTERN;
1317 	q->from.sym = s;
1318 	q->reg = 4;
1319 	q->to.type = D_CONST;
1320 	q->to.offset = n;
1321 
1322 	s->type = SBSS;
1323 	s->value = n*4;
1324 }
1325 
1326 static int brcond[] = {ABEQ, ABNE, ABCS, ABCC, ABMI, ABPL, ABVS, ABVC, ABHI, ABLS, ABGE, ABLT, ABGT, ABLE};
1327 
1328 void
doprof2(void)1329 doprof2(void)
1330 {
1331 	Sym *s2, *s4;
1332 	Prog *p, *q, *q2, *ps2, *ps4;
1333 
1334 	if(debug['v'])
1335 		Bprint(&bso, "%5.2f profile 2\n", cputime());
1336 	Bflush(&bso);
1337 
1338 	if(debug['e']){
1339 		s2 = lookup("_tracein", 0);
1340 		s4 = lookup("_traceout", 0);
1341 	}else{
1342 		s2 = lookup("_profin", 0);
1343 		s4 = lookup("_profout", 0);
1344 	}
1345 	if(s2->type != STEXT || s4->type != STEXT) {
1346 		if(debug['e'])
1347 			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1348 		else
1349 			diag("_profin/_profout not defined");
1350 		return;
1351 	}
1352 
1353 	ps2 = P;
1354 	ps4 = P;
1355 	for(p = firstp; p != P; p = p->link) {
1356 		if(p->as == ATEXT) {
1357 			if(p->from.sym == s2) {
1358 				ps2 = p;
1359 				p->reg = 1;
1360 			}
1361 			if(p->from.sym == s4) {
1362 				ps4 = p;
1363 				p->reg = 1;
1364 			}
1365 		}
1366 	}
1367 	for(p = firstp; p != P; p = p->link) {
1368 		if(p->as == ATEXT) {
1369 			if(p->reg & NOPROF) {
1370 				for(;;) {
1371 					q = p->link;
1372 					if(q == P)
1373 						break;
1374 					if(q->as == ATEXT)
1375 						break;
1376 					p = q;
1377 				}
1378 				continue;
1379 			}
1380 
1381 			/*
1382 			 * BL	profin
1383 			 */
1384 			q = prg();
1385 			q->line = p->line;
1386 			q->pc = p->pc;
1387 			q->link = p->link;
1388 			if(debug['e']){		/* embedded tracing */
1389 				q2 = prg();
1390 				p->link = q2;
1391 				q2->link = q;
1392 
1393 				q2->line = p->line;
1394 				q2->pc = p->pc;
1395 
1396 				q2->as = AB;
1397 				q2->to.type = D_BRANCH;
1398 				q2->to.sym = p->to.sym;
1399 				q2->cond = q->link;
1400 			}else
1401 				p->link = q;
1402 			p = q;
1403 			p->as = ABL;
1404 			p->to.type = D_BRANCH;
1405 			p->cond = ps2;
1406 			p->to.sym = s2;
1407 
1408 			continue;
1409 		}
1410 		if(p->as == ARET) {
1411 			/*
1412 			 * RET (default)
1413 			 */
1414 			if(debug['e']){		/* embedded tracing */
1415 				q = prg();
1416 				q->line = p->line;
1417 				q->pc = p->pc;
1418 				q->link = p->link;
1419 				p->link = q;
1420 				p = q;
1421 			}
1422 
1423 			/*
1424 			 * RET
1425 			 */
1426 			q = prg();
1427 			q->as = ARET;
1428 			q->from = p->from;
1429 			q->to = p->to;
1430 			q->cond = p->cond;
1431 			q->link = p->link;
1432 			q->reg = p->reg;
1433 			p->link = q;
1434 
1435 			if(p->scond != 14) {
1436 				q = prg();
1437 				q->as = ABL;
1438 				q->from = zprg.from;
1439 				q->to = zprg.to;
1440 				q->to.type = D_BRANCH;
1441 				q->cond = ps4;
1442 				q->to.sym = s4;
1443 				q->link = p->link;
1444 				p->link = q;
1445 
1446 				p->as = brcond[p->scond^1];	/* complement */
1447 				p->scond = 14;
1448 				p->from = zprg.from;
1449 				p->to = zprg.to;
1450 				p->to.type = D_BRANCH;
1451 				p->cond = q->link->link;	/* successor of RET */
1452 				p->to.offset = q->link->link->pc;
1453 
1454 				p = q->link->link;
1455 			} else {
1456 
1457 				/*
1458 				 * BL	profout
1459 				 */
1460 				p->as = ABL;
1461 				p->from = zprg.from;
1462 				p->to = zprg.to;
1463 				p->to.type = D_BRANCH;
1464 				p->cond = ps4;
1465 				p->to.sym = s4;
1466 				p->scond = 14;
1467 
1468 				p = q;
1469 			}
1470 			continue;
1471 		}
1472 	}
1473 }
1474 
1475 void
nuxiinit(void)1476 nuxiinit(void)
1477 {
1478 
1479 	int i, c;
1480 
1481 	for(i=0; i<4; i++) {
1482 		c = find1(0x04030201L, i+1);
1483 		if(i < 2)
1484 			inuxi2[i] = c;
1485 		if(i < 1)
1486 			inuxi1[i] = c;
1487 		inuxi4[i] = c;
1488 		fnuxi4[i] = c;
1489 		if(debug['d'] == 0){
1490 			fnuxi8[i] = c;
1491 			fnuxi8[i+4] = c+4;
1492 		}
1493 		else{
1494 			fnuxi8[i] = c+4;		/* ms word first, then ls, even in little endian mode */
1495 			fnuxi8[i+4] = c;
1496 		}
1497 	}
1498 	if(debug['v']) {
1499 		Bprint(&bso, "inuxi = ");
1500 		for(i=0; i<1; i++)
1501 			Bprint(&bso, "%d", inuxi1[i]);
1502 		Bprint(&bso, " ");
1503 		for(i=0; i<2; i++)
1504 			Bprint(&bso, "%d", inuxi2[i]);
1505 		Bprint(&bso, " ");
1506 		for(i=0; i<4; i++)
1507 			Bprint(&bso, "%d", inuxi4[i]);
1508 		Bprint(&bso, "\nfnuxi = ");
1509 		for(i=0; i<4; i++)
1510 			Bprint(&bso, "%d", fnuxi4[i]);
1511 		Bprint(&bso, " ");
1512 		for(i=0; i<8; i++)
1513 			Bprint(&bso, "%d", fnuxi8[i]);
1514 		Bprint(&bso, "\n");
1515 	}
1516 	Bflush(&bso);
1517 }
1518 
find1(long l,int c)1519 find1(long l, int c)
1520 {
1521 	char *p;
1522 	int i;
1523 
1524 	p = (char*)&l;
1525 	for(i=0; i<4; i++)
1526 		if(*p++ == c)
1527 			return i;
1528 	return 0;
1529 }
1530 
1531 long
ieeedtof(Ieee * ieeep)1532 ieeedtof(Ieee *ieeep)
1533 {
1534 	int exp;
1535 	long v;
1536 
1537 	if(ieeep->h == 0)
1538 		return 0;
1539 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
1540 	exp -= (1L<<10) - 2L;
1541 	v = (ieeep->h & 0xfffffL) << 3;
1542 	v |= (ieeep->l >> 29) & 0x7L;
1543 	if((ieeep->l >> 28) & 1) {
1544 		v++;
1545 		if(v & 0x800000L) {
1546 			v = (v & 0x7fffffL) >> 1;
1547 			exp++;
1548 		}
1549 	}
1550 	if(exp <= -126 || exp >= 130)
1551 		diag("double fp to single fp overflow");
1552 	v |= ((exp + 126) & 0xffL) << 23;
1553 	v |= ieeep->h & 0x80000000L;
1554 	return v;
1555 }
1556 
1557 double
ieeedtod(Ieee * ieeep)1558 ieeedtod(Ieee *ieeep)
1559 {
1560 	Ieee e;
1561 	double fr;
1562 	int exp;
1563 
1564 	if(ieeep->h & (1L<<31)) {
1565 		e.h = ieeep->h & ~(1L<<31);
1566 		e.l = ieeep->l;
1567 		return -ieeedtod(&e);
1568 	}
1569 	if(ieeep->l == 0 && ieeep->h == 0)
1570 		return 0;
1571 	fr = ieeep->l & ((1L<<16)-1L);
1572 	fr /= 1L<<16;
1573 	fr += (ieeep->l>>16) & ((1L<<16)-1L);
1574 	fr /= 1L<<16;
1575 	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1576 	fr /= 1L<<21;
1577 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
1578 	exp -= (1L<<10) - 2L;
1579 	return ldexp(fr, exp);
1580 }
1581 
1582 void
undefsym(Sym * s)1583 undefsym(Sym *s)
1584 {
1585 	int n;
1586 
1587 	n = imports;
1588 	if(s->value != 0)
1589 		diag("value != 0 on SXREF");
1590 	if(n >= 1<<Rindex)
1591 		diag("import index %d out of range", n);
1592 	s->value = n<<Roffset;
1593 	s->type = SUNDEF;
1594 	imports++;
1595 }
1596 
1597 void
zerosig(char * sp)1598 zerosig(char *sp)
1599 {
1600 	Sym *s;
1601 
1602 	s = lookup(sp, 0);
1603 	s->sig = 0;
1604 }
1605 
1606 void
readundefs(char * f,int t)1607 readundefs(char *f, int t)
1608 {
1609 	int i, n;
1610 	Sym *s;
1611 	Biobuf *b;
1612 	char *l, buf[256], *fields[64];
1613 
1614 	if(f == nil)
1615 		return;
1616 	b = Bopen(f, OREAD);
1617 	if(b == nil){
1618 		diag("could not open %s: %r", f);
1619 		errorexit();
1620 	}
1621 	while((l = Brdline(b, '\n')) != nil){
1622 		n = Blinelen(b);
1623 		if(n >= sizeof(buf)){
1624 			diag("%s: line too long", f);
1625 			errorexit();
1626 		}
1627 		memmove(buf, l, n);
1628 		buf[n-1] = '\0';
1629 		n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1630 		if(n == nelem(fields)){
1631 			diag("%s: bad format", f);
1632 			errorexit();
1633 		}
1634 		for(i = 0; i < n; i++) {
1635 			s = lookup(fields[i], 0);
1636 			s->type = SXREF;
1637 			s->subtype = t;
1638 			if(t == SIMPORT)
1639 				nimports++;
1640 			else
1641 				nexports++;
1642 		}
1643 	}
1644 	Bterm(b);
1645 }
1646