1845 lines · 36.2 KB · C
RawDownload
#include	"l.h"#include	<flate.h> long	OFFSET; static Prog *PP; ulongcrc32(char *name, int len, vlong off){	uchar buf[MAXIO];	int fd, n;	ulong crc;	static ulong *crctab; 	if(crctab == nil)		crctab = mkcrctab(0xedb88320);	fd = open(name, OREAD);	if(fd < 0) {		diag("cannot open %s: %r", name);		errorexit();	}	seek(fd, off, 0);	crc = 0;	while(len > 0) {		n = len;		if(n > sizeof buf)			n = sizeof buf;		n = read(fd, buf, n);		if(n < 0) {			diag("cannot read %s: %r", name);			errorexit();		}		crc = blockcrc(crctab, crc, buf, n);		len -= n;	}	close(fd);	return crc;} 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;	switch(s->type) {	case STEXT:	case SLEAF:		break;	case SDATA:		if(dlm)			return s->value+INITDAT;	default:		diag("entry not text: %s", s->name);	}	return s->value;} voidasmb(void){	Prog *p;	long 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 %lux sb %lux",				p->pc, pc);			if(!debug['a'])				prasm(curp);			pc = p->pc;		}		curp = p;		o = oplook(p);	/* could probably avoid this call */		asmout(p, o);		pc += o->size;	} 	if(debug['a'])		Bprint(&bso, "\n");	Bflush(&bso);	cflush(); 	/* output strings in text segment */	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);	} 	curtext = P;	switch(HEADTYPE) {	case 0:	case 1:	case 2:	case 5:	case 7:		OFFSET = HEADR+textsize;		seek(cout, OFFSET, 0);		break;	case 3:	case 6:	/* no header, padded segments */		OFFSET = rnd(HEADR+textsize, 4096);		seek(cout, OFFSET, 0);		break;	case 8:		OFFSET = rnd(textsize, 4096)+HEADR;		seek(cout, OFFSET, 0);		break;	}	if(dlm){		char buf[8]; 		write(cout, buf, INITDAT-textsize);		textsize = INITDAT;	}	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 1:		case 4:		case 5:		case 8:			debug['s'] = 1;			break;		case 2:			OFFSET = HEADR+textsize+datsize;			seek(cout, OFFSET, 0);			break;		case 3:		case 6:	/* no header, padded segments */			OFFSET += rnd(datsize, 4096);			seek(cout, OFFSET, 0);			break;		case 7:			break;		}		if(!debug['s'])			asmsym();		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 header\n", cputime());	Bflush(&bso);	OFFSET = 0;	seek(cout, OFFSET, 0);	switch(HEADTYPE) {	case 0:	/* no header */	case 6:	/* no header, padded segments */		break;	case 1:	/* aif for risc os */		lputl(0xe1a00000);		/* NOP - decompress code */		lputl(0xe1a00000);		/* NOP - relocation code */		lputl(0xeb000000 + 12);		/* BL - zero init code */		lputl(0xeb000000 +			(entryvalue()			 - INITTEXT			 + HEADR			 - 12			 - 8) / 4);		/* BL - entry code */ 		lputl(0xef000011);		/* SWI - exit code */		lputl(textsize+HEADR);		/* text size */		lputl(datsize);			/* data size */		lputl(0);			/* sym size */ 		lputl(bsssize);			/* bss size */		lputl(0);			/* sym type */		lputl(INITTEXT-HEADR);		/* text addr */		lputl(0);			/* workspace - ignored */ 		lputl(32);			/* addr mode / data addr flag */		lputl(0);			/* data addr */		for(t=0; t<2; t++)			lputl(0);		/* reserved */ 		for(t=0; t<15; t++)			lputl(0xe1a00000);	/* NOP - zero init code */		lputl(0xe1a0f00e);		/* B (R14) - zero init return */		break;	case 2:	/* plan 9 */		if(dlm)			lput(0x80000000|0x647);	/* magic */		else			lput(0x647);			/* magic */		lput(textsize);			/* sizes */		lput(datsize);		lput(bsssize);		lput(symsize);			/* nsyms */		lput(entryvalue());		/* va of entry */		lput(0L);		lput(lcsize);		break;	case 3:	/* boot for NetBSD */		lput((143<<16)|0413);		/* magic */		lputl(rnd(HEADR+textsize, 4096));		lputl(rnd(datsize, 4096));		lputl(bsssize);		lputl(symsize);			/* nsyms */		lputl(entryvalue());		/* va of entry */		lputl(0L);		lputl(0L);		break;	case 4: /* boot for IXP1200 */		break;	case 5: /* boot for ipaq */		lputl(0xe3300000);		/* nop */		lputl(0xe3300000);		/* nop */		lputl(0xe3300000);		/* nop */		lputl(0xe3300000);		/* nop */		break;	case 7:	/* elf */		debug['S'] = 1;			/* symbol table */		elf32(ARM, ELFDATA2LSB, 0, nil);		break;	}	cflush();} voidstrnput(char *s, int n){	for(; *s; s++){		cput(*s);		n--;	}	for(; n > 0; n--)		cput(0);} voidcput(int c){	cbp[0] = c;	cbp++;	cbc--;	if(cbc <= 0)		cflush();} 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){ 	cbp[0] = l>>24;	cbp[1] = l>>16;	cbp[2] = l>>8;	cbp[3] = l;	cbp += 4;	cbc -= 4;	if(cbc <= 0)		cflush();} voidlputl(long l){ 	cbp[3] = l>>24;	cbp[2] = l>>16;	cbp[1] = l>>8;	cbp[0] = l;	cbp += 4;	cbc -= 4;	if(cbc <= 0)		cflush();} voidllput(vlong v){	lput(v>>32);	lput(v);} voidllputl(vlong v){	lputl(v);	lputl(v>>32);} 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 SDATA:				putsymb(s->name, 'D', s->value+INITDAT, s->version);				continue; 			case SBSS:				putsymb(s->name, 'B', s->value+INITDAT, s->version);				continue; 			case SSTRING:				putsymb(s->name, 'T', s->value, 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)			if(a->type == D_AUTO)				putsymb(a->asym->name, 'a', -a->aoffset, 0);			else			if(a->type == D_PARAM)				putsymb(a->asym->name, 'p', a->aoffset, 0);	}	if(debug['v'] || debug['n'])		Bprint(&bso, "symsize = %lud\n", symsize);	Bflush(&bso);} voidputsymb(char *s, int t, long v, int ver){	int i, f; 	if(t == 'f')		s++;	lput(v);	if(ver)		t += 'a' - 'A';	cput(t+0x80);			/* 0x80 is variable length */ 	if(t == 'Z' || t == 'z') {		cput(s[0]);		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {			cput(s[i]);			cput(s[i+1]);		}		cput(0);		cput(0);		i++;	}	else {		for(i=0; s[i]; i++)			cput(s[i]);		cput(0);	}	symsize += 4 + 1 + i + 1; 	if(debug['n']) {		if(t == 'z' || t == 'Z') {			Bprint(&bso, "%c %.8lux ", t, v);			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);				Bprint(&bso, "/%x", f);			}			Bprint(&bso, "\n");			return;		}		if(ver)			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);		else			Bprint(&bso, "%c %.8lux %s\n", t, v, s);	}} #define	MINLC	4voidasmlc(void){	long oldpc, oldlc;	Prog *p;	long v, s; 	oldpc = INITTEXT;	oldlc = 0;	for(p = firstp; p != P; p = p->link) {		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {			if(p->as == ATEXT)				curtext = p;

Lines 1–500 of 1845.