1*dfc11533SChris Williamson /*
2*dfc11533SChris Williamson ** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $
3*dfc11533SChris Williamson ** load precompiled Lua chunks
4*dfc11533SChris Williamson ** See Copyright Notice in lua.h
5*dfc11533SChris Williamson */
6*dfc11533SChris Williamson
7*dfc11533SChris Williamson #include <sys/zfs_context.h>
8*dfc11533SChris Williamson
9*dfc11533SChris Williamson #define lundump_c
10*dfc11533SChris Williamson #define LUA_CORE
11*dfc11533SChris Williamson
12*dfc11533SChris Williamson #include "lua.h"
13*dfc11533SChris Williamson
14*dfc11533SChris Williamson #include "ldebug.h"
15*dfc11533SChris Williamson #include "ldo.h"
16*dfc11533SChris Williamson #include "lfunc.h"
17*dfc11533SChris Williamson #include "lmem.h"
18*dfc11533SChris Williamson #include "lobject.h"
19*dfc11533SChris Williamson #include "lstring.h"
20*dfc11533SChris Williamson #include "lundump.h"
21*dfc11533SChris Williamson #include "lzio.h"
22*dfc11533SChris Williamson
23*dfc11533SChris Williamson typedef struct {
24*dfc11533SChris Williamson lua_State* L;
25*dfc11533SChris Williamson ZIO* Z;
26*dfc11533SChris Williamson Mbuffer* b;
27*dfc11533SChris Williamson const char* name;
28*dfc11533SChris Williamson } LoadState;
29*dfc11533SChris Williamson
error(LoadState * S,const char * why)30*dfc11533SChris Williamson static l_noret error(LoadState* S, const char* why)
31*dfc11533SChris Williamson {
32*dfc11533SChris Williamson luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
33*dfc11533SChris Williamson luaD_throw(S->L,LUA_ERRSYNTAX);
34*dfc11533SChris Williamson }
35*dfc11533SChris Williamson
36*dfc11533SChris Williamson #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
37*dfc11533SChris Williamson #define LoadByte(S) (lu_byte)LoadChar(S)
38*dfc11533SChris Williamson #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
39*dfc11533SChris Williamson #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
40*dfc11533SChris Williamson
41*dfc11533SChris Williamson #if !defined(luai_verifycode)
42*dfc11533SChris Williamson #define luai_verifycode(L,b,f) /* empty */
43*dfc11533SChris Williamson #endif
44*dfc11533SChris Williamson
LoadBlock(LoadState * S,void * b,size_t size)45*dfc11533SChris Williamson static void LoadBlock(LoadState* S, void* b, size_t size)
46*dfc11533SChris Williamson {
47*dfc11533SChris Williamson if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated");
48*dfc11533SChris Williamson }
49*dfc11533SChris Williamson
LoadChar(LoadState * S)50*dfc11533SChris Williamson static int LoadChar(LoadState* S)
51*dfc11533SChris Williamson {
52*dfc11533SChris Williamson char x;
53*dfc11533SChris Williamson LoadVar(S,x);
54*dfc11533SChris Williamson return x;
55*dfc11533SChris Williamson }
56*dfc11533SChris Williamson
LoadInt(LoadState * S)57*dfc11533SChris Williamson static int LoadInt(LoadState* S)
58*dfc11533SChris Williamson {
59*dfc11533SChris Williamson int x;
60*dfc11533SChris Williamson LoadVar(S,x);
61*dfc11533SChris Williamson if (x<0) error(S,"corrupted");
62*dfc11533SChris Williamson return x;
63*dfc11533SChris Williamson }
64*dfc11533SChris Williamson
LoadNumber(LoadState * S)65*dfc11533SChris Williamson static lua_Number LoadNumber(LoadState* S)
66*dfc11533SChris Williamson {
67*dfc11533SChris Williamson lua_Number x;
68*dfc11533SChris Williamson LoadVar(S,x);
69*dfc11533SChris Williamson return x;
70*dfc11533SChris Williamson }
71*dfc11533SChris Williamson
LoadString(LoadState * S)72*dfc11533SChris Williamson static TString* LoadString(LoadState* S)
73*dfc11533SChris Williamson {
74*dfc11533SChris Williamson size_t size;
75*dfc11533SChris Williamson LoadVar(S,size);
76*dfc11533SChris Williamson if (size==0)
77*dfc11533SChris Williamson return NULL;
78*dfc11533SChris Williamson else
79*dfc11533SChris Williamson {
80*dfc11533SChris Williamson char* s=luaZ_openspace(S->L,S->b,size);
81*dfc11533SChris Williamson LoadBlock(S,s,size*sizeof(char));
82*dfc11533SChris Williamson return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
83*dfc11533SChris Williamson }
84*dfc11533SChris Williamson }
85*dfc11533SChris Williamson
LoadCode(LoadState * S,Proto * f)86*dfc11533SChris Williamson static void LoadCode(LoadState* S, Proto* f)
87*dfc11533SChris Williamson {
88*dfc11533SChris Williamson int n=LoadInt(S);
89*dfc11533SChris Williamson f->code=luaM_newvector(S->L,n,Instruction);
90*dfc11533SChris Williamson f->sizecode=n;
91*dfc11533SChris Williamson LoadVector(S,f->code,n,sizeof(Instruction));
92*dfc11533SChris Williamson }
93*dfc11533SChris Williamson
94*dfc11533SChris Williamson static void LoadFunction(LoadState* S, Proto* f);
95*dfc11533SChris Williamson
LoadConstants(LoadState * S,Proto * f)96*dfc11533SChris Williamson static void LoadConstants(LoadState* S, Proto* f)
97*dfc11533SChris Williamson {
98*dfc11533SChris Williamson int i,n;
99*dfc11533SChris Williamson n=LoadInt(S);
100*dfc11533SChris Williamson f->k=luaM_newvector(S->L,n,TValue);
101*dfc11533SChris Williamson f->sizek=n;
102*dfc11533SChris Williamson for (i=0; i<n; i++) setnilvalue(&f->k[i]);
103*dfc11533SChris Williamson for (i=0; i<n; i++)
104*dfc11533SChris Williamson {
105*dfc11533SChris Williamson TValue* o=&f->k[i];
106*dfc11533SChris Williamson int t=LoadChar(S);
107*dfc11533SChris Williamson switch (t)
108*dfc11533SChris Williamson {
109*dfc11533SChris Williamson case LUA_TNIL:
110*dfc11533SChris Williamson setnilvalue(o);
111*dfc11533SChris Williamson break;
112*dfc11533SChris Williamson case LUA_TBOOLEAN:
113*dfc11533SChris Williamson setbvalue(o,LoadChar(S));
114*dfc11533SChris Williamson break;
115*dfc11533SChris Williamson case LUA_TNUMBER:
116*dfc11533SChris Williamson setnvalue(o,LoadNumber(S));
117*dfc11533SChris Williamson break;
118*dfc11533SChris Williamson case LUA_TSTRING:
119*dfc11533SChris Williamson setsvalue2n(S->L,o,LoadString(S));
120*dfc11533SChris Williamson break;
121*dfc11533SChris Williamson default: lua_assert(0);
122*dfc11533SChris Williamson }
123*dfc11533SChris Williamson }
124*dfc11533SChris Williamson n=LoadInt(S);
125*dfc11533SChris Williamson f->p=luaM_newvector(S->L,n,Proto*);
126*dfc11533SChris Williamson f->sizep=n;
127*dfc11533SChris Williamson for (i=0; i<n; i++) f->p[i]=NULL;
128*dfc11533SChris Williamson for (i=0; i<n; i++)
129*dfc11533SChris Williamson {
130*dfc11533SChris Williamson f->p[i]=luaF_newproto(S->L);
131*dfc11533SChris Williamson LoadFunction(S,f->p[i]);
132*dfc11533SChris Williamson }
133*dfc11533SChris Williamson }
134*dfc11533SChris Williamson
LoadUpvalues(LoadState * S,Proto * f)135*dfc11533SChris Williamson static void LoadUpvalues(LoadState* S, Proto* f)
136*dfc11533SChris Williamson {
137*dfc11533SChris Williamson int i,n;
138*dfc11533SChris Williamson n=LoadInt(S);
139*dfc11533SChris Williamson f->upvalues=luaM_newvector(S->L,n,Upvaldesc);
140*dfc11533SChris Williamson f->sizeupvalues=n;
141*dfc11533SChris Williamson for (i=0; i<n; i++) f->upvalues[i].name=NULL;
142*dfc11533SChris Williamson for (i=0; i<n; i++)
143*dfc11533SChris Williamson {
144*dfc11533SChris Williamson f->upvalues[i].instack=LoadByte(S);
145*dfc11533SChris Williamson f->upvalues[i].idx=LoadByte(S);
146*dfc11533SChris Williamson }
147*dfc11533SChris Williamson }
148*dfc11533SChris Williamson
LoadDebug(LoadState * S,Proto * f)149*dfc11533SChris Williamson static void LoadDebug(LoadState* S, Proto* f)
150*dfc11533SChris Williamson {
151*dfc11533SChris Williamson int i,n;
152*dfc11533SChris Williamson f->source=LoadString(S);
153*dfc11533SChris Williamson n=LoadInt(S);
154*dfc11533SChris Williamson f->lineinfo=luaM_newvector(S->L,n,int);
155*dfc11533SChris Williamson f->sizelineinfo=n;
156*dfc11533SChris Williamson LoadVector(S,f->lineinfo,n,sizeof(int));
157*dfc11533SChris Williamson n=LoadInt(S);
158*dfc11533SChris Williamson f->locvars=luaM_newvector(S->L,n,LocVar);
159*dfc11533SChris Williamson f->sizelocvars=n;
160*dfc11533SChris Williamson for (i=0; i<n; i++) f->locvars[i].varname=NULL;
161*dfc11533SChris Williamson for (i=0; i<n; i++)
162*dfc11533SChris Williamson {
163*dfc11533SChris Williamson f->locvars[i].varname=LoadString(S);
164*dfc11533SChris Williamson f->locvars[i].startpc=LoadInt(S);
165*dfc11533SChris Williamson f->locvars[i].endpc=LoadInt(S);
166*dfc11533SChris Williamson }
167*dfc11533SChris Williamson n=LoadInt(S);
168*dfc11533SChris Williamson for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
169*dfc11533SChris Williamson }
170*dfc11533SChris Williamson
LoadFunction(LoadState * S,Proto * f)171*dfc11533SChris Williamson static void LoadFunction(LoadState* S, Proto* f)
172*dfc11533SChris Williamson {
173*dfc11533SChris Williamson f->linedefined=LoadInt(S);
174*dfc11533SChris Williamson f->lastlinedefined=LoadInt(S);
175*dfc11533SChris Williamson f->numparams=LoadByte(S);
176*dfc11533SChris Williamson f->is_vararg=LoadByte(S);
177*dfc11533SChris Williamson f->maxstacksize=LoadByte(S);
178*dfc11533SChris Williamson LoadCode(S,f);
179*dfc11533SChris Williamson LoadConstants(S,f);
180*dfc11533SChris Williamson LoadUpvalues(S,f);
181*dfc11533SChris Williamson LoadDebug(S,f);
182*dfc11533SChris Williamson }
183*dfc11533SChris Williamson
184*dfc11533SChris Williamson /* the code below must be consistent with the code in luaU_header */
185*dfc11533SChris Williamson #define N0 LUAC_HEADERSIZE
186*dfc11533SChris Williamson #define N1 (sizeof(LUA_SIGNATURE)-sizeof(char))
187*dfc11533SChris Williamson #define N2 N1+2
188*dfc11533SChris Williamson #define N3 N2+6
189*dfc11533SChris Williamson
LoadHeader(LoadState * S)190*dfc11533SChris Williamson static void LoadHeader(LoadState* S)
191*dfc11533SChris Williamson {
192*dfc11533SChris Williamson lu_byte h[LUAC_HEADERSIZE];
193*dfc11533SChris Williamson lu_byte s[LUAC_HEADERSIZE];
194*dfc11533SChris Williamson luaU_header(h);
195*dfc11533SChris Williamson memcpy(s,h,sizeof(char)); /* first char already read */
196*dfc11533SChris Williamson LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char));
197*dfc11533SChris Williamson if (memcmp(h,s,N0)==0) return;
198*dfc11533SChris Williamson if (memcmp(h,s,N1)!=0) error(S,"not a");
199*dfc11533SChris Williamson if (memcmp(h,s,N2)!=0) error(S,"version mismatch in");
200*dfc11533SChris Williamson if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted");
201*dfc11533SChris Williamson }
202*dfc11533SChris Williamson
203*dfc11533SChris Williamson /*
204*dfc11533SChris Williamson ** load precompiled chunk
205*dfc11533SChris Williamson */
luaU_undump(lua_State * L,ZIO * Z,Mbuffer * buff,const char * name)206*dfc11533SChris Williamson Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
207*dfc11533SChris Williamson {
208*dfc11533SChris Williamson LoadState S;
209*dfc11533SChris Williamson Closure* cl;
210*dfc11533SChris Williamson if (*name=='@' || *name=='=')
211*dfc11533SChris Williamson S.name=name+1;
212*dfc11533SChris Williamson else if (*name==LUA_SIGNATURE[0])
213*dfc11533SChris Williamson S.name="binary string";
214*dfc11533SChris Williamson else
215*dfc11533SChris Williamson S.name=name;
216*dfc11533SChris Williamson S.L=L;
217*dfc11533SChris Williamson S.Z=Z;
218*dfc11533SChris Williamson S.b=buff;
219*dfc11533SChris Williamson LoadHeader(&S);
220*dfc11533SChris Williamson cl=luaF_newLclosure(L,1);
221*dfc11533SChris Williamson setclLvalue(L,L->top,cl); incr_top(L);
222*dfc11533SChris Williamson cl->l.p=luaF_newproto(L);
223*dfc11533SChris Williamson LoadFunction(&S,cl->l.p);
224*dfc11533SChris Williamson if (cl->l.p->sizeupvalues != 1)
225*dfc11533SChris Williamson {
226*dfc11533SChris Williamson Proto* p=cl->l.p;
227*dfc11533SChris Williamson cl=luaF_newLclosure(L,cl->l.p->sizeupvalues);
228*dfc11533SChris Williamson cl->l.p=p;
229*dfc11533SChris Williamson setclLvalue(L,L->top-1,cl);
230*dfc11533SChris Williamson }
231*dfc11533SChris Williamson luai_verifycode(L,buff,cl->l.p);
232*dfc11533SChris Williamson return cl;
233*dfc11533SChris Williamson }
234*dfc11533SChris Williamson
235*dfc11533SChris Williamson #define MYINT(s) (s[0]-'0')
236*dfc11533SChris Williamson #define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)
237*dfc11533SChris Williamson #define FORMAT 0 /* this is the official format */
238*dfc11533SChris Williamson
239*dfc11533SChris Williamson /*
240*dfc11533SChris Williamson * make header for precompiled chunks
241*dfc11533SChris Williamson * if you change the code below be sure to update LoadHeader and FORMAT above
242*dfc11533SChris Williamson * and LUAC_HEADERSIZE in lundump.h
243*dfc11533SChris Williamson */
luaU_header(lu_byte * h)244*dfc11533SChris Williamson void luaU_header (lu_byte* h)
245*dfc11533SChris Williamson {
246*dfc11533SChris Williamson int x=1;
247*dfc11533SChris Williamson memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char));
248*dfc11533SChris Williamson h+=sizeof(LUA_SIGNATURE)-sizeof(char);
249*dfc11533SChris Williamson *h++=cast_byte(VERSION);
250*dfc11533SChris Williamson *h++=cast_byte(FORMAT);
251*dfc11533SChris Williamson *h++=cast_byte(*(char*)&x); /* endianness */
252*dfc11533SChris Williamson *h++=cast_byte(sizeof(int));
253*dfc11533SChris Williamson *h++=cast_byte(sizeof(size_t));
254*dfc11533SChris Williamson *h++=cast_byte(sizeof(Instruction));
255*dfc11533SChris Williamson *h++=cast_byte(sizeof(lua_Number));
256*dfc11533SChris Williamson *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */
257*dfc11533SChris Williamson memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char));
258*dfc11533SChris Williamson }
259