xref: /inferno-os/libinterp/dlm-Inferno.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "raise.h"
5 #include "pool.h"
6 #include "kernel.h"
7 #include "dynld.h"
8 
9 #define	DBG	if(1) print
10 
11 extern Dynobj* dynld(int);
12 extern char*	enverror(void);
13 
14 typedef struct{char *name; long sig; void (*fn)(void*); int size; int np; uchar map[16];} Runtab;
15 
16 static void*
addr(char * pre,char * suf,Dynobj * o,ulong sig)17 addr(char *pre, char *suf, Dynobj *o, ulong sig)
18 {
19 	char buf[64];
20 
21 	if(o == nil || strlen(pre)+strlen(suf) > 64-1)
22 		return nil;
23 	snprint(buf, sizeof(buf), "%s%s", pre, suf);
24 	return dynimport(o, buf, sig);
25 }
26 
27 Module*
newdyncode(int fd,char * path,Dir * dir)28 newdyncode(int fd, char *path, Dir *dir)
29 {
30 	Module *m;
31 	void *v;
32 	Runtab *r;
33 	Dynobj *o;
34 	char *name;
35 
36 	DBG("module path is %s\n", path);
37 	m = nil;
38 	o = dynld(fd);
39 	if(o == nil){
40 		DBG("%s\n", enverror());
41 		goto Error;
42 	}
43 	v = addr("XXX", "module", o, signof(char*));
44 	if(v == nil)
45 		goto Error;
46 	name = *(char**)v;
47 	DBG("module name is %s\n", name);
48 	r = addr(name, "modtab", o, signof(Runtab[]));
49 	if(r == nil)
50 		goto Error;
51 	m = builtinmod(name, r, 0);
52 	m->rt = DYNMOD;
53 	m->dev = dir->dev;
54 	m->dtype = dir->type;
55 	m->qid = dir->qid;
56 	m->mtime = dir->mtime;
57 	m->path = strdup(path);
58 	if(m->path == nil)
59 		goto Error;
60 	m->dlm = o;
61 	DBG("module base is 0x%p\n", o->base);
62 	return m;
63 Error:
64 	if(o != nil)
65 		dynobjfree(o);
66 	if(m != nil)
67 		freemod(m);
68 	return nil;
69 }
70 
71 void
freedyncode(Module * m)72 freedyncode(Module *m)
73 {
74 	dynobjfree(m->dlm);
75 }
76 
77 static void
callfn(Module * m,char * fn)78 callfn(Module *m, char *fn)
79 {
80 	void *v, (*f)(void);
81 
82 	if(m->ref != 1)
83 		return;
84 	v = addr(m->name, fn, m->dlm, signof(*f));
85 	if(v != nil){
86 		f = v;
87 		(*f)();
88 	}
89 }
90 
91 void
newdyndata(Modlink * ml)92 newdyndata(Modlink *ml)
93 {
94 	callfn(ml->m, "init");
95 }
96 
97 void
freedyndata(Modlink * ml)98 freedyndata(Modlink *ml)
99 {
100 	callfn(ml->m, "end");
101 }
102