diff options
Diffstat (limited to '')
-rw-r--r-- | lundump.c | 87 |
1 files changed, 72 insertions, 15 deletions
@@ -21,6 +21,7 @@ | |||
21 | #include "lmem.h" | 21 | #include "lmem.h" |
22 | #include "lobject.h" | 22 | #include "lobject.h" |
23 | #include "lstring.h" | 23 | #include "lstring.h" |
24 | #include "ltable.h" | ||
24 | #include "lundump.h" | 25 | #include "lundump.h" |
25 | #include "lzio.h" | 26 | #include "lzio.h" |
26 | 27 | ||
@@ -34,6 +35,10 @@ typedef struct { | |||
34 | lua_State *L; | 35 | lua_State *L; |
35 | ZIO *Z; | 36 | ZIO *Z; |
36 | const char *name; | 37 | const char *name; |
38 | Table *h; /* list for string reuse */ | ||
39 | lu_mem offset; /* current position relative to beginning of dump */ | ||
40 | lua_Integer nstr; /* number of strings in the list */ | ||
41 | lu_byte fixed; /* dump is fixed in memory */ | ||
37 | } LoadState; | 42 | } LoadState; |
38 | 43 | ||
39 | 44 | ||
@@ -52,6 +57,27 @@ static l_noret error (LoadState *S, const char *why) { | |||
52 | static void loadBlock (LoadState *S, void *b, size_t size) { | 57 | static void loadBlock (LoadState *S, void *b, size_t size) { |
53 | if (luaZ_read(S->Z, b, size) != 0) | 58 | if (luaZ_read(S->Z, b, size) != 0) |
54 | error(S, "truncated chunk"); | 59 | error(S, "truncated chunk"); |
60 | S->offset += size; | ||
61 | } | ||
62 | |||
63 | |||
64 | static void loadAlign (LoadState *S, int align) { | ||
65 | int padding = align - (S->offset % align); | ||
66 | if (padding < align) { /* apd == align means no padding */ | ||
67 | lua_Integer paddingContent; | ||
68 | loadBlock(S, &paddingContent, padding); | ||
69 | lua_assert(S->offset % align == 0); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | #define getaddr(S,n,t) cast(t *, getaddr_(S,n,sizeof(t))) | ||
75 | |||
76 | static const void *getaddr_ (LoadState *S, int n, int sz) { | ||
77 | const void *block = luaZ_getaddr(S->Z, n * sz); | ||
78 | if (block == NULL) | ||
79 | error(S, "truncated fixed buffer"); | ||
80 | return block; | ||
55 | } | 81 | } |
56 | 82 | ||
57 | 83 | ||
@@ -62,6 +88,7 @@ static lu_byte loadByte (LoadState *S) { | |||
62 | int b = zgetc(S->Z); | 88 | int b = zgetc(S->Z); |
63 | if (b == EOZ) | 89 | if (b == EOZ) |
64 | error(S, "truncated chunk"); | 90 | error(S, "truncated chunk"); |
91 | S->offset++; | ||
65 | return cast_byte(b); | 92 | return cast_byte(b); |
66 | } | 93 | } |
67 | 94 | ||
@@ -110,10 +137,16 @@ static lua_Integer loadInteger (LoadState *S) { | |||
110 | static TString *loadStringN (LoadState *S, Proto *p) { | 137 | static TString *loadStringN (LoadState *S, Proto *p) { |
111 | lua_State *L = S->L; | 138 | lua_State *L = S->L; |
112 | TString *ts; | 139 | TString *ts; |
140 | TValue sv; | ||
113 | size_t size = loadSize(S); | 141 | size_t size = loadSize(S); |
114 | if (size == 0) /* no string? */ | 142 | if (size == 0) /* no string? */ |
115 | return NULL; | 143 | return NULL; |
116 | else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ | 144 | else if (size == 1) { /* previously saved string? */ |
145 | int idx = loadInt(S); /* get its index */ | ||
146 | const TValue *stv = luaH_getint(S->h, idx); | ||
147 | return tsvalue(stv); | ||
148 | } | ||
149 | else if (size -= 2, size <= LUAI_MAXSHORTLEN) { /* short string? */ | ||
117 | char buff[LUAI_MAXSHORTLEN]; | 150 | char buff[LUAI_MAXSHORTLEN]; |
118 | loadVector(S, buff, size); /* load string into buffer */ | 151 | loadVector(S, buff, size); /* load string into buffer */ |
119 | ts = luaS_newlstr(L, buff, size); /* create string */ | 152 | ts = luaS_newlstr(L, buff, size); /* create string */ |
@@ -126,6 +159,10 @@ static TString *loadStringN (LoadState *S, Proto *p) { | |||
126 | L->top.p--; /* pop string */ | 159 | L->top.p--; /* pop string */ |
127 | } | 160 | } |
128 | luaC_objbarrier(L, p, ts); | 161 | luaC_objbarrier(L, p, ts); |
162 | S->nstr++; /* add string to list of saved strings */ | ||
163 | setsvalue(L, &sv, ts); | ||
164 | luaH_setint(L, S->h, S->nstr, &sv); | ||
165 | luaC_objbarrierback(L, obj2gco(S->h), ts); | ||
129 | return ts; | 166 | return ts; |
130 | } | 167 | } |
131 | 168 | ||
@@ -143,13 +180,20 @@ static TString *loadString (LoadState *S, Proto *p) { | |||
143 | 180 | ||
144 | static void loadCode (LoadState *S, Proto *f) { | 181 | static void loadCode (LoadState *S, Proto *f) { |
145 | int n = loadInt(S); | 182 | int n = loadInt(S); |
146 | f->code = luaM_newvectorchecked(S->L, n, Instruction); | 183 | loadAlign(S, sizeof(f->code[0])); |
147 | f->sizecode = n; | 184 | if (S->fixed) { |
148 | loadVector(S, f->code, n); | 185 | f->code = getaddr(S, n, Instruction); |
186 | f->sizecode = n; | ||
187 | } | ||
188 | else { | ||
189 | f->code = luaM_newvectorchecked(S->L, n, Instruction); | ||
190 | f->sizecode = n; | ||
191 | loadVector(S, f->code, n); | ||
192 | } | ||
149 | } | 193 | } |
150 | 194 | ||
151 | 195 | ||
152 | static void loadFunction(LoadState *S, Proto *f, TString *psource); | 196 | static void loadFunction(LoadState *S, Proto *f); |
153 | 197 | ||
154 | 198 | ||
155 | static void loadConstants (LoadState *S, Proto *f) { | 199 | static void loadConstants (LoadState *S, Proto *f) { |
@@ -198,7 +242,7 @@ static void loadProtos (LoadState *S, Proto *f) { | |||
198 | for (i = 0; i < n; i++) { | 242 | for (i = 0; i < n; i++) { |
199 | f->p[i] = luaF_newproto(S->L); | 243 | f->p[i] = luaF_newproto(S->L); |
200 | luaC_objbarrier(S->L, f, f->p[i]); | 244 | luaC_objbarrier(S->L, f, f->p[i]); |
201 | loadFunction(S, f->p[i], f->source); | 245 | loadFunction(S, f->p[i]); |
202 | } | 246 | } |
203 | } | 247 | } |
204 | 248 | ||
@@ -227,9 +271,15 @@ static void loadUpvalues (LoadState *S, Proto *f) { | |||
227 | static void loadDebug (LoadState *S, Proto *f) { | 271 | static void loadDebug (LoadState *S, Proto *f) { |
228 | int i, n; | 272 | int i, n; |
229 | n = loadInt(S); | 273 | n = loadInt(S); |
230 | f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); | 274 | if (S->fixed) { |
231 | f->sizelineinfo = n; | 275 | f->lineinfo = getaddr(S, n, ls_byte); |
232 | loadVector(S, f->lineinfo, n); | 276 | f->sizelineinfo = n; |
277 | } | ||
278 | else { | ||
279 | f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); | ||
280 | f->sizelineinfo = n; | ||
281 | loadVector(S, f->lineinfo, n); | ||
282 | } | ||
233 | n = loadInt(S); | 283 | n = loadInt(S); |
234 | f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); | 284 | f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); |
235 | f->sizeabslineinfo = n; | 285 | f->sizeabslineinfo = n; |
@@ -255,14 +305,14 @@ static void loadDebug (LoadState *S, Proto *f) { | |||
255 | } | 305 | } |
256 | 306 | ||
257 | 307 | ||
258 | static void loadFunction (LoadState *S, Proto *f, TString *psource) { | 308 | static void loadFunction (LoadState *S, Proto *f) { |
259 | f->source = loadStringN(S, f); | 309 | f->source = loadStringN(S, f); |
260 | if (f->source == NULL) /* no source in dump? */ | ||
261 | f->source = psource; /* reuse parent's source */ | ||
262 | f->linedefined = loadInt(S); | 310 | f->linedefined = loadInt(S); |
263 | f->lastlinedefined = loadInt(S); | 311 | f->lastlinedefined = loadInt(S); |
264 | f->numparams = loadByte(S); | 312 | f->numparams = loadByte(S); |
265 | f->is_vararg = loadByte(S); | 313 | f->flag = loadByte(S) & PF_ISVARARG; /* get only the meaningful flags */ |
314 | if (S->fixed) | ||
315 | f->flag |= PF_FIXED; /* signal that code is fixed */ | ||
266 | f->maxstacksize = loadByte(S); | 316 | f->maxstacksize = loadByte(S); |
267 | loadCode(S, f); | 317 | loadCode(S, f); |
268 | loadConstants(S, f); | 318 | loadConstants(S, f); |
@@ -310,7 +360,7 @@ static void checkHeader (LoadState *S) { | |||
310 | /* | 360 | /* |
311 | ** Load precompiled chunk. | 361 | ** Load precompiled chunk. |
312 | */ | 362 | */ |
313 | LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { | 363 | LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { |
314 | LoadState S; | 364 | LoadState S; |
315 | LClosure *cl; | 365 | LClosure *cl; |
316 | if (*name == '@' || *name == '=') | 366 | if (*name == '@' || *name == '=') |
@@ -321,15 +371,22 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { | |||
321 | S.name = name; | 371 | S.name = name; |
322 | S.L = L; | 372 | S.L = L; |
323 | S.Z = Z; | 373 | S.Z = Z; |
374 | S.fixed = fixed; | ||
375 | S.offset = 1; /* fist byte was already read */ | ||
324 | checkHeader(&S); | 376 | checkHeader(&S); |
325 | cl = luaF_newLclosure(L, loadByte(&S)); | 377 | cl = luaF_newLclosure(L, loadByte(&S)); |
326 | setclLvalue2s(L, L->top.p, cl); | 378 | setclLvalue2s(L, L->top.p, cl); |
327 | luaD_inctop(L); | 379 | luaD_inctop(L); |
380 | S.h = luaH_new(L); /* create list of saved strings */ | ||
381 | S.nstr = 0; | ||
382 | sethvalue2s(L, L->top.p, S.h); /* anchor it */ | ||
383 | luaD_inctop(L); | ||
328 | cl->p = luaF_newproto(L); | 384 | cl->p = luaF_newproto(L); |
329 | luaC_objbarrier(L, cl, cl->p); | 385 | luaC_objbarrier(L, cl, cl->p); |
330 | loadFunction(&S, cl->p, NULL); | 386 | loadFunction(&S, cl->p); |
331 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); | 387 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); |
332 | luai_verifycode(L, cl->p); | 388 | luai_verifycode(L, cl->p); |
389 | L->top.p--; /* pop table */ | ||
333 | return cl; | 390 | return cl; |
334 | } | 391 | } |
335 | 392 | ||