422 lines · 7.3 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. */ #include	"l.h" #define	Dbufslop	100 #define PADDR(a)	((a) & ~0xfffffffff0000000ull) vlongentryvalue(void){	char *a;	Sym *s; 	a = INITENTRY;	if(*a >= '0' && *a <= '9')		return atolwhex(a);	s = lookup(a, 0);	if(s->type == 0)		return INITTEXT;	switch(s->type) {	case STEXT:		break;	case SDATA:		if(dlm)			return s->value+INITDAT;	default:		diag("entry not text: %s", s->name);	}	return s->value;} /* these need to take long arguments to be compatible with elf.c */voidwputl(long w){	cput(w);	cput(w>>8);} voidwput(long w){	cput(w>>8);	cput(w);} voidlput(long l){	cput(l>>24);	cput(l>>16);	cput(l>>8);	cput(l);} voidllput(vlong v){	lput(v>>32);	lput(v);} voidlputl(long l){	cput(l);	cput(l>>8);	cput(l>>16);	cput(l>>24);} voidllputl(vlong v){	lputl(v);	lputl(v>>32);} voidstrnput(char *s, int n){	for(; *s && n > 0; s++){		cput(*s);		n--;	}	while(n > 0){		cput(0);		n--;	}} voidasmb(void){	Prog *p;	long v, magic;	int a;	uchar *op1;	vlong vl; 	if(debug['v'])		Bprint(&bso, "%5.2f asmb\n", cputime());	Bflush(&bso); 	seek(cout, HEADR, 0);	pc = INITTEXT;	curp = firstp;	for(p = firstp; p != P; p = p->link) {		if(p->as == ATEXT)			curtext = p;		if(p->pc != pc) {			if(!debug['a'])				print("%P\n", curp);			diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);			pc = p->pc;		}		curp = p;		asmins(p);		a = (andptr - and);		if(cbc < a)			cflush();		if(debug['a']) {			Bprint(&bso, pcstr, pc);			for(op1 = and; op1 < andptr; op1++)				Bprint(&bso, "%.2ux", *op1 & 0xff);			Bprint(&bso, "\t%P\n", curp);		}		if(dlm) {			if(p->as == ATEXT)				reloca = nil;			else if(reloca != nil)				diag("reloc failure: %P", curp);		}		memmove(cbp, and, a);		cbp += a;		pc += a;		cbc -= a;	}	cflush();	switch(HEADTYPE) {	default:		diag("unknown header type %ld", HEADTYPE);	case 2:	case 5:	case 6:		seek(cout, HEADR+textsize, 0);		break;	} 	if(debug['v'])		Bprint(&bso, "%5.2f datblk\n", cputime());	Bflush(&bso); 	if(dlm){		char buf[8]; 		write(cout, buf, INITDAT-textsize);		textsize = INITDAT;	} 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {		if(datsize-v > sizeof(buf)-Dbufslop)			datblk(v, sizeof(buf)-Dbufslop);		else			datblk(v, datsize-v);	} 	symsize = 0;	spsize = 0;	lcsize = 0;	if(!debug['s']) {		if(debug['v'])			Bprint(&bso, "%5.2f sym\n", cputime());		Bflush(&bso);		switch(HEADTYPE) {		default:		case 2:		case 5:		case 6:			seek(cout, HEADR+textsize+datsize, 0);			break;		}		if(!debug['s'])			asmsym();		if(debug['v'])			Bprint(&bso, "%5.2f sp\n", cputime());		Bflush(&bso);		if(debug['v'])			Bprint(&bso, "%5.2f pc\n", cputime());		Bflush(&bso);		if(!debug['s'])			asmlc();		if(dlm)			asmdyn();		cflush();	}	else if(dlm){		seek(cout, HEADR+textsize+datsize, 0);		asmdyn();		cflush();	}	if(debug['v'])		Bprint(&bso, "%5.2f headr\n", cputime());	Bflush(&bso);	seek(cout, 0L, 0);	switch(HEADTYPE) {	default:	case 2:	/* plan9 */		magic = 4*26*26+7;		magic |= 0x00008000;		/* fat header */		if(dlm)			magic |= 0x80000000;	/* dlm */		lput(magic);			/* magic */		lput(textsize);			/* sizes */		lput(datsize);		lput(bsssize);		lput(symsize);			/* nsyms */		vl = entryvalue();		lput(PADDR(vl));		/* va of entry */		lput(spsize);			/* sp offsets */		lput(lcsize);			/* line offsets */		llput(vl);			/* va of entry */		break;	case 5:		elf32(debug['8']? I386: AMD64, ELFDATA2LSB, 0, nil);		break;	case 6:		elf64(AMD64, ELFDATA2LSB, 0, nil);		break;	}	cflush();} voidcflush(void){	int n; 	n = sizeof(buf.cbuf) - cbc;	if(n)		write(cout, buf.cbuf, n);	cbp = buf.cbuf;	cbc = sizeof(buf.cbuf);} voiddatblk(long s, long n){	Prog *p;	uchar *cast;	long l, fl, j;	vlong o;	int i, c; 	memset(buf.dbuf, 0, n+Dbufslop);	for(p = datap; p != P; p = p->link) {		curp = p;		l = p->from.sym->value + p->from.offset - s;		c = p->from.scale;		i = 0;		if(l < 0) {			if(l+c <= 0)				continue;			while(l < 0) {				l++;				i++;			}		}		if(l >= n)			continue;		if(p->as != AINIT && p->as != ADYNT) {			for(j=l+(c-i)-1; j>=l; j--)				if(buf.dbuf[j]) {					print("%P\n", p);					diag("multiple initialization");					break;				}		}		switch(p->to.type) {		case D_FCONST:			switch(c) {			default:			case 4:				fl = ieeedtof(&p->to.ieee);				cast = (uchar*)&fl;				if(debug['a'] && i == 0) {					Bprint(&bso, pcstr, l+s+INITDAT);					for(j=0; j<c; j++)						Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);					Bprint(&bso, "\t%P\n", curp);				}				for(; i<c; i++) {					buf.dbuf[l] = cast[fnuxi4[i]];					l++;				}				break;			case 8:				cast = (uchar*)&p->to.ieee;				if(debug['a'] && i == 0) {					Bprint(&bso, pcstr, l+s+INITDAT);					for(j=0; j<c; j++)						Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);					Bprint(&bso, "\t%P\n", curp);				}				for(; i<c; i++) {					buf.dbuf[l] = cast[fnuxi8[i]];					l++;				}				break;			}			break; 		case D_SCONST:			if(debug['a'] && i == 0) {				Bprint(&bso, pcstr, l+s+INITDAT);				for(j=0; j<c; j++)					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);				Bprint(&bso, "\t%P\n", curp);			}			for(; i<c; i++) {				buf.dbuf[l] = p->to.scon[i];				l++;			}			break;		default:			o = p->to.offset;			if(p->to.type == D_ADDR) {				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)					diag("DADDR type%P", p);				if(p->to.sym) {					if(p->to.sym->type == SUNDEF)						ckoff(p->to.sym, o);					o += p->to.sym->value;					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)						o += INITDAT;					if(dlm)						dynreloc(p->to.sym, l+s+INITDAT, 1);				}			}			fl = o;			cast = (uchar*)&fl;			switch(c) {			default:				diag("bad nuxi %d %d\n%P", c, i, curp);				break;			case 1:				if(debug['a'] && i == 0) {					Bprint(&bso, pcstr, l+s+INITDAT);					for(j=0; j<c; j++)						Bprint(&bso, "%.2ux", cast[inuxi1[j]]);					Bprint(&bso, "\t%P\n", curp);				}				for(; i<c; i++) {					buf.dbuf[l] = cast[inuxi1[i]];					l++;				}				break;			case 2:				if(debug['a'] && i == 0) {					Bprint(&bso, pcstr, l+s+INITDAT);					for(j=0; j<c; j++)						Bprint(&bso, "%.2ux", cast[inuxi2[j]]);					Bprint(&bso, "\t%P\n", curp);				}				for(; i<c; i++) {					buf.dbuf[l] = cast[inuxi2[i]];					l++;				}				break;			case 4:				if(debug['a'] && i == 0) {					Bprint(&bso, pcstr, l+s+INITDAT);					for(j=0; j<c; j++)						Bprint(&bso, "%.2ux", cast[inuxi4[j]]);					Bprint(&bso, "\t%P\n", curp);				}				for(; i<c; i++) {					buf.dbuf[l] = cast[inuxi4[i]];					l++;				}				break;			case 8:				cast = (uchar*)&o;				if(debug['a'] && i == 0) {					Bprint(&bso, pcstr, l+s+INITDAT);					for(j=0; j<c; j++)						Bprint(&bso, "%.2ux", cast[inuxi8[j]]);					Bprint(&bso, "\t%P\n", curp);				}				for(; i<c; i++) {					buf.dbuf[l] = cast[inuxi8[i]];					l++;				}				break;			}			break;		}	}	write(cout, buf.dbuf, n);} vlongrnd(vlong v, vlong r){	vlong c; 	if(r <= 0)		return v;	v += r - 1;	c = v % r;	if(c < 0)		c += r;	v -= c;	return v;}