forsyth20100810-230642ca81116 years agoHistory
621 lines · 10.1 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h"#include <kernel.h> #define	A(r)	*((Array**)(r)) Module*	modules;int	dontcompile; static intoperand(uchar **p){	int c;	uchar *cp; 	cp = *p;	c = cp[0];	switch(c & 0xC0) {	case 0x00:		*p = cp+1;		return c;	case 0x40:		*p = cp+1;		return c|~0x7F;	case 0x80:		*p = cp+2;		if(c & 0x20)			c |= ~0x3F;		else			c &= 0x3F;		return (c<<8)|cp[1];			case 0xC0:		*p = cp+4;		if(c & 0x20)			c |= ~0x3F;		else			c &= 0x3F;		return (c<<24)|(cp[1]<<16)|(cp[2]<<8)|cp[3];			}	return 0;	} static ulongdisw(uchar **p){	ulong v;	uchar *c; 	c = *p;	v  = c[0] << 24;	v |= c[1] << 16;	v |= c[2] << 8;	v |= c[3];	*p = c + 4;	return v;} doublecanontod(ulong v[2]){	union { double d; unsigned long ul[2]; } a;	a.d = 1.;	if(a.ul[0]) {		a.ul[0] = v[0];		a.ul[1] = v[1];	}	else {		a.ul[1] = v[0];		a.ul[0] = v[1];	}	return a.d;} Module*load(char *path){	return readmod(path, nil, 0);} intbrpatch(Inst *ip, Module *m){	switch(ip->op) {	case ICALL:	case IJMP:	case IBEQW:	case IBNEW:	case IBLTW:	case IBLEW:	case IBGTW:	case IBGEW:	case IBEQB:	case IBNEB:	case IBLTB:	case IBLEB:	case IBGTB:	case IBGEB:	case IBEQF:	case IBNEF:	case IBLTF:	case IBLEF:	case IBGTF:	case IBGEF:	case IBEQC:	case IBNEC:	case IBLTC:	case IBLEC:	case IBGTC:	case IBGEC:	case IBEQL:	case IBNEL:	case IBLTL:	case IBLEL:	case IBGTL:	case IBGEL:	case ISPAWN:		if(ip->d.imm < 0 || ip->d.imm >= m->nprog)			return 0;		ip->d.imm = (WORD)&m->prog[ip->d.imm];		break;	}	return 1;} Module*parsemod(char *path, uchar *code, ulong length, Dir *dir){	Heap *h;	Inst *ip;	Type *pt;	String *s;	Module *m;	Array *ary;	ulong ul[2];	WORD lo, hi;	int lsize, id, v, entry, entryt, tnp, tsz, siglen;	int de, pc, i, n, isize, dsize, hsize, dasp;	uchar *mod, sm, *istream, **isp, *si, *addr, *dastack[DADEPTH];	Link *l; 	istream = code;	isp = &istream; 	m = malloc(sizeof(Module));	if(m == nil)		return nil; 	m->dev = dir->dev;	m->dtype = dir->type;	m->qid = dir->qid;	m->mtime = dir->mtime;	m->origmp = H;	m->pctab = nil; 	switch(operand(isp)) {	default:		kwerrstr("bad magic");		goto bad;	case SMAGIC:		siglen = operand(isp);		n = length-(*isp-code);		if(n < 0 || siglen > n){			kwerrstr("corrupt signature");			goto bad;		}		if(verifysigner(*isp, siglen, *isp+siglen, n-siglen) == 0) {			kwerrstr("security violation");			goto bad;		}		*isp += siglen;		break;			case XMAGIC:		if(mustbesigned(path, code, length, dir)){			kwerrstr("security violation: not signed");			goto bad;		}		break;	} 	m->rt = operand(isp);	m->ss = operand(isp);	isize = operand(isp);	dsize = operand(isp);	hsize = operand(isp);	lsize = operand(isp);	entry = operand(isp);	entryt = operand(isp); 	if(isize < 0 || dsize < 0 || hsize < 0 || lsize < 0) {		kwerrstr("implausible Dis file");		goto bad;	} 	m->nprog = isize;	m->prog = mallocz(isize*sizeof(Inst), 0);	if(m->prog == nil) {		kwerrstr(exNomem);		goto bad;	} 	m->ref = 1; 	ip = m->prog;	for(i = 0; i < isize; i++) {		ip->op = *istream++;		ip->add = *istream++;		ip->reg = 0;		ip->s.imm = 0;		ip->d.imm = 0;		switch(ip->add & ARM) {		case AXIMM:		case AXINF:		case AXINM:			ip->reg = operand(isp);		 	break;		}		switch(UXSRC(ip->add)) {		case SRC(AFP):		case SRC(AMP):			case SRC(AIMM):			ip->s.ind = operand(isp);			break;		case SRC(AIND|AFP):		case SRC(AIND|AMP):			ip->s.i.f = operand(isp);			ip->s.i.s = operand(isp);			break;		}		switch(UXDST(ip->add)) {		case DST(AFP):		case DST(AMP):				ip->d.ind = operand(isp);			break;		case DST(AIMM):			ip->d.ind = operand(isp);			if(brpatch(ip, m) == 0) {				kwerrstr("bad branch addr");				goto bad;			}			break;		case DST(AIND|AFP):		case DST(AIND|AMP):			ip->d.i.f = operand(isp);			ip->d.i.s = operand(isp);			break;		}		ip++;			} 	m->ntype = hsize;	m->type = malloc(hsize*sizeof(Type*));	if(m->type == nil) {		kwerrstr(exNomem);		goto bad;	}	for(i = 0; i < hsize; i++) {		id = operand(isp);		if(id > hsize) {			kwerrstr("heap id range");			goto bad;		}		tsz = operand(isp);		tnp = operand(isp);		if(tsz < 0 || tnp < 0 || tnp > 128*1024){			kwerrstr("implausible Dis file");			goto bad;		}		pt = dtype(freeheap, tsz, istream, tnp);		if(pt == nil) {			kwerrstr(exNomem);			goto bad;		}		istream += tnp;		m->type[id] = pt;	} 	if(dsize != 0) {		pt = m->type[0];		if(pt == 0 || pt->size != dsize) {			kwerrstr("bad desc for mp");			goto bad;		}		h = heapz(pt);		m->origmp = H2D(uchar*, h);	}	addr = m->origmp;	dasp = 0;	for(;;) {		sm = *istream++;		if(sm == 0)			break;		n = DLEN(sm);		if(n == 0)			n = operand(isp);		v = operand(isp);		si = addr + v;		switch(DTYPE(sm)) {		default:			kwerrstr("bad data item");			goto bad;		case DEFS:			s = c2string((char*)istream, n);			istream += n;			*(String**)si = s;			break;		case DEFB:			for(i = 0; i < n; i++)				*si++ = *istream++;			break;		case DEFW:			for(i = 0; i < n; i++) {				*(WORD*)si = disw(isp);				si += sizeof(WORD);			}			break;		case DEFL:			for(i = 0; i < n; i++) {				hi = disw(isp);				lo = disw(isp);				*(LONG*)si = (LONG)hi << 32 | (LONG)(ulong)lo;				si += sizeof(LONG);			}			break;		case DEFF:			for(i = 0; i < n; i++) {				ul[0] = disw(isp);				ul[1] = disw(isp);				*(REAL*)si = canontod(ul);				si += sizeof(REAL);			}			break;		case DEFA:			/* Array */			v = disw(isp);			if(v < 0 || v > m->ntype) {				kwerrstr("bad array type");				goto bad;			}			pt = m->type[v];			v = disw(isp);			h = nheap(sizeof(Array)+(pt->size*v));			h->t = &Tarray;			h->t->ref++;			ary = H2D(Array*, h);			ary->t = pt;			ary->len = v;			ary->root = H;			ary->data = (uchar*)ary+sizeof(Array);			memset((void*)ary->data, 0, pt->size*v);			initarray(pt, ary);			A(si) = ary;			break;					case DIND:			/* Set index */			ary = A(si);			if(ary == H || D2H(ary)->t != &Tarray) {				kwerrstr("ind not array");				goto bad;			}			v = disw(isp);			if(v > ary->len || v < 0 || dasp >= DADEPTH) {				kwerrstr("array init range");				goto bad;			}			dastack[dasp++] = addr;			addr = ary->data+v*ary->t->size;			break;		case DAPOP:			if(dasp == 0) {				kwerrstr("pop range");				goto bad;			}			addr = dastack[--dasp];			break;		}	}	mod = istream;	if(memchr(mod, 0, 128) == 0) {		kwerrstr("bad module name");		goto bad;	}	m->name = strdup((char*)mod);	if(m->name == nil) {		kwerrstr(exNomem);		goto bad;	}	while(*istream++)		; 	l = m->ext = (Link*)malloc((lsize+1)*sizeof(Link));	if(l == nil){		kwerrstr(exNomem);		goto bad;	}	for(i = 0; i < lsize; i++, l++) {		pc = operand(isp);		de = operand(isp);		v  = disw(isp);		pt = nil;		if(de != -1)			pt = m->type[de];		mlink(m, l, istream, v, pc, pt);		while(*istream++)			;	}	l->name = nil; 	if(m->rt & HASLDT0){		kwerrstr("obsolete dis");		goto bad;	} 	if(m->rt & HASLDT){		int j, nl;		Import *i1, **i2; 		nl = operand(isp);		i2 = m->ldt = (Import**)malloc((nl+1)*sizeof(Import*));		if(i2 == nil){			kwerrstr(exNomem);			goto bad;		}		for(i = 0; i < nl; i++, i2++){			n = operand(isp);			i1 = *i2 = (Import*)malloc((n+1)*sizeof(Import));			if(i1 == nil){				kwerrstr(exNomem);				goto bad;			}			for(j = 0; j < n; j++, i1++){				i1->sig = disw(isp);				i1->name = strdup((char*)istream);				if(i1->name == nil){					kwerrstr(exNomem);					goto bad;				}				while(*istream++)					;			}		}		istream++;	} 	if(m->rt & HASEXCEPT){		int j, nh;		Handler *h;		Except *e; 		nh = operand(isp);		m->htab = malloc((nh+1)*sizeof(Handler));		if(m->htab == nil){			kwerrstr(exNomem);			goto bad;		}		h = m->htab;		for(i = 0; i < nh; i++, h++){			h->eoff = operand(isp);			h->pc1 = operand(isp);			h->pc2 = operand(isp);			n = operand(isp);			if(n != -1)				h->t = m->type[n];			n = operand(isp);			h->ne = n>>16;			n &= 0xffff;			h->etab = malloc((n+1)*sizeof(Except));			if(h->etab == nil){				kwerrstr(exNomem);				goto bad;			}			e = h->etab;			for(j = 0; j < n; j++, e++){				e->s = strdup((char*)istream);				if(e->s == nil){					kwerrstr(exNomem);					goto bad;				}				while(*istream++)					;				e->pc = operand(isp);			}			e->s = nil;			e->pc = operand(isp);		}		istream++;	} 	m->entryt = nil;	m->entry = m->prog;	if((ulong)entry < isize && (ulong)entryt < hsize) {		m->entry = &m->prog[entry];		m->entryt = m->type[entryt];	} 	if(cflag) {		if((m->rt&DONTCOMPILE) == 0 && !dontcompile)			compile(m, isize, nil);	}	else	if(m->rt & MUSTCOMPILE && !dontcompile) {

Lines 1–500 of 621.