xref: /inferno-os/libinterp/load.c (revision 7de2b42d50e3c05cc143e7b51284009b5e185581)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "isa.h"
3*37da2899SCharles.Forsyth #include "interp.h"
4*37da2899SCharles.Forsyth #include "raise.h"
5*37da2899SCharles.Forsyth #include <kernel.h>
6*37da2899SCharles.Forsyth 
7*37da2899SCharles.Forsyth #define	A(r)	*((Array**)(r))
8*37da2899SCharles.Forsyth 
9*37da2899SCharles.Forsyth Module*	modules;
10*37da2899SCharles.Forsyth int	dontcompile;
11*37da2899SCharles.Forsyth 
12*37da2899SCharles.Forsyth static int
operand(uchar ** p)13*37da2899SCharles.Forsyth operand(uchar **p)
14*37da2899SCharles.Forsyth {
15*37da2899SCharles.Forsyth 	int c;
16*37da2899SCharles.Forsyth 	uchar *cp;
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 	cp = *p;
19*37da2899SCharles.Forsyth 	c = cp[0];
20*37da2899SCharles.Forsyth 	switch(c & 0xC0) {
21*37da2899SCharles.Forsyth 	case 0x00:
22*37da2899SCharles.Forsyth 		*p = cp+1;
23*37da2899SCharles.Forsyth 		return c;
24*37da2899SCharles.Forsyth 	case 0x40:
25*37da2899SCharles.Forsyth 		*p = cp+1;
26*37da2899SCharles.Forsyth 		return c|~0x7F;
27*37da2899SCharles.Forsyth 	case 0x80:
28*37da2899SCharles.Forsyth 		*p = cp+2;
29*37da2899SCharles.Forsyth 		if(c & 0x20)
30*37da2899SCharles.Forsyth 			c |= ~0x3F;
31*37da2899SCharles.Forsyth 		else
32*37da2899SCharles.Forsyth 			c &= 0x3F;
33*37da2899SCharles.Forsyth 		return (c<<8)|cp[1];
34*37da2899SCharles.Forsyth 	case 0xC0:
35*37da2899SCharles.Forsyth 		*p = cp+4;
36*37da2899SCharles.Forsyth 		if(c & 0x20)
37*37da2899SCharles.Forsyth 			c |= ~0x3F;
38*37da2899SCharles.Forsyth 		else
39*37da2899SCharles.Forsyth 			c &= 0x3F;
40*37da2899SCharles.Forsyth 		return (c<<24)|(cp[1]<<16)|(cp[2]<<8)|cp[3];
41*37da2899SCharles.Forsyth 	}
42*37da2899SCharles.Forsyth 	return 0;
43*37da2899SCharles.Forsyth }
44*37da2899SCharles.Forsyth 
45*37da2899SCharles.Forsyth static ulong
disw(uchar ** p)46*37da2899SCharles.Forsyth disw(uchar **p)
47*37da2899SCharles.Forsyth {
48*37da2899SCharles.Forsyth 	ulong v;
49*37da2899SCharles.Forsyth 	uchar *c;
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth 	c = *p;
52*37da2899SCharles.Forsyth 	v  = c[0] << 24;
53*37da2899SCharles.Forsyth 	v |= c[1] << 16;
54*37da2899SCharles.Forsyth 	v |= c[2] << 8;
55*37da2899SCharles.Forsyth 	v |= c[3];
56*37da2899SCharles.Forsyth 	*p = c + 4;
57*37da2899SCharles.Forsyth 	return v;
58*37da2899SCharles.Forsyth }
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth double
canontod(ulong v[2])61*37da2899SCharles.Forsyth canontod(ulong v[2])
62*37da2899SCharles.Forsyth {
63*37da2899SCharles.Forsyth 	union { double d; unsigned long ul[2]; } a;
64*37da2899SCharles.Forsyth 	a.d = 1.;
65*37da2899SCharles.Forsyth 	if(a.ul[0]) {
66*37da2899SCharles.Forsyth 		a.ul[0] = v[0];
67*37da2899SCharles.Forsyth 		a.ul[1] = v[1];
68*37da2899SCharles.Forsyth 	}
69*37da2899SCharles.Forsyth 	else {
70*37da2899SCharles.Forsyth 		a.ul[1] = v[0];
71*37da2899SCharles.Forsyth 		a.ul[0] = v[1];
72*37da2899SCharles.Forsyth 	}
73*37da2899SCharles.Forsyth 	return a.d;
74*37da2899SCharles.Forsyth }
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth Module*
load(char * path)77*37da2899SCharles.Forsyth load(char *path)
78*37da2899SCharles.Forsyth {
79*37da2899SCharles.Forsyth 	return readmod(path, nil, 0);
80*37da2899SCharles.Forsyth }
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth int
brpatch(Inst * ip,Module * m)83*37da2899SCharles.Forsyth brpatch(Inst *ip, Module *m)
84*37da2899SCharles.Forsyth {
85*37da2899SCharles.Forsyth 	switch(ip->op) {
86*37da2899SCharles.Forsyth 	case ICALL:
87*37da2899SCharles.Forsyth 	case IJMP:
88*37da2899SCharles.Forsyth 	case IBEQW:
89*37da2899SCharles.Forsyth 	case IBNEW:
90*37da2899SCharles.Forsyth 	case IBLTW:
91*37da2899SCharles.Forsyth 	case IBLEW:
92*37da2899SCharles.Forsyth 	case IBGTW:
93*37da2899SCharles.Forsyth 	case IBGEW:
94*37da2899SCharles.Forsyth 	case IBEQB:
95*37da2899SCharles.Forsyth 	case IBNEB:
96*37da2899SCharles.Forsyth 	case IBLTB:
97*37da2899SCharles.Forsyth 	case IBLEB:
98*37da2899SCharles.Forsyth 	case IBGTB:
99*37da2899SCharles.Forsyth 	case IBGEB:
100*37da2899SCharles.Forsyth 	case IBEQF:
101*37da2899SCharles.Forsyth 	case IBNEF:
102*37da2899SCharles.Forsyth 	case IBLTF:
103*37da2899SCharles.Forsyth 	case IBLEF:
104*37da2899SCharles.Forsyth 	case IBGTF:
105*37da2899SCharles.Forsyth 	case IBGEF:
106*37da2899SCharles.Forsyth 	case IBEQC:
107*37da2899SCharles.Forsyth 	case IBNEC:
108*37da2899SCharles.Forsyth 	case IBLTC:
109*37da2899SCharles.Forsyth 	case IBLEC:
110*37da2899SCharles.Forsyth 	case IBGTC:
111*37da2899SCharles.Forsyth 	case IBGEC:
112*37da2899SCharles.Forsyth 	case IBEQL:
113*37da2899SCharles.Forsyth 	case IBNEL:
114*37da2899SCharles.Forsyth 	case IBLTL:
115*37da2899SCharles.Forsyth 	case IBLEL:
116*37da2899SCharles.Forsyth 	case IBGTL:
117*37da2899SCharles.Forsyth 	case IBGEL:
118*37da2899SCharles.Forsyth 	case ISPAWN:
119*37da2899SCharles.Forsyth 		if(ip->d.imm < 0 || ip->d.imm >= m->nprog)
120*37da2899SCharles.Forsyth 			return 0;
121*37da2899SCharles.Forsyth 		ip->d.imm = (WORD)&m->prog[ip->d.imm];
122*37da2899SCharles.Forsyth 		break;
123*37da2899SCharles.Forsyth 	}
124*37da2899SCharles.Forsyth 	return 1;
125*37da2899SCharles.Forsyth }
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth Module*
parsemod(char * path,uchar * code,ulong length,Dir * dir)128*37da2899SCharles.Forsyth parsemod(char *path, uchar *code, ulong length, Dir *dir)
129*37da2899SCharles.Forsyth {
130*37da2899SCharles.Forsyth 	Heap *h;
131*37da2899SCharles.Forsyth 	Inst *ip;
132*37da2899SCharles.Forsyth 	Type *pt;
133*37da2899SCharles.Forsyth 	String *s;
134*37da2899SCharles.Forsyth 	Module *m;
135*37da2899SCharles.Forsyth 	Array *ary;
136*37da2899SCharles.Forsyth 	ulong ul[2];
137*37da2899SCharles.Forsyth 	WORD lo, hi;
138*37da2899SCharles.Forsyth 	int lsize, id, v, entry, entryt, tnp, tsz, siglen;
139*37da2899SCharles.Forsyth 	int de, pc, i, n, isize, dsize, hsize, dasp;
140*37da2899SCharles.Forsyth 	uchar *mod, sm, *istream, **isp, *si, *addr, *dastack[DADEPTH];
141*37da2899SCharles.Forsyth 	Link *l;
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth 	istream = code;
144*37da2899SCharles.Forsyth 	isp = &istream;
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth 	m = malloc(sizeof(Module));
147*37da2899SCharles.Forsyth 	if(m == nil)
148*37da2899SCharles.Forsyth 		return nil;
149*37da2899SCharles.Forsyth 
150*37da2899SCharles.Forsyth 	m->dev = dir->dev;
151*37da2899SCharles.Forsyth 	m->dtype = dir->type;
152*37da2899SCharles.Forsyth 	m->qid = dir->qid;
153*37da2899SCharles.Forsyth 	m->mtime = dir->mtime;
154*37da2899SCharles.Forsyth 	m->origmp = H;
155*37da2899SCharles.Forsyth 	m->pctab = nil;
156*37da2899SCharles.Forsyth 
157*37da2899SCharles.Forsyth 	switch(operand(isp)) {
158*37da2899SCharles.Forsyth 	default:
159*37da2899SCharles.Forsyth 		kwerrstr("bad magic");
160*37da2899SCharles.Forsyth 		goto bad;
161*37da2899SCharles.Forsyth 	case SMAGIC:
162*37da2899SCharles.Forsyth 		siglen = operand(isp);
163*37da2899SCharles.Forsyth 		n = length-(*isp-code);
164*37da2899SCharles.Forsyth 		if(n < 0 || siglen > n){
165*37da2899SCharles.Forsyth 			kwerrstr("corrupt signature");
166*37da2899SCharles.Forsyth 			goto bad;
167*37da2899SCharles.Forsyth 		}
168*37da2899SCharles.Forsyth 		if(verifysigner(*isp, siglen, *isp+siglen, n-siglen) == 0) {
169*37da2899SCharles.Forsyth 			kwerrstr("security violation");
170*37da2899SCharles.Forsyth 			goto bad;
171*37da2899SCharles.Forsyth 		}
172*37da2899SCharles.Forsyth 		*isp += siglen;
173*37da2899SCharles.Forsyth 		break;
174*37da2899SCharles.Forsyth 	case XMAGIC:
175*37da2899SCharles.Forsyth 		if(mustbesigned(path, code, length, dir)){
176*37da2899SCharles.Forsyth 			kwerrstr("security violation: not signed");
177*37da2899SCharles.Forsyth 			goto bad;
178*37da2899SCharles.Forsyth 		}
179*37da2899SCharles.Forsyth 		break;
180*37da2899SCharles.Forsyth 	}
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth 	m->rt = operand(isp);
183*37da2899SCharles.Forsyth 	m->ss = operand(isp);
184*37da2899SCharles.Forsyth 	isize = operand(isp);
185*37da2899SCharles.Forsyth 	dsize = operand(isp);
186*37da2899SCharles.Forsyth 	hsize = operand(isp);
187*37da2899SCharles.Forsyth 	lsize = operand(isp);
188*37da2899SCharles.Forsyth 	entry = operand(isp);
189*37da2899SCharles.Forsyth 	entryt = operand(isp);
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth 	if(isize < 0 || dsize < 0 || hsize < 0 || lsize < 0) {
192*37da2899SCharles.Forsyth 		kwerrstr("implausible Dis file");
193*37da2899SCharles.Forsyth 		goto bad;
194*37da2899SCharles.Forsyth 	}
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth 	m->nprog = isize;
197*37da2899SCharles.Forsyth 	m->prog = mallocz(isize*sizeof(Inst), 0);
198*37da2899SCharles.Forsyth 	if(m->prog == nil) {
199*37da2899SCharles.Forsyth 		kwerrstr(exNomem);
200*37da2899SCharles.Forsyth 		goto bad;
201*37da2899SCharles.Forsyth 	}
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth 	m->ref = 1;
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth 	ip = m->prog;
206*37da2899SCharles.Forsyth 	for(i = 0; i < isize; i++) {
207*37da2899SCharles.Forsyth 		ip->op = *istream++;
208*37da2899SCharles.Forsyth 		ip->add = *istream++;
209*37da2899SCharles.Forsyth 		ip->reg = 0;
210*37da2899SCharles.Forsyth 		ip->s.imm = 0;
211*37da2899SCharles.Forsyth 		ip->d.imm = 0;
212*37da2899SCharles.Forsyth 		switch(ip->add & ARM) {
213*37da2899SCharles.Forsyth 		case AXIMM:
214*37da2899SCharles.Forsyth 		case AXINF:
215*37da2899SCharles.Forsyth 		case AXINM:
216*37da2899SCharles.Forsyth 			ip->reg = operand(isp);
217*37da2899SCharles.Forsyth 		 	break;
218*37da2899SCharles.Forsyth 		}
219*37da2899SCharles.Forsyth 		switch(UXSRC(ip->add)) {
220*37da2899SCharles.Forsyth 		case SRC(AFP):
221*37da2899SCharles.Forsyth 		case SRC(AMP):
222*37da2899SCharles.Forsyth 		case SRC(AIMM):
223*37da2899SCharles.Forsyth 			ip->s.ind = operand(isp);
224*37da2899SCharles.Forsyth 			break;
225*37da2899SCharles.Forsyth 		case SRC(AIND|AFP):
226*37da2899SCharles.Forsyth 		case SRC(AIND|AMP):
227*37da2899SCharles.Forsyth 			ip->s.i.f = operand(isp);
228*37da2899SCharles.Forsyth 			ip->s.i.s = operand(isp);
229*37da2899SCharles.Forsyth 			break;
230*37da2899SCharles.Forsyth 		}
231*37da2899SCharles.Forsyth 		switch(UXDST(ip->add)) {
232*37da2899SCharles.Forsyth 		case DST(AFP):
233*37da2899SCharles.Forsyth 		case DST(AMP):
234*37da2899SCharles.Forsyth 			ip->d.ind = operand(isp);
235*37da2899SCharles.Forsyth 			break;
236*37da2899SCharles.Forsyth 		case DST(AIMM):
237*37da2899SCharles.Forsyth 			ip->d.ind = operand(isp);
238*37da2899SCharles.Forsyth 			if(brpatch(ip, m) == 0) {
239*37da2899SCharles.Forsyth 				kwerrstr("bad branch addr");
240*37da2899SCharles.Forsyth 				goto bad;
241*37da2899SCharles.Forsyth 			}
242*37da2899SCharles.Forsyth 			break;
243*37da2899SCharles.Forsyth 		case DST(AIND|AFP):
244*37da2899SCharles.Forsyth 		case DST(AIND|AMP):
245*37da2899SCharles.Forsyth 			ip->d.i.f = operand(isp);
246*37da2899SCharles.Forsyth 			ip->d.i.s = operand(isp);
247*37da2899SCharles.Forsyth 			break;
248*37da2899SCharles.Forsyth 		}
249*37da2899SCharles.Forsyth 		ip++;
250*37da2899SCharles.Forsyth 	}
251*37da2899SCharles.Forsyth 
252*37da2899SCharles.Forsyth 	m->ntype = hsize;
253*37da2899SCharles.Forsyth 	m->type = malloc(hsize*sizeof(Type*));
254*37da2899SCharles.Forsyth 	if(m->type == nil) {
255*37da2899SCharles.Forsyth 		kwerrstr(exNomem);
256*37da2899SCharles.Forsyth 		goto bad;
257*37da2899SCharles.Forsyth 	}
258*37da2899SCharles.Forsyth 	for(i = 0; i < hsize; i++) {
259*37da2899SCharles.Forsyth 		id = operand(isp);
260*37da2899SCharles.Forsyth 		if(id > hsize) {
261*37da2899SCharles.Forsyth 			kwerrstr("heap id range");
262*37da2899SCharles.Forsyth 			goto bad;
263*37da2899SCharles.Forsyth 		}
264*37da2899SCharles.Forsyth 		tsz = operand(isp);
265*37da2899SCharles.Forsyth 		tnp = operand(isp);
266*37da2899SCharles.Forsyth 		if(tsz < 0 || tnp < 0 || tnp > 128*1024){
267*37da2899SCharles.Forsyth 			kwerrstr("implausible Dis file");
268*37da2899SCharles.Forsyth 			goto bad;
269*37da2899SCharles.Forsyth 		}
270*37da2899SCharles.Forsyth 		pt = dtype(freeheap, tsz, istream, tnp);
271*37da2899SCharles.Forsyth 		if(pt == nil) {
272*37da2899SCharles.Forsyth 			kwerrstr(exNomem);
273*37da2899SCharles.Forsyth 			goto bad;
274*37da2899SCharles.Forsyth 		}
275*37da2899SCharles.Forsyth 		istream += tnp;
276*37da2899SCharles.Forsyth 		m->type[id] = pt;
277*37da2899SCharles.Forsyth 	}
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth 	if(dsize != 0) {
280*37da2899SCharles.Forsyth 		pt = m->type[0];
281*37da2899SCharles.Forsyth 		if(pt == 0 || pt->size != dsize) {
282*37da2899SCharles.Forsyth 			kwerrstr("bad desc for mp");
283*37da2899SCharles.Forsyth 			goto bad;
284*37da2899SCharles.Forsyth 		}
285*37da2899SCharles.Forsyth 		h = heapz(pt);
286*37da2899SCharles.Forsyth 		m->origmp = H2D(uchar*, h);
287*37da2899SCharles.Forsyth 	}
288*37da2899SCharles.Forsyth 	addr = m->origmp;
289*37da2899SCharles.Forsyth 	dasp = 0;
290*37da2899SCharles.Forsyth 	for(;;) {
291*37da2899SCharles.Forsyth 		sm = *istream++;
292*37da2899SCharles.Forsyth 		if(sm == 0)
293*37da2899SCharles.Forsyth 			break;
294*37da2899SCharles.Forsyth 		n = DLEN(sm);
295*37da2899SCharles.Forsyth 		if(n == 0)
296*37da2899SCharles.Forsyth 			n = operand(isp);
297*37da2899SCharles.Forsyth 		v = operand(isp);
298*37da2899SCharles.Forsyth 		si = addr + v;
299*37da2899SCharles.Forsyth 		switch(DTYPE(sm)) {
300*37da2899SCharles.Forsyth 		default:
301*37da2899SCharles.Forsyth 			kwerrstr("bad data item");
302*37da2899SCharles.Forsyth 			goto bad;
303*37da2899SCharles.Forsyth 		case DEFS:
304*37da2899SCharles.Forsyth 			s = c2string((char*)istream, n);
305*37da2899SCharles.Forsyth 			istream += n;
306*37da2899SCharles.Forsyth 			*(String**)si = s;
307*37da2899SCharles.Forsyth 			break;
308*37da2899SCharles.Forsyth 		case DEFB:
309*37da2899SCharles.Forsyth 			for(i = 0; i < n; i++)
310*37da2899SCharles.Forsyth 				*si++ = *istream++;
311*37da2899SCharles.Forsyth 			break;
312*37da2899SCharles.Forsyth 		case DEFW:
313*37da2899SCharles.Forsyth 			for(i = 0; i < n; i++) {
314*37da2899SCharles.Forsyth 				*(WORD*)si = disw(isp);
315*37da2899SCharles.Forsyth 				si += sizeof(WORD);
316*37da2899SCharles.Forsyth 			}
317*37da2899SCharles.Forsyth 			break;
318*37da2899SCharles.Forsyth 		case DEFL:
319*37da2899SCharles.Forsyth 			for(i = 0; i < n; i++) {
320*37da2899SCharles.Forsyth 				hi = disw(isp);
321*37da2899SCharles.Forsyth 				lo = disw(isp);
322*37da2899SCharles.Forsyth 				*(LONG*)si = (LONG)hi << 32 | (LONG)(ulong)lo;
323*37da2899SCharles.Forsyth 				si += sizeof(LONG);
324*37da2899SCharles.Forsyth 			}
325*37da2899SCharles.Forsyth 			break;
326*37da2899SCharles.Forsyth 		case DEFF:
327*37da2899SCharles.Forsyth 			for(i = 0; i < n; i++) {
328*37da2899SCharles.Forsyth 				ul[0] = disw(isp);
329*37da2899SCharles.Forsyth 				ul[1] = disw(isp);
330*37da2899SCharles.Forsyth 				*(REAL*)si = canontod(ul);
331*37da2899SCharles.Forsyth 				si += sizeof(REAL);
332*37da2899SCharles.Forsyth 			}
333*37da2899SCharles.Forsyth 			break;
334*37da2899SCharles.Forsyth 		case DEFA:			/* Array */
335*37da2899SCharles.Forsyth 			v = disw(isp);
336*37da2899SCharles.Forsyth 			if(v < 0 || v > m->ntype) {
337*37da2899SCharles.Forsyth 				kwerrstr("bad array type");
338*37da2899SCharles.Forsyth 				goto bad;
339*37da2899SCharles.Forsyth 			}
340*37da2899SCharles.Forsyth 			pt = m->type[v];
341*37da2899SCharles.Forsyth 			v = disw(isp);
342*37da2899SCharles.Forsyth 			h = nheap(sizeof(Array)+(pt->size*v));
343*37da2899SCharles.Forsyth 			h->t = &Tarray;
344*37da2899SCharles.Forsyth 			h->t->ref++;
345*37da2899SCharles.Forsyth 			ary = H2D(Array*, h);
346*37da2899SCharles.Forsyth 			ary->t = pt;
347*37da2899SCharles.Forsyth 			ary->len = v;
348*37da2899SCharles.Forsyth 			ary->root = H;
349*37da2899SCharles.Forsyth 			ary->data = (uchar*)ary+sizeof(Array);
350*37da2899SCharles.Forsyth 			memset((void*)ary->data, 0, pt->size*v);
351*37da2899SCharles.Forsyth 			initarray(pt, ary);
352*37da2899SCharles.Forsyth 			A(si) = ary;
353*37da2899SCharles.Forsyth 			break;
354*37da2899SCharles.Forsyth 		case DIND:			/* Set index */
355*37da2899SCharles.Forsyth 			ary = A(si);
356*37da2899SCharles.Forsyth 			if(ary == H || D2H(ary)->t != &Tarray) {
357*37da2899SCharles.Forsyth 				kwerrstr("ind not array");
358*37da2899SCharles.Forsyth 				goto bad;
359*37da2899SCharles.Forsyth 			}
360*37da2899SCharles.Forsyth 			v = disw(isp);
361*37da2899SCharles.Forsyth 			if(v > ary->len || v < 0 || dasp >= DADEPTH) {
362*37da2899SCharles.Forsyth 				kwerrstr("array init range");
363*37da2899SCharles.Forsyth 				goto bad;
364*37da2899SCharles.Forsyth 			}
365*37da2899SCharles.Forsyth 			dastack[dasp++] = addr;
366*37da2899SCharles.Forsyth 			addr = ary->data+v*ary->t->size;
367*37da2899SCharles.Forsyth 			break;
368*37da2899SCharles.Forsyth 		case DAPOP:
369*37da2899SCharles.Forsyth 			if(dasp == 0) {
370*37da2899SCharles.Forsyth 				kwerrstr("pop range");
371*37da2899SCharles.Forsyth 				goto bad;
372*37da2899SCharles.Forsyth 			}
373*37da2899SCharles.Forsyth 			addr = dastack[--dasp];
374*37da2899SCharles.Forsyth 			break;
375*37da2899SCharles.Forsyth 		}
376*37da2899SCharles.Forsyth 	}
377*37da2899SCharles.Forsyth 	mod = istream;
378*37da2899SCharles.Forsyth 	if(memchr(mod, 0, 128) == 0) {
379*37da2899SCharles.Forsyth 		kwerrstr("bad module name");
380*37da2899SCharles.Forsyth 		goto bad;
381*37da2899SCharles.Forsyth 	}
382*37da2899SCharles.Forsyth 	m->name = strdup((char*)mod);
383*37da2899SCharles.Forsyth 	if(m->name == nil) {
384*37da2899SCharles.Forsyth 		kwerrstr(exNomem);
385*37da2899SCharles.Forsyth 		goto bad;
386*37da2899SCharles.Forsyth 	}
387*37da2899SCharles.Forsyth 	while(*istream++)
388*37da2899SCharles.Forsyth 		;
389*37da2899SCharles.Forsyth 
390*37da2899SCharles.Forsyth 	l = m->ext = (Link*)malloc((lsize+1)*sizeof(Link));
391*37da2899SCharles.Forsyth 	if(l == nil){
392*37da2899SCharles.Forsyth 		kwerrstr(exNomem);
393*37da2899SCharles.Forsyth 		goto bad;
394*37da2899SCharles.Forsyth 	}
395*37da2899SCharles.Forsyth 	for(i = 0; i < lsize; i++, l++) {
396*37da2899SCharles.Forsyth 		pc = operand(isp);
397*37da2899SCharles.Forsyth 		de = operand(isp);
398*37da2899SCharles.Forsyth 		v  = disw(isp);
399*37da2899SCharles.Forsyth 		pt = nil;
400*37da2899SCharles.Forsyth 		if(de != -1)
401*37da2899SCharles.Forsyth 			pt = m->type[de];
402*37da2899SCharles.Forsyth 		mlink(m, l, istream, v, pc, pt);
403*37da2899SCharles.Forsyth 		while(*istream++)
404*37da2899SCharles.Forsyth 			;
405*37da2899SCharles.Forsyth 	}
406*37da2899SCharles.Forsyth 	l->name = nil;
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth 	if(m->rt & HASLDT0){
409*37da2899SCharles.Forsyth 		kwerrstr("obsolete dis");
410*37da2899SCharles.Forsyth 		goto bad;
411*37da2899SCharles.Forsyth 	}
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth 	if(m->rt & HASLDT){
414*37da2899SCharles.Forsyth 		int j, nl;
415*37da2899SCharles.Forsyth 		Import *i1, **i2;
416*37da2899SCharles.Forsyth 
417*37da2899SCharles.Forsyth 		nl = operand(isp);
418*37da2899SCharles.Forsyth 		i2 = m->ldt = (Import**)malloc((nl+1)*sizeof(Import*));
419*37da2899SCharles.Forsyth 		if(i2 == nil){
420*37da2899SCharles.Forsyth 			kwerrstr(exNomem);
421*37da2899SCharles.Forsyth 			goto bad;
422*37da2899SCharles.Forsyth 		}
423*37da2899SCharles.Forsyth 		for(i = 0; i < nl; i++, i2++){
424*37da2899SCharles.Forsyth 			n = operand(isp);
425*37da2899SCharles.Forsyth 			i1 = *i2 = (Import*)malloc((n+1)*sizeof(Import));
426*37da2899SCharles.Forsyth 			if(i1 == nil){
427*37da2899SCharles.Forsyth 				kwerrstr(exNomem);
428*37da2899SCharles.Forsyth 				goto bad;
429*37da2899SCharles.Forsyth 			}
430*37da2899SCharles.Forsyth 			for(j = 0; j < n; j++, i1++){
431*37da2899SCharles.Forsyth 				i1->sig = disw(isp);
432*37da2899SCharles.Forsyth 				i1->name = strdup((char*)istream);
433*37da2899SCharles.Forsyth 				if(i1->name == nil){
434*37da2899SCharles.Forsyth 					kwerrstr(exNomem);
435*37da2899SCharles.Forsyth 					goto bad;
436*37da2899SCharles.Forsyth 				}
437*37da2899SCharles.Forsyth 				while(*istream++)
438*37da2899SCharles.Forsyth 					;
439*37da2899SCharles.Forsyth 			}
440*37da2899SCharles.Forsyth 		}
441*37da2899SCharles.Forsyth 		istream++;
442*37da2899SCharles.Forsyth 	}
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth 	if(m->rt & HASEXCEPT){
445*37da2899SCharles.Forsyth 		int j, nh;
446*37da2899SCharles.Forsyth 		Handler *h;
447*37da2899SCharles.Forsyth 		Except *e;
448*37da2899SCharles.Forsyth 
449*37da2899SCharles.Forsyth 		nh = operand(isp);
450*37da2899SCharles.Forsyth 		m->htab = malloc((nh+1)*sizeof(Handler));
451*37da2899SCharles.Forsyth 		if(m->htab == nil){
452*37da2899SCharles.Forsyth 			kwerrstr(exNomem);
453*37da2899SCharles.Forsyth 			goto bad;
454*37da2899SCharles.Forsyth 		}
455*37da2899SCharles.Forsyth 		h = m->htab;
456*37da2899SCharles.Forsyth 		for(i = 0; i < nh; i++, h++){
457*37da2899SCharles.Forsyth 			h->eoff = operand(isp);
458*37da2899SCharles.Forsyth 			h->pc1 = operand(isp);
459*37da2899SCharles.Forsyth 			h->pc2 = operand(isp);
460*37da2899SCharles.Forsyth 			n = operand(isp);
461*37da2899SCharles.Forsyth 			if(n != -1)
462*37da2899SCharles.Forsyth 				h->t = m->type[n];
463*37da2899SCharles.Forsyth 			n = operand(isp);
464*37da2899SCharles.Forsyth 			h->ne = n>>16;
465*37da2899SCharles.Forsyth 			n &= 0xffff;
466*37da2899SCharles.Forsyth 			h->etab = malloc((n+1)*sizeof(Except));
467*37da2899SCharles.Forsyth 			if(h->etab == nil){
468*37da2899SCharles.Forsyth 				kwerrstr(exNomem);
469*37da2899SCharles.Forsyth 				goto bad;
470*37da2899SCharles.Forsyth 			}
471*37da2899SCharles.Forsyth 			e = h->etab;
472*37da2899SCharles.Forsyth 			for(j = 0; j < n; j++, e++){
473*37da2899SCharles.Forsyth 				e->s = strdup((char*)istream);
474*37da2899SCharles.Forsyth 				if(e->s == nil){
475*37da2899SCharles.Forsyth 					kwerrstr(exNomem);
476*37da2899SCharles.Forsyth 					goto bad;
477*37da2899SCharles.Forsyth 				}
478*37da2899SCharles.Forsyth 				while(*istream++)
479*37da2899SCharles.Forsyth 					;
480*37da2899SCharles.Forsyth 				e->pc = operand(isp);
481*37da2899SCharles.Forsyth 			}
482*37da2899SCharles.Forsyth 			e->s = nil;
483*37da2899SCharles.Forsyth 			e->pc = operand(isp);
484*37da2899SCharles.Forsyth 		}
485*37da2899SCharles.Forsyth 		istream++;
486*37da2899SCharles.Forsyth 	}
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth 	m->entryt = nil;
489*37da2899SCharles.Forsyth 	m->entry = m->prog;
490*37da2899SCharles.Forsyth 	if((ulong)entry < isize && (ulong)entryt < hsize) {
491*37da2899SCharles.Forsyth 		m->entry = &m->prog[entry];
492*37da2899SCharles.Forsyth 		m->entryt = m->type[entryt];
493*37da2899SCharles.Forsyth 	}
494*37da2899SCharles.Forsyth 
495*37da2899SCharles.Forsyth 	if(cflag) {
496*37da2899SCharles.Forsyth 		if((m->rt&DONTCOMPILE) == 0 && !dontcompile)
497*37da2899SCharles.Forsyth 			compile(m, isize, nil);
498*37da2899SCharles.Forsyth 	}
499*37da2899SCharles.Forsyth 	else
500*37da2899SCharles.Forsyth 	if(m->rt & MUSTCOMPILE && !dontcompile) {
501*37da2899SCharles.Forsyth 		if(compile(m, isize, nil) == 0) {
502*37da2899SCharles.Forsyth 			kwerrstr("compiler required");
503*37da2899SCharles.Forsyth 			goto bad;
504*37da2899SCharles.Forsyth 		}
505*37da2899SCharles.Forsyth 	}
506*37da2899SCharles.Forsyth 
507*37da2899SCharles.Forsyth 	m->path = strdup(path);
508*37da2899SCharles.Forsyth 	if(m->path == nil) {
509*37da2899SCharles.Forsyth 		kwerrstr(exNomem);
510*37da2899SCharles.Forsyth 		goto bad;
511*37da2899SCharles.Forsyth 	}
512*37da2899SCharles.Forsyth 	m->link = modules;
513*37da2899SCharles.Forsyth 	modules = m;
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth 	return m;
516*37da2899SCharles.Forsyth bad:
517*37da2899SCharles.Forsyth 	destroy(m->origmp);
518*37da2899SCharles.Forsyth 	freemod(m);
519*37da2899SCharles.Forsyth 	return nil;
520*37da2899SCharles.Forsyth }
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth Module*
newmod(char * s)523*37da2899SCharles.Forsyth newmod(char *s)
524*37da2899SCharles.Forsyth {
525*37da2899SCharles.Forsyth 	Module *m;
526*37da2899SCharles.Forsyth 
527*37da2899SCharles.Forsyth 	m = malloc(sizeof(Module));
528*37da2899SCharles.Forsyth 	if(m == nil)
529*37da2899SCharles.Forsyth 		error(exNomem);
530*37da2899SCharles.Forsyth 	m->ref = 1;
531*37da2899SCharles.Forsyth 	m->path = s;
532*37da2899SCharles.Forsyth 	m->origmp = H;
533*37da2899SCharles.Forsyth 	m->name = strdup(s);
534*37da2899SCharles.Forsyth 	if(m->name == nil) {
535*37da2899SCharles.Forsyth 		free(m);
536*37da2899SCharles.Forsyth 		error(exNomem);
537*37da2899SCharles.Forsyth 	}
538*37da2899SCharles.Forsyth 	m->link = modules;
539*37da2899SCharles.Forsyth 	modules = m;
540*37da2899SCharles.Forsyth 	m->pctab = nil;
541*37da2899SCharles.Forsyth 	return m;
542*37da2899SCharles.Forsyth }
543*37da2899SCharles.Forsyth 
544*37da2899SCharles.Forsyth Module*
lookmod(char * s)545*37da2899SCharles.Forsyth lookmod(char *s)
546*37da2899SCharles.Forsyth {
547*37da2899SCharles.Forsyth 	Module *m;
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth 	for(m = modules; m != nil; m = m->link)
550*37da2899SCharles.Forsyth 		if(strcmp(s, m->path) == 0) {
551*37da2899SCharles.Forsyth 			m->ref++;
552*37da2899SCharles.Forsyth 			return m;
553*37da2899SCharles.Forsyth 		}
554*37da2899SCharles.Forsyth 	return nil;
555*37da2899SCharles.Forsyth }
556*37da2899SCharles.Forsyth 
557*37da2899SCharles.Forsyth void
freemod(Module * m)558*37da2899SCharles.Forsyth freemod(Module *m)
559*37da2899SCharles.Forsyth {
560*37da2899SCharles.Forsyth 	int i;
561*37da2899SCharles.Forsyth 	Handler *h;
562*37da2899SCharles.Forsyth 	Except *e;
563*37da2899SCharles.Forsyth 	Import *i1, **i2;
564*37da2899SCharles.Forsyth 
565*37da2899SCharles.Forsyth 	if(m->type != nil) {
566*37da2899SCharles.Forsyth 		for(i = 0; i < m->ntype; i++)
567*37da2899SCharles.Forsyth 			freetype(m->type[i]);
568*37da2899SCharles.Forsyth 		free(m->type);
569*37da2899SCharles.Forsyth 	}
570*37da2899SCharles.Forsyth 	free(m->name);
571*37da2899SCharles.Forsyth 	free(m->prog);
572*37da2899SCharles.Forsyth 	free(m->path);
573*37da2899SCharles.Forsyth 	free(m->pctab);
574*37da2899SCharles.Forsyth 	if(m->ldt != nil){
575*37da2899SCharles.Forsyth 		for(i2 = m->ldt; *i2 != nil; i2++){
576*37da2899SCharles.Forsyth 			for(i1 = *i2; i1->name != nil; i1++)
577*37da2899SCharles.Forsyth 				free(i1->name);
578*37da2899SCharles.Forsyth 			free(*i2);
579*37da2899SCharles.Forsyth 		}
580*37da2899SCharles.Forsyth 		free(m->ldt);
581*37da2899SCharles.Forsyth 	}
582*37da2899SCharles.Forsyth 	if(m->htab != nil){
583*37da2899SCharles.Forsyth 		for(h = m->htab; h->etab != nil; h++){
584*37da2899SCharles.Forsyth 			for(e = h->etab; e->s != nil; e++)
585*37da2899SCharles.Forsyth 				free(e->s);
586*37da2899SCharles.Forsyth 			free(h->etab);
587*37da2899SCharles.Forsyth 		}
588*37da2899SCharles.Forsyth 		free(m->htab);
589*37da2899SCharles.Forsyth 	}
590*37da2899SCharles.Forsyth 	free(m);
591*37da2899SCharles.Forsyth }
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth void
unload(Module * m)594*37da2899SCharles.Forsyth unload(Module *m)
595*37da2899SCharles.Forsyth {
596*37da2899SCharles.Forsyth 	Module **last, *mm;
597*37da2899SCharles.Forsyth 
598*37da2899SCharles.Forsyth 	m->ref--;
599*37da2899SCharles.Forsyth 	if(m->ref > 0)
600*37da2899SCharles.Forsyth 		return;
601*37da2899SCharles.Forsyth 	if(m->ref == -1)
602*37da2899SCharles.Forsyth 		abort();
603*37da2899SCharles.Forsyth 
604*37da2899SCharles.Forsyth 	last = &modules;
605*37da2899SCharles.Forsyth 	for(mm = modules; mm != nil; mm = mm->link) {
606*37da2899SCharles.Forsyth 		if(mm == m) {
607*37da2899SCharles.Forsyth 			*last = m->link;
608*37da2899SCharles.Forsyth 			break;
609*37da2899SCharles.Forsyth 		}
610*37da2899SCharles.Forsyth 		last = &mm->link;
611*37da2899SCharles.Forsyth 	}
612*37da2899SCharles.Forsyth 
613*37da2899SCharles.Forsyth 	if(m->rt == DYNMOD)
614*37da2899SCharles.Forsyth 		freedyncode(m);
615*37da2899SCharles.Forsyth 	else
616*37da2899SCharles.Forsyth 		destroy(m->origmp);
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth 	destroylinks(m);
619*37da2899SCharles.Forsyth 
620*37da2899SCharles.Forsyth 	freemod(m);
621*37da2899SCharles.Forsyth }
622