1438 lines · 29.1 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" /* can't include a.out.h due to name clashes, but these are taken from it */#define	_MAGIC(f, b)	((f)|((((4*(b))+0)*(b))+7))#define	V_MAGIC		_MAGIC(0, 16)		/* mips 3000 BE */#define	M_MAGIC		_MAGIC(0, 18)		/* mips 4000 BE */#define	N_MAGIC		_MAGIC(0, 22)		/* mips 4000 LE */#define	P_MAGIC		_MAGIC(0, 24)		/* mips 3000 LE */ long	OFFSET;/*long	BADOFFSET	=	-1; 		if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\			abort();\		OFFSET += 4;\ 		if(OFFSET == BADOFFSET)\			abort();\		OFFSET++;\*/ #define LPUT(l) { \		if (little) { \			LLEPUT(l); \		} else { \			LBEPUT(l); \		} \	} #define	LLEPUT(c)\	{\		cbp[0] = (c);\		cbp[1] = (c)>>8;\		cbp[2] = (c)>>16;\		cbp[3] = (c)>>24;\		cbp += 4;\		cbc -= 4;\		if(cbc <= 0)\			cflush();\	} #define	LBEPUT(c)\	{\		cbp[0] = (c)>>24;\		cbp[1] = (c)>>16;\		cbp[2] = (c)>>8;\		cbp[3] = (c);\		cbp += 4;\		cbc -= 4;\		if(cbc <= 0)\			cflush();\	} #define HPUT(h) { \		if (little) { \			HLEPUT(h); \		} else { \			HBEPUT(h); \		} \	} #define	HLEPUT(c)\	{\		cbp[0] = (c);\		cbp[1] = (c)>>8;\		cbp += 2;\		cbc -= 2;\		if(cbc <= 0)\			cflush();\	} #define	HBEPUT(c)\	{\		cbp[0] = (c)>>8;\		cbp[1] = (c);\		cbp += 2;\		cbc -= 2;\		if(cbc <= 0)\			cflush();\	}  #define	CPUT(c)\	{\		cbp[0] = (c);\		cbp++;\		cbc--;\		if(cbc <= 0)\			cflush();\	} voidcput(long l){	CPUT(l);} voidobjput(long l)	/* emit long in byte order appropriate to object machine */{	LPUT(l);} voidobjhput(short s){	HPUT(s);} voidwput(long l){ 	cbp[0] = l>>8;	cbp[1] = l;	cbp += 2;	cbc -= 2;	if(cbc <= 0)		cflush();} voidwputl(long l){ 	cbp[0] = l;	cbp[1] = l>>8;	cbp += 2;	cbc -= 2;	if(cbc <= 0)		cflush();} voidlput(long l)		/* emit long in big-endian byte order */{	LBEPUT(l);} voidlputl(long l)		/* emit long in big-endian byte order */{	LLEPUT(l);} voidllput(vlong v){	lput(v>>32);	lput(v);} voidllputl(vlong v){	lputl(v);	lputl(v>>32);} longentryvalue(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;	if(s->type != STEXT && s->type != SLEAF)		diag("entry not text: %s", s->name);	return s->value;} static voidplan9bootimage(ulong sects, ulong submagicvers, ulong tm,	ulong hdrtxtsz, ulong textsz, ulong textva, ulong lcsize){	lput(0x160L<<16|sects);		/* magic and sections */	lput(tm);			/* time and date */	lput(hdrtxtsz+datsize);		/* offset to symbol table */	lput(symsize);			/* size of symbol table */	lput((0x38L<<16)|7L);		/* size of optional hdr and flags */	lput(submagicvers);		/* magic and version */ 	lput(textsz);			/* segment sizes */	lput(datsize);	lput(bsssize); 	lput(entryvalue());		/* va of entry */	lput(textva);			/* va of base of text */	lput(INITDAT);			/* va of base of data */	lput(INITDAT+datsize);		/* va of base of bss */ 	lput(~0);			/* gp reg mask */	lput(lcsize);			/* pcsize / cprmask[0] */	lput(0);			/* coproc reg masks[1⋯3] */	lput(0);	lput(0);	lput(~0);			/* gp value ?? */} static voidsymhdrs(ulong hdrtxtsz){	strnput(".text", 8);		/* text segment */	lput(INITTEXT);			/* address */	lput(INITTEXT);	lput(textsize);	lput(HEADR);	lput(0);	lput(HEADR+textsize+datsize+symsize);	lput(lcsize);			/* line number size */	lput(0x20);			/* flags */ 	strnput(".data", 8);		/* data segment */	lput(INITDAT);			/* address */	lput(INITDAT);	lput(datsize);	lput(hdrtxtsz);	lput(0);	lput(0);	lput(0);	lput(0x40);			/* flags */ 	strnput(".bss", 8);		/* bss segment */	lput(INITDAT+datsize);		/* address */	lput(INITDAT+datsize);	lput(bsssize);	lput(0);	lput(0);	lput(0);	lput(0);	lput(0x80);			/* flags */} voidasmb(void){	Prog *p;	long tm;	ulong rndtxtsz;	vlong t, etext;	Optab *o; 	if(debug['v'])		Bprint(&bso, "%5.2f asm\n", cputime());	Bflush(&bso);	OFFSET = HEADR;	seek(cout, OFFSET, 0);	pc = INITTEXT;	for(p = firstp; p != P; p = p->link) {		if(p->as == ATEXT) {			curtext = p;			autosize = p->to.offset + 4;		}		if(p->pc != pc) {			diag("phase error %llux sb %llux", p->pc, pc);			if(!debug['a'])				prasm(curp);			pc = p->pc;		}		curp = p;		o = oplook(p);	/* could probably avoid this call */		if(asmout(p, o, 0)) {			p = p->link;			pc += 4;		}		pc += o->size;	}	if(debug['a'])		Bprint(&bso, "\n");	Bflush(&bso);	cflush(); 	etext = INITTEXT + textsize;	for(t = pc; t < etext; t += sizeof(buf)-100) {		if(etext-t > sizeof(buf)-100)			datblk(t, sizeof(buf)-100, 1);		else			datblk(t, etext-t, 1);	} 	Bflush(&bso);	cflush(); 	curtext = P;	switch(HEADTYPE) {	case 0:	case 4:		OFFSET = rnd(HEADR+textsize, 4096);		seek(cout, OFFSET, 0);		break;	case 1:	case 2:	case 3:	case 5:	case 6:	case 7:		OFFSET = HEADR+textsize;		seek(cout, OFFSET, 0);		break;	}	for(t = 0; t < datsize; t += sizeof(buf)-100) {		if(datsize-t > sizeof(buf)-100)			datblk(t, sizeof(buf)-100, 0);		else			datblk(t, datsize-t, 0);	} 	symsize = 0;	lcsize = 0;	if(!debug['s']) {		if(debug['v'])			Bprint(&bso, "%5.2f sym\n", cputime());		Bflush(&bso);		switch(HEADTYPE) {		case 0:		case 4:			OFFSET = rnd(HEADR+textsize, 4096)+datsize;			seek(cout, OFFSET, 0);			break;		case 3:		case 2:		case 1:		case 5:		case 6:		case 7:			OFFSET = HEADR+textsize+datsize;			seek(cout, OFFSET, 0);			break;		}		if(!debug['s'])			asmsym();		if(debug['v'])			Bprint(&bso, "%5.2f pc\n", cputime());		Bflush(&bso);		if(!debug['s'])			asmlc();		cflush();	} 	if(debug['v'])		Bprint(&bso, "%5.2f header\n", cputime());	Bflush(&bso);	OFFSET = 0;	seek(cout, OFFSET, 0); 	rndtxtsz = rnd(HEADR+textsize, (INITRND > 0? INITRND: 4096));	tm = time(0);	switch(HEADTYPE) {	case 0:		/* 0413: plan 9 boot image, text segment rounded (to 4KB) */		plan9bootimage(0, 0413<<16|0437, 0, rndtxtsz, rndtxtsz,			INITTEXT-HEADR, 0);		break;	case 1:		/* 0407: plan 9 boot image, extra word */		plan9bootimage(0, 0407<<16|0437, 0, HEADR+textsize, textsize,			INITTEXT, lcsize);		lput(0);			/* extra; complete mystery */		break;	case 2:					/* plan 9 format */		if (little)			lput(P_MAGIC);		/* mips 3000 LE */		else			lput(V_MAGIC);		/* mips 3000 BE */		lput(textsize);			/* sizes */		lput(datsize);		lput(bsssize);		lput(symsize);			/* nsyms */		lput(entryvalue());		/* va of entry */		lput(0L);		lput(lcsize);		break;	case 3:		/* 0407: plan 9 mips 4k boot image with symbols */		plan9bootimage(3, 0407<<16|0437, tm, HEADR+textsize, textsize,			INITTEXT, lcsize);		symhdrs(HEADR+textsize);		break;	case 4:		/* 0413: plan 9 mips 4k boot image with symbols */		plan9bootimage(3, 0413<<16|01012, tm, rndtxtsz, textsize,			INITTEXT, lcsize);		symhdrs(rndtxtsz);		break;	case 5:		elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);		break;	case 6:		break;	case 7:		elf64(MIPSR4K, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);		break;	}	cflush();} voidstrnput(char *s, int n){	for(; *s; s++){		CPUT(*s);		n--;	}	for(; n > 0; n--)		CPUT(0);} voidcflush(void){	int n; 	n = sizeof(buf.cbuf) - cbc;	if(n)		write(cout, buf.cbuf, n);	cbp = buf.cbuf;	cbc = sizeof(buf.cbuf);} voidnopstat(char *f, Count *c){	if(c->outof)	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,		c->outof - c->count, c->outof,		(double)(c->outof - c->count)/c->outof);} voidasmsym(void){	Prog *p;	Auto *a;	Sym *s;	int h; 	s = lookup("etext", 0);	if(s->type == STEXT)		putsymb(s->name, 'T', s->value, s->version); 	for(h=0; h<NHASH; h++)		for(s=hash[h]; s!=S; s=s->link)			switch(s->type) {			case SCONST:				putsymb(s->name, 'D', s->value, s->version);				continue; 			case SSTRING:				putsymb(s->name, 'T', s->value, s->version);				continue; 			case SDATA:				putsymb(s->name, 'D', s->value+INITDAT, s->version);				continue; 			case SBSS:				putsymb(s->name, 'B', s->value+INITDAT, s->version);				continue; 			case SFILE:				putsymb(s->name, 'f', s->value, s->version);				continue;			} 	for(p=textp; p!=P; p=p->cond) {		s = p->from.sym;		if(s->type != STEXT && s->type != SLEAF)			continue; 		/* filenames first */		for(a=p->to.autom; a; a=a->link)			if(a->type == D_FILE)				putsymb(a->asym->name, 'z', a->aoffset, 0);			else			if(a->type == D_FILE1)				putsymb(a->asym->name, 'Z', a->aoffset, 0); 		if(s->type == STEXT)			putsymb(s->name, 'T', s->value, s->version);		else			putsymb(s->name, 'L', s->value, s->version); 		/* frame, auto and param after */		putsymb(".frame", 'm', p->to.offset+4, 0);		for(a=p->to.autom; a; a=a->link)

Lines 1–500 of 1438.